diff --git a/MiniScanner/Core/Extensions/Image+Images.swift b/MiniScanner/Core/Extensions/Image+Images.swift index f7242bed3f11f085156f3767931c4d95c57f8f13..b793be47722e8ea52ec1943a11d891865e5711f4 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 315094405f7f049c99356eec1e5dffc6b3b7234b..e35098626a5feba3251e46a1d549c96c7249f2c1 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 2d52efbcd9a8a3dbe99a3d779e4a092d04d01638..69d0f344edee99ebc881a449bbe77e914d2f00bd 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 6523d31dbee664d03e3a104a186bcf1e80967472..5a16e0536e4d5748b01ab0304b20fdaf50f02357 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 7fdf858c30a73f51eb29c72144e24daad5e48e41..9f220b2dc2695863271ef858a0f1410851b6747e 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 bcbed4d43bfe56e8a9f2098751a220110cca5db2..f639b31884e11185cb3c9ff2ed86b0b514035d01 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 24bf44e5a67f9798bac98de4403a8ce69ba83c7a..23e199e71d10e984364497731d34486218e893bf 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))