@@ -9,6 +9,7 @@ import Foundation
9
9
import Combine
10
10
import SwiftUI
11
11
import LiveViewNativeCore
12
+ import UniformTypeIdentifiers
12
13
13
14
/// The working-copy data model for a ``LiveView``.
14
15
///
@@ -35,6 +36,15 @@ public class LiveViewModel: ObservableObject {
35
36
func clearForms( ) {
36
37
self . forms. removeAll ( )
37
38
}
39
+
40
+ func fileUpload( id: String ) -> FormModel . FileUpload ? {
41
+ for (_, form) in forms {
42
+ guard let file = form. fileUploads. first ( where: { $0. id == id } )
43
+ else { continue }
44
+ return file
45
+ }
46
+ return nil
47
+ }
38
48
}
39
49
40
50
/// A form model stores the working copy of the data for a specific `<form>` element.
@@ -59,7 +69,12 @@ public class FormModel: ObservableObject, CustomDebugStringConvertible {
59
69
/// A publisher that emits a value before sending the form submission event.
60
70
var formWillSubmit = PassthroughSubject < ( ) , Never > ( )
61
71
62
- var fileUploads : [ ( ) async throws -> ( ) ] = [ ]
72
+ var fileUploads : [ FileUpload ] = [ ]
73
+ struct FileUpload {
74
+ let id : String
75
+ let data : Data
76
+ let upload : ( ) async throws -> ( )
77
+ }
63
78
64
79
init ( elementID: String ) {
65
80
self . elementID = elementID
@@ -99,10 +114,8 @@ public class FormModel: ObservableObject, CustomDebugStringConvertible {
99
114
public func sendSubmitEvent( ) async throws {
100
115
formWillSubmit. send ( ( ) )
101
116
for fileUpload in fileUploads {
102
- print ( " Upload... " )
103
- try await fileUpload ( )
117
+ try await fileUpload. upload ( )
104
118
}
105
- print ( " All uploads done " )
106
119
if let submitEvent = submitEvent {
107
120
try await pushFormEvent ( submitEvent)
108
121
} else if let submitAction {
@@ -229,6 +242,44 @@ public class FormModel: ObservableObject, CustomDebugStringConvertible {
229
242
data = [ : ]
230
243
}
231
244
245
+ public func queueFileUpload(
246
+ id: String ,
247
+ url: URL ,
248
+ coordinator: LiveViewCoordinator < some RootRegistry >
249
+ ) async throws {
250
+ return try await queueFileUpload (
251
+ id: id,
252
+ contents: try Data ( contentsOf: url) ,
253
+ fileType: UTType ( filenameExtension: url. pathExtension) !,
254
+ name: url. lastPathComponent,
255
+ coordinator: coordinator
256
+ )
257
+ }
258
+
259
+ public func queueFileUpload(
260
+ id: String ,
261
+ contents: Data ,
262
+ fileType: UTType ,
263
+ name: String ,
264
+ coordinator: LiveViewCoordinator < some RootRegistry >
265
+ ) async throws {
266
+ guard let liveChannel = coordinator. liveChannel
267
+ else { return }
268
+
269
+ let file = LiveFile (
270
+ contents,
271
+ fileType. preferredMIMEType!,
272
+ name,
273
+ id
274
+ )
275
+ let replyPayload = try await liveChannel. validateUpload ( file)
276
+ try await coordinator. handleEventReplyPayload ( replyPayload)
277
+ self . fileUploads. append ( . init(
278
+ id: id,
279
+ data: contents,
280
+ upload: { try await liveChannel. uploadFile ( file) }
281
+ ) )
282
+ }
232
283
}
233
284
234
285
private extension URLComponents {
0 commit comments