always keep home as the first route in navigator stack, apply double back exit policy to filter grid pages
This commit is contained in:
parent
da26ccdc87
commit
751f2fcacc
9 changed files with 87 additions and 70 deletions
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Reference in a new issue