fluffychat/lib/components/user_bottom_sheet.dart

262 lines
7.9 KiB
Dart
Raw Normal View History

2020-10-28 07:23:50 +01:00
import 'dart:math';
2020-11-14 10:08:13 +01:00
import 'package:adaptive_dialog/adaptive_dialog.dart';
2021-01-16 12:46:38 +01:00
import 'package:adaptive_page_layout/adaptive_page_layout.dart';
2020-10-28 07:23:50 +01:00
import 'package:famedlysdk/famedlysdk.dart';
2020-12-05 13:03:57 +01:00
import 'package:fluffychat/components/dialogs/permission_slider_dialog.dart';
2021-01-16 12:46:38 +01:00
import 'package:fluffychat/config/themes.dart';
2020-10-28 07:23:50 +01:00
import 'package:fluffychat/utils/fluffy_share.dart';
import 'package:flutter/material.dart';
import 'content_banner.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
import '../utils/presence_extension.dart';
2020-12-25 09:58:34 +01:00
import 'package:future_loading_dialog/future_loading_dialog.dart';
2020-11-22 22:48:10 +01:00
import 'dialogs/key_verification_dialog.dart';
2020-10-28 07:23:50 +01:00
class UserBottomSheet extends StatelessWidget {
final User user;
final Function onMention;
2021-01-19 15:48:50 +01:00
final L10n l10n;
2020-10-28 07:23:50 +01:00
2021-01-19 15:48:50 +01:00
const UserBottomSheet({
Key key,
@required this.user,
@required this.l10n,
this.onMention,
}) : super(key: key);
2020-10-28 07:23:50 +01:00
void participantAction(BuildContext context, String action) async {
2020-11-14 10:08:13 +01:00
final Function _askConfirmation = () async =>
(await showOkCancelAlertDialog(
2021-01-19 15:48:50 +01:00
context: context, title: l10n.areYouSure) ==
2020-11-14 10:08:13 +01:00
OkCancelResult.ok);
2020-10-28 07:23:50 +01:00
switch (action) {
case 'mention':
Navigator.of(context).pop();
onMention();
break;
case 'ban':
2020-11-14 10:08:13 +01:00
if (await _askConfirmation()) {
2020-12-25 09:58:34 +01:00
await showFutureLoadingDialog(
context: context,
future: () => user.ban(),
);
Navigator.of(context).pop();
2020-10-28 07:23:50 +01:00
}
break;
case 'unban':
2020-11-14 10:08:13 +01:00
if (await _askConfirmation()) {
2020-12-25 09:58:34 +01:00
await showFutureLoadingDialog(
context: context,
future: () => user.unban(),
);
Navigator.of(context).pop();
2020-10-28 07:23:50 +01:00
}
break;
case 'kick':
2020-11-14 10:08:13 +01:00
if (await _askConfirmation()) {
2020-12-25 09:58:34 +01:00
await showFutureLoadingDialog(
context: context,
future: () => user.kick(),
);
Navigator.of(context).pop();
2020-10-28 07:23:50 +01:00
}
break;
2020-12-05 13:03:57 +01:00
case 'permission':
2021-01-19 15:46:43 +01:00
final newPermission = await PermissionSliderDialog(
initialPermission: user.powerLevel,
l10n: L10n.of(context),
).show(context);
2020-12-05 13:03:57 +01:00
if (newPermission != null) {
if (newPermission == 100 && await _askConfirmation() == false) break;
2020-12-25 09:58:34 +01:00
await showFutureLoadingDialog(
context: context,
future: () => user.setPower(newPermission),
);
Navigator.of(context).pop();
2020-10-28 07:23:50 +01:00
}
break;
case 'message':
final roomId = await user.startDirectChat();
2021-01-16 12:46:38 +01:00
await AdaptivePageLayout.of(context)
.pushNamedAndRemoveUntilIsFirst('/rooms/${roomId}');
2020-10-28 07:23:50 +01:00
break;
}
}
2020-10-31 10:39:38 +01:00
void _verifyAction(BuildContext context) async {
2021-01-17 09:13:47 +01:00
final client = user.room.client;
2020-10-31 10:39:38 +01:00
final req = await client.userDeviceKeys[user.id].startVerification();
2021-01-19 15:48:50 +01:00
await KeyVerificationDialog(
request: req,
l10n: L10n.of(context),
).show(context);
2020-10-31 10:39:38 +01:00
}
2020-10-28 07:23:50 +01:00
@override
Widget build(BuildContext context) {
2021-01-17 09:13:47 +01:00
final client = user.room.client;
2020-10-31 10:39:38 +01:00
final presence = client.presences[user.id];
final verificationStatus = client.userDeviceKeys[user.id]?.verified;
2020-10-28 07:23:50 +01:00
var items = <PopupMenuEntry<String>>[];
if (onMention != null) {
items.add(
PopupMenuItem(
child: _TextWithIcon(
2021-01-19 15:48:50 +01:00
l10n.mention,
Icons.alternate_email_outlined,
),
value: 'mention'),
2020-10-28 07:23:50 +01:00
);
}
2021-01-17 09:13:47 +01:00
if (user.id != user.room.client.userID && !user.room.isDirectChat) {
2020-10-28 07:23:50 +01:00
items.add(
PopupMenuItem(
child: _TextWithIcon(
2021-01-19 15:48:50 +01:00
l10n.sendAMessage,
2020-12-06 10:31:35 +01:00
Icons.send_outlined,
),
value: 'message'),
2020-10-28 07:23:50 +01:00
);
}
2020-12-05 13:03:57 +01:00
if (user.canChangePowerLevel) {
2020-10-28 07:23:50 +01:00
items.add(
PopupMenuItem(
child: _TextWithIcon(
2021-01-19 15:48:50 +01:00
l10n.setPermissionsLevel,
2020-12-05 13:03:57 +01:00
Icons.edit_attributes_outlined,
),
2020-12-05 13:03:57 +01:00
value: 'permission'),
2020-10-28 07:23:50 +01:00
);
}
if (user.canKick) {
items.add(
PopupMenuItem(
child: _TextWithIcon(
2021-01-19 15:48:50 +01:00
l10n.kickFromChat,
Icons.exit_to_app_outlined,
),
value: 'kick'),
2020-10-28 07:23:50 +01:00
);
}
if (user.canBan && user.membership != Membership.ban) {
items.add(
PopupMenuItem(
child: _TextWithIcon(
2021-01-19 15:48:50 +01:00
l10n.banFromChat,
Icons.warning_sharp,
),
value: 'ban'),
2020-10-28 07:23:50 +01:00
);
2020-11-22 21:12:46 +01:00
} else if (user.canBan && user.membership == Membership.ban) {
2020-10-28 07:23:50 +01:00
items.add(
PopupMenuItem(
child: _TextWithIcon(
2021-01-19 15:48:50 +01:00
l10n.removeExile,
2020-11-22 21:12:46 +01:00
Icons.warning_outlined,
),
value: 'unban'),
2020-10-28 07:23:50 +01:00
);
}
return Center(
child: Container(
2021-01-16 12:46:38 +01:00
width: min(
MediaQuery.of(context).size.width, FluffyThemes.columnWidth * 1.5),
2020-10-28 07:23:50 +01:00
child: SafeArea(
child: Material(
elevation: 4,
child: Scaffold(
extendBodyBehindAppBar: true,
appBar: AppBar(
elevation: 0,
backgroundColor:
Theme.of(context).scaffoldBackgroundColor.withOpacity(0.5),
leading: IconButton(
icon: Icon(Icons.arrow_downward_outlined),
onPressed: Navigator.of(context).pop,
),
title: Text(user.calcDisplayname()),
actions: [
2020-10-31 10:39:38 +01:00
if (verificationStatus != null)
2020-11-22 11:46:31 +01:00
IconButton(
icon: Icon(
2020-12-06 10:31:35 +01:00
Icons.lock_outlined,
2020-10-31 10:39:38 +01:00
color: {
UserVerifiedStatus.unknownDevice: Colors.red,
UserVerifiedStatus.verified: Colors.green,
}[verificationStatus] ??
Colors.orange,
),
2020-11-22 11:46:31 +01:00
onPressed: () =>
2020-10-31 10:39:38 +01:00
verificationStatus == UserVerifiedStatus.unknown
? _verifyAction(context)
: null,
),
2021-01-17 09:13:47 +01:00
if (user.id != user.room.client.userID)
2020-10-28 07:23:50 +01:00
PopupMenuButton(
itemBuilder: (_) => items,
onSelected: (action) =>
participantAction(context, action),
),
],
),
2020-10-28 09:59:18 +01:00
body: Column(
2020-10-28 07:23:50 +01:00
children: [
2020-10-28 09:59:18 +01:00
Expanded(
child: ContentBanner(
user.avatarUrl,
defaultIcon: Icons.person_outline,
2021-01-20 20:27:09 +01:00
client: user.room.client,
2020-10-28 09:59:18 +01:00
),
2020-10-28 07:23:50 +01:00
),
ListTile(
2021-01-19 15:48:50 +01:00
title: Text(l10n.username),
2020-10-28 07:23:50 +01:00
subtitle: Text(user.id),
2020-12-06 10:31:35 +01:00
trailing: Icon(Icons.share_outlined),
2020-10-28 07:23:50 +01:00
onTap: () => FluffyShare.share(user.id, context),
),
if (presence != null)
ListTile(
title: Text(presence.getLocalizedStatusMessage(context)),
subtitle:
Text(presence.getLocalizedLastActiveAgo(context)),
trailing: Icon(Icons.circle,
2020-10-28 18:13:04 +01:00
color: presence.presence.currentlyActive ?? false
2020-10-28 07:23:50 +01:00
? Colors.green
: Colors.grey),
),
],
),
),
),
),
),
);
}
}
class _TextWithIcon extends StatelessWidget {
final String text;
final IconData iconData;
const _TextWithIcon(
this.text,
this.iconData, {
Key key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(iconData),
SizedBox(width: 16),
Text(text),
],
);
}
}