diff --git a/lib/src/database/daos/messages_dao.dart b/lib/src/database/daos/messages_dao.dart index be73ee8..f9b8352 100644 --- a/lib/src/database/daos/messages_dao.dart +++ b/lib/src/database/daos/messages_dao.dart @@ -171,7 +171,10 @@ class MessagesDao extends DatabaseAccessor } Future deleteMessagesByContactId(int contactId) { - return (delete(messages)..where((t) => t.contactId.equals(contactId))).go(); + return (delete(messages) + ..where((t) => + t.contactId.equals(contactId) & t.mediaStored.equals(false))) + .go(); } Future containsOtherMessageId( diff --git a/lib/src/localization/app_de.arb b/lib/src/localization/app_de.arb index 953cd27..26a5ac2 100644 --- a/lib/src/localization/app_de.arb +++ b/lib/src/localization/app_de.arb @@ -137,7 +137,7 @@ "contactNicknameNew": "Neuer Spitzname", "contactBlock": "Blockieren", "deleteAllContactMessages": "Alle Nachrichten löschen", - "deleteAllContactMessagesBody": "Dadurch werden alle Nachrichten in deinem Chat mit {username} gelöscht. Dies löscht NICHT die auf dem Gerät von {username} gespeicherten Nachrichten!", + "deleteAllContactMessagesBody": "Dadurch werden alle Nachrichten, ausgenommen gespeicherte Mediendateien, in deinem Chat mit {username} gelöscht. Dies löscht NICHT die auf dem Gerät von {username} gespeicherten Nachrichten!", "contactBlockTitle": "Blockiere {username}", "contactBlockBody": "Ein blockierter Benutzer kann dir keine Nachrichten mehr senden, und sein Profil ist nicht mehr sichtbar. Um die Blockierung eines Benutzers aufzuheben, navigiere einfach zu Einstellungen > Datenschutz > Blockierte Benutzer.", "undo": "Rückgängig", diff --git a/lib/src/localization/app_en.arb b/lib/src/localization/app_en.arb index 06db8c7..8cc177d 100644 --- a/lib/src/localization/app_en.arb +++ b/lib/src/localization/app_en.arb @@ -247,7 +247,7 @@ "@contactNicknameNew": {}, "deleteAllContactMessages": "Delete all messages", "@deleteAllContactMessages": {}, - "deleteAllContactMessagesBody": "This will remove all messages in your chat with {username}. This will NOT delete the messages stored at {username}s device!", + "deleteAllContactMessagesBody": "This will remove all messages, except stored media files, in your chat with {username}. This will NOT delete the messages stored at {username}s device!", "@deleteAllContactMessagesBody": { "placeholders": { "username": {} diff --git a/lib/src/localization/generated/app_localizations.dart b/lib/src/localization/generated/app_localizations.dart index f629248..fa9f2d2 100644 --- a/lib/src/localization/generated/app_localizations.dart +++ b/lib/src/localization/generated/app_localizations.dart @@ -818,7 +818,7 @@ abstract class AppLocalizations { /// No description provided for @deleteAllContactMessagesBody. /// /// In en, this message translates to: - /// **'This will remove all messages in your chat with {username}. This will NOT delete the messages stored at {username}s device!'** + /// **'This will remove all messages, except stored media files, in your chat with {username}. This will NOT delete the messages stored at {username}s device!'** String deleteAllContactMessagesBody(Object username); /// No description provided for @contactBlock. diff --git a/lib/src/localization/generated/app_localizations_de.dart b/lib/src/localization/generated/app_localizations_de.dart index 3260d3c..f7ec2cf 100644 --- a/lib/src/localization/generated/app_localizations_de.dart +++ b/lib/src/localization/generated/app_localizations_de.dart @@ -376,7 +376,7 @@ class AppLocalizationsDe extends AppLocalizations { @override String deleteAllContactMessagesBody(Object username) { - return 'Dadurch werden alle Nachrichten in deinem Chat mit $username gelöscht. Dies löscht NICHT die auf dem Gerät von $username gespeicherten Nachrichten!'; + return 'Dadurch werden alle Nachrichten, ausgenommen gespeicherte Mediendateien, in deinem Chat mit $username gelöscht. Dies löscht NICHT die auf dem Gerät von $username gespeicherten Nachrichten!'; } @override diff --git a/lib/src/localization/generated/app_localizations_en.dart b/lib/src/localization/generated/app_localizations_en.dart index b57fa21..bbb0acb 100644 --- a/lib/src/localization/generated/app_localizations_en.dart +++ b/lib/src/localization/generated/app_localizations_en.dart @@ -376,7 +376,7 @@ class AppLocalizationsEn extends AppLocalizations { @override String deleteAllContactMessagesBody(Object username) { - return 'This will remove all messages in your chat with $username. This will NOT delete the messages stored at ${username}s device!'; + return 'This will remove all messages, except stored media files, in your chat with $username. This will NOT delete the messages stored at ${username}s device!'; } @override diff --git a/lib/src/providers/api/media_send.dart b/lib/src/providers/api/media_send.dart index 1732f99..08c789d 100644 --- a/lib/src/providers/api/media_send.dart +++ b/lib/src/providers/api/media_send.dart @@ -129,9 +129,9 @@ Future handleSingleMediaFile( } try { // delete non compressed media files - await deleteMediaFile(media, "orginal.png"); - await deleteMediaFile(media, "orginal.mp4"); - await deleteMediaFile(media, "encrypted"); + await deleteMediaFile(media.mediaUploadId, "orginal.png"); + await deleteMediaFile(media.mediaUploadId, "orginal.mp4"); + await deleteMediaFile(media.mediaUploadId, "encrypted"); } catch (e) { Logger("media_send.dart").shout("$e"); } @@ -512,8 +512,8 @@ Future writeMediaFile( await file.writeAsBytes(data); } -Future deleteMediaFile(MediaUpload media, String type) async { - String basePath = await getMediaFilePath(media.mediaUploadId, "send"); +Future deleteMediaFile(int mediaUploadId, String type) async { + String basePath = await getMediaFilePath(mediaUploadId, "send"); File file = File("$basePath.$type"); if (await file.exists()) { await file.delete(); diff --git a/lib/src/views/chats/chat_item_details_view.dart b/lib/src/views/chats/chat_item_details_view.dart index 3749526..cd8da92 100644 --- a/lib/src/views/chats/chat_item_details_view.dart +++ b/lib/src/views/chats/chat_item_details_view.dart @@ -6,7 +6,7 @@ import 'package:drift/drift.dart' show Value; import 'package:flutter/material.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:twonly/globals.dart'; -import 'package:twonly/src/providers/api/media_send.dart'; +import 'package:twonly/src/providers/api/media_send.dart' as send; import 'package:twonly/src/views/components/animate_icon.dart'; import 'package:twonly/src/views/components/better_text.dart'; import 'package:twonly/src/views/components/initialsavatar.dart'; @@ -17,7 +17,7 @@ import 'package:twonly/src/database/twonly_database.dart'; import 'package:twonly/src/database/tables/messages_table.dart'; import 'package:twonly/src/model/json/message.dart'; import 'package:twonly/src/providers/api/api.dart'; -import 'package:twonly/src/providers/api/media_received.dart'; +import 'package:twonly/src/providers/api/media_received.dart' as received; import 'package:twonly/src/services/notification_service.dart'; import 'package:twonly/src/views/camera/camera_send_to_view.dart'; import 'package:twonly/src/views/chats/media_viewer_view.dart'; @@ -67,7 +67,7 @@ class _InChatMediaViewerState extends State { Future initAsync() async { if (!widget.message.mediaStored) return; bool isSend = widget.message.messageOtherId == null; - final basePath = await getMediaFilePath( + final basePath = await send.getMediaFilePath( isSend ? widget.message.mediaUploadId! : widget.message.messageId, isSend ? "send" : "received", ); @@ -108,18 +108,39 @@ class _InChatMediaViewerState extends State { videoController?.dispose(); } + Future deleteFiles() async { + await twonlyDatabase.messagesDao.updateMessageByMessageId( + widget.message.messageId, + MessagesCompanion(mediaStored: Value(false)), + ); + await send.purgeSendMediaFiles(); + await received.purgeReceivedMediaFiles(); + if (context.mounted) { + Navigator.pop(context, true); + } + } + @override Widget build(BuildContext context) { return GestureDetector( - onTap: () { - if (widget.isInFullscreen) return; - Navigator.push( - context, - MaterialPageRoute(builder: (context) { - return ChatMediaViewerFullScreen(message: widget.message); - }), - ); - }, + onTap: (image == null && videoController == null) + ? null + : () async { + if (widget.isInFullscreen) return; + bool? removed = await Navigator.push( + context, + MaterialPageRoute(builder: (context) { + return ChatMediaViewerFullScreen(message: widget.message); + }), + ); + + if (removed != null && removed) { + image = null; + videoController?.dispose(); + videoController = null; + setState(() {}); + } + }, child: Stack( children: [ if (image != null) Image.file(image!), @@ -137,7 +158,23 @@ class _InChatMediaViewerState extends State { [widget.message], mainAxisAlignment: MainAxisAlignment.center, ), - ) + ), + if (widget.isInFullscreen) + Positioned( + bottom: 10, + left: 0, + right: 0, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + OutlinedButton.icon( + onPressed: deleteFiles, + icon: FaIcon(FontAwesomeIcons.trashCan), + label: Text("Delete media file"), + ) + ], + ), + ), ], ), ); @@ -348,7 +385,7 @@ class ChatListEntry extends StatelessWidget { message.mediaStored) { return; } - if (await existsMediaFile(message.messageId, "png")) { + if (await received.existsMediaFile(message.messageId, "png")) { encryptAndSendMessage( null, contact.userId, @@ -379,7 +416,7 @@ class ChatListEntry extends StatelessWidget { }), ); } else if (message.downloadState == DownloadState.pending) { - startDownloadMedia(message, true); + received.startDownloadMedia(message, true); } } },