From 9ad919186b2f408c088a871e51830d80dde3afe4 Mon Sep 17 00:00:00 2001 From: Thibault Deckers Date: Thu, 29 Apr 2021 12:20:44 +0900 Subject: [PATCH] #43 #44 drawer: moved about/settings tiles away from navigation tiles --- lib/theme/durations.dart | 6 +- lib/widgets/drawer/app_drawer.dart | 96 +++++++++++++++++++++--------- 2 files changed, 73 insertions(+), 29 deletions(-) diff --git a/lib/theme/durations.dart b/lib/theme/durations.dart index b14205552..03fde8263 100644 --- a/lib/theme/durations.dart +++ b/lib/theme/durations.dart @@ -4,6 +4,7 @@ class Durations { // Flutter animations (with margin) static const popupMenuAnimation = Duration(milliseconds: 300 + 10); // ref `_kMenuDuration` used in `_PopupMenuRoute` static const dialogTransitionAnimation = Duration(milliseconds: 150 + 10); // ref `transitionDuration` used in `DialogRoute` + static const drawerTransitionAnimation = Duration(milliseconds: 246 + 10); // ref `_kBaseSettleDuration` used in `DrawerControllerState` static const toggleableTransitionAnimation = Duration(milliseconds: 200 + 10); // ref `_kToggleDuration` used in `ToggleableStateMixin` // common animations @@ -12,12 +13,15 @@ class Durations { static const sweepingAnimation = Duration(milliseconds: 650); static const staggeredAnimation = Duration(milliseconds: 375); - static const staggeredAnimationPageTarget = Duration(milliseconds: 900); + static const staggeredAnimationPageTarget = Duration(milliseconds: 800); static const dialogFieldReachAnimation = Duration(milliseconds: 300); static const appBarTitleAnimation = Duration(milliseconds: 300); static const appBarActionChangeAnimation = Duration(milliseconds: 200); + // drawer + static const newsBadgeAnimation = Duration(milliseconds: 200); + // filter grids animations static const chipDecorationAnimation = Duration(milliseconds: 200); static const highlightScrollAnimationMinMillis = 400; diff --git a/lib/widgets/drawer/app_drawer.dart b/lib/widgets/drawer/app_drawer.dart index e3c3ff760..e11c4b497 100644 --- a/lib/widgets/drawer/app_drawer.dart +++ b/lib/widgets/drawer/app_drawer.dart @@ -8,10 +8,10 @@ import 'package:aves/model/source/collection_source.dart'; import 'package:aves/model/source/location.dart'; import 'package:aves/model/source/tag.dart'; import 'package:aves/services/services.dart'; +import 'package:aves/theme/durations.dart'; import 'package:aves/theme/icons.dart'; import 'package:aves/utils/android_file_utils.dart'; import 'package:aves/widgets/about/about_page.dart'; -import 'package:aves/widgets/about/news_badge.dart'; import 'package:aves/widgets/common/extensions/build_context.dart'; import 'package:aves/widgets/common/extensions/media_query.dart'; import 'package:aves/widgets/common/identity/aves_logo.dart'; @@ -58,9 +58,6 @@ class _AppDrawerState extends State { albumListTile, countryListTile, tagListTile, - Divider(), - settingsTile, - aboutTile, if (kDebugMode) ...[ Divider(), debugTile, @@ -92,8 +89,19 @@ class _AppDrawerState extends State { } Widget _buildHeader(BuildContext context) { + Future goTo(String routeName, WidgetBuilder pageBuilder) async { + Navigator.pop(context); + await Future.delayed(Durations.drawerTransitionAnimation); + await Navigator.push( + context, + MaterialPageRoute( + settings: RouteSettings(name: routeName), + builder: pageBuilder, + )); + } + return Container( - padding: EdgeInsets.all(16), + padding: EdgeInsets.only(left: 16, top: 16, right: 16, bottom: 8), color: Theme.of(context).accentColor, child: SafeArea( bottom: false, @@ -119,6 +127,61 @@ class _AppDrawerState extends State { ], ), ), + SizedBox(height: 8), + OutlinedButtonTheme( + data: OutlinedButtonThemeData( + style: ButtonStyle( + foregroundColor: MaterialStateProperty.all(Colors.white), + overlayColor: MaterialStateProperty.all(Colors.white24), + ), + ), + child: Wrap( + spacing: 8, + runSpacing: 8, + children: [ + OutlinedButton.icon( + onPressed: () => goTo(AboutPage.routeName, (_) => AboutPage()), + icon: Icon(AIcons.info), + label: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(context.l10n.aboutPageTitle), + FutureBuilder( + future: _newVersionLoader, + builder: (context, snapshot) { + final newVersion = snapshot.data == true; + final badgeSize = 8.0 * MediaQuery.textScaleFactorOf(context); + return AnimatedOpacity( + duration: Durations.newsBadgeAnimation, + opacity: newVersion ? 1 : 0, + child: Padding( + padding: EdgeInsetsDirectional.only(start: 2), + child: DecoratedBox( + decoration: BoxDecoration( + border: Border.all(color: Colors.white70), + borderRadius: BorderRadius.circular(badgeSize), + ), + child: Icon( + Icons.circle, + size: badgeSize, + color: Colors.red, + ), + ), + ), + ); + }, + ), + ], + ), + ), + OutlinedButton.icon( + onPressed: () => goTo(SettingsPage.routeName, (_) => SettingsPage()), + icon: Icon(AIcons.settings), + label: Text(context.l10n.settingsPageTitle), + ), + ], + ), + ) ], ), ), @@ -198,29 +261,6 @@ class _AppDrawerState extends State { pageBuilder: (_) => TagListPage(), ); - Widget get settingsTile => NavTile( - icon: AIcons.settings, - title: context.l10n.settingsPageTitle, - topLevel: false, - routeName: SettingsPage.routeName, - pageBuilder: (_) => SettingsPage(), - ); - - Widget get aboutTile => FutureBuilder( - future: _newVersionLoader, - builder: (context, snapshot) { - final newVersion = snapshot.data == true; - return NavTile( - icon: AIcons.info, - title: context.l10n.aboutPageTitle, - trailing: newVersion ? AboutNewsBadge() : null, - topLevel: false, - routeName: AboutPage.routeName, - pageBuilder: (_) => AboutPage(), - ); - }, - ); - Widget get debugTile => NavTile( icon: AIcons.debug, title: 'Debug',