♻️ Better refresh indicator

This commit is contained in:
2025-12-27 22:16:00 +08:00
parent 48e66580c3
commit 5d5bda7925
2 changed files with 36 additions and 47 deletions

View File

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

View File

@@ -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<ExtendedRefreshIndicator> createState() =>
_ExtendedRefreshIndicatorState();
}
Widget build(BuildContext context, WidgetRef ref) {
final hotKeyIdentifier = useState(Uuid().v4().substring(0, 8));
class _ExtendedRefreshIndicatorState extends State<ExtendedRefreshIndicator> {
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, Intent>{
LogicalKeySet(LogicalKeyboardKey.control, LogicalKeyboardKey.keyR):
const RefreshIntent(),
LogicalKeySet(LogicalKeyboardKey.meta, LogicalKeyboardKey.keyR):
const RefreshIntent(),
LogicalKeySet(LogicalKeyboardKey.f5): const RefreshIntent(),
},
child: Actions(
actions: <Type, Action<Intent>>{
RefreshIntent: CallbackAction<RefreshIntent>(
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);
}
}