From eeb630b5fcf68bbd9364c3dc5dfc9f089e75b96a Mon Sep 17 00:00:00 2001 From: Krille Date: Fri, 11 Apr 2025 08:30:58 +0200 Subject: [PATCH] chore: Follow up dialog themes Signed-off-by: Krille --- lib/pages/chat/events/message.dart | 32 +- .../chat_details/participant_list_item.dart | 113 ++-- lib/widgets/adaptive_dialogs/user_dialog.dart | 124 +++-- .../member_actions_popup_menu_button.dart | 509 +++++++++--------- lib/widgets/permission_slider_dialog.dart | 6 +- 5 files changed, 397 insertions(+), 387 deletions(-) diff --git a/lib/pages/chat/events/message.dart b/lib/pages/chat/events/message.dart index 267f00883..0428db2fe 100644 --- a/lib/pages/chat/events/message.dart +++ b/lib/pages/chat/events/message.dart @@ -1,12 +1,5 @@ import 'dart:ui' as ui; -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; - -import 'package:flutter_gen/gen_l10n/l10n.dart'; -import 'package:matrix/matrix.dart'; -import 'package:swipe_to_action/swipe_to_action.dart'; - import 'package:fluffychat/config/themes.dart'; import 'package:fluffychat/pages/chat/events/room_creation_state_event.dart'; import 'package:fluffychat/utils/date_time_extension.dart'; @@ -15,6 +8,12 @@ import 'package:fluffychat/utils/string_color.dart'; import 'package:fluffychat/widgets/avatar.dart'; import 'package:fluffychat/widgets/matrix.dart'; import 'package:fluffychat/widgets/member_actions_popup_menu_button.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_gen/gen_l10n/l10n.dart'; +import 'package:matrix/matrix.dart'; +import 'package:swipe_to_action/swipe_to_action.dart'; + import '../../../config/app_config.dart'; import 'message_content.dart'; import 'message_reactions.dart'; @@ -237,16 +236,17 @@ class Message extends StatelessWidget { builder: (context, snapshot) { final user = snapshot.data ?? event.senderFromMemoryOrFallback; - return MemberActionsPopupMenuButton( - onMention: onMention, - user: user, - child: Avatar( - mxContent: user.avatarUrl, - name: user.calcDisplayname(), - presenceUserId: user.stateKey, - presenceBackgroundColor: - wallpaperMode ? Colors.transparent : null, + return Avatar( + mxContent: user.avatarUrl, + name: user.calcDisplayname(), + onTap: () => showMemberActionsPopupMenu( + context: context, + user: user, + onMention: onMention, ), + presenceUserId: user.stateKey, + presenceBackgroundColor: + wallpaperMode ? Colors.transparent : null, ); }, ), diff --git a/lib/pages/chat_details/participant_list_item.dart b/lib/pages/chat_details/participant_list_item.dart index e463c9fb1..8ec64f1f7 100644 --- a/lib/pages/chat_details/participant_list_item.dart +++ b/lib/pages/chat_details/participant_list_item.dart @@ -1,10 +1,9 @@ +import 'package:fluffychat/config/app_config.dart'; +import 'package:fluffychat/widgets/member_actions_popup_menu_button.dart'; import 'package:flutter/material.dart'; - import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:matrix/matrix.dart'; -import 'package:fluffychat/config/app_config.dart'; -import 'package:fluffychat/widgets/member_actions_popup_menu_button.dart'; import '../../widgets/avatar.dart'; class ParticipantListItem extends StatelessWidget { @@ -32,68 +31,66 @@ class ParticipantListItem extends StatelessWidget { return Opacity( opacity: user.membership == Membership.join ? 1 : 0.5, - child: MemberActionsPopupMenuButton( - user: user, - child: ListTile( - title: Row( - children: [ - Expanded( - child: Text( - user.calcDisplayname(), - overflow: TextOverflow.ellipsis, - ), + child: ListTile( + onTap: () => showMemberActionsPopupMenu(context: context, user: user), + title: Row( + children: [ + Expanded( + child: Text( + user.calcDisplayname(), + overflow: TextOverflow.ellipsis, ), - if (permissionBatch.isNotEmpty) - Container( - padding: const EdgeInsets.symmetric( - horizontal: 12, - vertical: 6, + ), + if (permissionBatch.isNotEmpty) + Container( + padding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 6, + ), + decoration: BoxDecoration( + color: user.powerLevel >= 100 + ? theme.colorScheme.tertiary + : theme.colorScheme.tertiaryContainer, + borderRadius: BorderRadius.circular( + AppConfig.borderRadius, ), - decoration: BoxDecoration( + ), + child: Text( + permissionBatch, + style: theme.textTheme.labelSmall?.copyWith( color: user.powerLevel >= 100 - ? theme.colorScheme.tertiary - : theme.colorScheme.tertiaryContainer, - borderRadius: BorderRadius.circular( - AppConfig.borderRadius, - ), - ), - child: Text( - permissionBatch, - style: theme.textTheme.labelSmall?.copyWith( - color: user.powerLevel >= 100 - ? theme.colorScheme.onTertiary - : theme.colorScheme.onTertiaryContainer, - ), + ? theme.colorScheme.onTertiary + : theme.colorScheme.onTertiaryContainer, ), ), - membershipBatch == null - ? const SizedBox.shrink() - : Container( - padding: const EdgeInsets.all(4), - margin: const EdgeInsets.symmetric(horizontal: 8), - decoration: BoxDecoration( - color: theme.secondaryHeaderColor, - borderRadius: BorderRadius.circular(8), - ), - child: Center( - child: Text( - membershipBatch, - style: theme.textTheme.labelSmall, - ), + ), + membershipBatch == null + ? const SizedBox.shrink() + : Container( + padding: const EdgeInsets.all(4), + margin: const EdgeInsets.symmetric(horizontal: 8), + decoration: BoxDecoration( + color: theme.secondaryHeaderColor, + borderRadius: BorderRadius.circular(8), + ), + child: Center( + child: Text( + membershipBatch, + style: theme.textTheme.labelSmall, ), ), - ], - ), - subtitle: Text( - user.id, - maxLines: 1, - overflow: TextOverflow.ellipsis, - ), - leading: Avatar( - mxContent: user.avatarUrl, - name: user.calcDisplayname(), - presenceUserId: user.stateKey, - ), + ), + ], + ), + subtitle: Text( + user.id, + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + leading: Avatar( + mxContent: user.avatarUrl, + name: user.calcDisplayname(), + presenceUserId: user.stateKey, ), ), ); diff --git a/lib/widgets/adaptive_dialogs/user_dialog.dart b/lib/widgets/adaptive_dialogs/user_dialog.dart index c3645e426..ec06a58b3 100644 --- a/lib/widgets/adaptive_dialogs/user_dialog.dart +++ b/lib/widgets/adaptive_dialogs/user_dialog.dart @@ -23,6 +23,7 @@ class UserDialog extends StatelessWidget { }) => showAdaptiveDialog( context: context, + barrierDismissible: true, builder: (context) => UserDialog( profile, noProfileWarning: noProfileWarning, @@ -49,34 +50,35 @@ class UserDialog extends StatelessWidget { child: Center(child: Text(displayname, textAlign: TextAlign.center)), ), content: ConstrainedBox( - constraints: const BoxConstraints(maxWidth: 256), + constraints: const BoxConstraints(maxWidth: 256, maxHeight: 256), child: SelectionArea( - child: Center( - child: PresenceBuilder( - userId: profile.userId, - client: Matrix.of(context).client, - builder: (context, presence) { - if (presence == null) return const SizedBox.shrink(); - final statusMsg = presence.statusMsg; - final lastActiveTimestamp = presence.lastActiveTimestamp; - final presenceText = presence.currentlyActive == true - ? L10n.of(context).currentlyActive - : lastActiveTimestamp != null - ? L10n.of(context).lastActiveAgo( - lastActiveTimestamp.localizedTimeShort(context), - ) - : null; - return Column( + child: PresenceBuilder( + userId: profile.userId, + client: Matrix.of(context).client, + builder: (context, presence) { + if (presence == null) return const SizedBox.shrink(); + final statusMsg = presence.statusMsg; + final lastActiveTimestamp = presence.lastActiveTimestamp; + final presenceText = presence.currentlyActive == true + ? L10n.of(context).currentlyActive + : lastActiveTimestamp != null + ? L10n.of(context).lastActiveAgo( + lastActiveTimestamp.localizedTimeShort(context), + ) + : null; + return SingleChildScrollView( + child: Column( spacing: 8, mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.stretch, children: [ HoverBuilder( builder: (context, hovered) => StatefulBuilder( builder: (context, setState) => GestureDetector( onTap: () { Clipboard.setData( - ClipboardData(text: profile.userId)); + ClipboardData(text: profile.userId), + ); setState(() { copied = true; }); @@ -115,15 +117,18 @@ class UserDialog extends StatelessWidget { ), ), ), - Avatar( - mxContent: profile.avatarUrl, - name: displayname, - size: Avatar.defaultSize * 2, + Center( + child: Avatar( + mxContent: profile.avatarUrl, + name: displayname, + size: Avatar.defaultSize * 2, + ), ), if (presenceText != null) Text( presenceText, style: const TextStyle(fontSize: 10), + textAlign: TextAlign.center, ), if (statusMsg != null) Linkify( @@ -139,48 +144,49 @@ class UserDialog extends StatelessWidget { UrlLauncher(context, url.url).launchUrl(), ), ], - ); - }, - ), + ), + ); + }, ), ), ), actions: [ - if (client.userID != profile.userId) ...[], - AdaptiveDialogAction( - bigButtons: true, - onPressed: () async { - final router = GoRouter.of(context); - Navigator.of(context).pop(); - final roomIdResult = await showFutureLoadingDialog( - context: context, - future: () => client.startDirectChat(profile.userId), - ); - final roomId = roomIdResult.result; - if (roomId == null) return; - router.go('/rooms/$roomId'); - }, - child: Text( - dmRoomId == null - ? L10n.of(context).startConversation - : L10n.of(context).sendAMessage, + if (client.userID != profile.userId) ...[ + AdaptiveDialogAction( + bigButtons: true, + onPressed: () async { + final router = GoRouter.of(context); + Navigator.of(context).pop(); + final roomIdResult = await showFutureLoadingDialog( + context: context, + future: () => client.startDirectChat(profile.userId), + ); + final roomId = roomIdResult.result; + if (roomId == null) return; + router.go('/rooms/$roomId'); + }, + child: Text( + dmRoomId == null + ? L10n.of(context).startConversation + : L10n.of(context).sendAMessage, + ), ), - ), - AdaptiveDialogAction( - bigButtons: true, - onPressed: () { - final router = GoRouter.of(context); - Navigator.of(context).pop(); - router.go( - '/rooms/settings/security/ignorelist', - extra: profile.userId, - ); - }, - child: Text( - L10n.of(context).ignoreUser, - style: TextStyle(color: theme.colorScheme.error), + AdaptiveDialogAction( + bigButtons: true, + onPressed: () { + final router = GoRouter.of(context); + Navigator.of(context).pop(); + router.go( + '/rooms/settings/security/ignorelist', + extra: profile.userId, + ); + }, + child: Text( + L10n.of(context).ignoreUser, + style: TextStyle(color: theme.colorScheme.error), + ), ), - ), + ], AdaptiveDialogAction( bigButtons: true, onPressed: Navigator.of(context).pop, diff --git a/lib/widgets/member_actions_popup_menu_button.dart b/lib/widgets/member_actions_popup_menu_button.dart index 29525a45f..204a418e7 100644 --- a/lib/widgets/member_actions_popup_menu_button.dart +++ b/lib/widgets/member_actions_popup_menu_button.dart @@ -1,9 +1,8 @@ +import 'package:fluffychat/widgets/permission_slider_dialog.dart'; import 'package:flutter/material.dart'; - import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:matrix/matrix.dart'; -import 'package:fluffychat/widgets/permission_slider_dialog.dart'; import 'adaptive_dialogs/show_modal_action_popup.dart'; import 'adaptive_dialogs/show_ok_cancel_alert_dialog.dart'; import 'adaptive_dialogs/show_text_input_dialog.dart'; @@ -11,278 +10,284 @@ import 'adaptive_dialogs/user_dialog.dart'; import 'avatar.dart'; import 'future_loading_dialog.dart'; -class MemberActionsPopupMenuButton extends StatelessWidget { - final Widget child; - final User user; - final void Function()? onMention; +void showMemberActionsPopupMenu({ + required BuildContext context, + required User user, + void Function()? onMention, +}) async { + final theme = Theme.of(context); + final displayname = user.calcDisplayname(); + final isMe = user.room.client.userID == user.id; - const MemberActionsPopupMenuButton({ - required this.child, - required this.user, - this.onMention, - super.key, - }); + final overlay = Overlay.of(context).context.findRenderObject() as RenderBox; - @override - Widget build(BuildContext context) { - final theme = Theme.of(context); - final displayname = user.calcDisplayname(); - final isMe = user.room.client.userID == user.id; - return PopupMenuButton( - onSelected: (action) async { - switch (action) { - case _MemberActions.mention: - onMention?.call(); - return; - case _MemberActions.setRole: - final power = await showPermissionChooser( - context, - currentLevel: user.powerLevel, - maxLevel: user.room.ownPowerLevel, - ); - if (power == null) return; - if (!context.mounted) return; - if (power >= 100) { - final consent = await showOkCancelAlertDialog( - context: context, - title: L10n.of(context).areYouSure, - message: L10n.of(context).makeAdminDescription, - ); - if (consent != OkCancelResult.ok) return; - if (!context.mounted) return; - } - await showFutureLoadingDialog( - context: context, - future: () => user.setPower(power), - ); - return; - case _MemberActions.kick: - if (await showOkCancelAlertDialog( - useRootNavigator: false, - context: context, - title: L10n.of(context).areYouSure, - okLabel: L10n.of(context).yes, - cancelLabel: L10n.of(context).no, - message: L10n.of(context).kickUserDescription, - ) == - OkCancelResult.ok) { - await showFutureLoadingDialog( - context: context, - future: () => user.kick(), - ); - } - return; - case _MemberActions.ban: - if (await showOkCancelAlertDialog( - useRootNavigator: false, - context: context, - title: L10n.of(context).areYouSure, - okLabel: L10n.of(context).yes, - cancelLabel: L10n.of(context).no, - message: L10n.of(context).banUserDescription, - ) == - OkCancelResult.ok) { - await showFutureLoadingDialog( - context: context, - future: () => user.ban(), - ); - } - return; - case _MemberActions.report: - final score = await showModalActionPopup( - context: context, - title: L10n.of(context).reportUser, - message: L10n.of(context).howOffensiveIsThisContent, - cancelLabel: L10n.of(context).cancel, - actions: [ - AdaptiveModalAction( - value: -100, - label: L10n.of(context).extremeOffensive, - ), - AdaptiveModalAction( - value: -50, - label: L10n.of(context).offensive, - ), - AdaptiveModalAction( - value: 0, - label: L10n.of(context).inoffensive, - ), - ], - ); - if (score == null) return; - final reason = await showTextInputDialog( - useRootNavigator: false, - context: context, - title: L10n.of(context).whyDoYouWantToReportThis, - okLabel: L10n.of(context).ok, - cancelLabel: L10n.of(context).cancel, - hintText: L10n.of(context).reason, - ); - if (reason == null || reason.isEmpty) return; + final button = context.findRenderObject() as RenderBox; - final result = await showFutureLoadingDialog( - context: context, - future: () => user.room.client.reportEvent( - user.room.id, - user.id, - reason: reason, - score: score, + final position = RelativeRect.fromRect( + Rect.fromPoints( + button.localToGlobal(const Offset(0, -65), ancestor: overlay), + button.localToGlobal( + button.size.bottomRight(Offset.zero) + const Offset(-50, 0), + ancestor: overlay, + ), + ), + Offset.zero & overlay.size, + ); + + final action = await showMenu<_MemberActions>( + context: context, + position: position, + items: >[ + PopupMenuItem( + value: _MemberActions.info, + child: Center( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Avatar( + name: displayname, + mxContent: user.avatarUrl, + presenceUserId: user.id, + presenceBackgroundColor: theme.colorScheme.surfaceContainer, ), - ); - if (result.error != null) return; - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text(L10n.of(context).contentHasBeenReported)), - ); - return; - case _MemberActions.info: - await UserDialog.show( - context: context, - profile: Profile( - userId: user.id, - displayName: user.displayName, - avatarUrl: user.avatarUrl, + const SizedBox(height: 8), + Text( + displayname, + textAlign: TextAlign.center, + style: theme.textTheme.labelLarge, + maxLines: 1, + overflow: TextOverflow.ellipsis, ), - ); - return; - case _MemberActions.unban: - if (await showOkCancelAlertDialog( - useRootNavigator: false, - context: context, - title: L10n.of(context).areYouSure, - okLabel: L10n.of(context).yes, - cancelLabel: L10n.of(context).no, - message: L10n.of(context).unbanUserDescription, - ) == - OkCancelResult.ok) { - await showFutureLoadingDialog( - context: context, - future: () => user.unban(), - ); - } - return; - } - }, - itemBuilder: (context) => >[ + Text( + user.id, + textAlign: TextAlign.center, + style: const TextStyle(fontSize: 10), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + ], + ), + ), + ), + const PopupMenuDivider(), + if (onMention != null) PopupMenuItem( - value: _MemberActions.info, - child: Center( - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Avatar( - name: displayname, - mxContent: user.avatarUrl, - presenceUserId: user.id, - presenceBackgroundColor: theme.colorScheme.surfaceContainer, - ), - const SizedBox(height: 8), - Text( - displayname, - textAlign: TextAlign.center, - style: theme.textTheme.labelLarge, - maxLines: 1, - overflow: TextOverflow.ellipsis, - ), - Text( - user.id, - textAlign: TextAlign.center, - style: const TextStyle(fontSize: 10), - maxLines: 1, - overflow: TextOverflow.ellipsis, - ), - ], - ), + value: _MemberActions.mention, + child: ListTile( + leading: const Icon(Icons.alternate_email_outlined), + title: Text(L10n.of(context).mention), ), ), - const PopupMenuDivider(), - if (onMention != null) - PopupMenuItem( - value: _MemberActions.mention, - child: ListTile( - leading: const Icon(Icons.alternate_email_outlined), - title: Text(L10n.of(context).mention), - ), + PopupMenuItem( + enabled: user.room.canChangePowerLevel && user.canChangeUserPowerLevel, + value: _MemberActions.setRole, + child: ListTile( + leading: const Icon(Icons.admin_panel_settings_outlined), + title: Text(L10n.of(context).chatPermissions), + subtitle: Text( + user.powerLevel < 50 + ? L10n.of(context).userLevel(user.powerLevel) + : user.powerLevel < 100 + ? L10n.of(context).moderatorLevel(user.powerLevel) + : L10n.of(context).adminLevel(user.powerLevel), + style: const TextStyle(fontSize: 10), ), + ), + ), + if (user.canKick) PopupMenuItem( - enabled: - user.room.canChangePowerLevel && user.canChangeUserPowerLevel, - value: _MemberActions.setRole, + value: _MemberActions.kick, child: ListTile( - leading: const Icon(Icons.admin_panel_settings_outlined), - title: Text(L10n.of(context).chatPermissions), - subtitle: Text( - user.powerLevel < 50 - ? L10n.of(context).userLevel(user.powerLevel) - : user.powerLevel < 100 - ? L10n.of(context).moderatorLevel(user.powerLevel) - : L10n.of(context).adminLevel(user.powerLevel), - style: const TextStyle(fontSize: 10), + leading: Icon( + Icons.person_remove_outlined, + color: theme.colorScheme.onErrorContainer, + ), + title: Text( + L10n.of(context).kickFromChat, + style: TextStyle(color: theme.colorScheme.onErrorContainer), ), ), ), - if (user.canKick) - PopupMenuItem( - value: _MemberActions.kick, - child: ListTile( - leading: Icon( - Icons.person_remove_outlined, - color: theme.colorScheme.onErrorContainer, - ), - title: Text( - L10n.of(context).kickFromChat, - style: TextStyle(color: theme.colorScheme.onErrorContainer), - ), + if (user.canBan) + PopupMenuItem( + value: _MemberActions.ban, + child: ListTile( + leading: Icon( + Icons.block_outlined, + color: theme.colorScheme.onErrorContainer, ), - ), - if (user.canBan) - PopupMenuItem( - value: _MemberActions.ban, - child: ListTile( - leading: Icon( - Icons.block_outlined, - color: theme.colorScheme.onErrorContainer, - ), - title: Text( - L10n.of(context).banFromChat, - style: TextStyle(color: theme.colorScheme.onErrorContainer), - ), + title: Text( + L10n.of(context).banFromChat, + style: TextStyle(color: theme.colorScheme.onErrorContainer), ), ), - if (user.canBan && user.membership == Membership.ban) - PopupMenuItem( - value: _MemberActions.ban, - child: ListTile( - leading: const Icon(Icons.warning), - title: Text( - L10n.of(context).unbanFromChat, - ), + ), + if (user.canBan && user.membership == Membership.ban) + PopupMenuItem( + value: _MemberActions.ban, + child: ListTile( + leading: const Icon(Icons.warning), + title: Text( + L10n.of(context).unbanFromChat, ), ), - if (user.canBan && user.membership == Membership.ban) - PopupMenuItem( - value: _MemberActions.unban, - child: ListTile( - leading: const Icon(Icons.warning_outlined), - title: Text(L10n.of(context).unbanFromChat), - ), + ), + if (user.canBan && user.membership == Membership.ban) + PopupMenuItem( + value: _MemberActions.unban, + child: ListTile( + leading: const Icon(Icons.warning_outlined), + title: Text(L10n.of(context).unbanFromChat), ), - if (!isMe) - PopupMenuItem( - value: _MemberActions.report, - child: ListTile( - leading: Icon( - Icons.gavel_outlined, - color: theme.colorScheme.onErrorContainer, - ), - title: Text( - L10n.of(context).reportUser, - style: TextStyle(color: theme.colorScheme.onErrorContainer), - ), + ), + if (!isMe) + PopupMenuItem( + value: _MemberActions.report, + child: ListTile( + leading: Icon( + Icons.gavel_outlined, + color: theme.colorScheme.onErrorContainer, + ), + title: Text( + L10n.of(context).reportUser, + style: TextStyle(color: theme.colorScheme.onErrorContainer), ), ), - ], - child: child, - ); + ), + ], + ); + if (action == null) return; + if (!context.mounted) return; + + switch (action) { + case _MemberActions.mention: + onMention?.call(); + return; + case _MemberActions.setRole: + final power = await showPermissionChooser( + context, + currentLevel: user.powerLevel, + maxLevel: user.room.ownPowerLevel, + ); + if (power == null) return; + if (!context.mounted) return; + if (power >= 100) { + final consent = await showOkCancelAlertDialog( + context: context, + title: L10n.of(context).areYouSure, + message: L10n.of(context).makeAdminDescription, + ); + if (consent != OkCancelResult.ok) return; + if (!context.mounted) return; + } + await showFutureLoadingDialog( + context: context, + future: () => user.setPower(power), + ); + return; + case _MemberActions.kick: + if (await showOkCancelAlertDialog( + useRootNavigator: false, + context: context, + title: L10n.of(context).areYouSure, + okLabel: L10n.of(context).yes, + cancelLabel: L10n.of(context).no, + message: L10n.of(context).kickUserDescription, + ) == + OkCancelResult.ok) { + await showFutureLoadingDialog( + context: context, + future: () => user.kick(), + ); + } + return; + case _MemberActions.ban: + if (await showOkCancelAlertDialog( + useRootNavigator: false, + context: context, + title: L10n.of(context).areYouSure, + okLabel: L10n.of(context).yes, + cancelLabel: L10n.of(context).no, + message: L10n.of(context).banUserDescription, + ) == + OkCancelResult.ok) { + await showFutureLoadingDialog( + context: context, + future: () => user.ban(), + ); + } + return; + case _MemberActions.report: + final score = await showModalActionPopup( + context: context, + title: L10n.of(context).reportUser, + message: L10n.of(context).howOffensiveIsThisContent, + cancelLabel: L10n.of(context).cancel, + actions: [ + AdaptiveModalAction( + value: -100, + label: L10n.of(context).extremeOffensive, + ), + AdaptiveModalAction( + value: -50, + label: L10n.of(context).offensive, + ), + AdaptiveModalAction( + value: 0, + label: L10n.of(context).inoffensive, + ), + ], + ); + if (score == null) return; + final reason = await showTextInputDialog( + useRootNavigator: false, + context: context, + title: L10n.of(context).whyDoYouWantToReportThis, + okLabel: L10n.of(context).ok, + cancelLabel: L10n.of(context).cancel, + hintText: L10n.of(context).reason, + ); + if (reason == null || reason.isEmpty) return; + + final result = await showFutureLoadingDialog( + context: context, + future: () => user.room.client.reportEvent( + user.room.id, + user.id, + reason: reason, + score: score, + ), + ); + if (result.error != null) return; + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text(L10n.of(context).contentHasBeenReported)), + ); + return; + case _MemberActions.info: + await UserDialog.show( + context: context, + profile: Profile( + userId: user.id, + displayName: user.displayName, + avatarUrl: user.avatarUrl, + ), + ); + return; + case _MemberActions.unban: + if (await showOkCancelAlertDialog( + useRootNavigator: false, + context: context, + title: L10n.of(context).areYouSure, + okLabel: L10n.of(context).yes, + cancelLabel: L10n.of(context).no, + message: L10n.of(context).unbanUserDescription, + ) == + OkCancelResult.ok) { + await showFutureLoadingDialog( + context: context, + future: () => user.unban(), + ); + } } } diff --git a/lib/widgets/permission_slider_dialog.dart b/lib/widgets/permission_slider_dialog.dart index e76096bcd..0d2d365ea 100644 --- a/lib/widgets/permission_slider_dialog.dart +++ b/lib/widgets/permission_slider_dialog.dart @@ -1,8 +1,10 @@ -import 'package:fluffychat/widgets/adaptive_dialogs/adaptive_dialog_action.dart'; -import 'package:fluffychat/widgets/adaptive_dialogs/dialog_text_field.dart'; import 'package:flutter/material.dart'; + import 'package:flutter_gen/gen_l10n/l10n.dart'; +import 'package:fluffychat/widgets/adaptive_dialogs/adaptive_dialog_action.dart'; +import 'package:fluffychat/widgets/adaptive_dialogs/dialog_text_field.dart'; + Future showPermissionChooser( BuildContext context, { int currentLevel = 0,