From 76a9cf3cb39d6d8d700db178ca2362bc0204103a Mon Sep 17 00:00:00 2001 From: Thibault Deckers Date: Tue, 25 Feb 2025 19:59:28 +0100 Subject: [PATCH] #1448 display home tile in side drawer when customized --- CHANGELOG.md | 1 + lib/widgets/explorer/explorer_page.dart | 4 +- lib/widgets/navigation/drawer/app_drawer.dart | 51 ++++++++++++++++++- .../drawer/collection_nav_tile.dart | 8 +-- .../navigation/drawer/page_nav_tile.dart | 20 ++++++-- lib/widgets/navigation/nav_display.dart | 5 ++ lib/widgets/navigation/tv_rail.dart | 2 +- 7 files changed, 77 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7599e4d92..15fbe0e70 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ All notable changes to this project will be documented in this file. - support for Samsung HEIC motion photos embedding video in sefd box - Cataloguing: identify video location from Apple QuickTime metadata, and 3GPP `loci` atom - Collection: stack RAW and HEIC with same file names +- display home tile in side drawer when customized ### Changed diff --git a/lib/widgets/explorer/explorer_page.dart b/lib/widgets/explorer/explorer_page.dart index 390578e1b..a0748d8ea 100644 --- a/lib/widgets/explorer/explorer_page.dart +++ b/lib/widgets/explorer/explorer_page.dart @@ -84,12 +84,12 @@ class _ExplorerPageState extends State { valueListenable: _directory, builder: (context, directory, child) { final atRoot = directory?.relativeDir.isEmpty ?? true; + final path = _pathOf(directory); return AvesPopScope( handlers: [ APopHandler( canPop: (context) => atRoot, onPopBlocked: (context) { - final path = _pathOf(directory); if (path != null) { _goTo(pContext.dirname(path)); } @@ -99,7 +99,7 @@ class _ExplorerPageState extends State { doubleBackPopHandler, ], child: AvesScaffold( - drawer: const AppDrawer(), + drawer: AppDrawer(currentExplorerPath: path), body: GestureAreaProtectorStack( child: Column( children: [ diff --git a/lib/widgets/navigation/drawer/app_drawer.dart b/lib/widgets/navigation/drawer/app_drawer.dart index 8c2785f7b..95580471f 100644 --- a/lib/widgets/navigation/drawer/app_drawer.dart +++ b/lib/widgets/navigation/drawer/app_drawer.dart @@ -21,10 +21,12 @@ import 'package:aves/widgets/common/extensions/media_query.dart'; import 'package:aves/widgets/common/identity/aves_logo.dart'; import 'package:aves/widgets/common/search/page.dart'; import 'package:aves/widgets/debug/app_debug_page.dart'; +import 'package:aves/widgets/explorer/explorer_page.dart'; import 'package:aves/widgets/filter_grids/albums_page.dart'; import 'package:aves/widgets/filter_grids/countries_page.dart'; import 'package:aves/widgets/filter_grids/places_page.dart'; import 'package:aves/widgets/filter_grids/tags_page.dart'; +import 'package:aves/widgets/home_page.dart'; import 'package:aves/widgets/navigation/drawer/collection_nav_tile.dart'; import 'package:aves/widgets/navigation/drawer/page_nav_tile.dart'; import 'package:aves/widgets/navigation/drawer/tile.dart'; @@ -39,9 +41,13 @@ class AppDrawer extends StatefulWidget { // collection loaded in the `CollectionPage`, if any final CollectionLens? currentCollection; + // current path loaded in the `ExplorerPage`, if any + final String? currentExplorerPath; + const AppDrawer({ super.key, this.currentCollection, + this.currentExplorerPath, }); @override @@ -121,6 +127,7 @@ class _AppDrawerState extends State with WidgetsBindingObserver { Widget build(BuildContext context) { final drawerItems = [ _buildHeader(context), + _buildHomeLink(), ..._buildTypeLinks(), _buildAlbumLinks(context), ..._buildPageLinks(context), @@ -279,6 +286,46 @@ class _AppDrawerState extends State with WidgetsBindingObserver { ); } + Widget _buildHomeLink() { + // route name used for display purposes, no actual routing + const displayRoute = HomePage.routeName; + const leading = DrawerPageIcon(route: displayRoute); + const title = DrawerPageTitle(route: displayRoute); + + switch (settings.homePage) { + case HomePageSetting.collection: + final filters = settings.homeCustomCollection; + if (filters.isNotEmpty) { + return CollectionNavTile( + leading: leading, + title: title, + filters: filters, + isSelected: () => setEquals(currentCollection?.filters, filters), + ); + } + case HomePageSetting.explorer: + final path = settings.homeCustomExplorerPath; + if (path != null) { + return PageNavTile( + leading: leading, + title: title, + routeName: ExplorerPage.routeName, + isSelected: () => widget.currentExplorerPath == path, + routeBuilder: (context, routeName, _) { + return MaterialPageRoute( + settings: RouteSettings(name: routeName), + builder: (_) => ExplorerPage(path: path), + ); + }, + ); + } + case HomePageSetting.albums: + case HomePageSetting.tags: + break; + } + return const SizedBox(); + } + List _buildTypeLinks() { final hiddenFilters = settings.hiddenFilters; final typeBookmarks = settings.drawerTypeBookmarks; @@ -290,7 +337,7 @@ class _AppDrawerState extends State with WidgetsBindingObserver { key: Key('drawer-type-${filter?.key}'), leading: DrawerFilterIcon(filter: filter), title: DrawerFilterTitle(filter: filter), - filter: filter, + filters: {filter}, isSelected: () { if (currentFilters == null || currentFilters.length > 1) return false; return currentFilters.firstOrNull == filter; @@ -380,7 +427,7 @@ class _AppDrawerState extends State with WidgetsBindingObserver { leading: const DrawerFilterIcon(filter: filter), title: const DrawerFilterTitle(filter: filter), trailing: Text(formatFileSize(context.locale, trashSize, round: 0)), - filter: filter, + filters: {filter}, isSelected: () => currentCollection?.filters.contains(filter) ?? false, ); } diff --git a/lib/widgets/navigation/drawer/collection_nav_tile.dart b/lib/widgets/navigation/drawer/collection_nav_tile.dart index 24ea7067d..e5f8676d0 100644 --- a/lib/widgets/navigation/drawer/collection_nav_tile.dart +++ b/lib/widgets/navigation/drawer/collection_nav_tile.dart @@ -12,7 +12,7 @@ class CollectionNavTile extends StatelessWidget { final Widget? leading; final Widget title; final Widget? trailing; - final CollectionFilter? filter; + final Set? filters; final bool Function() isSelected; const CollectionNavTile({ @@ -20,7 +20,7 @@ class CollectionNavTile extends StatelessWidget { required this.leading, required this.title, this.trailing, - required this.filter, + required this.filters, required this.isSelected, }); @@ -59,7 +59,7 @@ class CollectionNavTile extends StatelessWidget { settings: const RouteSettings(name: CollectionPage.routeName), builder: (context) => CollectionPage( source: context.read(), - filters: {filter}, + filters: filters, ), ), (route) => false, @@ -88,7 +88,7 @@ class AlbumNavTile extends StatelessWidget { size: 16, ) : null, - filter: filter, + filters: {filter}, isSelected: isSelected, ); } diff --git a/lib/widgets/navigation/drawer/page_nav_tile.dart b/lib/widgets/navigation/drawer/page_nav_tile.dart index 9c5dfbf8e..172cbf510 100644 --- a/lib/widgets/navigation/drawer/page_nav_tile.dart +++ b/lib/widgets/navigation/drawer/page_nav_tile.dart @@ -17,16 +17,26 @@ import 'package:aves/widgets/settings/settings_page.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; +typedef TileRouteBuilder = Route Function(BuildContext context, String routeName, bool topLevel); + class PageNavTile extends StatelessWidget { + final Widget? leading; + final Widget? title; final Widget? trailing; final bool topLevel; final String routeName; + final bool Function()? isSelected; + final TileRouteBuilder? routeBuilder; const PageNavTile({ super.key, + this.leading, + this.title, this.trailing, this.topLevel = true, required this.routeName, + this.isSelected, + this.routeBuilder, }); @override @@ -37,8 +47,8 @@ class PageNavTile extends StatelessWidget { child: ListTile( // key is expected by test driver key: Key('$routeName-tile'), - leading: DrawerPageIcon(route: routeName), - title: DrawerPageTitle(route: routeName), + leading: leading ?? DrawerPageIcon(route: routeName), + title: title ?? DrawerPageTitle(route: routeName), trailing: trailing != null ? Builder( builder: (context) => DefaultTextStyle.merge( @@ -51,7 +61,7 @@ class PageNavTile extends StatelessWidget { : null, onTap: () { Navigator.maybeOf(context)?.pop(); - final route = routeBuilder(context, routeName, topLevel); + final route = (routeBuilder ?? defaultRouteBuilder).call(context, routeName, topLevel); if (topLevel) { Navigator.maybeOf(context)?.pushAndRemoveUntil( route, @@ -61,12 +71,12 @@ class PageNavTile extends StatelessWidget { Navigator.maybeOf(context)?.push(route); } }, - selected: context.currentRouteName == routeName, + selected: context.currentRouteName == routeName && (isSelected?.call() ?? true), ), ); } - static Route routeBuilder(BuildContext context, String routeName, bool topLevel) { + static Route defaultRouteBuilder(BuildContext context, String routeName, bool topLevel) { switch (routeName) { case SearchPage.routeName: final currentCollection = context.read(); diff --git a/lib/widgets/navigation/nav_display.dart b/lib/widgets/navigation/nav_display.dart index 343cad986..1b3668784 100644 --- a/lib/widgets/navigation/nav_display.dart +++ b/lib/widgets/navigation/nav_display.dart @@ -12,6 +12,7 @@ import 'package:aves/widgets/filter_grids/albums_page.dart'; import 'package:aves/widgets/filter_grids/countries_page.dart'; import 'package:aves/widgets/filter_grids/places_page.dart'; import 'package:aves/widgets/filter_grids/tags_page.dart'; +import 'package:aves/widgets/home_page.dart'; import 'package:aves/widgets/settings/settings_page.dart'; import 'package:flutter/material.dart'; @@ -33,6 +34,8 @@ class NavigationDisplay { static String getPageTitle(BuildContext context, route) { final l10n = context.l10n; switch (route) { + case HomePage.routeName: + return l10n.settingsHomeTile; case AlbumListPage.routeName: return l10n.drawerAlbumPage; case CountryListPage.routeName: @@ -58,6 +61,8 @@ class NavigationDisplay { static IconData? getPageIcon(String route) { switch (route) { + case HomePage.routeName: + return AIcons.home; case AlbumListPage.routeName: return AIcons.album; case CountryListPage.routeName: diff --git a/lib/widgets/navigation/tv_rail.dart b/lib/widgets/navigation/tv_rail.dart index 4cc3ddfea..5d72bdc2e 100644 --- a/lib/widgets/navigation/tv_rail.dart +++ b/lib/widgets/navigation/tv_rail.dart @@ -261,7 +261,7 @@ class _TvRailState extends State { void _goTo(String routeName) { Navigator.maybeOf(context)?.pushAndRemoveUntil( - PageNavTile.routeBuilder(context, routeName, true), + PageNavTile.defaultRouteBuilder(context, routeName, true), (route) => false, ); }