Skip to content

Commit be2fc89

Browse files
committed
feat: Store sending attachment in temporary file storage
This could make retrying to send files more easy as the file is stored in the file storage. This just replaces the current approach to store the file in the memory instead so they are gone on the next session. For this we need a deleteFile() method for the database.
1 parent b6945e7 commit be2fc89

File tree

7 files changed

+89
-12
lines changed

7 files changed

+89
-12
lines changed

lib/src/database/database_api.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,8 @@ abstract class DatabaseApi {
116116

117117
Future storeFile(Uri mxcUri, Uint8List bytes, int time);
118118

119+
Future<bool> deleteFile(Uri mxcUri);
120+
119121
Future storeSyncFilterId(
120122
String syncFilterId,
121123
);

lib/src/database/database_file_storage_io.dart

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,20 @@ mixin DatabaseFileStorage {
3333
return null;
3434
}
3535

36+
Future<bool> deleteFile(Uri mxcUri) async {
37+
final fileStorageLocation = this.fileStorageLocation;
38+
if (!supportsFileStoring || fileStorageLocation == null) return false;
39+
40+
final dir = Directory.fromUri(fileStorageLocation);
41+
42+
final file = File('${dir.path}/${mxcUri.toString().split('/').last}');
43+
44+
if (await file.exists() == false) return false;
45+
46+
await file.delete();
47+
return true;
48+
}
49+
3650
Future<void> deleteOldFiles(int savedAt) async {
3751
final dirUri = fileStorageLocation;
3852
final deleteFilesAfterDuration = this.deleteFilesAfterDuration;

lib/src/database/database_file_storage_stub.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,6 @@ mixin DatabaseFileStorage {
1717
Future<void> deleteOldFiles(int savedAt) async {
1818
return;
1919
}
20+
21+
Future<bool> deleteFile(Uri mxcUri) async => false;
2022
}

lib/src/database/hive_collections_database.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,11 @@ class HiveCollectionsDatabase extends DatabaseApi {
453453
return null;
454454
}
455455

456+
@override
457+
Future<bool> deleteFile(Uri mxcUri) async {
458+
return false;
459+
}
460+
456461
@override
457462
Future<StoredInboundGroupSession?> getInboundGroupSession(
458463
String roomId,

lib/src/database/hive_database.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,11 @@ class FamedlySdkHiveDatabase extends DatabaseApi with ZoneTransactionMixin {
461461
return null;
462462
}
463463

464+
@override
465+
Future<bool> deleteFile(Uri mxcUri) async {
466+
return false;
467+
}
468+
464469
@override
465470
Future<StoredInboundGroupSession?> getInboundGroupSession(
466471
String roomId,

lib/src/event.dart

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -403,12 +403,29 @@ class Event extends MatrixEvent {
403403
MessageTypes.Audio,
404404
MessageTypes.File,
405405
}.contains(messageType)) {
406-
final file = room.sendingFilePlaceholders[eventId];
406+
final bytes = await room.client.database?.getFile(
407+
Uri.parse('com.famedly.sendingAttachment://file/$eventId'),
408+
);
409+
final file = bytes == null
410+
? null
411+
: MatrixFile(
412+
bytes: bytes,
413+
name: content.tryGet<String>('filename') ?? 'image',
414+
);
407415
if (file == null) {
408416
await cancelSend();
409417
throw Exception('Can not try to send again. File is no longer cached.');
410418
}
411-
final thumbnail = room.sendingFileThumbnails[eventId];
419+
final thumbnailBytes = await room.client.database?.getFile(
420+
Uri.parse('com.famedly.sendingAttachment://thumbnail/$txid'),
421+
);
422+
final thumbnail = thumbnailBytes == null
423+
? null
424+
: MatrixImageFile(
425+
bytes: thumbnailBytes,
426+
name:
427+
'thumbnail_${content.tryGet<String>('filename') ?? 'image'}',
428+
);
412429
final credentials = FileSendRequestCredentials.fromJson(unsigned ?? {});
413430
final inReplyTo = credentials.inReplyTo == null
414431
? null
@@ -688,7 +705,15 @@ class Event extends MatrixEvent {
688705
throw ("This event has the type '$type' and so it can't contain an attachment.");
689706
}
690707
if (status.isSending) {
691-
final localFile = room.sendingFilePlaceholders[eventId];
708+
final bytes = await room.client.database?.getFile(
709+
Uri.parse('com.famedly.sendingAttachment://file/$eventId'),
710+
);
711+
final localFile = bytes == null
712+
? null
713+
: MatrixImageFile(
714+
bytes: bytes,
715+
name: content.tryGet<String>('filename') ?? 'image',
716+
);
692717
if (localFile != null) return localFile;
693718
}
694719
final database = room.client.database;

lib/src/room.dart

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -665,9 +665,6 @@ class Room {
665665
return sendEvent(event, txid: txid);
666666
}
667667

668-
final Map<String, MatrixFile> sendingFilePlaceholders = {};
669-
final Map<String, MatrixImageFile> sendingFileThumbnails = {};
670-
671668
/// Sends a [file] to this room after uploading it. Returns the mxc uri of
672669
/// the uploaded file. If [waitUntilSent] is true, the future will wait until
673670
/// the message event has received the server. Otherwise the future will only
@@ -691,10 +688,6 @@ class Room {
691688
String? threadLastEventId,
692689
}) async {
693690
txid ??= client.generateUniqueTransactionId();
694-
sendingFilePlaceholders[txid] = file;
695-
if (thumbnail != null) {
696-
sendingFileThumbnails[txid] = thumbnail;
697-
}
698691

699692
// Create a fake Event object as a placeholder for the uploading file:
700693
final syncUpdate = SyncUpdate(
@@ -731,6 +724,22 @@ class Room {
731724
},
732725
),
733726
);
727+
await _handleFakeSync(syncUpdate);
728+
729+
if (client.database?.supportsFileStoring == true) {
730+
await client.database?.storeFile(
731+
Uri.parse('com.famedly.sendingAttachment://file/$txid'),
732+
file.bytes,
733+
DateTime.now().millisecondsSinceEpoch,
734+
);
735+
if (thumbnail != null) {
736+
await client.database?.storeFile(
737+
Uri.parse('com.famedly.sendingAttachment://thumbnail/$txid'),
738+
file.bytes,
739+
DateTime.now().millisecondsSinceEpoch,
740+
);
741+
}
742+
}
734743

735744
MatrixFile uploadFile = file; // ignore: omit_local_variable_types
736745
// computing the thumbnail in case we can
@@ -816,12 +825,22 @@ class Room {
816825
syncUpdate.rooms!.join!.values.first.timeline!.events!.first
817826
.unsigned![messageSendingStatusKey] = EventStatus.error.intValue;
818827
await _handleFakeSync(syncUpdate);
828+
829+
if (client.database?.supportsFileStoring != true) {
830+
final sendEvent = await getEventById(txid);
831+
await sendEvent?.cancelSend();
832+
}
819833
rethrow;
820834
} catch (_) {
821835
if (DateTime.now().isAfter(timeoutDate)) {
822836
syncUpdate.rooms!.join!.values.first.timeline!.events!.first
823837
.unsigned![messageSendingStatusKey] = EventStatus.error.intValue;
824838
await _handleFakeSync(syncUpdate);
839+
840+
if (client.database?.supportsFileStoring != true) {
841+
final sendEvent = await getEventById(txid);
842+
await sendEvent?.cancelSend();
843+
}
825844
rethrow;
826845
}
827846
Logs().v('Send File into room failed. Try again...');
@@ -885,8 +904,13 @@ class Room {
885904
threadRootEventId: threadRootEventId,
886905
threadLastEventId: threadLastEventId,
887906
);
888-
sendingFilePlaceholders.remove(txid);
889-
sendingFileThumbnails.remove(txid);
907+
await client.database?.deleteFile(
908+
Uri.parse('com.famedly.sendingAttachment://file/$txid'),
909+
);
910+
await client.database?.deleteFile(
911+
Uri.parse('com.famedly.sendingAttachment://thumbnail/$txid'),
912+
);
913+
890914
return eventId;
891915
}
892916

0 commit comments

Comments
 (0)