#1448 display home tile in side drawer when customized
This commit is contained in:
parent
5c94d2eece
commit
76a9cf3cb3
7 changed files with 77 additions and 14 deletions
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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: [
|
||||||
|
|
|
@ -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,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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?>();
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue