05/04 Update the app functionalities
This commit is contained in:
@@ -12,6 +12,7 @@
|
||||
|
||||
import SwiftUI
|
||||
import PencilKit
|
||||
import PhotosUI
|
||||
|
||||
// MARK: - FormFieldView
|
||||
// Retained for standalone/legacy usage outside the grid inspection form.
|
||||
@@ -420,8 +421,14 @@ struct ImageFieldView: View {
|
||||
let currentValue: String
|
||||
var onPhotoSelected: ((String) -> Void)?
|
||||
|
||||
@State private var showPicker = false
|
||||
@State private var selectedImage: UIImage?
|
||||
@State private var showChoice = false
|
||||
@State private var showCamera = false
|
||||
@State private var showLibrary = false
|
||||
|
||||
private var cameraAvailable: Bool {
|
||||
UIImagePickerController.isSourceTypeAvailable(.camera)
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .leading, spacing: 10) {
|
||||
@@ -445,7 +452,7 @@ struct ImageFieldView: View {
|
||||
}
|
||||
|
||||
Button {
|
||||
showPicker = true
|
||||
if cameraAvailable { showChoice = true } else { showLibrary = true }
|
||||
} label: {
|
||||
Label(
|
||||
selectedImage != nil || currentValue.hasPrefix("uploads/")
|
||||
@@ -459,10 +466,17 @@ struct ImageFieldView: View {
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
}
|
||||
.sheet(isPresented: $showPicker) {
|
||||
ImagePickerView(image: $selectedImage) { img in
|
||||
saveAndCallback(img)
|
||||
}
|
||||
.confirmationDialog("Add Photo", isPresented: $showChoice, titleVisibility: .visible) {
|
||||
Button("Take Photo") { showCamera = true }
|
||||
Button("Photo Library") { showLibrary = true }
|
||||
Button("Cancel", role: .cancel) {}
|
||||
}
|
||||
.fullScreenCover(isPresented: $showCamera) {
|
||||
CameraPickerView(image: $selectedImage, onSelected: saveAndCallback)
|
||||
.ignoresSafeArea()
|
||||
}
|
||||
.sheet(isPresented: $showLibrary) {
|
||||
LibraryPickerView(image: $selectedImage, onSelected: saveAndCallback)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -480,16 +494,24 @@ struct ImageFieldView: View {
|
||||
}
|
||||
|
||||
// MARK: - ImagePickerView
|
||||
// Retained as a thin typealias so existing call sites that reference
|
||||
// ImagePickerView(image:onSelected:) continue to compile without changes.
|
||||
// Internally it now just shows the library picker directly — callers that
|
||||
// need the camera+library choice should use the inline pattern in ImageFieldView.
|
||||
// NOTE: FlagIssueView and CompactImageFieldView have been updated to use
|
||||
// the inline confirmationDialog pattern instead.
|
||||
typealias ImagePickerView = LibraryPickerView
|
||||
|
||||
struct ImagePickerView: UIViewControllerRepresentable {
|
||||
// ── Camera — UIImagePickerController with .camera source ─────────────────────
|
||||
|
||||
struct CameraPickerView: UIViewControllerRepresentable {
|
||||
@Binding var image: UIImage?
|
||||
var onSelected: (UIImage) -> Void
|
||||
|
||||
func makeUIViewController(context: Context) -> UIImagePickerController {
|
||||
let picker = UIImagePickerController()
|
||||
let picker = UIImagePickerController()
|
||||
picker.sourceType = .camera
|
||||
picker.delegate = context.coordinator
|
||||
picker.sourceType = UIImagePickerController.isSourceTypeAvailable(.camera)
|
||||
? .camera : .photoLibrary
|
||||
return picker
|
||||
}
|
||||
|
||||
@@ -497,8 +519,8 @@ struct ImagePickerView: UIViewControllerRepresentable {
|
||||
func makeCoordinator() -> Coordinator { Coordinator(self) }
|
||||
|
||||
class Coordinator: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
|
||||
let parent: ImagePickerView
|
||||
init(_ parent: ImagePickerView) { self.parent = parent }
|
||||
let parent: CameraPickerView
|
||||
init(_ parent: CameraPickerView) { self.parent = parent }
|
||||
|
||||
func imagePickerController(
|
||||
_ picker: UIImagePickerController,
|
||||
@@ -517,6 +539,45 @@ struct ImagePickerView: UIViewControllerRepresentable {
|
||||
}
|
||||
}
|
||||
|
||||
// ── Photo Library — PHPickerViewController (no permission required) ───────────
|
||||
|
||||
struct LibraryPickerView: UIViewControllerRepresentable {
|
||||
@Binding var image: UIImage?
|
||||
var onSelected: (UIImage) -> Void
|
||||
|
||||
func makeUIViewController(context: Context) -> PHPickerViewController {
|
||||
var config = PHPickerConfiguration()
|
||||
config.filter = .images
|
||||
config.selectionLimit = 1
|
||||
let picker = PHPickerViewController(configuration: config)
|
||||
picker.delegate = context.coordinator
|
||||
return picker
|
||||
}
|
||||
|
||||
func updateUIViewController(_ vc: PHPickerViewController, context: Context) {}
|
||||
func makeCoordinator() -> Coordinator { Coordinator(self) }
|
||||
|
||||
class Coordinator: NSObject, PHPickerViewControllerDelegate {
|
||||
let parent: LibraryPickerView
|
||||
init(_ parent: LibraryPickerView) { self.parent = parent }
|
||||
|
||||
func picker(_ picker: PHPickerViewController,
|
||||
didFinishPicking results: [PHPickerResult]) {
|
||||
picker.dismiss(animated: true)
|
||||
guard let provider = results.first?.itemProvider,
|
||||
provider.canLoadObject(ofClass: UIImage.self) else { return }
|
||||
provider.loadObject(ofClass: UIImage.self) { object, _ in
|
||||
DispatchQueue.main.async {
|
||||
if let img = object as? UIImage {
|
||||
self.parent.image = img
|
||||
self.parent.onSelected(img)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - TableFieldView
|
||||
|
||||
struct TableFieldView: View {
|
||||
|
||||
Reference in New Issue
Block a user