diff --git a/lib/src/database/database_api.dart b/lib/src/database/database_api.dart index d8bc3cf4..893d674a 100644 --- a/lib/src/database/database_api.dart +++ b/lib/src/database/database_api.dart @@ -116,6 +116,8 @@ abstract class DatabaseApi { Future storeFile(Uri mxcUri, Uint8List bytes, int time); + Future deleteFile(Uri mxcUri); + Future storeSyncFilterId( String syncFilterId, ); diff --git a/lib/src/database/database_file_storage_io.dart b/lib/src/database/database_file_storage_io.dart index 6a80efd7..5e9dfb83 100644 --- a/lib/src/database/database_file_storage_io.dart +++ b/lib/src/database/database_file_storage_io.dart @@ -33,6 +33,20 @@ mixin DatabaseFileStorage { return null; } + Future deleteFile(Uri mxcUri) async { + final fileStorageLocation = this.fileStorageLocation; + if (!supportsFileStoring || fileStorageLocation == null) return false; + + final dir = Directory.fromUri(fileStorageLocation); + + final file = File('${dir.path}/${mxcUri.toString().split('/').last}'); + + if (await file.exists() == false) return false; + + await file.delete(); + return true; + } + Future deleteOldFiles(int savedAt) async { final dirUri = fileStorageLocation; final deleteFilesAfterDuration = this.deleteFilesAfterDuration; diff --git a/lib/src/database/database_file_storage_stub.dart b/lib/src/database/database_file_storage_stub.dart index 7addfe1a..1aa9b101 100644 --- a/lib/src/database/database_file_storage_stub.dart +++ b/lib/src/database/database_file_storage_stub.dart @@ -17,4 +17,6 @@ mixin DatabaseFileStorage { Future deleteOldFiles(int savedAt) async { return; } + + Future deleteFile(Uri mxcUri) async => false; } diff --git a/lib/src/database/hive_collections_database.dart b/lib/src/database/hive_collections_database.dart index 80b98d93..b86ecd6b 100644 --- a/lib/src/database/hive_collections_database.dart +++ b/lib/src/database/hive_collections_database.dart @@ -453,6 +453,11 @@ class HiveCollectionsDatabase extends DatabaseApi { return null; } + @override + Future deleteFile(Uri mxcUri) async { + return false; + } + @override Future getInboundGroupSession( String roomId, diff --git a/lib/src/database/hive_database.dart b/lib/src/database/hive_database.dart index 8086d7f3..116abae0 100644 --- a/lib/src/database/hive_database.dart +++ b/lib/src/database/hive_database.dart @@ -461,6 +461,11 @@ class FamedlySdkHiveDatabase extends DatabaseApi with ZoneTransactionMixin { return null; } + @override + Future deleteFile(Uri mxcUri) async { + return false; + } + @override Future getInboundGroupSession( String roomId, diff --git a/lib/src/event.dart b/lib/src/event.dart index 10688fdf..6a7d739b 100644 --- a/lib/src/event.dart +++ b/lib/src/event.dart @@ -403,12 +403,29 @@ class Event extends MatrixEvent { MessageTypes.Audio, MessageTypes.File, }.contains(messageType)) { - final file = room.sendingFilePlaceholders[eventId]; + final bytes = await room.client.database?.getFile( + Uri.parse('com.famedly.sendingAttachment://file/$eventId'), + ); + final file = bytes == null + ? null + : MatrixFile( + bytes: bytes, + name: content.tryGet('filename') ?? 'image', + ); if (file == null) { await cancelSend(); throw Exception('Can not try to send again. File is no longer cached.'); } - final thumbnail = room.sendingFileThumbnails[eventId]; + final thumbnailBytes = await room.client.database?.getFile( + Uri.parse('com.famedly.sendingAttachment://thumbnail/$txid'), + ); + final thumbnail = thumbnailBytes == null + ? null + : MatrixImageFile( + bytes: thumbnailBytes, + name: + 'thumbnail_${content.tryGet('filename') ?? 'image'}', + ); final credentials = FileSendRequestCredentials.fromJson(unsigned ?? {}); final inReplyTo = credentials.inReplyTo == null ? null @@ -688,7 +705,15 @@ class Event extends MatrixEvent { throw ("This event has the type '$type' and so it can't contain an attachment."); } if (status.isSending) { - final localFile = room.sendingFilePlaceholders[eventId]; + final bytes = await room.client.database?.getFile( + Uri.parse('com.famedly.sendingAttachment://file/$eventId'), + ); + final localFile = bytes == null + ? null + : MatrixImageFile( + bytes: bytes, + name: content.tryGet('filename') ?? 'image', + ); if (localFile != null) return localFile; } final database = room.client.database; diff --git a/lib/src/room.dart b/lib/src/room.dart index bdef55e4..1e974427 100644 --- a/lib/src/room.dart +++ b/lib/src/room.dart @@ -665,9 +665,6 @@ class Room { return sendEvent(event, txid: txid); } - final Map sendingFilePlaceholders = {}; - final Map sendingFileThumbnails = {}; - /// Sends a [file] to this room after uploading it. Returns the mxc uri of /// the uploaded file. If [waitUntilSent] is true, the future will wait until /// the message event has received the server. Otherwise the future will only @@ -691,10 +688,6 @@ class Room { String? threadLastEventId, }) async { txid ??= client.generateUniqueTransactionId(); - sendingFilePlaceholders[txid] = file; - if (thumbnail != null) { - sendingFileThumbnails[txid] = thumbnail; - } // Create a fake Event object as a placeholder for the uploading file: final syncUpdate = SyncUpdate( @@ -731,6 +724,22 @@ class Room { }, ), ); + await _handleFakeSync(syncUpdate); + + if (client.database?.supportsFileStoring == true) { + await client.database?.storeFile( + Uri.parse('com.famedly.sendingAttachment://file/$txid'), + file.bytes, + DateTime.now().millisecondsSinceEpoch, + ); + if (thumbnail != null) { + await client.database?.storeFile( + Uri.parse('com.famedly.sendingAttachment://thumbnail/$txid'), + file.bytes, + DateTime.now().millisecondsSinceEpoch, + ); + } + } MatrixFile uploadFile = file; // ignore: omit_local_variable_types // computing the thumbnail in case we can @@ -816,12 +825,22 @@ class Room { syncUpdate.rooms!.join!.values.first.timeline!.events!.first .unsigned![messageSendingStatusKey] = EventStatus.error.intValue; await _handleFakeSync(syncUpdate); + + if (client.database?.supportsFileStoring != true) { + final sendEvent = await getEventById(txid); + await sendEvent?.cancelSend(); + } rethrow; } catch (_) { if (DateTime.now().isAfter(timeoutDate)) { syncUpdate.rooms!.join!.values.first.timeline!.events!.first .unsigned![messageSendingStatusKey] = EventStatus.error.intValue; await _handleFakeSync(syncUpdate); + + if (client.database?.supportsFileStoring != true) { + final sendEvent = await getEventById(txid); + await sendEvent?.cancelSend(); + } rethrow; } Logs().v('Send File into room failed. Try again...'); @@ -885,8 +904,13 @@ class Room { threadRootEventId: threadRootEventId, threadLastEventId: threadLastEventId, ); - sendingFilePlaceholders.remove(txid); - sendingFileThumbnails.remove(txid); + await client.database?.deleteFile( + Uri.parse('com.famedly.sendingAttachment://file/$txid'), + ); + await client.database?.deleteFile( + Uri.parse('com.famedly.sendingAttachment://thumbnail/$txid'), + ); + return eventId; }