import 'dart:async'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:matrix/matrix.dart'; import 'package:fluffychat/l10n/l10n.dart'; import 'package:fluffychat/widgets/adaptive_dialogs/show_ok_cancel_alert_dialog.dart'; import 'package:fluffychat/widgets/future_loading_dialog.dart'; import 'matrix.dart'; enum ChatPopupMenuActions { details, mute, unmute, emote, leave, search } class ChatSettingsPopupMenu extends StatefulWidget { final Room room; final bool displayChatDetails; const ChatSettingsPopupMenu(this.room, this.displayChatDetails, {super.key}); @override ChatSettingsPopupMenuState createState() => ChatSettingsPopupMenuState(); } class ChatSettingsPopupMenuState extends State { StreamSubscription? notificationChangeSub; @override void dispose() { notificationChangeSub?.cancel(); super.dispose(); } void goToEmoteSettings() async { final room = widget.room; // okay, we need to test if there are any emote state events other than the default one // if so, we need to be directed to a selection screen for which pack we want to look at // otherwise, we just open the normal one. if ((room.states['im.ponies.room_emotes'] ?? {}) .keys .any((String s) => s.isNotEmpty)) { context.push('/rooms/${room.id}/details/multiple_emotes'); } else { context.push('/rooms/${room.id}/details/emotes'); } } @override Widget build(BuildContext context) { notificationChangeSub ??= Matrix.of(context) .client .onSync .stream .where( (syncUpdate) => syncUpdate.accountData?.any( (accountData) => accountData.type == 'm.push_rules', ) ?? false, ) .listen( (u) => setState(() {}), ); return Stack( alignment: Alignment.center, children: [ const SizedBox.shrink(), PopupMenuButton( useRootNavigator: true, onSelected: (choice) async { switch (choice) { case ChatPopupMenuActions.leave: final router = GoRouter.of(context); final confirmed = await showOkCancelAlertDialog( context: context, title: L10n.of(context).areYouSure, message: L10n.of(context).archiveRoomDescription, okLabel: L10n.of(context).leave, cancelLabel: L10n.of(context).cancel, isDestructive: true, ); if (confirmed != OkCancelResult.ok) return; final result = await showFutureLoadingDialog( context: context, future: () => widget.room.leave(), ); if (result.error == null) { router.go('/rooms'); } break; case ChatPopupMenuActions.mute: await showFutureLoadingDialog( context: context, future: () => widget.room.setPushRuleState(PushRuleState.mentionsOnly), ); break; case ChatPopupMenuActions.unmute: await showFutureLoadingDialog( context: context, future: () => widget.room.setPushRuleState(PushRuleState.notify), ); break; case ChatPopupMenuActions.details: _showChatDetails(); break; case ChatPopupMenuActions.search: context.go('/rooms/${widget.room.id}/search'); break; case ChatPopupMenuActions.emote: goToEmoteSettings(); } }, itemBuilder: (BuildContext context) => [ if (widget.displayChatDetails) PopupMenuItem( value: ChatPopupMenuActions.details, child: Row( children: [ const Icon(Icons.info_outline_rounded), const SizedBox(width: 12), Text(L10n.of(context).chatDetails), ], ), ), if (widget.room.pushRuleState == PushRuleState.notify) PopupMenuItem( value: ChatPopupMenuActions.mute, child: Row( children: [ const Icon(Icons.notifications_off_outlined), const SizedBox(width: 12), Text(L10n.of(context).muteChat), ], ), ) else PopupMenuItem( value: ChatPopupMenuActions.unmute, child: Row( children: [ const Icon(Icons.notifications_on_outlined), const SizedBox(width: 12), Text(L10n.of(context).unmuteChat), ], ), ), PopupMenuItem( value: ChatPopupMenuActions.search, child: Row( children: [ const Icon(Icons.search_outlined), const SizedBox(width: 12), Text(L10n.of(context).search), ], ), ), PopupMenuItem( value: ChatPopupMenuActions.emote, child: Row( children: [ const Icon(Icons.emoji_emotions_outlined), const SizedBox(width: 12), Text(L10n.of(context).emoteSettings), ], ), ), PopupMenuItem( value: ChatPopupMenuActions.leave, child: Row( children: [ const Icon(Icons.delete_outlined), const SizedBox(width: 12), Text(L10n.of(context).leave), ], ), ), ], ), ], ); } void _showChatDetails() { if (GoRouterState.of(context).uri.path.endsWith('/details')) { context.go('/rooms/${widget.room.id}'); } else { context.go('/rooms/${widget.room.id}/details'); } } }