@@ -49,9 +49,11 @@ final class ChatFileService: ChatFileProtocol, Sendable {
49
49
private var fileDownloadAttemptsCount : [ String : Int ] = [ : ]
50
50
private var uploadingFilesDictionary : [ String : FileMessage ] = [ : ]
51
51
private var previewDownloadsAttemps : [ String : Int ] = [ : ]
52
- private var uploadTasks : [ String : Task < UploadFileResult , Error > ] = [ : ]
53
52
private let synchronizer = AsyncStreamSender < @MainActor ( ) -> Void > ( )
54
53
private let _updateFileFields = ObservableSender < FileUpdateProperties > ( )
54
+
55
+ // [messageId: [fileID: Task]] we can cancel all tasks for one message by messageId, uploading is managing by fileID
56
+ private var uploadTasks : [ String : [ String : Task < UploadFileResult , Error > ] ] = [ : ]
55
57
56
58
private var subscriptions = Set < AnyCancellable > ( )
57
59
private let maxDownloadAttemptsCount = 3
@@ -204,17 +206,24 @@ final class ChatFileService: ChatFileProtocol, Sendable {
204
206
return decodedData
205
207
}
206
208
207
- func cancelUpload( messageId: String , fileId: String ) async {
208
- if let task = uploadTasks [ fileId] {
209
+ func cancelUpload( messageId: String ) async {
210
+ guard let tasks = uploadTasks [ messageId] else { return }
211
+
212
+ var fileIdsToRemove : [ String ] = [ ]
213
+
214
+ for (fileId, task) in tasks {
209
215
task. cancel ( )
210
- uploadTasks [ fileId] = nil
211
216
uploadingFiles. removeAll { $0 == fileId }
212
- } else {
213
- await removeFromRichFile (
214
- oldId: fileId,
215
- txId: messageId
216
- )
217
+ fileIdsToRemove. append ( fileId)
217
218
}
219
+
220
+ await removeFilesFromRichFile (
221
+ oldIds: fileIdsToRemove,
222
+ txId: messageId
223
+ )
224
+
225
+ uploadTasks [ messageId] = nil
226
+ uploadingFilesDictionary [ messageId] = nil
218
227
}
219
228
220
229
func isDownloadPreviewLimitReached( for fileId: String ) -> Bool {
@@ -973,10 +982,13 @@ extension ChatFileService {
973
982
saveEncrypted: saveEncrypted
974
983
)
975
984
976
- uploadTasks [ file. url. absoluteString] = uploadTask
985
+ if uploadTasks [ txId] == nil {
986
+ uploadTasks [ txId] = [ : ]
987
+ }
988
+ uploadTasks [ txId] ? [ file. url. absoluteString] = uploadTask
977
989
978
990
defer {
979
- uploadTasks [ file. url. absoluteString] = nil
991
+ uploadTasks [ txId ] ? [ file. url. absoluteString] = nil
980
992
}
981
993
982
994
do {
@@ -1004,6 +1016,12 @@ extension ChatFileService {
1004
1016
txId: txId
1005
1017
)
1006
1018
} catch is CancellationError {
1019
+ guard let ( fileMessage, _) = uploadingFilesDictionary [ richMessageId: txId] ,
1020
+ fileMessage. files. contains ( where: { $0. file. url. absoluteString == file. url. absoluteString } )
1021
+ else {
1022
+ return
1023
+ }
1024
+
1007
1025
await removeFromRichFile (
1008
1026
oldId: file. url. absoluteString,
1009
1027
txId: txId
@@ -1134,9 +1152,41 @@ extension ChatFileService {
1134
1152
uploadingFilesDictionary [ txId] = fileMessage
1135
1153
1136
1154
if !updatedFiles. isEmpty {
1137
- // skip double update which causes bugs
1138
- // first update: here
1139
- // second update: if fileMessages is empty in sendFile method
1155
+ // skip double update which causes bugs
1156
+ // first update: here
1157
+ // second update: if fileMessages is empty in sendFile method
1158
+ try ? await chatsProvider. updateTxMessageContent (
1159
+ txId: txId,
1160
+ richMessage: richMessage
1161
+ )
1162
+ }
1163
+ }
1164
+
1165
+ fileprivate func removeFilesFromRichFile(
1166
+ oldIds: [ String ] ,
1167
+ txId: String
1168
+ ) async {
1169
+ oldIds. forEach { oldId in
1170
+ uploadingFiles. removeAll { $0 == oldId }
1171
+ }
1172
+
1173
+ guard var ( fileMessage, richMessage) = uploadingFilesDictionary [ richMessageId: txId]
1174
+ else { return }
1175
+
1176
+ richMessage. files = richMessage. files. filter { file in
1177
+ !oldIds. contains ( file. id)
1178
+ }
1179
+ fileMessage. adamantMessage = . richMessage( payload: richMessage)
1180
+
1181
+ let updatedFiles = fileMessage. files. filter { file in
1182
+ let url = file. file. url
1183
+ return !oldIds. contains ( url. absoluteString)
1184
+ }
1185
+
1186
+ fileMessage. files = updatedFiles
1187
+ uploadingFilesDictionary [ txId] = fileMessage
1188
+
1189
+ if !updatedFiles. isEmpty {
1140
1190
try ? await chatsProvider. updateTxMessageContent (
1141
1191
txId: txId,
1142
1192
richMessage: richMessage
0 commit comments