diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index abbbc7a9e1..70c1916e8e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -72,7 +72,7 @@ jobs: run: bundle exec fastlane cru_shared_lane_run_tests output_directory:fastlane_scan_output_directory result_bundle:true - name: Upload Xcode Code Coverage Report to CodeCov - uses: codecov/codecov-action@v3 + uses: codecov/codecov-action@v4 with: fail_ci_if_error: true token: ${{ secrets.CODECOV_TOKEN }} diff --git a/.github/workflows/download_onesky_translations.yml b/.github/workflows/download_onesky_translations.yml index f56c4ef3fb..ed8428bebe 100644 --- a/.github/workflows/download_onesky_translations.yml +++ b/.github/workflows/download_onesky_translations.yml @@ -46,7 +46,7 @@ jobs: run: bundle exec fastlane cru_shared_lane_download_and_commit_latest_one_sky_localizations - name: Create Pull Request - uses: peter-evans/create-pull-request@v5 + uses: peter-evans/create-pull-request@v6 with: branch: 'latest-onesky-translations' token: ${{ secrets.CREATE_PULL_REQUEST_ACCESS_TOKEN }} diff --git a/godtools.xcodeproj/project.pbxproj b/godtools.xcodeproj/project.pbxproj index 54450c4aed..c47aed641f 100644 --- a/godtools.xcodeproj/project.pbxproj +++ b/godtools.xcodeproj/project.pbxproj @@ -204,6 +204,9 @@ 452D355F2A8FCCFF00BC4F97 /* ConfirmRemoveToolFromFavoritesAlertViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 452D355E2A8FCCFF00BC4F97 /* ConfirmRemoveToolFromFavoritesAlertViewModel.swift */; }; 452D55372A33615900DE70BF /* MenuAccountSectionVisibility.swift in Sources */ = {isa = PBXBuildFile; fileRef = 452D55362A33615900DE70BF /* MenuAccountSectionVisibility.swift */; }; 452F4B082A97E117003071D1 /* PageNavigationCollectionViewCenterLayoutPageAttributes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 452F4B072A97E117003071D1 /* PageNavigationCollectionViewCenterLayoutPageAttributes.swift */; }; + 452F6E812B69A1C40012AF9C /* DownloadLatestToolsForFavoritedToolsUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 452F6E802B69A1C40012AF9C /* DownloadLatestToolsForFavoritedToolsUseCase.swift */; }; + 452F6E852B69A33C0012AF9C /* FavoritedToolsLatestToolDownloaderInterface.swift in Sources */ = {isa = PBXBuildFile; fileRef = 452F6E842B69A33C0012AF9C /* FavoritedToolsLatestToolDownloaderInterface.swift */; }; + 452F6E872B69A3420012AF9C /* FavoritedToolsLatestToolDownloader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 452F6E862B69A3420012AF9C /* FavoritedToolsLatestToolDownloader.swift */; }; 45325F23285CF8B40078D932 /* SegmentControl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45325F19285CF8B40078D932 /* SegmentControl.swift */; }; 45325F24285CF8B40078D932 /* Segment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45325F1A285CF8B40078D932 /* Segment.swift */; }; 45325F25285CF8B40078D932 /* AnimatedSwiftUIView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45325F1C285CF8B40078D932 /* AnimatedSwiftUIView.swift */; }; @@ -1026,7 +1029,7 @@ 45BE4A812AF287D2004021DA /* ConfirmAppLanguageViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45BE4A7F2AF287D2004021DA /* ConfirmAppLanguageViewModel.swift */; }; 45BE4A822AF287D2004021DA /* ConfirmAppLanguageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45BE4A802AF287D2004021DA /* ConfirmAppLanguageView.swift */; }; 45BE4A842AF287E3004021DA /* ConfirmAppLanguageInterfaceStringsDomainModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45BE4A832AF287E3004021DA /* ConfirmAppLanguageInterfaceStringsDomainModel.swift */; }; - 45BE4A862AF287F0004021DA /* GetConfirmAppLanguageInterfaceStringsUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45BE4A852AF287F0004021DA /* GetConfirmAppLanguageInterfaceStringsUseCase.swift */; }; + 45BE4A862AF287F0004021DA /* ViewConfirmAppLanguageUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45BE4A852AF287F0004021DA /* ViewConfirmAppLanguageUseCase.swift */; }; 45BEDB712A98DBD9009C7664 /* DisableGoogleTagManagerLogging.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45BEDB702A98DBD9009C7664 /* DisableGoogleTagManagerLogging.swift */; }; 45BF2B9E27A9573F00D23EDA /* MobileContentPagesInitialPageRenderingType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45BF2B9D27A9573F00D23EDA /* MobileContentPagesInitialPageRenderingType.swift */; }; 45BF6EBA27050A29003596A4 /* TransparentModalView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45BF6EB927050A29003596A4 /* TransparentModalView.swift */; }; @@ -1127,7 +1130,6 @@ 45D7CAEB2A9BA23C00913E12 /* SwiftUIPreviewDatabaseConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45D7CAEA2A9BA23C00913E12 /* SwiftUIPreviewDatabaseConfiguration.swift */; }; 45D7CAEE2A9BA47200913E12 /* FirebaseInAppMessaging.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45D7CAED2A9BA47200913E12 /* FirebaseInAppMessaging.swift */; }; 45D95CCE271F3F1100263D46 /* MobileContentRendererEventAnalyticsTracking.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45D95CCD271F3F1100263D46 /* MobileContentRendererEventAnalyticsTracking.swift */; }; - 45D9608D289B877D001A5A3E /* GetAllFavoritedToolsLatestTranslationFilesUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45D9608C289B877D001A5A3E /* GetAllFavoritedToolsLatestTranslationFilesUseCase.swift */; }; 45DAC8C62B2BB9E500A138C0 /* AppLanguageDataModel+TranslatableLanguage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45DAC8C52B2BB9E500A138C0 /* AppLanguageDataModel+TranslatableLanguage.swift */; }; 45DAC8CA2B2BBA1200A138C0 /* GetTranslatedLanguageName.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45DAC8C82B2BBA1200A138C0 /* GetTranslatedLanguageName.swift */; }; 45DAC8CB2B2BBA1200A138C0 /* TranslatableLanguage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45DAC8C92B2BBA1200A138C0 /* TranslatableLanguage.swift */; }; @@ -1400,6 +1402,9 @@ D42FEBD62875D8D50002FAD9 /* GetOptInOnboardingTutorialAvailableUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = D42FEBD52875D8D50002FAD9 /* GetOptInOnboardingTutorialAvailableUseCase.swift */; }; D42FEBDA287604570002FAD9 /* OptInOnboardingBannerEnabledRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = D42FEBD9287604570002FAD9 /* OptInOnboardingBannerEnabledRepository.swift */; }; D43FC1BE2B62EFD800F8310E /* View+AppLifecycle.swift in Sources */ = {isa = PBXBuildFile; fileRef = D43FC1BD2B62EFD800F8310E /* View+AppLifecycle.swift */; }; + D43FC1C02B64531F00F8310E /* ViewConfirmAppLanguageDomainModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D43FC1BF2B64531F00F8310E /* ViewConfirmAppLanguageDomainModel.swift */; }; + D43FC1C22B65E08C00F8310E /* GetConfirmAppLanguageInterfaceStringsRepositoryInterface.swift in Sources */ = {isa = PBXBuildFile; fileRef = D43FC1C12B65E08C00F8310E /* GetConfirmAppLanguageInterfaceStringsRepositoryInterface.swift */; }; + D43FC1C42B65E0F300F8310E /* GetConfirmAppLanguageInterfaceStringsRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = D43FC1C32B65E0F300F8310E /* GetConfirmAppLanguageInterfaceStringsRepository.swift */; }; D43FC1C62B6996D000F8310E /* DownloadedLanguageListItemDomainModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D43FC1C52B6996D000F8310E /* DownloadedLanguageListItemDomainModel.swift */; }; D43FC1C82B69976200F8310E /* GetDownloadedLanguagesListRepositoryInterface.swift in Sources */ = {isa = PBXBuildFile; fileRef = D43FC1C72B69976200F8310E /* GetDownloadedLanguagesListRepositoryInterface.swift */; }; D43FC1CA2B6997B600F8310E /* GetDownloadedLanguagesListRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = D43FC1C92B6997B600F8310E /* GetDownloadedLanguagesListRepository.swift */; }; @@ -1443,7 +1448,6 @@ D4E243CC29EDC6A100EA4BB7 /* SendFeedbackWebContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4E243CB29EDC6A100EA4BB7 /* SendFeedbackWebContent.swift */; }; D4E243CE29EDCA5700EA4BB7 /* ReportABugWebContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4E243CD29EDCA5700EA4BB7 /* ReportABugWebContent.swift */; }; D4E243D029EDD2E800EA4BB7 /* AskAQuestionWebContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4E243CF29EDD2E800EA4BB7 /* AskAQuestionWebContent.swift */; }; - D4E243DF29F30DAD00EA4BB7 /* Roboto-Medium.ttf in Resources */ = {isa = PBXBuildFile; fileRef = D4E243DE29F30DAC00EA4BB7 /* Roboto-Medium.ttf */; }; D4EFC9632B49B28200B0D34A /* LanguageDownloadErrorAlertView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4EFC9622B49B28200B0D34A /* LanguageDownloadErrorAlertView.swift */; }; D4EFC9652B49B29D00B0D34A /* LanguageDownloadErrorAlertViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4EFC9642B49B29D00B0D34A /* LanguageDownloadErrorAlertViewModel.swift */; }; D4F1DE8D2967538A00A2F674 /* IncrementUserCounterUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4F1DE8C2967538A00A2F674 /* IncrementUserCounterUseCase.swift */; }; @@ -1679,6 +1683,9 @@ 452D355E2A8FCCFF00BC4F97 /* ConfirmRemoveToolFromFavoritesAlertViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfirmRemoveToolFromFavoritesAlertViewModel.swift; sourceTree = ""; }; 452D55362A33615900DE70BF /* MenuAccountSectionVisibility.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenuAccountSectionVisibility.swift; sourceTree = ""; }; 452F4B072A97E117003071D1 /* PageNavigationCollectionViewCenterLayoutPageAttributes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PageNavigationCollectionViewCenterLayoutPageAttributes.swift; sourceTree = ""; }; + 452F6E802B69A1C40012AF9C /* DownloadLatestToolsForFavoritedToolsUseCase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DownloadLatestToolsForFavoritedToolsUseCase.swift; sourceTree = ""; }; + 452F6E842B69A33C0012AF9C /* FavoritedToolsLatestToolDownloaderInterface.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FavoritedToolsLatestToolDownloaderInterface.swift; sourceTree = ""; }; + 452F6E862B69A3420012AF9C /* FavoritedToolsLatestToolDownloader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FavoritedToolsLatestToolDownloader.swift; sourceTree = ""; }; 45325F19285CF8B40078D932 /* SegmentControl.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SegmentControl.swift; sourceTree = ""; }; 45325F1A285CF8B40078D932 /* Segment.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Segment.swift; sourceTree = ""; }; 45325F1C285CF8B40078D932 /* AnimatedSwiftUIView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AnimatedSwiftUIView.swift; sourceTree = ""; }; @@ -2472,7 +2479,7 @@ 45BE4A7F2AF287D2004021DA /* ConfirmAppLanguageViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConfirmAppLanguageViewModel.swift; sourceTree = ""; }; 45BE4A802AF287D2004021DA /* ConfirmAppLanguageView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConfirmAppLanguageView.swift; sourceTree = ""; }; 45BE4A832AF287E3004021DA /* ConfirmAppLanguageInterfaceStringsDomainModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConfirmAppLanguageInterfaceStringsDomainModel.swift; sourceTree = ""; }; - 45BE4A852AF287F0004021DA /* GetConfirmAppLanguageInterfaceStringsUseCase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GetConfirmAppLanguageInterfaceStringsUseCase.swift; sourceTree = ""; }; + 45BE4A852AF287F0004021DA /* ViewConfirmAppLanguageUseCase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ViewConfirmAppLanguageUseCase.swift; sourceTree = ""; }; 45BEDB702A98DBD9009C7664 /* DisableGoogleTagManagerLogging.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisableGoogleTagManagerLogging.swift; sourceTree = ""; }; 45BF2B9D27A9573F00D23EDA /* MobileContentPagesInitialPageRenderingType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MobileContentPagesInitialPageRenderingType.swift; sourceTree = ""; }; 45BF6EB927050A29003596A4 /* TransparentModalView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TransparentModalView.swift; sourceTree = ""; }; @@ -2565,7 +2572,6 @@ 45D7CAEA2A9BA23C00913E12 /* SwiftUIPreviewDatabaseConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftUIPreviewDatabaseConfiguration.swift; sourceTree = ""; }; 45D7CAED2A9BA47200913E12 /* FirebaseInAppMessaging.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FirebaseInAppMessaging.swift; sourceTree = ""; }; 45D95CCD271F3F1100263D46 /* MobileContentRendererEventAnalyticsTracking.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MobileContentRendererEventAnalyticsTracking.swift; sourceTree = ""; }; - 45D9608C289B877D001A5A3E /* GetAllFavoritedToolsLatestTranslationFilesUseCase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GetAllFavoritedToolsLatestTranslationFilesUseCase.swift; sourceTree = ""; }; 45DAC8C52B2BB9E500A138C0 /* AppLanguageDataModel+TranslatableLanguage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "AppLanguageDataModel+TranslatableLanguage.swift"; sourceTree = ""; }; 45DAC8C82B2BBA1200A138C0 /* GetTranslatedLanguageName.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GetTranslatedLanguageName.swift; sourceTree = ""; }; 45DAC8C92B2BBA1200A138C0 /* TranslatableLanguage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TranslatableLanguage.swift; sourceTree = ""; }; @@ -2896,6 +2902,9 @@ D42FEBD52875D8D50002FAD9 /* GetOptInOnboardingTutorialAvailableUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GetOptInOnboardingTutorialAvailableUseCase.swift; sourceTree = ""; }; D42FEBD9287604570002FAD9 /* OptInOnboardingBannerEnabledRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OptInOnboardingBannerEnabledRepository.swift; sourceTree = ""; }; D43FC1BD2B62EFD800F8310E /* View+AppLifecycle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+AppLifecycle.swift"; sourceTree = ""; }; + D43FC1BF2B64531F00F8310E /* ViewConfirmAppLanguageDomainModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewConfirmAppLanguageDomainModel.swift; sourceTree = ""; }; + D43FC1C12B65E08C00F8310E /* GetConfirmAppLanguageInterfaceStringsRepositoryInterface.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GetConfirmAppLanguageInterfaceStringsRepositoryInterface.swift; sourceTree = ""; }; + D43FC1C32B65E0F300F8310E /* GetConfirmAppLanguageInterfaceStringsRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GetConfirmAppLanguageInterfaceStringsRepository.swift; sourceTree = ""; }; D43FC1C52B6996D000F8310E /* DownloadedLanguageListItemDomainModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DownloadedLanguageListItemDomainModel.swift; sourceTree = ""; }; D43FC1C72B69976200F8310E /* GetDownloadedLanguagesListRepositoryInterface.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GetDownloadedLanguagesListRepositoryInterface.swift; sourceTree = ""; }; D43FC1C92B6997B600F8310E /* GetDownloadedLanguagesListRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GetDownloadedLanguagesListRepository.swift; sourceTree = ""; }; @@ -3005,7 +3014,6 @@ D4E243CB29EDC6A100EA4BB7 /* SendFeedbackWebContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SendFeedbackWebContent.swift; sourceTree = ""; }; D4E243CD29EDCA5700EA4BB7 /* ReportABugWebContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportABugWebContent.swift; sourceTree = ""; }; D4E243CF29EDD2E800EA4BB7 /* AskAQuestionWebContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AskAQuestionWebContent.swift; sourceTree = ""; }; - D4E243DE29F30DAC00EA4BB7 /* Roboto-Medium.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Roboto-Medium.ttf"; sourceTree = ""; }; D4EFC9622B49B28200B0D34A /* LanguageDownloadErrorAlertView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LanguageDownloadErrorAlertView.swift; sourceTree = ""; }; D4EFC9642B49B29D00B0D34A /* LanguageDownloadErrorAlertViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LanguageDownloadErrorAlertViewModel.swift; sourceTree = ""; }; D4F1DE8C2967538A00A2F674 /* IncrementUserCounterUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IncrementUserCounterUseCase.swift; sourceTree = ""; }; @@ -3435,6 +3443,7 @@ 45B3F4652AC3B1B800D61BFD /* GetAppInterfaceLayoutDirectionInterface.swift */, 450DB5632AC3553E00B2FE3A /* GetAppLanguagesListRepositoryInterface.swift */, 45DB188F2AD7907600E9578F /* GetAppLanguagesRepositoryInterface.swift */, + D43FC1C12B65E08C00F8310E /* GetConfirmAppLanguageInterfaceStringsRepositoryInterface.swift */, 450DB55B2AC3545300B2FE3A /* GetDeviceAppLanguageRepositoryInterface.swift */, 45AC9DE12B28A9A400DEEBFE /* GetDownloadableLanguagesInterfaceStringsRepositoryInterface.swift */, 453A2EFA2B3636E300C8F865 /* GetDownloadableLanguagesListRepositoryInterface.swift */, @@ -3459,6 +3468,7 @@ D43FC1C52B6996D000F8310E /* DownloadedLanguageListItemDomainModel.swift */, 45AC9DDA2B28A98800DEEBFE /* LanguageDownloadStatusDomainModel.swift */, 453D2F7D2AD88A89001C44E3 /* LanguageSettingsInterfaceStringsDomainModel.swift */, + D43FC1BF2B64531F00F8310E /* ViewConfirmAppLanguageDomainModel.swift */, 45AC9DDB2B28A98800DEEBFE /* ViewDownloadableLanguagesDomainModel.swift */, 4500698A2B193880008A7499 /* ViewLanguageSettingsDomainModel.swift */, ); @@ -4230,6 +4240,14 @@ path = MobileContentApi; sourceTree = ""; }; + 452F6E7F2B69A1C40012AF9C /* DownloadLatestToolsForFavoritedToolsUseCase */ = { + isa = PBXGroup; + children = ( + 452F6E802B69A1C40012AF9C /* DownloadLatestToolsForFavoritedToolsUseCase.swift */, + ); + path = DownloadLatestToolsForFavoritedToolsUseCase; + sourceTree = ""; + }; 45325F18285CF8B40078D932 /* SegmentControl */ = { isa = PBXGroup; children = ( @@ -5707,7 +5725,6 @@ 4556AED323E221FE002C15E8 /* NotoSansEthiopic-Regular.ttf */, D14F75B825D58B96008749CF /* NotoSansMyanmarUI-Condensed.ttf */, D14F75B925D58B96008749CF /* NotoSansMyanmarUI-CondensedBold.ttf */, - D4E243DE29F30DAC00EA4BB7 /* Roboto-Medium.ttf */, 4556AECA23E22185002C15E8 /* SF-Pro-Display-Light.otf */, 45BE4A7C2AF28788004021DA /* SF-Pro-Display-Regular.otf */, 450EF833247EB3D300978926 /* SF-Pro-Text-Bold.otf */, @@ -8013,6 +8030,7 @@ 45B3F4672AC3B1F500D61BFD /* GetAppInterfaceLayoutDirection.swift */, 45B3F4332AC3A82E00D61BFD /* GetAppLanguagesListRepository.swift */, 45DB188D2AD7906900E9578F /* GetAppLanguagesRepository.swift */, + D43FC1C32B65E0F300F8310E /* GetConfirmAppLanguageInterfaceStringsRepository.swift */, 45B3F4352AC3A82E00D61BFD /* GetDeviceAppLanguageRepository.swift */, 45AC9DD72B28A97300DEEBFE /* GetDownloadableLanguagesInterfaceStringsRepository.swift */, 453A2EFF2B3636EC00C8F865 /* GetDownloadableLanguagesListRepository.swift */, @@ -8815,14 +8833,6 @@ path = FirebaseInAppMessaging; sourceTree = ""; }; - 45D9608B289B877D001A5A3E /* GetAllFavoritedToolsLatestTranslationFilesUseCase */ = { - isa = PBXGroup; - children = ( - 45D9608C289B877D001A5A3E /* GetAllFavoritedToolsLatestTranslationFilesUseCase.swift */, - ); - path = GetAllFavoritedToolsLatestTranslationFilesUseCase; - sourceTree = ""; - }; 45DAC8C72B2BBA1200A138C0 /* GetTranslatedLanguageName */ = { isa = PBXGroup; children = ( @@ -8837,6 +8847,7 @@ children = ( 45DBE5E92ACD9EAA008A93BF /* AddToolToFavoritesUseCase */, 45DBE5D72ACD9EAA008A93BF /* DisableOptInOnboardingBannerUseCase */, + 452F6E7F2B69A1C40012AF9C /* DownloadLatestToolsForFavoritedToolsUseCase */, 45DBE5EB2ACD9EAA008A93BF /* GetAllFavoritedToolsUseCase */, 45DBE5E12ACD9EAA008A93BF /* GetAllToolsUseCase */, 45DBE5F62ACD9EAA008A93BF /* GetLanguageAvailabilityUseCase */, @@ -9141,6 +9152,7 @@ 45E246952B446C43008223FB /* Data-DomainInterface */ = { isa = PBXGroup; children = ( + 452F6E862B69A3420012AF9C /* FavoritedToolsLatestToolDownloader.swift */, 45965D4E2B44890F001C9AA5 /* GetDashboardInterfaceStringsRepository.swift */, ); path = "Data-DomainInterface"; @@ -9159,6 +9171,7 @@ 45E246972B446C5D008223FB /* Interface */ = { isa = PBXGroup; children = ( + 452F6E842B69A33C0012AF9C /* FavoritedToolsLatestToolDownloaderInterface.swift */, 45965D4C2B4488BD001C9AA5 /* GetDashboardInterfaceStringsRepositoryInterface.swift */, ); path = Interface; @@ -9692,13 +9705,13 @@ children = ( 453A2EF52B3636D900C8F865 /* DownloadToolLanguageUseCase.swift */, 450DB5612AC3552700B2FE3A /* GetAppLanguagesListUseCase.swift */, - 45BE4A852AF287F0004021DA /* GetConfirmAppLanguageInterfaceStringsUseCase.swift */, 450DB55F2AC354C000B2FE3A /* GetCurrentAppLanguageUseCase.swift */, 45B3F46B2AC3B5DC00D61BFD /* GetInterfaceLayoutDirectionUseCase.swift */, 4569C5012AC367BD0004BCDE /* GetInterfaceStringInAppLanguageUseCase.swift */, 453A2EF62B3636DA00C8F865 /* RemoveDownloadedToolLanguageUseCase.swift */, 45ACEE192AD0492D004B62E4 /* SearchAppLanguageInAppLanguagesListUseCase.swift */, 4585BF632AC391D200A6D720 /* SetAppLanguageUseCase.swift */, + 45BE4A852AF287F0004021DA /* ViewConfirmAppLanguageUseCase.swift */, 45AC9DE32B28A9B100DEEBFE /* ViewDownloadableLanguagesUseCase.swift */, 450069882B193867008A7499 /* ViewLanguageSettingsUseCase.swift */, ); @@ -9968,7 +9981,6 @@ 45F88AFA2860BA8700C8027F /* UseCases */ = { isa = PBXGroup; children = ( - 45D9608B289B877D001A5A3E /* GetAllFavoritedToolsLatestTranslationFilesUseCase */, 45569E6A29F30BE7006F3E4E /* GetAppUIDebuggingIsEnabledUseCase */, D41B38C028906AF600BD5899 /* GetDeviceLanguageUseCase */, 451FB9332896B3DE00423865 /* GetLanguageUseCase */, @@ -11058,7 +11070,6 @@ 4556AED823E221FE002C15E8 /* NotoSansEthiopic-Regular.ttf in Resources */, 4555840F269F2DA500C3FF14 /* MobileContentTextView.xib in Resources */, 4556AED523E221FE002C15E8 /* AbyssinicaSIL-R.ttf in Resources */, - D4E243DF29F30DAD00EA4BB7 /* Roboto-Medium.ttf in Resources */, 45B6480A25E581660098BAF1 /* (null) in Resources */, 45F7162E290A12D70019B715 /* WebContentView.xib in Resources */, 45DEF22E2576A6A20007AC64 /* learn_to_share_tool_with_anyone.json in Resources */, @@ -11264,7 +11275,7 @@ 45AD20BD25938F1A00A096A0 /* Signal.swift in Sources */, 4561AC9C279C4CD4003718C0 /* MobileContentCardCollectionPageViewModel.swift in Sources */, 450D7B0428E32965006C3FDF /* DownloadedTranslationDataModel.swift in Sources */, - 45BE4A862AF287F0004021DA /* GetConfirmAppLanguageInterfaceStringsUseCase.swift in Sources */, + 45BE4A862AF287F0004021DA /* ViewConfirmAppLanguageUseCase.swift in Sources */, 45DBE6212ACDA371008A93BF /* FeaturedLessonsDataLayerDependencies.swift in Sources */, 45FE825D2ACE5D8C00930C39 /* NavBarItem.swift in Sources */, 452486E72B07C9AA007AD932 /* UserFiltersUserDefaultsCache.swift in Sources */, @@ -11308,6 +11319,7 @@ 452486CF2B07C987007AD932 /* GetUserFiltersUseCase.swift in Sources */, 456D445A2AF2A617008F61B9 /* AuthenticationProviderInterface.swift in Sources */, 45FB160E27DBDDB60009DF8E /* TractFlowCompletedState.swift in Sources */, + D43FC1C42B65E0F300F8310E /* GetConfirmAppLanguageInterfaceStringsRepository.swift in Sources */, 453AC11328F4A10400291791 /* RealmFollowUp.swift in Sources */, 45E62FBA2AFA927B00FFEC61 /* ToolScreenShareFlow.swift in Sources */, 4504D00428BD00E400D8A5FD /* GodToolsParserLogger.swift in Sources */, @@ -11414,6 +11426,7 @@ 45B3F44C2AC3A86100D61BFD /* AppLanguagesRepository.swift in Sources */, D409F2A8291D9C2300D9D2FE /* MobileContentApiAuthSession.swift in Sources */, 452486BB2B07C894007AD932 /* ToolFilterCategorySelectionView.swift in Sources */, + 452F6E852B69A33C0012AF9C /* FavoritedToolsLatestToolDownloaderInterface.swift in Sources */, 45DBE6272ACDA41A008A93BF /* GetFeaturedLessonsRepositoryInterface.swift in Sources */, 45D08D762AFAC9DD00ADA673 /* CreatingToolScreenShareSessionView.swift in Sources */, 45EB9B7C29F16CF200CA74A8 /* UIViewController+Containment.swift in Sources */, @@ -11527,6 +11540,7 @@ D455F3F0297739F6009D5F93 /* AccountActivityView.swift in Sources */, D4670B092AFAA07F00FAD896 /* StringSearcher.swift in Sources */, 450F94DB27A1F0F6009DEA43 /* MobileContentCardCollectionPageCardView.swift in Sources */, + 452F6E812B69A1C40012AF9C /* DownloadLatestToolsForFavoritedToolsUseCase.swift in Sources */, 452259B82ABCC6FB0070F7F3 /* AnalyticsContainer+TrackActionAnalyticsInterface.swift in Sources */, 45DAC8CD2B2BBA2B00A138C0 /* LanguageModel+TranslatableLanguage.swift in Sources */, 4592A0EA29D74AE00002E70A /* OnboardingTutorialPrimaryButton.swift in Sources */, @@ -11835,7 +11849,6 @@ 45B212B629229CBA00C9A94D /* SwiftUIPreviewDiContainer.swift in Sources */, 45AE974E27C97A9500C2CB33 /* LessonPage+MobileContentRenderableModel.swift in Sources */, 45920D342A8D17FE00E336A8 /* ToolSpotlightView.swift in Sources */, - 45D9608D289B877D001A5A3E /* GetAllFavoritedToolsLatestTranslationFilesUseCase.swift in Sources */, 45ACBE092B1F64230017D17E /* LessonView.swift in Sources */, 45EA98FE2AFD691200E7EA9A /* GetCreatingToolScreenShareSessionTimedOutInterfaceStringsRepository.swift in Sources */, 45828BC8279CCB5300F6B5F3 /* MobileContentCardView.swift in Sources */, @@ -12330,6 +12343,7 @@ 45F7B0B32AF18E3D00A0E7B4 /* GetMenuInterfaceStringsUseCase.swift in Sources */, 45FE825A2ACE5D8C00930C39 /* NavBarItemController.swift in Sources */, 4570C3032ADDC86600F0B83B /* AppNavigationBarAppearance.swift in Sources */, + 452F6E872B69A3420012AF9C /* FavoritedToolsLatestToolDownloader.swift in Sources */, 45AE974F27C97A9500C2CB33 /* Hero+MobileContentRenderableModel.swift in Sources */, 45AE975727C97A9500C2CB33 /* Form+MobileContentRenderableModel.swift in Sources */, D4B060042913096A005852D0 /* MobileContentAuthTokenKeychainAccessor.swift in Sources */, @@ -12474,6 +12488,7 @@ 45B3F45F2AC3ADF500D61BFD /* DeviceLanguageDomainModel.swift in Sources */, 45965D472B4486A1001C9AA5 /* ViewDashboardUseCase.swift in Sources */, 45AD1F6025938A9800A096A0 /* ActionCableChannelPublisher.swift in Sources */, + D43FC1C02B64531F00F8310E /* ViewConfirmAppLanguageDomainModel.swift in Sources */, 45AE975E27C97A9500C2CB33 /* Card+MobileContentRenderableModel.swift in Sources */, 4529B96628933A610011F16B /* ParseTranslationManifestForRenderer.swift in Sources */, 453F84D22A029FC00005101E /* ArticleAemDownloadOperationError.swift in Sources */, @@ -12487,6 +12502,7 @@ 45A8E4332AFC0A9C008EF03D /* CreatingToolScreenShareSessionInterfaceStringsDomainModel.swift in Sources */, 451C84922AF1C2A40003BF1A /* SocialSignInButtonView.swift in Sources */, 456BB02A27C588E80087CCA4 /* MobileContentHeadingView.swift in Sources */, + D43FC1C22B65E08C00F8310E /* GetConfirmAppLanguageInterfaceStringsRepositoryInterface.swift in Sources */, 458D01812B1E4D0B0029523C /* ViewLessonsDomainModel.swift in Sources */, 45DBE61F2ACDA34D008A93BF /* FeaturedLessonsDiContainer.swift in Sources */, 455582E9269F2C1000C3FF14 /* TrainingPageView.swift in Sources */, diff --git a/godtools/App/AppBackgroundState.swift b/godtools/App/AppBackgroundState.swift index 8a5b2cecf0..562ea9056c 100644 --- a/godtools/App/AppBackgroundState.swift +++ b/godtools/App/AppBackgroundState.swift @@ -7,20 +7,23 @@ // import Foundation +import Combine class AppBackgroundState { static let shared: AppBackgroundState = AppBackgroundState() - - private var getAllFavoritedToolsLatestTranslationFilesUseCase: GetAllFavoritedToolsLatestTranslationFilesUseCase? + private var storeInitialFavoritedToolsUseCase: StoreInitialFavoritedToolsUseCase? + private var cancellables: Set = Set() private var isStarted: Bool = false + @Published private var appLanguage: AppLanguageDomainModel = "" + private init() { } - func start(getAllFavoritedToolsLatestTranslationFilesUseCase: GetAllFavoritedToolsLatestTranslationFilesUseCase, storeInitialFavoritedToolsUseCase: StoreInitialFavoritedToolsUseCase) { + func start(appDiContainer: AppDiContainer) { guard !isStarted else { return @@ -28,7 +31,26 @@ class AppBackgroundState { isStarted = true - self.getAllFavoritedToolsLatestTranslationFilesUseCase = getAllFavoritedToolsLatestTranslationFilesUseCase - self.storeInitialFavoritedToolsUseCase = storeInitialFavoritedToolsUseCase + let downloadLatestToolsForFavoritedToolsUseCase: DownloadLatestToolsForFavoritedToolsUseCase = appDiContainer.feature.dashboard.domainLayer.getDownloadLatestToolsForFavoritedToolsUseCase() + + appDiContainer.feature.appLanguage.domainLayer + .getCurrentAppLanguageUseCase() + .getLanguagePublisher() + .assign(to: &$appLanguage) + + $appLanguage + .eraseToAnyPublisher() + .flatMap({ (appLanguage: AppLanguageDomainModel) -> AnyPublisher in + + return downloadLatestToolsForFavoritedToolsUseCase + .downloadPublisher(appLanguage: appLanguage) + .eraseToAnyPublisher() + }) + .sink { _ in + + } + .store(in: &cancellables) + + self.storeInitialFavoritedToolsUseCase = appDiContainer.domainLayer.getStoreInitialFavoritedToolsUseCase() } } diff --git a/godtools/App/DependencyContainer/AppDomainLayerDependencies.swift b/godtools/App/DependencyContainer/AppDomainLayerDependencies.swift index da8368aa63..25b3797980 100644 --- a/godtools/App/DependencyContainer/AppDomainLayerDependencies.swift +++ b/godtools/App/DependencyContainer/AppDomainLayerDependencies.swift @@ -27,16 +27,6 @@ class AppDomainLayerDependencies { ) } - func getAllFavoritedToolsLatestTranslationFilesUseCase() -> GetAllFavoritedToolsLatestTranslationFilesUseCase { - return GetAllFavoritedToolsLatestTranslationFilesUseCase( - getLanguageUseCase: getLanguageUseCase(), - getSettingsPrimaryLanguageUseCase: getSettingsPrimaryLanguageUseCase(), - favoritedResourcesRepository: dataLayer.getFavoritedResourcesRepository(), - resourcesRepository: dataLayer.getResourcesRepository(), - translationsRepository: dataLayer.getTranslationsRepository() - ) - } - func getAllFavoritedToolsUseCase() -> GetAllFavoritedToolsUseCase { return GetAllFavoritedToolsUseCase( getSettingsPrimaryLanguageUseCase: getSettingsPrimaryLanguageUseCase(), diff --git a/godtools/App/Features/AppLanguage/Data-DomainInterface/GetConfirmAppLanguageInterfaceStringsRepository.swift b/godtools/App/Features/AppLanguage/Data-DomainInterface/GetConfirmAppLanguageInterfaceStringsRepository.swift new file mode 100644 index 0000000000..f46cec0b59 --- /dev/null +++ b/godtools/App/Features/AppLanguage/Data-DomainInterface/GetConfirmAppLanguageInterfaceStringsRepository.swift @@ -0,0 +1,52 @@ +// +// GetConfirmAppLanguageInterfaceStringsRepository.swift +// godtools +// +// Created by Rachael Skeath on 1/27/24. +// Copyright © 2024 Cru. All rights reserved. +// + +import Foundation +import Combine + +class GetConfirmAppLanguageInterfaceStringsRepository: GetConfirmAppLanguageInterfaceStringsRepositoryInterface { + + private let localizationServices: LocalizationServices + private let localeLanguageName: LocaleLanguageName + + init(localizationServices: LocalizationServices, localeLanguageName: LocaleLanguageName) { + + self.localizationServices = localizationServices + self.localeLanguageName = localeLanguageName + } + + func getStringsPublisher(translateInAppLanguage: AppLanguageDomainModel, selectedLanguage: AppLanguageDomainModel) -> AnyPublisher { + + let appLanguageLocaleId: String = translateInAppLanguage + + let interfaceStrings = ConfirmAppLanguageInterfaceStringsDomainModel( + messageInNewlySelectedLanguage: getAttributedMessageStringPublisher(selectedLanguage: selectedLanguage, localeId: selectedLanguage), + messageInCurrentLanguage: getAttributedMessageStringPublisher(selectedLanguage: selectedLanguage, localeId: appLanguageLocaleId), + changeLanguageButtonText: localizationServices.stringForLocaleElseEnglish(localeIdentifier: appLanguageLocaleId, key: "languageSettings.confirmAppLanguage.changeLanguageButton.title"), + nevermindButtonText: localizationServices.stringForLocaleElseEnglish(localeIdentifier: appLanguageLocaleId, key: "languageSettings.confirmAppLanguage.nevermindButton.title") + ) + + return Just(interfaceStrings) + .eraseToAnyPublisher() + } + + private func getAttributedMessageStringPublisher(selectedLanguage: AppLanguageDomainModel, localeId: String) -> NSAttributedString { + + let formatString = localizationServices.stringForLocaleElseEnglish(localeIdentifier: localeId, key: "languageSettings.confirmAppLanguage.message") + + let languageName = self.localeLanguageName.getLanguageName(forLanguageCode: selectedLanguage, translatedInLanguageId: localeId) ?? "" + let languageNameAttributed = NSAttributedString( + string: languageName, + attributes: [NSAttributedString.Key.foregroundColor: ColorPalette.gtBlue.uiColor] + ) + + let attributedString = NSAttributedString(format: NSAttributedString(string: formatString), args: languageNameAttributed) + + return attributedString + } +} diff --git a/godtools/App/Features/AppLanguage/DependencyContainer/AppLanguageFeatureDataLayerDependencies.swift b/godtools/App/Features/AppLanguage/DependencyContainer/AppLanguageFeatureDataLayerDependencies.swift index 08b68fa441..a175cff3d0 100644 --- a/godtools/App/Features/AppLanguage/DependencyContainer/AppLanguageFeatureDataLayerDependencies.swift +++ b/godtools/App/Features/AppLanguage/DependencyContainer/AppLanguageFeatureDataLayerDependencies.swift @@ -68,6 +68,13 @@ class AppLanguageFeatureDataLayerDependencies { ) } + func getConfirmAppLanguageInterfaceStringsRepositoryInterface() -> GetConfirmAppLanguageInterfaceStringsRepositoryInterface { + return GetConfirmAppLanguageInterfaceStringsRepository( + localizationServices: coreDataLayer.getLocalizationServices(), + localeLanguageName: coreDataLayer.getLocaleLanguageName() + ) + } + func getDeviceAppLanguageRepositoryInterface() -> GetDeviceAppLanguageRepositoryInterface { return GetDeviceAppLanguageRepository( deviceSystemLanguage: coreDataLayer.getDeviceSystemLanguage() diff --git a/godtools/App/Features/AppLanguage/DependencyContainer/AppLanguageFeatureDomainLayerDependencies.swift b/godtools/App/Features/AppLanguage/DependencyContainer/AppLanguageFeatureDomainLayerDependencies.swift index 18f55fdad1..693e3e2418 100644 --- a/godtools/App/Features/AppLanguage/DependencyContainer/AppLanguageFeatureDomainLayerDependencies.swift +++ b/godtools/App/Features/AppLanguage/DependencyContainer/AppLanguageFeatureDomainLayerDependencies.swift @@ -35,15 +35,6 @@ class AppLanguageFeatureDomainLayerDependencies { ) } - func getConfirmAppLanguageInterfaceStringsUseCase() -> GetConfirmAppLanguageInterfaceStringsUseCase { - return GetConfirmAppLanguageInterfaceStringsUseCase( - getCurrentAppLanguageUseCase: getCurrentAppLanguageUseCase(), - getInterfaceStringInAppLanguageUseCase: getInterfaceStringInAppLanguageUseCase(), - getInterfaceStringRepositoryInterface: coreDataLayer.getInterfaceStringForLanguageRepositoryInterface(), - localeLanguageName: coreDataLayer.getLocaleLanguageName() - ) - } - func getDownloadToolLanguageUseCase() -> DownloadToolLanguageUseCase { return DownloadToolLanguageUseCase( downloadToolLanguageRepository: dataLayer.getDownloadToolLanguageRepositoryInterface() @@ -81,6 +72,12 @@ class AppLanguageFeatureDomainLayerDependencies { ) } + func getViewConfirmAppLanguageUseCase() -> ViewConfirmAppLanguageUseCase { + return ViewConfirmAppLanguageUseCase( + getConfirmAppLanguageInterfaceStringsRepository: dataLayer.getConfirmAppLanguageInterfaceStringsRepositoryInterface() + ) + } + func getViewDownloadableLanguagesUseCase() -> ViewDownloadableLanguagesUseCase { return ViewDownloadableLanguagesUseCase( getDownloadableLanguagesListRepository: dataLayer.getDownloadableLanguagesListRepositoryInterface(), diff --git a/godtools/App/Features/AppLanguage/Domain/Entities/ViewConfirmAppLanguageDomainModel.swift b/godtools/App/Features/AppLanguage/Domain/Entities/ViewConfirmAppLanguageDomainModel.swift new file mode 100644 index 0000000000..fa259c1ec8 --- /dev/null +++ b/godtools/App/Features/AppLanguage/Domain/Entities/ViewConfirmAppLanguageDomainModel.swift @@ -0,0 +1,14 @@ +// +// ViewConfirmAppLanguageDomainModel.swift +// godtools +// +// Created by Rachael Skeath on 1/26/24. +// Copyright © 2024 Cru. All rights reserved. +// + +import Foundation + +struct ViewConfirmAppLanguageDomainModel { + + let interfaceStrings: ConfirmAppLanguageInterfaceStringsDomainModel +} diff --git a/godtools/App/Features/AppLanguage/Domain/Interface/GetConfirmAppLanguageInterfaceStringsRepositoryInterface.swift b/godtools/App/Features/AppLanguage/Domain/Interface/GetConfirmAppLanguageInterfaceStringsRepositoryInterface.swift new file mode 100644 index 0000000000..dbea40dffa --- /dev/null +++ b/godtools/App/Features/AppLanguage/Domain/Interface/GetConfirmAppLanguageInterfaceStringsRepositoryInterface.swift @@ -0,0 +1,15 @@ +// +// GetConfirmAppLanguageInterfaceStringsRepositoryInterface.swift +// godtools +// +// Created by Rachael Skeath on 1/27/24. +// Copyright © 2024 Cru. All rights reserved. +// + +import Foundation +import Combine + +protocol GetConfirmAppLanguageInterfaceStringsRepositoryInterface { + + func getStringsPublisher(translateInAppLanguage: AppLanguageDomainModel, selectedLanguage: AppLanguageDomainModel) -> AnyPublisher +} diff --git a/godtools/App/Features/AppLanguage/Domain/UseCases/GetConfirmAppLanguageInterfaceStringsUseCase.swift b/godtools/App/Features/AppLanguage/Domain/UseCases/GetConfirmAppLanguageInterfaceStringsUseCase.swift deleted file mode 100644 index c2ede018b6..0000000000 --- a/godtools/App/Features/AppLanguage/Domain/UseCases/GetConfirmAppLanguageInterfaceStringsUseCase.swift +++ /dev/null @@ -1,91 +0,0 @@ -// -// GetConfirmAppLanguageInterfaceStringsUseCase.swift -// godtools -// -// Created by Rachael Skeath on 10/23/23. -// Copyright © 2023 Cru. All rights reserved. -// - -import Foundation -import Combine - -class GetConfirmAppLanguageInterfaceStringsUseCase { - - private let getCurrentAppLanguageUseCase: GetCurrentAppLanguageUseCase - private let getInterfaceStringInAppLanguageUseCase: GetInterfaceStringInAppLanguageUseCase - private let getInterfaceStringRepositoryInterface: GetInterfaceStringForLanguageRepositoryInterface - private let localeLanguageName: LocaleLanguageName - - init(getCurrentAppLanguageUseCase: GetCurrentAppLanguageUseCase, getInterfaceStringInAppLanguageUseCase: GetInterfaceStringInAppLanguageUseCase, getInterfaceStringRepositoryInterface: GetInterfaceStringForLanguageRepositoryInterface, localeLanguageName: LocaleLanguageName) { - - self.getCurrentAppLanguageUseCase = getCurrentAppLanguageUseCase - self.getInterfaceStringInAppLanguageUseCase = getInterfaceStringInAppLanguageUseCase - self.getInterfaceStringRepositoryInterface = getInterfaceStringRepositoryInterface - self.localeLanguageName = localeLanguageName - } - - func getStringsPublisher(for selectedLanguage: AppLanguageDomainModel) -> AnyPublisher { - - return Publishers.CombineLatest4( - getMessageInNewlySelectedLanguagePublisher(selectedLanguage: selectedLanguage), - getMessageInCurrentLanguagePublisher(selectedLanguage: selectedLanguage), - getChangeLanguageButtonTextPublisher(selectedLanguage: selectedLanguage), - getNevermindButtonTextPublisher(selectedLanguage: selectedLanguage) - ) - .flatMap { messageInNewlySelectedLanguage, messageInCurrenttLanguage, changeLanguageButtonText, nevermindButtonText in - - let domainModel = ConfirmAppLanguageInterfaceStringsDomainModel( - messageInNewlySelectedLanguage: messageInNewlySelectedLanguage, - messageInCurrentLanguage: messageInCurrenttLanguage, - changeLanguageButtonText: changeLanguageButtonText, - nevermindButtonText: nevermindButtonText - ) - - return Just(domainModel) - } - .eraseToAnyPublisher() - } - - private func getMessageInNewlySelectedLanguagePublisher(selectedLanguage: AppLanguageDomainModel) -> AnyPublisher { - - return getAttributedMessageStringPublisher(selectedLanguage: selectedLanguage, translatedInLanguage: selectedLanguage) - } - - private func getMessageInCurrentLanguagePublisher(selectedLanguage: AppLanguageDomainModel) -> AnyPublisher { - - return getCurrentAppLanguageUseCase.getLanguagePublisher() - .flatMap { currentAppLanguage in - - return self.getAttributedMessageStringPublisher(selectedLanguage: selectedLanguage, translatedInLanguage: currentAppLanguage) - } - .eraseToAnyPublisher() - } - - private func getAttributedMessageStringPublisher(selectedLanguage: AppLanguageDomainModel, translatedInLanguage: AppLanguageDomainModel) -> AnyPublisher { - - return getInterfaceStringRepositoryInterface.getStringPublisher(languageCode: translatedInLanguage, stringId: "languageSettings.confirmAppLanguage.message") - .flatMap { formatString in - - let languageName = self.localeLanguageName.getLanguageName(forLanguageCode: selectedLanguage, translatedInLanguageId: translatedInLanguage) ?? "" - let languageNameAttributed = NSAttributedString( - string: languageName, - attributes: [NSAttributedString.Key.foregroundColor: ColorPalette.gtBlue.uiColor] - ) - - let attributedString = NSAttributedString(format: NSAttributedString(string: formatString), args: languageNameAttributed) - - return Just(attributedString) - } - .eraseToAnyPublisher() - } - - private func getChangeLanguageButtonTextPublisher(selectedLanguage: AppLanguageDomainModel) -> AnyPublisher { - - return getInterfaceStringRepositoryInterface.getStringPublisher(languageCode: selectedLanguage, stringId: "languageSettings.confirmAppLanguage.changeLanguageButton.title") - } - - private func getNevermindButtonTextPublisher(selectedLanguage: AppLanguageDomainModel) -> AnyPublisher { - - return getInterfaceStringRepositoryInterface.getStringPublisher(languageCode: selectedLanguage, stringId: "languageSettings.confirmAppLanguage.nevermindButton.title") - } -} diff --git a/godtools/App/Features/AppLanguage/Domain/UseCases/ViewConfirmAppLanguageUseCase.swift b/godtools/App/Features/AppLanguage/Domain/UseCases/ViewConfirmAppLanguageUseCase.swift new file mode 100644 index 0000000000..b0e2bf424e --- /dev/null +++ b/godtools/App/Features/AppLanguage/Domain/UseCases/ViewConfirmAppLanguageUseCase.swift @@ -0,0 +1,30 @@ +// +// ViewConfirmAppLanguageUseCase.swift +// godtools +// +// Created by Rachael Skeath on 10/23/23. +// Copyright © 2023 Cru. All rights reserved. +// + +import Foundation +import Combine + +class ViewConfirmAppLanguageUseCase { + + private let getConfirmAppLanguageInterfaceStringsRepository: GetConfirmAppLanguageInterfaceStringsRepositoryInterface + + init(getConfirmAppLanguageInterfaceStringsRepository: GetConfirmAppLanguageInterfaceStringsRepositoryInterface) { + + self.getConfirmAppLanguageInterfaceStringsRepository = getConfirmAppLanguageInterfaceStringsRepository + } + + func viewPublisher(appLanguage: AppLanguageDomainModel, selectedLanguage: AppLanguageDomainModel) -> AnyPublisher { + + return getConfirmAppLanguageInterfaceStringsRepository.getStringsPublisher(translateInAppLanguage: appLanguage, selectedLanguage: selectedLanguage) + .map { interfaceStrings in + + return ViewConfirmAppLanguageDomainModel(interfaceStrings: interfaceStrings) + } + .eraseToAnyPublisher() + } +} diff --git a/godtools/App/Features/AppLanguage/Presentation/ConfirmAppLanguage/ConfirmAppLanguageView.swift b/godtools/App/Features/AppLanguage/Presentation/ConfirmAppLanguage/ConfirmAppLanguageView.swift index 9ffcbeade5..42e8d38b88 100644 --- a/godtools/App/Features/AppLanguage/Presentation/ConfirmAppLanguage/ConfirmAppLanguageView.swift +++ b/godtools/App/Features/AppLanguage/Presentation/ConfirmAppLanguage/ConfirmAppLanguageView.swift @@ -52,7 +52,7 @@ struct ConfirmAppLanguageView: View { Group { attributedMessageView(attributedString: viewModel.messageInCurrentLanguage, fontSize: 18) - attributedMessageView(attributedString: viewModel.messageInNewlySelectedLanguage, fontSize: 14) + attributedMessageView(attributedString: viewModel.messageInNewlySelectedLanguage, fontSize: 18) } .padding(.horizontal, 10) @@ -64,14 +64,14 @@ struct ConfirmAppLanguageView: View { let buttonWidth = (geometry.size.width - buttonSpacing - 2*horizontalPadding) / 2 - GTBlueButton(title: viewModel.changeLanguageButtonTitle, fontSize: 15, width: buttonWidth, height: 48) { + GTWhiteButton(title: viewModel.nevermindButtonTitle, fontSize: 15, width: buttonWidth, height: 48) { - viewModel.confirmLanguageButtonTapped() + viewModel.nevermindButtonTapped() } - GTWhiteButton(title: viewModel.nevermindButtonTitle, fontSize: 15, width: buttonWidth, height: 48) { + GTBlueButton(title: viewModel.changeLanguageButtonTitle, fontSize: 15, width: buttonWidth, height: 48) { - viewModel.nevermindButtonTapped() + viewModel.confirmLanguageButtonTapped() } } diff --git a/godtools/App/Features/AppLanguage/Presentation/ConfirmAppLanguage/ConfirmAppLanguageViewModel.swift b/godtools/App/Features/AppLanguage/Presentation/ConfirmAppLanguage/ConfirmAppLanguageViewModel.swift index 15a79ad25c..d8a0139958 100644 --- a/godtools/App/Features/AppLanguage/Presentation/ConfirmAppLanguage/ConfirmAppLanguageViewModel.swift +++ b/godtools/App/Features/AppLanguage/Presentation/ConfirmAppLanguage/ConfirmAppLanguageViewModel.swift @@ -12,30 +12,46 @@ import Combine class ConfirmAppLanguageViewModel: ObservableObject { private let selectedLanguage: AppLanguageListItemDomainModel - private var cancellables: Set = Set() + private let getCurrentAppLanguageUseCase: GetCurrentAppLanguageUseCase + private let viewConfirmAppLanguageUseCase: ViewConfirmAppLanguageUseCase + private var cancellables: Set = Set() private weak var flowDelegate: FlowDelegate? + @Published private var appLanguage: AppLanguageDomainModel = LanguageCodeDomainModel.english.rawValue + @Published var messageInNewlySelectedLanguage: NSAttributedString = NSAttributedString() @Published var messageInCurrentLanguage: NSAttributedString = NSAttributedString() @Published var changeLanguageButtonTitle: String = "" @Published var nevermindButtonTitle: String = "" - init(selectedLanguage: AppLanguageListItemDomainModel, getConfirmAppLanguageInterfaceStringsUseCase: GetConfirmAppLanguageInterfaceStringsUseCase, flowDelegate: FlowDelegate?) { + init(selectedLanguage: AppLanguageListItemDomainModel, getCurrentAppLanguageUseCase: GetCurrentAppLanguageUseCase, viewConfirmAppLanguageUseCase: ViewConfirmAppLanguageUseCase, flowDelegate: FlowDelegate?) { self.selectedLanguage = selectedLanguage self.flowDelegate = flowDelegate - getConfirmAppLanguageInterfaceStringsUseCase.getStringsPublisher(for: selectedLanguage.language) + self.getCurrentAppLanguageUseCase = getCurrentAppLanguageUseCase + self.viewConfirmAppLanguageUseCase = viewConfirmAppLanguageUseCase + + getCurrentAppLanguageUseCase.getLanguagePublisher() + .receive(on: DispatchQueue.main) + .assign(to: &$appLanguage) + + $appLanguage.eraseToAnyPublisher() + .flatMap { appLanguage in + + return viewConfirmAppLanguageUseCase.viewPublisher(appLanguage: appLanguage, selectedLanguage: selectedLanguage.language) + .eraseToAnyPublisher() + } .receive(on: DispatchQueue.main) - .sink { _ in + .sink { [weak self] domainModel in - } receiveValue: { [weak self] stringsDomainModel in + let interfaceStrings = domainModel.interfaceStrings - self?.messageInNewlySelectedLanguage = stringsDomainModel.messageInNewlySelectedLanguage - self?.messageInCurrentLanguage = stringsDomainModel.messageInCurrentLanguage - self?.changeLanguageButtonTitle = stringsDomainModel.changeLanguageButtonText - self?.nevermindButtonTitle = stringsDomainModel.nevermindButtonText + self?.messageInNewlySelectedLanguage = interfaceStrings.messageInNewlySelectedLanguage + self?.messageInCurrentLanguage = interfaceStrings.messageInCurrentLanguage + self?.changeLanguageButtonTitle = interfaceStrings.changeLanguageButtonText + self?.nevermindButtonTitle = interfaceStrings.nevermindButtonText } .store(in: &cancellables) } diff --git a/godtools/App/Features/Dashboard/Data-DomainInterface/FavoritedToolsLatestToolDownloader.swift b/godtools/App/Features/Dashboard/Data-DomainInterface/FavoritedToolsLatestToolDownloader.swift new file mode 100644 index 0000000000..d47f957f01 --- /dev/null +++ b/godtools/App/Features/Dashboard/Data-DomainInterface/FavoritedToolsLatestToolDownloader.swift @@ -0,0 +1,77 @@ +// +// FavoritedToolsLatestToolDownloader.swift +// godtools +// +// Created by Levi Eggert on 1/30/24. +// Copyright © 2024 Cru. All rights reserved. +// + +import Foundation +import Combine + +class FavoritedToolsLatestToolDownloader: FavoritedToolsLatestToolDownloaderInterface { + + private let favoritedResourcesRepository: FavoritedResourcesRepository + private let resourcesRepository: ResourcesRepository + private let translationsRepository: TranslationsRepository + + init(favoritedResourcesRepository: FavoritedResourcesRepository, resourcesRepository: ResourcesRepository, translationsRepository: TranslationsRepository) { + + self.favoritedResourcesRepository = favoritedResourcesRepository + self.resourcesRepository = resourcesRepository + self.translationsRepository = translationsRepository + } + + func downloadLatestToolsPublisher(inLanguages: [BCP47LanguageIdentifier]) -> AnyPublisher { + + return Publishers.CombineLatest( + resourcesRepository.getResourcesChangedPublisher(), + favoritedResourcesRepository.getFavoritedResourcesChangedPublisher() + ) + .flatMap({ (resourcesChanged: Void, favoritedResourcesChanged: Void) -> AnyPublisher<[FavoritedResourceDataModel], Never> in + + let favoritedTools: [FavoritedResourceDataModel] = self.favoritedResourcesRepository.getFavoritedResourcesSortedByCreatedAt(ascendingOrder: false) + + return Just(favoritedTools) + .eraseToAnyPublisher() + }) + .flatMap({ (favoritedTools: [FavoritedResourceDataModel]) -> AnyPublisher<[TranslationModel], Never> in + + var translations: [TranslationModel] = Array() + + guard !favoritedTools.isEmpty && !inLanguages.isEmpty else { + return Just(translations) + .eraseToAnyPublisher() + } + + for favoritedTool in favoritedTools { + + for languageIdentifier in inLanguages { + + guard let translation = self.translationsRepository.getLatestTranslation(resourceId: favoritedTool.id, languageCode: languageIdentifier) else { + continue + } + + translations.append(translation) + } + } + + return Just(translations) + .eraseToAnyPublisher() + }) + .flatMap({ (translations: [TranslationModel]) -> AnyPublisher in + + return self.translationsRepository + .downloadAndCacheTranslationsFiles(translations: translations) + .catch { _ in + return Just([]) + .eraseToAnyPublisher() + } + .map { _ in + return Void() + } + .eraseToAnyPublisher() + }) + .eraseToAnyPublisher() + } +} diff --git a/godtools/App/Features/Dashboard/DependencyContainer/DashboardDataLayerDependencies.swift b/godtools/App/Features/Dashboard/DependencyContainer/DashboardDataLayerDependencies.swift index b3d7ba508f..2abbfed1c4 100644 --- a/godtools/App/Features/Dashboard/DependencyContainer/DashboardDataLayerDependencies.swift +++ b/godtools/App/Features/Dashboard/DependencyContainer/DashboardDataLayerDependencies.swift @@ -26,4 +26,12 @@ class DashboardDataLayerDependencies { localizationServices: coreDataLayer.getLocalizationServices() ) } + + func getFavoritedToolsLatestToolDownloaderInterface() -> FavoritedToolsLatestToolDownloaderInterface { + return FavoritedToolsLatestToolDownloader( + favoritedResourcesRepository: coreDataLayer.getFavoritedResourcesRepository(), + resourcesRepository: coreDataLayer.getResourcesRepository(), + translationsRepository: coreDataLayer.getTranslationsRepository() + ) + } } diff --git a/godtools/App/Features/Dashboard/DependencyContainer/DashboardDomainLayerDependencies.swift b/godtools/App/Features/Dashboard/DependencyContainer/DashboardDomainLayerDependencies.swift index 82cf8d09f6..a3477bd112 100644 --- a/godtools/App/Features/Dashboard/DependencyContainer/DashboardDomainLayerDependencies.swift +++ b/godtools/App/Features/Dashboard/DependencyContainer/DashboardDomainLayerDependencies.swift @@ -17,6 +17,12 @@ class DashboardDomainLayerDependencies { self.dataLayer = dataLayer } + func getDownloadLatestToolsForFavoritedToolsUseCase() -> DownloadLatestToolsForFavoritedToolsUseCase { + return DownloadLatestToolsForFavoritedToolsUseCase( + latestToolDownloader: dataLayer.getFavoritedToolsLatestToolDownloaderInterface() + ) + } + func getViewDashboardUseCase() -> ViewDashboardUseCase { return ViewDashboardUseCase( getInterfaceStringsRepository: dataLayer.getDashboardInterfaceStringsRepositoryInterface() diff --git a/godtools/App/Features/Dashboard/Domain/Interface/FavoritedToolsLatestToolDownloaderInterface.swift b/godtools/App/Features/Dashboard/Domain/Interface/FavoritedToolsLatestToolDownloaderInterface.swift new file mode 100644 index 0000000000..c0fcdba503 --- /dev/null +++ b/godtools/App/Features/Dashboard/Domain/Interface/FavoritedToolsLatestToolDownloaderInterface.swift @@ -0,0 +1,15 @@ +// +// FavoritedToolsLatestToolDownloaderInterface.swift +// godtools +// +// Created by Levi Eggert on 1/30/24. +// Copyright © 2024 Cru. All rights reserved. +// + +import Foundation +import Combine + +protocol FavoritedToolsLatestToolDownloaderInterface { + + func downloadLatestToolsPublisher(inLanguages: [BCP47LanguageIdentifier]) -> AnyPublisher +} diff --git a/godtools/App/Features/Dashboard/Domain/UseCases/DownloadLatestToolsForFavoritedToolsUseCase/DownloadLatestToolsForFavoritedToolsUseCase.swift b/godtools/App/Features/Dashboard/Domain/UseCases/DownloadLatestToolsForFavoritedToolsUseCase/DownloadLatestToolsForFavoritedToolsUseCase.swift new file mode 100644 index 0000000000..53e945d5a6 --- /dev/null +++ b/godtools/App/Features/Dashboard/Domain/UseCases/DownloadLatestToolsForFavoritedToolsUseCase/DownloadLatestToolsForFavoritedToolsUseCase.swift @@ -0,0 +1,27 @@ +// +// DownloadLatestToolsForFavoritedToolsUseCase.swift +// godtools +// +// Created by Levi Eggert on 1/30/24. +// Copyright © 2024 Cru. All rights reserved. +// + +import Foundation +import Combine + +class DownloadLatestToolsForFavoritedToolsUseCase { + + private let latestToolDownloader: FavoritedToolsLatestToolDownloaderInterface + + init(latestToolDownloader: FavoritedToolsLatestToolDownloaderInterface) { + + self.latestToolDownloader = latestToolDownloader + } + + func downloadPublisher(appLanguage: AppLanguageDomainModel) -> AnyPublisher { + + return latestToolDownloader + .downloadLatestToolsPublisher(inLanguages: [appLanguage]) + .eraseToAnyPublisher() + } +} diff --git a/godtools/App/Features/Dashboard/Presentation/Tool/ToolViewModel.swift b/godtools/App/Features/Dashboard/Presentation/Tool/ToolViewModel.swift index ebba259f95..34c0b4d465 100644 --- a/godtools/App/Features/Dashboard/Presentation/Tool/ToolViewModel.swift +++ b/godtools/App/Features/Dashboard/Presentation/Tool/ToolViewModel.swift @@ -165,6 +165,7 @@ extension ToolViewModel { renderer: renderer, currentPageRenderer: currentPageRenderer, tractRemoteSharePublisher: tractRemoteSharePublisher, + selectedLanguage: languages[selectedLanguageIndex], pageNumber: currentRenderedPageNumber, trainingTipsEnabled: trainingTipsEnabled ) diff --git a/godtools/App/Features/ToolDetails/Data-DomainInterface/GetToolDetailsLearnToShareToolIsAvailableRepository.swift b/godtools/App/Features/ToolDetails/Data-DomainInterface/GetToolDetailsLearnToShareToolIsAvailableRepository.swift index 224e1d874f..1c2f06ab69 100644 --- a/godtools/App/Features/ToolDetails/Data-DomainInterface/GetToolDetailsLearnToShareToolIsAvailableRepository.swift +++ b/godtools/App/Features/ToolDetails/Data-DomainInterface/GetToolDetailsLearnToShareToolIsAvailableRepository.swift @@ -19,9 +19,9 @@ class GetToolDetailsLearnToShareToolIsAvailableRepository: GetToolDetailsLearnTo self.translationsRepository = translationsRepository } - func getIsAvailablePublisher(tool: ToolDomainModel, toolLanguageCode: String) -> AnyPublisher { + func getIsAvailablePublisher(tool: ToolDomainModel, language: BCP47LanguageIdentifier) -> AnyPublisher { - guard let translation = translationsRepository.getLatestTranslation(resourceId: tool.dataModelId, languageCode: toolLanguageCode) else { + guard let translation = translationsRepository.getLatestTranslation(resourceId: tool.dataModelId, languageCode: language) else { return Just(false) .eraseToAnyPublisher() } diff --git a/godtools/App/Features/ToolDetails/Data-DomainInterface/GetToolDetailsRepository.swift b/godtools/App/Features/ToolDetails/Data-DomainInterface/GetToolDetailsRepository.swift index 80cbcaf36b..7c6c5de57c 100644 --- a/godtools/App/Features/ToolDetails/Data-DomainInterface/GetToolDetailsRepository.swift +++ b/godtools/App/Features/ToolDetails/Data-DomainInterface/GetToolDetailsRepository.swift @@ -106,32 +106,51 @@ class GetToolDetailsRepository: GetToolDetailsRepositoryInterface { let localizedTotalLanguages: String = localizationServices.stringForLocaleElseEnglish(localeIdentifier: translateInLanguage, key: "total_languages") - let versions: [ToolVersionDomainModel] = resourceVariants.compactMap { (variantDataModel: ResourceModel) in - - guard let translation = self.translationsRepository.getLatestTranslation(resourceId: variantDataModel.id, languageCode: translateInLanguage) else { - return nil - } + var toolVersions: [ToolVersionDomainModel] = Array() + + for resourceVariant in resourceVariants { let numberOfLanguagesString: String = String( format: localizedTotalLanguages, locale: Locale(identifier: translateInLanguage), - variantDataModel.languageIds.count + resourceVariant.languageIds.count ) - return ToolVersionDomainModel( - bannerImageId: variantDataModel.attrBanner, - dataModelId: variantDataModel.id, - description: translation.translatedTagline, - name: translation.translatedName, + let name: String + let description: String + + if let appLanguageTranslation = translationsRepository.getLatestTranslation(resourceId: resourceVariant.id, languageCode: translateInLanguage) { + + name = appLanguageTranslation.translatedName + description = appLanguageTranslation.translatedTagline + } + else if let englishTranslation = translationsRepository.getLatestTranslation(resourceId: resourceVariant.id, languageCode: LanguageCodeDomainModel.english.rawValue) { + + name = englishTranslation.translatedName + description = englishTranslation.translatedTagline + } + else { + + name = resourceVariant.name + description = resourceVariant.resourceDescription + } + + let toolVersion = ToolVersionDomainModel( + bannerImageId: resourceVariant.attrBanner, + dataModelId: resourceVariant.id, + description: description, + name: name, numberOfLanguages: numberOfLanguagesString, toolLanguageName: toolPrimaryLanguageName ?? "", - toolLanguageNameIsSupported: getToolSupportsLanguage(resource: variantDataModel, language: toolPrimaryLanguage), + toolLanguageNameIsSupported: getToolSupportsLanguage(resource: resourceVariant, language: toolPrimaryLanguage), toolParallelLanguageName: toolParallelLanguageName, - toolParallelLanguageNameIsSupported: getToolSupportsLanguage(resource: variantDataModel, language: toolParallelLanguage) + toolParallelLanguageNameIsSupported: getToolSupportsLanguage(resource: resourceVariant, language: toolParallelLanguage) ) + + toolVersions.append(toolVersion) } - return versions + return toolVersions } private func getToolSupportsLanguage(resource: ResourceModel, language: AppLanguageDomainModel?) -> Bool { diff --git a/godtools/App/Features/ToolDetails/Domain/Interface/GetToolDetailsLearnToShareToolIsAvailableRepositoryInterface.swift b/godtools/App/Features/ToolDetails/Domain/Interface/GetToolDetailsLearnToShareToolIsAvailableRepositoryInterface.swift index af318f704d..a969648fc7 100644 --- a/godtools/App/Features/ToolDetails/Domain/Interface/GetToolDetailsLearnToShareToolIsAvailableRepositoryInterface.swift +++ b/godtools/App/Features/ToolDetails/Domain/Interface/GetToolDetailsLearnToShareToolIsAvailableRepositoryInterface.swift @@ -11,5 +11,5 @@ import Combine protocol GetToolDetailsLearnToShareToolIsAvailableRepositoryInterface { - func getIsAvailablePublisher(tool: ToolDomainModel, toolLanguageCode: String) -> AnyPublisher + func getIsAvailablePublisher(tool: ToolDomainModel, language: BCP47LanguageIdentifier) -> AnyPublisher } diff --git a/godtools/App/Features/ToolDetails/Domain/UseCases/GetToolDetailsLearnToShareToolIsAvailableUseCase.swift b/godtools/App/Features/ToolDetails/Domain/UseCases/GetToolDetailsLearnToShareToolIsAvailableUseCase.swift index 17d4342b53..6a4c3e4694 100644 --- a/godtools/App/Features/ToolDetails/Domain/UseCases/GetToolDetailsLearnToShareToolIsAvailableUseCase.swift +++ b/godtools/App/Features/ToolDetails/Domain/UseCases/GetToolDetailsLearnToShareToolIsAvailableUseCase.swift @@ -18,17 +18,9 @@ class GetToolDetailsLearnToShareToolIsAvailableUseCase { self.getToolDetailsLearnToShareToolIsAvailableRepository = getToolDetailsLearnToShareToolIsAvailableRepository } - func getIsAvailablePublisher(toolChangedPublisher: AnyPublisher, toolLanguageCodeChangedPublisher: AnyPublisher) -> AnyPublisher { + func getIsAvailablePublisher(tool: ToolDomainModel, language: BCP47LanguageIdentifier) -> AnyPublisher { - Publishers.CombineLatest( - toolChangedPublisher.eraseToAnyPublisher(), - toolLanguageCodeChangedPublisher.eraseToAnyPublisher() - ) - .flatMap({ (tool: ToolDomainModel, toolLanguageCode: String) -> AnyPublisher in - - return self.getToolDetailsLearnToShareToolIsAvailableRepository.getIsAvailablePublisher(tool: tool, toolLanguageCode: toolLanguageCode) - .eraseToAnyPublisher() - }) - .eraseToAnyPublisher() + return self.getToolDetailsLearnToShareToolIsAvailableRepository.getIsAvailablePublisher(tool: tool, language: language) + .eraseToAnyPublisher() } } diff --git a/godtools/App/Features/ToolDetails/Presentation/ToolDetails/ToolDetailsViewModel.swift b/godtools/App/Features/ToolDetails/Presentation/ToolDetails/ToolDetailsViewModel.swift index 311634f100..b1af46ee42 100644 --- a/godtools/App/Features/ToolDetails/Presentation/ToolDetails/ToolDetailsViewModel.swift +++ b/godtools/App/Features/ToolDetails/Presentation/ToolDetails/ToolDetailsViewModel.swift @@ -23,6 +23,8 @@ class ToolDetailsViewModel: ObservableObject { private let attachmentsRepository: AttachmentsRepository private let trackScreenViewAnalyticsUseCase: TrackScreenViewAnalyticsUseCase private let trackActionAnalyticsUseCase: TrackActionAnalyticsUseCase + private let primaryLanguage: AppLanguageDomainModel + private let parallelLanguage: AppLanguageDomainModel? private let selectedLanguageIndex: Int? private var segmentTypes: [ToolDetailsSegmentType] = Array() @@ -36,8 +38,6 @@ class ToolDetailsViewModel: ObservableObject { } } @Published private var appLanguage: AppLanguageDomainModel = LanguageCodeDomainModel.english.rawValue - @Published private var primaryLanguage: AppLanguageDomainModel = LanguageCodeDomainModel.english.value - @Published private var parallelLanguage: AppLanguageDomainModel? @Published var mediaType: ToolDetailsMediaDomainModel = .empty @Published var name: String = "" @@ -65,6 +65,9 @@ class ToolDetailsViewModel: ObservableObject { init(flowDelegate: FlowDelegate, tool: ToolDomainModel, primaryLanguage: AppLanguageDomainModel, parallelLanguage: AppLanguageDomainModel?, selectedLanguageIndex: Int?, getCurrentAppLanguageUseCase: GetCurrentAppLanguageUseCase, getToolUseCase: GetToolUseCase, viewToolDetailsUseCase: ViewToolDetailsUseCase, getToolDetailsMediaUseCase: GetToolDetailsMediaUseCase, getToolDetailsLearnToShareToolIsAvailableUseCase: GetToolDetailsLearnToShareToolIsAvailableUseCase, toggleToolFavoritedUseCase: ToggleToolFavoritedUseCase, attachmentsRepository: AttachmentsRepository, trackScreenViewAnalyticsUseCase: TrackScreenViewAnalyticsUseCase, trackActionAnalyticsUseCase: TrackActionAnalyticsUseCase) { + let primaryLanguage: AppLanguageDomainModel = primaryLanguage + let parallelLanguage: AppLanguageDomainModel? = parallelLanguage != primaryLanguage ? parallelLanguage : nil + self.flowDelegate = flowDelegate self.tool = tool self.primaryLanguage = primaryLanguage @@ -84,14 +87,12 @@ class ToolDetailsViewModel: ObservableObject { .getLanguagePublisher() .assign(to: &$appLanguage) - Publishers.CombineLatest4( + Publishers.CombineLatest( $tool.eraseToAnyPublisher(), - $appLanguage.eraseToAnyPublisher(), - $primaryLanguage.eraseToAnyPublisher(), - $parallelLanguage.eraseToAnyPublisher() + $appLanguage.eraseToAnyPublisher() ) .receive(on: DispatchQueue.main) - .flatMap ({ (tool: ToolDomainModel, appLanguage: AppLanguageDomainModel, primaryLanguage: AppLanguageDomainModel, parallelLanguage: AppLanguageDomainModel?) -> AnyPublisher in + .flatMap ({ (tool: ToolDomainModel, appLanguage: AppLanguageDomainModel) -> AnyPublisher in return viewToolDetailsUseCase .viewPublisher(tool: tool, translateInLanguage: appLanguage, toolPrimaryLanguage: primaryLanguage, toolParallelLanguage: parallelLanguage) @@ -146,11 +147,13 @@ class ToolDetailsViewModel: ObservableObject { .receive(on: DispatchQueue.main) .assign(to: &$mediaType) - getToolDetailsLearnToShareToolIsAvailableUseCase - .getIsAvailablePublisher( - toolChangedPublisher: $tool.eraseToAnyPublisher(), - toolLanguageCodeChangedPublisher: $primaryLanguage.eraseToAnyPublisher() - ) + $tool.eraseToAnyPublisher() + .flatMap({ (tool: ToolDomainModel) -> AnyPublisher in + + return getToolDetailsLearnToShareToolIsAvailableUseCase + .getIsAvailablePublisher(tool: tool, language: primaryLanguage) + .eraseToAnyPublisher() + }) .receive(on: DispatchQueue.main) .assign(to: &$showsLearnToShareToolButton) } diff --git a/godtools/App/Features/ToolScreenShare/Data/TractRemoteShare/TractRemoteSharePublisher/TractRemoteShareURLBuilder.swift b/godtools/App/Features/ToolScreenShare/Data/TractRemoteShare/TractRemoteSharePublisher/TractRemoteShareURLBuilder.swift index 2b716785a8..84aa15c946 100644 --- a/godtools/App/Features/ToolScreenShare/Data/TractRemoteShare/TractRemoteSharePublisher/TractRemoteShareURLBuilder.swift +++ b/godtools/App/Features/ToolScreenShare/Data/TractRemoteShare/TractRemoteSharePublisher/TractRemoteShareURLBuilder.swift @@ -16,13 +16,21 @@ class TractRemoteShareURLBuilder { } - func buildRemoteShareURL(resource: ResourceModel, primaryLanguage: LanguageDomainModel, parallelLanguage: LanguageDomainModel?, subscriberChannelId: String) -> String? { + func buildRemoteShareURL(resource: ResourceModel, primaryLanguage: LanguageDomainModel, parallelLanguage: LanguageDomainModel?, selectedLanguage: LanguageDomainModel, page: Int?, subscriberChannelId: String) -> String? { + + var urlPath: String = "" + urlPath += "/" + selectedLanguage.localeIdentifier + urlPath += "/" + resource.abbreviation + + if let page = page { + urlPath += "/" + String(page) + } var urlComponents: URLComponents = URLComponents() urlComponents.scheme = "https" urlComponents.host = "knowgod.com" - urlComponents.path = "/" + primaryLanguage.localeIdentifier + "/" + resource.abbreviation + urlComponents.path = urlPath var queryItems: [URLQueryItem] = Array() if let parallelLanguage = parallelLanguage { @@ -34,6 +42,8 @@ class TractRemoteShareURLBuilder { urlComponents.queryItems = queryItems - return urlComponents.url?.absoluteString + let urlString: String? = urlComponents.url?.absoluteString + + return urlString } } diff --git a/godtools/App/Features/ToolSettings/Presentation/ToolSettings/ToolSettingsViewModel.swift b/godtools/App/Features/ToolSettings/Presentation/ToolSettings/ToolSettingsViewModel.swift index 05463a8177..976391fc77 100644 --- a/godtools/App/Features/ToolSettings/Presentation/ToolSettings/ToolSettingsViewModel.swift +++ b/godtools/App/Features/ToolSettings/Presentation/ToolSettings/ToolSettingsViewModel.swift @@ -23,6 +23,7 @@ class ToolSettingsViewModel: ObservableObject { private let setToolSettingsParallelLanguageUseCase: SetToolSettingsParallelLanguageUseCase private let getShareablesUseCase: GetShareablesUseCase private let getShareableImageUseCase: GetShareableImageUseCase + private let currentPageRenderer: AnyPublisher private var cancellables: Set = Set() @@ -47,7 +48,7 @@ class ToolSettingsViewModel: ObservableObject { @Published var shareablesTitle: String = "" @Published var shareables: [ShareableDomainModel] = Array() - init(flowDelegate: FlowDelegate, tool: ResourceModel, toolPrimaryLanguage: LanguageDomainModel, getCurrentAppLanguageUseCase: GetCurrentAppLanguageUseCase, viewToolSettingsUseCase: ViewToolSettingsUseCase, getToolSettingsPrimaryLanguageUseCase: GetToolSettingsPrimaryLanguageUseCase, setToolSettingsPrimaryLanguageUseCase: SetToolSettingsPrimaryLanguageUseCase, setToolSettingsParallelLanguageUseCase: SetToolSettingsParallelLanguageUseCase, getShareablesUseCase: GetShareablesUseCase, getShareableImageUseCase: GetShareableImageUseCase, trainingTipsEnabled: Bool) { + init(flowDelegate: FlowDelegate, tool: ResourceModel, getCurrentAppLanguageUseCase: GetCurrentAppLanguageUseCase, viewToolSettingsUseCase: ViewToolSettingsUseCase, getToolSettingsPrimaryLanguageUseCase: GetToolSettingsPrimaryLanguageUseCase, setToolSettingsPrimaryLanguageUseCase: SetToolSettingsPrimaryLanguageUseCase, setToolSettingsParallelLanguageUseCase: SetToolSettingsParallelLanguageUseCase, getShareablesUseCase: GetShareablesUseCase, getShareableImageUseCase: GetShareableImageUseCase, trainingTipsEnabled: Bool, currentPageRenderer: AnyPublisher) { self.flowDelegate = flowDelegate self.tool = tool @@ -59,6 +60,7 @@ class ToolSettingsViewModel: ObservableObject { self.getShareablesUseCase = getShareablesUseCase self.getShareableImageUseCase = getShareableImageUseCase self.trainingTipsEnabled = trainingTipsEnabled + self.currentPageRenderer = currentPageRenderer getCurrentAppLanguageUseCase .getLanguagePublisher() @@ -115,11 +117,14 @@ class ToolSettingsViewModel: ObservableObject { } .store(in: &cancellables) - $appLanguage - .eraseToAnyPublisher() - .flatMap({ (appLanguage: AppLanguageDomainModel) -> AnyPublisher<[ShareableDomainModel], Never> in + currentPageRenderer + .flatMap({ (pageRenderer: MobileContentPageRenderer) -> AnyPublisher in + return Just(pageRenderer.language) + .eraseToAnyPublisher() + }) + .flatMap({ (language: LanguageDomainModel) -> AnyPublisher<[ShareableDomainModel], Never> in return getShareablesUseCase - .getShareablesPublisher(toolId: tool.id, toolLanguage: appLanguage) + .getShareablesPublisher(toolId: tool.id, toolLanguage: language.localeIdentifier) .eraseToAnyPublisher() }) .receive(on: DispatchQueue.main) diff --git a/godtools/App/Flows/App/AppFlow.swift b/godtools/App/Flows/App/AppFlow.swift index 7673240e47..f6a78a3a8f 100644 --- a/godtools/App/Flows/App/AppFlow.swift +++ b/godtools/App/Flows/App/AppFlow.swift @@ -172,7 +172,7 @@ class AppFlow: NSObject, ToolNavigationFlow, Flow { let toolDetails = getToolDetails( tool: spotlightTool, - toolLanguage: toolFilterLanguage?.language?.localeIdentifier, + parallelLanguage: toolFilterLanguage?.language?.localeIdentifier, selectedLanguageIndex: 1 ) @@ -182,7 +182,7 @@ class AppFlow: NSObject, ToolNavigationFlow, Flow { let toolDetails = getToolDetails( tool: tool, - toolLanguage: toolFilterLanguage?.language?.localeIdentifier, + parallelLanguage: toolFilterLanguage?.language?.localeIdentifier, selectedLanguageIndex: 1 ) @@ -204,7 +204,7 @@ class AppFlow: NSObject, ToolNavigationFlow, Flow { let toolDetails = getToolDetails( tool: tool, - toolLanguage: nil, + parallelLanguage: nil, selectedLanguageIndex: nil ) @@ -229,7 +229,7 @@ class AppFlow: NSObject, ToolNavigationFlow, Flow { let toolDetails = getToolDetails( tool: tool, - toolLanguage: nil, + parallelLanguage: nil, selectedLanguageIndex: nil ) @@ -656,7 +656,7 @@ extension AppFlow { navigateToDashboard(startingTab: .favorites, animatePopToToolsMenu: false, animateDismissingPresentedView: false, didCompleteDismissingPresentedView: nil) - navigateToToolFromToolDeepLink(toolDeepLink: toolDeepLink, selectedLanguageIndex: nil, didCompleteToolNavigation: nil) + navigateToToolFromToolDeepLink(toolDeepLink: toolDeepLink, didCompleteToolNavigation: nil) case .articleAemUri(let aemUri): @@ -707,10 +707,13 @@ extension AppFlow { let languagesRepository: LanguagesRepository = appDiContainer.dataLayer.getLanguagesRepository() - var languageIds: [String] = Array() + let languageIds: Set if let appLanguageModel = languagesRepository.getLanguage(code: appLanguage) { - languageIds.append(appLanguageModel.id) + languageIds = [appLanguageModel.id] + } + else { + languageIds = Set() } navigateToTool(toolDataModelId: toolDataModelId, languageIds: languageIds, selectedLanguageIndex: nil, trainingTipsEnabled: trainingTipsEnabled) @@ -720,33 +723,32 @@ extension AppFlow { let languagesRepository: LanguagesRepository = appDiContainer.dataLayer.getLanguagesRepository() - var languageIds: [String] = Array() + var languageIds: Set = Set() if let languageModel = languagesRepository.getLanguage(code: primaryLanguage) { - languageIds.append(languageModel.id) + languageIds.insert(languageModel.id) } if let parallelLanguage = parallelLanguage, let languageModel = languagesRepository.getLanguage(code: parallelLanguage) { - languageIds.append(languageModel.id) + languageIds.insert(languageModel.id) } navigateToTool(toolDataModelId: toolDataModelId, languageIds: languageIds, selectedLanguageIndex: selectedLanguageIndex, trainingTipsEnabled: trainingTipsEnabled) } - private func navigateToTool(toolDataModelId: String, languageIds: [String], selectedLanguageIndex: Int?, trainingTipsEnabled: Bool) { - - var openToolInLanguages: [String] = Array() - - for languageId in languageIds { - if !openToolInLanguages.contains(languageId) { - openToolInLanguages.append(languageId) - } - } + private func navigateToTool(toolDataModelId: String, languageIds: Set, selectedLanguageIndex: Int?, trainingTipsEnabled: Bool) { let languagesRepository: LanguagesRepository = appDiContainer.dataLayer.getLanguagesRepository() - if openToolInLanguages.isEmpty, let englishLanguage = languagesRepository.getLanguage(code: LanguageCodeDomainModel.english.rawValue) { - openToolInLanguages.append(englishLanguage.id) + let openToolInLanguages: Set + + if languageIds.isEmpty, let englishLanguage = languagesRepository.getLanguage(code: LanguageCodeDomainModel.english.rawValue) { + + openToolInLanguages = [englishLanguage.id] + } + else { + + openToolInLanguages = languageIds } navigateToTool( @@ -955,13 +957,13 @@ extension AppFlow { extension AppFlow { - private func getToolDetails(tool: ToolDomainModel, toolLanguage: AppLanguageDomainModel?, selectedLanguageIndex: Int?) -> UIViewController { + private func getToolDetails(tool: ToolDomainModel, parallelLanguage: AppLanguageDomainModel?, selectedLanguageIndex: Int?) -> UIViewController { let viewModel = ToolDetailsViewModel( flowDelegate: self, tool: tool, primaryLanguage: appLanguage, - parallelLanguage: toolLanguage, + parallelLanguage: parallelLanguage, selectedLanguageIndex: selectedLanguageIndex, getCurrentAppLanguageUseCase: appDiContainer.feature.appLanguage.domainLayer.getCurrentAppLanguageUseCase(), getToolUseCase: appDiContainer.domainLayer.getToolUseCase(), @@ -1226,10 +1228,7 @@ extension AppFlow { } else if notification.name == UIApplication.didBecomeActiveNotification { - AppBackgroundState.shared.start( - getAllFavoritedToolsLatestTranslationFilesUseCase: appDiContainer.domainLayer.getAllFavoritedToolsLatestTranslationFilesUseCase(), - storeInitialFavoritedToolsUseCase: appDiContainer.domainLayer.getStoreInitialFavoritedToolsUseCase() - ) + AppBackgroundState.shared.start(appDiContainer: appDiContainer) ApplicationLayout.shared.configure(appLanguageFeatureDiContainer: appDiContainer.feature.appLanguage) diff --git a/godtools/App/Flows/ChooseAppLanguage/ChooseAppLanguageFlow.swift b/godtools/App/Flows/ChooseAppLanguage/ChooseAppLanguageFlow.swift index b3e98e37e1..ab36edb878 100644 --- a/godtools/App/Flows/ChooseAppLanguage/ChooseAppLanguageFlow.swift +++ b/godtools/App/Flows/ChooseAppLanguage/ChooseAppLanguageFlow.swift @@ -107,7 +107,8 @@ extension ChooseAppLanguageFlow { let viewModel = ConfirmAppLanguageViewModel( selectedLanguage: selectedLanguage, - getConfirmAppLanguageInterfaceStringsUseCase: appDiContainer.feature.appLanguage.domainLayer.getConfirmAppLanguageInterfaceStringsUseCase(), + getCurrentAppLanguageUseCase: appDiContainer.feature.appLanguage.domainLayer.getCurrentAppLanguageUseCase(), + viewConfirmAppLanguageUseCase: appDiContainer.feature.appLanguage.domainLayer.getViewConfirmAppLanguageUseCase(), flowDelegate: self ) diff --git a/godtools/App/Flows/ToolNavigation/ToolNavigationFlow.swift b/godtools/App/Flows/ToolNavigation/ToolNavigationFlow.swift index a92c11f18b..10f6e1afc0 100644 --- a/godtools/App/Flows/ToolNavigation/ToolNavigationFlow.swift +++ b/godtools/App/Flows/ToolNavigation/ToolNavigationFlow.swift @@ -20,7 +20,7 @@ protocol ToolNavigationFlow: Flow { extension ToolNavigationFlow { - func navigateToToolFromToolDeepLink(toolDeepLink: ToolDeepLink, selectedLanguageIndex: Int?, didCompleteToolNavigation: ((_ resource: ResourceModel) -> Void)?) { + func navigateToToolFromToolDeepLink(toolDeepLink: ToolDeepLink, didCompleteToolNavigation: ((_ resource: ResourceModel) -> Void)?) { let determineDeepLinkedToolTranslationsToDownload = DetermineDeepLinkedToolTranslationsToDownload( toolDeepLink: toolDeepLink, @@ -33,13 +33,13 @@ extension ToolNavigationFlow { navigateToToolAndDetermineToolTranslationsToDownload( determineToolTranslationsToDownload: determineDeepLinkedToolTranslationsToDownload, liveShareStream: toolDeepLink.liveShareStream, - selectedLanguageIndex: selectedLanguageIndex, + selectedLanguageIndex: toolDeepLink.selectedLanguageIndex, trainingTipsEnabled: false, initialPage: toolDeepLink.mobileContentPage ) } - func navigateToTool(resourceId: String, languageIds: [String], liveShareStream: String?, selectedLanguageIndex: Int?, trainingTipsEnabled: Bool, initialPage: MobileContentPagesPage?) { + func navigateToTool(resourceId: String, languageIds: Set, liveShareStream: String?, selectedLanguageIndex: Int?, trainingTipsEnabled: Bool, initialPage: MobileContentPagesPage?) { let determineToolTranslationsToDownload = DetermineToolTranslationsToDownload( resourceId: resourceId, diff --git a/godtools/App/Flows/ToolScreenShare/ToolScreenShareFlow.swift b/godtools/App/Flows/ToolScreenShare/ToolScreenShareFlow.swift index 11952eb636..30761d5121 100644 --- a/godtools/App/Flows/ToolScreenShare/ToolScreenShareFlow.swift +++ b/godtools/App/Flows/ToolScreenShare/ToolScreenShareFlow.swift @@ -121,9 +121,11 @@ class ToolScreenShareFlow: Flow { let tractRemoteShareURLBuilder: TractRemoteShareURLBuilder = appDiContainer.feature.toolScreenShare.dataLayer.getTractRemoteShareURLBuilder() let resource: ResourceModel = toolData.renderer.value.resource + let selectedLanguage: LanguageDomainModel = toolData.selectedLanguage + let page: Int = toolData.pageNumber guard let domainModel = shareToolScreenShareSessionDomainModel, - let remoteShareUrl = tractRemoteShareURLBuilder.buildRemoteShareURL(resource: resource, primaryLanguage: primaryLanguage, parallelLanguage: parallelLanguage, subscriberChannelId: channel.subscriberChannelId) else { + let remoteShareUrl = tractRemoteShareURLBuilder.buildRemoteShareURL(resource: resource, primaryLanguage: primaryLanguage, parallelLanguage: parallelLanguage, selectedLanguage: selectedLanguage, page: page, subscriberChannelId: channel.subscriberChannelId) else { let viewModel = AlertMessageViewModel( title: "Error", diff --git a/godtools/App/Flows/ToolSettings/ToolSettingsFlow.swift b/godtools/App/Flows/ToolSettings/ToolSettingsFlow.swift index cf320671fa..3676b7bcad 100644 --- a/godtools/App/Flows/ToolSettings/ToolSettingsFlow.swift +++ b/godtools/App/Flows/ToolSettings/ToolSettingsFlow.swift @@ -82,14 +82,14 @@ class ToolSettingsFlow: Flow { .receive(on: DispatchQueue.main) .sink { [weak self] (primaryLanguage: LanguageDomainModel?, parallelLanguage: LanguageDomainModel?) in - var languageIds: [String] = Array() + var languageIds: Set = Set() if let primaryLanguage = primaryLanguage { - languageIds.append(primaryLanguage.id) + languageIds.insert(primaryLanguage.id) } if let parallelLanguage = parallelLanguage { - languageIds.append(parallelLanguage.id) + languageIds.insert(parallelLanguage.id) } self?.setToolLanguages(languageIds: languageIds) @@ -241,7 +241,7 @@ class ToolSettingsFlow: Flow { } } - private func setToolLanguages(languageIds: [String]) { + private func setToolLanguages(languageIds: Set){ let determineToolTranslationsToDownload = DetermineToolTranslationsToDownload( resourceId: toolData.renderer.value.resource.id, @@ -290,7 +290,6 @@ extension ToolSettingsFlow { let viewModel = ToolSettingsViewModel( flowDelegate: self, tool: toolData.renderer.value.resource, - toolPrimaryLanguage: primaryLanguage, getCurrentAppLanguageUseCase: appDiContainer.feature.appLanguage.domainLayer.getCurrentAppLanguageUseCase(), viewToolSettingsUseCase: appDiContainer.feature.toolSettings.domainLayer.getViewToolSettingsUseCase(), getToolSettingsPrimaryLanguageUseCase: appDiContainer.feature.toolSettings.domainLayer.getToolSettingsPrimaryLanguageUseCase(), @@ -298,7 +297,8 @@ extension ToolSettingsFlow { setToolSettingsParallelLanguageUseCase: appDiContainer.feature.toolSettings.domainLayer.getSetToolSettingsParallelLanguageUseCase(), getShareablesUseCase: appDiContainer.feature.shareables.domainLayer.getShareablesUseCase(), getShareableImageUseCase: appDiContainer.feature.shareables.domainLayer.getShareableImageUseCase(), - trainingTipsEnabled: toolData.trainingTipsEnabled + trainingTipsEnabled: toolData.trainingTipsEnabled, + currentPageRenderer: toolData.currentPageRenderer.eraseToAnyPublisher() ) let toolSettingsView = ToolSettingsView(viewModel: viewModel) diff --git a/godtools/App/Flows/ToolSettings/ToolSettingsFlowToolData.swift b/godtools/App/Flows/ToolSettings/ToolSettingsFlowToolData.swift index ac26ba2d13..d1fed90fc1 100644 --- a/godtools/App/Flows/ToolSettings/ToolSettingsFlowToolData.swift +++ b/godtools/App/Flows/ToolSettings/ToolSettingsFlowToolData.swift @@ -14,14 +14,16 @@ class ToolSettingsFlowToolData { let renderer: CurrentValueSubject let currentPageRenderer: CurrentValueSubject let tractRemoteSharePublisher: TractRemoteSharePublisher + let selectedLanguage: LanguageDomainModel let pageNumber: Int let trainingTipsEnabled: Bool - required init(renderer: CurrentValueSubject, currentPageRenderer: CurrentValueSubject, tractRemoteSharePublisher: TractRemoteSharePublisher, pageNumber: Int, trainingTipsEnabled: Bool) { + init(renderer: CurrentValueSubject, currentPageRenderer: CurrentValueSubject, tractRemoteSharePublisher: TractRemoteSharePublisher, selectedLanguage: LanguageDomainModel, pageNumber: Int, trainingTipsEnabled: Bool) { self.renderer = renderer self.currentPageRenderer = currentPageRenderer self.tractRemoteSharePublisher = tractRemoteSharePublisher + self.selectedLanguage = selectedLanguage self.pageNumber = pageNumber self.trainingTipsEnabled = trainingTipsEnabled } diff --git a/godtools/App/Services/Renderer/Navigation/MobileContentRendererNavigation.swift b/godtools/App/Services/Renderer/Navigation/MobileContentRendererNavigation.swift index e275b74b17..cb0e5ecc5a 100644 --- a/godtools/App/Services/Renderer/Navigation/MobileContentRendererNavigation.swift +++ b/godtools/App/Services/Renderer/Navigation/MobileContentRendererNavigation.swift @@ -61,7 +61,7 @@ class MobileContentRendererNavigation { case .tool(let toolDeepLink): - parentFlow?.navigateToToolFromToolDeepLink(toolDeepLink: toolDeepLink, selectedLanguageIndex: nil, didCompleteToolNavigation: nil) + parentFlow?.navigateToToolFromToolDeepLink(toolDeepLink: toolDeepLink, didCompleteToolNavigation: nil) } } else { diff --git a/godtools/App/Services/Renderer/Views/MobileContent/Views/Pages/MobileContentPagesViewModel.swift b/godtools/App/Services/Renderer/Views/MobileContent/Views/Pages/MobileContentPagesViewModel.swift index f7eb2b4c93..39acbc56b0 100644 --- a/godtools/App/Services/Renderer/Views/MobileContent/Views/Pages/MobileContentPagesViewModel.swift +++ b/godtools/App/Services/Renderer/Views/MobileContent/Views/Pages/MobileContentPagesViewModel.swift @@ -93,6 +93,15 @@ class MobileContentPagesViewModel: NSObject, ObservableObject { return renderer.value.resource } + func getSelectedLanguage() -> LanguageDomainModel? { + + guard selectedLanguageIndex >= 0 && selectedLanguageIndex < languages.count else { + return nil + } + + return languages[selectedLanguageIndex] + } + func viewDidFinishLayout(window: UIViewController, safeArea: UIEdgeInsets) { self.window = window diff --git a/godtools/App/Share/Application/FontLibrary/FontLibrary.swift b/godtools/App/Share/Application/FontLibrary/FontLibrary.swift index 97205f71cd..56019656da 100644 --- a/godtools/App/Share/Application/FontLibrary/FontLibrary.swift +++ b/godtools/App/Share/Application/FontLibrary/FontLibrary.swift @@ -16,7 +16,6 @@ enum FontLibrary: String { case notoSansEthiopic = "NotoSansEthiopic" case notoSansMyanmarBold = "NotoSansMyanmarUI-CondensedBold" case notoSansMyanmar = "NotoSansMyanmarUI-Condensed" - case robotoMedium = "Roboto-Medium" case sfProDisplayLight = "SFProDisplay-Light" case sfProDisplayRegular = "SFProDisplay-Regular" case sfProTextBold = "SFProText-Bold" diff --git a/godtools/App/Share/Data/DeepLinkingService/ParsedDeepLink/ToolDeepLink.swift b/godtools/App/Share/Data/DeepLinkingService/ParsedDeepLink/ToolDeepLink.swift index 9fb9d1493c..6d70081b56 100644 --- a/godtools/App/Share/Data/DeepLinkingService/ParsedDeepLink/ToolDeepLink.swift +++ b/godtools/App/Share/Data/DeepLinkingService/ParsedDeepLink/ToolDeepLink.swift @@ -16,4 +16,5 @@ struct ToolDeepLink: Equatable { let liveShareStream: String? let page: Int? let pageId: String? + let selectedLanguageIndex: Int? } diff --git a/godtools/App/Share/Data/DeepLinkingService/Parsers/AppsFlyerDeepLinkValue/AppsFlyerDeepLinkValueComponentsParser.swift b/godtools/App/Share/Data/DeepLinkingService/Parsers/AppsFlyerDeepLinkValue/AppsFlyerDeepLinkValueComponentsParser.swift index 67f3200a2a..a5289002df 100644 --- a/godtools/App/Share/Data/DeepLinkingService/Parsers/AppsFlyerDeepLinkValue/AppsFlyerDeepLinkValueComponentsParser.swift +++ b/godtools/App/Share/Data/DeepLinkingService/Parsers/AppsFlyerDeepLinkValue/AppsFlyerDeepLinkValueComponentsParser.swift @@ -75,7 +75,8 @@ class AppsFlyerDeepLinkValueComponentsParser { parallelLanguageCodes: [], liveShareStream: nil, page: pageNumber, - pageId: pageId + pageId: pageId, + selectedLanguageIndex: nil ) ) diff --git a/godtools/App/Share/Data/DeepLinkingService/Parsers/GodtoolsApp/Lessons/GodToolsAppLessonsPathDeepLinkParser.swift b/godtools/App/Share/Data/DeepLinkingService/Parsers/GodtoolsApp/Lessons/GodToolsAppLessonsPathDeepLinkParser.swift index 4ab077d4b1..3a069e5ef2 100644 --- a/godtools/App/Share/Data/DeepLinkingService/Parsers/GodtoolsApp/Lessons/GodToolsAppLessonsPathDeepLinkParser.swift +++ b/godtools/App/Share/Data/DeepLinkingService/Parsers/GodtoolsApp/Lessons/GodToolsAppLessonsPathDeepLinkParser.swift @@ -43,7 +43,8 @@ class GodToolsAppLessonsPathDeepLinkParser: DeepLinkUrlParserType { parallelLanguageCodes: [], liveShareStream: nil, page: nil, - pageId: nil + pageId: nil, + selectedLanguageIndex: nil ) return .tool(toolDeepLink: toolDeepLink) diff --git a/godtools/App/Share/Data/DeepLinkingService/Parsers/KnowGod/KnowGodDeepLinkParser.swift b/godtools/App/Share/Data/DeepLinkingService/Parsers/KnowGod/KnowGodDeepLinkParser.swift index 78fb6e17ad..ac01ebff91 100644 --- a/godtools/App/Share/Data/DeepLinkingService/Parsers/KnowGod/KnowGodDeepLinkParser.swift +++ b/godtools/App/Share/Data/DeepLinkingService/Parsers/KnowGod/KnowGodDeepLinkParser.swift @@ -47,7 +47,8 @@ class KnowGodDeepLinkParser: DeepLinkUrlParserType { parallelLanguageCodes: [], liveShareStream: nil, page: nil, - pageId: nil + pageId: nil, + selectedLanguageIndex: nil ) return .tool(toolDeepLink: toolDeepLink) @@ -57,29 +58,40 @@ class KnowGodDeepLinkParser: DeepLinkUrlParserType { let knowGodQueryParameters: KnowGodTractDeepLinkQueryParameters? = JsonServices().decodeJsonObject(jsonObject: queryParameters) - var abbreviationFromUrlPath: String? - var primaryLanguageCodeFromUrlPath: String? - var pageFromUrlPath: Int? + let primaryLanguageCodeFromUrlPath: String? = pathComponents[safe: 0] + let abbreviationFromUrlPath: String? = pathComponents[safe: 1] + let pageFromUrlPath: Int? - if pathComponents.count > 1 { - abbreviationFromUrlPath = pathComponents[1] + if let pageStringFromUrlPath = pathComponents[safe: 2] { + pageFromUrlPath = Int(pageStringFromUrlPath) } - - if pathComponents.count > 0 { - primaryLanguageCodeFromUrlPath = pathComponents[0] - } - - if pathComponents.count > 2, let pageIntegerValue = Int(pathComponents[2]) { - pageFromUrlPath = pageIntegerValue + else { + pageFromUrlPath = nil } - var primaryLanguageCodesFromUrlQuery: [String] = knowGodQueryParameters?.getPrimaryLanguageCodes() ?? Array() + var primaryLanguageCodes: [String] = knowGodQueryParameters?.getPrimaryLanguageCodes() ?? Array() + let parallelLanguageCodes: [String] = knowGodQueryParameters?.getParallelLanguageCodes() ?? Array() + let selectedLanguageIndex: Int? - if let primaryLanguageCodeFromUrlPath = primaryLanguageCodeFromUrlPath, !primaryLanguageCodesFromUrlQuery.contains(primaryLanguageCodeFromUrlPath) { - primaryLanguageCodesFromUrlQuery.insert(primaryLanguageCodeFromUrlPath, at: 0) + if primaryLanguageCodes.isEmpty, let primaryLanguageCodeFromUrlPath = primaryLanguageCodeFromUrlPath, !parallelLanguageCodes.contains(primaryLanguageCodeFromUrlPath) { + primaryLanguageCodes.append(primaryLanguageCodeFromUrlPath) } - let parallelLanguageCodesFromUrlQuery: [String] = knowGodQueryParameters?.getParallelLanguageCodes() ?? Array() + if let primaryLanguageCodeFromUrlPath = primaryLanguageCodeFromUrlPath { + + if primaryLanguageCodes.contains(primaryLanguageCodeFromUrlPath) { + selectedLanguageIndex = 0 + } + else if parallelLanguageCodes.contains(primaryLanguageCodeFromUrlPath) { + selectedLanguageIndex = 1 + } + else { + selectedLanguageIndex = nil + } + } + else { + selectedLanguageIndex = nil + } guard let resourceAbbreviation = abbreviationFromUrlPath, !resourceAbbreviation.isEmpty else { return nil @@ -87,11 +99,12 @@ class KnowGodDeepLinkParser: DeepLinkUrlParserType { let toolDeepLink = ToolDeepLink( resourceAbbreviation: resourceAbbreviation, - primaryLanguageCodes: primaryLanguageCodesFromUrlQuery, - parallelLanguageCodes: parallelLanguageCodesFromUrlQuery, + primaryLanguageCodes: primaryLanguageCodes, + parallelLanguageCodes: parallelLanguageCodes, liveShareStream: knowGodQueryParameters?.liveShareStream, page: pageFromUrlPath, - pageId: nil + pageId: nil, + selectedLanguageIndex: selectedLanguageIndex ) return .tool(toolDeepLink: toolDeepLink) diff --git a/godtools/App/Share/Data/DeepLinkingService/Parsers/Legacy/LegacyAppsFlyerDeepLinkValueParser.swift b/godtools/App/Share/Data/DeepLinkingService/Parsers/Legacy/LegacyAppsFlyerDeepLinkValueParser.swift index 827010b2ce..b8887df9ab 100644 --- a/godtools/App/Share/Data/DeepLinkingService/Parsers/Legacy/LegacyAppsFlyerDeepLinkValueParser.swift +++ b/godtools/App/Share/Data/DeepLinkingService/Parsers/Legacy/LegacyAppsFlyerDeepLinkValueParser.swift @@ -42,7 +42,8 @@ class LegacyAppsFlyerDeepLinkValueParser: DeepLinkAppsFlyerParserType { parallelLanguageCodes: [], liveShareStream: nil, page: nil, - pageId: nil + pageId: nil, + selectedLanguageIndex: nil ) return .tool(toolDeepLink: toolDeepLink) diff --git a/godtools/App/Share/Data/DeepLinkingService/Parsers/ToolPath/ToolPathDeepLinkParser.swift b/godtools/App/Share/Data/DeepLinkingService/Parsers/ToolPath/ToolPathDeepLinkParser.swift index b7f1488ce1..ae50ed5889 100644 --- a/godtools/App/Share/Data/DeepLinkingService/Parsers/ToolPath/ToolPathDeepLinkParser.swift +++ b/godtools/App/Share/Data/DeepLinkingService/Parsers/ToolPath/ToolPathDeepLinkParser.swift @@ -76,7 +76,8 @@ class ToolPathDeepLinkParser: DeepLinkUrlParserType { parallelLanguageCodes: [], liveShareStream: nil, page: pageNumber, - pageId: pageId + pageId: pageId, + selectedLanguageIndex: nil ) ) } diff --git a/godtools/App/Share/Domain/UseCases/GetAllFavoritedToolsLatestTranslationFilesUseCase/GetAllFavoritedToolsLatestTranslationFilesUseCase.swift b/godtools/App/Share/Domain/UseCases/GetAllFavoritedToolsLatestTranslationFilesUseCase/GetAllFavoritedToolsLatestTranslationFilesUseCase.swift deleted file mode 100644 index 8a7216baa1..0000000000 --- a/godtools/App/Share/Domain/UseCases/GetAllFavoritedToolsLatestTranslationFilesUseCase/GetAllFavoritedToolsLatestTranslationFilesUseCase.swift +++ /dev/null @@ -1,83 +0,0 @@ -// -// GetAllFavoritedToolsLatestTranslationFilesUseCase.swift -// godtools -// -// Created by Levi Eggert on 8/3/22. -// Copyright © 2022 Cru. All rights reserved. -// - -import Foundation -import Combine - -class GetAllFavoritedToolsLatestTranslationFilesUseCase { - - private let getLanguageUseCase: GetLanguageUseCase - private let getSettingsPrimaryLanguageUseCase: GetSettingsPrimaryLanguageUseCase - private let favoritedResourcesRepository: FavoritedResourcesRepository - private let resourcesRepository: ResourcesRepository - private let translationsRepository: TranslationsRepository - - private var cancellables = Set() - private var downloadLatestTranslationsCancellable: AnyCancellable? - - init(getLanguageUseCase: GetLanguageUseCase, getSettingsPrimaryLanguageUseCase: GetSettingsPrimaryLanguageUseCase, favoritedResourcesRepository: FavoritedResourcesRepository, resourcesRepository: ResourcesRepository, translationsRepository: TranslationsRepository) { - - self.getLanguageUseCase = getLanguageUseCase - self.getSettingsPrimaryLanguageUseCase = getSettingsPrimaryLanguageUseCase - self.favoritedResourcesRepository = favoritedResourcesRepository - self.resourcesRepository = resourcesRepository - self.translationsRepository = translationsRepository - - Publishers.CombineLatest3( - resourcesRepository.getResourcesChangedPublisher(), - favoritedResourcesRepository.getFavoritedResourcesChangedPublisher(), - getSettingsPrimaryLanguageUseCase.getPrimaryLanguagePublisher() - ) - .sink { [weak self] (resourcesChanged: Void, _, primaryLanguage: LanguageDomainModel?) in - - let favoritedTools = favoritedResourcesRepository.getFavoritedResourcesSortedByCreatedAt(ascendingOrder: false) - - self?.downloadLatestTranslationsForAllFavoritedTools( - favoritedTools: favoritedTools, - primaryLanguage: primaryLanguage - ) - } - .store(in: &cancellables) - } - - private func downloadLatestTranslationsForAllFavoritedTools(favoritedTools: [FavoritedResourceDataModel], primaryLanguage: LanguageDomainModel?) { - - downloadLatestTranslationsCancellable?.cancel() - - let englishLanguage: LanguageDomainModel? = getLanguageUseCase.getLanguage(languageCode: LanguageCodeDomainModel.english.value) - - let languages: [LanguageDomainModel] = [englishLanguage, primaryLanguage].compactMap({ - return $0 - }) - - guard !favoritedTools.isEmpty && !languages.isEmpty else { - return - } - - var translations: [TranslationModel] = Array() - - for favoritedTool in favoritedTools { - - for language in languages { - - guard let translation = translationsRepository.getLatestTranslation(resourceId: favoritedTool.id, languageId: language.dataModelId) else { - continue - } - - translations.append(translation) - } - } - - downloadLatestTranslationsCancellable = translationsRepository.downloadAndCacheTranslationsFiles(translations: translations) - .sink { completed in - print(completed) - } receiveValue: { (files: [TranslationFilesDataModel]) in - - } - } -} diff --git a/godtools/App/Share/Domain/UseCases/GetToolTranslationsFilesUseCase/DetermineToolTranslationsToDownload/DetermineToolTranslationsToDownload.swift b/godtools/App/Share/Domain/UseCases/GetToolTranslationsFilesUseCase/DetermineToolTranslationsToDownload/DetermineToolTranslationsToDownload.swift index 1d08fbc858..0d45e4d6a4 100644 --- a/godtools/App/Share/Domain/UseCases/GetToolTranslationsFilesUseCase/DetermineToolTranslationsToDownload/DetermineToolTranslationsToDownload.swift +++ b/godtools/App/Share/Domain/UseCases/GetToolTranslationsFilesUseCase/DetermineToolTranslationsToDownload/DetermineToolTranslationsToDownload.swift @@ -11,11 +11,11 @@ import Foundation class DetermineToolTranslationsToDownload: DetermineToolTranslationsToDownloadType { private let resourceId: String - private let languageIds: [String] + private let languageIds: Set private let resourcesRepository: ResourcesRepository private let translationsRepository: TranslationsRepository - required init(resourceId: String, languageIds: [String], resourcesRepository: ResourcesRepository, translationsRepository: TranslationsRepository) { + init(resourceId: String, languageIds: Set, resourcesRepository: ResourcesRepository, translationsRepository: TranslationsRepository) { self.resourceId = resourceId self.languageIds = languageIds diff --git a/godtools/Assets/Fonts/Roboto-Medium.ttf b/godtools/Assets/Fonts/Roboto-Medium.ttf deleted file mode 100644 index ac0f908b9c..0000000000 Binary files a/godtools/Assets/Fonts/Roboto-Medium.ttf and /dev/null differ diff --git a/godtools/Info.plist b/godtools/Info.plist index 2ee0cf9317..ed5be8d1bd 100644 --- a/godtools/Info.plist +++ b/godtools/Info.plist @@ -122,7 +122,6 @@ SF-Pro-Text-Light.otf SF-Pro-Text-Regular.otf SF-Pro-Text-Semibold.otf - Roboto-Medium.ttf UIBackgroundModes diff --git a/godtoolsTests/App/Share/Data/DeepLinkingService/DeepLinkingServiceTests.swift b/godtoolsTests/App/Share/Data/DeepLinkingService/DeepLinkingServiceTests.swift index 7bb3eb6608..e704890914 100644 --- a/godtoolsTests/App/Share/Data/DeepLinkingService/DeepLinkingServiceTests.swift +++ b/godtoolsTests/App/Share/Data/DeepLinkingService/DeepLinkingServiceTests.swift @@ -140,7 +140,8 @@ class DeepLinkingServiceTests: XCTestCase { parallelLanguageCodes: [], liveShareStream: nil, page: nil, - pageId: nil + pageId: nil, + selectedLanguageIndex: nil ) ) @@ -158,7 +159,8 @@ class DeepLinkingServiceTests: XCTestCase { parallelLanguageCodes: [], liveShareStream: nil, page: nil, - pageId: nil + pageId: nil, + selectedLanguageIndex: nil ) ) @@ -176,7 +178,8 @@ class DeepLinkingServiceTests: XCTestCase { parallelLanguageCodes: [], liveShareStream: nil, page: nil, - pageId: nil + pageId: nil, + selectedLanguageIndex: nil ) ) @@ -194,7 +197,8 @@ class DeepLinkingServiceTests: XCTestCase { parallelLanguageCodes: [], liveShareStream: nil, page: nil, - pageId: nil + pageId: nil, + selectedLanguageIndex: nil ) ) @@ -212,7 +216,8 @@ class DeepLinkingServiceTests: XCTestCase { parallelLanguageCodes: [], liveShareStream: nil, page: nil, - pageId: nil + pageId: nil, + selectedLanguageIndex: nil ) ) @@ -230,7 +235,8 @@ class DeepLinkingServiceTests: XCTestCase { parallelLanguageCodes: [], liveShareStream: nil, page: nil, - pageId: nil + pageId: nil, + selectedLanguageIndex: nil ) ) @@ -248,7 +254,8 @@ class DeepLinkingServiceTests: XCTestCase { parallelLanguageCodes: [], liveShareStream: nil, page: 5, - pageId: nil + pageId: nil, + selectedLanguageIndex: nil ) ) @@ -275,7 +282,8 @@ class DeepLinkingServiceTests: XCTestCase { parallelLanguageCodes: [], liveShareStream: nil, page: nil, - pageId: nil + pageId: nil, + selectedLanguageIndex: nil ) ) @@ -286,6 +294,8 @@ class DeepLinkingServiceTests: XCTestCase { func testTractTeachMeToShareEnglishPage4FromKnowGod() { + let primaryLanguageIndex: Int = 0 + let tract: ParsedDeepLinkType = .tool( toolDeepLink: ToolDeepLink( resourceAbbreviation: "teachmetoshare", @@ -293,7 +303,8 @@ class DeepLinkingServiceTests: XCTestCase { parallelLanguageCodes: [], liveShareStream: nil, page: 4, - pageId: nil + pageId: nil, + selectedLanguageIndex: primaryLanguageIndex ) ) @@ -304,6 +315,8 @@ class DeepLinkingServiceTests: XCTestCase { func testTractTeachMeToShareEnglishWithLiveStreamFromKnowGod() { + let primaryLanguageIndex: Int = 0 + let tract: ParsedDeepLinkType = .tool( toolDeepLink: ToolDeepLink( resourceAbbreviation: "teachmetoshare", @@ -311,7 +324,8 @@ class DeepLinkingServiceTests: XCTestCase { parallelLanguageCodes: [], liveShareStream: "acd9bee66b6057476cee-1612666248", page: nil, - pageId: nil + pageId: nil, + selectedLanguageIndex: primaryLanguageIndex ) ) @@ -322,6 +336,8 @@ class DeepLinkingServiceTests: XCTestCase { func testTractTeachMeToShareSpanishAndRussianFromKnowGod() { + let primaryLanguageIndex: Int = 0 + let tract: ParsedDeepLinkType = .tool( toolDeepLink: ToolDeepLink( resourceAbbreviation: "teachmetoshare", @@ -329,7 +345,8 @@ class DeepLinkingServiceTests: XCTestCase { parallelLanguageCodes: ["ru"], liveShareStream: nil, page: nil, - pageId: nil + pageId: nil, + selectedLanguageIndex: primaryLanguageIndex ) ) @@ -347,7 +364,8 @@ class DeepLinkingServiceTests: XCTestCase { parallelLanguageCodes: [], liveShareStream: nil, page: nil, - pageId: nil + pageId: nil, + selectedLanguageIndex: nil ) )