🐛 Fix bugs again

This commit is contained in:
2025-12-21 02:40:48 +08:00
parent e16a04bd5a
commit 4d87ca7cca
7 changed files with 181 additions and 32 deletions

View File

@@ -309,25 +309,6 @@ class FeaturedPostCard extends HookConsumerWidget {
children: [ children: [
const Icon(Symbols.highlight), const Icon(Symbols.highlight),
Text('highlightPost').tr(), 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), ).padding(horizontal: 16, vertical: 8),
), ),

View File

@@ -28,3 +28,13 @@ class OidcAuthCallbackEvent {
class CommandPaletteTriggerEvent { class CommandPaletteTriggerEvent {
const 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();
}

View File

@@ -17,6 +17,9 @@ import 'package:island/services/sharing_intent.dart';
import 'package:island/services/update_service.dart'; import 'package:island/services/update_service.dart';
import 'package:island/widgets/content/network_status_sheet.dart'; import 'package:island/widgets/content/network_status_sheet.dart';
import 'package:island/widgets/tour/tour.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:tray_manager/tray_manager.dart';
import 'package:window_manager/window_manager.dart'; import 'package:window_manager/window_manager.dart';
@@ -33,6 +36,9 @@ class _AppWrapperState extends ConsumerState<AppWrapper>
StreamSubscription? ntySubs; StreamSubscription? ntySubs;
bool networkStateShowing = false; bool networkStateShowing = false;
StreamSubscription? composeSheetSubs;
StreamSubscription? notificationSheetSubs;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
@@ -49,6 +55,21 @@ class _AppWrapperState extends ConsumerState<AppWrapper>
ref.read(rpcServerStateProvider.notifier).start(); ref.read(rpcServerStateProvider.notifier).start();
ref.read(webAuthServerStateProvider.notifier).start(); ref.read(webAuthServerStateProvider.notifier).start();
// Listen to special action events
composeSheetSubs = eventBus.on<ShowComposeSheetEvent>().listen((event) {
if (mounted) {
_showComposeSheet();
}
});
notificationSheetSubs = eventBus.on<ShowNotificationSheetEvent>().listen((
event,
) {
if (mounted) {
_showNotificationSheet();
}
});
final initialUrl = await protocolHandler.getInitialUrl(); final initialUrl = await protocolHandler.getInitialUrl();
if (initialUrl != null && mounted) { if (initialUrl != null && mounted) {
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
@@ -64,6 +85,8 @@ class _AppWrapperState extends ConsumerState<AppWrapper>
ref.read(rpcServerProvider).stop(); ref.read(rpcServerProvider).stop();
TrayService.instance.dispose(this); TrayService.instance.dispose(this);
ntySubs?.cancel(); ntySubs?.cancel();
composeSheetSubs?.cancel();
notificationSheetSubs?.cancel();
super.dispose(); super.dispose();
} }
@@ -80,9 +103,8 @@ class _AppWrapperState extends ConsumerState<AppWrapper>
context: context, context: context,
isScrollControlled: true, isScrollControlled: true,
isDismissible: false, isDismissible: false,
builder: builder: (context) =>
(context) => NetworkStatusSheet(onReconnect: () => wsNotifier.connect()),
NetworkStatusSheet(onReconnect: () => wsNotifier.connect()),
).then((_) => setState(() => networkStateShowing = false)); ).then((_) => setState(() => networkStateShowing = false));
}); });
} }
@@ -119,6 +141,19 @@ class _AppWrapperState extends ConsumerState<AppWrapper>
TrayService.instance.handleAction(menuItem); 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 { void _handleDeepLink(Uri uri, WidgetRef ref) async {
String path = '/${uri.host}${uri.path}'; String path = '/${uri.host}${uri.path}';
@@ -153,10 +188,9 @@ class _AppWrapperState extends ConsumerState<AppWrapper>
final router = ref.read(routerProvider); final router = ref.read(routerProvider);
if (uri.queryParameters.isNotEmpty) { if (uri.queryParameters.isNotEmpty) {
path = path = Uri.parse(
Uri.parse( path,
path, ).replace(queryParameters: uri.queryParameters).toString();
).replace(queryParameters: uri.queryParameters).toString();
} }
router.push(path); router.push(path);
if (!kIsWeb && if (!kIsWeb &&

View File

@@ -18,6 +18,21 @@ import 'package:island/widgets/content/cloud_files.dart';
import 'package:material_symbols_icons/symbols.dart'; import 'package:material_symbols_icons/symbols.dart';
import 'package:relative_time/relative_time.dart'; import 'package:relative_time/relative_time.dart';
import 'package:styled_widget/styled_widget.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 { class CommandPattleWidget extends HookConsumerWidget {
final VoidCallback onDismiss; final VoidCallback onDismiss;
@@ -189,6 +204,27 @@ class CommandPattleWidget extends HookConsumerWidget {
), ),
]; ];
static List<SpecialAction> _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 @override
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
final textController = useTextEditingController(); final textController = useTextEditingController();
@@ -269,8 +305,23 @@ class CommandPattleWidget extends HookConsumerWidget {
.take(5) // Limit to 5 results .take(5) // Limit to 5 results
.toList(); .toList();
// Combine results: chats first, then routes final filteredSpecialActions = searchQuery.value.isEmpty
final allResults = [...filteredChats, ...filteredRoutes]; ? <SpecialAction>[]
: _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 // Update focused index when results change
useEffect(() { useEffect(() {
@@ -326,6 +377,9 @@ class CommandPattleWidget extends HookConsumerWidget {
final item = allResults[focusedIndex.value ?? 0]; final item = allResults[focusedIndex.value ?? 0];
if (item is SnChatRoom) { if (item is SnChatRoom) {
_navigateToChat(context, ref, item); _navigateToChat(context, ref, item);
} else if (item is SpecialAction) {
onDismiss();
item.action();
} else if (item is RouteItem) { } else if (item is RouteItem) {
_navigateToRoute(context, ref, item); _navigateToRoute(context, ref, item);
} }
@@ -379,7 +433,7 @@ class CommandPattleWidget extends HookConsumerWidget {
), ),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Theme.of(context).colorScheme.surface, color: Theme.of(context).colorScheme.surface,
borderRadius: BorderRadius.circular(24), borderRadius: BorderRadius.circular(28),
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
color: Colors.black.withOpacity(0.3), color: Colors.black.withOpacity(0.3),
@@ -389,8 +443,9 @@ class CommandPattleWidget extends HookConsumerWidget {
], ],
), ),
child: Material( child: Material(
elevation: 0,
color: Theme.of(context).colorScheme.surface, color: Theme.of(context).colorScheme.surface,
borderRadius: BorderRadius.circular(24), borderRadius: BorderRadius.circular(28),
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
@@ -428,6 +483,16 @@ class CommandPattleWidget extends HookConsumerWidget {
item, item,
), ),
); );
} else if (item is SpecialAction) {
return _SpecialActionSearchResult(
action: item,
isFocused:
index == focusedIndex.value,
onTap: () {
onDismiss();
item.action();
},
);
} else if (item is RouteItem) { } else if (item is RouteItem) {
return _RouteSearchResult( return _RouteSearchResult(
route: item, route: item,
@@ -497,7 +562,7 @@ class _RouteSearchResult extends StatelessWidget {
color: isFocused color: isFocused
? Theme.of(context).colorScheme.surfaceContainerHighest ? Theme.of(context).colorScheme.surfaceContainerHighest
: null, : null,
borderRadius: const BorderRadius.all(Radius.circular(24)), borderRadius: const BorderRadius.all(Radius.circular(28)),
), ),
child: ListTile( child: ListTile(
leading: CircleAvatar( 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 { class _ChatRoomSearchResult extends HookConsumerWidget {
final SnChatRoom room; final SnChatRoom room;
final bool isFocused; final bool isFocused;

View File

@@ -179,7 +179,7 @@ class PostComposeSheet extends HookConsumerWidget {
final isTablet = final isTablet =
isWideScreen(context) && isWideScreen(context) &&
!kIsWeb && !kIsWeb &&
(Platform.isAndroid || Platform.isAndroid); (Platform.isAndroid || Platform.isIOS);
return SheetScaffold( return SheetScaffold(
heightFactor: isTablet ? 0.95 : 0.8, heightFactor: isTablet ? 0.95 : 0.8,

View File

@@ -2430,6 +2430,30 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.3.2" 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: share_plus:
dependency: "direct main" dependency: "direct main"
description: description:

View File

@@ -173,6 +173,7 @@ dependencies:
skeletonizer: ^2.1.2 skeletonizer: ^2.1.2
permission_handler: ^12.0.1 permission_handler: ^12.0.1
hotkey_manager: ^0.2.3 hotkey_manager: ^0.2.3
shake: ^3.0.0
dev_dependencies: dev_dependencies:
flutter_test: flutter_test: