From 5d5bda7925434af389a0a5487a0e940deda340b6 Mon Sep 17 00:00:00 2001 From: LittleSheep Date: Sat, 27 Dec 2025 22:16:00 +0800 Subject: [PATCH] :recycle: Better refresh indicator --- lib/screens/chat/chat.dart | 3 +- lib/widgets/extended_refresh_indicator.dart | 80 +++++++++------------ 2 files changed, 36 insertions(+), 47 deletions(-) diff --git a/lib/screens/chat/chat.dart b/lib/screens/chat/chat.dart index 2d7c7f17..8bb76f24 100644 --- a/lib/screens/chat/chat.dart +++ b/lib/screens/chat/chat.dart @@ -19,6 +19,7 @@ import 'package:island/widgets/app_scaffold.dart'; import 'package:island/widgets/chat_room_widgets.dart'; import 'package:island/widgets/content/cloud_files.dart'; import 'package:island/widgets/content/sheet.dart'; +import 'package:island/widgets/extended_refresh_indicator.dart'; import 'package:island/widgets/response.dart'; import 'package:material_symbols_icons/symbols.dart'; import 'package:styled_widget/styled_widget.dart'; @@ -73,7 +74,7 @@ class ChatListBodyWidget extends HookConsumerWidget { .where((item) => !item.isPinned) .toList(); - return RefreshIndicator( + return ExtendedRefreshIndicator( onRefresh: () => Future.sync(() { ref.invalidate(chatRoomJoinedProvider); }), diff --git a/lib/widgets/extended_refresh_indicator.dart b/lib/widgets/extended_refresh_indicator.dart index 0d2fb2af..0e195e58 100644 --- a/lib/widgets/extended_refresh_indicator.dart +++ b/lib/widgets/extended_refresh_indicator.dart @@ -1,11 +1,18 @@ +import 'dart:io'; + +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:flutter_hooks/flutter_hooks.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:hotkey_manager/hotkey_manager.dart'; +import 'package:uuid/uuid.dart'; class RefreshIntent extends Intent { const RefreshIntent(); } -class ExtendedRefreshIndicator extends StatefulWidget { +class ExtendedRefreshIndicator extends HookConsumerWidget { final Widget child; final RefreshCallback onRefresh; @@ -16,52 +23,33 @@ class ExtendedRefreshIndicator extends StatefulWidget { }); @override - State createState() => - _ExtendedRefreshIndicatorState(); -} + Widget build(BuildContext context, WidgetRef ref) { + final hotKeyIdentifier = useState(Uuid().v4().substring(0, 8)); -class _ExtendedRefreshIndicatorState extends State { - late final FocusNode _focusNode; - - @override - void initState() { - super.initState(); - _focusNode = FocusNode(); - WidgetsBinding.instance.addPostFrameCallback((_) { - _focusNode.requestFocus(); - }); - } - - @override - void dispose() { - _focusNode.dispose(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - return Shortcuts( - shortcuts: { - LogicalKeySet(LogicalKeyboardKey.control, LogicalKeyboardKey.keyR): - const RefreshIntent(), - LogicalKeySet(LogicalKeyboardKey.meta, LogicalKeyboardKey.keyR): - const RefreshIntent(), - LogicalKeySet(LogicalKeyboardKey.f5): const RefreshIntent(), - }, - child: Actions( - actions: >{ - RefreshIntent: CallbackAction( - onInvoke: (RefreshIntent intent) => widget.onRefresh(), - ), - }, - child: Focus( - focusNode: _focusNode, - child: RefreshIndicator( - onRefresh: widget.onRefresh, - child: widget.child, - ), - ), - ), + final refreshHotKey = HotKey( + identifier: 'refresh_indicator_$hotKeyIdentifier', + key: PhysicalKeyboardKey.keyR, + modifiers: [ + (!kIsWeb && Platform.isMacOS) + ? HotKeyModifier.meta + : HotKeyModifier.control, + ], + scope: HotKeyScope.inapp, ); + + useEffect(() { + hotKeyManager.register( + refreshHotKey, + keyDownHandler: (_) { + onRefresh.call(); + }, + ); + + return () { + hotKeyManager.unregister(refreshHotKey); + }; + }, []); + + return RefreshIndicator(onRefresh: onRefresh, child: child); } }