various fixes
This commit is contained in:
parent
a5cf5ca555
commit
7bf83b4892
80 changed files with 165 additions and 193 deletions
|
@ -172,7 +172,18 @@ open class MainActivity : FlutterActivity() {
|
|||
mediaSessionHandler.dispose()
|
||||
mediaStoreChangeStreamHandler.dispose()
|
||||
settingsChangeStreamHandler.dispose()
|
||||
try {
|
||||
super.onDestroy()
|
||||
} catch (e: Exception) {
|
||||
// on Android 11, app may crash as follows:
|
||||
// `Fatal Exception:`
|
||||
// `java.lang.RuntimeException: Unable to destroy activity {deckers.thibault.aves/deckers.thibault.aves.MainActivity}:`
|
||||
// `java.lang.IllegalArgumentException: NetworkCallback was not registered`
|
||||
// related to this error:
|
||||
// `Package android does not belong to 10162`
|
||||
// cf https://issuetracker.google.com/issues/175055271
|
||||
Log.e(LOG_TAG, "failed while destroying activity", e)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onNewIntent(intent: Intent) {
|
||||
|
|
|
@ -30,6 +30,7 @@ import 'package:latlong2/latlong.dart';
|
|||
final Settings settings = Settings._private();
|
||||
|
||||
class Settings extends ChangeNotifier {
|
||||
final List<StreamSubscription> _subscriptions = [];
|
||||
final EventChannel _platformSettingsChangeChannel = const OptionalEventChannel('deckers.thibault/aves/settings_change');
|
||||
final StreamController<SettingsChangedEvent> _updateStreamController = StreamController.broadcast();
|
||||
|
||||
|
@ -209,7 +210,10 @@ class Settings extends ChangeNotifier {
|
|||
await settingsStore.init();
|
||||
_appliedLocale = null;
|
||||
if (monitorPlatformSettings) {
|
||||
_platformSettingsChangeChannel.receiveBroadcastStream().listen((event) => _onPlatformSettingsChanged(event as Map?));
|
||||
_subscriptions
|
||||
..forEach((sub) => sub.cancel())
|
||||
..clear();
|
||||
_subscriptions.add(_platformSettingsChangeChannel.receiveBroadcastStream().listen((event) => _onPlatformSettingsChanged(event as Map?)));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ import 'package:aves/widgets/viewer/video/controller.dart';
|
|||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
|
||||
abstract class MediaSessionService {
|
||||
Stream<MediaCommandEvent> get mediaCommands;
|
||||
|
@ -15,14 +16,22 @@ abstract class MediaSessionService {
|
|||
Future<void> release();
|
||||
}
|
||||
|
||||
class PlatformMediaSessionService implements MediaSessionService {
|
||||
class PlatformMediaSessionService implements MediaSessionService, Disposable {
|
||||
static const _platformObject = MethodChannel('deckers.thibault/aves/media_session');
|
||||
|
||||
final List<StreamSubscription> _subscriptions = [];
|
||||
final EventChannel _mediaCommandChannel = const OptionalEventChannel('deckers.thibault/aves/media_command');
|
||||
final StreamController _streamController = StreamController.broadcast();
|
||||
|
||||
PlatformMediaSessionService() {
|
||||
_mediaCommandChannel.receiveBroadcastStream().listen((event) => _onMediaCommand(event as Map?));
|
||||
_subscriptions.add(_mediaCommandChannel.receiveBroadcastStream().listen((event) => _onMediaCommand(event as Map?)));
|
||||
}
|
||||
|
||||
@override
|
||||
FutureOr onDispose() {
|
||||
_subscriptions
|
||||
..forEach((sub) => sub.cancel())
|
||||
..clear();
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
@ -2,8 +2,16 @@ import 'dart:ui';
|
|||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:latlong2/latlong.dart';
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
|
||||
class Constants {
|
||||
static const storagePermissions = [
|
||||
Permission.storage,
|
||||
// for media access on Android >=13
|
||||
Permission.photos,
|
||||
Permission.videos,
|
||||
];
|
||||
|
||||
static const separator = ' • ';
|
||||
|
||||
// `Color(0x00FFFFFF)` is different from `Color(0x00000000)` (or `Colors.transparent`)
|
||||
|
|
|
@ -102,8 +102,7 @@ class _AppReferenceState extends State<AppReference> {
|
|||
}
|
||||
|
||||
void _goToPolicyPage() {
|
||||
Navigator.push(
|
||||
context,
|
||||
Navigator.maybeOf(context)?.push(
|
||||
MaterialPageRoute(
|
||||
settings: const RouteSettings(name: PolicyPage.routeName),
|
||||
builder: (context) => const PolicyPage(),
|
||||
|
|
|
@ -80,8 +80,7 @@ class _LicensesState extends State<Licenses> {
|
|||
Center(
|
||||
child: AvesOutlinedButton(
|
||||
label: context.l10n.aboutLicensesShowAllButtonLabel,
|
||||
onPressed: () => Navigator.push(
|
||||
context,
|
||||
onPressed: () => Navigator.maybeOf(context)?.push(
|
||||
MaterialPageRoute(
|
||||
builder: (context) => Theme(
|
||||
data: Theme.of(context).copyWith(
|
||||
|
|
|
@ -678,8 +678,7 @@ class _CollectionAppBarState extends State<CollectionAppBar> with SingleTickerPr
|
|||
}
|
||||
|
||||
void _goToSearch() {
|
||||
Navigator.push(
|
||||
context,
|
||||
Navigator.maybeOf(context)?.push(
|
||||
SearchPageRoute(
|
||||
delegate: CollectionSearchDelegate(
|
||||
searchFieldLabel: context.l10n.searchCollectionFieldHint,
|
||||
|
|
|
@ -13,6 +13,7 @@ import 'package:aves/model/source/section_keys.dart';
|
|||
import 'package:aves/ref/mime_types.dart';
|
||||
import 'package:aves/theme/durations.dart';
|
||||
import 'package:aves/theme/icons.dart';
|
||||
import 'package:aves/utils/constants.dart';
|
||||
import 'package:aves/widgets/collection/app_bar.dart';
|
||||
import 'package:aves/widgets/collection/draggable_thumb_label.dart';
|
||||
import 'package:aves/widgets/collection/grid/list_details_theme.dart';
|
||||
|
@ -642,5 +643,5 @@ class _CollectionScrollViewState extends State<_CollectionScrollView> with Widge
|
|||
return crumbs;
|
||||
}
|
||||
|
||||
Future<bool> get _isStoragePermissionGranted => Permission.storage.status.then((status) => status.isGranted);
|
||||
Future<bool> get _isStoragePermissionGranted => Future.wait(Constants.storagePermissions.map((v) => v.status)).then((v) => v.any((status) => status.isGranted));
|
||||
}
|
||||
|
|
|
@ -342,8 +342,7 @@ class EntrySetActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAware
|
|||
Future<void> _rename(BuildContext context) async {
|
||||
final entries = _getTargetItems(context).toList();
|
||||
|
||||
final pattern = await Navigator.push<NamingPattern>(
|
||||
context,
|
||||
final pattern = await Navigator.maybeOf(context)?.push<NamingPattern>(
|
||||
MaterialPageRoute(
|
||||
settings: const RouteSettings(name: RenameEntrySetPage.routeName),
|
||||
builder: (context) => RenameEntrySetPage(
|
||||
|
@ -468,7 +467,7 @@ class EntrySetActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAware
|
|||
const CancelButton(),
|
||||
if (supported.isNotEmpty)
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context, true),
|
||||
onPressed: () => Navigator.maybeOf(context)?.pop(true),
|
||||
child: Text(l10n.continueButtonLabel),
|
||||
),
|
||||
],
|
||||
|
@ -523,8 +522,7 @@ class EntrySetActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAware
|
|||
final editableEntries = await _getEditableItems(context, entries, canEdit: (entry) => entry.canEditLocation);
|
||||
if (editableEntries == null || editableEntries.isEmpty) return null;
|
||||
|
||||
final location = await Navigator.push(
|
||||
context,
|
||||
final location = await Navigator.maybeOf(context)?.push(
|
||||
MaterialPageRoute(
|
||||
settings: const RouteSettings(name: LocationPickPage.routeName),
|
||||
builder: (context) => LocationPickPage(
|
||||
|
@ -548,7 +546,7 @@ class EntrySetActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAware
|
|||
actions: [
|
||||
const CancelButton(),
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context, true),
|
||||
onPressed: () => Navigator.maybeOf(context)?.pop(true),
|
||||
child: Text(context.l10n.applyButtonLabel),
|
||||
),
|
||||
],
|
||||
|
@ -621,8 +619,7 @@ class EntrySetActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAware
|
|||
filters: collection.filters,
|
||||
fixedSelection: entries.where((entry) => entry.hasGps).toList(),
|
||||
);
|
||||
await Navigator.push(
|
||||
context,
|
||||
await Navigator.maybeOf(context)?.push(
|
||||
MaterialPageRoute(
|
||||
settings: const RouteSettings(name: MapPage.routeName),
|
||||
builder: (context) => MapPage(collection: mapCollection),
|
||||
|
@ -635,8 +632,7 @@ class EntrySetActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAware
|
|||
final collection = context.read<CollectionLens>();
|
||||
final entries = _getTargetItems(context);
|
||||
|
||||
Navigator.push(
|
||||
context,
|
||||
Navigator.maybeOf(context)?.push(
|
||||
MaterialPageRoute(
|
||||
settings: const RouteSettings(name: SlideshowPage.routeName),
|
||||
builder: (context) {
|
||||
|
@ -656,8 +652,7 @@ class EntrySetActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAware
|
|||
final collection = context.read<CollectionLens>();
|
||||
final entries = _getTargetItems(context);
|
||||
|
||||
Navigator.push(
|
||||
context,
|
||||
Navigator.maybeOf(context)?.push(
|
||||
MaterialPageRoute(
|
||||
settings: const RouteSettings(name: StatsPage.routeName),
|
||||
builder: (context) => StatsPage(
|
||||
|
@ -672,8 +667,7 @@ class EntrySetActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAware
|
|||
void _goToSearch(BuildContext context) {
|
||||
final collection = context.read<CollectionLens>();
|
||||
|
||||
Navigator.push(
|
||||
context,
|
||||
Navigator.maybeOf(context)?.push(
|
||||
SearchPageRoute(
|
||||
delegate: CollectionSearchDelegate(
|
||||
searchFieldLabel: context.l10n.searchCollectionFieldHint,
|
||||
|
|
|
@ -51,7 +51,7 @@ class InteractiveTile extends StatelessWidget {
|
|||
selection.toggleSelection(entry);
|
||||
break;
|
||||
case AppMode.pickMediaInternal:
|
||||
Navigator.pop(context, entry);
|
||||
Navigator.maybeOf(context)?.pop(entry);
|
||||
break;
|
||||
case AppMode.pickCollectionFiltersExternal:
|
||||
case AppMode.pickFilterInternal:
|
||||
|
@ -81,8 +81,7 @@ class InteractiveTile extends StatelessWidget {
|
|||
}
|
||||
|
||||
void _goToViewer(BuildContext context) {
|
||||
Navigator.push(
|
||||
context,
|
||||
Navigator.maybeOf(context)?.push(
|
||||
TransparentMaterialPageRoute(
|
||||
settings: const RouteSettings(name: EntryViewerPage.routeName),
|
||||
pageBuilder: (context, a, sa) {
|
||||
|
|
|
@ -82,8 +82,7 @@ mixin EntryEditorMixin {
|
|||
final filters = <CollectionFilter>{...v.tags.map(TagFilter.new)};
|
||||
return MapEntry(v, filters);
|
||||
}));
|
||||
await Navigator.push(
|
||||
context,
|
||||
await Navigator.maybeOf(context)?.push(
|
||||
MaterialPageRoute(
|
||||
settings: const RouteSettings(name: TagEditorPage.routeName),
|
||||
builder: (context) => TagEditorPage(
|
||||
|
@ -128,7 +127,7 @@ mixin EntryEditorMixin {
|
|||
actions: [
|
||||
const CancelButton(),
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context, true),
|
||||
onPressed: () => Navigator.maybeOf(context)?.pop(true),
|
||||
child: Text(context.l10n.applyButtonLabel),
|
||||
),
|
||||
],
|
||||
|
|
|
@ -330,8 +330,7 @@ mixin EntryStorageMixin on FeedbackMixin, PermissionAwareMixin, SizeAwareMixin {
|
|||
targetFilters.removeWhere((f) => f is AlbumFilter);
|
||||
targetFilters.add(AlbumFilter(destinationAlbum, source.getAlbumDisplayName(context, destinationAlbum)));
|
||||
}
|
||||
unawaited(Navigator.pushAndRemoveUntil(
|
||||
context,
|
||||
unawaited(Navigator.maybeOf(context)?.pushAndRemoveUntil(
|
||||
MaterialPageRoute(
|
||||
settings: const RouteSettings(name: CollectionPage.routeName),
|
||||
builder: (context) => CollectionPage(
|
||||
|
|
|
@ -145,7 +145,7 @@ mixin FeedbackMixin {
|
|||
itemCount: itemCount,
|
||||
onCancel: onCancel,
|
||||
onDone: (processed) {
|
||||
Navigator.pop(context);
|
||||
Navigator.maybeOf(context)?.pop();
|
||||
onDone?.call(processed);
|
||||
},
|
||||
),
|
||||
|
|
|
@ -56,7 +56,7 @@ mixin PermissionAwareMixin {
|
|||
actions: [
|
||||
const CancelButton(),
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context, true),
|
||||
onPressed: () => Navigator.maybeOf(context)?.pop(true),
|
||||
child: Text(MaterialLocalizations.of(context).okButtonLabel),
|
||||
),
|
||||
],
|
||||
|
|
|
@ -96,7 +96,7 @@ class _ColorPickerDialogState extends State<ColorPickerDialog> {
|
|||
actions: [
|
||||
const CancelButton(),
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context, color),
|
||||
onPressed: () => Navigator.maybeOf(context)?.pop(color),
|
||||
child: Text(context.l10n.applyButtonLabel),
|
||||
),
|
||||
],
|
||||
|
|
|
@ -16,8 +16,7 @@ class TvNavigationPopHandler {
|
|||
return true;
|
||||
}
|
||||
|
||||
Navigator.pushAndRemoveUntil(
|
||||
context,
|
||||
Navigator.maybeOf(context)?.pushAndRemoveUntil(
|
||||
_getHomeRoute(),
|
||||
(route) => false,
|
||||
);
|
||||
|
|
|
@ -37,7 +37,7 @@ class MapButtonPanel extends StatelessWidget {
|
|||
if (!settings.useTvLayout) {
|
||||
navigationButton = MapOverlayButton(
|
||||
icon: const BackButtonIcon(),
|
||||
onPressed: () => Navigator.pop(context),
|
||||
onPressed: () => Navigator.maybeOf(context)?.pop(),
|
||||
tooltip: MaterialLocalizations.of(context).backButtonTooltip,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -61,7 +61,7 @@ abstract class AvesSearchDelegate extends SearchDelegate {
|
|||
|
||||
void goBack(BuildContext context) {
|
||||
clean();
|
||||
Navigator.pop(context);
|
||||
Navigator.maybeOf(context)?.pop();
|
||||
}
|
||||
|
||||
void clean() {
|
||||
|
|
|
@ -196,8 +196,7 @@ class _AppDebugPageState extends State<AppDebugPage> {
|
|||
);
|
||||
break;
|
||||
case AppDebugAction.greenScreen:
|
||||
await Navigator.push(
|
||||
context,
|
||||
await Navigator.maybeOf(context)?.push(
|
||||
MaterialPageRoute(
|
||||
builder: (context) => const Scaffold(
|
||||
backgroundColor: Colors.green,
|
||||
|
|
|
@ -41,7 +41,7 @@ class _MediaStoreScanDirDialogState extends State<MediaStoreScanDirDialog> {
|
|||
}
|
||||
});
|
||||
}
|
||||
Navigator.pop(context);
|
||||
Navigator.maybeOf(context)?.pop();
|
||||
},
|
||||
child: const Text('Scan'),
|
||||
)
|
||||
|
|
|
@ -108,8 +108,7 @@ class _AddShortcutDialogState extends State<AddShortcutDialog> {
|
|||
final _collection = widget.collection;
|
||||
if (_collection == null) return;
|
||||
|
||||
final entry = await Navigator.push<AvesEntry>(
|
||||
context,
|
||||
final entry = await Navigator.maybeOf(context)?.push<AvesEntry>(
|
||||
MaterialPageRoute(
|
||||
settings: const RouteSettings(name: ItemPickPage.routeName),
|
||||
builder: (context) {
|
||||
|
@ -142,7 +141,7 @@ class _AddShortcutDialogState extends State<AddShortcutDialog> {
|
|||
|
||||
void _submit(BuildContext context) {
|
||||
if (_isValidNotifier.value) {
|
||||
Navigator.pop(context, Tuple2<AvesEntry?, String>(_coverEntry, _nameController.text));
|
||||
Navigator.maybeOf(context)?.pop(Tuple2<AvesEntry?, String>(_coverEntry, _nameController.text));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -116,7 +116,7 @@ class _AvesConfirmationDialogState extends State<_AvesConfirmationDialog> {
|
|||
if (_skip.value) {
|
||||
_skipConfirmation(widget.type);
|
||||
}
|
||||
Navigator.pop(context, true);
|
||||
Navigator.maybeOf(context)?.pop(true);
|
||||
},
|
||||
child: Text(widget.confirmationButtonLabel),
|
||||
),
|
||||
|
|
|
@ -166,7 +166,7 @@ class CancelButton extends StatelessWidget {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return TextButton(
|
||||
onPressed: () => Navigator.pop(context),
|
||||
onPressed: () => Navigator.maybeOf(context)?.pop(),
|
||||
child: Text(MaterialLocalizations.of(context).cancelButtonLabel),
|
||||
);
|
||||
}
|
||||
|
@ -178,7 +178,7 @@ class OkButton extends StatelessWidget {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return TextButton(
|
||||
onPressed: () => Navigator.pop(context),
|
||||
onPressed: () => Navigator.maybeOf(context)?.pop(),
|
||||
child: Text(MaterialLocalizations.of(context).okButtonLabel),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -89,7 +89,7 @@ class _AvesSelectionDialogState<T> extends State<AvesSelectionDialog<T>> {
|
|||
const CancelButton(),
|
||||
if (needConfirmation)
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context, _selectedValue),
|
||||
onPressed: () => Navigator.maybeOf(context)?.pop(_selectedValue),
|
||||
child: Text(confirmationButtonLabel),
|
||||
),
|
||||
],
|
||||
|
@ -129,7 +129,7 @@ class SelectionRadioListTile<T> extends StatelessWidget {
|
|||
if (needConfirmation) {
|
||||
setGroupValue(v as T);
|
||||
} else {
|
||||
Navigator.pop(context, v);
|
||||
Navigator.maybeOf(context)?.pop(v);
|
||||
}
|
||||
},
|
||||
reselectable: true,
|
||||
|
|
|
@ -106,5 +106,5 @@ class _DurationDialogState extends State<DurationDialog> {
|
|||
);
|
||||
}
|
||||
|
||||
void _submit(BuildContext context) => Navigator.pop(context, _minutes.value * secondsInMinute + _seconds.value);
|
||||
void _submit(BuildContext context) => Navigator.maybeOf(context)?.pop(_minutes.value * secondsInMinute + _seconds.value);
|
||||
}
|
||||
|
|
|
@ -329,8 +329,7 @@ class _EditEntryDateDialogState extends State<EditEntryDateDialog> {
|
|||
final _collection = widget.collection;
|
||||
if (_collection == null) return;
|
||||
|
||||
final entry = await Navigator.push<AvesEntry>(
|
||||
context,
|
||||
final entry = await Navigator.maybeOf(context)?.push<AvesEntry>(
|
||||
MaterialPageRoute(
|
||||
settings: const RouteSettings(name: ItemPickPage.routeName),
|
||||
builder: (context) => ItemPickPage(
|
||||
|
@ -384,7 +383,7 @@ class _EditEntryDateDialogState extends State<EditEntryDateDialog> {
|
|||
|
||||
void _submit(BuildContext context) {
|
||||
if (_isValidNotifier.value) {
|
||||
Navigator.pop(context, _getModifier());
|
||||
Navigator.maybeOf(context)?.pop(_getModifier());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -103,6 +103,6 @@ class _EditEntryTitleDescriptionDialogState extends State<EditEntryTitleDescript
|
|||
final text = _fieldController(field).text;
|
||||
return MapEntry(field, text.isEmpty ? null : text);
|
||||
}));
|
||||
return Navigator.pop<Map<DescriptionField, String?>>(context, modifier);
|
||||
return Navigator.maybeOf(context)?.pop<Map<DescriptionField, String?>>(modifier);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -180,8 +180,7 @@ class _EditEntryLocationDialogState extends State<EditEntryLocationDialog> {
|
|||
fixedSelection: baseCollection.sortedEntries.where((entry) => entry.hasGps).toList(),
|
||||
)
|
||||
: null;
|
||||
final latLng = await Navigator.push(
|
||||
context,
|
||||
final latLng = await Navigator.maybeOf(context)?.push(
|
||||
MaterialPageRoute(
|
||||
settings: const RouteSettings(name: LocationPickPage.routeName),
|
||||
builder: (context) => LocationPickPage(
|
||||
|
@ -222,8 +221,7 @@ class _EditEntryLocationDialogState extends State<EditEntryLocationDialog> {
|
|||
final _collection = widget.collection;
|
||||
if (_collection == null) return;
|
||||
|
||||
final entry = await Navigator.push<AvesEntry>(
|
||||
context,
|
||||
final entry = await Navigator.maybeOf(context)?.push<AvesEntry>(
|
||||
MaterialPageRoute(
|
||||
settings: const RouteSettings(name: ItemPickPage.routeName),
|
||||
builder: (context) => ItemPickPage(
|
||||
|
@ -330,16 +328,16 @@ class _EditEntryLocationDialogState extends State<EditEntryLocationDialog> {
|
|||
void _submit(BuildContext context) {
|
||||
switch (_action) {
|
||||
case LocationEditAction.chooseOnMap:
|
||||
Navigator.pop(context, _mapCoordinates);
|
||||
Navigator.maybeOf(context)?.pop(_mapCoordinates);
|
||||
break;
|
||||
case LocationEditAction.copyItem:
|
||||
Navigator.pop(context, _copyItemSource.latLng);
|
||||
Navigator.maybeOf(context)?.pop(_copyItemSource.latLng);
|
||||
break;
|
||||
case LocationEditAction.setCustom:
|
||||
Navigator.pop(context, _parseLatLng());
|
||||
Navigator.maybeOf(context)?.pop(_parseLatLng());
|
||||
break;
|
||||
case LocationEditAction.remove:
|
||||
Navigator.pop(context, ExtraAvesEntryMetadataEdition.removalLocation);
|
||||
Navigator.maybeOf(context)?.pop(ExtraAvesEntryMetadataEdition.removalLocation);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -126,7 +126,7 @@ class _EditEntryRatingDialogState extends State<EditEntryRatingDialog> {
|
|||
entryRating = 0;
|
||||
break;
|
||||
}
|
||||
Navigator.pop(context, entryRating);
|
||||
Navigator.maybeOf(context)?.pop(entryRating);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -136,5 +136,5 @@ class _RemoveEntryMetadataDialogState extends State<RemoveEntryMetadataDialog> {
|
|||
|
||||
void _validate() => _isValidNotifier.value = _types.isNotEmpty;
|
||||
|
||||
void _submit(BuildContext context) => Navigator.pop(context, _types);
|
||||
void _submit(BuildContext context) => Navigator.maybeOf(context)?.pop(_types);
|
||||
}
|
||||
|
|
|
@ -88,7 +88,7 @@ class _RenameEntryDialogState extends State<RenameEntryDialog> {
|
|||
|
||||
void _submit(BuildContext context) {
|
||||
if (_isValidNotifier.value) {
|
||||
Navigator.pop(context, newName);
|
||||
Navigator.maybeOf(context)?.pop(newName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -185,7 +185,7 @@ class _RenameEntrySetPageState extends State<RenameEntrySetPage> {
|
|||
label: l10n.entryActionRename,
|
||||
onPressed: () {
|
||||
settings.entryRenamingPattern = _patternTextController.text;
|
||||
Navigator.pop<NamingPattern>(context, _namingPatternNotifier.value);
|
||||
Navigator.maybeOf(context)?.pop<NamingPattern>(_namingPatternNotifier.value);
|
||||
},
|
||||
),
|
||||
),
|
||||
|
|
|
@ -130,7 +130,7 @@ class _ExportEntryDialogState extends State<ExportEntryDialog> {
|
|||
height: height,
|
||||
)
|
||||
: null;
|
||||
Navigator.pop(context, options);
|
||||
Navigator.maybeOf(context)?.pop(options);
|
||||
}
|
||||
: null,
|
||||
child: Text(l10n.applyButtonLabel),
|
||||
|
|
|
@ -161,7 +161,7 @@ class _CoverSelectionDialogState extends State<CoverSelectionDialog> {
|
|||
final entry = _isCustomEntry ? _customEntry : null;
|
||||
final package = _isCustomPackage ? _customPackage : null;
|
||||
final color = _isCustomColor ? _customColor : null;
|
||||
return Navigator.pop(context, Tuple3<AvesEntry?, String?, Color?>(entry, package, color));
|
||||
return Navigator.maybeOf(context)?.pop(Tuple3<AvesEntry?, String?, Color?>(entry, package, color));
|
||||
},
|
||||
child: Text(l10n.applyButtonLabel),
|
||||
)
|
||||
|
@ -340,8 +340,7 @@ class _CoverSelectionDialogState extends State<CoverSelectionDialog> {
|
|||
}
|
||||
|
||||
Future<void> _pickEntry() async {
|
||||
final entry = await Navigator.push<AvesEntry>(
|
||||
context,
|
||||
final entry = await Navigator.maybeOf(context)?.push<AvesEntry>(
|
||||
MaterialPageRoute(
|
||||
settings: const RouteSettings(name: ItemPickPage.routeName),
|
||||
builder: (context) => ItemPickPage(
|
||||
|
@ -361,8 +360,7 @@ class _CoverSelectionDialogState extends State<CoverSelectionDialog> {
|
|||
}
|
||||
|
||||
Future<void> _pickPackage() async {
|
||||
final package = await Navigator.push<String>(
|
||||
context,
|
||||
final package = await Navigator.maybeOf(context)?.push<String>(
|
||||
MaterialPageRoute(
|
||||
settings: const RouteSettings(name: AppPickPage.routeName),
|
||||
builder: (context) => AppPickPage(
|
||||
|
|
|
@ -159,7 +159,7 @@ class _CreateAlbumDialogState extends State<CreateAlbumDialog> {
|
|||
|
||||
void _submit(BuildContext context) {
|
||||
if (_isValidNotifier.value) {
|
||||
Navigator.pop(context, _buildAlbumPath(_nameController.text));
|
||||
Navigator.maybeOf(context)?.pop(_buildAlbumPath(_nameController.text));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -88,7 +88,7 @@ class _RenameAlbumDialogState extends State<RenameAlbumDialog> {
|
|||
|
||||
void _submit(BuildContext context) {
|
||||
if (_isValidNotifier.value) {
|
||||
Navigator.pop(context, _nameController.text);
|
||||
Navigator.maybeOf(context)?.pop(_nameController.text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,8 +35,7 @@ Future<String?> pickAlbum({
|
|||
// source may not be fully initialized in view mode
|
||||
await source.init();
|
||||
}
|
||||
final filter = await Navigator.push(
|
||||
context,
|
||||
final filter = await Navigator.maybeOf(context)?.push(
|
||||
MaterialPageRoute<AlbumFilter>(
|
||||
settings: const RouteSettings(name: _AlbumPickPage.routeName),
|
||||
builder: (context) => _AlbumPickPage(source: source, moveType: moveType),
|
||||
|
@ -188,7 +187,7 @@ class _AlbumPickPageState extends State<_AlbumPickPage> {
|
|||
// wait for the dialog to hide as applying the change may block the UI
|
||||
await Future.delayed(Durations.dialogTransitionAnimation * timeDilation);
|
||||
if (newAlbum != null && newAlbum.isNotEmpty) {
|
||||
Navigator.pop<AlbumFilter>(context, AlbumFilter(newAlbum, source.getAlbumDisplayName(context, newAlbum)));
|
||||
Navigator.maybeOf(context)?.pop<AlbumFilter>(AlbumFilter(newAlbum, source.getAlbumDisplayName(context, newAlbum)));
|
||||
}
|
||||
},
|
||||
tooltip: context.l10n.createAlbumTooltip,
|
||||
|
|
|
@ -83,7 +83,7 @@ class _AppPickPageState extends State<AppPickPage> {
|
|||
return ReselectableRadioListTile<String?>(
|
||||
value: '',
|
||||
groupValue: _selectedValue,
|
||||
onChanged: (v) => Navigator.pop(context, v),
|
||||
onChanged: (v) => Navigator.maybeOf(context)?.pop(v),
|
||||
reselectable: true,
|
||||
title: Text(
|
||||
context.l10n.appPickDialogNone,
|
||||
|
@ -100,7 +100,7 @@ class _AppPickPageState extends State<AppPickPage> {
|
|||
return ReselectableRadioListTile<String?>(
|
||||
value: package.packageName,
|
||||
groupValue: _selectedValue,
|
||||
onChanged: (v) => Navigator.pop(context, v),
|
||||
onChanged: (v) => Navigator.maybeOf(context)?.pop(v),
|
||||
reselectable: true,
|
||||
title: Text.rich(
|
||||
TextSpan(
|
||||
|
|
|
@ -118,7 +118,7 @@ class _ContentState extends State<_Content> with SingleTickerProviderStateMixin
|
|||
const SizedBox(height: 8),
|
||||
AvesOutlinedButton(
|
||||
label: context.l10n.locationPickerUseThisLocationButton,
|
||||
onPressed: () => Navigator.pop(context, _dotLocationNotifier.value),
|
||||
onPressed: () => Navigator.maybeOf(context)?.pop(_dotLocationNotifier.value),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
|
@ -150,7 +150,7 @@ class _TileViewDialogState<S, G, L> extends State<TileViewDialog<S, G, L>> with
|
|||
key: const Key('button-apply'),
|
||||
onPressed: () {
|
||||
tileExtentController.setUserPreferredColumnCount(_columnCountNotifier.value);
|
||||
Navigator.pop(context, Tuple4(_selectedSort, _selectedGroup, _selectedLayout, _reverseSort));
|
||||
Navigator.maybeOf(context)?.pop(Tuple4(_selectedSort, _selectedGroup, _selectedLayout, _reverseSort));
|
||||
},
|
||||
child: Text(l10n.applyButtonLabel),
|
||||
)
|
||||
|
|
|
@ -66,5 +66,5 @@ class _VideoSpeedDialogState extends State<VideoSpeedDialog> {
|
|||
);
|
||||
}
|
||||
|
||||
void _submit(BuildContext context) => Navigator.pop(context, _speed);
|
||||
void _submit(BuildContext context) => Navigator.maybeOf(context)?.pop(_speed);
|
||||
}
|
||||
|
|
|
@ -153,7 +153,7 @@ class _VideoStreamSelectionDialogState extends State<VideoStreamSelectionDialog>
|
|||
];
|
||||
}
|
||||
|
||||
void _submit(BuildContext context) => Navigator.pop(context, {
|
||||
void _submit(BuildContext context) => Navigator.maybeOf(context)?.pop({
|
||||
StreamType.video: _currentVideo,
|
||||
StreamType.audio: _currentAudio,
|
||||
StreamType.text: _currentText,
|
||||
|
|
|
@ -41,7 +41,7 @@ class _WallpaperSettingsDialogState extends State<WallpaperSettingsDialog> {
|
|||
actions: [
|
||||
const CancelButton(),
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context, Tuple2<WallpaperTarget, bool>(_selectedTarget, _useScrollEffect)),
|
||||
onPressed: () => Navigator.maybeOf(context)?.pop(Tuple2<WallpaperTarget, bool>(_selectedTarget, _useScrollEffect)),
|
||||
child: Text(context.l10n.applyButtonLabel),
|
||||
),
|
||||
],
|
||||
|
|
|
@ -191,8 +191,7 @@ class AlbumChipSetActionDelegate extends ChipSetActionDelegate<AlbumFilter> with
|
|||
highlightInfo.trackItem(FilterGridItem(filter, null), highlightItem: filter);
|
||||
} else {
|
||||
highlightInfo.set(filter);
|
||||
await Navigator.pushAndRemoveUntil(
|
||||
context,
|
||||
await Navigator.maybeOf(context)?.pushAndRemoveUntil(
|
||||
MaterialPageRoute(
|
||||
settings: const RouteSettings(name: AlbumListPage.routeName),
|
||||
builder: (_) => const AlbumListPage(),
|
||||
|
@ -239,7 +238,7 @@ class AlbumChipSetActionDelegate extends ChipSetActionDelegate<AlbumFilter> with
|
|||
actions: [
|
||||
const CancelButton(),
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context, true),
|
||||
onPressed: () => Navigator.maybeOf(context)?.pop(true),
|
||||
child: Text(l10n.deleteButtonLabel),
|
||||
),
|
||||
],
|
||||
|
|
|
@ -40,8 +40,7 @@ class ChipActionDelegate {
|
|||
WidgetBuilder pageBuilder,
|
||||
) {
|
||||
context.read<HighlightInfo>().set(filter);
|
||||
Navigator.pushAndRemoveUntil(
|
||||
context,
|
||||
Navigator.maybeOf(context)?.pushAndRemoveUntil(
|
||||
MaterialPageRoute(
|
||||
settings: RouteSettings(name: routeName),
|
||||
builder: pageBuilder,
|
||||
|
@ -58,7 +57,7 @@ class ChipActionDelegate {
|
|||
actions: [
|
||||
const CancelButton(),
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context, true),
|
||||
onPressed: () => Navigator.maybeOf(context)?.pop(true),
|
||||
child: Text(context.l10n.hideButtonLabel),
|
||||
),
|
||||
],
|
||||
|
|
|
@ -248,8 +248,7 @@ abstract class ChipSetActionDelegate<T extends CollectionFilter> with FeedbackMi
|
|||
source: context.read<CollectionSource>(),
|
||||
fixedSelection: _selectedEntries(context, filters).where((entry) => entry.hasGps).toList(),
|
||||
);
|
||||
await Navigator.push(
|
||||
context,
|
||||
await Navigator.maybeOf(context)?.push(
|
||||
MaterialPageRoute(
|
||||
settings: const RouteSettings(name: MapPage.routeName),
|
||||
builder: (context) => MapPage(collection: mapCollection),
|
||||
|
@ -259,8 +258,7 @@ abstract class ChipSetActionDelegate<T extends CollectionFilter> with FeedbackMi
|
|||
}
|
||||
|
||||
void _goToSlideshow(BuildContext context, Set<T> filters) {
|
||||
Navigator.push(
|
||||
context,
|
||||
Navigator.maybeOf(context)?.push(
|
||||
MaterialPageRoute(
|
||||
settings: const RouteSettings(name: SlideshowPage.routeName),
|
||||
builder: (context) {
|
||||
|
@ -276,8 +274,7 @@ abstract class ChipSetActionDelegate<T extends CollectionFilter> with FeedbackMi
|
|||
}
|
||||
|
||||
void _goToStats(BuildContext context, Set<T> filters) {
|
||||
Navigator.push(
|
||||
context,
|
||||
Navigator.maybeOf(context)?.push(
|
||||
MaterialPageRoute(
|
||||
settings: const RouteSettings(name: StatsPage.routeName),
|
||||
builder: (context) {
|
||||
|
@ -291,8 +288,7 @@ abstract class ChipSetActionDelegate<T extends CollectionFilter> with FeedbackMi
|
|||
}
|
||||
|
||||
void _goToSearch(BuildContext context) {
|
||||
Navigator.push(
|
||||
context,
|
||||
Navigator.maybeOf(context)?.push(
|
||||
SearchPageRoute(
|
||||
delegate: CollectionSearchDelegate(
|
||||
searchFieldLabel: context.l10n.searchCollectionFieldHint,
|
||||
|
@ -310,7 +306,7 @@ abstract class ChipSetActionDelegate<T extends CollectionFilter> with FeedbackMi
|
|||
actions: [
|
||||
const CancelButton(),
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context, true),
|
||||
onPressed: () => Navigator.maybeOf(context)?.pop(true),
|
||||
child: Text(context.l10n.hideButtonLabel),
|
||||
),
|
||||
],
|
||||
|
|
|
@ -422,8 +422,7 @@ class _FilterGridAppBarState<T extends CollectionFilter, CSAD extends ChipSetAct
|
|||
}
|
||||
|
||||
void _goToSearch() {
|
||||
Navigator.push(
|
||||
context,
|
||||
Navigator.maybeOf(context)?.push(
|
||||
SearchPageRoute(
|
||||
delegate: CollectionSearchDelegate(
|
||||
searchFieldLabel: context.l10n.searchCollectionFieldHint,
|
||||
|
|
|
@ -61,7 +61,7 @@ class _InteractiveFilterTileState<T extends CollectionFilter> extends State<Inte
|
|||
}
|
||||
break;
|
||||
case AppMode.pickFilterInternal:
|
||||
Navigator.pop<T>(context, filter);
|
||||
Navigator.maybeOf(context)?.pop<T>(filter);
|
||||
break;
|
||||
case AppMode.pickMediaInternal:
|
||||
case AppMode.screenSaver:
|
||||
|
@ -96,8 +96,7 @@ class _InteractiveFilterTileState<T extends CollectionFilter> extends State<Inte
|
|||
}
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
if (!mounted) return;
|
||||
Navigator.push(
|
||||
context,
|
||||
Navigator.maybeOf(context)?.push(
|
||||
MaterialPageRoute(
|
||||
settings: const RouteSettings(name: CollectionPage.routeName),
|
||||
builder: (context) => CollectionPage(
|
||||
|
|
|
@ -16,6 +16,7 @@ import 'package:aves/services/global_search.dart';
|
|||
import 'package:aves/services/intent_service.dart';
|
||||
import 'package:aves/services/widget_service.dart';
|
||||
import 'package:aves/utils/android_file_utils.dart';
|
||||
import 'package:aves/utils/constants.dart';
|
||||
import 'package:aves/widgets/collection/collection_page.dart';
|
||||
import 'package:aves/widgets/common/behaviour/routes.dart';
|
||||
import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||
|
@ -95,10 +96,7 @@ class _HomePageState extends State<HomePage> {
|
|||
// do not check whether permission was granted, because some app stores
|
||||
// hide in some countries apps that force quit on permission denial
|
||||
await [
|
||||
Permission.storage,
|
||||
// for media access on Android >=13
|
||||
Permission.photos,
|
||||
Permission.videos,
|
||||
...Constants.storagePermissions,
|
||||
// to access media with unredacted metadata with scoped storage (Android >=10)
|
||||
Permission.accessMediaLocation,
|
||||
].request();
|
||||
|
@ -239,8 +237,7 @@ class _HomePageState extends State<HomePage> {
|
|||
|
||||
// `pushReplacement` is not enough in some edge cases
|
||||
// e.g. when opening the viewer in `view` mode should replace a viewer in `main` mode
|
||||
unawaited(Navigator.pushAndRemoveUntil(
|
||||
context,
|
||||
unawaited(Navigator.maybeOf(context)?.pushAndRemoveUntil(
|
||||
await _getRedirectRoute(appMode),
|
||||
(route) => false,
|
||||
));
|
||||
|
|
|
@ -456,8 +456,7 @@ class _ContentState extends State<_Content> with SingleTickerProviderStateMixin
|
|||
void _goToViewer(AvesEntry? initialEntry) {
|
||||
if (initialEntry == null) return;
|
||||
|
||||
Navigator.push(
|
||||
context,
|
||||
Navigator.maybeOf(context)?.push(
|
||||
TransparentMaterialPageRoute(
|
||||
settings: const RouteSettings(name: EntryViewerPage.routeName),
|
||||
pageBuilder: (context, a, sa) {
|
||||
|
@ -476,8 +475,7 @@ class _ContentState extends State<_Content> with SingleTickerProviderStateMixin
|
|||
final isMainMode = context.read<ValueNotifier<AppMode>>().value == AppMode.main;
|
||||
if (!isMainMode) return;
|
||||
|
||||
Navigator.pushAndRemoveUntil(
|
||||
context,
|
||||
Navigator.maybeOf(context)?.pushAndRemoveUntil(
|
||||
MaterialPageRoute(
|
||||
settings: const RouteSettings(name: CollectionPage.routeName),
|
||||
builder: (context) => CollectionPage(
|
||||
|
|
|
@ -105,10 +105,9 @@ class _AppDrawerState extends State<AppDrawer> {
|
|||
|
||||
Widget _buildHeader(BuildContext context) {
|
||||
Future<void> goTo(String routeName, WidgetBuilder pageBuilder) async {
|
||||
Navigator.pop(context);
|
||||
Navigator.maybeOf(context)?.pop();
|
||||
await Future.delayed(Durations.drawerTransitionAnimation);
|
||||
await Navigator.push(
|
||||
context,
|
||||
await Navigator.maybeOf(context)?.push(
|
||||
MaterialPageRoute(
|
||||
settings: RouteSettings(name: routeName),
|
||||
builder: pageBuilder,
|
||||
|
|
|
@ -57,9 +57,8 @@ class CollectionNavTile extends StatelessWidget {
|
|||
}
|
||||
|
||||
void _goToCollection(BuildContext context) {
|
||||
Navigator.pop(context);
|
||||
Navigator.pushAndRemoveUntil(
|
||||
context,
|
||||
Navigator.maybeOf(context)?.pop();
|
||||
Navigator.maybeOf(context)?.pushAndRemoveUntil(
|
||||
MaterialPageRoute(
|
||||
settings: const RouteSettings(name: CollectionPage.routeName),
|
||||
builder: (context) => CollectionPage(
|
||||
|
|
|
@ -47,16 +47,15 @@ class PageNavTile extends StatelessWidget {
|
|||
)
|
||||
: null,
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
Navigator.maybeOf(context)?.pop();
|
||||
final route = routeBuilder(context, routeName);
|
||||
if (topLevel) {
|
||||
Navigator.pushAndRemoveUntil(
|
||||
context,
|
||||
Navigator.maybeOf(context)?.pushAndRemoveUntil(
|
||||
route,
|
||||
(route) => false,
|
||||
);
|
||||
} else {
|
||||
Navigator.push(context, route);
|
||||
Navigator.maybeOf(context)?.push(route);
|
||||
}
|
||||
},
|
||||
selected: context.currentRouteName == routeName,
|
||||
|
|
|
@ -135,8 +135,7 @@ class _AppBottomNavBarState extends State<AppBottomNavBar> {
|
|||
void _goTo(BuildContext context, List<AvesBottomNavItem> items, int index) {
|
||||
final item = items[index];
|
||||
final routeName = item.route;
|
||||
Navigator.pushAndRemoveUntil(
|
||||
context,
|
||||
Navigator.maybeOf(context)?.pushAndRemoveUntil(
|
||||
MaterialPageRoute(
|
||||
settings: RouteSettings(name: routeName),
|
||||
builder: (context) {
|
||||
|
|
|
@ -249,16 +249,14 @@ class _TvRailState extends State<TvRail> {
|
|||
);
|
||||
|
||||
void _goTo(String routeName) {
|
||||
Navigator.pushAndRemoveUntil(
|
||||
context,
|
||||
Navigator.maybeOf(context)?.pushAndRemoveUntil(
|
||||
PageNavTile.routeBuilder(context, routeName),
|
||||
(route) => false,
|
||||
);
|
||||
}
|
||||
|
||||
void _goToCollection(BuildContext context, CollectionFilter? filter) {
|
||||
Navigator.pushAndRemoveUntil(
|
||||
context,
|
||||
Navigator.maybeOf(context)?.pushAndRemoveUntil(
|
||||
MaterialPageRoute(
|
||||
settings: const RouteSettings(name: CollectionPage.routeName),
|
||||
builder: (context) => CollectionPage(
|
||||
|
|
|
@ -320,8 +320,7 @@ class CollectionSearchDelegate extends AvesSearchDelegate {
|
|||
|
||||
void _jumpToCollectionPage(BuildContext context, Set<CollectionFilter> filters) {
|
||||
clean();
|
||||
Navigator.pushAndRemoveUntil(
|
||||
context,
|
||||
Navigator.maybeOf(context)?.pushAndRemoveUntil(
|
||||
MaterialPageRoute(
|
||||
settings: const RouteSettings(name: CollectionPage.routeName),
|
||||
builder: (context) => CollectionPage(
|
||||
|
|
|
@ -56,7 +56,7 @@ class _AppExportItemSelectionDialogState extends State<AppExportItemSelectionDia
|
|||
actions: [
|
||||
const CancelButton(),
|
||||
TextButton(
|
||||
onPressed: _selectedItems.isEmpty ? null : () => Navigator.pop(context, _selectedItems),
|
||||
onPressed: _selectedItems.isEmpty ? null : () => Navigator.maybeOf(context)?.pop(_selectedItems),
|
||||
child: Text(context.l10n.applyButtonLabel),
|
||||
),
|
||||
],
|
||||
|
|
|
@ -24,8 +24,7 @@ class SettingsSubPageTile extends StatelessWidget {
|
|||
return ListTile(
|
||||
title: Text(title),
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
Navigator.maybeOf(context)?.push(
|
||||
MaterialPageRoute(
|
||||
settings: RouteSettings(name: routeName),
|
||||
builder: builder,
|
||||
|
|
|
@ -125,7 +125,7 @@ class SettingsTileDisplayForceTvLayout extends SettingsTile {
|
|||
actions: [
|
||||
const CancelButton(),
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context, true),
|
||||
onPressed: () => Navigator.maybeOf(context)?.pop(true),
|
||||
child: Text(l10n.applyButtonLabel),
|
||||
),
|
||||
],
|
||||
|
|
|
@ -60,7 +60,7 @@ class _LocaleSelectionPageState extends State<LocaleSelectionPage> {
|
|||
key: Key(value.toString()),
|
||||
value: value,
|
||||
groupValue: _selectedValue,
|
||||
onChanged: (v) => Navigator.pop(context, v),
|
||||
onChanged: (v) => Navigator.maybeOf(context)?.pop(v),
|
||||
reselectable: true,
|
||||
title: Text(
|
||||
title,
|
||||
|
|
|
@ -25,8 +25,7 @@ class LocaleTile extends StatelessWidget {
|
|||
},
|
||||
),
|
||||
onTap: () async {
|
||||
final value = await Navigator.push<Locale>(
|
||||
context,
|
||||
final value = await Navigator.maybeOf(context)?.push<Locale>(
|
||||
MaterialPageRoute(
|
||||
settings: const RouteSettings(name: LocaleSelectionPage.routeName),
|
||||
builder: (context) => const LocaleSelectionPage(),
|
||||
|
|
|
@ -129,7 +129,7 @@ class _FilePickerPageState extends State<FilePickerPage> {
|
|||
padding: const EdgeInsets.all(8),
|
||||
child: AvesOutlinedButton(
|
||||
label: l10n.filePickerUseThisFolder,
|
||||
onPressed: () => Navigator.pop(context, currentDirectoryPath),
|
||||
onPressed: () => Navigator.maybeOf(context)?.pop(currentDirectoryPath),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
@ -165,7 +165,7 @@ class _FilePickerPageState extends State<FilePickerPage> {
|
|||
leading: Icon(icon),
|
||||
title: Text(v.getDescription(context)),
|
||||
onTap: () async {
|
||||
Navigator.pop(context);
|
||||
Navigator.maybeOf(context)?.pop();
|
||||
await Future.delayed(Durations.drawerTransitionAnimation);
|
||||
_goTo(v.path);
|
||||
setState(() {});
|
||||
|
|
|
@ -144,8 +144,7 @@ class _HiddenPaths extends StatelessWidget {
|
|||
icon: const Icon(AIcons.add),
|
||||
label: context.l10n.addPathTooltip,
|
||||
onPressed: () async {
|
||||
final path = await Navigator.push(
|
||||
context,
|
||||
final path = await Navigator.maybeOf(context)?.push(
|
||||
MaterialPageRoute<String>(
|
||||
settings: const RouteSettings(name: FilePickerPage.routeName),
|
||||
builder: (context) => const FilePickerPage(),
|
||||
|
|
|
@ -284,8 +284,7 @@ class _SettingsPageState extends State<SettingsPage> with FeedbackMixin {
|
|||
}
|
||||
|
||||
void _goToSearch(BuildContext context) {
|
||||
Navigator.push(
|
||||
context,
|
||||
Navigator.maybeOf(context)?.push(
|
||||
SearchPageRoute(
|
||||
delegate: SettingsSearchDelegate(
|
||||
searchFieldLabel: context.l10n.settingsSearchFieldLabel,
|
||||
|
|
|
@ -253,8 +253,7 @@ class _StatsPageState extends State<StatsPage> {
|
|||
final totalEntryCount = entries.length;
|
||||
final hasMore = maxRowCount != null && entryCountMap.length > maxRowCount;
|
||||
final onHeaderPressed = hasMore
|
||||
? () => Navigator.push(
|
||||
context,
|
||||
? () => Navigator.maybeOf(context)?.push(
|
||||
MaterialPageRoute(
|
||||
settings: const RouteSettings(name: StatsTopPage.routeName),
|
||||
builder: (context) => StatsTopPage(
|
||||
|
@ -334,12 +333,11 @@ class _StatsPageState extends State<StatsPage> {
|
|||
// even when the target is a child of an `AnimatedList`.
|
||||
// Do not use `WidgetsBinding.instance.addPostFrameCallback`,
|
||||
// as it may not trigger if there is no subsequent build.
|
||||
Future.delayed(const Duration(milliseconds: 100), () => Navigator.popUntil(context, (route) => route.settings.name == CollectionPage.routeName));
|
||||
Future.delayed(const Duration(milliseconds: 100), () => Navigator.maybeOf(context)?.popUntil((route) => route.settings.name == CollectionPage.routeName));
|
||||
}
|
||||
|
||||
void _jumpToCollectionPage(BuildContext context, CollectionFilter filter) {
|
||||
Navigator.pushAndRemoveUntil(
|
||||
context,
|
||||
Navigator.maybeOf(context)?.pushAndRemoveUntil(
|
||||
MaterialPageRoute(
|
||||
settings: const RouteSettings(name: CollectionPage.routeName),
|
||||
builder: (context) => CollectionPage(
|
||||
|
|
|
@ -460,8 +460,7 @@ class EntryActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAwareMix
|
|||
// local context may be deactivated when action is triggered after navigation
|
||||
final context = AvesApp.navigatorKey.currentContext;
|
||||
if (context != null) {
|
||||
Navigator.pushAndRemoveUntil(
|
||||
context,
|
||||
Navigator.maybeOf(context)?.pushAndRemoveUntil(
|
||||
MaterialPageRoute(
|
||||
settings: const RouteSettings(name: CollectionPage.routeName),
|
||||
builder: (context) => CollectionPage(
|
||||
|
@ -521,8 +520,7 @@ class EntryActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAwareMix
|
|||
bool _isMainMode(BuildContext context) => context.read<ValueNotifier<AppMode>>().value == AppMode.main;
|
||||
|
||||
void _goToSourceViewer(BuildContext context, AvesEntry targetEntry) {
|
||||
Navigator.push(
|
||||
context,
|
||||
Navigator.maybeOf(context)?.push(
|
||||
MaterialPageRoute(
|
||||
settings: const RouteSettings(name: SourceViewerPage.routeName),
|
||||
builder: (context) => SourceViewerPage(
|
||||
|
@ -540,8 +538,7 @@ class EntryActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAwareMix
|
|||
}
|
||||
|
||||
void _goToDebug(BuildContext context, AvesEntry targetEntry) {
|
||||
Navigator.push(
|
||||
context,
|
||||
Navigator.maybeOf(context)?.push(
|
||||
MaterialPageRoute(
|
||||
settings: const RouteSettings(name: ViewerDebugPage.routeName),
|
||||
builder: (context) => ViewerDebugPage(entry: targetEntry),
|
||||
|
|
|
@ -234,7 +234,7 @@ class EntryInfoActionDelegate with FeedbackMixin, PermissionAwareMixin, EntryEdi
|
|||
actions: [
|
||||
const CancelButton(),
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context, true),
|
||||
onPressed: () => Navigator.maybeOf(context)?.pop(true),
|
||||
child: Text(context.l10n.applyButtonLabel),
|
||||
),
|
||||
],
|
||||
|
@ -262,8 +262,7 @@ class EntryInfoActionDelegate with FeedbackMixin, PermissionAwareMixin, EntryEdi
|
|||
listenToSource: true,
|
||||
fixedSelection: baseCollection.sortedEntries.where((entry) => entry.hasGps).where((entry) => entry != targetEntry).toList(),
|
||||
);
|
||||
await Navigator.push(
|
||||
context,
|
||||
await Navigator.maybeOf(context)?.push(
|
||||
MaterialPageRoute(
|
||||
settings: const RouteSettings(name: MapPage.routeName),
|
||||
builder: (context) => MapPage(
|
||||
|
@ -276,8 +275,7 @@ class EntryInfoActionDelegate with FeedbackMixin, PermissionAwareMixin, EntryEdi
|
|||
}
|
||||
|
||||
void _goToDebug(BuildContext context, AvesEntry targetEntry) {
|
||||
Navigator.push(
|
||||
context,
|
||||
Navigator.maybeOf(context)?.push(
|
||||
MaterialPageRoute(
|
||||
settings: const RouteSettings(name: ViewerDebugPage.routeName),
|
||||
builder: (context) => ViewerDebugPage(entry: targetEntry),
|
||||
|
|
|
@ -72,8 +72,7 @@ class EmbeddedDataOpener extends StatelessWidget with FeedbackMixin {
|
|||
}
|
||||
|
||||
void _openTempEntry(BuildContext context, AvesEntry tempEntry) {
|
||||
Navigator.push(
|
||||
context,
|
||||
Navigator.maybeOf(context)?.push(
|
||||
TransparentMaterialPageRoute(
|
||||
settings: const RouteSettings(name: EntryViewerPage.routeName),
|
||||
pageBuilder: (context, a, sa) => EntryViewerPage(
|
||||
|
|
|
@ -233,7 +233,7 @@ class _ViewerVerticalPageViewState extends State<ViewerVerticalPageView> {
|
|||
actions: {
|
||||
_ShowPreviousIntent: CallbackAction<Intent>(onInvoke: (intent) => _goToHorizontalPage(-1, animate: false)),
|
||||
_ShowNextIntent: CallbackAction<Intent>(onInvoke: (intent) => _goToHorizontalPage(1, animate: false)),
|
||||
_LeaveIntent: CallbackAction<Intent>(onInvoke: (intent) => Navigator.pop(context)),
|
||||
_LeaveIntent: CallbackAction<Intent>(onInvoke: (intent) => Navigator.maybeOf(context)?.pop()),
|
||||
_ShowInfoIntent: CallbackAction<Intent>(onInvoke: (intent) => ShowInfoPageNotification().dispatch(context)),
|
||||
TvShowLessInfoIntent: CallbackAction<Intent>(onInvoke: (intent) => TvShowLessInfoNotification().dispatch(context)),
|
||||
_TvShowMoreInfoIntent: CallbackAction<Intent>(onInvoke: (intent) => TvShowMoreInfoNotification().dispatch(context)),
|
||||
|
@ -320,7 +320,7 @@ class _ViewerVerticalPageViewState extends State<ViewerVerticalPageView> {
|
|||
await _entry.catalog(background: false, force: false, persist: true);
|
||||
await _entry.locate(background: false, force: false, geocoderLocale: settings.appliedLocale);
|
||||
} else {
|
||||
Navigator.pop(context);
|
||||
Navigator.maybeOf(context)?.pop();
|
||||
}
|
||||
|
||||
// needed to refresh when entry changes but the page does not (e.g. on page deletion)
|
||||
|
|
|
@ -503,8 +503,7 @@ class _EntryViewerStackState extends State<EntryViewerStack> with EntryViewContr
|
|||
if (baseCollection == null) return;
|
||||
|
||||
_onLeave();
|
||||
Navigator.pushAndRemoveUntil(
|
||||
context,
|
||||
Navigator.maybeOf(context)?.pushAndRemoveUntil(
|
||||
MaterialPageRoute(
|
||||
settings: const RouteSettings(name: CollectionPage.routeName),
|
||||
builder: (context) => CollectionPage(
|
||||
|
@ -602,7 +601,7 @@ class _EntryViewerStackState extends State<EntryViewerStack> with EntryViewContr
|
|||
}
|
||||
|
||||
if (Navigator.canPop(context)) {
|
||||
Navigator.pop(context);
|
||||
Navigator.maybeOf(context)?.pop();
|
||||
} else {
|
||||
_leaveViewer();
|
||||
}
|
||||
|
@ -639,7 +638,7 @@ class _EntryViewerStackState extends State<EntryViewerStack> with EntryViewContr
|
|||
if (Navigator.canPop(context)) {
|
||||
void pop() {
|
||||
_onLeave();
|
||||
Navigator.pop(context);
|
||||
Navigator.maybeOf(context)?.pop();
|
||||
}
|
||||
|
||||
// closing hero, with viewer as source
|
||||
|
|
|
@ -30,7 +30,7 @@ class InfoSearchDelegate extends SearchDelegate {
|
|||
icon: AnimatedIcons.menu_arrow,
|
||||
progress: transitionAnimation,
|
||||
),
|
||||
onPressed: () => Navigator.pop(context),
|
||||
onPressed: () => Navigator.maybeOf(context)?.pop(),
|
||||
tooltip: MaterialLocalizations.of(context).backButtonTooltip,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -137,8 +137,7 @@ class _LocationSectionState extends State<LocationSection> {
|
|||
listenToSource: true,
|
||||
fixedSelection: baseCollection.sortedEntries.where((entry) => entry.hasGps).toList(),
|
||||
);
|
||||
await Navigator.push(
|
||||
context,
|
||||
await Navigator.maybeOf(context)?.push(
|
||||
MaterialPageRoute(
|
||||
settings: const RouteSettings(name: MapPage.routeName),
|
||||
builder: (context) => MapPage(
|
||||
|
|
|
@ -93,8 +93,7 @@ class MetadataDirTile extends StatelessWidget {
|
|||
'Metadata': InfoRowGroup.linkSpanBuilder(
|
||||
linkText: (context) => context.l10n.viewerInfoViewXmlLinkText,
|
||||
onTap: (context) {
|
||||
Navigator.push(
|
||||
context,
|
||||
Navigator.maybeOf(context)?.push(
|
||||
MaterialPageRoute(
|
||||
settings: const RouteSettings(name: SourceViewerPage.routeName),
|
||||
builder: (context) => SourceViewerPage(
|
||||
|
|
|
@ -27,8 +27,7 @@ class PanoramaOverlay extends StatelessWidget {
|
|||
onPressed: () async {
|
||||
final info = await metadataFetchService.getPanoramaInfo(entry);
|
||||
if (info != null) {
|
||||
unawaited(Navigator.push(
|
||||
context,
|
||||
unawaited(Navigator.maybeOf(context)?.push(
|
||||
MaterialPageRoute(
|
||||
settings: const RouteSettings(name: PanoramaPage.routeName),
|
||||
builder: (context) => PanoramaPage(
|
||||
|
|
|
@ -123,8 +123,7 @@ class _SlideshowPageState extends State<SlideshowPage> {
|
|||
final album = entry.directory;
|
||||
final uri = entry.uri;
|
||||
|
||||
Navigator.pushAndRemoveUntil(
|
||||
context,
|
||||
Navigator.maybeOf(context)?.pushAndRemoveUntil(
|
||||
MaterialPageRoute(
|
||||
settings: const RouteSettings(name: CollectionPage.routeName),
|
||||
builder: (context) => CollectionPage(
|
||||
|
|
|
@ -70,11 +70,11 @@ abstract class AvesVideoController {
|
|||
content: Text(context.l10n.videoResumeDialogMessage(formatFriendlyDuration(Duration(milliseconds: resumeTime)))),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context),
|
||||
onPressed: () => Navigator.maybeOf(context)?.pop(),
|
||||
child: Text(context.l10n.videoStartOverButtonLabel),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context, true),
|
||||
onPressed: () => Navigator.maybeOf(context)?.pop(true),
|
||||
child: Text(context.l10n.videoResumeButtonLabel),
|
||||
),
|
||||
],
|
||||
|
|
|
@ -120,8 +120,7 @@ class VideoActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAwareMix
|
|||
if (context != null) {
|
||||
final source = _collection.source;
|
||||
final newUri = newFields['uri'] as String?;
|
||||
Navigator.pushAndRemoveUntil(
|
||||
context,
|
||||
Navigator.maybeOf(context)?.pushAndRemoveUntil(
|
||||
MaterialPageRoute(
|
||||
settings: const RouteSettings(name: CollectionPage.routeName),
|
||||
builder: (context) => CollectionPage(
|
||||
|
@ -181,8 +180,7 @@ class VideoActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAwareMix
|
|||
resumePosition = controller.currentPosition;
|
||||
await controller.pause();
|
||||
}
|
||||
await Navigator.push(
|
||||
context,
|
||||
await Navigator.maybeOf(context)?.push(
|
||||
MaterialPageRoute(
|
||||
settings: const RouteSettings(name: VideoSettingsPage.routeName),
|
||||
builder: (context) => const VideoSettingsPage(),
|
||||
|
|
|
@ -222,8 +222,7 @@ class _WelcomePageState extends State<WelcomePage> {
|
|||
}
|
||||
|
||||
void _goToPolicyPage() {
|
||||
Navigator.push(
|
||||
context,
|
||||
Navigator.maybeOf(context)?.push(
|
||||
MaterialPageRoute(
|
||||
settings: const RouteSettings(name: PolicyPage.routeName),
|
||||
builder: (context) => const PolicyPage(),
|
||||
|
|
|
@ -84,14 +84,14 @@ packages:
|
|||
name: firebase_crashlytics
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.0.10"
|
||||
version: "3.0.11"
|
||||
firebase_crashlytics_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: firebase_crashlytics_platform_interface
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.3.10"
|
||||
version: "3.3.11"
|
||||
flutter:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
|
|
|
@ -35,7 +35,7 @@ packages:
|
|||
name: args
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.3.1"
|
||||
version: "2.3.2"
|
||||
async:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -307,14 +307,14 @@ packages:
|
|||
name: firebase_crashlytics
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.0.10"
|
||||
version: "3.0.11"
|
||||
firebase_crashlytics_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: firebase_crashlytics_platform_interface
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.3.10"
|
||||
version: "3.3.11"
|
||||
flex_color_picker:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
Loading…
Reference in a new issue