From 98113eca4785f3111d91c4a38abe4735219cd357 Mon Sep 17 00:00:00 2001
From: Mustafa Merza <mustafa.merza95@gmail.com>
Date: Sun, 21 Jul 2024 11:31:45 +0300
Subject: [PATCH] - Added settings screen.

- Added language setting to change app's language.
- Added app theme setting to change app's appearance.
---
 MiniScanner.xcodeproj/project.pbxproj         |  28 ++++
 .../Extensions/String+StringKeys.swift        |  23 +++-
 .../Data/Model/SupportedColorScheme.swift     |  16 ++-
 .../Common/Data/Model/SupportedLanguage.swift |  60 ++++++---
 .../Repositories/SettingsRepository.swift     |   8 ++
 .../Settings/Presentation/SettingsView.swift  |  94 +++++++++++++
 .../SettingsViewCoordinator.swift             |  27 ++++
 .../Presentation/SettingsViewModel.swift      |  98 ++++++++++++++
 .../Localization/Localizable.xcstrings        | 124 ++++++++++++++++++
 9 files changed, 456 insertions(+), 22 deletions(-)
 create mode 100644 MiniScanner/Features/Settings/Presentation/SettingsView.swift
 create mode 100644 MiniScanner/Features/Settings/Presentation/SettingsViewCoordinator.swift
 create mode 100644 MiniScanner/Features/Settings/Presentation/SettingsViewModel.swift

diff --git a/MiniScanner.xcodeproj/project.pbxproj b/MiniScanner.xcodeproj/project.pbxproj
index d976490..46ebe13 100644
--- a/MiniScanner.xcodeproj/project.pbxproj
+++ b/MiniScanner.xcodeproj/project.pbxproj
@@ -200,6 +200,9 @@
 		67807FA02C4934BD00D1F168 /* View+LayoutChanges.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67807F9F2C4934BD00D1F168 /* View+LayoutChanges.swift */; };
 		678BD70D2C4CF18300833DA5 /* CustomMenuPickerItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 678BD70C2C4CF18300833DA5 /* CustomMenuPickerItem.swift */; };
 		678BD70F2C4CF1A000833DA5 /* CustomMenuPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 678BD70E2C4CF1A000833DA5 /* CustomMenuPicker.swift */; };
+		678BD7152C4CF1EB00833DA5 /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 678BD7102C4CF1EB00833DA5 /* SettingsView.swift */; };
+		678BD7162C4CF1EB00833DA5 /* SettingsViewCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 678BD7112C4CF1EB00833DA5 /* SettingsViewCoordinator.swift */; };
+		678BD7172C4CF1EB00833DA5 /* SettingsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 678BD7122C4CF1EB00833DA5 /* SettingsViewModel.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 */; };
@@ -450,6 +453,9 @@
 		67807F9F2C4934BD00D1F168 /* View+LayoutChanges.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+LayoutChanges.swift"; sourceTree = "<group>"; };
 		678BD70C2C4CF18300833DA5 /* CustomMenuPickerItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomMenuPickerItem.swift; sourceTree = "<group>"; };
 		678BD70E2C4CF1A000833DA5 /* CustomMenuPicker.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomMenuPicker.swift; sourceTree = "<group>"; };
+		678BD7102C4CF1EB00833DA5 /* SettingsView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = "<group>"; };
+		678BD7112C4CF1EB00833DA5 /* SettingsViewCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsViewCoordinator.swift; sourceTree = "<group>"; };
+		678BD7122C4CF1EB00833DA5 /* SettingsViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsViewModel.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; };
@@ -1020,6 +1026,7 @@
 		672C46AF2C47E8D700497EF0 /* Features */ = {
 			isa = PBXGroup;
 			children = (
+				678BD7142C4CF1EB00833DA5 /* Settings */,
 				672C46AE2C47E8D700497EF0 /* Common */,
 			);
 			path = Features;
@@ -1136,6 +1143,24 @@
 			path = View;
 			sourceTree = "<group>";
 		};
+		678BD7132C4CF1EB00833DA5 /* Presentation */ = {
+			isa = PBXGroup;
+			children = (
+				678BD7102C4CF1EB00833DA5 /* SettingsView.swift */,
+				678BD7112C4CF1EB00833DA5 /* SettingsViewCoordinator.swift */,
+				678BD7122C4CF1EB00833DA5 /* SettingsViewModel.swift */,
+			);
+			path = Presentation;
+			sourceTree = "<group>";
+		};
+		678BD7142C4CF1EB00833DA5 /* Settings */ = {
+			isa = PBXGroup;
+			children = (
+				678BD7132C4CF1EB00833DA5 /* Presentation */,
+			);
+			path = Settings;
+			sourceTree = "<group>";
+		};
 		98E49D3F46C8E62718825860 /* Pods */ = {
 			isa = PBXGroup;
 			children = (
@@ -1541,6 +1566,7 @@
 				53014FA82C11A8E80071CE39 /* CIRectangleDetector.swift in Sources */,
 				EC8A9AD5254DB76000F9AF99 /* BaseNavigationViewController.swift in Sources */,
 				535983EB2C142B16003EB6ED /* UILabel+Extensions.swift in Sources */,
+				678BD7172C4CF1EB00833DA5 /* SettingsViewModel.swift in Sources */,
 				EC8A9B10254DC6DD00F9AF99 /* PDFManager.swift in Sources */,
 				5399964B2C26E86700671340 /* FlashButton.m in Sources */,
 				5399968C2C27130000671340 /* ConstraintInsetTarget.swift in Sources */,
@@ -1583,6 +1609,7 @@
 				53014FA32C11A8E80071CE39 /* ZoomGestureController.swift in Sources */,
 				5399964C2C26E86700671340 /* CDCameraView.m in Sources */,
 				5399969B2C27130000671340 /* ConstraintView+Extensions.swift in Sources */,
+				678BD7152C4CF1EB00833DA5 /* SettingsView.swift in Sources */,
 				53E3A2092C19D17100C9B95E /* PreviewImageViewController.swift in Sources */,
 				53E7D3362C1B00880025A1D3 /* FSPageViewTransformer.swift in Sources */,
 				EC70252A254E066400BE1958 /* SettingsViewController+Safari.swift in Sources */,
@@ -1631,6 +1658,7 @@
 				53E7D3382C1B00880025A1D3 /* FSPagerViewLayoutAttributes.swift in Sources */,
 				53014F8E2C11A8E80071CE39 /* ImageScannerController.swift in Sources */,
 				539996A42C27130000671340 /* ConstraintMakerRelatable.swift in Sources */,
+				678BD7162C4CF1EB00833DA5 /* SettingsViewCoordinator.swift in Sources */,
 				539996942C27130000671340 /* Typealiases.swift in Sources */,
 				5399964D2C26E86700671340 /* CDImageRectangleDetector.m in Sources */,
 				5399964E2C26E86700671340 /* CDZoomView.m in Sources */,
diff --git a/MiniScanner/Extensions/String+StringKeys.swift b/MiniScanner/Extensions/String+StringKeys.swift
index 9c56420..2ee2fb1 100644
--- a/MiniScanner/Extensions/String+StringKeys.swift
+++ b/MiniScanner/Extensions/String+StringKeys.swift
@@ -53,11 +53,22 @@ extension String {
     static let yes = "yes"
     static let no = "no"
     
-    static let fileManager =  "file_manager"
-    static let folders =  "folders"
-    static let folderFiles =  "folder_files"
-    static let noFilesToShow =  "no_files_to_show"
+    static let fileManager = "file_manager"
+    static let folders = "folders"
+    static let folderFiles = "folder_files"
+    static let noFilesToShow = "no_files_to_show"
     static let folderName = "folder_name"
-    static let preview =  "preview"
-    static let done =  "done"
+    static let preview = "preview"
+    static let done = "done"
+    
+    static let settings = "settings"
+    
+    static let language = "language"
+    static let appTheme = "app_theme"
+    
+    static let appearence = "appearence"
+    static let deviceLanguage = "device_language"
+    static let deviceTheme = "device_theme"
+    static let darkMode = "dark_mode"
+    static let lightMode = "light_mode"
 }
diff --git a/MiniScanner/Features/Common/Data/Model/SupportedColorScheme.swift b/MiniScanner/Features/Common/Data/Model/SupportedColorScheme.swift
index 25773e7..39381e3 100644
--- a/MiniScanner/Features/Common/Data/Model/SupportedColorScheme.swift
+++ b/MiniScanner/Features/Common/Data/Model/SupportedColorScheme.swift
@@ -8,11 +8,25 @@
 
 import Foundation
 
-enum SupportedColorScheme: String, CaseIterable {
+enum SupportedColorScheme: String, CaseIterable, CustomMenuPickerItem {
     
     case device
     case light
     case dark
+    
+    var id: Self { self }
+    
+    var displayedName: String {
+        switch self {
+        case .device:
+                .deviceTheme.localized
+        case .light:
+                .lightMode.localized
+        case .dark:
+                .darkMode.localized
+        }
+    }
+    
 }
 
 extension SupportedColorScheme {
diff --git a/MiniScanner/Features/Common/Data/Model/SupportedLanguage.swift b/MiniScanner/Features/Common/Data/Model/SupportedLanguage.swift
index 3883c3b..a8e9bc0 100644
--- a/MiniScanner/Features/Common/Data/Model/SupportedLanguage.swift
+++ b/MiniScanner/Features/Common/Data/Model/SupportedLanguage.swift
@@ -8,8 +8,9 @@
 
 import Foundation
 import LanguageManager_iOS
+import SwiftUI
 
-enum SupportedLanguage: CaseIterable {
+enum SupportedLanguage: CaseIterable, CustomMenuPickerItem {
     
     case device
     case english
@@ -18,11 +19,11 @@ enum SupportedLanguage: CaseIterable {
     var flag: String {
         switch self {
         case .device:
-            return SupportedLanguage.currentLanguage.flag
+            SupportedLanguage.currentLanguage.flag
         case .english:
-            return "🇺🇸"
+            "🇺🇸"
         case .arabic:
-            return "🇰🇼"
+            "🇰🇼"
         }
     }
     
@@ -31,12 +32,41 @@ enum SupportedLanguage: CaseIterable {
     }
     
     var isRTL: Bool {
-        LanguageManager.shared.isRightToLeft
+        switch self {
+        case .device:
+            LanguageManager.shared.isRightToLeft
+        case .english:
+            false
+        case .arabic:
+            true
+        }
     }
     
     var layoutDirection: LayoutDirection {
         isRTL ? .rightToLeft : .leftToRight
     }
+    
+    var semanticContentAttribute:  UISemanticContentAttribute {
+        isRTL ? .forceRightToLeft : .forceLeftToRight
+    }
+    
+    var id: Self { self }
+    
+    var displayedName: String {
+        switch self {
+        case .device:
+                .deviceLanguage.localized
+        case .english:
+            displayNameForLanguage(.english)
+        case .arabic:
+            displayNameForLanguage(.arabic)
+        }
+    }
+    
+    func displayNameForLanguage(_ language: SupportedLanguage) -> String {
+        let locale = NSLocale(localeIdentifier: SupportedLanguage.currentLanguage.codeName)
+        return locale.displayName(forKey: .identifier, value: language.codeName) ?? ""
+    }
 }
 
 extension SupportedLanguage {
@@ -48,11 +78,11 @@ extension SupportedLanguage {
     var codeName: String {
         switch self {
         case .device:
-            return Languages.deviceLanguage.rawValue
+            Languages.deviceLanguage.rawValue
         case .english:
-            return Languages.en.rawValue
+            Languages.en.rawValue
         case .arabic:
-            return Languages.ar.rawValue
+            Languages.ar.rawValue
         }
     }
 }
@@ -62,25 +92,25 @@ extension SupportedLanguage {
     static func from(language: Languages) -> Self {
         switch language {
         case .ar:
-            return .arabic
+                .arabic
         case .en:
-            return .english
+                .english
         case .deviceLanguage:
-            return .device
+                .device
             
         default:
-            return .device
+                .device
         }
     }
     
     var language: Languages {
         switch self {
         case .device:
-            return LanguageManager.shared.deviceLanguage ?? .en
+            LanguageManager.shared.deviceLanguage ?? .en
         case .english:
-            return .en
+                .en
         case .arabic:
-            return .ar
+                .ar
         }
     }
 }
diff --git a/MiniScanner/Features/Common/Data/Repositories/SettingsRepository.swift b/MiniScanner/Features/Common/Data/Repositories/SettingsRepository.swift
index 908de5a..199927e 100644
--- a/MiniScanner/Features/Common/Data/Repositories/SettingsRepository.swift
+++ b/MiniScanner/Features/Common/Data/Repositories/SettingsRepository.swift
@@ -101,6 +101,9 @@ extension SettingsRepository {
     }
     
     private func handleUISettings() {
+        
+        handleScrollViewAppearace()
+        
         handleNavigationBarAppearace()
         
         handleToolBarAppearace()
@@ -108,6 +111,11 @@ extension SettingsRepository {
         handleButtonAppearace()
     }
     
+    private func handleScrollViewAppearace() {
+        
+        UIScrollView.appearance().bounces = false
+    }
+    
     private func handleNavigationBarAppearace() {
         let navigationBarAppearace = UINavigationBar.appearance()
         
diff --git a/MiniScanner/Features/Settings/Presentation/SettingsView.swift b/MiniScanner/Features/Settings/Presentation/SettingsView.swift
new file mode 100644
index 0000000..3c4c4e8
--- /dev/null
+++ b/MiniScanner/Features/Settings/Presentation/SettingsView.swift
@@ -0,0 +1,94 @@
+//
+//  SettingsView.swift
+//  MiniScanner
+//
+//  Created by Mustafa Merza on 7/18/24.
+//  Copyright © 2024 AppsNectar. All rights reserved.
+//
+
+import SwiftUI
+
+struct SettingsView: View {
+    
+    @StateObject var viewModel: SettingsViewModel2
+    
+    init(coordinator: SettingsViewCoordinating) {
+        self._viewModel = StateObject(wrappedValue: SettingsViewModel2(coordinator: coordinator))
+    }
+    
+    var body: some View {
+        MainView(viewModel: viewModel) {
+            VStack {
+                
+                if viewModel.refreshView {
+                    settingsForm
+                }
+                else {
+                    settingsForm
+                }
+            }
+            .environment(\.layoutDirection, viewModel.layoutDirection)
+        }
+    }
+    
+    private var settingsForm: some View {
+        
+        Form {
+            
+            Section {
+                
+                language
+                
+                colorScheme
+                
+            } header: {
+                Text(String.appearence.localized)
+            }
+        }
+    }
+}
+
+extension SettingsView {
+    
+    private var language: some View {
+        CustomMenuPicker(selectedItem: $viewModel.selectedLangauge,
+                         items: viewModel.languages,
+                         label: { languageLabel })
+    }
+    
+    private var languageLabel: some View {
+        HStack {
+            
+            Text(String.language.localized)
+            
+            Spacer()
+            
+            Text(viewModel.selectedLangauge.displayedName)
+            
+            Text(viewModel.selectedLangauge.flag)
+        }
+        .foregroundStyle(Color.mainText)
+    }
+    
+    private var colorScheme: some View {
+        CustomMenuPicker(selectedItem: $viewModel.selectedColorScheme,
+                         items: viewModel.colorShemes,
+                         label: { colorSchemeLabel })
+    }
+    
+    private var colorSchemeLabel: some View {
+        HStack {
+            
+            Text(String.appTheme.localized)
+            
+            Spacer()
+            
+            Text(viewModel.selectedColorScheme.displayedName)
+        }
+        .foregroundStyle(Color.mainText)
+    }
+}
+
+#Preview {
+    SettingsView(coordinator: SettingsViewCoordinator(navigationController: UINavigationController()))
+}
diff --git a/MiniScanner/Features/Settings/Presentation/SettingsViewCoordinator.swift b/MiniScanner/Features/Settings/Presentation/SettingsViewCoordinator.swift
new file mode 100644
index 0000000..8f1578a
--- /dev/null
+++ b/MiniScanner/Features/Settings/Presentation/SettingsViewCoordinator.swift
@@ -0,0 +1,27 @@
+//
+//  SettingsViewCoordinator.swift
+//  MiniScanner
+//
+//  Created by Mustafa Merza on 7/18/24.
+//  Copyright © 2024 AppsNectar. All rights reserved.
+//
+
+import Foundation
+
+protocol SettingsViewCoordinating {
+    var navigationController: UINavigationController { get set }
+}
+
+class SettingsViewCoordinator: SettingsViewCoordinating, MainCoordinator {
+    
+    var navigationController: UINavigationController
+    
+    init(navigationController: UINavigationController) {
+        self.navigationController = navigationController
+    }
+    
+    func start() {
+        let view = SettingsView(coordinator: self)
+        coordinateToView(view, title: .settings.localized)
+    }
+}
diff --git a/MiniScanner/Features/Settings/Presentation/SettingsViewModel.swift b/MiniScanner/Features/Settings/Presentation/SettingsViewModel.swift
new file mode 100644
index 0000000..a3d0f29
--- /dev/null
+++ b/MiniScanner/Features/Settings/Presentation/SettingsViewModel.swift
@@ -0,0 +1,98 @@
+//
+//  SettingsViewModel.swift
+//  MiniScanner
+//
+//  Created by Mustafa Merza on 7/18/24.
+//  Copyright © 2024 AppsNectar. All rights reserved.
+//
+
+import SwiftUI
+
+final class SettingsViewModel2: MainViewModel {
+    
+    @Published var layoutDirection: LayoutDirection = .leftToRight
+    
+    @Published var refreshView: Bool = false
+    
+    @Published var languages: [SupportedLanguage] = []
+    @Published var colorShemes: [SupportedColorScheme] = []
+    
+    @Published var selectedLangauge: SupportedLanguage = .device {
+        didSet {
+            changeLanguage(to: selectedLangauge)
+        }
+    }
+    
+    @Published var selectedColorScheme: SupportedColorScheme = .device {
+        didSet {
+            changeColorShceme(to: selectedColorScheme)
+        }
+    }
+    
+    @Inject var getLanguagesUseCase: GetLanguagesUseCase
+    @Inject var getLanguageUseCase: GetLanguageUseCase
+    @Inject var changeLanguageUseCase: ChangeLanguageUseCase
+    
+    @Inject var getColorSchemeUseCase: GetColorSchemeUseCase
+    @Inject var changeColorSchemeUseCase: ChangeColorSchemeUseCase
+    
+    private let coordinator: SettingsViewCoordinating
+    
+    init(coordinator: SettingsViewCoordinating) {
+        self.coordinator = coordinator
+    }
+}
+
+extension SettingsViewModel2 {
+    
+    func onAppear() {
+        fetchSettings()
+    }
+}
+
+extension SettingsViewModel2 {
+    
+    private func fetchSettings() {
+        languages = getLanguagesUseCase.execute()
+        colorShemes = SupportedColorScheme.allCases
+        
+        selectedLangauge = getLanguageUseCase.execute()
+        selectedColorScheme = getColorSchemeUseCase.execute()
+    }
+}
+
+extension SettingsViewModel2 {
+    
+    private func changeLanguage(to language: SupportedLanguage) {
+        changeLanguageUseCase.execute(to: language)
+        layoutDirection = language.layoutDirection
+        
+        refreshLocalization()
+        
+        if language == .english {
+            refreshView.toggle()
+        }
+    }
+    
+    private func changeColorShceme(to colorScheme: SupportedColorScheme) {
+        changeColorSchemeUseCase.execute(to: colorScheme)
+    }
+}
+
+extension SettingsViewModel2 {
+    
+    private func refreshLocalization() {
+        let navigationController = coordinator.navigationController
+        
+        let settings = navigationController.topViewController!
+        let filesManager = navigationController.viewControllers[0]
+        
+        settings.navigationItem.title = .settings.localized
+        filesManager.navigationItem.title = .fileManager.localized
+        
+        let semanticContentAttribute = SupportedLanguage.currentLanguage.semanticContentAttribute
+        
+        navigationController.tabBarController?.tabBar.semanticContentAttribute = semanticContentAttribute
+        navigationController.navigationBar.semanticContentAttribute = semanticContentAttribute
+    }
+}
diff --git a/MiniScanner/Supporting Files/Localization/Localizable.xcstrings b/MiniScanner/Supporting Files/Localization/Localizable.xcstrings
index 70deb08..768326e 100644
--- a/MiniScanner/Supporting Files/Localization/Localizable.xcstrings	
+++ b/MiniScanner/Supporting Files/Localization/Localizable.xcstrings	
@@ -35,6 +35,34 @@
         }
       }
     },
+    "app_theme" : {
+      "extractionState" : "manual",
+      "localizations" : {
+        "en" : {
+          "stringUnit" : {
+            "state" : "translated",
+            "value" : "App theme"
+          }
+        }
+      }
+    },
+    "appearence" : {
+      "extractionState" : "manual",
+      "localizations" : {
+        "ar" : {
+          "stringUnit" : {
+            "state" : "translated",
+            "value" : "مظهر التطبيق"
+          }
+        },
+        "en" : {
+          "stringUnit" : {
+            "state" : "translated",
+            "value" : "Appearence"
+          }
+        }
+      }
+    },
     "are_you_sure" : {
       "extractionState" : "manual",
       "localizations" : {
@@ -103,6 +131,23 @@
         }
       }
     },
+    "dark_mode" : {
+      "extractionState" : "manual",
+      "localizations" : {
+        "ar" : {
+          "stringUnit" : {
+            "state" : "translated",
+            "value" : "الوضع الليلي"
+          }
+        },
+        "en" : {
+          "stringUnit" : {
+            "state" : "translated",
+            "value" : "Dark mode"
+          }
+        }
+      }
+    },
     "delete" : {
       "extractionState" : "manual",
       "localizations" : {
@@ -154,6 +199,34 @@
         }
       }
     },
+    "device_language" : {
+      "extractionState" : "manual",
+      "localizations" : {
+        "ar" : {
+          "stringUnit" : {
+            "state" : "translated",
+            "value" : "لغة الجهاز"
+          }
+        },
+        "en" : {
+          "stringUnit" : {
+            "state" : "translated",
+            "value" : "Device language"
+          }
+        }
+      }
+    },
+    "device_theme" : {
+      "extractionState" : "manual",
+      "localizations" : {
+        "en" : {
+          "stringUnit" : {
+            "state" : "translated",
+            "value" : "Device Theme"
+          }
+        }
+      }
+    },
     "discard" : {
       "extractionState" : "manual",
       "localizations" : {
@@ -335,6 +408,40 @@
         }
       }
     },
+    "language" : {
+      "extractionState" : "manual",
+      "localizations" : {
+        "ar" : {
+          "stringUnit" : {
+            "state" : "translated",
+            "value" : "اللغة"
+          }
+        },
+        "en" : {
+          "stringUnit" : {
+            "state" : "translated",
+            "value" : "Language"
+          }
+        }
+      }
+    },
+    "light_mode" : {
+      "extractionState" : "manual",
+      "localizations" : {
+        "ar" : {
+          "stringUnit" : {
+            "state" : "translated",
+            "value" : "الوضع النهاري"
+          }
+        },
+        "en" : {
+          "stringUnit" : {
+            "state" : "translated",
+            "value" : "Light mode"
+          }
+        }
+      }
+    },
     "more" : {
       "extractionState" : "manual",
       "localizations" : {
@@ -482,6 +589,23 @@
         }
       }
     },
+    "settings" : {
+      "extractionState" : "manual",
+      "localizations" : {
+        "ar" : {
+          "stringUnit" : {
+            "state" : "translated",
+            "value" : "الإعدادات"
+          }
+        },
+        "en" : {
+          "stringUnit" : {
+            "state" : "translated",
+            "value" : "Settings"
+          }
+        }
+      }
+    },
     "telegram" : {
       "extractionState" : "manual",
       "localizations" : {
-- 
GitLab