@@ -7,15 +7,23 @@ import _PhotosUI_SwiftUI
77
88@MainActor
99final class ChatAttachmentState {
10-
11- nonisolated init ( ) { }
10+
11+ @Injected ( \. fileActionsService)
12+ private var fileActionsService : any FileActionsServiceProtocol
1213
1314 private let linkedObjectsSubject = CurrentValueSubject < [ ChatLinkedObject ] , Never > ( [ ] )
1415 private let attachmentsDownloadingSubject = CurrentValueSubject < Bool , Never > ( false )
1516 private let photosItemsTaskSubject = CurrentValueSubject < UUID , Never > ( UUID ( ) )
1617 private var linkPreviewTasks : [ URL : AnyCancellable ] = [ : ]
18+ private var preloadTasks : [ Int : Task < Void , Never > ] = [ : ]
1719 private var photosItems : [ PhotosPickerItem ] = [ ]
1820
21+ let spaceId : String
22+
23+ nonisolated init ( spaceId: String ) {
24+ self . spaceId = spaceId
25+ }
26+
1927 var linkedObjectsPublisher : AnyPublisher < [ ChatLinkedObject ] , Never > {
2028 linkedObjectsSubject. eraseToAnyPublisher ( )
2129 }
@@ -36,29 +44,6 @@ final class ChatAttachmentState {
3644 linkedObjectsSubject. send ( objects)
3745 }
3846
39- func addLinkedObject( _ object: ChatLinkedObject ) {
40- var current = linkedObjectsSubject. value
41- current. append ( object)
42- linkedObjectsSubject. send ( current)
43- }
44-
45- func removeLinkedObject( with id: Int ) {
46- var current = linkedObjectsSubject. value
47- current. removeAll { $0. id == id }
48- linkedObjectsSubject. send ( current)
49- }
50-
51- func updateLinkedObject( at index: Int , with object: ChatLinkedObject ) {
52- var current = linkedObjectsSubject. value
53- guard index < current. count else { return }
54- current [ index] = object
55- linkedObjectsSubject. send ( current)
56- }
57-
58- func clearAllLinkedObjects( ) {
59- linkedObjectsSubject. send ( [ ] )
60- }
61-
6247 func setAttachmentsDownloading( _ downloading: Bool ) {
6348 attachmentsDownloadingSubject. send ( downloading)
6449 }
@@ -75,11 +60,6 @@ final class ChatAttachmentState {
7560 linkPreviewTasks [ url] = nil
7661 }
7762
78- func cancelAllLinkPreviewTasks( ) {
79- linkPreviewTasks. values. forEach { $0. cancel ( ) }
80- linkPreviewTasks. removeAll ( )
81- }
82-
8363 func hasLinkPreviewTask( for url: URL ) -> Bool {
8464 return linkPreviewTasks [ url] != nil
8565 }
@@ -96,7 +76,109 @@ final class ChatAttachmentState {
9676 photosItems. removeAll ( where: predicate)
9777 }
9878
99- func clearPhotosItems( ) {
79+ func clearState( ) {
80+ preloadTasks. values. forEach { $0. cancel ( ) }
81+ preloadTasks. removeAll ( )
82+
83+ discardPreloadedFiles ( linkedObjects. compactMap { $0. preloadFileId } )
84+
85+ linkedObjectsSubject. send ( [ ] )
86+
87+ linkPreviewTasks. values. forEach { $0. cancel ( ) }
88+ linkPreviewTasks. removeAll ( )
89+
10090 photosItems = [ ]
91+
92+ updatePhotosItemsTask ( )
93+ }
94+
95+ func addLinkedObject( _ linkedObject: ChatLinkedObject ) {
96+ storeLinkedObject ( linkedObject)
97+ startPreload ( linkedObject: linkedObject)
98+ }
99+
100+ func updateLinkedObject( at index: Int , with linkedObject: ChatLinkedObject ) {
101+ updateLinkedObjectStorage ( at: index, with: linkedObject)
102+ startPreload ( linkedObject: linkedObject)
103+ }
104+
105+ func removeLinkedObject( with id: Int ) {
106+ if let objectToRemove = linkedObjects. first ( where: { $0. id == id } ) {
107+ discardPreloadedFile ( from: objectToRemove)
108+ }
109+ removeLinkedObjectFromStorage ( with: id)
110+ }
111+
112+ private func storeLinkedObject( _ object: ChatLinkedObject ) {
113+ var current = linkedObjectsSubject. value
114+ current. append ( object)
115+ linkedObjectsSubject. send ( current)
116+ }
117+
118+ private func updateLinkedObjectStorage( at index: Int , with object: ChatLinkedObject ) {
119+ var current = linkedObjectsSubject. value
120+ guard index < current. count else { return }
121+ current [ index] = object
122+ linkedObjectsSubject. send ( current)
123+ }
124+
125+ private func removeLinkedObjectFromStorage( with id: Int ) {
126+ var current = linkedObjectsSubject. value
127+ current. removeAll { $0. id == id }
128+ linkedObjectsSubject. send ( current)
129+ }
130+
131+ private func startPreload( linkedObject: ChatLinkedObject ) {
132+ guard let data = linkedObject. fileData else { return }
133+
134+ let task = Task { [ weak self, fileActionsService, spaceId] in
135+ if let preloadFileId = try ? await fileActionsService. preloadFileObject ( spaceId: spaceId, data: data, origin: . none) {
136+ self ? . updatePreloadFileId ( for: linkedObject. id, preloadFileId: preloadFileId)
137+ }
138+ self? . removePreloadTask ( objectId: linkedObject. id)
139+ }
140+
141+ addPreloadTask( objectId: linkedObject. id, task: task)
142+ }
143+
144+ private func updatePreloadFileId( for objectId: Int, preloadFileId: String) {
145+ var linkedObjects = linkedObjectsSubject. value
146+ guard let index = linkedObjects. firstIndex ( where: { $0. id == objectId } ) else { return }
147+
148+ switch linkedObjects [ index] {
149+ case . localPhotosFile( var file) :
150+ file. data? . preloadFileId = preloadFileId
151+ linkedObjects [ index] = . localPhotosFile( file)
152+ case . localBinaryFile( var file) :
153+ file. preloadFileId = preloadFileId
154+ linkedObjects [ index] = . localBinaryFile( file)
155+ default :
156+ return
157+ }
158+
159+ linkedObjectsSubject. send ( linkedObjects)
160+ }
161+
162+ private func addPreloadTask( objectId: Int , task: Task < Void , Never > ) {
163+ removePreloadTask ( objectId: objectId)
164+ preloadTasks [ objectId] = task
165+ }
166+
167+ private func removePreloadTask( objectId: Int ) {
168+ preloadTasks [ objectId] ? . cancel ( )
169+ preloadTasks [ objectId] = nil
170+ }
171+
172+ private func discardPreloadedFile( from linkedObject: ChatLinkedObject ) {
173+ guard let preloadFileId = linkedObject. preloadFileId else { return }
174+ discardPreloadedFiles ( [ preloadFileId] )
175+ }
176+
177+ private func discardPreloadedFiles( _ preloadFileIds: [ String ] ) {
178+ for preloadFileId in preloadFileIds {
179+ Task {
180+ try await fileActionsService. discardPreloadFile ( fileId: preloadFileId, spaceId: spaceId)
181+ }
182+ }
101183 }
102184}
0 commit comments