🐛 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: [
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),
),

View File

@@ -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();
}

View File

@@ -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<AppWrapper>
StreamSubscription? ntySubs;
bool networkStateShowing = false;
StreamSubscription? composeSheetSubs;
StreamSubscription? notificationSheetSubs;
@override
void initState() {
super.initState();
@@ -49,6 +55,21 @@ class _AppWrapperState extends ConsumerState<AppWrapper>
ref.read(rpcServerStateProvider.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();
if (initialUrl != null && mounted) {
WidgetsBinding.instance.addPostFrameCallback((_) {
@@ -64,6 +85,8 @@ class _AppWrapperState extends ConsumerState<AppWrapper>
ref.read(rpcServerProvider).stop();
TrayService.instance.dispose(this);
ntySubs?.cancel();
composeSheetSubs?.cancel();
notificationSheetSubs?.cancel();
super.dispose();
}
@@ -80,9 +103,8 @@ class _AppWrapperState extends ConsumerState<AppWrapper>
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<AppWrapper>
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<AppWrapper>
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 &&

View File

@@ -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<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
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
? <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
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;

View File

@@ -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,

View File

@@ -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:

View File

@@ -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: