feat: Add chat permissions settings
parent
068cb85f90
commit
4c8744f027
@ -0,0 +1,32 @@
|
||||
import 'package:fluffychat/utils/platform_infos.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class AdaptiveFlatButton extends StatelessWidget {
|
||||
final Widget child;
|
||||
final Color textColor;
|
||||
final Function onPressed;
|
||||
|
||||
const AdaptiveFlatButton({
|
||||
Key key,
|
||||
this.child,
|
||||
this.textColor,
|
||||
this.onPressed,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (PlatformInfos.isCupertinoStyle) {
|
||||
return CupertinoDialogAction(
|
||||
child: child,
|
||||
onPressed: onPressed,
|
||||
textStyle: textColor != null ? TextStyle(color: textColor) : null,
|
||||
);
|
||||
}
|
||||
return FlatButton(
|
||||
child: child,
|
||||
textColor: textColor,
|
||||
onPressed: onPressed,
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
import 'package:fluffychat/components/dialogs/adaptive_flat_button.dart';
|
||||
import 'package:fluffychat/utils/platform_infos.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
|
||||
class PermissionSliderDialog extends StatefulWidget {
|
||||
const PermissionSliderDialog({Key key, this.initialPermission = 0})
|
||||
: super(key: key);
|
||||
|
||||
Future<int> show(BuildContext context) => PlatformInfos.isCupertinoStyle
|
||||
? showCupertinoDialog<int>(context: context, builder: (context) => this)
|
||||
: showDialog<int>(context: context, builder: (context) => this);
|
||||
|
||||
final int initialPermission;
|
||||
@override
|
||||
_PermissionSliderDialogState createState() => _PermissionSliderDialogState();
|
||||
}
|
||||
|
||||
class _PermissionSliderDialogState extends State<PermissionSliderDialog> {
|
||||
int _permission;
|
||||
@override
|
||||
void initState() {
|
||||
_permission = widget.initialPermission;
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final slider = PlatformInfos.isCupertinoStyle
|
||||
? CupertinoSlider(
|
||||
value: _permission.toDouble(),
|
||||
onChanged: (d) => setState(() => _permission = d.round()),
|
||||
max: 100.0,
|
||||
min: 0.0,
|
||||
)
|
||||
: Slider(
|
||||
value: _permission.toDouble(),
|
||||
onChanged: (d) => setState(() => _permission = d.round()),
|
||||
max: 100.0,
|
||||
min: 0.0,
|
||||
);
|
||||
final title = Text(
|
||||
L10n.of(context).setPermissionsLevel,
|
||||
textAlign: TextAlign.center,
|
||||
);
|
||||
final content = Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text('Level: ' +
|
||||
(_permission == 100
|
||||
? '$_permission (${L10n.of(context).admin})'
|
||||
: _permission >= 50
|
||||
? '$_permission (${L10n.of(context).moderator})'
|
||||
: _permission.toString())),
|
||||
Container(
|
||||
height: 56,
|
||||
child: slider,
|
||||
),
|
||||
],
|
||||
);
|
||||
final buttons = [
|
||||
AdaptiveFlatButton(
|
||||
child: Text(L10n.of(context).cancel),
|
||||
onPressed: () => Navigator.of(context).pop<int>(null),
|
||||
),
|
||||
AdaptiveFlatButton(
|
||||
child: Text(L10n.of(context).confirm),
|
||||
onPressed: () => Navigator.of(context).pop<int>(_permission),
|
||||
),
|
||||
];
|
||||
if (PlatformInfos.isCupertinoStyle) {
|
||||
return CupertinoAlertDialog(
|
||||
title: title,
|
||||
content: content,
|
||||
actions: buttons,
|
||||
);
|
||||
}
|
||||
return AlertDialog(
|
||||
title: title,
|
||||
content: content,
|
||||
actions: buttons,
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,249 @@
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:fluffychat/components/adaptive_page_layout.dart';
|
||||
import 'package:fluffychat/components/dialogs/permission_slider_dialog.dart';
|
||||
import 'package:fluffychat/components/dialogs/simple_dialogs.dart';
|
||||
import 'package:fluffychat/components/matrix.dart';
|
||||
import 'package:flushbar/flushbar_helper.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
import 'package:famedlysdk/famedlysdk.dart';
|
||||
|
||||
import 'chat_list.dart';
|
||||
|
||||
class ChatPermissionsSettingsView extends StatelessWidget {
|
||||
final String roomId;
|
||||
|
||||
const ChatPermissionsSettingsView({Key key, this.roomId}) : super(key: key);
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AdaptivePageLayout(
|
||||
firstScaffold: ChatList(
|
||||
activeChat: roomId,
|
||||
),
|
||||
secondScaffold: ChatPermissionsSettings(roomId: roomId),
|
||||
primaryPage: FocusPage.SECOND,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ChatPermissionsSettings extends StatelessWidget {
|
||||
final String roomId;
|
||||
|
||||
const ChatPermissionsSettings({Key key, @required this.roomId})
|
||||
: super(key: key);
|
||||
|
||||
void _editPowerLevel(BuildContext context, String key, int currentLevel,
|
||||
{String category}) async {
|
||||
final room = Matrix.of(context).client.getRoomById(roomId);
|
||||
if (!room.canSendEvent(EventTypes.RoomPowerLevels)) {
|
||||
return FlushbarHelper.createError(message: L10n.of(context).noPermission)
|
||||
.show(context);
|
||||
}
|
||||
final newLevel =
|
||||
await PermissionSliderDialog(initialPermission: currentLevel)
|
||||
.show(context);
|
||||
if (newLevel == null) return;
|
||||
final content = Map<String, dynamic>.from(
|
||||
room.getState(EventTypes.RoomPowerLevels).content);
|
||||
if (category != null) {
|
||||
if (!content.containsKey(category)) {
|
||||
content[category] = <String, dynamic>{};
|
||||
}
|
||||
content[category][key] = newLevel;
|
||||
} else {
|
||||
content[key] = newLevel;
|
||||
}
|
||||
inspect(content);
|
||||
await SimpleDialogs(context).tryRequestWithLoadingDialog(
|
||||
room.client.sendState(room.id, EventTypes.RoomPowerLevels, content),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: Text(L10n.of(context).editChatPermissions)),
|
||||
body: StreamBuilder(
|
||||
stream: Matrix.of(context).client.onSync.stream.where(
|
||||
(e) =>
|
||||
(e?.rooms?.join?.containsKey(roomId) ?? false) &&
|
||||
(e.rooms.join[roomId]?.timeline?.events
|
||||
?.any((s) => s.type == EventTypes.RoomPowerLevels) ??
|
||||
false),
|
||||
),
|
||||
builder: (context, _) {
|
||||
final room = Matrix.of(context).client.getRoomById(roomId);
|
||||
final powerLevelsContent = Map<String, dynamic>.from(
|
||||
room.getState(EventTypes.RoomPowerLevels).content);
|
||||
final powerLevels = Map<String, dynamic>.from(powerLevelsContent)
|
||||
..removeWhere((k, v) => !(v is int));
|
||||
final eventsPowerLevels =
|
||||
Map<String, dynamic>.from(powerLevelsContent['events'])
|
||||
..removeWhere((k, v) => !(v is int));
|
||||
|
||||
return ListView(
|
||||
children: [
|
||||
Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
for (var entry in powerLevels.entries)
|
||||
PermissionsListTile(
|
||||
permissionKey: entry.key,
|
||||
permission: entry.value,
|
||||
onTap: () =>
|
||||
_editPowerLevel(context, entry.key, entry.value),
|
||||
),
|
||||
Divider(thickness: 1),
|
||||
ListTile(
|
||||
title: Text(
|
||||
L10n.of(context).notifications,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).primaryColor,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
Builder(builder: (context) {
|
||||
final key = 'rooms';
|
||||
final int value =
|
||||
powerLevelsContent.containsKey('notifications')
|
||||
? powerLevelsContent['notifications']['rooms'] ?? 0
|
||||
: 0;
|
||||
return PermissionsListTile(
|
||||
permissionKey: key,
|
||||
permission: value,
|
||||
category: 'notifications',
|
||||
onTap: () => _editPowerLevel(context, key, value,
|
||||
category: 'notifications'),
|
||||
);
|
||||
}),
|
||||
Divider(thickness: 1),
|
||||
ListTile(
|
||||
title: Text(
|
||||
L10n.of(context).configureChat,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).primaryColor,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
if (eventsPowerLevels != null)
|
||||
for (var entry in eventsPowerLevels.entries)
|
||||
PermissionsListTile(
|
||||
permissionKey: entry.key,
|
||||
category: 'events',
|
||||
permission: entry.value,
|
||||
onTap: () => _editPowerLevel(
|
||||
context, entry.key, entry.value,
|
||||
category: 'events'),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class PermissionsListTile extends StatelessWidget {
|
||||
final String permissionKey;
|
||||
final int permission;
|
||||
final String category;
|
||||
final void Function() onTap;
|
||||
|
||||
const PermissionsListTile({
|
||||
Key key,
|
||||
@required this.permissionKey,
|
||||
@required this.permission,
|
||||
this.category,
|
||||
this.onTap,
|
||||
}) : super(key: key);
|
||||
|
||||
String getLocalizedPowerLevelString(BuildContext context) {
|
||||
if (category == null) {
|
||||
switch (permissionKey) {
|
||||
case 'users_default':
|
||||
return L10n.of(context).defaultPermissionLevel;
|
||||
case 'events_default':
|
||||
return L10n.of(context).sendMessages;
|
||||
case 'state_default':
|
||||
return L10n.of(context).configureChat;
|
||||
case 'ban':
|
||||
return L10n.of(context).banFromChat;
|
||||
case 'kick':
|
||||
return L10n.of(context).kickFromChat;
|
||||
case 'redact':
|
||||
return L10n.of(context).deleteMessage;
|
||||
case 'invite':
|
||||
return L10n.of(context).inviteContact;
|
||||
}
|
||||
} else if (category == 'notifications') {
|
||||
switch (permissionKey) {
|
||||
case 'rooms':
|
||||
return L10n.of(context).notifications;
|
||||
}
|
||||
} else if (category == 'events') {
|
||||
switch (permissionKey) {
|
||||
case EventTypes.RoomName:
|
||||
return L10n.of(context).changeTheNameOfTheGroup;
|
||||
case EventTypes.RoomPowerLevels:
|
||||
return L10n.of(context).editChatPermissions;
|
||||
case EventTypes.HistoryVisibility:
|
||||
return L10n.of(context).visibilityOfTheChatHistory;
|
||||
case EventTypes.RoomCanonicalAlias:
|
||||
return L10n.of(context).setInvitationLink;
|
||||
case EventTypes.RoomAvatar:
|
||||
return L10n.of(context).editRoomAvatar;
|
||||
case EventTypes.RoomTombstone:
|
||||
return L10n.of(context).replaceRoomWithNewerVersion;
|
||||
case EventTypes.Encryption:
|
||||
return L10n.of(context).enableEncryption;
|
||||
case 'm.room.server_acl':
|
||||
return L10n.of(context).editBlockedServers;
|
||||
}
|
||||
}
|
||||
return permissionKey;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ListTile(
|
||||
onTap: onTap,
|
||||
leading: CircleAvatar(
|
||||
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
|
||||
foregroundColor: Colors.grey,
|
||||
child: Icon(Icons.edit_attributes_outlined),
|
||||
),
|
||||
title: Text(getLocalizedPowerLevelString(context)),
|
||||
subtitle: Row(
|
||||
children: [
|
||||
Container(
|
||||
padding: EdgeInsets.all(4),
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).secondaryHeaderColor,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Center(
|
||||
child: Text(permission.toString()),
|
||||
),
|
||||
),
|
||||
SizedBox(width: 8),
|
||||
Text(permission.toLocalizedPowerLevelString(context)),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
extension on int {
|
||||
String toLocalizedPowerLevelString(BuildContext context) {
|
||||
return this == 100
|
||||
? L10n.of(context).admin
|
||||
: this >= 50
|
||||
? L10n.of(context).moderator
|
||||
: L10n.of(context).participant;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue