diff --git a/apps/ios/Shared/Views/Helpers/ImagePicker.swift b/apps/ios/Shared/Views/Helpers/ImagePicker.swift index 5bd16f693b..8c2b68b8bc 100644 --- a/apps/ios/Shared/Views/Helpers/ImagePicker.swift +++ b/apps/ios/Shared/Views/Helpers/ImagePicker.swift @@ -7,44 +7,102 @@ // import SwiftUI +import PhotosUI -struct ImagePicker: UIViewControllerRepresentable { - @Environment(\.presentationMode) var presentationMode - var source: UIImagePickerController.SourceType +enum ImageSource { + case imageLibrary + case camera +} + +struct LibraryImagePicker: UIViewControllerRepresentable { + typealias UIViewControllerType = PHPickerViewController @Binding var image: UIImage? - @Binding var imageUrl: URL? - - class Coordinator: NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate { - let parent: ImagePicker - - init(_ parent: ImagePicker) { + var didFinishPicking: (_ didSelectItems: Bool) -> Void + + class Coordinator: PHPickerViewControllerDelegate { + let parent: LibraryImagePicker + + init(_ parent: LibraryImagePicker) { self.parent = parent } - + + func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) { + parent.didFinishPicking(!results.isEmpty) + guard !results.isEmpty else { + return + } + + if let chosenImageProvider = results.first?.itemProvider { + if chosenImageProvider.canLoadObject(ofClass: UIImage.self) { + chosenImageProvider.loadObject(ofClass: UIImage.self) { [weak self] image, error in + DispatchQueue.main.async { + self?.loadImage(object: image, error: error) + } + } + } + } + } + + func loadImage(object: Any?, error: Error? = nil) { + if let error = error { + logger.error("Couldn't load image with error: \(error.localizedDescription)") + } + parent.image = object as? UIImage + } + } + + func makeCoordinator() -> Coordinator { + Coordinator(self) + } + + func makeUIViewController(context: Context) -> PHPickerViewController { + var config = PHPickerConfiguration() + config.filter = .images + config.selectionLimit = 1 + let controller = PHPickerViewController(configuration: config) + controller.delegate = context.coordinator + return controller + } + + func updateUIViewController(_ uiViewController: PHPickerViewController, context: Context) { + + } +} + + +struct CameraImagePicker: UIViewControllerRepresentable { + @Environment(\.presentationMode) var presentationMode + @Binding var image: UIImage? + + class Coordinator: NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate { + let parent: CameraImagePicker + + init(_ parent: CameraImagePicker) { + self.parent = parent + } + func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) { if let uiImage = info[.originalImage] as? UIImage { - parent.imageUrl = info[.imageURL] as? URL parent.image = uiImage } parent.presentationMode.wrappedValue.dismiss() } } - + func makeCoordinator() -> Coordinator { Coordinator(self) } - - func makeUIViewController(context: UIViewControllerRepresentableContext) -> UIImagePickerController { + func makeUIViewController(context: UIViewControllerRepresentableContext) -> UIImagePickerController { let picker = UIImagePickerController() - picker.sourceType = source + picker.sourceType = .camera picker.allowsEditing = false picker.delegate = context.coordinator return picker } - func updateUIViewController(_ uiViewController: UIImagePickerController, context: UIViewControllerRepresentableContext) { - + func updateUIViewController(_ uiViewController: UIImagePickerController, context: UIViewControllerRepresentableContext) { + } } diff --git a/apps/ios/Shared/Views/UserSettings/UserProfile.swift b/apps/ios/Shared/Views/UserSettings/UserProfile.swift index 4e5d62bf31..df2e64c4ba 100644 --- a/apps/ios/Shared/Views/UserSettings/UserProfile.swift +++ b/apps/ios/Shared/Views/UserSettings/UserProfile.swift @@ -14,9 +14,8 @@ struct UserProfile: View { @State private var editProfile = false @State private var showChooseSource = false @State private var showImagePicker = false - @State private var imageSource: UIImagePickerController.SourceType = .photoLibrary - @State private var pickedImage: UIImage? = nil - @State private var tmpImageUrl: URL? = nil + @State private var imageSource: ImageSource = .imageLibrary + @State private var chosenImage: UIImage? = nil var body: some View { let user: User = chatModel.currentUser! @@ -84,14 +83,21 @@ struct UserProfile: View { showImagePicker = true } Button("Choose from library") { - imageSource = .photoLibrary + imageSource = .imageLibrary showImagePicker = true } } .sheet(isPresented: $showImagePicker) { - ImagePicker(source: imageSource, image: $pickedImage, imageUrl: $tmpImageUrl) + switch imageSource { + case .imageLibrary: + LibraryImagePicker(image: $chosenImage) { + didSelectItem in showImagePicker = false + } + case .camera: + CameraImagePicker(image: $chosenImage) + } } - .onChange(of: pickedImage) { image in + .onChange(of: chosenImage) { image in if let image = image, let data = resizeToSquare(image, 104).jpegData(compressionQuality: 0.85) { let imageStr = "data:image/jpg;base64,\(data.base64EncodedString())" @@ -100,13 +106,6 @@ struct UserProfile: View { } else { logger.error("UserProfile: resized image is too big \(imageStr.count)") } - if let tmpImageUrl = tmpImageUrl { - do { - try FileManager.default.removeItem(at: tmpImageUrl) - } catch { - logger.error("UserProfile: file deletion error \(error.localizedDescription)") - } - } } else { profile.image = nil }