feat: Write and display reason for redacting a message

pull/474/head
krille-chan 2 years ago
parent b27af74918
commit 5e3c62110b
No known key found for this signature in database

@ -1061,6 +1061,8 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"redactMessageDescription": "The message will be redacted for all participants in this conversation. This cannot be undone.",
"optionalRedactReason": "(Optional) Reason for redacting this message...",
"invitedUser": "📩 {username} invited {targetName}", "invitedUser": "📩 {username} invited {targetName}",
"@invitedUser": { "@invitedUser": {
"type": "text", "type": "text",
@ -1568,6 +1570,21 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"redactedBy": "Redacted by {username}",
"@redactedBy": {
"type": "text",
"placeholders": {
"username": {}
}
},
"redactedByBecause": "Redacted by {username} because: \"{reason}\"",
"@redactedByBecause": {
"type": "text",
"placeholders": {
"username": {},
"reason": {}
}
},
"redactedAnEvent": "{username} redacted an event", "redactedAnEvent": "{username} redacted an event",
"@redactedAnEvent": { "@redactedAnEvent": {
"type": "text", "type": "text",

@ -734,22 +734,28 @@ class ChatController extends State<ChatPageWithRoom> {
} }
void redactEventsAction() async { void redactEventsAction() async {
final confirmed = await showOkCancelAlertDialog( final reasonInput = await showTextInputDialog(
useRootNavigator: false,
context: context, context: context,
title: L10n.of(context)!.messageWillBeRemovedWarning, title: L10n.of(context)!.redactMessage,
message: L10n.of(context)!.redactMessageDescription,
isDestructiveAction: true,
textFields: [
DialogTextField(
hintText: L10n.of(context)!.optionalRedactReason,
),
],
okLabel: L10n.of(context)!.remove, okLabel: L10n.of(context)!.remove,
cancelLabel: L10n.of(context)!.cancel, cancelLabel: L10n.of(context)!.cancel,
) == );
OkCancelResult.ok; if (reasonInput == null) return;
if (!confirmed) return; final reason = reasonInput.single.isEmpty ? null : reasonInput.single;
for (final event in selectedEvents) { for (final event in selectedEvents) {
await showFutureLoadingDialog( await showFutureLoadingDialog(
context: context, context: context,
future: () async { future: () async {
if (event.status.isSent) { if (event.status.isSent) {
if (event.canRedact) { if (event.canRedact) {
await event.redactEvent(); await event.redactEvent(reason: reason);
} else { } else {
final client = currentRoomBundle.firstWhere( final client = currentRoomBundle.firstWhere(
(cl) => selectedEvents.first.senderId == cl!.userID, (cl) => selectedEvents.first.senderId == cl!.userID,
@ -759,7 +765,9 @@ class ChatController extends State<ChatPageWithRoom> {
return; return;
} }
final room = client.getRoomById(roomId)!; final room = client.getRoomById(roomId)!;
await Event.fromJson(event.toJson(), room).redactEvent(); await Event.fromJson(event.toJson(), room).redactEvent(
reason: reason,
);
} }
} else { } else {
await event.remove(); await event.remove();

@ -385,8 +385,8 @@ class Message extends StatelessWidget {
container = row; container = row;
} }
if (event.messageType == MessageTypes.BadEncrypted || event.redacted) { if (event.messageType == MessageTypes.BadEncrypted) {
container = Opacity(opacity: 0.33, child: container); container = Opacity(opacity: 0.4, child: container);
} }
return Swipeable( return Swipeable(

@ -162,7 +162,7 @@ class MessageContent extends StatelessWidget {
return _ButtonContent( return _ButtonContent(
textColor: buttonTextColor, textColor: buttonTextColor,
onPressed: () => _verifyOrRequestKey(context), onPressed: () => _verifyOrRequestKey(context),
icon: const Icon(Icons.lock_outline), icon: '🔒',
label: L10n.of(context)!.encrypted, label: L10n.of(context)!.encrypted,
fontSize: fontSize, fontSize: fontSize,
); );
@ -208,12 +208,19 @@ class MessageContent extends StatelessWidget {
return FutureBuilder<User?>( return FutureBuilder<User?>(
future: event.redactedBecause?.fetchSenderUser(), future: event.redactedBecause?.fetchSenderUser(),
builder: (context, snapshot) { builder: (context, snapshot) {
final reason =
event.redactedBecause?.content.tryGet<String>('reason');
final redactedBy = snapshot.data?.calcDisplayname() ??
event.redactedBecause?.senderId.localpart ??
L10n.of(context)!.user;
return _ButtonContent( return _ButtonContent(
label: L10n.of(context)!.redactedAnEvent( label: reason == null
snapshot.data?.calcDisplayname() ?? ? L10n.of(context)!.redactedBy(redactedBy)
event.senderFromMemoryOrFallback.calcDisplayname(), : L10n.of(context)!.redactedByBecause(
redactedBy,
reason,
), ),
icon: const Icon(Icons.delete_outlined), icon: '🗑️',
textColor: buttonTextColor, textColor: buttonTextColor,
onPressed: () => onInfoTab!(event), onPressed: () => onInfoTab!(event),
fontSize: fontSize, fontSize: fontSize,
@ -263,7 +270,7 @@ class MessageContent extends StatelessWidget {
snapshot.data?.calcDisplayname() ?? snapshot.data?.calcDisplayname() ??
event.senderFromMemoryOrFallback.calcDisplayname(), event.senderFromMemoryOrFallback.calcDisplayname(),
), ),
icon: const Icon(Icons.phone_outlined), icon: '📞',
textColor: buttonTextColor, textColor: buttonTextColor,
onPressed: () => onInfoTab!(event), onPressed: () => onInfoTab!(event),
fontSize: fontSize, fontSize: fontSize,
@ -280,7 +287,7 @@ class MessageContent extends StatelessWidget {
event.senderFromMemoryOrFallback.calcDisplayname(), event.senderFromMemoryOrFallback.calcDisplayname(),
event.type, event.type,
), ),
icon: const Icon(Icons.info_outlined), icon: '',
textColor: buttonTextColor, textColor: buttonTextColor,
onPressed: () => onInfoTab!(event), onPressed: () => onInfoTab!(event),
fontSize: fontSize, fontSize: fontSize,
@ -294,7 +301,7 @@ class MessageContent extends StatelessWidget {
class _ButtonContent extends StatelessWidget { class _ButtonContent extends StatelessWidget {
final void Function() onPressed; final void Function() onPressed;
final String label; final String label;
final Icon icon; final String icon;
final Color? textColor; final Color? textColor;
final double fontSize; final double fontSize;
@ -311,21 +318,13 @@ class _ButtonContent extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return InkWell( return InkWell(
onTap: onPressed, onTap: onPressed,
child: Row( child: Text(
mainAxisSize: MainAxisSize.min, '$icon $label',
children: [
icon,
const SizedBox(width: 8),
Text(
label,
overflow: TextOverflow.ellipsis,
style: TextStyle( style: TextStyle(
color: textColor, color: textColor,
fontSize: fontSize, fontSize: fontSize,
), ),
), ),
],
),
); );
} }
} }

Loading…
Cancel
Save