From 745294bbb1f8c858d15c70af4121c1cac39d083e Mon Sep 17 00:00:00 2001 From: Mustafa Merza <mustafa.merza95@gmail.com> Date: Wed, 17 Jul 2024 15:01:37 +0300 Subject: [PATCH] - Added use cases to handle app's language. --- MiniScanner.xcodeproj/project.pbxproj | 92 +++++++++++++++++++ .../Common/DI/DependencyManager.swift | 10 ++ .../Data/DataSources/SettingsDataSource.swift | 51 ++++++++++ .../Common/Data/Model/SupportedLanguage.swift | 63 +++++++++++++ .../Repositories/SettingsRepository.swift | 41 +++++++++ .../SettingsRepositoryProtocol.swift | 16 ++++ .../Language/ChangeLanguageUseCase.swift | 22 +++++ .../Language/GetLanguageUseCase.swift | 22 +++++ .../Language/GetLanguagesUseCase.swift | 22 +++++ 9 files changed, 339 insertions(+) create mode 100644 MiniScanner/Features/Common/Data/DataSources/SettingsDataSource.swift create mode 100644 MiniScanner/Features/Common/Data/Model/SupportedLanguage.swift create mode 100644 MiniScanner/Features/Common/Data/Repositories/SettingsRepository.swift create mode 100644 MiniScanner/Features/Common/Domain/Repositories/SettingsRepositoryProtocol.swift create mode 100644 MiniScanner/Features/Common/Domain/UseCases/Language/ChangeLanguageUseCase.swift create mode 100644 MiniScanner/Features/Common/Domain/UseCases/Language/GetLanguageUseCase.swift create mode 100644 MiniScanner/Features/Common/Domain/UseCases/Language/GetLanguagesUseCase.swift diff --git a/MiniScanner.xcodeproj/project.pbxproj b/MiniScanner.xcodeproj/project.pbxproj index a0ce321..df35133 100644 --- a/MiniScanner.xcodeproj/project.pbxproj +++ b/MiniScanner.xcodeproj/project.pbxproj @@ -179,6 +179,13 @@ 672C468F2C47CB2000497EF0 /* UserDefaultsManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 672C468E2C47CB2000497EF0 /* UserDefaultsManager.swift */; }; 672C46912C47CB5D00497EF0 /* UserDefaultsKeys.swift in Sources */ = {isa = PBXBuildFile; fileRef = 672C46902C47CB5D00497EF0 /* UserDefaultsKeys.swift */; }; 672C46B32C47E8D700497EF0 /* DependencyManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 672C46A52C47E8D700497EF0 /* DependencyManager.swift */; }; + 672C46C52C47E98A00497EF0 /* SettingsRepositoryProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 672C46B72C47E98900497EF0 /* SettingsRepositoryProtocol.swift */; }; + 672C46C62C47E98A00497EF0 /* ChangeLanguageUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 672C46B92C47E98900497EF0 /* ChangeLanguageUseCase.swift */; }; + 672C46C72C47E98A00497EF0 /* GetLanguagesUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 672C46BA2C47E98900497EF0 /* GetLanguagesUseCase.swift */; }; + 672C46C82C47E98A00497EF0 /* SettingsDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 672C46BE2C47E98A00497EF0 /* SettingsDataSource.swift */; }; + 672C46C92C47E98A00497EF0 /* SupportedLanguage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 672C46C02C47E98A00497EF0 /* SupportedLanguage.swift */; }; + 672C46CA2C47E98A00497EF0 /* SettingsRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 672C46C22C47E98A00497EF0 /* SettingsRepository.swift */; }; + 672C46CC2C47E9AB00497EF0 /* GetLanguageUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 672C46CB2C47E9AB00497EF0 /* GetLanguageUseCase.swift */; }; B827E5196CC419E773B843E1 /* Pods_MiniScanner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E9A37DC9F9A8E3AF632DFB98 /* Pods_MiniScanner.framework */; }; EC0CF1FE254D8BBF00888722 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC0CF1FD254D8BBF00888722 /* AppDelegate.swift */; }; EC0CF200254D8BBF00888722 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC0CF1FF254D8BBF00888722 /* SceneDelegate.swift */; }; @@ -408,6 +415,13 @@ 672C468E2C47CB2000497EF0 /* UserDefaultsManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDefaultsManager.swift; sourceTree = "<group>"; }; 672C46902C47CB5D00497EF0 /* UserDefaultsKeys.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDefaultsKeys.swift; sourceTree = "<group>"; }; 672C46A52C47E8D700497EF0 /* DependencyManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DependencyManager.swift; sourceTree = "<group>"; }; + 672C46B72C47E98900497EF0 /* SettingsRepositoryProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsRepositoryProtocol.swift; sourceTree = "<group>"; }; + 672C46B92C47E98900497EF0 /* ChangeLanguageUseCase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChangeLanguageUseCase.swift; sourceTree = "<group>"; }; + 672C46BA2C47E98900497EF0 /* GetLanguagesUseCase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GetLanguagesUseCase.swift; sourceTree = "<group>"; }; + 672C46BE2C47E98A00497EF0 /* SettingsDataSource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsDataSource.swift; sourceTree = "<group>"; }; + 672C46C02C47E98A00497EF0 /* SupportedLanguage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SupportedLanguage.swift; sourceTree = "<group>"; }; + 672C46C22C47E98A00497EF0 /* SettingsRepository.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsRepository.swift; sourceTree = "<group>"; }; + 672C46CB2C47E9AB00497EF0 /* GetLanguageUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GetLanguageUseCase.swift; sourceTree = "<group>"; }; E8AF4FB39674DF589D719DCF /* Pods-MiniScanner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MiniScanner.release.xcconfig"; path = "Target Support Files/Pods-MiniScanner/Pods-MiniScanner.release.xcconfig"; sourceTree = "<group>"; }; E9A37DC9F9A8E3AF632DFB98 /* Pods_MiniScanner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_MiniScanner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; EC0CF1FA254D8BBF00888722 /* MiniScanner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MiniScanner.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -968,6 +982,8 @@ isa = PBXGroup; children = ( 672C46A62C47E8D700497EF0 /* DI */, + 672C46C42C47E98A00497EF0 /* Data */, + 672C46BD2C47E98900497EF0 /* Domain */, ); path = Common; sourceTree = "<group>"; @@ -980,6 +996,75 @@ path = Features; sourceTree = "<group>"; }; + 672C46B82C47E98900497EF0 /* Repositories */ = { + isa = PBXGroup; + children = ( + 672C46B72C47E98900497EF0 /* SettingsRepositoryProtocol.swift */, + ); + path = Repositories; + sourceTree = "<group>"; + }; + 672C46BB2C47E98900497EF0 /* Language */ = { + isa = PBXGroup; + children = ( + 672C46B92C47E98900497EF0 /* ChangeLanguageUseCase.swift */, + 672C46BA2C47E98900497EF0 /* GetLanguagesUseCase.swift */, + 672C46CB2C47E9AB00497EF0 /* GetLanguageUseCase.swift */, + ); + path = Language; + sourceTree = "<group>"; + }; + 672C46BC2C47E98900497EF0 /* UseCases */ = { + isa = PBXGroup; + children = ( + 672C46BB2C47E98900497EF0 /* Language */, + ); + path = UseCases; + sourceTree = "<group>"; + }; + 672C46BD2C47E98900497EF0 /* Domain */ = { + isa = PBXGroup; + children = ( + 672C46B82C47E98900497EF0 /* Repositories */, + 672C46BC2C47E98900497EF0 /* UseCases */, + ); + path = Domain; + sourceTree = "<group>"; + }; + 672C46BF2C47E98A00497EF0 /* DataSources */ = { + isa = PBXGroup; + children = ( + 672C46BE2C47E98A00497EF0 /* SettingsDataSource.swift */, + ); + path = DataSources; + sourceTree = "<group>"; + }; + 672C46C12C47E98A00497EF0 /* Model */ = { + isa = PBXGroup; + children = ( + 672C46C02C47E98A00497EF0 /* SupportedLanguage.swift */, + ); + path = Model; + sourceTree = "<group>"; + }; + 672C46C32C47E98A00497EF0 /* Repositories */ = { + isa = PBXGroup; + children = ( + 672C46C22C47E98A00497EF0 /* SettingsRepository.swift */, + ); + path = Repositories; + sourceTree = "<group>"; + }; + 672C46C42C47E98A00497EF0 /* Data */ = { + isa = PBXGroup; + children = ( + 672C46C12C47E98A00497EF0 /* Model */, + 672C46BF2C47E98A00497EF0 /* DataSources */, + 672C46C32C47E98A00497EF0 /* Repositories */, + ); + path = Data; + sourceTree = "<group>"; + }; 98E49D3F46C8E62718825860 /* Pods */ = { isa = PBXGroup; children = ( @@ -1350,6 +1435,7 @@ 53014FA42C11A8E80071CE39 /* EditScanViewController.swift in Sources */, 53E7D33C2C1B00880025A1D3 /* FSPagerCollectionView.swift in Sources */, EC8A9B1A254DCE3E00F9AF99 /* UIImage+Extensions.swift in Sources */, + 672C46CC2C47E9AB00497EF0 /* GetLanguageUseCase.swift in Sources */, 53014FB72C11A8E80071CE39 /* CaptureDevice.swift in Sources */, 5399968D2C27130000671340 /* ConstraintDirectionalInsetTarget.swift in Sources */, 53014F8F2C11A8E80071CE39 /* RectangleFeaturesFunnel.swift in Sources */, @@ -1386,6 +1472,8 @@ 672C468F2C47CB2000497EF0 /* UserDefaultsManager.swift in Sources */, 672C46642C47C74800497EF0 /* Provide.swift in Sources */, 53CD5F562C1503150010424B /* BMViewController.swift in Sources */, + 672C46C92C47E98A00497EF0 /* SupportedLanguage.swift in Sources */, + 672C46C72C47E98A00497EF0 /* GetLanguagesUseCase.swift in Sources */, 539996822C27130000671340 /* ConstraintDescription.swift in Sources */, EC702546254E1E9E00BE1958 /* WalkthroughModel.swift in Sources */, 53D9D1C22C1AF521004D1C1C /* StickerView.swift in Sources */, @@ -1398,6 +1486,7 @@ 5399969C2C27130000671340 /* ConstraintItem.swift in Sources */, 53014F982C11A8E80071CE39 /* URL+Utils.swift in Sources */, EC8A9B00254DBFC700F9AF99 /* UserDefaults+Extensions.swift in Sources */, + 672C46C82C47E98A00497EF0 /* SettingsDataSource.swift in Sources */, 53CD5F5C2C1505A20010424B /* Globals.swift in Sources */, EC8A9B03254DC08800F9AF99 /* NSNotification+Extensions.swift in Sources */, 539996492C26E86700671340 /* CDCameraOverlayView.m in Sources */, @@ -1422,6 +1511,7 @@ 539996852C27130000671340 /* ConstraintViewDSL.swift in Sources */, EC702542254E1E7500BE1958 /* ClassicWalkthroughViewController.swift in Sources */, 539996882C27130000671340 /* ConstraintMakerFinalizable.swift in Sources */, + 672C46C52C47E98A00497EF0 /* SettingsRepositoryProtocol.swift in Sources */, 53EDED9D2C183CDF00DB8DF9 /* BannerView.swift in Sources */, 5399969A2C27130000671340 /* ConstraintLayoutGuideDSL.swift in Sources */, 53014F922C11A8E80071CE39 /* ScannedItemRenderer.swift in Sources */, @@ -1430,6 +1520,7 @@ 53014FBA2C11A8E80071CE39 /* CaptureSession+Flash.swift in Sources */, 539996572C27124B00671340 /* FontChooserContainerView.swift in Sources */, 53014F952C11A8E80071CE39 /* FocusRectangleView.swift in Sources */, + 672C46C62C47E98A00497EF0 /* ChangeLanguageUseCase.swift in Sources */, 53014F9E2C11A8E80071CE39 /* UIImage+Orientation.swift in Sources */, 53014FB82C11A8E80071CE39 /* Transformable.swift in Sources */, 53014FA22C11A8E80071CE39 /* ScannedPageViewController.swift in Sources */, @@ -1444,6 +1535,7 @@ 5399964A2C26E86700671340 /* CropperConstantValues.m in Sources */, 53014F9F2C11A8E80071CE39 /* UIImage+Utils.swift in Sources */, 53CD5F582C1504CF0010424B /* UIButton+Extensions.swift in Sources */, + 672C46CA2C47E98A00497EF0 /* SettingsRepository.swift in Sources */, 539D1C8B2C16E97F009DB24A /* ShareSheetViewController.swift in Sources */, 539996A12C27130000671340 /* ConstraintLayoutGuide+Extensions.swift in Sources */, 672C464A2C47BD8800497EF0 /* String+StringKeys.swift in Sources */, diff --git a/MiniScanner/Features/Common/DI/DependencyManager.swift b/MiniScanner/Features/Common/DI/DependencyManager.swift index ee21786..9631b29 100644 --- a/MiniScanner/Features/Common/DI/DependencyManager.swift +++ b/MiniScanner/Features/Common/DI/DependencyManager.swift @@ -18,6 +18,16 @@ final class DependencyManager { } private func initializeDependencies() { + initializeSettingsDependencies() + } + + private func initializeSettingsDependencies() { + + let dataSource = SettingsDataSource(userDefaultsManager: userDefaultsManager) + let repository = SettingsRepository(dataSource: dataSource) + @Provide var getLanguagesUseCase = GetLanguagesUseCase(repository: repository) + @Provide var getLanguageUseCase = GetLanguageUseCase(repository: repository) + @Provide var changeLanguageUseCase = ChangeLanguageUseCase(repository: repository) } } diff --git a/MiniScanner/Features/Common/Data/DataSources/SettingsDataSource.swift b/MiniScanner/Features/Common/Data/DataSources/SettingsDataSource.swift new file mode 100644 index 0000000..0751c0b --- /dev/null +++ b/MiniScanner/Features/Common/Data/DataSources/SettingsDataSource.swift @@ -0,0 +1,51 @@ +// +// SettingsDataSource.swift +// MiniScanner +// +// Created by Mustafa Merza on 7/17/24. +// Copyright © 2024 AppsNectar. All rights reserved. +// + +import Foundation +import LanguageManager_iOS + +protocol SettingsDataSourceProtocol { + func getLanguages() -> [SupportedLanguage] + func getLanguage() -> SupportedLanguage + func changeLanguage(to language: SupportedLanguage) +} + +class SettingsDataSource: SettingsDataSourceProtocol { + + private let userDefaultsManager: UserDefaultsManagerProtocol + + private let languageManager = LanguageManager.shared + + private var language: SupportedLanguage { + get { + .from(codeName: userDefaultsManager.string(key: .appLanguage) ?? SupportedLanguage.device.codeName) + } + set { + userDefaultsManager.set(value: newValue.codeName, key: .appLanguage) + } + } + + init(userDefaultsManager: UserDefaultsManagerProtocol) { + self.userDefaultsManager = userDefaultsManager + } + + func getLanguages() -> [SupportedLanguage] { + return SupportedLanguage.allCases + } + + func getLanguage() -> SupportedLanguage { + language + } + + func changeLanguage(to language: SupportedLanguage) { + self.language = language + + languageManager.setLanguage(language: language.language) + languageManager.defaultLanguage = language.language + } +} diff --git a/MiniScanner/Features/Common/Data/Model/SupportedLanguage.swift b/MiniScanner/Features/Common/Data/Model/SupportedLanguage.swift new file mode 100644 index 0000000..b620f9e --- /dev/null +++ b/MiniScanner/Features/Common/Data/Model/SupportedLanguage.swift @@ -0,0 +1,63 @@ +// +// SupportedLanguage.swift +// MiniScanner +// +// Created by Mustafa Merza on 7/17/24. +// Copyright © 2024 AppsNectar. All rights reserved. +// + +import Foundation +import LanguageManager_iOS + +enum SupportedLanguage: CaseIterable { + + case device + case english + case arabic +} + +extension SupportedLanguage { + + static func from(codeName: String) -> SupportedLanguage { + .from(language: Languages(rawValue: codeName) ?? .deviceLanguage) + } + + var codeName: String { + switch self { + case .device: + return Languages.deviceLanguage.rawValue + case .english: + return Languages.en.rawValue + case .arabic: + return Languages.ar.rawValue + } + } +} + +extension SupportedLanguage { + + static func from(language: Languages) -> Self { + switch language { + case .ar: + return .arabic + case .en: + return .english + case .deviceLanguage: + return .device + + default: + return .device + } + } + + var language: Languages { + switch self { + case .device: + return .deviceLanguage + case .english: + return .en + case .arabic: + return .ar + } + } +} diff --git a/MiniScanner/Features/Common/Data/Repositories/SettingsRepository.swift b/MiniScanner/Features/Common/Data/Repositories/SettingsRepository.swift new file mode 100644 index 0000000..35932a2 --- /dev/null +++ b/MiniScanner/Features/Common/Data/Repositories/SettingsRepository.swift @@ -0,0 +1,41 @@ +// +// SettingsRepository.swift +// MiniScanner +// +// Created by Mustafa Merza on 7/17/24. +// Copyright © 2024 AppsNectar. All rights reserved. +// + +import Foundation + +class SettingsRepository: SettingsRepositoryProtocol { + + private let dataSource: SettingsDataSourceProtocol + + init(dataSource: SettingsDataSourceProtocol) { + self.dataSource = dataSource + } + + func getLanguages() -> [SupportedLanguage] { + dataSource.getLanguages() + } + + func getLanguage() -> SupportedLanguage { + dataSource.getLanguage() + } + + func changeLanguage(to language: SupportedLanguage) { + + if shouldChangeLanguage(to: language) { + + dataSource.changeLanguage(to: language) + } + } +} + +extension SettingsRepository { + + private func shouldChangeLanguage(to language: SupportedLanguage) -> Bool { + dataSource.getLanguage() != language + } +} diff --git a/MiniScanner/Features/Common/Domain/Repositories/SettingsRepositoryProtocol.swift b/MiniScanner/Features/Common/Domain/Repositories/SettingsRepositoryProtocol.swift new file mode 100644 index 0000000..99d7566 --- /dev/null +++ b/MiniScanner/Features/Common/Domain/Repositories/SettingsRepositoryProtocol.swift @@ -0,0 +1,16 @@ +// +// SettingsRepositoryProtocol.swift +// MiniScanner +// +// Created by Mustafa Merza on 7/17/24. +// Copyright © 2024 AppsNectar. All rights reserved. +// + +import Foundation + +protocol SettingsRepositoryProtocol { + + func getLanguages() -> [SupportedLanguage] + func getLanguage() -> SupportedLanguage + func changeLanguage(to language: SupportedLanguage) +} diff --git a/MiniScanner/Features/Common/Domain/UseCases/Language/ChangeLanguageUseCase.swift b/MiniScanner/Features/Common/Domain/UseCases/Language/ChangeLanguageUseCase.swift new file mode 100644 index 0000000..3810da3 --- /dev/null +++ b/MiniScanner/Features/Common/Domain/UseCases/Language/ChangeLanguageUseCase.swift @@ -0,0 +1,22 @@ +// +// ChangeLanguageUseCase.swift +// MiniScanner +// +// Created by Mustafa Merza on 7/17/24. +// Copyright © 2024 AppsNectar. All rights reserved. +// + +import Foundation + +class ChangeLanguageUseCase { + + private let repository: SettingsRepositoryProtocol + + init(repository: SettingsRepositoryProtocol) { + self.repository = repository + } + + func execute(to language: SupportedLanguage) { + repository.changeLanguage(to: language) + } +} diff --git a/MiniScanner/Features/Common/Domain/UseCases/Language/GetLanguageUseCase.swift b/MiniScanner/Features/Common/Domain/UseCases/Language/GetLanguageUseCase.swift new file mode 100644 index 0000000..e949d0b --- /dev/null +++ b/MiniScanner/Features/Common/Domain/UseCases/Language/GetLanguageUseCase.swift @@ -0,0 +1,22 @@ +// +// GetLanguageUseCase.swift +// MiniScanner +// +// Created by Mustafa Merza on 7/17/24. +// Copyright © 2024 AppsNectar. All rights reserved. +// + +import Foundation + +class GetLanguageUseCase { + + private let repository: SettingsRepositoryProtocol + + init(repository: SettingsRepositoryProtocol) { + self.repository = repository + } + + func execute() -> SupportedLanguage { + repository.getLanguage() + } +} diff --git a/MiniScanner/Features/Common/Domain/UseCases/Language/GetLanguagesUseCase.swift b/MiniScanner/Features/Common/Domain/UseCases/Language/GetLanguagesUseCase.swift new file mode 100644 index 0000000..1a79364 --- /dev/null +++ b/MiniScanner/Features/Common/Domain/UseCases/Language/GetLanguagesUseCase.swift @@ -0,0 +1,22 @@ +// +// GetLanguagesUseCase.swift +// MiniScanner +// +// Created by Mustafa Merza on 7/17/24. +// Copyright © 2024 AppsNectar. All rights reserved. +// + +import Foundation + +class GetLanguagesUseCase { + + private let repository: SettingsRepositoryProtocol + + init(repository: SettingsRepositoryProtocol) { + self.repository = repository + } + + func execute() -> [SupportedLanguage] { + repository.getLanguages() + } +} -- GitLab