mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-05-15 10:17:08 +00:00
ios: update image picker (#495)
* switch to PHPicker for photos. TODO add back camera functionality. [rough] * add back camera selection option * remove force unwrap of optional * response to comments * rerun tests * refactor naming
This commit is contained in:
@@ -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<ImagePicker>) -> UIImagePickerController {
|
||||
func makeUIViewController(context: UIViewControllerRepresentableContext<CameraImagePicker>) -> 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<ImagePicker>) {
|
||||
|
||||
func updateUIViewController(_ uiViewController: UIImagePickerController, context: UIViewControllerRepresentableContext<CameraImagePicker>) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user