refactor: Widget file structure and MVC user bottom sheet

This commit is contained in:
Christian Pauly 2021-04-24 09:29:17 +02:00
parent 69deae3dc1
commit bd53745f35
27 changed files with 268 additions and 264 deletions

View File

@ -14,7 +14,7 @@ import 'package:fluffychat/views/chat_encryption_settings.dart';
import 'package:fluffychat/views/chat_list.dart';
import 'package:fluffychat/views/chat_permissions_settings.dart';
import 'package:fluffychat/views/ui/empty_page_ui.dart';
import 'package:fluffychat/views/widgets/loading_view.dart';
import 'package:fluffychat/views/widgets/layouts/loading_view.dart';
import 'package:fluffychat/views/widgets/log_view.dart';
import 'package:fluffychat/views/ui/login_ui.dart';
import 'package:fluffychat/views/new_group.dart';

View File

@ -7,7 +7,7 @@ import 'package:famedlysdk/famedlysdk.dart';
import 'package:fluffychat/config/routes.dart';
import 'package:fluffychat/utils/platform_infos.dart';
import 'package:fluffychat/utils/sentry_controller.dart';
import 'package:fluffychat/views/widgets/lock_screen.dart';
import 'package:fluffychat/views/widgets/layouts/lock_screen.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

View File

@ -9,7 +9,7 @@ import 'package:famedlysdk/famedlysdk.dart';
import 'package:fluffychat/views/widgets/chat_settings_popup_menu.dart';
import 'package:fluffychat/views/widgets/content_banner.dart';
import 'package:fluffychat/views/widgets/max_width_body.dart';
import 'package:fluffychat/views/widgets/layouts/max_width_body.dart';
import 'package:fluffychat/views/widgets/list_items/participant_list_item.dart';
import 'package:fluffychat/utils/matrix_locals.dart';
import 'package:flutter/material.dart';

View File

@ -2,7 +2,7 @@ import 'package:famedlysdk/famedlysdk.dart';
import 'package:fluffychat/views/chat_encryption_settings.dart';
import 'package:fluffychat/views/widgets/avatar.dart';
import 'package:fluffychat/views/widgets/matrix.dart';
import 'package:fluffychat/views/widgets/max_width_body.dart';
import 'package:fluffychat/views/widgets/layouts/max_width_body.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
import '../../utils/device_extension.dart';

View File

@ -1,6 +1,6 @@
import 'package:fluffychat/views/chat_permissions_settings.dart';
import 'package:fluffychat/views/widgets/list_items/permission_list_tile.dart';
import 'package:fluffychat/views/widgets/max_width_body.dart';
import 'package:fluffychat/views/widgets/layouts/max_width_body.dart';
import 'package:fluffychat/views/widgets/matrix.dart';
import 'package:flutter/material.dart';

View File

@ -16,7 +16,7 @@ import 'package:fluffychat/views/widgets/encryption_button.dart';
import 'package:fluffychat/views/widgets/list_items/message.dart';
import 'package:fluffychat/views/widgets/matrix.dart';
import 'package:fluffychat/views/widgets/reply_content.dart';
import 'package:fluffychat/views/widgets/user_bottom_sheet.dart';
import 'package:fluffychat/views/user_bottom_sheet.dart';
import 'package:fluffychat/config/app_emojis.dart';
import 'package:fluffychat/utils/matrix_locals.dart';
import 'package:fluffychat/utils/platform_infos.dart';

View File

@ -1,5 +1,5 @@
import 'package:fluffychat/views/device_settings.dart';
import 'package:fluffychat/views/widgets/max_width_body.dart';
import 'package:fluffychat/views/widgets/layouts/max_width_body.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';

View File

@ -2,7 +2,7 @@ import '../homeserver_picker.dart';
import 'package:fluffychat/views/widgets/default_app_bar_search_field.dart';
import 'package:fluffychat/views/widgets/fluffy_banner.dart';
import 'package:fluffychat/config/app_config.dart';
import 'package:fluffychat/views/widgets/one_page_card.dart';
import 'package:fluffychat/views/widgets/layouts/one_page_card.dart';
import 'package:fluffychat/utils/platform_infos.dart';
import 'package:flutter/foundation.dart';

View File

@ -3,7 +3,7 @@ import 'package:fluffychat/views/widgets/default_app_bar_search_field.dart';
import 'package:famedlysdk/famedlysdk.dart';
import 'package:fluffychat/views/widgets/avatar.dart';
import 'package:fluffychat/views/widgets/max_width_body.dart';
import 'package:fluffychat/views/widgets/layouts/max_width_body.dart';
import 'package:fluffychat/views/widgets/matrix.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';

View File

@ -3,7 +3,7 @@ import 'dart:async';
import 'package:adaptive_dialog/adaptive_dialog.dart';
import 'package:adaptive_page_layout/adaptive_page_layout.dart';
import 'package:famedlysdk/famedlysdk.dart';
import 'package:fluffychat/views/widgets/one_page_card.dart';
import 'package:fluffychat/views/widgets/layouts/one_page_card.dart';
import 'package:future_loading_dialog/future_loading_dialog.dart';
import 'package:fluffychat/views/widgets/matrix.dart';

View File

@ -1,5 +1,5 @@
import 'package:fluffychat/views/new_group.dart';
import 'package:fluffychat/views/widgets/max_width_body.dart';
import 'package:fluffychat/views/widgets/layouts/max_width_body.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';

View File

@ -2,7 +2,7 @@ import 'package:adaptive_page_layout/adaptive_page_layout.dart';
import 'package:fluffychat/views/new_private_chat.dart';
import 'package:fluffychat/views/widgets/avatar.dart';
import 'package:fluffychat/views/widgets/contacts_list.dart';
import 'package:fluffychat/views/widgets/max_width_body.dart';
import 'package:fluffychat/views/widgets/layouts/max_width_body.dart';
import 'package:fluffychat/views/widgets/matrix.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';

View File

@ -1,6 +1,6 @@
import 'package:famedlysdk/famedlysdk.dart';
import 'package:fluffychat/views/settings_3pid.dart';
import 'package:fluffychat/views/widgets/max_width_body.dart';
import 'package:fluffychat/views/widgets/layouts/max_width_body.dart';
import 'package:fluffychat/views/widgets/matrix.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';

View File

@ -1,6 +1,6 @@
import 'package:cached_network_image/cached_network_image.dart';
import 'package:famedlysdk/famedlysdk.dart';
import 'package:fluffychat/views/widgets/max_width_body.dart';
import 'package:fluffychat/views/widgets/layouts/max_width_body.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';

View File

@ -1,6 +1,6 @@
import 'package:famedlysdk/famedlysdk.dart';
import 'package:fluffychat/views/widgets/avatar.dart';
import 'package:fluffychat/views/widgets/max_width_body.dart';
import 'package:fluffychat/views/widgets/layouts/max_width_body.dart';
import 'package:future_loading_dialog/future_loading_dialog.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';

View File

@ -1,7 +1,7 @@
import 'dart:io';
import 'package:famedlysdk/famedlysdk.dart';
import 'package:fluffychat/views/widgets/max_width_body.dart';
import 'package:fluffychat/views/widgets/layouts/max_width_body.dart';
import 'package:future_loading_dialog/future_loading_dialog.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

View File

@ -1,5 +1,5 @@
import 'package:adaptive_theme/adaptive_theme.dart';
import 'package:fluffychat/views/widgets/max_width_body.dart';
import 'package:fluffychat/views/widgets/layouts/max_width_body.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';

View File

@ -1,6 +1,6 @@
import 'package:fluffychat/views/sign_up_password.dart';
import 'package:fluffychat/views/widgets/one_page_card.dart';
import 'package:fluffychat/views/widgets/layouts/one_page_card.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';

View File

@ -3,7 +3,7 @@ import 'package:fluffychat/views/sign_up.dart';
import 'package:fluffychat/views/widgets/fluffy_banner.dart';
import 'package:fluffychat/views/widgets/matrix.dart';
import 'package:fluffychat/views/widgets/one_page_card.dart';
import 'package:fluffychat/views/widgets/layouts/one_page_card.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';

View File

@ -0,0 +1,156 @@
import 'dart:math';
import 'package:famedlysdk/famedlysdk.dart';
import 'package:fluffychat/config/themes.dart';
import 'package:fluffychat/utils/fluffy_share.dart';
import 'package:flutter/material.dart';
import '../widgets/content_banner.dart';
import '../user_bottom_sheet.dart';
import '../../utils/presence_extension.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
class UserBottomSheetUI extends StatelessWidget {
final UserBottomSheetController controller;
const UserBottomSheetUI(this.controller, {Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
final user = controller.widget.user;
final client = user.room.client;
final presence = client.presences[user.id];
return Center(
child: Container(
width: min(
MediaQuery.of(context).size.width, FluffyThemes.columnWidth * 1.5),
child: Material(
elevation: 4,
child: SafeArea(
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, rootNavigator: false).pop,
tooltip: L10n.of(context).close,
),
title: Text(user.calcDisplayname()),
actions: [
if (user.id != user.room.client.userID)
PopupMenuButton(
itemBuilder: (_) => [
if (controller.widget.onMention != null)
PopupMenuItem(
value: 'mention',
child: _TextWithIcon(
L10n.of(context).mention,
Icons.alternate_email_outlined,
),
),
if (user.id != user.room.client.userID &&
!user.room.isDirectChat)
PopupMenuItem(
value: 'message',
child: _TextWithIcon(
L10n.of(context).sendAMessage,
Icons.send_outlined,
),
),
if (user.canChangePowerLevel)
PopupMenuItem(
value: 'permission',
child: _TextWithIcon(
L10n.of(context).setPermissionsLevel,
Icons.edit_attributes_outlined,
),
),
if (user.canKick)
PopupMenuItem(
value: 'kick',
child: _TextWithIcon(
L10n.of(context).kickFromChat,
Icons.exit_to_app_outlined,
),
),
if (user.canBan && user.membership != Membership.ban)
PopupMenuItem(
value: 'ban',
child: _TextWithIcon(
L10n.of(context).banFromChat,
Icons.warning_sharp,
),
)
else if (user.canBan &&
user.membership == Membership.ban)
PopupMenuItem(
value: 'unban',
child: _TextWithIcon(
L10n.of(context).removeExile,
Icons.warning_outlined,
),
),
],
onSelected: controller.participantAction,
),
],
),
body: Column(
children: [
Expanded(
child: ContentBanner(
user.avatarUrl,
defaultIcon: Icons.person_outline,
client: user.room.client,
),
),
ListTile(
title: Text(L10n.of(context).username),
subtitle: Text(user.id),
trailing: Icon(Icons.share_outlined),
onTap: () => FluffyShare.share(user.id, context),
),
if (presence != null)
ListTile(
title: Text(presence.getLocalizedStatusMessage(context)),
subtitle:
Text(presence.getLocalizedLastActiveAgo(context)),
trailing: Icon(Icons.circle,
color: presence.presence.currentlyActive ?? false
? 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),
],
);
}
}

View File

@ -0,0 +1,92 @@
import 'package:adaptive_dialog/adaptive_dialog.dart';
import 'package:adaptive_page_layout/adaptive_page_layout.dart';
import 'package:famedlysdk/famedlysdk.dart';
import 'package:fluffychat/views/permission_slider_dialog.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:future_loading_dialog/future_loading_dialog.dart';
import 'ui/user_bottom_sheet_ui.dart';
class UserBottomSheet extends StatefulWidget {
final User user;
final Function onMention;
const UserBottomSheet({
Key key,
@required this.user,
this.onMention,
}) : super(key: key);
@override
UserBottomSheetController createState() => UserBottomSheetController();
}
class UserBottomSheetController extends State<UserBottomSheet> {
void participantAction(String action) async {
final Function _askConfirmation =
() async => (await showOkCancelAlertDialog(
context: context,
useRootNavigator: false,
title: L10n.of(context).areYouSure,
okLabel: L10n.of(context).yes,
cancelLabel: L10n.of(context).no,
) ==
OkCancelResult.ok);
switch (action) {
case 'mention':
Navigator.of(context, rootNavigator: false).pop();
widget.onMention();
break;
case 'ban':
if (await _askConfirmation()) {
await showFutureLoadingDialog(
context: context,
future: () => widget.user.ban(),
);
Navigator.of(context, rootNavigator: false).pop();
}
break;
case 'unban':
if (await _askConfirmation()) {
await showFutureLoadingDialog(
context: context,
future: () => widget.user.unban(),
);
Navigator.of(context, rootNavigator: false).pop();
}
break;
case 'kick':
if (await _askConfirmation()) {
await showFutureLoadingDialog(
context: context,
future: () => widget.user.kick(),
);
Navigator.of(context, rootNavigator: false).pop();
}
break;
case 'permission':
final newPermission = await PermissionSliderDialog(
initialPermission: widget.user.powerLevel)
.show(context);
if (newPermission != null) {
if (newPermission == 100 && await _askConfirmation() == false) break;
await showFutureLoadingDialog(
context: context,
future: () => widget.user.setPower(newPermission),
);
Navigator.of(context, rootNavigator: false).pop();
}
break;
case 'message':
final roomId = await widget.user.startDirectChat();
await AdaptivePageLayout.of(context)
.pushNamedAndRemoveUntilIsFirst('/rooms/$roomId');
break;
}
}
@override
Widget build(BuildContext context) => UserBottomSheetUI(this);
}

View File

@ -3,7 +3,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
import '../avatar.dart';
import '../user_bottom_sheet.dart';
import '../../user_bottom_sheet.dart';
class ParticipantListItem extends StatelessWidget {
final User user;

View File

@ -1,244 +0,0 @@
import 'dart:math';
import 'package:adaptive_dialog/adaptive_dialog.dart';
import 'package:adaptive_page_layout/adaptive_page_layout.dart';
import 'package:famedlysdk/famedlysdk.dart';
import 'package:fluffychat/views/permission_slider_dialog.dart';
import 'package:fluffychat/config/themes.dart';
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';
import 'package:future_loading_dialog/future_loading_dialog.dart';
class UserBottomSheet extends StatelessWidget {
final User user;
final Function onMention;
const UserBottomSheet({
Key key,
@required this.user,
this.onMention,
}) : super(key: key);
void participantAction(BuildContext context, String action) async {
final Function _askConfirmation =
() async => (await showOkCancelAlertDialog(
context: context,
useRootNavigator: false,
title: L10n.of(context).areYouSure,
okLabel: L10n.of(context).yes,
cancelLabel: L10n.of(context).no,
) ==
OkCancelResult.ok);
switch (action) {
case 'mention':
Navigator.of(context, rootNavigator: false).pop();
onMention();
break;
case 'ban':
if (await _askConfirmation()) {
await showFutureLoadingDialog(
context: context,
future: () => user.ban(),
);
Navigator.of(context, rootNavigator: false).pop();
}
break;
case 'unban':
if (await _askConfirmation()) {
await showFutureLoadingDialog(
context: context,
future: () => user.unban(),
);
Navigator.of(context, rootNavigator: false).pop();
}
break;
case 'kick':
if (await _askConfirmation()) {
await showFutureLoadingDialog(
context: context,
future: () => user.kick(),
);
Navigator.of(context, rootNavigator: false).pop();
}
break;
case 'permission':
final newPermission =
await PermissionSliderDialog(initialPermission: user.powerLevel)
.show(context);
if (newPermission != null) {
if (newPermission == 100 && await _askConfirmation() == false) break;
await showFutureLoadingDialog(
context: context,
future: () => user.setPower(newPermission),
);
Navigator.of(context, rootNavigator: false).pop();
}
break;
case 'message':
final roomId = await user.startDirectChat();
await AdaptivePageLayout.of(context)
.pushNamedAndRemoveUntilIsFirst('/rooms/$roomId');
break;
}
}
@override
Widget build(BuildContext context) {
final client = user.room.client;
final presence = client.presences[user.id];
final items = <PopupMenuEntry<String>>[];
if (onMention != null) {
items.add(
PopupMenuItem(
value: 'mention',
child: _TextWithIcon(
L10n.of(context).mention,
Icons.alternate_email_outlined,
),
),
);
}
if (user.id != user.room.client.userID && !user.room.isDirectChat) {
items.add(
PopupMenuItem(
value: 'message',
child: _TextWithIcon(
L10n.of(context).sendAMessage,
Icons.send_outlined,
),
),
);
}
if (user.canChangePowerLevel) {
items.add(
PopupMenuItem(
value: 'permission',
child: _TextWithIcon(
L10n.of(context).setPermissionsLevel,
Icons.edit_attributes_outlined,
),
),
);
}
if (user.canKick) {
items.add(
PopupMenuItem(
value: 'kick',
child: _TextWithIcon(
L10n.of(context).kickFromChat,
Icons.exit_to_app_outlined,
),
),
);
}
if (user.canBan && user.membership != Membership.ban) {
items.add(
PopupMenuItem(
value: 'ban',
child: _TextWithIcon(
L10n.of(context).banFromChat,
Icons.warning_sharp,
),
),
);
} else if (user.canBan && user.membership == Membership.ban) {
items.add(
PopupMenuItem(
value: 'unban',
child: _TextWithIcon(
L10n.of(context).removeExile,
Icons.warning_outlined,
),
),
);
}
return Center(
child: Container(
width: min(
MediaQuery.of(context).size.width, FluffyThemes.columnWidth * 1.5),
child: Material(
elevation: 4,
child: SafeArea(
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, rootNavigator: false).pop,
tooltip: L10n.of(context).close,
),
title: Text(user.calcDisplayname()),
actions: [
if (user.id != user.room.client.userID)
PopupMenuButton(
itemBuilder: (_) => items,
onSelected: (action) =>
participantAction(context, action),
),
],
),
body: Column(
children: [
Expanded(
child: ContentBanner(
user.avatarUrl,
defaultIcon: Icons.person_outline,
client: user.room.client,
),
),
ListTile(
title: Text(L10n.of(context).username),
subtitle: Text(user.id),
trailing: Icon(Icons.share_outlined),
onTap: () => FluffyShare.share(user.id, context),
),
if (presence != null)
ListTile(
title: Text(presence.getLocalizedStatusMessage(context)),
subtitle:
Text(presence.getLocalizedLastActiveAgo(context)),
trailing: Icon(Icons.circle,
color: presence.presence.currentlyActive ?? false
? 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),
],
);
}
}