From 5193bef94067236fd774a68beda1433226ebced2 Mon Sep 17 00:00:00 2001
From: Mustafa Merza <mustafa.merza95@gmail.com>
Date: Mon, 22 Jul 2024 12:10:19 +0300
Subject: [PATCH] - Fixed back button style (icon and alignment) when changing
 languages.

---
 MiniScanner/Extensions/Image+Images.swift     |  1 +
 .../Settings/Presentation/SettingsView.swift  | 50 +++++++++++++++++--
 .../SettingsViewCoordinator.swift             |  4 +-
 .../Presentation/SettingsViewModel.swift      | 44 ++++++++--------
 .../DocumentsTableViewController.swift        | 14 +++++-
 5 files changed, 84 insertions(+), 29 deletions(-)

diff --git a/MiniScanner/Extensions/Image+Images.swift b/MiniScanner/Extensions/Image+Images.swift
index 144c438..f4616a7 100644
--- a/MiniScanner/Extensions/Image+Images.swift
+++ b/MiniScanner/Extensions/Image+Images.swift
@@ -16,4 +16,5 @@ extension Image {
 // MARK: - Common system images and icons
 extension Image {
     
+    static let chevronBackward = Image(systemName: "chevron.backward")
 }
diff --git a/MiniScanner/Features/Settings/Presentation/SettingsView.swift b/MiniScanner/Features/Settings/Presentation/SettingsView.swift
index 868a0f7..9095868 100644
--- a/MiniScanner/Features/Settings/Presentation/SettingsView.swift
+++ b/MiniScanner/Features/Settings/Presentation/SettingsView.swift
@@ -27,10 +27,26 @@ struct SettingsView: View {
                     settingsForm
                 }
             }
+            .navigationTitle(viewModel.navigationTitle)
+            .customNavigationBackButton(defaultBackButtonHidden: viewModel.isDefaultBackButtonHidden,
+                                        backButton: backButton)
             .environment(\.layoutDirection, viewModel.layoutDirection)
         }
     }
     
+    private var backButton: some View {
+        Button(action: {
+            viewModel.onBackButtonClick()
+        }, label: {
+            HStack(spacing: 4) {
+                
+                Image.chevronBackward
+                
+                Text(viewModel.backButtonTitle)
+            }
+        })
+    }
+    
     private var settingsForm: some View {
         
         Form {
@@ -51,7 +67,7 @@ struct SettingsView: View {
 extension SettingsView {
     
     private var language: some View {
-        CustomMenuPicker(selectedItem: $viewModel.selectedLangauge,
+        CustomMenuPicker(selectedItem: $viewModel.selectedLanguage,
                          items: viewModel.languages,
                          label: { languageLabel })
     }
@@ -63,9 +79,9 @@ extension SettingsView {
             
             Spacer()
             
-            Text(viewModel.selectedLangauge.displayedName)
+            Text(viewModel.selectedLanguage.displayedName)
             
-            Text(viewModel.selectedLangauge.flag)
+            Text(viewModel.selectedLanguage.flag)
         }
         .foregroundStyle(Color.mainText)
     }
@@ -92,3 +108,31 @@ extension SettingsView {
 #Preview {
     SettingsView(coordinator: SettingsViewCoordinator(navigationController: UINavigationController()))
 }
+
+fileprivate extension View {
+    
+    func customNavigationBackButton<T: View>(defaultBackButtonHidden: Bool,
+                                             backButton: T) -> some View {
+        ModifiedContent(content: self,
+                        modifier: CustomBackButtonViewModifier(defaultBackButtonHidden: defaultBackButtonHidden, backButton: backButton))
+    }
+}
+
+fileprivate struct CustomBackButtonViewModifier<T: View>: ViewModifier {
+    
+    var defaultBackButtonHidden: Bool
+    var backButton: T
+    
+    func body(content: Content) -> some View {
+        
+        if defaultBackButtonHidden {
+            
+            content
+                .navigationBarBackButtonHidden(defaultBackButtonHidden)
+                .navigationBarItems(leading: backButton)
+        }
+        else {
+            content
+        }
+    }
+}
diff --git a/MiniScanner/Features/Settings/Presentation/SettingsViewCoordinator.swift b/MiniScanner/Features/Settings/Presentation/SettingsViewCoordinator.swift
index 8f1578a..2d52efb 100644
--- a/MiniScanner/Features/Settings/Presentation/SettingsViewCoordinator.swift
+++ b/MiniScanner/Features/Settings/Presentation/SettingsViewCoordinator.swift
@@ -8,11 +8,11 @@
 
 import Foundation
 
-protocol SettingsViewCoordinating {
+protocol SettingsViewCoordinating: MainCoordinator {
     var navigationController: UINavigationController { get set }
 }
 
-class SettingsViewCoordinator: SettingsViewCoordinating, MainCoordinator {
+class SettingsViewCoordinator: SettingsViewCoordinating {
     
     var navigationController: UINavigationController
     
diff --git a/MiniScanner/Features/Settings/Presentation/SettingsViewModel.swift b/MiniScanner/Features/Settings/Presentation/SettingsViewModel.swift
index d197fcd..f3e24db 100644
--- a/MiniScanner/Features/Settings/Presentation/SettingsViewModel.swift
+++ b/MiniScanner/Features/Settings/Presentation/SettingsViewModel.swift
@@ -17,9 +17,9 @@ final class SettingsViewModel: MainViewModel {
     @Published var languages: [SupportedLanguage] = []
     @Published var colorShemes: [SupportedColorScheme] = []
     
-    @Published var selectedLangauge: SupportedLanguage = .device {
+    @Published var selectedLanguage: SupportedLanguage = .device {
         didSet {
-            changeLanguage(to: selectedLangauge)
+            changeLanguage(to: selectedLanguage)
         }
     }
     
@@ -29,6 +29,11 @@ final class SettingsViewModel: MainViewModel {
         }
     }
     
+    @Published var isDefaultBackButtonHidden: Bool = false
+    
+    var navigationTitle: String { .settings.localized }
+    var backButtonTitle: String { .fileManager.localized }
+    
     @Inject var getLanguagesUseCase: GetLanguagesUseCase
     @Inject var getLanguageUseCase: GetLanguageUseCase
     @Inject var changeLanguageUseCase: ChangeLanguageUseCase
@@ -56,7 +61,7 @@ extension SettingsViewModel {
         languages = getLanguagesUseCase.execute()
         colorShemes = SupportedColorScheme.allCases
         
-        selectedLangauge = getLanguageUseCase.execute()
+        selectedLanguage = getLanguageUseCase.execute()
         selectedColorScheme = getColorSchemeUseCase.execute()
     }
 }
@@ -64,14 +69,21 @@ extension SettingsViewModel {
 extension SettingsViewModel {
     
     private func changeLanguage(to language: SupportedLanguage) {
+        
+        let previousLanguage = SupportedLanguage.currentLanguage
+        
         changeLanguageUseCase.execute(to: language)
-        layoutDirection = language.layoutDirection
         
-        refreshLocalization()
+        layoutDirection = language.layoutDirection
         
         if language.layoutDirection == .leftToRight {
             refreshView.toggle()
         }
+        
+        if previousLanguage != SupportedLanguage.currentLanguage {
+            
+            refreshSemanticContentAttribute()
+        }
     }
     
     private func changeColorShceme(to colorScheme: SupportedColorScheme) {
@@ -81,30 +93,18 @@ extension SettingsViewModel {
 
 extension SettingsViewModel {
     
-    private func refreshLocalization() {
+    private func refreshSemanticContentAttribute() {
         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
         
-        handleBackIcon()
+        isDefaultBackButtonHidden = true
     }
     
-    private func handleBackIcon() {
-        
-        let navigationController = coordinator.navigationController
-        
-        let backImage: UIImage? = SupportedLanguage.currentLanguage.layoutDirection == .leftToRight ? .chevronLeft : .chevronRight
-        
-        navigationController.navigationBar.backIndicatorImage = backImage
-        navigationController.navigationBar.backIndicatorTransitionMaskImage = backImage
+    func onBackButtonClick() {
+        coordinator.coordinateBack()
     }
 }
diff --git a/MiniScanner/Modules/Documents/DocumentsTableViewController.swift b/MiniScanner/Modules/Documents/DocumentsTableViewController.swift
index 5c7cce1..d7bc532 100644
--- a/MiniScanner/Modules/Documents/DocumentsTableViewController.swift
+++ b/MiniScanner/Modules/Documents/DocumentsTableViewController.swift
@@ -63,7 +63,6 @@ final class DocumentsTableViewController: UIViewController, UITableViewDelegate,
         }
         scanSession =  MultiPageScanSession()
         options = ImageScannerOptions()
-        navigationItem.title = .fileManager.localized
         let settingsButton = UIBarButtonItem(image: .settings, style: .done, target: self, action: #selector(openSettings))
         navigationItem.rightBarButtonItem = settingsButton
         
@@ -126,6 +125,7 @@ final class DocumentsTableViewController: UIViewController, UITableViewDelegate,
         fetchViewModels()
         
         handleBackIcon()
+        navigationItem.title = .fileManager.localized
         noFilesLabel.set(text: .noFilesToShow.localized, color: .mainText, font: .medium(22))
         
         AllFolderView.reloadLocalization()
@@ -639,7 +639,17 @@ extension DocumentsTableViewController {
         
         let navigationController = navigationController!
         
-        let backImage: UIImage? = SupportedLanguage.currentLanguage.layoutDirection == .leftToRight ? .chevronLeft : .chevronRight
+        var backImage: UIImage? = nil
+        
+        let deviceLanguage = SupportedLanguage.device.language
+        let currentLanguageLayoutDirection = SupportedLanguage.currentLanguage.layoutDirection
+        
+        if deviceLanguage == .ar {
+            backImage = currentLanguageLayoutDirection == .leftToRight ? .chevronRight : .chevronLeft
+        }
+        else {
+            backImage = currentLanguageLayoutDirection == .leftToRight ? .chevronLeft : .chevronRight
+        }
         
         navigationController.navigationBar.backIndicatorImage = backImage
         navigationController.navigationBar.backIndicatorTransitionMaskImage = backImage
-- 
GitLab