mirror of
https://github.com/krille-chan/fluffychat
synced 2024-09-10 11:45:10 +00:00
design: Improve user permission settings
This commit is contained in:
parent
ac7e424b7b
commit
216d3bd403
5 changed files with 312 additions and 325 deletions
|
@ -2525,6 +2525,7 @@
|
|||
"@thisDevice": {},
|
||||
"initAppError": "An error occured while init the app",
|
||||
"@initAppError": {},
|
||||
"userRole": "User role",
|
||||
"minimumPowerLevel": "{level} is the minimum power level.",
|
||||
"@minimumPowerLevel": {
|
||||
"type": "text",
|
||||
|
|
|
@ -2,7 +2,6 @@ import 'dart:developer';
|
|||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:adaptive_dialog/adaptive_dialog.dart';
|
||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
import 'package:future_loading_dialog/future_loading_dialog.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
@ -10,6 +9,7 @@ import 'package:matrix/matrix.dart';
|
|||
|
||||
import 'package:fluffychat/pages/chat_permissions_settings/chat_permissions_settings_view.dart';
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
import 'package:fluffychat/widgets/permission_slider_dialog.dart';
|
||||
|
||||
class ChatPermissionsSettings extends StatefulWidget {
|
||||
const ChatPermissionsSettings({super.key});
|
||||
|
@ -35,30 +35,9 @@ class ChatPermissionsSettingsController extends State<ChatPermissionsSettings> {
|
|||
);
|
||||
return;
|
||||
}
|
||||
newLevel ??= int.tryParse(
|
||||
(await showTextInputDialog(
|
||||
context: context,
|
||||
title: L10n.of(context)!.setPermissionsLevel,
|
||||
textFields: [
|
||||
DialogTextField(
|
||||
initialText: currentLevel.toString(),
|
||||
keyboardType: TextInputType.number,
|
||||
autocorrect: false,
|
||||
validator: (text) {
|
||||
if (text == null) {
|
||||
return L10n.of(context)!.pleaseEnterANumber;
|
||||
}
|
||||
final level = int.tryParse(text);
|
||||
if (level == null || level < 0) {
|
||||
return L10n.of(context)!.pleaseEnterANumber;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
],
|
||||
))
|
||||
?.singleOrNull ??
|
||||
'',
|
||||
newLevel ??= await showPermissionChooser(
|
||||
context,
|
||||
currentLevel: currentLevel,
|
||||
);
|
||||
if (newLevel == null) return;
|
||||
final content = Map<String, dynamic>.from(
|
||||
|
|
|
@ -17,7 +17,6 @@ enum UserBottomSheetAction {
|
|||
ban,
|
||||
kick,
|
||||
unban,
|
||||
permission,
|
||||
message,
|
||||
ignore,
|
||||
}
|
||||
|
@ -201,30 +200,6 @@ class UserBottomSheetController extends State<UserBottomSheet> {
|
|||
Navigator.of(context).pop();
|
||||
}
|
||||
break;
|
||||
case UserBottomSheetAction.permission:
|
||||
if (user == null) throw ('User must not be null for this action!');
|
||||
final newPermission = await showPermissionChooser(
|
||||
context,
|
||||
currentLevel: user.powerLevel,
|
||||
);
|
||||
if (newPermission != null) {
|
||||
if (newPermission == 100 &&
|
||||
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)!.makeAdminDescription,
|
||||
) !=
|
||||
OkCancelResult.ok) break;
|
||||
await showFutureLoadingDialog(
|
||||
context: context,
|
||||
future: () => user.setPower(newPermission),
|
||||
);
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
break;
|
||||
case UserBottomSheetAction.message:
|
||||
Navigator.of(context).pop();
|
||||
// Workaround for https://github.com/flutter/flutter/issues/27495
|
||||
|
@ -270,6 +245,35 @@ class UserBottomSheetController extends State<UserBottomSheet> {
|
|||
Navigator.of(context).pop();
|
||||
}
|
||||
|
||||
void setPowerLevel(int? newLevel) async {
|
||||
final user = widget.user;
|
||||
if (user == null) throw ('User must not be null for this action!');
|
||||
|
||||
final level = newLevel ??
|
||||
await showPermissionChooser(
|
||||
context,
|
||||
currentLevel: user.powerLevel,
|
||||
);
|
||||
if (level == null) return;
|
||||
|
||||
if (level == 100) {
|
||||
final consent = 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)!.makeAdminDescription,
|
||||
);
|
||||
if (consent != OkCancelResult.ok) return;
|
||||
}
|
||||
|
||||
await showFutureLoadingDialog(
|
||||
context: context,
|
||||
future: () => user.setPower(level),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => UserBottomSheetView(this);
|
||||
}
|
||||
|
|
|
@ -104,228 +104,277 @@ class UserBottomSheetView extends StatelessWidget {
|
|||
),
|
||||
],
|
||||
),
|
||||
body: ListView(
|
||||
children: [
|
||||
if (user?.membership == Membership.knock)
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(12.0),
|
||||
child: Material(
|
||||
color: Theme.of(context).colorScheme.surfaceVariant,
|
||||
borderRadius: BorderRadius.circular(AppConfig.borderRadius),
|
||||
child: ListTile(
|
||||
minVerticalPadding: 16,
|
||||
title: Padding(
|
||||
padding: const EdgeInsets.only(bottom: 12.0),
|
||||
child: Text(
|
||||
L10n.of(context)!
|
||||
.userWouldLikeToChangeTheChat(displayname),
|
||||
body: StreamBuilder<Object>(
|
||||
stream: user?.room.client.onSync.stream.where(
|
||||
(syncUpdate) =>
|
||||
syncUpdate.rooms?.join?[user.room.id]?.timeline?.events?.any(
|
||||
(state) => state.type == EventTypes.RoomPowerLevels,
|
||||
) ??
|
||||
false,
|
||||
),
|
||||
builder: (context, snapshot) {
|
||||
return ListView(
|
||||
children: [
|
||||
if (user?.membership == Membership.knock)
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(12.0),
|
||||
child: Material(
|
||||
color: Theme.of(context).colorScheme.surfaceVariant,
|
||||
borderRadius:
|
||||
BorderRadius.circular(AppConfig.borderRadius),
|
||||
child: ListTile(
|
||||
minVerticalPadding: 16,
|
||||
title: Padding(
|
||||
padding: const EdgeInsets.only(bottom: 12.0),
|
||||
child: Text(
|
||||
L10n.of(context)!
|
||||
.userWouldLikeToChangeTheChat(displayname),
|
||||
),
|
||||
),
|
||||
subtitle: Row(
|
||||
children: [
|
||||
TextButton.icon(
|
||||
style: TextButton.styleFrom(
|
||||
backgroundColor:
|
||||
Theme.of(context).colorScheme.background,
|
||||
foregroundColor:
|
||||
Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
onPressed: controller.knockAccept,
|
||||
icon: const Icon(Icons.check_outlined),
|
||||
label: Text(L10n.of(context)!.accept),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
TextButton.icon(
|
||||
style: TextButton.styleFrom(
|
||||
backgroundColor: Theme.of(context)
|
||||
.colorScheme
|
||||
.errorContainer,
|
||||
foregroundColor: Theme.of(context)
|
||||
.colorScheme
|
||||
.onErrorContainer,
|
||||
),
|
||||
onPressed: controller.knockDecline,
|
||||
icon: const Icon(Icons.cancel_outlined),
|
||||
label: Text(L10n.of(context)!.decline),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
subtitle: Row(
|
||||
children: [
|
||||
TextButton.icon(
|
||||
style: TextButton.styleFrom(
|
||||
backgroundColor:
|
||||
Theme.of(context).colorScheme.background,
|
||||
foregroundColor:
|
||||
Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Material(
|
||||
elevation: Theme.of(context)
|
||||
.appBarTheme
|
||||
.scrolledUnderElevation ??
|
||||
4,
|
||||
shadowColor: Theme.of(context).appBarTheme.shadowColor,
|
||||
shape: RoundedRectangleBorder(
|
||||
side: BorderSide(
|
||||
color: Theme.of(context).dividerColor,
|
||||
),
|
||||
borderRadius: BorderRadius.circular(
|
||||
Avatar.defaultSize * 2.5,
|
||||
),
|
||||
onPressed: controller.knockAccept,
|
||||
icon: const Icon(Icons.check_outlined),
|
||||
label: Text(L10n.of(context)!.accept),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
TextButton.icon(
|
||||
style: TextButton.styleFrom(
|
||||
backgroundColor:
|
||||
Theme.of(context).colorScheme.errorContainer,
|
||||
foregroundColor:
|
||||
Theme.of(context).colorScheme.onErrorContainer,
|
||||
child: Avatar(
|
||||
mxContent: avatarUrl,
|
||||
name: displayname,
|
||||
size: Avatar.defaultSize * 2.5,
|
||||
fontSize: 18 * 2.5,
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
TextButton.icon(
|
||||
onPressed: () => FluffyShare.share(
|
||||
'https://matrix.to/#/$userId',
|
||||
context,
|
||||
),
|
||||
icon: Icon(
|
||||
Icons.adaptive.share_outlined,
|
||||
size: 16,
|
||||
),
|
||||
style: TextButton.styleFrom(
|
||||
foregroundColor:
|
||||
Theme.of(context).colorScheme.onBackground,
|
||||
),
|
||||
label: Text(
|
||||
displayname,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
// style: const TextStyle(fontSize: 18),
|
||||
),
|
||||
),
|
||||
onPressed: controller.knockDecline,
|
||||
icon: const Icon(Icons.cancel_outlined),
|
||||
label: Text(L10n.of(context)!.decline),
|
||||
TextButton.icon(
|
||||
onPressed: () => FluffyShare.share(
|
||||
userId,
|
||||
context,
|
||||
copyOnly: true,
|
||||
),
|
||||
icon: const Icon(
|
||||
Icons.copy_outlined,
|
||||
size: 14,
|
||||
),
|
||||
style: TextButton.styleFrom(
|
||||
foregroundColor:
|
||||
Theme.of(context).colorScheme.secondary,
|
||||
),
|
||||
label: Text(
|
||||
userId,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
// style: const TextStyle(fontSize: 12),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
if (userId != client.userID)
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 16.0,
|
||||
vertical: 8.0,
|
||||
),
|
||||
child: ElevatedButton.icon(
|
||||
onPressed: () => controller
|
||||
.participantAction(UserBottomSheetAction.message),
|
||||
icon: const Icon(Icons.forum_outlined),
|
||||
label: Text(
|
||||
controller.widget.user == null
|
||||
? L10n.of(context)!.startConversation
|
||||
: L10n.of(context)!.sendAMessage,
|
||||
),
|
||||
),
|
||||
),
|
||||
PresenceBuilder(
|
||||
userId: userId,
|
||||
client: client,
|
||||
builder: (context, presence) {
|
||||
final status = presence?.statusMsg;
|
||||
if (status == null || status.isEmpty) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
return ListTile(
|
||||
title: SelectableLinkify(
|
||||
text: status,
|
||||
style: const TextStyle(fontSize: 16),
|
||||
options: const LinkifyOptions(humanize: false),
|
||||
linkStyle: const TextStyle(
|
||||
color: Colors.blueAccent,
|
||||
decorationColor: Colors.blueAccent,
|
||||
),
|
||||
onOpen: (url) =>
|
||||
UrlLauncher(context, url.url).launchUrl(),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
if (controller.widget.onMention != null)
|
||||
ListTile(
|
||||
leading: const Icon(Icons.alternate_email_outlined),
|
||||
title: Text(L10n.of(context)!.mention),
|
||||
onTap: () => controller
|
||||
.participantAction(UserBottomSheetAction.mention),
|
||||
),
|
||||
if (user != null) ...[
|
||||
Divider(height: 1, color: Theme.of(context).dividerColor),
|
||||
ListTile(
|
||||
title: Text(
|
||||
'${L10n.of(context)!.userRole} (${user.powerLevel})',
|
||||
),
|
||||
leading: const Icon(Icons.person_outlined),
|
||||
trailing: DropdownButton<int>(
|
||||
onChanged: user.canChangePowerLevel
|
||||
? controller.setPowerLevel
|
||||
: null,
|
||||
value: {0, 50, 100}.contains(user.powerLevel)
|
||||
? user.powerLevel
|
||||
: null,
|
||||
items: [
|
||||
DropdownMenuItem(
|
||||
value: 0,
|
||||
child: Text(L10n.of(context)!.user),
|
||||
),
|
||||
DropdownMenuItem(
|
||||
value: 50,
|
||||
child: Text(L10n.of(context)!.moderator),
|
||||
),
|
||||
DropdownMenuItem(
|
||||
value: 100,
|
||||
child: Text(L10n.of(context)!.admin),
|
||||
),
|
||||
DropdownMenuItem(
|
||||
value: null,
|
||||
child: Text(L10n.of(context)!.custom),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Material(
|
||||
elevation:
|
||||
Theme.of(context).appBarTheme.scrolledUnderElevation ??
|
||||
4,
|
||||
shadowColor: Theme.of(context).appBarTheme.shadowColor,
|
||||
shape: RoundedRectangleBorder(
|
||||
side: BorderSide(
|
||||
color: Theme.of(context).dividerColor,
|
||||
),
|
||||
borderRadius: BorderRadius.circular(
|
||||
Avatar.defaultSize * 2.5,
|
||||
),
|
||||
Divider(height: 1, color: Theme.of(context).dividerColor),
|
||||
],
|
||||
if (user != null && user.canKick)
|
||||
ListTile(
|
||||
textColor: Theme.of(context).colorScheme.error,
|
||||
iconColor: Theme.of(context).colorScheme.error,
|
||||
title: Text(L10n.of(context)!.kickFromChat),
|
||||
leading: const Icon(Icons.exit_to_app_outlined),
|
||||
onTap: () => controller
|
||||
.participantAction(UserBottomSheetAction.kick),
|
||||
),
|
||||
if (user != null &&
|
||||
user.canBan &&
|
||||
user.membership != Membership.ban)
|
||||
ListTile(
|
||||
textColor: Theme.of(context).colorScheme.onErrorContainer,
|
||||
iconColor: Theme.of(context).colorScheme.onErrorContainer,
|
||||
title: Text(L10n.of(context)!.banFromChat),
|
||||
leading: const Icon(Icons.warning_sharp),
|
||||
onTap: () =>
|
||||
controller.participantAction(UserBottomSheetAction.ban),
|
||||
)
|
||||
else if (user != null &&
|
||||
user.canBan &&
|
||||
user.membership == Membership.ban)
|
||||
ListTile(
|
||||
title: Text(L10n.of(context)!.unbanFromChat),
|
||||
leading: const Icon(Icons.warning_outlined),
|
||||
onTap: () => controller
|
||||
.participantAction(UserBottomSheetAction.unban),
|
||||
),
|
||||
if (user != null && user.id != client.userID)
|
||||
ListTile(
|
||||
textColor: Theme.of(context).colorScheme.onErrorContainer,
|
||||
iconColor: Theme.of(context).colorScheme.onErrorContainer,
|
||||
title: Text(L10n.of(context)!.reportUser),
|
||||
leading: const Icon(Icons.report_outlined),
|
||||
onTap: () => controller
|
||||
.participantAction(UserBottomSheetAction.report),
|
||||
),
|
||||
if (profileSearchError != null)
|
||||
ListTile(
|
||||
leading: const Icon(
|
||||
Icons.warning_outlined,
|
||||
color: Colors.orange,
|
||||
),
|
||||
child: Avatar(
|
||||
mxContent: avatarUrl,
|
||||
name: displayname,
|
||||
size: Avatar.defaultSize * 2.5,
|
||||
fontSize: 18 * 2.5,
|
||||
subtitle: Text(
|
||||
L10n.of(context)!.profileNotFound,
|
||||
style: const TextStyle(color: Colors.orange),
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
TextButton.icon(
|
||||
onPressed: () => FluffyShare.share(
|
||||
'https://matrix.to/#/$userId',
|
||||
context,
|
||||
),
|
||||
icon: Icon(
|
||||
Icons.adaptive.share_outlined,
|
||||
size: 16,
|
||||
),
|
||||
style: TextButton.styleFrom(
|
||||
foregroundColor:
|
||||
Theme.of(context).colorScheme.onBackground,
|
||||
),
|
||||
label: Text(
|
||||
displayname,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
// style: const TextStyle(fontSize: 18),
|
||||
),
|
||||
),
|
||||
TextButton.icon(
|
||||
onPressed: () => FluffyShare.share(
|
||||
userId,
|
||||
context,
|
||||
copyOnly: true,
|
||||
),
|
||||
icon: const Icon(
|
||||
Icons.copy_outlined,
|
||||
size: 14,
|
||||
),
|
||||
style: TextButton.styleFrom(
|
||||
foregroundColor:
|
||||
Theme.of(context).colorScheme.secondary,
|
||||
),
|
||||
label: Text(
|
||||
userId,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
// style: const TextStyle(fontSize: 12),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
if (userId != client.userID)
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 16.0,
|
||||
vertical: 8.0,
|
||||
),
|
||||
child: ElevatedButton.icon(
|
||||
onPressed: () => controller
|
||||
.participantAction(UserBottomSheetAction.message),
|
||||
icon: const Icon(Icons.forum_outlined),
|
||||
label: Text(
|
||||
controller.widget.user == null
|
||||
? L10n.of(context)!.startConversation
|
||||
: L10n.of(context)!.sendAMessage,
|
||||
),
|
||||
),
|
||||
),
|
||||
PresenceBuilder(
|
||||
userId: userId,
|
||||
client: client,
|
||||
builder: (context, presence) {
|
||||
final status = presence?.statusMsg;
|
||||
if (status == null || status.isEmpty) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
return ListTile(
|
||||
title: SelectableLinkify(
|
||||
text: status,
|
||||
style: const TextStyle(fontSize: 16),
|
||||
options: const LinkifyOptions(humanize: false),
|
||||
linkStyle: const TextStyle(
|
||||
color: Colors.blueAccent,
|
||||
decorationColor: Colors.blueAccent,
|
||||
),
|
||||
onOpen: (url) => UrlLauncher(context, url.url).launchUrl(),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
if (controller.widget.onMention != null)
|
||||
ListTile(
|
||||
leading: const Icon(Icons.alternate_email_outlined),
|
||||
title: Text(L10n.of(context)!.mention),
|
||||
onTap: () =>
|
||||
controller.participantAction(UserBottomSheetAction.mention),
|
||||
),
|
||||
if (user != null && user.canChangePowerLevel)
|
||||
ListTile(
|
||||
title: Text(L10n.of(context)!.setPermissionsLevel),
|
||||
leading: const Icon(Icons.edit_attributes_outlined),
|
||||
onTap: () => controller
|
||||
.participantAction(UserBottomSheetAction.permission),
|
||||
),
|
||||
if (user != null && user.canKick)
|
||||
ListTile(
|
||||
title: Text(L10n.of(context)!.kickFromChat),
|
||||
leading: const Icon(Icons.exit_to_app_outlined),
|
||||
onTap: () =>
|
||||
controller.participantAction(UserBottomSheetAction.kick),
|
||||
),
|
||||
if (user != null &&
|
||||
user.canBan &&
|
||||
user.membership != Membership.ban)
|
||||
ListTile(
|
||||
title: Text(L10n.of(context)!.banFromChat),
|
||||
leading: const Icon(Icons.warning_sharp),
|
||||
onTap: () =>
|
||||
controller.participantAction(UserBottomSheetAction.ban),
|
||||
)
|
||||
else if (user != null &&
|
||||
user.canBan &&
|
||||
user.membership == Membership.ban)
|
||||
ListTile(
|
||||
title: Text(L10n.of(context)!.unbanFromChat),
|
||||
leading: const Icon(Icons.warning_outlined),
|
||||
onTap: () =>
|
||||
controller.participantAction(UserBottomSheetAction.unban),
|
||||
),
|
||||
if (user != null && user.id != client.userID)
|
||||
ListTile(
|
||||
textColor: Theme.of(context).colorScheme.onErrorContainer,
|
||||
iconColor: Theme.of(context).colorScheme.onErrorContainer,
|
||||
title: Text(L10n.of(context)!.reportUser),
|
||||
leading: const Icon(Icons.report_outlined),
|
||||
onTap: () =>
|
||||
controller.participantAction(UserBottomSheetAction.report),
|
||||
),
|
||||
if (profileSearchError != null)
|
||||
ListTile(
|
||||
leading: const Icon(
|
||||
Icons.warning_outlined,
|
||||
color: Colors.orange,
|
||||
),
|
||||
subtitle: Text(
|
||||
L10n.of(context)!.profileNotFound,
|
||||
style: const TextStyle(color: Colors.orange),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
|
|
|
@ -4,77 +4,31 @@ import 'package:flutter/material.dart';
|
|||
import 'package:adaptive_dialog/adaptive_dialog.dart';
|
||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
|
||||
enum PermissionLevel {
|
||||
user,
|
||||
moderator,
|
||||
admin,
|
||||
custom,
|
||||
}
|
||||
|
||||
extension on PermissionLevel {
|
||||
String toLocalizedString(BuildContext context) {
|
||||
switch (this) {
|
||||
case PermissionLevel.user:
|
||||
return L10n.of(context)!.user;
|
||||
case PermissionLevel.moderator:
|
||||
return L10n.of(context)!.moderator;
|
||||
case PermissionLevel.admin:
|
||||
return L10n.of(context)!.admin;
|
||||
case PermissionLevel.custom:
|
||||
default:
|
||||
return L10n.of(context)!.custom;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<int?> showPermissionChooser(
|
||||
BuildContext context, {
|
||||
int currentLevel = 0,
|
||||
}) async {
|
||||
final permissionLevel = await showConfirmationDialog(
|
||||
final customLevel = await showTextInputDialog(
|
||||
context: context,
|
||||
title: L10n.of(context)!.setPermissionsLevel,
|
||||
actions: PermissionLevel.values
|
||||
.map(
|
||||
(level) => AlertDialogAction(
|
||||
key: level,
|
||||
label: level.toLocalizedString(context),
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
textFields: [
|
||||
DialogTextField(
|
||||
initialText: currentLevel.toString(),
|
||||
keyboardType: TextInputType.number,
|
||||
autocorrect: false,
|
||||
validator: (text) {
|
||||
if (text == null) {
|
||||
return L10n.of(context)!.pleaseEnterANumber;
|
||||
}
|
||||
final level = int.tryParse(text);
|
||||
if (level == null || level < 0) {
|
||||
return L10n.of(context)!.pleaseEnterANumber;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
if (permissionLevel == null) return null;
|
||||
|
||||
switch (permissionLevel) {
|
||||
case PermissionLevel.user:
|
||||
return 0;
|
||||
case PermissionLevel.moderator:
|
||||
return 50;
|
||||
case PermissionLevel.admin:
|
||||
return 100;
|
||||
case PermissionLevel.custom:
|
||||
final customLevel = await showTextInputDialog(
|
||||
context: context,
|
||||
title: L10n.of(context)!.setPermissionsLevel,
|
||||
textFields: [
|
||||
DialogTextField(
|
||||
initialText: currentLevel.toString(),
|
||||
keyboardType: TextInputType.number,
|
||||
autocorrect: false,
|
||||
validator: (text) {
|
||||
if (text == null) {
|
||||
return L10n.of(context)!.pleaseEnterANumber;
|
||||
}
|
||||
final level = int.tryParse(text);
|
||||
if (level == null || level < 0) {
|
||||
return L10n.of(context)!.pleaseEnterANumber;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
if (customLevel == null) return null;
|
||||
return int.tryParse(customLevel.first);
|
||||
}
|
||||
if (customLevel == null) return null;
|
||||
return int.tryParse(customLevel.first);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue