@@ -11,10 +11,10 @@ struct TodoListView: View {
1111 @State private var newTodo : NewTodo ?
1212 @State private var editing : Bool = false
1313
14- @State private var selectedImage : UIImage ?
1514 // Called when a photo has been captured. Individual widgets should register the listener
16- @State private var onPhotoCapture : ( ( _: Data ) async throws -> Void ) ?
17- @State private var showCamera = false
15+ @State private var onMediaSelect : ( ( _: Data ) async throws -> Void ) ?
16+ @State private var pickMediaType : UIImagePickerController . SourceType = . camera
17+ @State private var showMediaPicker = false
1818
1919 var body : some View {
2020 List {
@@ -56,25 +56,14 @@ struct TodoListView: View {
5656
5757 } ,
5858 capturePhotoTapped: {
59- showCamera = true
60- // Register a callback for successful image capture
61- onPhotoCapture = { ( _ fileData: Data ) in
62- guard let attachments = system. attachments
63- else {
64- return
65- }
66-
67- try await attachments. saveFile (
68- data: fileData,
69- mediaType: " image/jpeg " ,
70- fileExtension: " jpg "
71- ) { tx, record in
72- _ = try tx. execute (
73- sql: " UPDATE \( TODOS_TABLE) SET photo_id = ? WHERE id = ? " ,
74- parameters: [ record. id, todo. id]
75- )
76- }
77- }
59+ registerMediaCallback ( todo: todo)
60+ pickMediaType = . camera
61+ showMediaPicker = true
62+ } ,
63+ selectPhotoTapped: {
64+ registerMediaCallback ( todo: todo)
65+ pickMediaType = . photoLibrary
66+ showMediaPicker = true
7867 }
7968 )
8069 }
@@ -84,8 +73,11 @@ struct TodoListView: View {
8473 }
8574 }
8675 }
87- . sheet ( isPresented: $showCamera) {
88- CameraView ( onPhotoCapture: $onPhotoCapture)
76+ . sheet ( isPresented: $showMediaPicker) {
77+ CameraView (
78+ onMediaSelect: $onMediaSelect,
79+ mediaType: $pickMediaType
80+ )
8981 }
9082 . animation ( . default, value: todos)
9183 . navigationTitle ( " Todos " )
@@ -143,6 +135,32 @@ struct TodoListView: View {
143135 self . error = error
144136 }
145137 }
138+
139+ /// Registers a callback which saves a photo for the specified Todo item if media is sucessfully loaded.
140+ func registerMediaCallback( todo: Todo ) {
141+ // Register a callback for successful image capture
142+ onMediaSelect = { ( _ fileData: Data ) in
143+ guard let attachments = system. attachments
144+ else {
145+ return
146+ }
147+
148+ do {
149+ try await attachments. saveFile (
150+ data: fileData,
151+ mediaType: " image/jpeg " ,
152+ fileExtension: " jpg "
153+ ) { tx, record in
154+ _ = try tx. execute (
155+ sql: " UPDATE \( TODOS_TABLE) SET photo_id = ? WHERE id = ? " ,
156+ parameters: [ record. id, todo. id]
157+ )
158+ }
159+ } catch {
160+ self . error = error
161+ }
162+ }
163+ }
146164}
147165
148166#Preview {
@@ -154,13 +172,15 @@ struct TodoListView: View {
154172}
155173
156174struct CameraView : UIViewControllerRepresentable {
157- @Binding var onPhotoCapture : ( ( _: Data ) async throws -> Void ) ?
175+ @Binding var onMediaSelect : ( ( _: Data ) async throws -> Void ) ?
176+ @Binding var mediaType : UIImagePickerController . SourceType
177+
158178 @Environment ( \. presentationMode) var presentationMode
159179
160180 func makeUIViewController( context: Context ) -> UIImagePickerController {
161181 let picker = UIImagePickerController ( )
162182 picker. delegate = context. coordinator
163- picker. sourceType = . camera
183+ picker. sourceType = mediaType
164184 return picker
165185 }
166186
@@ -181,11 +201,12 @@ struct CameraView: UIViewControllerRepresentable {
181201 if let image = info [ . originalImage] as? UIImage {
182202 // Convert UIImage to Data
183203 if let jpegData = image. jpegData ( compressionQuality: 0.8 ) {
184- if let photoCapture = parent. onPhotoCapture {
204+ if let photoCapture = parent. onMediaSelect {
185205 Task {
186206 do {
187207 try await photoCapture ( jpegData)
188208 } catch {
209+ // The photoCapture method should handle errors
189210 print ( " Error saving photo: \( error) " )
190211 }
191212 }
0 commit comments