chore: Adjust power level UX
This commit is contained in:
parent
1ea607f633
commit
47934a3378
4 changed files with 187 additions and 107 deletions
|
|
@ -3126,5 +3126,12 @@
|
|||
"theProcessWasCanceled": "The process was canceled.",
|
||||
"join": "Join",
|
||||
"searchOrEnterHomeserverAddress": "Search or enter homeserver address",
|
||||
"matrixId": "Matrix ID"
|
||||
"matrixId": "Matrix ID",
|
||||
"setPowerLevel": "Set power level",
|
||||
"makeModerator": "Make moderator",
|
||||
"makeAdmin": "Make admin",
|
||||
"removeModeratorRights": "Remove moderator rights",
|
||||
"removeAdminRights": "Remove admin rights",
|
||||
"powerLevel": "Power level",
|
||||
"setPowerLevelDescription": "Power levels define what a member is allowed to do in this room and usually range between 0 and 100."
|
||||
}
|
||||
|
|
|
|||
|
|
@ -210,6 +210,7 @@ class Message extends StatelessWidget {
|
|||
singleSelected && event.room.canSendDefaultMessages;
|
||||
|
||||
final enterThread = this.enterThread;
|
||||
final sender = event.senderFromMemoryOrFallback;
|
||||
|
||||
return Center(
|
||||
child: Swipeable(
|
||||
|
|
@ -358,9 +359,7 @@ class Message extends StatelessWidget {
|
|||
FutureBuilder<User?>(
|
||||
future: event.fetchSenderUser(),
|
||||
builder: (context, snapshot) {
|
||||
final user =
|
||||
snapshot.data ??
|
||||
event.senderFromMemoryOrFallback;
|
||||
final user = snapshot.data ?? sender;
|
||||
return Avatar(
|
||||
mxContent: user.avatarUrl,
|
||||
name: user.calcDisplayname(),
|
||||
|
|
@ -392,52 +391,78 @@ class Message extends StatelessWidget {
|
|||
ownMessage ||
|
||||
event.room.isDirectChat
|
||||
? const SizedBox(height: 12)
|
||||
: FutureBuilder<User?>(
|
||||
future: event
|
||||
.fetchSenderUser(),
|
||||
builder: (context, snapshot) {
|
||||
final displayname =
|
||||
snapshot.data
|
||||
?.calcDisplayname() ??
|
||||
event
|
||||
.senderFromMemoryOrFallback
|
||||
.calcDisplayname();
|
||||
return Text(
|
||||
displayname,
|
||||
style: TextStyle(
|
||||
fontSize: 11,
|
||||
fontWeight:
|
||||
FontWeight.bold,
|
||||
color:
|
||||
(theme.brightness ==
|
||||
Brightness
|
||||
.light
|
||||
? displayname
|
||||
.color
|
||||
: displayname
|
||||
.lightColorText),
|
||||
shadows:
|
||||
!wallpaperMode
|
||||
? null
|
||||
: [
|
||||
const Shadow(
|
||||
offset:
|
||||
Offset(
|
||||
0.0,
|
||||
0.0,
|
||||
),
|
||||
blurRadius:
|
||||
3,
|
||||
color: Colors
|
||||
.black,
|
||||
),
|
||||
],
|
||||
: Row(
|
||||
children: [
|
||||
if (sender.powerLevel >=
|
||||
50)
|
||||
Padding(
|
||||
padding:
|
||||
const EdgeInsets.only(
|
||||
right: 2.0,
|
||||
),
|
||||
child: Icon(
|
||||
sender.powerLevel >=
|
||||
100
|
||||
? Icons
|
||||
.admin_panel_settings
|
||||
: Icons
|
||||
.add_moderator_outlined,
|
||||
size: 14,
|
||||
color: theme
|
||||
.colorScheme
|
||||
.onPrimaryContainer,
|
||||
),
|
||||
),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow
|
||||
.ellipsis,
|
||||
);
|
||||
},
|
||||
Expanded(
|
||||
child: FutureBuilder<User?>(
|
||||
future: event
|
||||
.fetchSenderUser(),
|
||||
builder: (context, snapshot) {
|
||||
final displayname =
|
||||
snapshot.data
|
||||
?.calcDisplayname() ??
|
||||
sender
|
||||
.calcDisplayname();
|
||||
return Text(
|
||||
displayname,
|
||||
style: TextStyle(
|
||||
fontSize: 11,
|
||||
fontWeight:
|
||||
FontWeight
|
||||
.bold,
|
||||
color:
|
||||
(theme.brightness ==
|
||||
Brightness
|
||||
.light
|
||||
? displayname
|
||||
.color
|
||||
: displayname
|
||||
.lightColorText),
|
||||
shadows:
|
||||
!wallpaperMode
|
||||
? null
|
||||
: [
|
||||
const Shadow(
|
||||
offset: Offset(
|
||||
0.0,
|
||||
0.0,
|
||||
),
|
||||
blurRadius:
|
||||
3,
|
||||
color:
|
||||
Colors.black,
|
||||
),
|
||||
],
|
||||
),
|
||||
maxLines: 1,
|
||||
overflow:
|
||||
TextOverflow
|
||||
.ellipsis,
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Container(
|
||||
|
|
|
|||
|
|
@ -43,13 +43,7 @@ Future<void> showMemberActionsPopupMenu({
|
|||
child: Row(
|
||||
spacing: 12.0,
|
||||
children: [
|
||||
Avatar(
|
||||
name: displayname,
|
||||
size: 30,
|
||||
mxContent: user.avatarUrl,
|
||||
presenceUserId: user.id,
|
||||
presenceBackgroundColor: theme.colorScheme.surfaceContainer,
|
||||
),
|
||||
Avatar(name: displayname, size: 30, mxContent: user.avatarUrl),
|
||||
ConstrainedBox(
|
||||
constraints: const BoxConstraints(maxWidth: 200),
|
||||
child: Text(
|
||||
|
|
@ -83,31 +77,71 @@ Future<void> showMemberActionsPopupMenu({
|
|||
],
|
||||
),
|
||||
),
|
||||
PopupMenuItem(
|
||||
enabled: user.room.canChangePowerLevel && user.canChangeUserPowerLevel,
|
||||
value: _MemberActions.setRole,
|
||||
child: Row(
|
||||
children: [
|
||||
const Icon(Icons.admin_panel_settings_outlined),
|
||||
const SizedBox(width: 18),
|
||||
Column(
|
||||
mainAxisSize: .min,
|
||||
crossAxisAlignment: .start,
|
||||
if (user.canChangeUserPowerLevel) ...[
|
||||
if (user.powerLevel < 100)
|
||||
PopupMenuItem(
|
||||
value: _MemberActions.makeAdmin,
|
||||
child: Row(
|
||||
children: [
|
||||
Text(L10n.of(context).chatPermissions),
|
||||
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),
|
||||
),
|
||||
const Icon(Icons.admin_panel_settings_outlined),
|
||||
const SizedBox(width: 18),
|
||||
Text(L10n.of(context).makeAdmin),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
if (user.powerLevel < 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 >= 100)
|
||||
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 >= 50)
|
||||
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 ||
|
||||
!{0, 50, 100}.contains(user.powerLevel))
|
||||
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 (!{0, 50, 100}.contains(user.powerLevel))
|
||||
Text(' (${user.powerLevel})'),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
if (user.canKick)
|
||||
PopupMenuItem(
|
||||
value: _MemberActions.kick,
|
||||
|
|
@ -179,7 +213,7 @@ Future<void> showMemberActionsPopupMenu({
|
|||
case _MemberActions.mention:
|
||||
onMention?.call();
|
||||
return;
|
||||
case _MemberActions.setRole:
|
||||
case _MemberActions.setPowerLevel:
|
||||
final power = await showPermissionChooser(
|
||||
context,
|
||||
currentLevel: user.powerLevel,
|
||||
|
|
@ -280,13 +314,48 @@ Future<void> showMemberActionsPopupMenu({
|
|||
future: () => user.unban(),
|
||||
);
|
||||
}
|
||||
case _MemberActions.makeAdmin:
|
||||
if (user.room.ownPowerLevel <= 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,
|
||||
setRole,
|
||||
setPowerLevel,
|
||||
makeAdmin,
|
||||
makeModerator,
|
||||
removeAdmin,
|
||||
removeModerator,
|
||||
kick,
|
||||
ban,
|
||||
approve,
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ Future<int?> showPermissionChooser(
|
|||
int currentLevel = 0,
|
||||
int maxLevel = 100,
|
||||
}) async {
|
||||
final controller = TextEditingController();
|
||||
final controller = TextEditingController(text: currentLevel.toString());
|
||||
final error = ValueNotifier<String?>(null);
|
||||
return await showAdaptiveDialog<int>(
|
||||
context: context,
|
||||
|
|
@ -22,7 +22,7 @@ Future<int?> showPermissionChooser(
|
|||
crossAxisAlignment: .stretch,
|
||||
spacing: 12.0,
|
||||
children: [
|
||||
Text(L10n.of(context).setPermissionsLevelDescription),
|
||||
Text(L10n.of(context).setPowerLevelDescription),
|
||||
ValueListenableBuilder(
|
||||
valueListenable: error,
|
||||
builder: (context, errorText, _) => DialogTextField(
|
||||
|
|
@ -38,8 +38,6 @@ Future<int?> showPermissionChooser(
|
|||
),
|
||||
actions: [
|
||||
AdaptiveDialogAction(
|
||||
bigButtons: true,
|
||||
borderRadius: AdaptiveDialogAction.topRadius,
|
||||
onPressed: () {
|
||||
final level = int.tryParse(controller.text.trim());
|
||||
if (level == null) {
|
||||
|
|
@ -52,31 +50,12 @@ Future<int?> showPermissionChooser(
|
|||
}
|
||||
Navigator.of(context).pop<int>(level);
|
||||
},
|
||||
child: Text(L10n.of(context).setCustomPermissionLevel),
|
||||
child: Text(L10n.of(context).setPowerLevel),
|
||||
),
|
||||
AdaptiveDialogAction(
|
||||
onPressed: () => Navigator.of(context).pop<int>(null),
|
||||
child: Text(L10n.of(context).cancel),
|
||||
),
|
||||
if (maxLevel >= 100 && currentLevel != 100)
|
||||
AdaptiveDialogAction(
|
||||
borderRadius: AdaptiveDialogAction.centerRadius,
|
||||
bigButtons: true,
|
||||
onPressed: () => Navigator.of(context).pop<int>(100),
|
||||
child: Text(L10n.of(context).admin),
|
||||
),
|
||||
if (maxLevel >= 50 && currentLevel != 50)
|
||||
AdaptiveDialogAction(
|
||||
borderRadius: maxLevel != 0
|
||||
? AdaptiveDialogAction.centerRadius
|
||||
: AdaptiveDialogAction.bottomRadius,
|
||||
bigButtons: true,
|
||||
onPressed: () => Navigator.of(context).pop<int>(50),
|
||||
child: Text(L10n.of(context).moderator),
|
||||
),
|
||||
if (currentLevel != 0)
|
||||
AdaptiveDialogAction(
|
||||
borderRadius: AdaptiveDialogAction.bottomRadius,
|
||||
bigButtons: true,
|
||||
onPressed: () => Navigator.of(context).pop<int>(0),
|
||||
child: Text(L10n.of(context).normalUser),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue