jellyflood/Swiftfin/Views/PhotoPickerView/PhotoPickerView.swift

87 lines
2.5 KiB
Swift

//
// Swiftfin is subject to the terms of the Mozilla Public
// License, v2.0. If a copy of the MPL was not distributed with this
// file, you can obtain one at https://mozilla.org/MPL/2.0/.
//
// Copyright (c) 2025 Jellyfin & Jellyfin Contributors
//
import PhotosUI
import SwiftUI
// TODO: polish: find way to deselect image on appear
// - from popping from cropping
// TODO: polish: when image is picked, instead of loading it here
// which takes ~1-2s, show some kind of loading indicator
// on this view or push to another view that will go to crop
struct PhotoPickerView: UIViewControllerRepresentable {
// MARK: - Photo Picker Actions
var onSelect: (UIImage) -> Void
var onCancel: () -> Void
// MARK: - Initializer
init(onSelect: @escaping (UIImage) -> Void, onCancel: @escaping () -> Void) {
self.onSelect = onSelect
self.onCancel = onCancel
}
// MARK: - UIView Controller
func makeUIViewController(context: Context) -> PHPickerViewController {
var configuration = PHPickerConfiguration(photoLibrary: .shared())
configuration.filter = .all(of: [.images, .not(.livePhotos)])
configuration.preferredAssetRepresentationMode = .current
configuration.selection = .default
configuration.selectionLimit = 1
let picker = PHPickerViewController(configuration: configuration)
picker.delegate = context.coordinator
context.coordinator.onSelect = onSelect
context.coordinator.onCancel = onCancel
return picker
}
// MARK: - Update UIView Controller
func updateUIViewController(_ uiViewController: PHPickerViewController, context: Context) {}
// MARK: - Make Coordinator
func makeCoordinator() -> Coordinator {
Coordinator()
}
// MARK: - Coordinator
class Coordinator: PHPickerViewControllerDelegate {
var onSelect: ((UIImage) -> Void)?
var onCancel: (() -> Void)?
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
guard let image = results.first else {
onCancel?()
return
}
let itemProvider = image.itemProvider
guard itemProvider.canLoadObject(ofClass: UIImage.self) else { return }
itemProvider.loadObject(ofClass: UIImage.self) { image, _ in
guard let image = image as? UIImage else { return }
self.onSelect?(image)
}
}
}
}