#1448 display home tile in side drawer when customized

This commit is contained in:
Thibault Deckers 2025-02-25 19:59:28 +01:00
parent 5c94d2eece
commit 76a9cf3cb3
7 changed files with 77 additions and 14 deletions

View file

@ -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 - support for Samsung HEIC motion photos embedding video in sefd box
- Cataloguing: identify video location from Apple QuickTime metadata, and 3GPP `loci` atom - Cataloguing: identify video location from Apple QuickTime metadata, and 3GPP `loci` atom
- Collection: stack RAW and HEIC with same file names - Collection: stack RAW and HEIC with same file names
- display home tile in side drawer when customized
### Changed ### Changed

View file

@ -84,12 +84,12 @@ class _ExplorerPageState extends State<ExplorerPage> {
valueListenable: _directory, valueListenable: _directory,
builder: (context, directory, child) { builder: (context, directory, child) {
final atRoot = directory?.relativeDir.isEmpty ?? true; final atRoot = directory?.relativeDir.isEmpty ?? true;
final path = _pathOf(directory);
return AvesPopScope( return AvesPopScope(
handlers: [ handlers: [
APopHandler( APopHandler(
canPop: (context) => atRoot, canPop: (context) => atRoot,
onPopBlocked: (context) { onPopBlocked: (context) {
final path = _pathOf(directory);
if (path != null) { if (path != null) {
_goTo(pContext.dirname(path)); _goTo(pContext.dirname(path));
} }
@ -99,7 +99,7 @@ class _ExplorerPageState extends State<ExplorerPage> {
doubleBackPopHandler, doubleBackPopHandler,
], ],
child: AvesScaffold( child: AvesScaffold(
drawer: const AppDrawer(), drawer: AppDrawer(currentExplorerPath: path),
body: GestureAreaProtectorStack( body: GestureAreaProtectorStack(
child: Column( child: Column(
children: [ children: [

View file

@ -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/identity/aves_logo.dart';
import 'package:aves/widgets/common/search/page.dart'; import 'package:aves/widgets/common/search/page.dart';
import 'package:aves/widgets/debug/app_debug_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/albums_page.dart';
import 'package:aves/widgets/filter_grids/countries_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/places_page.dart';
import 'package:aves/widgets/filter_grids/tags_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/collection_nav_tile.dart';
import 'package:aves/widgets/navigation/drawer/page_nav_tile.dart'; import 'package:aves/widgets/navigation/drawer/page_nav_tile.dart';
import 'package:aves/widgets/navigation/drawer/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 // collection loaded in the `CollectionPage`, if any
final CollectionLens? currentCollection; final CollectionLens? currentCollection;
// current path loaded in the `ExplorerPage`, if any
final String? currentExplorerPath;
const AppDrawer({ const AppDrawer({
super.key, super.key,
this.currentCollection, this.currentCollection,
this.currentExplorerPath,
}); });
@override @override
@ -121,6 +127,7 @@ class _AppDrawerState extends State<AppDrawer> with WidgetsBindingObserver {
Widget build(BuildContext context) { Widget build(BuildContext context) {
final drawerItems = <Widget>[ final drawerItems = <Widget>[
_buildHeader(context), _buildHeader(context),
_buildHomeLink(),
..._buildTypeLinks(), ..._buildTypeLinks(),
_buildAlbumLinks(context), _buildAlbumLinks(context),
..._buildPageLinks(context), ..._buildPageLinks(context),
@ -279,6 +286,46 @@ class _AppDrawerState extends State<AppDrawer> 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<Widget> _buildTypeLinks() { List<Widget> _buildTypeLinks() {
final hiddenFilters = settings.hiddenFilters; final hiddenFilters = settings.hiddenFilters;
final typeBookmarks = settings.drawerTypeBookmarks; final typeBookmarks = settings.drawerTypeBookmarks;
@ -290,7 +337,7 @@ class _AppDrawerState extends State<AppDrawer> with WidgetsBindingObserver {
key: Key('drawer-type-${filter?.key}'), key: Key('drawer-type-${filter?.key}'),
leading: DrawerFilterIcon(filter: filter), leading: DrawerFilterIcon(filter: filter),
title: DrawerFilterTitle(filter: filter), title: DrawerFilterTitle(filter: filter),
filter: filter, filters: {filter},
isSelected: () { isSelected: () {
if (currentFilters == null || currentFilters.length > 1) return false; if (currentFilters == null || currentFilters.length > 1) return false;
return currentFilters.firstOrNull == filter; return currentFilters.firstOrNull == filter;
@ -380,7 +427,7 @@ class _AppDrawerState extends State<AppDrawer> with WidgetsBindingObserver {
leading: const DrawerFilterIcon(filter: filter), leading: const DrawerFilterIcon(filter: filter),
title: const DrawerFilterTitle(filter: filter), title: const DrawerFilterTitle(filter: filter),
trailing: Text(formatFileSize(context.locale, trashSize, round: 0)), trailing: Text(formatFileSize(context.locale, trashSize, round: 0)),
filter: filter, filters: {filter},
isSelected: () => currentCollection?.filters.contains(filter) ?? false, isSelected: () => currentCollection?.filters.contains(filter) ?? false,
); );
} }

View file

@ -12,7 +12,7 @@ class CollectionNavTile extends StatelessWidget {
final Widget? leading; final Widget? leading;
final Widget title; final Widget title;
final Widget? trailing; final Widget? trailing;
final CollectionFilter? filter; final Set<CollectionFilter?>? filters;
final bool Function() isSelected; final bool Function() isSelected;
const CollectionNavTile({ const CollectionNavTile({
@ -20,7 +20,7 @@ class CollectionNavTile extends StatelessWidget {
required this.leading, required this.leading,
required this.title, required this.title,
this.trailing, this.trailing,
required this.filter, required this.filters,
required this.isSelected, required this.isSelected,
}); });
@ -59,7 +59,7 @@ class CollectionNavTile extends StatelessWidget {
settings: const RouteSettings(name: CollectionPage.routeName), settings: const RouteSettings(name: CollectionPage.routeName),
builder: (context) => CollectionPage( builder: (context) => CollectionPage(
source: context.read<CollectionSource>(), source: context.read<CollectionSource>(),
filters: {filter}, filters: filters,
), ),
), ),
(route) => false, (route) => false,
@ -88,7 +88,7 @@ class AlbumNavTile extends StatelessWidget {
size: 16, size: 16,
) )
: null, : null,
filter: filter, filters: {filter},
isSelected: isSelected, isSelected: isSelected,
); );
} }

View file

@ -17,16 +17,26 @@ import 'package:aves/widgets/settings/settings_page.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
typedef TileRouteBuilder = Route Function(BuildContext context, String routeName, bool topLevel);
class PageNavTile extends StatelessWidget { class PageNavTile extends StatelessWidget {
final Widget? leading;
final Widget? title;
final Widget? trailing; final Widget? trailing;
final bool topLevel; final bool topLevel;
final String routeName; final String routeName;
final bool Function()? isSelected;
final TileRouteBuilder? routeBuilder;
const PageNavTile({ const PageNavTile({
super.key, super.key,
this.leading,
this.title,
this.trailing, this.trailing,
this.topLevel = true, this.topLevel = true,
required this.routeName, required this.routeName,
this.isSelected,
this.routeBuilder,
}); });
@override @override
@ -37,8 +47,8 @@ class PageNavTile extends StatelessWidget {
child: ListTile( child: ListTile(
// key is expected by test driver // key is expected by test driver
key: Key('$routeName-tile'), key: Key('$routeName-tile'),
leading: DrawerPageIcon(route: routeName), leading: leading ?? DrawerPageIcon(route: routeName),
title: DrawerPageTitle(route: routeName), title: title ?? DrawerPageTitle(route: routeName),
trailing: trailing != null trailing: trailing != null
? Builder( ? Builder(
builder: (context) => DefaultTextStyle.merge( builder: (context) => DefaultTextStyle.merge(
@ -51,7 +61,7 @@ class PageNavTile extends StatelessWidget {
: null, : null,
onTap: () { onTap: () {
Navigator.maybeOf(context)?.pop(); Navigator.maybeOf(context)?.pop();
final route = routeBuilder(context, routeName, topLevel); final route = (routeBuilder ?? defaultRouteBuilder).call(context, routeName, topLevel);
if (topLevel) { if (topLevel) {
Navigator.maybeOf(context)?.pushAndRemoveUntil( Navigator.maybeOf(context)?.pushAndRemoveUntil(
route, route,
@ -61,12 +71,12 @@ class PageNavTile extends StatelessWidget {
Navigator.maybeOf(context)?.push(route); 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) { switch (routeName) {
case SearchPage.routeName: case SearchPage.routeName:
final currentCollection = context.read<CollectionLens?>(); final currentCollection = context.read<CollectionLens?>();

View file

@ -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/countries_page.dart';
import 'package:aves/widgets/filter_grids/places_page.dart'; import 'package:aves/widgets/filter_grids/places_page.dart';
import 'package:aves/widgets/filter_grids/tags_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:aves/widgets/settings/settings_page.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@ -33,6 +34,8 @@ class NavigationDisplay {
static String getPageTitle(BuildContext context, route) { static String getPageTitle(BuildContext context, route) {
final l10n = context.l10n; final l10n = context.l10n;
switch (route) { switch (route) {
case HomePage.routeName:
return l10n.settingsHomeTile;
case AlbumListPage.routeName: case AlbumListPage.routeName:
return l10n.drawerAlbumPage; return l10n.drawerAlbumPage;
case CountryListPage.routeName: case CountryListPage.routeName:
@ -58,6 +61,8 @@ class NavigationDisplay {
static IconData? getPageIcon(String route) { static IconData? getPageIcon(String route) {
switch (route) { switch (route) {
case HomePage.routeName:
return AIcons.home;
case AlbumListPage.routeName: case AlbumListPage.routeName:
return AIcons.album; return AIcons.album;
case CountryListPage.routeName: case CountryListPage.routeName:

View file

@ -261,7 +261,7 @@ class _TvRailState extends State<TvRail> {
void _goTo(String routeName) { void _goTo(String routeName) {
Navigator.maybeOf(context)?.pushAndRemoveUntil( Navigator.maybeOf(context)?.pushAndRemoveUntil(
PageNavTile.routeBuilder(context, routeName, true), PageNavTile.defaultRouteBuilder(context, routeName, true),
(route) => false, (route) => false,
); );
} }