diff --git a/lib/widgets/aves_app.dart b/lib/widgets/aves_app.dart index 72d22e9b8..3554ea4a9 100644 --- a/lib/widgets/aves_app.dart +++ b/lib/widgets/aves_app.dart @@ -60,7 +60,6 @@ class AvesApp extends StatefulWidget { static final _unsupportedLocales = {'ar', 'ckb', 'fa', 'gl', 'he', 'hi', 'nn', 'sk', 'th'}.map(Locale.new).toSet(); static final List supportedLocales = AppLocalizations.supportedLocales.where((v) => !_unsupportedLocales.contains(v)).toList(); static final ValueNotifier cutoutInsetsNotifier = ValueNotifier(EdgeInsets.zero); - static final GlobalKey navigatorKey = GlobalKey(debugLabel: 'app-navigator'); // do not monitor all `ModalRoute`s, which would include popup menus, // so that we can react to fullscreen `PageRoute`s only @@ -156,6 +155,7 @@ class _AvesAppState extends State with WidgetsBindingObserver { // - `OpenUpwardsPageTransitionsBuilder` on Pie / API 28 // - `ZoomPageTransitionsBuilder` on Android 10 / API 29 and above (default in Flutter v3.0.0) static const defaultPageTransitionsBuilder = FadeUpwardsPageTransitionsBuilder(); + static final GlobalKey _navigatorKey = GlobalKey(debugLabel: 'app-navigator'); @override void initState() { @@ -259,7 +259,7 @@ class _AvesAppState extends State with WidgetsBindingObserver { accessibleNavigation: false, ), child: MaterialApp( - navigatorKey: AvesApp.navigatorKey, + navigatorKey: _navigatorKey, home: home, navigatorObservers: _navigatorObservers, builder: (context, child) => _decorateAppChild( @@ -510,7 +510,7 @@ class _AvesAppState extends State with WidgetsBindingObserver { void applyForceTvLayout() { _onTvLayoutChanged(); - unawaited(AvesApp.navigatorKey.currentState!.pushAndRemoveUntil( + unawaited(_navigatorKey.currentState!.pushAndRemoveUntil( MaterialPageRoute( settings: const RouteSettings(name: HomePage.routeName), builder: (_) => _getFirstPage(), @@ -572,7 +572,7 @@ class _AvesAppState extends State with WidgetsBindingObserver { } reportService.log('New intent data=$intentData'); - AvesApp.navigatorKey.currentState!.pushReplacement(DirectMaterialPageRoute( + _navigatorKey.currentState!.pushReplacement(DirectMaterialPageRoute( settings: const RouteSettings(name: HomePage.routeName), builder: (_) => _getFirstPage(intentData: intentData), )); diff --git a/lib/widgets/common/action_mixins/entry_storage.dart b/lib/widgets/common/action_mixins/entry_storage.dart index 3ac7a3e63..9d7df8fbd 100644 --- a/lib/widgets/common/action_mixins/entry_storage.dart +++ b/lib/widgets/common/action_mixins/entry_storage.dart @@ -21,7 +21,6 @@ import 'package:aves/services/media/enums.dart'; import 'package:aves/services/media/media_edit_service.dart'; import 'package:aves/theme/durations.dart'; import 'package:aves/utils/android_file_utils.dart'; -import 'package:aves/widgets/aves_app.dart'; import 'package:aves/widgets/collection/collection_page.dart'; import 'package:aves/widgets/collection/entry_set_action_delegate.dart'; import 'package:aves/widgets/common/action_mixins/feedback.dart'; @@ -91,14 +90,15 @@ mixin EntryStorageMixin on FeedbackMixin, PermissionAwareMixin, SizeAwareMixin { unawaited(source.refreshUris(newUris)); final l10n = context.l10n; + // get navigator beforehand because + // local context may be deactivated when action is triggered after navigation + final navigator = Navigator.maybeOf(context); final showAction = isMainMode && newUris.isNotEmpty ? SnackBarAction( label: l10n.showButtonLabel, onPressed: () { - // local context may be deactivated when action is triggered after navigation - final context = AvesApp.navigatorKey.currentContext; - if (context != null) { - Navigator.maybeOf(context)?.pushAndRemoveUntil( + if (navigator != null) { + navigator.pushAndRemoveUntil( MaterialPageRoute( settings: const RouteSettings(name: CollectionPage.routeName), builder: (context) => CollectionPage( @@ -235,17 +235,18 @@ mixin EntryStorageMixin on FeedbackMixin, PermissionAwareMixin, SizeAwareMixin { SnackBarAction? action; if (count > 0 && appMode == AppMode.main) { + // get navigator beforehand because + // local context may be deactivated when action is triggered after navigation + final navigator = Navigator.maybeOf(context); if (toBin) { if (movedEntries.isNotEmpty) { action = SnackBarAction( // TODO TLAD [l10n] key for "RESTORE" label: l10n.entryActionRestore.toUpperCase(), onPressed: () { - // local context may be deactivated when action is triggered after navigation - final context = AvesApp.navigatorKey.currentContext; - if (context != null) { + if (navigator != null) { doMove( - context, + navigator.context, moveType: MoveType.fromBin, entries: movedEntries, hideShowAction: true, @@ -258,10 +259,8 @@ mixin EntryStorageMixin on FeedbackMixin, PermissionAwareMixin, SizeAwareMixin { action = SnackBarAction( label: l10n.showButtonLabel, onPressed: () { - // local context may be deactivated when action is triggered after navigation - final context = AvesApp.navigatorKey.currentContext; - if (context != null) { - _showMovedItems(context, destinationAlbums, movedOps); + if (navigator != null) { + _showMovedItems(navigator.context, destinationAlbums, movedOps); } }, ); diff --git a/lib/widgets/filter_grids/common/action_delegates/album_set.dart b/lib/widgets/filter_grids/common/action_delegates/album_set.dart index 207802309..b90da750e 100644 --- a/lib/widgets/filter_grids/common/action_delegates/album_set.dart +++ b/lib/widgets/filter_grids/common/action_delegates/album_set.dart @@ -21,7 +21,6 @@ import 'package:aves/services/common/services.dart'; import 'package:aves/services/media/enums.dart'; import 'package:aves/theme/durations.dart'; import 'package:aves/utils/android_file_utils.dart'; -import 'package:aves/widgets/aves_app.dart'; import 'package:aves/widgets/common/action_mixins/entry_storage.dart'; import 'package:aves/widgets/common/action_mixins/vault_aware.dart'; import 'package:aves/widgets/common/extensions/build_context.dart'; @@ -245,18 +244,21 @@ class AlbumChipSetActionDelegate extends ChipSetActionDelegate with source.createAlbum(directory); final filter = AlbumFilter(directory, source.getAlbumDisplayName(context, directory)); + // get navigator beforehand because + // local context may be deactivated when action is triggered after navigation + final navigator = Navigator.maybeOf(context); final showAction = SnackBarAction( label: l10n.showButtonLabel, onPressed: () async { // local context may be deactivated when action is triggered after navigation - final context = AvesApp.navigatorKey.currentContext; - if (context != null) { + if (navigator != null) { + final context = navigator.context; final highlightInfo = context.read(); if (context.currentRouteName == AlbumListPage.routeName) { highlightInfo.trackItem(FilterGridItem(filter, null), highlightItem: filter); } else { highlightInfo.set(filter); - await Navigator.maybeOf(context)?.pushAndRemoveUntil( + await navigator.pushAndRemoveUntil( MaterialPageRoute( settings: const RouteSettings(name: AlbumListPage.routeName), builder: (_) => const AlbumListPage(), diff --git a/lib/widgets/viewer/action/video_action_delegate.dart b/lib/widgets/viewer/action/video_action_delegate.dart index df67b5a91..784aec424 100644 --- a/lib/widgets/viewer/action/video_action_delegate.dart +++ b/lib/widgets/viewer/action/video_action_delegate.dart @@ -10,7 +10,6 @@ import 'package:aves/services/common/services.dart'; import 'package:aves/services/media/enums.dart'; import 'package:aves/theme/durations.dart'; import 'package:aves/utils/android_file_utils.dart'; -import 'package:aves/widgets/aves_app.dart'; import 'package:aves/widgets/collection/collection_page.dart'; import 'package:aves/widgets/common/action_mixins/feedback.dart'; import 'package:aves/widgets/common/action_mixins/permission_aware.dart'; @@ -112,16 +111,17 @@ class VideoActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAwareMix final l10n = context.l10n; if (success) { final _collection = collection; + // get navigator beforehand because + // local context may be deactivated when action is triggered after navigation + final navigator = Navigator.maybeOf(context); final showAction = _collection != null ? SnackBarAction( label: l10n.showButtonLabel, onPressed: () { - // local context may be deactivated when action is triggered after navigation - final context = AvesApp.navigatorKey.currentContext; - if (context != null) { + if (navigator != null) { final source = _collection.source; final newUri = newFields['uri'] as String?; - Navigator.maybeOf(context)?.pushAndRemoveUntil( + navigator.pushAndRemoveUntil( MaterialPageRoute( settings: const RouteSettings(name: CollectionPage.routeName), builder: (context) => CollectionPage(