Initial commit
This commit is contained in:
377
lib/widgets/member_actions_popup_menu_button.dart
Normal file
377
lib/widgets/member_actions_popup_menu_button.dart
Normal file
@@ -0,0 +1,377 @@
|
||||
// SPDX-FileCopyrightText: 2019-Present Christian Kußowski
|
||||
// SPDX-FileCopyrightText: 2019-Present Contributors to FluffyChat
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
import 'package:tatchat/l10n/l10n.dart';
|
||||
import 'package:tatchat/widgets/permission_slider_dialog.dart';
|
||||
import 'package:material_ui/material_ui.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
import 'adaptive_dialogs/show_ok_cancel_alert_dialog.dart';
|
||||
import 'adaptive_dialogs/show_text_input_dialog.dart';
|
||||
import 'adaptive_dialogs/user_dialog.dart';
|
||||
import 'avatar.dart';
|
||||
import 'future_loading_dialog.dart';
|
||||
|
||||
Future<void> showMemberActionsPopupMenu({
|
||||
required BuildContext context,
|
||||
required User user,
|
||||
void Function()? onMention,
|
||||
}) async {
|
||||
final l10n = L10n.of(context);
|
||||
final scaffoldMessenger = ScaffoldMessenger.of(context);
|
||||
final theme = Theme.of(context);
|
||||
final displayname = user.calcDisplayname();
|
||||
final isMe = user.room.client.userID == user.id;
|
||||
|
||||
final overlay = Overlay.of(context).context.findRenderObject() as RenderBox;
|
||||
|
||||
final button = context.findRenderObject() as RenderBox;
|
||||
|
||||
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,
|
||||
);
|
||||
|
||||
const defaultPowerLevels = {0, 50, 100, 9007199254740991};
|
||||
|
||||
final action = await showMenu<_MemberActions>(
|
||||
context: context,
|
||||
position: position,
|
||||
items: <PopupMenuEntry<_MemberActions>>[
|
||||
PopupMenuItem(
|
||||
value: _MemberActions.info,
|
||||
child: Row(
|
||||
spacing: 12.0,
|
||||
children: [
|
||||
Avatar(name: displayname, size: 30, mxContent: user.avatarUrl),
|
||||
ConstrainedBox(
|
||||
constraints: const BoxConstraints(maxWidth: 200),
|
||||
child: Text(
|
||||
displayname,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (onMention != null)
|
||||
PopupMenuItem(
|
||||
value: _MemberActions.mention,
|
||||
child: Row(
|
||||
children: [
|
||||
const Icon(Icons.alternate_email_outlined),
|
||||
const SizedBox(width: 18),
|
||||
Text(L10n.of(context).mention),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (user.membership == Membership.knock)
|
||||
PopupMenuItem(
|
||||
value: _MemberActions.approve,
|
||||
child: Row(
|
||||
children: [
|
||||
const Icon(Icons.how_to_reg_outlined),
|
||||
const SizedBox(width: 18),
|
||||
Text(L10n.of(context).approve),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (user.canChangeUserPowerLevel) ...[
|
||||
if (user.powerLevel.level < 100)
|
||||
PopupMenuItem(
|
||||
value: _MemberActions.makeAdmin,
|
||||
child: Row(
|
||||
children: [
|
||||
const Icon(Icons.admin_panel_settings_outlined),
|
||||
const SizedBox(width: 18),
|
||||
Text(L10n.of(context).makeAdmin),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (user.powerLevel.level < 50)
|
||||
PopupMenuItem(
|
||||
value: _MemberActions.makeModerator,
|
||||
child: Row(
|
||||
children: [
|
||||
const Icon(Icons.add_moderator_outlined),
|
||||
const SizedBox(width: 18),
|
||||
Text(L10n.of(context).makeModerator),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (user.powerLevel.role == PowerLevelRole.admin)
|
||||
PopupMenuItem(
|
||||
value: _MemberActions.removeAdmin,
|
||||
child: Row(
|
||||
children: [
|
||||
const Icon(Icons.remove_moderator_outlined),
|
||||
const SizedBox(width: 18),
|
||||
Text(L10n.of(context).removeAdminRights),
|
||||
],
|
||||
),
|
||||
)
|
||||
else if (user.powerLevel.role == PowerLevelRole.moderator)
|
||||
PopupMenuItem(
|
||||
value: _MemberActions.removeModerator,
|
||||
child: Row(
|
||||
children: [
|
||||
const Icon(Icons.remove_moderator_outlined),
|
||||
const SizedBox(width: 18),
|
||||
Text(L10n.of(context).removeModeratorRights),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
if (user.canChangeUserPowerLevel ||
|
||||
!defaultPowerLevels.contains(user.powerLevel.level))
|
||||
PopupMenuItem(
|
||||
value: _MemberActions.setPowerLevel,
|
||||
enabled: user.canChangeUserPowerLevel,
|
||||
child: Row(
|
||||
children: [
|
||||
const Icon(Icons.manage_accounts_outlined),
|
||||
const SizedBox(width: 18),
|
||||
Text(
|
||||
user.canChangeUserPowerLevel
|
||||
? L10n.of(context).setPowerLevel
|
||||
: L10n.of(context).powerLevel,
|
||||
),
|
||||
if (!defaultPowerLevels.contains(user.powerLevel.level))
|
||||
Text(' (${user.powerLevel})'),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (user.canKick)
|
||||
PopupMenuItem(
|
||||
value: _MemberActions.kick,
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(
|
||||
Icons.person_remove_outlined,
|
||||
color: theme.colorScheme.onErrorContainer,
|
||||
),
|
||||
const SizedBox(width: 18),
|
||||
Text(
|
||||
L10n.of(context).kickFromChat,
|
||||
style: TextStyle(color: theme.colorScheme.onErrorContainer),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (user.canBan && user.membership != Membership.ban)
|
||||
PopupMenuItem(
|
||||
value: _MemberActions.ban,
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(
|
||||
Icons.block_outlined,
|
||||
color: theme.colorScheme.onErrorContainer,
|
||||
),
|
||||
const SizedBox(width: 18),
|
||||
Text(
|
||||
L10n.of(context).banFromChat,
|
||||
style: TextStyle(color: theme.colorScheme.onErrorContainer),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (user.canBan && user.membership == Membership.ban)
|
||||
PopupMenuItem(
|
||||
value: _MemberActions.unban,
|
||||
child: Row(
|
||||
children: [
|
||||
const Icon(Icons.warning),
|
||||
const SizedBox(width: 18),
|
||||
Text(L10n.of(context).unbanFromChat),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (!isMe)
|
||||
PopupMenuItem(
|
||||
value: _MemberActions.report,
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(
|
||||
Icons.gavel_outlined,
|
||||
color: theme.colorScheme.onErrorContainer,
|
||||
),
|
||||
const SizedBox(width: 18),
|
||||
Text(
|
||||
L10n.of(context).reportUser,
|
||||
style: TextStyle(color: theme.colorScheme.onErrorContainer),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
if (action == null) return;
|
||||
if (!context.mounted) return;
|
||||
|
||||
switch (action) {
|
||||
case _MemberActions.mention:
|
||||
onMention?.call();
|
||||
return;
|
||||
case _MemberActions.setPowerLevel:
|
||||
final power = await showPermissionChooser(
|
||||
context,
|
||||
currentLevel: user.powerLevel.level,
|
||||
maxLevel: user.room.ownPowerLevel.level,
|
||||
);
|
||||
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.approve:
|
||||
await showFutureLoadingDialog(
|
||||
context: context,
|
||||
future: () => user.room.invite(user.id),
|
||||
);
|
||||
return;
|
||||
case _MemberActions.kick:
|
||||
if (await showOkCancelAlertDialog(
|
||||
context: context,
|
||||
title: l10n.areYouSure,
|
||||
okLabel: l10n.yes,
|
||||
cancelLabel: l10n.no,
|
||||
message: l10n.kickUserDescription,
|
||||
) ==
|
||||
OkCancelResult.ok) {
|
||||
if (!context.mounted) return;
|
||||
await showFutureLoadingDialog(
|
||||
context: context,
|
||||
future: () => user.kick(),
|
||||
);
|
||||
}
|
||||
return;
|
||||
case _MemberActions.ban:
|
||||
if (await showOkCancelAlertDialog(
|
||||
context: context,
|
||||
title: l10n.areYouSure,
|
||||
okLabel: l10n.yes,
|
||||
cancelLabel: l10n.no,
|
||||
message: l10n.banUserDescription,
|
||||
) ==
|
||||
OkCancelResult.ok) {
|
||||
if (!context.mounted) return;
|
||||
await showFutureLoadingDialog(
|
||||
context: context,
|
||||
future: () => user.ban(),
|
||||
);
|
||||
}
|
||||
return;
|
||||
case _MemberActions.report:
|
||||
final reason = await showTextInputDialog(
|
||||
context: context,
|
||||
title: l10n.whyDoYouWantToReportThis,
|
||||
okLabel: l10n.report,
|
||||
cancelLabel: l10n.cancel,
|
||||
hintText: l10n.reason,
|
||||
);
|
||||
if (reason == null || reason.isEmpty) return;
|
||||
if (!context.mounted) return;
|
||||
|
||||
final result = await showFutureLoadingDialog(
|
||||
context: context,
|
||||
future: () => user.room.client.reportUser(user.id, reason),
|
||||
);
|
||||
if (result.error != null) return;
|
||||
if (!context.mounted) return;
|
||||
scaffoldMessenger.showSnackBar(
|
||||
SnackBar(content: Text(l10n.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(
|
||||
context: context,
|
||||
title: l10n.areYouSure,
|
||||
okLabel: l10n.yes,
|
||||
cancelLabel: l10n.no,
|
||||
message: l10n.unbanUserDescription,
|
||||
) ==
|
||||
OkCancelResult.ok) {
|
||||
if (!context.mounted) return;
|
||||
await showFutureLoadingDialog(
|
||||
context: context,
|
||||
future: () => user.unban(),
|
||||
);
|
||||
}
|
||||
case _MemberActions.makeAdmin:
|
||||
if (user.room.ownPowerLevel.level <= 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(100),
|
||||
);
|
||||
case _MemberActions.makeModerator:
|
||||
await showFutureLoadingDialog(
|
||||
context: context,
|
||||
future: () => user.setPower(50),
|
||||
);
|
||||
case _MemberActions.removeAdmin:
|
||||
case _MemberActions.removeModerator:
|
||||
final defaultUserLevel =
|
||||
user.room
|
||||
.getState(EventTypes.RoomPowerLevels)
|
||||
?.content
|
||||
.tryGet<int>('users_default') ??
|
||||
0;
|
||||
await showFutureLoadingDialog(
|
||||
context: context,
|
||||
future: () => user.setPower(defaultUserLevel),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
enum _MemberActions {
|
||||
info,
|
||||
mention,
|
||||
setPowerLevel,
|
||||
makeAdmin,
|
||||
makeModerator,
|
||||
removeAdmin,
|
||||
removeModerator,
|
||||
kick,
|
||||
ban,
|
||||
approve,
|
||||
unban,
|
||||
report,
|
||||
}
|
||||
Reference in New Issue
Block a user