always keep home as the first route in navigator stack, apply double back exit policy to filter grid pages

This commit is contained in:
Thibault Deckers 2020-09-04 22:01:11 +09:00
parent da26ccdc87
commit 751f2fcacc
9 changed files with 87 additions and 70 deletions

View file

@ -104,6 +104,14 @@ class Settings extends ChangeNotifier {
set svgBackground(int newValue) => setAndNotify(svgBackgroundKey, newValue); 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 // convenience methods
// ignore: avoid_positional_boolean_parameters // ignore: avoid_positional_boolean_parameters

View file

@ -32,7 +32,7 @@ class _DoubleBackPopScopeState extends State<DoubleBackPopScope> with FeedbackMi
Widget build(BuildContext context) { Widget build(BuildContext context) {
return WillPopScope( return WillPopScope(
onWillPop: () { onWillPop: () {
if (!Navigator.of(context).canPop() && settings.mustBackTwiceToExit && !_backOnce) { if (!Navigator.canPop(context) && settings.mustBackTwiceToExit && !_backOnce) {
_backOnce = true; _backOnce = true;
_stopBackTimer(); _stopBackTimer();
_backTimer = Timer(Durations.doubleBackTimerDelay, () => _backOnce = false); _backTimer = Timer(Durations.doubleBackTimerDelay, () => _backOnce = false);

View file

@ -39,6 +39,7 @@ class CollectionNavTile extends StatelessWidget {
} }
void _goToCollection(BuildContext context) { void _goToCollection(BuildContext context) {
Navigator.pop(context);
Navigator.pushAndRemoveUntil( Navigator.pushAndRemoveUntil(
context, context,
MaterialPageRoute( MaterialPageRoute(
@ -50,7 +51,7 @@ class CollectionNavTile extends StatelessWidget {
sortFactor: settings.collectionSortFactor, sortFactor: settings.collectionSortFactor,
)), )),
), ),
(route) => false, settings.navRemoveRoutePredicate(CollectionPage.routeName),
); );
} }
} }

View file

@ -1,5 +1,6 @@
import 'dart:ui'; import 'dart:ui';
import 'package:aves/model/settings/settings.dart';
import 'package:aves/utils/flutter_utils.dart'; import 'package:aves/utils/flutter_utils.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@ -41,12 +42,14 @@ class NavTile extends StatelessWidget {
onTap: () { onTap: () {
Navigator.pop(context); Navigator.pop(context);
if (routeName != context.currentRouteName) { if (routeName != context.currentRouteName) {
Navigator.push( Navigator.pushAndRemoveUntil(
context, context,
MaterialPageRoute( MaterialPageRoute(
settings: RouteSettings(name: routeName), settings: RouteSettings(name: routeName),
builder: pageBuilder, builder: pageBuilder,
)); ),
settings.navRemoveRoutePredicate(routeName),
);
} }
}, },
selected: context.currentRouteName == routeName, selected: context.currentRouteName == routeName,

View file

@ -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/app_bar_subtitle.dart';
import 'package:aves/widgets/common/aves_filter_chip.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/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/drawer/app_drawer.dart';
import 'package:aves/widgets/filter_grids/decorated_filter_chip.dart'; import 'package:aves/widgets/filter_grids/decorated_filter_chip.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@ -64,7 +65,7 @@ class FilterNavigationPage extends StatelessWidget {
sortFactor: settings.collectionSortFactor, sortFactor: settings.collectionSortFactor,
)), )),
), ),
(route) => false, settings.navRemoveRoutePredicate(CollectionPage.routeName),
), ),
); );
} }
@ -96,66 +97,68 @@ class FilterGridPage extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return MediaQueryDataProvider( return MediaQueryDataProvider(
child: Scaffold( child: Scaffold(
body: SafeArea( body: DoubleBackPopScope(
child: Selector<MediaQueryData, double>( child: SafeArea(
selector: (c, mq) => mq.size.width, child: Selector<MediaQueryData, double>(
builder: (c, mqWidth, child) { selector: (c, mq) => mq.size.width,
final columnCount = (mqWidth / maxCrossAxisExtent).ceil(); builder: (c, mqWidth, child) {
return AnimationLimiter( final columnCount = (mqWidth / maxCrossAxisExtent).ceil();
child: CustomScrollView( return AnimationLimiter(
slivers: [ child: CustomScrollView(
appBar, slivers: [
filterKeys.isEmpty appBar,
? SliverFillRemaining( filterKeys.isEmpty
child: emptyBuilder(), ? SliverFillRemaining(
hasScrollBody: false, child: emptyBuilder(),
) hasScrollBody: false,
: SliverPadding( )
padding: EdgeInsets.all(AvesFilterChip.outlineWidth), : SliverPadding(
sliver: SliverGrid( padding: EdgeInsets.all(AvesFilterChip.outlineWidth),
delegate: SliverChildBuilderDelegate( sliver: SliverGrid(
(context, i) { delegate: SliverChildBuilderDelegate(
final key = filterKeys[i]; (context, i) {
final child = DecoratedFilterChip( final key = filterKeys[i];
source: source, final child = DecoratedFilterChip(
filter: filterBuilder(key), source: source,
entry: filterEntries[key], filter: filterBuilder(key),
onPressed: onPressed, entry: filterEntries[key],
); onPressed: onPressed,
return AnimationConfiguration.staggeredGrid( );
position: i, return AnimationConfiguration.staggeredGrid(
columnCount: columnCount, position: i,
duration: Durations.staggeredAnimation, columnCount: columnCount,
delay: Durations.staggeredAnimationDelay, duration: Durations.staggeredAnimation,
child: SlideAnimation( delay: Durations.staggeredAnimationDelay,
verticalOffset: 50.0, child: SlideAnimation(
child: FadeInAnimation( verticalOffset: 50.0,
child: child, child: FadeInAnimation(
child: child,
),
), ),
), );
); },
}, childCount: filterKeys.length,
childCount: filterKeys.length, ),
), gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent( maxCrossAxisExtent: maxCrossAxisExtent,
maxCrossAxisExtent: maxCrossAxisExtent, mainAxisSpacing: 8,
mainAxisSpacing: 8, crossAxisSpacing: 8,
crossAxisSpacing: 8, ),
), ),
), ),
), SliverToBoxAdapter(
SliverToBoxAdapter( child: Selector<MediaQueryData, double>(
child: Selector<MediaQueryData, double>( selector: (context, mq) => mq.viewInsets.bottom,
selector: (context, mq) => mq.viewInsets.bottom, builder: (context, mqViewInsetsBottom, child) {
builder: (context, mqViewInsetsBottom, child) { return SizedBox(height: mqViewInsetsBottom);
return SizedBox(height: mqViewInsetsBottom); },
}, ),
), ),
), ],
], ),
), );
); },
}, ),
), ),
), ),
drawer: AppDrawer( drawer: AppDrawer(

View file

@ -3,6 +3,7 @@ import 'dart:math';
import 'package:aves/model/filters/filters.dart'; import 'package:aves/model/filters/filters.dart';
import 'package:aves/model/image_entry.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/model/source/collection_lens.dart';
import 'package:aves/utils/change_notifier.dart'; import 'package:aves/utils/change_notifier.dart';
import 'package:aves/utils/durations.dart'; import 'package:aves/utils/durations.dart';
@ -278,7 +279,7 @@ class FullscreenBodyState extends State<FullscreenBody> with SingleTickerProvide
settings: RouteSettings(name: CollectionPage.routeName), settings: RouteSettings(name: CollectionPage.routeName),
builder: (context) => CollectionPage(collection.derive(filter)), builder: (context) => CollectionPage(collection.derive(filter)),
), ),
(route) => false, settings.navRemoveRoutePredicate(CollectionPage.routeName),
); );
} }

View file

@ -1,4 +1,5 @@
import 'package:aves/model/filters/filters.dart'; 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/model/source/collection_lens.dart';
import 'package:aves/utils/color_utils.dart'; import 'package:aves/utils/color_utils.dart';
import 'package:aves/widgets/album/collection_page.dart'; import 'package:aves/widgets/album/collection_page.dart';
@ -93,7 +94,7 @@ class FilterTable extends StatelessWidget {
settings: RouteSettings(name: CollectionPage.routeName), settings: RouteSettings(name: CollectionPage.routeName),
builder: (context) => CollectionPage(collection.derive(filter)), builder: (context) => CollectionPage(collection.derive(filter)),
), ),
(route) => false, settings.navRemoveRoutePredicate(CollectionPage.routeName),
); );
} }
} }

View file

@ -5,6 +5,7 @@ import 'package:aves/model/filters/location.dart';
import 'package:aves/model/filters/mime.dart'; import 'package:aves/model/filters/mime.dart';
import 'package:aves/model/filters/tag.dart'; import 'package:aves/model/filters/tag.dart';
import 'package:aves/model/image_entry.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/model/source/collection_lens.dart';
import 'package:aves/utils/color_utils.dart'; import 'package:aves/utils/color_utils.dart';
import 'package:aves/utils/constants.dart'; import 'package:aves/utils/constants.dart';
@ -241,7 +242,7 @@ class StatsPage extends StatelessWidget {
settings: RouteSettings(name: CollectionPage.routeName), settings: RouteSettings(name: CollectionPage.routeName),
builder: (context) => CollectionPage(collection.derive(filter)), builder: (context) => CollectionPage(collection.derive(filter)),
), ),
(route) => false, settings.navRemoveRoutePredicate(CollectionPage.routeName),
); );
} }
} }

View file

@ -104,13 +104,12 @@ class _WelcomePageState extends State<WelcomePage> {
onPressed: _hasAcceptedTerms onPressed: _hasAcceptedTerms
? () { ? () {
settings.hasAcceptedTerms = true; settings.hasAcceptedTerms = true;
Navigator.pushAndRemoveUntil( Navigator.pushReplacement(
context, context,
MaterialPageRoute( MaterialPageRoute(
settings: RouteSettings(name: HomePage.routeName), settings: RouteSettings(name: HomePage.routeName),
builder: (context) => HomePage(), builder: (context) => HomePage(),
), ),
(route) => false,
); );
} }
: null, : null,