✨ Extended refresh indicator (keyboard based)
This commit is contained in:
		| @@ -9,6 +9,7 @@ import 'package:island/widgets/poll/poll_feedback.dart'; | ||||
| import 'package:material_symbols_icons/symbols.dart'; | ||||
| import 'package:riverpod_annotation/riverpod_annotation.dart'; | ||||
| import 'package:riverpod_paging_utils/riverpod_paging_utils.dart'; | ||||
| import 'package:island/widgets/extended_refresh_indicator.dart'; | ||||
|  | ||||
| part 'poll_list.g.dart'; | ||||
|  | ||||
| @@ -86,7 +87,7 @@ class CreatorPollListScreen extends HookConsumerWidget { | ||||
|         onPressed: () => _createPoll(context), | ||||
|         child: const Icon(Icons.add), | ||||
|       ), | ||||
|       body: RefreshIndicator( | ||||
|       body: ExtendedRefreshIndicator( | ||||
|         onRefresh: () => ref.refresh(pollListNotifierProvider(pubName).future), | ||||
|         child: CustomScrollView( | ||||
|           slivers: [ | ||||
|   | ||||
| @@ -4,6 +4,7 @@ import 'package:go_router/go_router.dart'; | ||||
| import 'package:island/pods/webfeed.dart'; | ||||
| import 'package:island/widgets/app_scaffold.dart'; | ||||
| import 'package:island/widgets/empty_state.dart'; | ||||
| import 'package:island/widgets/extended_refresh_indicator.dart'; | ||||
| import 'package:material_symbols_icons/symbols.dart'; | ||||
|  | ||||
| class WebFeedListScreen extends ConsumerWidget { | ||||
| @@ -20,7 +21,10 @@ class WebFeedListScreen extends ConsumerWidget { | ||||
|       floatingActionButton: FloatingActionButton( | ||||
|         child: const Icon(Symbols.add), | ||||
|         onPressed: () { | ||||
|           context.pushNamed('creatorFeedNew', pathParameters: {'name': pubName}); | ||||
|           context.pushNamed( | ||||
|             'creatorFeedNew', | ||||
|             pathParameters: {'name': pubName}, | ||||
|           ); | ||||
|         }, | ||||
|       ), | ||||
|       body: feedsAsync.when( | ||||
| @@ -32,7 +36,7 @@ class WebFeedListScreen extends ConsumerWidget { | ||||
|               description: 'Add a new web feed to get started', | ||||
|             ); | ||||
|           } | ||||
|           return RefreshIndicator( | ||||
|           return ExtendedRefreshIndicator( | ||||
|             onRefresh: () => ref.refresh(webFeedListProvider(pubName).future), | ||||
|             child: ListView.builder( | ||||
|               padding: EdgeInsets.only(top: 8), | ||||
| @@ -62,7 +66,10 @@ class WebFeedListScreen extends ConsumerWidget { | ||||
|                     ), | ||||
|                     trailing: const Icon(Symbols.chevron_right), | ||||
|                     onTap: () { | ||||
|                       context.pushNamed('creatorFeedEdit', pathParameters: {'name': pubName, 'feedId': feed.id}); | ||||
|                       context.pushNamed( | ||||
|                         'creatorFeedEdit', | ||||
|                         pathParameters: {'name': pubName, 'feedId': feed.id}, | ||||
|                       ); | ||||
|                     }, | ||||
|                   ), | ||||
|                 ); | ||||
|   | ||||
| @@ -9,6 +9,7 @@ import 'package:island/widgets/content/cloud_files.dart'; | ||||
| import 'package:island/widgets/response.dart'; | ||||
| import 'package:material_symbols_icons/symbols.dart'; | ||||
| import 'package:riverpod_annotation/riverpod_annotation.dart'; | ||||
| import 'package:island/widgets/extended_refresh_indicator.dart'; | ||||
|  | ||||
| part 'bots.g.dart'; | ||||
|  | ||||
| @@ -60,7 +61,7 @@ class BotsScreen extends HookConsumerWidget { | ||||
|             ), | ||||
|           ); | ||||
|         } | ||||
|         return RefreshIndicator( | ||||
|         return ExtendedRefreshIndicator( | ||||
|           onRefresh: | ||||
|               () => ref.refresh(botsProvider(publisherName, projectId).future), | ||||
|           child: ListView.builder( | ||||
|   | ||||
| @@ -27,6 +27,7 @@ import 'package:island/pods/network.dart'; | ||||
| import 'package:island/widgets/realm/realm_card.dart'; | ||||
| import 'package:island/widgets/publisher/publisher_card.dart'; | ||||
| import 'package:island/widgets/web_article_card.dart'; | ||||
| import 'package:island/widgets/extended_refresh_indicator.dart'; | ||||
| import 'package:styled_widget/styled_widget.dart'; | ||||
|  | ||||
| part 'explore.g.dart'; | ||||
| @@ -368,7 +369,7 @@ class ExploreScreen extends HookConsumerWidget { | ||||
|  | ||||
|     final isWide = isWideScreen(context); | ||||
|  | ||||
|     return RefreshIndicator( | ||||
|     return ExtendedRefreshIndicator( | ||||
|       onRefresh: () => Future.sync(activitiesNotifier.forceRefresh), | ||||
|       child: PagingHelperView( | ||||
|         provider: activityListNotifierProvider(filter), | ||||
|   | ||||
| @@ -23,6 +23,7 @@ import 'package:material_symbols_icons/symbols.dart'; | ||||
| import 'package:riverpod_annotation/riverpod_annotation.dart'; | ||||
| import 'package:styled_widget/styled_widget.dart'; | ||||
| import 'package:island/widgets/realm/realm_list_tile.dart'; | ||||
| import 'package:island/widgets/extended_refresh_indicator.dart'; | ||||
|  | ||||
| part 'realms.g.dart'; | ||||
|  | ||||
| @@ -90,7 +91,7 @@ class RealmListScreen extends HookConsumerWidget { | ||||
|         }, | ||||
|       ), | ||||
|       floatingActionButtonLocation: TabbedFabLocation(context), | ||||
|       body: RefreshIndicator( | ||||
|       body: ExtendedRefreshIndicator( | ||||
|         child: realms.when( | ||||
|           data: | ||||
|               (value) => Column( | ||||
|   | ||||
| @@ -12,6 +12,7 @@ import 'package:island/widgets/content/sheet.dart'; | ||||
| import 'package:island/widgets/response.dart'; | ||||
| import 'package:riverpod_annotation/riverpod_annotation.dart'; | ||||
| import 'package:styled_widget/styled_widget.dart'; | ||||
| import 'package:island/widgets/extended_refresh_indicator.dart'; | ||||
|  | ||||
| part 'account_devices.g.dart'; | ||||
|  | ||||
| @@ -177,7 +178,7 @@ class AccountSessionSheet extends HookConsumerWidget { | ||||
|       titleText: 'authSessions'.tr(), | ||||
|       child: authDevices.when( | ||||
|         data: | ||||
|             (data) => RefreshIndicator( | ||||
|             (data) => ExtendedRefreshIndicator( | ||||
|               onRefresh: | ||||
|                   () => Future.sync(() => ref.invalidate(authDevicesProvider)), | ||||
|               child: ListView.builder( | ||||
|   | ||||
							
								
								
									
										67
									
								
								lib/widgets/extended_refresh_indicator.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								lib/widgets/extended_refresh_indicator.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,67 @@ | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:flutter/services.dart'; | ||||
|  | ||||
| class RefreshIntent extends Intent { | ||||
|   const RefreshIntent(); | ||||
| } | ||||
|  | ||||
| class ExtendedRefreshIndicator extends StatefulWidget { | ||||
|   final Widget child; | ||||
|   final RefreshCallback onRefresh; | ||||
|  | ||||
|   const ExtendedRefreshIndicator({ | ||||
|     super.key, | ||||
|     required this.child, | ||||
|     required this.onRefresh, | ||||
|   }); | ||||
|  | ||||
|   @override | ||||
|   State<ExtendedRefreshIndicator> createState() => | ||||
|       _ExtendedRefreshIndicatorState(); | ||||
| } | ||||
|  | ||||
| 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, | ||||
|           ), | ||||
|         ), | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
| } | ||||
| @@ -12,6 +12,7 @@ import 'package:material_symbols_icons/symbols.dart'; | ||||
| import 'package:riverpod_annotation/riverpod_annotation.dart'; | ||||
| import 'package:styled_widget/styled_widget.dart'; | ||||
| import 'package:flutter_popup_card/flutter_popup_card.dart'; | ||||
| import 'package:island/widgets/extended_refresh_indicator.dart'; | ||||
|  | ||||
| part 'picker.g.dart'; | ||||
|  | ||||
| @@ -208,7 +209,7 @@ class _PackSwitcherState extends State<_PackSwitcher> { | ||||
|  | ||||
|         // Content | ||||
|         Expanded( | ||||
|           child: RefreshIndicator( | ||||
|           child: ExtendedRefreshIndicator( | ||||
|             onRefresh: widget.onRefresh, | ||||
|             child: _StickersGrid( | ||||
|               pack: selectedPack, | ||||
|   | ||||
		Reference in New Issue
	
	Block a user