From dac594a9c3f9048fa1e7ca961447dd14f3831895 Mon Sep 17 00:00:00 2001
From: Mustafa Merza <mustafa.merza95@gmail.com>
Date: Thu, 15 Aug 2024 14:48:37 +0300
Subject: [PATCH] - Moved images compression test from scanned items cells
 screen to settings screen.

---
 .../Core/Extensions/Image+Images.swift        |  1 +
 .../Settings/Presentation/SettingsView.swift  | 12 ++++
 .../SettingsViewCoordinator.swift             | 16 +++++
 .../Presentation/SettingsViewModel.swift      | 66 +++++++++++++++++++
 .../Compress/ImageCompressView.swift          | 18 +++--
 .../DocumentPreviewViewController.swift       | 14 ----
 .../ScannedItemPagerViewCell.swift            | 15 -----
 7 files changed, 107 insertions(+), 35 deletions(-)

diff --git a/MiniScanner/Core/Extensions/Image+Images.swift b/MiniScanner/Core/Extensions/Image+Images.swift
index f7242be..b793be4 100644
--- a/MiniScanner/Core/Extensions/Image+Images.swift
+++ b/MiniScanner/Core/Extensions/Image+Images.swift
@@ -23,4 +23,5 @@ extension Image {
     static let chevronBackward = Image(systemName: "chevron.backward")
     
     static let checkmark = Image(systemName: "checkmark")
+    static let xMark = Image(systemName: "xmark")
 }
diff --git a/MiniScanner/Features/Settings/Presentation/SettingsView.swift b/MiniScanner/Features/Settings/Presentation/SettingsView.swift
index 3150944..e350986 100644
--- a/MiniScanner/Features/Settings/Presentation/SettingsView.swift
+++ b/MiniScanner/Features/Settings/Presentation/SettingsView.swift
@@ -59,6 +59,10 @@ struct SettingsView: View {
                 screenSheet
                     .readSize(size: $viewModel.sheetSize)
             })
+            .fullScreenCover(isPresented: $viewModel.isImageCompresserPresented) {
+                ImageCompressView(isPresented: $viewModel.isImageCompresserPresented,
+                                  image: viewModel.image)
+            }
         }
     }
 }
@@ -88,6 +92,8 @@ extension SettingsView {
             fileType
             
             screenType
+            
+            compress
         }
     }
     
@@ -146,6 +152,12 @@ extension SettingsView {
                          items: viewModel.screens,
                          saveAction: viewModel.onScreenSaveClick)
     }
+    
+    private var compress: some View {
+        PrimaryButton(title: "Compress Image Tester",
+                      action: viewModel.onCompressClick)
+        .padding(.horizontal, 32)
+    }
 }
 
 #Preview {
diff --git a/MiniScanner/Features/Settings/Presentation/SettingsViewCoordinator.swift b/MiniScanner/Features/Settings/Presentation/SettingsViewCoordinator.swift
index 2d52efb..69d0f34 100644
--- a/MiniScanner/Features/Settings/Presentation/SettingsViewCoordinator.swift
+++ b/MiniScanner/Features/Settings/Presentation/SettingsViewCoordinator.swift
@@ -7,9 +7,12 @@
 //
 
 import Foundation
+import PhotosUI
 
 protocol SettingsViewCoordinating: MainCoordinator {
     var navigationController: UINavigationController { get set }
+    
+    func displayImagePicker(delegate: PHPickerViewControllerDelegate)
 }
 
 class SettingsViewCoordinator: SettingsViewCoordinating {
@@ -24,4 +27,17 @@ class SettingsViewCoordinator: SettingsViewCoordinating {
         let view = SettingsView(coordinator: self)
         coordinateToView(view, title: .settings.localized)
     }
+    
+    func displayImagePicker(delegate: PHPickerViewControllerDelegate) {
+        var configuration = PHPickerConfiguration()
+        configuration.selectionLimit = 1
+        configuration.filter = .images
+        let picker = PHPickerViewController(configuration: configuration)
+        
+        picker.delegate = delegate
+        
+        picker.modalPresentationStyle = .fullScreen
+        
+        navigationController.present(picker, animated: true, completion: nil)
+    }
 }
diff --git a/MiniScanner/Features/Settings/Presentation/SettingsViewModel.swift b/MiniScanner/Features/Settings/Presentation/SettingsViewModel.swift
index 6523d31..5a16e05 100644
--- a/MiniScanner/Features/Settings/Presentation/SettingsViewModel.swift
+++ b/MiniScanner/Features/Settings/Presentation/SettingsViewModel.swift
@@ -7,6 +7,7 @@
 //
 
 import SwiftUI
+import PhotosUI
 
 final class SettingsViewModel: MainViewModel {
     
@@ -45,6 +46,9 @@ final class SettingsViewModel: MainViewModel {
     @Published var isFileTypeSettingSheetPresented: Bool = false
     @Published var isScreenSettingSheetPresented: Bool = false
     
+    @Published var image: UIImage = UIImage()
+    @Published var isImageCompresserPresented: Bool = false
+    
     var selectedDefaultFileType: DefaultFileType {
         get {
             userSettings.defaultFileType
@@ -143,6 +147,10 @@ extension SettingsViewModel {
         
         hideScreenSheet()
     }
+    
+    func onCompressClick() {
+        coordinator.displayImagePicker(delegate: self)
+    }
 }
 
 extension SettingsViewModel {
@@ -178,6 +186,14 @@ extension SettingsViewModel {
     private func hideScreenSheet() {
         isScreenSettingSheetPresented = false
     }
+    
+    private func displayImageCompresser() {
+        isImageCompresserPresented = true
+    }
+    
+    private func hideImageCompresser() {
+        isImageCompresserPresented = false
+    }
 }
 
 extension SettingsViewModel {
@@ -236,3 +252,53 @@ extension SettingsViewModel {
         coordinator.coordinateBack()
     }
 }
+
+extension SettingsViewModel: PHPickerViewControllerDelegate {
+    
+    func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
+
+        picker.dismiss(animated: true) { [weak self] in
+            guard let self else { return }
+            
+            if results.count > 0 {
+                handlePHPickerResults(results: results)
+            }
+        }
+    }
+    
+    private func handlePHPickerResults(results: [PHPickerResult]) {
+        
+        var images: [UIImage] = []
+        
+        let dispatchGroup = DispatchGroup()
+        
+        for result in results {
+            
+            dispatchGroup.enter()  // Enter the group before each task
+            
+            result.itemProvider.loadObject(ofClass: UIImage.self) { (object, error) in
+                
+                defer { dispatchGroup.leave() } // Leave the group after each task, regardless of whether it was successful
+                
+                if let error = error {
+                    print("Error loading image: \(error)")
+                } else if let image = object as? UIImage {
+                    images.append(image)
+                }
+            }
+        }
+        
+        dispatchGroup.notify(queue: .main) { [weak self] in
+            guard let self else { return }
+            
+            handlePHPickerImages(images: images)
+        }
+    }
+    
+    private func handlePHPickerImages(images: [UIImage]) {
+        
+        self.image = images[0]
+        
+        displayImageCompresser()
+    }
+}
diff --git a/MiniScanner/Modules/DocumentPreview/Compress/ImageCompressView.swift b/MiniScanner/Modules/DocumentPreview/Compress/ImageCompressView.swift
index 7fdf858..9f220b2 100644
--- a/MiniScanner/Modules/DocumentPreview/Compress/ImageCompressView.swift
+++ b/MiniScanner/Modules/DocumentPreview/Compress/ImageCompressView.swift
@@ -11,20 +11,19 @@ import mozjpeg
 
 struct ImageCompressView: View {
     
+    @Binding var isPresented: Bool
     var image: UIImage
     
     var columns = [GridItem(.flexible()), GridItem(.flexible())]
     
     @State private var images: [[UIImage]] = Array(repeating: Array(repeating: UIImage(), count: 4), count: 4)
     
-    init(image: UIImage) {
-        self.image = image
-    }
-    
     var body: some View {
         ScrollView(showsIndicators: false) {
             
-            VStack(spacing: 16) {
+            VStack(alignment: .leading, spacing: 16) {
+                
+                close
                 
                 imagesGrid("") {
                     
@@ -77,6 +76,13 @@ struct ImageCompressView: View {
         }
     }
     
+    private var close: some View {
+        Button(action: { isPresented = false }, label: {
+            Image.xMark
+                .customForeground(.gray600)
+        })
+    }
+    
     private func prepareImages() async {
         
         images[0][0] = image
@@ -242,5 +248,5 @@ extension ImageCompressView {
 }
 
 #Preview {
-    ImageCompressView(image: .actions)
+    ImageCompressView(isPresented: .constant(true), image: .actions)
 }
diff --git a/MiniScanner/Modules/DocumentPreview/DocumentPreviewViewController.swift b/MiniScanner/Modules/DocumentPreview/DocumentPreviewViewController.swift
index bcbed4d..f639b31 100644
--- a/MiniScanner/Modules/DocumentPreview/DocumentPreviewViewController.swift
+++ b/MiniScanner/Modules/DocumentPreview/DocumentPreviewViewController.swift
@@ -363,20 +363,6 @@ extension DocumentPreviewViewController: ScannedItemPagerViewCellDelegate {
     func delete(at index: Int) {
         displayDeletePageDialog(at: index)
     }
-    
-    func compress(at index: Int) {
-        displayCompressImage(at: index)
-    }
-    
-    private func displayCompressImage(at index: Int) {
-        
-        if let image = session.scannedItems[index].newRenderedImage?.retrieveImage() {
-            
-            let imageCompressController = UIHostingController(rootView: ImageCompressView(image: image))
-            
-            present(imageCompressController, animated: true)
-        }
-    }
 }
 
 // MARK: - UIPrintInteractionControllerDelegate
diff --git a/MiniScanner/Modules/DocumentPreview/ScannedItemPagerViewCell.swift b/MiniScanner/Modules/DocumentPreview/ScannedItemPagerViewCell.swift
index 24bf44e..23e199e 100644
--- a/MiniScanner/Modules/DocumentPreview/ScannedItemPagerViewCell.swift
+++ b/MiniScanner/Modules/DocumentPreview/ScannedItemPagerViewCell.swift
@@ -12,7 +12,6 @@ protocol ScannedItemPagerViewCellDelegate: AnyObject {
     func delete(at: Int)
     func preview(at: Int)
     func select(at: Int)
-    func compress(at: Int)
 }
 
 class ScannedItemPagerViewCell: FSPagerViewCell {
@@ -54,8 +53,6 @@ class ScannedItemPagerViewCell: FSPagerViewCell {
         view.addArrangedSubview(preview)
         view.addArrangedSubview(trash)
         
-        view.addArrangedSubview(compress)
-        
         view.translatesAutoresizingMaskIntoConstraints = false
         
         return view
@@ -79,12 +76,6 @@ class ScannedItemPagerViewCell: FSPagerViewCell {
         return button
     }()
     
-    lazy var compress: UIButton = {
-        var button = getButton(image: .photoStack!)
-        button.addTarget(self, action: #selector(compressTapped), for: .touchUpInside)
-        return button
-    }()
-    
     func configure(with scannedItem: ScannedItem,
                    at index: Int,
                    delegate: ScannedItemPagerViewCellDelegate) {
@@ -137,12 +128,6 @@ extension ScannedItemPagerViewCell {
         }
     }
     
-    @objc private func compressTapped() {
-        if let index {
-            cellDelegate?.compress(at: index)
-        }
-    }
-    
     private func getButton(image: UIImage) -> UIButton {
         let button = UIButton(frame: CGRect(x: 0, y: 0, width: 24, height: 24))
         
-- 
GitLab