feat: Write and display reason for redacting a message
This commit is contained in:
parent
b27af74918
commit
5e3c62110b
4 changed files with 60 additions and 36 deletions
|
|
@ -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)!.redactMessage,
|
||||||
title: L10n.of(context)!.messageWillBeRemovedWarning,
|
message: L10n.of(context)!.redactMessageDescription,
|
||||||
okLabel: L10n.of(context)!.remove,
|
isDestructiveAction: true,
|
||||||
cancelLabel: L10n.of(context)!.cancel,
|
textFields: [
|
||||||
) ==
|
DialogTextField(
|
||||||
OkCancelResult.ok;
|
hintText: L10n.of(context)!.optionalRedactReason,
|
||||||
if (!confirmed) return;
|
),
|
||||||
|
],
|
||||||
|
okLabel: L10n.of(context)!.remove,
|
||||||
|
cancelLabel: L10n.of(context)!.cancel,
|
||||||
|
);
|
||||||
|
if (reasonInput == null) 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,
|
||||||
icon: const Icon(Icons.delete_outlined),
|
reason,
|
||||||
|
),
|
||||||
|
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,20 +318,12 @@ 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: [
|
style: TextStyle(
|
||||||
icon,
|
color: textColor,
|
||||||
const SizedBox(width: 8),
|
fontSize: fontSize,
|
||||||
Text(
|
),
|
||||||
label,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
style: TextStyle(
|
|
||||||
color: textColor,
|
|
||||||
fontSize: fontSize,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue