From 4d87ca7cca50ac61b2c1baedf866fee36dd5876e Mon Sep 17 00:00:00 2001 From: LittleSheep Date: Sun, 21 Dec 2025 02:40:48 +0800 Subject: [PATCH] :bug: Fix bugs again --- lib/screens/dashboard/dash.dart | 19 ----- lib/services/event_bus.dart | 10 +++ lib/widgets/app_wrapper.dart | 48 ++++++++++-- lib/widgets/cmp/pattle.dart | 109 ++++++++++++++++++++++++++-- lib/widgets/post/compose_sheet.dart | 2 +- pubspec.lock | 24 ++++++ pubspec.yaml | 1 + 7 files changed, 181 insertions(+), 32 deletions(-) diff --git a/lib/screens/dashboard/dash.dart b/lib/screens/dashboard/dash.dart index b0208b03..8ac3979e 100644 --- a/lib/screens/dashboard/dash.dart +++ b/lib/screens/dashboard/dash.dart @@ -309,25 +309,6 @@ class FeaturedPostCard extends HookConsumerWidget { children: [ const Icon(Symbols.highlight), Text('highlightPost').tr(), - const Spacer(), - IconButton( - padding: EdgeInsets.zero, - visualDensity: VisualDensity.compact, - constraints: const BoxConstraints(), - onPressed: () { - // Navigation to previous post - }, - icon: const Icon(Symbols.arrow_left), - ), - IconButton( - padding: EdgeInsets.zero, - visualDensity: VisualDensity.compact, - constraints: const BoxConstraints(), - onPressed: () { - // Navigation to next post - }, - icon: const Icon(Symbols.arrow_right), - ), ], ).padding(horizontal: 16, vertical: 8), ), diff --git a/lib/services/event_bus.dart b/lib/services/event_bus.dart index c7fdc214..023967c1 100644 --- a/lib/services/event_bus.dart +++ b/lib/services/event_bus.dart @@ -28,3 +28,13 @@ class OidcAuthCallbackEvent { class CommandPaletteTriggerEvent { const CommandPaletteTriggerEvent(); } + +/// Event fired to show the compose post sheet +class ShowComposeSheetEvent { + const ShowComposeSheetEvent(); +} + +/// Event fired to show the notification sheet +class ShowNotificationSheetEvent { + const ShowNotificationSheetEvent(); +} diff --git a/lib/widgets/app_wrapper.dart b/lib/widgets/app_wrapper.dart index 1efa0733..7004db8f 100644 --- a/lib/widgets/app_wrapper.dart +++ b/lib/widgets/app_wrapper.dart @@ -17,6 +17,9 @@ import 'package:island/services/sharing_intent.dart'; import 'package:island/services/update_service.dart'; import 'package:island/widgets/content/network_status_sheet.dart'; import 'package:island/widgets/tour/tour.dart'; +import 'package:island/widgets/post/compose_sheet.dart'; +import 'package:island/screens/notification.dart'; +import 'package:island/services/event_bus.dart'; import 'package:tray_manager/tray_manager.dart'; import 'package:window_manager/window_manager.dart'; @@ -33,6 +36,9 @@ class _AppWrapperState extends ConsumerState StreamSubscription? ntySubs; bool networkStateShowing = false; + StreamSubscription? composeSheetSubs; + StreamSubscription? notificationSheetSubs; + @override void initState() { super.initState(); @@ -49,6 +55,21 @@ class _AppWrapperState extends ConsumerState ref.read(rpcServerStateProvider.notifier).start(); ref.read(webAuthServerStateProvider.notifier).start(); + // Listen to special action events + composeSheetSubs = eventBus.on().listen((event) { + if (mounted) { + _showComposeSheet(); + } + }); + + notificationSheetSubs = eventBus.on().listen(( + event, + ) { + if (mounted) { + _showNotificationSheet(); + } + }); + final initialUrl = await protocolHandler.getInitialUrl(); if (initialUrl != null && mounted) { WidgetsBinding.instance.addPostFrameCallback((_) { @@ -64,6 +85,8 @@ class _AppWrapperState extends ConsumerState ref.read(rpcServerProvider).stop(); TrayService.instance.dispose(this); ntySubs?.cancel(); + composeSheetSubs?.cancel(); + notificationSheetSubs?.cancel(); super.dispose(); } @@ -80,9 +103,8 @@ class _AppWrapperState extends ConsumerState context: context, isScrollControlled: true, isDismissible: false, - builder: - (context) => - NetworkStatusSheet(onReconnect: () => wsNotifier.connect()), + builder: (context) => + NetworkStatusSheet(onReconnect: () => wsNotifier.connect()), ).then((_) => setState(() => networkStateShowing = false)); }); } @@ -119,6 +141,19 @@ class _AppWrapperState extends ConsumerState TrayService.instance.handleAction(menuItem); } + void _showComposeSheet() { + PostComposeSheet.show(context); + } + + void _showNotificationSheet() { + showModalBottomSheet( + context: context, + isScrollControlled: true, + useRootNavigator: true, + builder: (context) => const NotificationSheet(), + ); + } + void _handleDeepLink(Uri uri, WidgetRef ref) async { String path = '/${uri.host}${uri.path}'; @@ -153,10 +188,9 @@ class _AppWrapperState extends ConsumerState final router = ref.read(routerProvider); if (uri.queryParameters.isNotEmpty) { - path = - Uri.parse( - path, - ).replace(queryParameters: uri.queryParameters).toString(); + path = Uri.parse( + path, + ).replace(queryParameters: uri.queryParameters).toString(); } router.push(path); if (!kIsWeb && diff --git a/lib/widgets/cmp/pattle.dart b/lib/widgets/cmp/pattle.dart index e3306189..d5678a65 100644 --- a/lib/widgets/cmp/pattle.dart +++ b/lib/widgets/cmp/pattle.dart @@ -18,6 +18,21 @@ import 'package:island/widgets/content/cloud_files.dart'; import 'package:material_symbols_icons/symbols.dart'; import 'package:relative_time/relative_time.dart'; import 'package:styled_widget/styled_widget.dart'; +import 'package:island/services/event_bus.dart'; + +class SpecialAction { + final String name; + final String description; + final IconData icon; + final VoidCallback action; + + const SpecialAction({ + required this.name, + required this.description, + required this.icon, + required this.action, + }); +} class CommandPattleWidget extends HookConsumerWidget { final VoidCallback onDismiss; @@ -189,6 +204,27 @@ class CommandPattleWidget extends HookConsumerWidget { ), ]; + static List _getSpecialActions(BuildContext context) { + return [ + SpecialAction( + name: 'Compose Post', + description: 'Create a new post', + icon: Symbols.edit, + action: () { + eventBus.fire(const ShowComposeSheetEvent()); + }, + ), + SpecialAction( + name: 'Notifications', + description: 'View your notifications', + icon: Symbols.notifications, + action: () { + eventBus.fire(const ShowNotificationSheetEvent()); + }, + ), + ]; + } + @override Widget build(BuildContext context, WidgetRef ref) { final textController = useTextEditingController(); @@ -269,8 +305,23 @@ class CommandPattleWidget extends HookConsumerWidget { .take(5) // Limit to 5 results .toList(); - // Combine results: chats first, then routes - final allResults = [...filteredChats, ...filteredRoutes]; + final filteredSpecialActions = searchQuery.value.isEmpty + ? [] + : _getSpecialActions(context) + .where((action) { + final query = searchQuery.value.toLowerCase(); + return action.name.toLowerCase().contains(query) || + action.description.toLowerCase().contains(query); + }) + .take(5) // Limit to 5 results + .toList(); + + // Combine results: chats first, then special actions, then routes + final allResults = [ + ...filteredChats, + ...filteredSpecialActions, + ...filteredRoutes, + ]; // Update focused index when results change useEffect(() { @@ -326,6 +377,9 @@ class CommandPattleWidget extends HookConsumerWidget { final item = allResults[focusedIndex.value ?? 0]; if (item is SnChatRoom) { _navigateToChat(context, ref, item); + } else if (item is SpecialAction) { + onDismiss(); + item.action(); } else if (item is RouteItem) { _navigateToRoute(context, ref, item); } @@ -379,7 +433,7 @@ class CommandPattleWidget extends HookConsumerWidget { ), decoration: BoxDecoration( color: Theme.of(context).colorScheme.surface, - borderRadius: BorderRadius.circular(24), + borderRadius: BorderRadius.circular(28), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.3), @@ -389,8 +443,9 @@ class CommandPattleWidget extends HookConsumerWidget { ], ), child: Material( + elevation: 0, color: Theme.of(context).colorScheme.surface, - borderRadius: BorderRadius.circular(24), + borderRadius: BorderRadius.circular(28), child: Column( mainAxisSize: MainAxisSize.min, children: [ @@ -428,6 +483,16 @@ class CommandPattleWidget extends HookConsumerWidget { item, ), ); + } else if (item is SpecialAction) { + return _SpecialActionSearchResult( + action: item, + isFocused: + index == focusedIndex.value, + onTap: () { + onDismiss(); + item.action(); + }, + ); } else if (item is RouteItem) { return _RouteSearchResult( route: item, @@ -497,7 +562,7 @@ class _RouteSearchResult extends StatelessWidget { color: isFocused ? Theme.of(context).colorScheme.surfaceContainerHighest : null, - borderRadius: const BorderRadius.all(Radius.circular(24)), + borderRadius: const BorderRadius.all(Radius.circular(28)), ), child: ListTile( leading: CircleAvatar( @@ -513,6 +578,40 @@ class _RouteSearchResult extends StatelessWidget { } } +class _SpecialActionSearchResult extends StatelessWidget { + final SpecialAction action; + final bool isFocused; + final VoidCallback onTap; + + const _SpecialActionSearchResult({ + required this.action, + required this.isFocused, + required this.onTap, + }); + + @override + Widget build(BuildContext context) { + return Container( + decoration: BoxDecoration( + color: isFocused + ? Theme.of(context).colorScheme.surfaceContainerHighest + : null, + borderRadius: const BorderRadius.all(Radius.circular(24)), + ), + child: ListTile( + leading: CircleAvatar( + backgroundColor: Theme.of(context).colorScheme.tertiaryContainer, + foregroundColor: Theme.of(context).colorScheme.onTertiaryContainer, + child: Icon(action.icon), + ), + title: Text(action.name), + subtitle: Text(action.description), + onTap: onTap, + ), + ); + } +} + class _ChatRoomSearchResult extends HookConsumerWidget { final SnChatRoom room; final bool isFocused; diff --git a/lib/widgets/post/compose_sheet.dart b/lib/widgets/post/compose_sheet.dart index a81e848c..43b77679 100644 --- a/lib/widgets/post/compose_sheet.dart +++ b/lib/widgets/post/compose_sheet.dart @@ -179,7 +179,7 @@ class PostComposeSheet extends HookConsumerWidget { final isTablet = isWideScreen(context) && !kIsWeb && - (Platform.isAndroid || Platform.isAndroid); + (Platform.isAndroid || Platform.isIOS); return SheetScaffold( heightFactor: isTablet ? 0.95 : 0.8, diff --git a/pubspec.lock b/pubspec.lock index c2872727..303bd082 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -2430,6 +2430,30 @@ packages: url: "https://pub.dev" source: hosted version: "0.3.2" + sensors_plus: + dependency: transitive + description: + name: sensors_plus + sha256: "89e2bfc3d883743539ce5774a2b93df61effde40ff958ecad78cd66b1a8b8d52" + url: "https://pub.dev" + source: hosted + version: "6.1.2" + sensors_plus_platform_interface: + dependency: transitive + description: + name: sensors_plus_platform_interface + sha256: "58815d2f5e46c0c41c40fb39375d3f127306f7742efe3b891c0b1c87e2b5cd5d" + url: "https://pub.dev" + source: hosted + version: "2.0.1" + shake: + dependency: "direct main" + description: + name: shake + sha256: "7bb2bd14e9cd23a0d569f8a286b2b63ba1552ac348914d2d41ec757117ddda4e" + url: "https://pub.dev" + source: hosted + version: "3.0.0" share_plus: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 77f6944d..80cfd6fb 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -173,6 +173,7 @@ dependencies: skeletonizer: ^2.1.2 permission_handler: ^12.0.1 hotkey_manager: ^0.2.3 + shake: ^3.0.0 dev_dependencies: flutter_test: