From 751f2fcacc1a170b2908cc014e13e24d5beeecf6 Mon Sep 17 00:00:00 2001 From: Thibault Deckers Date: Fri, 4 Sep 2020 22:01:11 +0900 Subject: [PATCH] always keep home as the first route in navigator stack, apply double back exit policy to filter grid pages --- lib/model/settings/settings.dart | 8 ++ lib/widgets/common/double_back_pop.dart | 2 +- lib/widgets/drawer/collection_tile.dart | 3 +- lib/widgets/drawer/tile.dart | 15 ++- .../filter_grids/filter_grid_page.dart | 117 +++++++++--------- lib/widgets/fullscreen/fullscreen_body.dart | 3 +- lib/widgets/stats/filter_table.dart | 3 +- lib/widgets/stats/stats.dart | 3 +- lib/widgets/welcome_page.dart | 3 +- 9 files changed, 87 insertions(+), 70 deletions(-) diff --git a/lib/model/settings/settings.dart b/lib/model/settings/settings.dart index c0eff5b5c..03ee79fbf 100644 --- a/lib/model/settings/settings.dart +++ b/lib/model/settings/settings.dart @@ -104,6 +104,14 @@ class Settings extends ChangeNotifier { set svgBackground(int newValue) => setAndNotify(svgBackgroundKey, newValue); + // utils + + // `RoutePredicate` + RoutePredicate navRemoveRoutePredicate(String pushedRouteName) { + final home = homePage.routeName; + return (route) => pushedRouteName != home && route.settings?.name == home; + } + // convenience methods // ignore: avoid_positional_boolean_parameters diff --git a/lib/widgets/common/double_back_pop.dart b/lib/widgets/common/double_back_pop.dart index b24b75834..dda008461 100644 --- a/lib/widgets/common/double_back_pop.dart +++ b/lib/widgets/common/double_back_pop.dart @@ -32,7 +32,7 @@ class _DoubleBackPopScopeState extends State with FeedbackMi Widget build(BuildContext context) { return WillPopScope( onWillPop: () { - if (!Navigator.of(context).canPop() && settings.mustBackTwiceToExit && !_backOnce) { + if (!Navigator.canPop(context) && settings.mustBackTwiceToExit && !_backOnce) { _backOnce = true; _stopBackTimer(); _backTimer = Timer(Durations.doubleBackTimerDelay, () => _backOnce = false); diff --git a/lib/widgets/drawer/collection_tile.dart b/lib/widgets/drawer/collection_tile.dart index 89f7c9429..2acada773 100644 --- a/lib/widgets/drawer/collection_tile.dart +++ b/lib/widgets/drawer/collection_tile.dart @@ -39,6 +39,7 @@ class CollectionNavTile extends StatelessWidget { } void _goToCollection(BuildContext context) { + Navigator.pop(context); Navigator.pushAndRemoveUntil( context, MaterialPageRoute( @@ -50,7 +51,7 @@ class CollectionNavTile extends StatelessWidget { sortFactor: settings.collectionSortFactor, )), ), - (route) => false, + settings.navRemoveRoutePredicate(CollectionPage.routeName), ); } } diff --git a/lib/widgets/drawer/tile.dart b/lib/widgets/drawer/tile.dart index 4b51362bd..6ac50d08b 100644 --- a/lib/widgets/drawer/tile.dart +++ b/lib/widgets/drawer/tile.dart @@ -1,5 +1,6 @@ import 'dart:ui'; +import 'package:aves/model/settings/settings.dart'; import 'package:aves/utils/flutter_utils.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; @@ -41,12 +42,14 @@ class NavTile extends StatelessWidget { onTap: () { Navigator.pop(context); if (routeName != context.currentRouteName) { - Navigator.push( - context, - MaterialPageRoute( - settings: RouteSettings(name: routeName), - builder: pageBuilder, - )); + Navigator.pushAndRemoveUntil( + context, + MaterialPageRoute( + settings: RouteSettings(name: routeName), + builder: pageBuilder, + ), + settings.navRemoveRoutePredicate(routeName), + ); } }, selected: context.currentRouteName == routeName, diff --git a/lib/widgets/filter_grids/filter_grid_page.dart b/lib/widgets/filter_grids/filter_grid_page.dart index a64e4d7fb..4c198d059 100644 --- a/lib/widgets/filter_grids/filter_grid_page.dart +++ b/lib/widgets/filter_grids/filter_grid_page.dart @@ -10,6 +10,7 @@ import 'package:aves/widgets/album/collection_page.dart'; import 'package:aves/widgets/common/app_bar_subtitle.dart'; import 'package:aves/widgets/common/aves_filter_chip.dart'; import 'package:aves/widgets/common/data_providers/media_query_data_provider.dart'; +import 'package:aves/widgets/common/double_back_pop.dart'; import 'package:aves/widgets/drawer/app_drawer.dart'; import 'package:aves/widgets/filter_grids/decorated_filter_chip.dart'; import 'package:flutter/material.dart'; @@ -64,7 +65,7 @@ class FilterNavigationPage extends StatelessWidget { sortFactor: settings.collectionSortFactor, )), ), - (route) => false, + settings.navRemoveRoutePredicate(CollectionPage.routeName), ), ); } @@ -96,66 +97,68 @@ class FilterGridPage extends StatelessWidget { Widget build(BuildContext context) { return MediaQueryDataProvider( child: Scaffold( - body: SafeArea( - child: Selector( - selector: (c, mq) => mq.size.width, - builder: (c, mqWidth, child) { - final columnCount = (mqWidth / maxCrossAxisExtent).ceil(); - return AnimationLimiter( - child: CustomScrollView( - slivers: [ - appBar, - filterKeys.isEmpty - ? SliverFillRemaining( - child: emptyBuilder(), - hasScrollBody: false, - ) - : SliverPadding( - padding: EdgeInsets.all(AvesFilterChip.outlineWidth), - sliver: SliverGrid( - delegate: SliverChildBuilderDelegate( - (context, i) { - final key = filterKeys[i]; - final child = DecoratedFilterChip( - source: source, - filter: filterBuilder(key), - entry: filterEntries[key], - onPressed: onPressed, - ); - return AnimationConfiguration.staggeredGrid( - position: i, - columnCount: columnCount, - duration: Durations.staggeredAnimation, - delay: Durations.staggeredAnimationDelay, - child: SlideAnimation( - verticalOffset: 50.0, - child: FadeInAnimation( - child: child, + body: DoubleBackPopScope( + child: SafeArea( + child: Selector( + selector: (c, mq) => mq.size.width, + builder: (c, mqWidth, child) { + final columnCount = (mqWidth / maxCrossAxisExtent).ceil(); + return AnimationLimiter( + child: CustomScrollView( + slivers: [ + appBar, + filterKeys.isEmpty + ? SliverFillRemaining( + child: emptyBuilder(), + hasScrollBody: false, + ) + : SliverPadding( + padding: EdgeInsets.all(AvesFilterChip.outlineWidth), + sliver: SliverGrid( + delegate: SliverChildBuilderDelegate( + (context, i) { + final key = filterKeys[i]; + final child = DecoratedFilterChip( + source: source, + filter: filterBuilder(key), + entry: filterEntries[key], + onPressed: onPressed, + ); + return AnimationConfiguration.staggeredGrid( + position: i, + columnCount: columnCount, + duration: Durations.staggeredAnimation, + delay: Durations.staggeredAnimationDelay, + child: SlideAnimation( + verticalOffset: 50.0, + child: FadeInAnimation( + child: child, + ), ), - ), - ); - }, - childCount: filterKeys.length, - ), - gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent( - maxCrossAxisExtent: maxCrossAxisExtent, - mainAxisSpacing: 8, - crossAxisSpacing: 8, + ); + }, + childCount: filterKeys.length, + ), + gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent( + maxCrossAxisExtent: maxCrossAxisExtent, + mainAxisSpacing: 8, + crossAxisSpacing: 8, + ), ), ), - ), - SliverToBoxAdapter( - child: Selector( - selector: (context, mq) => mq.viewInsets.bottom, - builder: (context, mqViewInsetsBottom, child) { - return SizedBox(height: mqViewInsetsBottom); - }, + SliverToBoxAdapter( + child: Selector( + selector: (context, mq) => mq.viewInsets.bottom, + builder: (context, mqViewInsetsBottom, child) { + return SizedBox(height: mqViewInsetsBottom); + }, + ), ), - ), - ], - ), - ); - }, + ], + ), + ); + }, + ), ), ), drawer: AppDrawer( diff --git a/lib/widgets/fullscreen/fullscreen_body.dart b/lib/widgets/fullscreen/fullscreen_body.dart index 0e5113c0a..81e29e9d0 100644 --- a/lib/widgets/fullscreen/fullscreen_body.dart +++ b/lib/widgets/fullscreen/fullscreen_body.dart @@ -3,6 +3,7 @@ import 'dart:math'; import 'package:aves/model/filters/filters.dart'; import 'package:aves/model/image_entry.dart'; +import 'package:aves/model/settings/settings.dart'; import 'package:aves/model/source/collection_lens.dart'; import 'package:aves/utils/change_notifier.dart'; import 'package:aves/utils/durations.dart'; @@ -278,7 +279,7 @@ class FullscreenBodyState extends State with SingleTickerProvide settings: RouteSettings(name: CollectionPage.routeName), builder: (context) => CollectionPage(collection.derive(filter)), ), - (route) => false, + settings.navRemoveRoutePredicate(CollectionPage.routeName), ); } diff --git a/lib/widgets/stats/filter_table.dart b/lib/widgets/stats/filter_table.dart index 6db934778..ec3fb536c 100644 --- a/lib/widgets/stats/filter_table.dart +++ b/lib/widgets/stats/filter_table.dart @@ -1,4 +1,5 @@ import 'package:aves/model/filters/filters.dart'; +import 'package:aves/model/settings/settings.dart'; import 'package:aves/model/source/collection_lens.dart'; import 'package:aves/utils/color_utils.dart'; import 'package:aves/widgets/album/collection_page.dart'; @@ -93,7 +94,7 @@ class FilterTable extends StatelessWidget { settings: RouteSettings(name: CollectionPage.routeName), builder: (context) => CollectionPage(collection.derive(filter)), ), - (route) => false, + settings.navRemoveRoutePredicate(CollectionPage.routeName), ); } } diff --git a/lib/widgets/stats/stats.dart b/lib/widgets/stats/stats.dart index d4db446c5..2370e7261 100644 --- a/lib/widgets/stats/stats.dart +++ b/lib/widgets/stats/stats.dart @@ -5,6 +5,7 @@ import 'package:aves/model/filters/location.dart'; import 'package:aves/model/filters/mime.dart'; import 'package:aves/model/filters/tag.dart'; import 'package:aves/model/image_entry.dart'; +import 'package:aves/model/settings/settings.dart'; import 'package:aves/model/source/collection_lens.dart'; import 'package:aves/utils/color_utils.dart'; import 'package:aves/utils/constants.dart'; @@ -241,7 +242,7 @@ class StatsPage extends StatelessWidget { settings: RouteSettings(name: CollectionPage.routeName), builder: (context) => CollectionPage(collection.derive(filter)), ), - (route) => false, + settings.navRemoveRoutePredicate(CollectionPage.routeName), ); } } diff --git a/lib/widgets/welcome_page.dart b/lib/widgets/welcome_page.dart index e719d7909..b1e1cc4e6 100644 --- a/lib/widgets/welcome_page.dart +++ b/lib/widgets/welcome_page.dart @@ -104,13 +104,12 @@ class _WelcomePageState extends State { onPressed: _hasAcceptedTerms ? () { settings.hasAcceptedTerms = true; - Navigator.pushAndRemoveUntil( + Navigator.pushReplacement( context, MaterialPageRoute( settings: RouteSettings(name: HomePage.routeName), builder: (context) => HomePage(), ), - (route) => false, ); } : null,