From ccfd4ecae3dc2be8089155d464bc814262e3392a Mon Sep 17 00:00:00 2001 From: TheOneWithTheBraid Date: Sat, 24 Dec 2022 07:13:44 +0100 Subject: [PATCH] chore: do not block UI while redacting events Signed-off-by: TheOneWithTheBraid --- assets/l10n/intl_en.arb | 14 +++++++ lib/pages/chat/chat.dart | 79 +++++++++++++++++++++++++---------- lib/pages/chat/chat_view.dart | 26 ++++++++---- 3 files changed, 88 insertions(+), 31 deletions(-) diff --git a/assets/l10n/intl_en.arb b/assets/l10n/intl_en.arb index c29d0570..53513af5 100644 --- a/assets/l10n/intl_en.arb +++ b/assets/l10n/intl_en.arb @@ -1467,6 +1467,20 @@ "count": {} } }, + "messagesRemoving": "{count,plural, =1{Message removing...} other{Messages removing...}}", + "@messagesRemoving": { + "type": "text", + "placeholders": { + "count": {} + } + }, + "couldNotDeleteMessages": "{count,plural, =1{Could not delete the message.} other{Could not delete {count} message.}}", + "@couldNotDeleteMessages": { + "type": "text", + "placeholders": { + "count": {} + } + }, "muteChat": "Mute chat", "@muteChat": { "type": "text", diff --git a/lib/pages/chat/chat.dart b/lib/pages/chat/chat.dart index e7990a9f..05762f72 100644 --- a/lib/pages/chat/chat.dart +++ b/lib/pages/chat/chat.dart @@ -110,6 +110,8 @@ class ChatController extends State { List selectedEvents = []; + bool actionsDisabled = false; + final Set unfolded = {}; Event? replyEvent; @@ -259,7 +261,7 @@ class ChatController extends State { if (sendController.text.trim().isEmpty) return; var parseCommands = true; - final commandMatch = RegExp(r'^\/(\w+)').firstMatch(sendController.text); + final commandMatch = RegExp(r'^/(\w+)').firstMatch(sendController.text); if (commandMatch != null && !room!.client.commands.keys.contains(commandMatch[1]!.toLowerCase())) { final l10n = L10n.of(context)!; @@ -549,31 +551,63 @@ class ChatController extends State { ) == OkCancelResult.ok; if (!confirmed) return; + + setState(() { + actionsDisabled = true; + showEmojiPicker = false; + }); + ScaffoldFeatureController? + bannerController; + final banner = MaterialBanner( + content: Text(L10n.of(context)!.messagesRemoving(selectedEvents.length)), + actions: [ + TextButton( + onPressed: () => bannerController?.close(), + child: Text(L10n.of(context)!.close), + ), + ], + ); + + bannerController = ScaffoldMessenger.of(context).showMaterialBanner(banner); + + final Set failedRedacts = {}; + for (final event in selectedEvents) { - await showFutureLoadingDialog( - context: context, - future: () async { - if (event.status.isSent) { - if (event.canRedact) { - await event.redactEvent(); - } else { - final client = currentRoomBundle.firstWhere( - (cl) => selectedEvents.first.senderId == cl!.userID, - orElse: () => null); - if (client == null) { - return; - } - final room = client.getRoomById(roomId!)!; - await Event.fromJson(event.toJson(), room).redactEvent(); - } - } else { - await event.remove(); + try { + if (event.status.isSent) { + if (event.canRedact) { + await event.redactEvent(); + } else { + final client = currentRoomBundle.firstWhere( + (cl) => selectedEvents.first.senderId == cl!.userID, + orElse: () => null); + if (client == null) { + return; } - }); + final room = client.getRoomById(roomId!)!; + await Event.fromJson(event.toJson(), room).redactEvent(); + } + } else { + await event.remove(); + } + } catch (e) { + failedRedacts.add(event.eventId); + } + } + bannerController.close(); + if (failedRedacts.isEmpty) { + selectedEvents.clear(); + } else { + selectedEvents.removeWhere( + (element) => !failedRedacts.contains(element.eventId), + ); + showAlertDialog( + context: context, + message: L10n.of(context)!.couldNotDeleteMessages(failedRedacts.length), + ); } setState(() { - showEmojiPicker = false; - selectedEvents.clear(); + actionsDisabled = false; }); } @@ -823,6 +857,7 @@ class ChatController extends State { } void onSelectMessage(Event event) { + if (actionsDisabled) return; if (!event.redacted) { if (selectedEvents.contains(event)) { setState( diff --git a/lib/pages/chat/chat_view.dart b/lib/pages/chat/chat_view.dart index 0aab7b5f..6d029c5e 100644 --- a/lib/pages/chat/chat_view.dart +++ b/lib/pages/chat/chat_view.dart @@ -40,30 +40,38 @@ class ChatView extends StatelessWidget { IconButton( icon: const Icon(Icons.edit_outlined), tooltip: L10n.of(context)!.edit, - onPressed: controller.editSelectedEventAction, + onPressed: controller.actionsDisabled + ? null + : controller.editSelectedEventAction, ), IconButton( icon: const Icon(Icons.copy_outlined), tooltip: L10n.of(context)!.copy, - onPressed: controller.copyEventsAction, + onPressed: + controller.actionsDisabled ? null : controller.copyEventsAction, ), if (controller.canSaveSelectedEvent) // Use builder context to correctly position the share dialog on iPad Builder( - builder: (context) => IconButton( - icon: Icon(Icons.adaptive.share), - tooltip: L10n.of(context)!.share, - onPressed: () => controller.saveSelectedEvent(context), - )), + builder: (context) => IconButton( + icon: Icon(Icons.adaptive.share), + tooltip: L10n.of(context)!.share, + onPressed: controller.actionsDisabled + ? null + : () => controller.saveSelectedEvent(context), + ), + ), if (controller.canRedactSelectedEvents) IconButton( icon: const Icon(Icons.delete_outlined), tooltip: L10n.of(context)!.redactMessage, - onPressed: controller.redactEventsAction, + onPressed: controller.actionsDisabled + ? null + : controller.redactEventsAction, ), IconButton( icon: const Icon(Icons.push_pin_outlined), - onPressed: controller.pinEvent, + onPressed: controller.actionsDisabled ? null : controller.pinEvent, tooltip: L10n.of(context)!.pinMessage, ), if (controller.selectedEvents.length == 1)