diff --git a/lib/controllers/room_chat_controller.dart b/lib/controllers/room_chat_controller.dart index fc9b218..f7d35a5 100644 --- a/lib/controllers/room_chat_controller.dart +++ b/lib/controllers/room_chat_controller.dart @@ -18,17 +18,27 @@ class RoomChatController extends AsyncNotifier { ref.onDispose( room.client.onTimelineEvent.stream.listen((event) async { if (event.roomId != room.id) return; - final message = await event.toMessage(); - if (message != null) { - if (event.relationshipType == RelationshipTypes.edit) { - final controller = await future; - final oldMessage = controller.messages.firstWhereOrNull( - (element) => element.id == event.relationshipEventId, - ); - if (oldMessage == null) return; - await updateMessage(oldMessage, message); - } else { - await insertMessage(message); + + if (event.type == EventTypes.Redaction) { + final controller = await future; + await controller.removeMessage( + controller.messages.firstWhere( + (message) => message.id == event.redacts, + ), + ); + } else { + final message = await event.toMessage(); + if (message != null) { + if (event.relationshipType == RelationshipTypes.edit) { + final controller = await future; + final oldMessage = controller.messages.firstWhereOrNull( + (element) => element.id == event.relationshipEventId, + ); + if (oldMessage == null) return; + await updateMessage(oldMessage, message); + } else { + await insertMessage(message); + } } } }).cancel, @@ -53,6 +63,12 @@ class RoomChatController extends AsyncNotifier { : controller.updateMessage(oldMessage, message); } + Future deleteMessage(Message message, {String? reason}) async { + final controller = await future; + await controller.removeMessage(message); + await room.redactEvent(message.id, reason: reason); + } + Future loadOlder() async { final controller = await future; final response = await ref diff --git a/lib/widgets/chat_page/room_chat.dart b/lib/widgets/chat_page/room_chat.dart index a1ac38e..0f815c6 100644 --- a/lib/widgets/chat_page/room_chat.dart +++ b/lib/widgets/chat_page/room_chat.dart @@ -23,6 +23,7 @@ import "package:nexus/widgets/chat_page/room_appbar.dart"; import "package:nexus/widgets/chat_page/spoiler_text.dart"; import "package:nexus/widgets/chat_page/top_widget.dart"; import "package:flutter_widget_from_html_core/flutter_widget_from_html_core.dart"; +import "package:nexus/widgets/form_text_input.dart"; import "package:nexus/widgets/loading.dart"; class RoomChat extends HookConsumerWidget { @@ -40,21 +41,6 @@ class RoomChat extends HookConsumerWidget { final memberListOpened = useState(showMembersByDefault); final theme = Theme.of(context); - List getMessageOptions(Message message) => [ - PopupMenuItem( - onTap: () => replyToMessage.value = message, - child: ListTile(leading: Icon(Icons.reply), title: Text("Reply")), - ), - PopupMenuItem( - onTap: () {}, - child: ListTile(leading: Icon(Icons.edit), title: Text("Edit")), - ), - PopupMenuItem( - onTap: () {}, - child: ListTile(leading: Icon(Icons.delete), title: Text("Delete")), - ), - ]; - return ref .watch(CurrentRoomController.provider) .betterWhen( @@ -71,6 +57,76 @@ class RoomChat extends HookConsumerWidget { room.roomData, ); final notifier = ref.watch(controllerProvider.notifier); + + List getMessageOptions(Message message) => [ + PopupMenuItem( + onTap: () => replyToMessage.value = message, + child: ListTile( + leading: Icon(Icons.reply), + title: Text("Reply"), + ), + ), + if (message.authorId == room.roomData.client.userID) + PopupMenuItem( + onTap: () {}, + child: ListTile( + leading: Icon(Icons.edit), + title: Text("Edit"), + ), + ), + if (message.authorId == room.roomData.client.userID || + room.roomData.canRedact) + PopupMenuItem( + onTap: () => showDialog( + context: context, + builder: (context) => HookBuilder( + builder: (_) { + final deleteReasonController = + useTextEditingController(); + return AlertDialog( + title: Text("Delete Message"), + content: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + "Are you sure you want to delete this message? This can not be reversed.", + ), + SizedBox(height: 12), + FormTextInput( + required: false, + capitalize: true, + controller: deleteReasonController, + title: "Reason for deletion (optional)", + ), + ], + ), + actions: [ + TextButton( + onPressed: Navigator.of(context).pop, + child: Text("Cancel"), + ), + TextButton( + onPressed: () async { + notifier.deleteMessage( + message, + reason: deleteReasonController.text, + ); + Navigator.of(context).pop(); + }, + child: Text("Delete"), + ), + ], + ); + }, + ), + ), + child: ListTile( + leading: Icon(Icons.delete), + title: Text("Delete"), + ), + ), + ]; + return Scaffold( appBar: RoomAppbar( room,