#222 optional bottom nav bar
This commit is contained in:
parent
37fc57f694
commit
39aebf49e2
21 changed files with 547 additions and 206 deletions
|
@ -599,6 +599,7 @@
|
||||||
|
|
||||||
"settingsSectionNavigation": "Navigation",
|
"settingsSectionNavigation": "Navigation",
|
||||||
"settingsHome": "Home",
|
"settingsHome": "Home",
|
||||||
|
"settingsShowBottomNavigationBar": "Show bottom navigation bar",
|
||||||
"settingsKeepScreenOnTile": "Keep screen on",
|
"settingsKeepScreenOnTile": "Keep screen on",
|
||||||
"settingsKeepScreenOnTitle": "Keep Screen On",
|
"settingsKeepScreenOnTitle": "Keep Screen On",
|
||||||
"settingsDoubleBackExit": "Tap “back” twice to exit",
|
"settingsDoubleBackExit": "Tap “back” twice to exit",
|
||||||
|
|
|
@ -27,6 +27,7 @@ class SettingsDefaults {
|
||||||
static const mustBackTwiceToExit = true;
|
static const mustBackTwiceToExit = true;
|
||||||
static const keepScreenOn = KeepScreenOn.viewerOnly;
|
static const keepScreenOn = KeepScreenOn.viewerOnly;
|
||||||
static const homePage = HomePageSetting.collection;
|
static const homePage = HomePageSetting.collection;
|
||||||
|
static const showBottomNavigationBar = false;
|
||||||
static const confirmDeleteForever = true;
|
static const confirmDeleteForever = true;
|
||||||
static const confirmMoveToBin = true;
|
static const confirmMoveToBin = true;
|
||||||
static const confirmMoveUndatedItems = true;
|
static const confirmMoveUndatedItems = true;
|
||||||
|
|
|
@ -56,6 +56,7 @@ class Settings extends ChangeNotifier {
|
||||||
static const mustBackTwiceToExitKey = 'must_back_twice_to_exit';
|
static const mustBackTwiceToExitKey = 'must_back_twice_to_exit';
|
||||||
static const keepScreenOnKey = 'keep_screen_on';
|
static const keepScreenOnKey = 'keep_screen_on';
|
||||||
static const homePageKey = 'home_page';
|
static const homePageKey = 'home_page';
|
||||||
|
static const showBottomNavigationBarKey = 'show_bottom_navigation_bar';
|
||||||
static const confirmDeleteForeverKey = 'confirm_delete_forever';
|
static const confirmDeleteForeverKey = 'confirm_delete_forever';
|
||||||
static const confirmMoveToBinKey = 'confirm_move_to_bin';
|
static const confirmMoveToBinKey = 'confirm_move_to_bin';
|
||||||
static const confirmMoveUndatedItemsKey = 'confirm_move_undated_items';
|
static const confirmMoveUndatedItemsKey = 'confirm_move_undated_items';
|
||||||
|
@ -294,6 +295,10 @@ class Settings extends ChangeNotifier {
|
||||||
|
|
||||||
set homePage(HomePageSetting newValue) => setAndNotify(homePageKey, newValue.toString());
|
set homePage(HomePageSetting newValue) => setAndNotify(homePageKey, newValue.toString());
|
||||||
|
|
||||||
|
bool get showBottomNavigationBar => getBoolOrDefault(showBottomNavigationBarKey, SettingsDefaults.showBottomNavigationBar);
|
||||||
|
|
||||||
|
set showBottomNavigationBar(bool newValue) => setAndNotify(showBottomNavigationBarKey, newValue);
|
||||||
|
|
||||||
bool get confirmDeleteForever => getBoolOrDefault(confirmDeleteForeverKey, SettingsDefaults.confirmDeleteForever);
|
bool get confirmDeleteForever => getBoolOrDefault(confirmDeleteForeverKey, SettingsDefaults.confirmDeleteForever);
|
||||||
|
|
||||||
set confirmDeleteForever(bool newValue) => setAndNotify(confirmDeleteForeverKey, newValue);
|
set confirmDeleteForever(bool newValue) => setAndNotify(confirmDeleteForeverKey, newValue);
|
||||||
|
@ -682,6 +687,7 @@ class Settings extends ChangeNotifier {
|
||||||
break;
|
break;
|
||||||
case isInstalledAppAccessAllowedKey:
|
case isInstalledAppAccessAllowedKey:
|
||||||
case isErrorReportingAllowedKey:
|
case isErrorReportingAllowedKey:
|
||||||
|
case showBottomNavigationBarKey:
|
||||||
case mustBackTwiceToExitKey:
|
case mustBackTwiceToExitKey:
|
||||||
case confirmDeleteForeverKey:
|
case confirmDeleteForeverKey:
|
||||||
case confirmMoveToBinKey:
|
case confirmMoveToBinKey:
|
||||||
|
|
|
@ -139,7 +139,6 @@ class _AvesAppState extends State<AvesApp> with WidgetsBindingObserver {
|
||||||
return AvesColorsProvider(
|
return AvesColorsProvider(
|
||||||
child: child!,
|
child: child!,
|
||||||
);
|
);
|
||||||
// return child!;
|
|
||||||
},
|
},
|
||||||
onGenerateTitle: (context) => context.l10n.appName,
|
onGenerateTitle: (context) => context.l10n.appName,
|
||||||
theme: Themes.lightTheme,
|
theme: Themes.lightTheme,
|
||||||
|
|
|
@ -16,7 +16,8 @@ import 'package:aves/widgets/common/behaviour/double_back_pop.dart';
|
||||||
import 'package:aves/widgets/common/providers/media_query_data_provider.dart';
|
import 'package:aves/widgets/common/providers/media_query_data_provider.dart';
|
||||||
import 'package:aves/widgets/common/providers/query_provider.dart';
|
import 'package:aves/widgets/common/providers/query_provider.dart';
|
||||||
import 'package:aves/widgets/common/providers/selection_provider.dart';
|
import 'package:aves/widgets/common/providers/selection_provider.dart';
|
||||||
import 'package:aves/widgets/drawer/app_drawer.dart';
|
import 'package:aves/widgets/navigation/drawer/app_drawer.dart';
|
||||||
|
import 'package:aves/widgets/navigation/nav_bar/nav_bar.dart';
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
@ -74,30 +75,35 @@ class _CollectionPageState extends State<CollectionPage> {
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final liveFilter = _collection.filters.firstWhereOrNull((v) => v is QueryFilter && v.live) as QueryFilter?;
|
final liveFilter = _collection.filters.firstWhereOrNull((v) => v is QueryFilter && v.live) as QueryFilter?;
|
||||||
return MediaQueryDataProvider(
|
return MediaQueryDataProvider(
|
||||||
child: Scaffold(
|
child: Selector<Settings, bool>(
|
||||||
body: SelectionProvider<AvesEntry>(
|
selector: (context, s) => s.showBottomNavigationBar,
|
||||||
child: QueryProvider(
|
builder: (context, showBottomNavigationBar, child) {
|
||||||
initialQuery: liveFilter?.query,
|
return Scaffold(
|
||||||
child: Builder(
|
body: SelectionProvider<AvesEntry>(
|
||||||
builder: (context) => WillPopScope(
|
child: QueryProvider(
|
||||||
onWillPop: () {
|
initialQuery: liveFilter?.query,
|
||||||
final selection = context.read<Selection<AvesEntry>>();
|
child: Builder(
|
||||||
if (selection.isSelecting) {
|
builder: (context) => WillPopScope(
|
||||||
selection.browse();
|
onWillPop: () {
|
||||||
return SynchronousFuture(false);
|
final selection = context.read<Selection<AvesEntry>>();
|
||||||
}
|
if (selection.isSelecting) {
|
||||||
return SynchronousFuture(true);
|
selection.browse();
|
||||||
},
|
return SynchronousFuture(false);
|
||||||
child: DoubleBackPopScope(
|
}
|
||||||
child: GestureAreaProtectorStack(
|
return SynchronousFuture(true);
|
||||||
child: SafeArea(
|
},
|
||||||
bottom: false,
|
child: DoubleBackPopScope(
|
||||||
child: ChangeNotifierProvider<CollectionLens>.value(
|
child: GestureAreaProtectorStack(
|
||||||
value: _collection,
|
child: SafeArea(
|
||||||
child: const CollectionGrid(
|
bottom: false,
|
||||||
// key is expected by test driver
|
child: ChangeNotifierProvider<CollectionLens>.value(
|
||||||
key: Key('collection-grid'),
|
value: _collection,
|
||||||
settingsRouteKey: CollectionPage.routeName,
|
child: const CollectionGrid(
|
||||||
|
// key is expected by test driver
|
||||||
|
key: Key('collection-grid'),
|
||||||
|
settingsRouteKey: CollectionPage.routeName,
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -105,10 +111,12 @@ class _CollectionPageState extends State<CollectionPage> {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
drawer: AppDrawer(currentCollection: _collection),
|
||||||
),
|
bottomNavigationBar: showBottomNavigationBar ? AppBottomNavBar(currentCollection: _collection) : null,
|
||||||
drawer: AppDrawer(currentCollection: _collection),
|
resizeToAvoidBottomInset: false,
|
||||||
resizeToAvoidBottomInset: false,
|
extendBody: true,
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,118 +0,0 @@
|
||||||
import 'package:aves/model/filters/favourite.dart';
|
|
||||||
import 'package:aves/model/filters/filters.dart';
|
|
||||||
import 'package:aves/model/filters/mime.dart';
|
|
||||||
import 'package:aves/model/filters/type.dart';
|
|
||||||
import 'package:aves/theme/colors.dart';
|
|
||||||
import 'package:aves/theme/icons.dart';
|
|
||||||
import 'package:aves/widgets/common/extensions/build_context.dart';
|
|
||||||
import 'package:aves/widgets/debug/app_debug_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/tags_page.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
class DrawerFilterIcon extends StatelessWidget {
|
|
||||||
final CollectionFilter? filter;
|
|
||||||
|
|
||||||
const DrawerFilterIcon({
|
|
||||||
Key? key,
|
|
||||||
required this.filter,
|
|
||||||
}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final textScaleFactor = MediaQuery.textScaleFactorOf(context);
|
|
||||||
final iconSize = 24 * textScaleFactor;
|
|
||||||
|
|
||||||
final _filter = filter;
|
|
||||||
if (_filter == null) return Icon(AIcons.allCollection, size: iconSize);
|
|
||||||
return _filter.iconBuilder(context, iconSize) ?? const SizedBox();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class DrawerFilterTitle extends StatelessWidget {
|
|
||||||
final CollectionFilter? filter;
|
|
||||||
|
|
||||||
const DrawerFilterTitle({
|
|
||||||
Key? key,
|
|
||||||
required this.filter,
|
|
||||||
}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
String _getString(CollectionFilter? filter) {
|
|
||||||
final l10n = context.l10n;
|
|
||||||
if (filter == null) return l10n.drawerCollectionAll;
|
|
||||||
if (filter == FavouriteFilter.instance) return l10n.drawerCollectionFavourites;
|
|
||||||
if (filter == MimeFilter.image) return l10n.drawerCollectionImages;
|
|
||||||
if (filter == MimeFilter.video) return l10n.drawerCollectionVideos;
|
|
||||||
if (filter == TypeFilter.animated) return l10n.drawerCollectionAnimated;
|
|
||||||
if (filter == TypeFilter.motionPhoto) return l10n.drawerCollectionMotionPhotos;
|
|
||||||
if (filter == TypeFilter.panorama) return l10n.drawerCollectionPanoramas;
|
|
||||||
if (filter == TypeFilter.raw) return l10n.drawerCollectionRaws;
|
|
||||||
if (filter == TypeFilter.sphericalVideo) return l10n.drawerCollectionSphericalVideos;
|
|
||||||
return filter.getLabel(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Text(_getString(filter));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class DrawerPageIcon extends StatelessWidget {
|
|
||||||
final String route;
|
|
||||||
|
|
||||||
const DrawerPageIcon({
|
|
||||||
Key? key,
|
|
||||||
required this.route,
|
|
||||||
}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
switch (route) {
|
|
||||||
case AlbumListPage.routeName:
|
|
||||||
return const Icon(AIcons.album);
|
|
||||||
case CountryListPage.routeName:
|
|
||||||
return const Icon(AIcons.location);
|
|
||||||
case TagListPage.routeName:
|
|
||||||
return const Icon(AIcons.tag);
|
|
||||||
case AppDebugPage.routeName:
|
|
||||||
return ShaderMask(
|
|
||||||
shaderCallback: AvesColorsData.debugGradient.createShader,
|
|
||||||
blendMode: BlendMode.srcIn,
|
|
||||||
child: const Icon(AIcons.debug),
|
|
||||||
);
|
|
||||||
default:
|
|
||||||
return const SizedBox();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class DrawerPageTitle extends StatelessWidget {
|
|
||||||
final String route;
|
|
||||||
|
|
||||||
const DrawerPageTitle({
|
|
||||||
Key? key,
|
|
||||||
required this.route,
|
|
||||||
}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
String _getString() {
|
|
||||||
final l10n = context.l10n;
|
|
||||||
switch (route) {
|
|
||||||
case AlbumListPage.routeName:
|
|
||||||
return l10n.albumPageTitle;
|
|
||||||
case CountryListPage.routeName:
|
|
||||||
return l10n.countryPageTitle;
|
|
||||||
case TagListPage.routeName:
|
|
||||||
return l10n.tagPageTitle;
|
|
||||||
case AppDebugPage.routeName:
|
|
||||||
return 'Debug';
|
|
||||||
default:
|
|
||||||
return route;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Text(_getString());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -21,13 +21,14 @@ import 'package:aves/widgets/common/identity/scroll_thumb.dart';
|
||||||
import 'package:aves/widgets/common/providers/media_query_data_provider.dart';
|
import 'package:aves/widgets/common/providers/media_query_data_provider.dart';
|
||||||
import 'package:aves/widgets/common/providers/tile_extent_controller_provider.dart';
|
import 'package:aves/widgets/common/providers/tile_extent_controller_provider.dart';
|
||||||
import 'package:aves/widgets/common/tile_extent_controller.dart';
|
import 'package:aves/widgets/common/tile_extent_controller.dart';
|
||||||
import 'package:aves/widgets/drawer/app_drawer.dart';
|
|
||||||
import 'package:aves/widgets/filter_grids/common/covered_filter_chip.dart';
|
import 'package:aves/widgets/filter_grids/common/covered_filter_chip.dart';
|
||||||
import 'package:aves/widgets/filter_grids/common/draggable_thumb_label.dart';
|
import 'package:aves/widgets/filter_grids/common/draggable_thumb_label.dart';
|
||||||
import 'package:aves/widgets/filter_grids/common/filter_tile.dart';
|
import 'package:aves/widgets/filter_grids/common/filter_tile.dart';
|
||||||
import 'package:aves/widgets/filter_grids/common/list_details_theme.dart';
|
import 'package:aves/widgets/filter_grids/common/list_details_theme.dart';
|
||||||
import 'package:aves/widgets/filter_grids/common/section_keys.dart';
|
import 'package:aves/widgets/filter_grids/common/section_keys.dart';
|
||||||
import 'package:aves/widgets/filter_grids/common/section_layout.dart';
|
import 'package:aves/widgets/filter_grids/common/section_layout.dart';
|
||||||
|
import 'package:aves/widgets/navigation/drawer/app_drawer.dart';
|
||||||
|
import 'package:aves/widgets/navigation/nav_bar/nav_bar.dart';
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
@ -69,42 +70,49 @@ class FilterGridPage<T extends CollectionFilter> extends StatelessWidget {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return MediaQueryDataProvider(
|
return MediaQueryDataProvider(
|
||||||
child: Scaffold(
|
child: Selector<Settings, bool>(
|
||||||
body: WillPopScope(
|
selector: (context, s) => s.showBottomNavigationBar,
|
||||||
onWillPop: () {
|
builder: (context, showBottomNavigationBar, child) {
|
||||||
final selection = context.read<Selection<FilterGridItem<T>>>();
|
return Scaffold(
|
||||||
if (selection.isSelecting) {
|
body: WillPopScope(
|
||||||
selection.browse();
|
onWillPop: () {
|
||||||
return SynchronousFuture(false);
|
final selection = context.read<Selection<FilterGridItem<T>>>();
|
||||||
}
|
if (selection.isSelecting) {
|
||||||
return SynchronousFuture(true);
|
selection.browse();
|
||||||
},
|
return SynchronousFuture(false);
|
||||||
child: DoubleBackPopScope(
|
}
|
||||||
child: GestureAreaProtectorStack(
|
return SynchronousFuture(true);
|
||||||
child: SafeArea(
|
},
|
||||||
bottom: false,
|
child: DoubleBackPopScope(
|
||||||
child: FilterGrid<T>(
|
child: GestureAreaProtectorStack(
|
||||||
// key is expected by test driver
|
child: SafeArea(
|
||||||
key: const Key('filter-grid'),
|
bottom: false,
|
||||||
settingsRouteKey: settingsRouteKey,
|
child: FilterGrid<T>(
|
||||||
appBar: appBar,
|
// key is expected by test driver
|
||||||
appBarHeight: appBarHeight,
|
key: const Key('filter-grid'),
|
||||||
sections: sections,
|
settingsRouteKey: settingsRouteKey,
|
||||||
newFilters: newFilters,
|
appBar: appBar,
|
||||||
sortFactor: sortFactor,
|
appBarHeight: appBarHeight,
|
||||||
showHeaders: showHeaders,
|
sections: sections,
|
||||||
selectable: selectable,
|
newFilters: newFilters,
|
||||||
queryNotifier: queryNotifier,
|
sortFactor: sortFactor,
|
||||||
applyQuery: applyQuery,
|
showHeaders: showHeaders,
|
||||||
emptyBuilder: emptyBuilder,
|
selectable: selectable,
|
||||||
heroType: heroType,
|
queryNotifier: queryNotifier,
|
||||||
|
applyQuery: applyQuery,
|
||||||
|
emptyBuilder: emptyBuilder,
|
||||||
|
heroType: heroType,
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
drawer: const AppDrawer(),
|
||||||
),
|
bottomNavigationBar: showBottomNavigationBar ? const AppBottomNavBar() : null,
|
||||||
drawer: const AppDrawer(),
|
resizeToAvoidBottomInset: false,
|
||||||
resizeToAvoidBottomInset: false,
|
extendBody: true,
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,19 +17,19 @@ import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||||
import 'package:aves/widgets/common/extensions/media_query.dart';
|
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/debug/app_debug_page.dart';
|
import 'package:aves/widgets/debug/app_debug_page.dart';
|
||||||
import 'package:aves/widgets/drawer/collection_nav_tile.dart';
|
|
||||||
import 'package:aves/widgets/drawer/page_nav_tile.dart';
|
|
||||||
import 'package:aves/widgets/drawer/tile.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/tags_page.dart';
|
import 'package:aves/widgets/filter_grids/tags_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';
|
||||||
import 'package:aves/widgets/settings/settings_page.dart';
|
import 'package:aves/widgets/settings/settings_page.dart';
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
class AppDrawer extends StatelessWidget {
|
class AppDrawer extends StatefulWidget {
|
||||||
// collection loaded in the `CollectionPage`, if any
|
// collection loaded in the `CollectionPage`, if any
|
||||||
final CollectionLens? currentCollection;
|
final CollectionLens? currentCollection;
|
||||||
|
|
||||||
|
@ -38,6 +38,9 @@ class AppDrawer extends StatelessWidget {
|
||||||
this.currentCollection,
|
this.currentCollection,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<AppDrawer> createState() => _AppDrawerState();
|
||||||
|
|
||||||
static List<String> getDefaultAlbums(BuildContext context) {
|
static List<String> getDefaultAlbums(BuildContext context) {
|
||||||
final source = context.read<CollectionSource>();
|
final source = context.read<CollectionSource>();
|
||||||
final specialAlbums = source.rawAlbums.where((album) {
|
final specialAlbums = source.rawAlbums.where((album) {
|
||||||
|
@ -47,6 +50,14 @@ class AppDrawer extends StatelessWidget {
|
||||||
..sort(source.compareAlbumsByName);
|
..sort(source.compareAlbumsByName);
|
||||||
return specialAlbums;
|
return specialAlbums;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _AppDrawerState extends State<AppDrawer> {
|
||||||
|
// using the default controller conflicts
|
||||||
|
// with bottom nav bar primary scroll monitoring
|
||||||
|
final ScrollController _scrollController = ScrollController();
|
||||||
|
|
||||||
|
CollectionLens? get currentCollection => widget.currentCollection;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
@ -73,6 +84,7 @@ class AppDrawer extends StatelessWidget {
|
||||||
builder: (context, mqPaddingBottom, child) {
|
builder: (context, mqPaddingBottom, child) {
|
||||||
final iconTheme = IconTheme.of(context);
|
final iconTheme = IconTheme.of(context);
|
||||||
return SingleChildScrollView(
|
return SingleChildScrollView(
|
||||||
|
controller: _scrollController,
|
||||||
// key is expected by test driver
|
// key is expected by test driver
|
||||||
key: const Key('drawer-scrollview'),
|
key: const Key('drawer-scrollview'),
|
||||||
padding: EdgeInsets.only(bottom: mqPaddingBottom),
|
padding: EdgeInsets.only(bottom: mqPaddingBottom),
|
|
@ -5,7 +5,7 @@ import 'package:aves/theme/icons.dart';
|
||||||
import 'package:aves/utils/android_file_utils.dart';
|
import 'package:aves/utils/android_file_utils.dart';
|
||||||
import 'package:aves/widgets/collection/collection_page.dart';
|
import 'package:aves/widgets/collection/collection_page.dart';
|
||||||
import 'package:aves/widgets/common/extensions/build_context.dart';
|
import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||||
import 'package:aves/widgets/drawer/tile.dart';
|
import 'package:aves/widgets/navigation/drawer/tile.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import 'package:aves/widgets/common/extensions/build_context.dart';
|
import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||||
import 'package:aves/widgets/drawer/tile.dart';
|
import 'package:aves/widgets/navigation/drawer/tile.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class PageNavTile extends StatelessWidget {
|
class PageNavTile extends StatelessWidget {
|
81
lib/widgets/navigation/drawer/tile.dart
Normal file
81
lib/widgets/navigation/drawer/tile.dart
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
import 'package:aves/model/filters/filters.dart';
|
||||||
|
import 'package:aves/theme/colors.dart';
|
||||||
|
import 'package:aves/theme/icons.dart';
|
||||||
|
import 'package:aves/widgets/debug/app_debug_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/tags_page.dart';
|
||||||
|
import 'package:aves/widgets/navigation/nav_display.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class DrawerFilterIcon extends StatelessWidget {
|
||||||
|
final CollectionFilter? filter;
|
||||||
|
|
||||||
|
const DrawerFilterIcon({
|
||||||
|
Key? key,
|
||||||
|
required this.filter,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final textScaleFactor = MediaQuery.textScaleFactorOf(context);
|
||||||
|
final iconSize = 24 * textScaleFactor;
|
||||||
|
|
||||||
|
final _filter = filter;
|
||||||
|
if (_filter == null) return Icon(AIcons.allCollection, size: iconSize);
|
||||||
|
return _filter.iconBuilder(context, iconSize) ?? const SizedBox();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DrawerFilterTitle extends StatelessWidget {
|
||||||
|
final CollectionFilter? filter;
|
||||||
|
|
||||||
|
const DrawerFilterTitle({
|
||||||
|
Key? key,
|
||||||
|
required this.filter,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) => Text(NavigationDisplay.getFilterTitle(context, filter));
|
||||||
|
}
|
||||||
|
|
||||||
|
class DrawerPageIcon extends StatelessWidget {
|
||||||
|
final String route;
|
||||||
|
|
||||||
|
const DrawerPageIcon({
|
||||||
|
Key? key,
|
||||||
|
required this.route,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final icon = NavigationDisplay.getPageIcon(route);
|
||||||
|
if (icon != null) {
|
||||||
|
switch (route) {
|
||||||
|
case AlbumListPage.routeName:
|
||||||
|
case CountryListPage.routeName:
|
||||||
|
case TagListPage.routeName:
|
||||||
|
return Icon(icon);
|
||||||
|
case AppDebugPage.routeName:
|
||||||
|
return ShaderMask(
|
||||||
|
shaderCallback: AvesColorsData.debugGradient.createShader,
|
||||||
|
blendMode: BlendMode.srcIn,
|
||||||
|
child: Icon(icon),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return const SizedBox();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DrawerPageTitle extends StatelessWidget {
|
||||||
|
final String route;
|
||||||
|
|
||||||
|
const DrawerPageTitle({
|
||||||
|
Key? key,
|
||||||
|
required this.route,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) => Text(NavigationDisplay.getPageTitle(context, route));
|
||||||
|
}
|
100
lib/widgets/navigation/nav_bar/floating.dart
Normal file
100
lib/widgets/navigation/nav_bar/floating.dart
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class FloatingNavBar extends StatefulWidget {
|
||||||
|
final ScrollController? scrollController;
|
||||||
|
final Widget child;
|
||||||
|
|
||||||
|
const FloatingNavBar({
|
||||||
|
Key? key,
|
||||||
|
required this.scrollController,
|
||||||
|
required this.child,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_FloatingNavBarState createState() => _FloatingNavBarState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _FloatingNavBarState extends State<FloatingNavBar> with SingleTickerProviderStateMixin {
|
||||||
|
late AnimationController _controller;
|
||||||
|
late Animation<Offset> _offsetAnimation;
|
||||||
|
double? _lastOffset;
|
||||||
|
double _delta = 0;
|
||||||
|
|
||||||
|
static const double _deltaThreshold = 50;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_controller = AnimationController(
|
||||||
|
duration: const Duration(milliseconds: 200),
|
||||||
|
vsync: this,
|
||||||
|
);
|
||||||
|
_offsetAnimation = Tween<Offset>(
|
||||||
|
begin: const Offset(0, 0),
|
||||||
|
end: const Offset(0, 1),
|
||||||
|
).animate(CurvedAnimation(
|
||||||
|
parent: _controller,
|
||||||
|
curve: Curves.linear,
|
||||||
|
))
|
||||||
|
..addListener(() {
|
||||||
|
if (mounted) {
|
||||||
|
setState(() {});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
_registerWidget(widget);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void didUpdateWidget(covariant FloatingNavBar oldWidget) {
|
||||||
|
super.didUpdateWidget(oldWidget);
|
||||||
|
|
||||||
|
if (oldWidget.scrollController != widget.scrollController) {
|
||||||
|
_unregisterWidget(oldWidget);
|
||||||
|
_registerWidget(widget);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_unregisterWidget(widget);
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _registerWidget(FloatingNavBar widget) {
|
||||||
|
_lastOffset = null;
|
||||||
|
_delta = 0;
|
||||||
|
widget.scrollController?.addListener(_onScrollChange);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _unregisterWidget(FloatingNavBar widget) {
|
||||||
|
widget.scrollController?.removeListener(_onScrollChange);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return SlideTransition(
|
||||||
|
position: _offsetAnimation,
|
||||||
|
child: widget.child,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _onScrollChange() {
|
||||||
|
final scrollController = widget.scrollController;
|
||||||
|
if (scrollController == null) return;
|
||||||
|
|
||||||
|
final offset = scrollController.offset;
|
||||||
|
_delta += offset - (_lastOffset ?? offset);
|
||||||
|
_lastOffset = offset;
|
||||||
|
|
||||||
|
if (_delta.abs() > _deltaThreshold) {
|
||||||
|
if (_delta > 0) {
|
||||||
|
// hide
|
||||||
|
_controller.forward();
|
||||||
|
} else {
|
||||||
|
// show
|
||||||
|
_controller.reverse();
|
||||||
|
}
|
||||||
|
_delta = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
117
lib/widgets/navigation/nav_bar/nav_bar.dart
Normal file
117
lib/widgets/navigation/nav_bar/nav_bar.dart
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
import 'package:aves/model/filters/favourite.dart';
|
||||||
|
import 'package:aves/model/filters/mime.dart';
|
||||||
|
import 'package:aves/model/settings/settings.dart';
|
||||||
|
import 'package:aves/model/source/collection_lens.dart';
|
||||||
|
import 'package:aves/model/source/collection_source.dart';
|
||||||
|
import 'package:aves/widgets/collection/collection_page.dart';
|
||||||
|
import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||||
|
import 'package:aves/widgets/common/fx/blurred.dart';
|
||||||
|
import 'package:aves/widgets/filter_grids/albums_page.dart';
|
||||||
|
import 'package:aves/widgets/navigation/nav_bar/floating.dart';
|
||||||
|
import 'package:aves/widgets/navigation/nav_bar/nav_item.dart';
|
||||||
|
import 'package:collection/collection.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
class AppBottomNavBar extends StatelessWidget {
|
||||||
|
// collection loaded in the `CollectionPage`, if any
|
||||||
|
final CollectionLens? currentCollection;
|
||||||
|
|
||||||
|
const AppBottomNavBar({
|
||||||
|
Key? key,
|
||||||
|
this.currentCollection,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
const borderRadius = BorderRadius.all(Radius.circular(8));
|
||||||
|
|
||||||
|
final blurred = context.select<Settings, bool>((s) => s.enableOverlayBlurEffect);
|
||||||
|
final showVideo = context.select<Settings, bool>((s) => !s.hiddenFilters.contains(MimeFilter.video));
|
||||||
|
|
||||||
|
final items = [
|
||||||
|
const AvesBottomNavItem(route: CollectionPage.routeName),
|
||||||
|
if (showVideo) AvesBottomNavItem(route: CollectionPage.routeName, filter: MimeFilter.video),
|
||||||
|
const AvesBottomNavItem(route: CollectionPage.routeName, filter: FavouriteFilter.instance),
|
||||||
|
const AvesBottomNavItem(route: AlbumListPage.routeName),
|
||||||
|
];
|
||||||
|
|
||||||
|
Widget child = Padding(
|
||||||
|
padding: const EdgeInsets.all(8),
|
||||||
|
child: BlurredRRect(
|
||||||
|
enabled: blurred,
|
||||||
|
borderRadius: borderRadius,
|
||||||
|
child: BottomNavigationBar(
|
||||||
|
items: items
|
||||||
|
.map((item) => BottomNavigationBarItem(
|
||||||
|
icon: item.icon(context),
|
||||||
|
label: item.label(context),
|
||||||
|
))
|
||||||
|
.toList(),
|
||||||
|
onTap: (index) => _goTo(context, items, index),
|
||||||
|
currentIndex: _getCurrentIndex(context, items),
|
||||||
|
type: BottomNavigationBarType.fixed,
|
||||||
|
backgroundColor: Theme.of(context).canvasColor.withOpacity(.85),
|
||||||
|
showSelectedLabels: false,
|
||||||
|
showUnselectedLabels: false,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
return Hero(
|
||||||
|
tag: 'nav-bar',
|
||||||
|
flightShuttleBuilder: (flight, animation, direction, fromHero, toHero) {
|
||||||
|
return MediaQuery.removeViewInsets(
|
||||||
|
context: context,
|
||||||
|
removeBottom: true,
|
||||||
|
child: toHero.widget,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: FloatingNavBar(
|
||||||
|
scrollController: PrimaryScrollController.of(context),
|
||||||
|
child: SafeArea(
|
||||||
|
child: child,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
int _getCurrentIndex(BuildContext context, List<AvesBottomNavItem> items) {
|
||||||
|
final currentRoute = context.currentRouteName;
|
||||||
|
final currentItem = items.firstWhereOrNull((item) {
|
||||||
|
if (currentRoute != item.route) return false;
|
||||||
|
|
||||||
|
if (item.route != CollectionPage.routeName) return true;
|
||||||
|
|
||||||
|
final currentFilters = currentCollection?.filters;
|
||||||
|
if (currentFilters == null || currentFilters.length > 1) return false;
|
||||||
|
return currentFilters.firstOrNull == item.filter;
|
||||||
|
});
|
||||||
|
final currentIndex = currentItem != null ? items.indexOf(currentItem) : 0;
|
||||||
|
return currentIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _goTo(BuildContext context, List<AvesBottomNavItem> items, int index) {
|
||||||
|
final item = items[index];
|
||||||
|
final routeName = item.route;
|
||||||
|
Navigator.pushAndRemoveUntil(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
settings: RouteSettings(name: routeName),
|
||||||
|
builder: (context) {
|
||||||
|
switch (routeName) {
|
||||||
|
case AlbumListPage.routeName:
|
||||||
|
return const AlbumListPage();
|
||||||
|
case CollectionPage.routeName:
|
||||||
|
default:
|
||||||
|
return CollectionPage(
|
||||||
|
source: context.read<CollectionSource>(),
|
||||||
|
filters: {item.filter},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(route) => false,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
36
lib/widgets/navigation/nav_bar/nav_item.dart
Normal file
36
lib/widgets/navigation/nav_bar/nav_item.dart
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
import 'package:aves/model/filters/filters.dart';
|
||||||
|
import 'package:aves/widgets/collection/collection_page.dart';
|
||||||
|
import 'package:aves/widgets/navigation/drawer/tile.dart';
|
||||||
|
import 'package:aves/widgets/navigation/nav_display.dart';
|
||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class AvesBottomNavItem extends Equatable {
|
||||||
|
final String route;
|
||||||
|
final CollectionFilter? filter;
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [route, filter];
|
||||||
|
|
||||||
|
const AvesBottomNavItem({
|
||||||
|
required this.route,
|
||||||
|
this.filter,
|
||||||
|
});
|
||||||
|
|
||||||
|
Widget icon(BuildContext context) {
|
||||||
|
if (route == CollectionPage.routeName) {
|
||||||
|
return DrawerFilterIcon(filter: filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
final textScaleFactor = MediaQuery.textScaleFactorOf(context);
|
||||||
|
final iconSize = 24 * textScaleFactor;
|
||||||
|
return Icon(NavigationDisplay.getPageIcon(route), size: iconSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
String label(BuildContext context) {
|
||||||
|
if (route == CollectionPage.routeName) {
|
||||||
|
return NavigationDisplay.getFilterTitle(context, filter);
|
||||||
|
}
|
||||||
|
return NavigationDisplay.getPageTitle(context, route);
|
||||||
|
}
|
||||||
|
}
|
59
lib/widgets/navigation/nav_display.dart
Normal file
59
lib/widgets/navigation/nav_display.dart
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
import 'package:aves/model/filters/favourite.dart';
|
||||||
|
import 'package:aves/model/filters/filters.dart';
|
||||||
|
import 'package:aves/model/filters/mime.dart';
|
||||||
|
import 'package:aves/model/filters/type.dart';
|
||||||
|
import 'package:aves/theme/icons.dart';
|
||||||
|
import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||||
|
import 'package:aves/widgets/debug/app_debug_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/tags_page.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/widgets.dart';
|
||||||
|
|
||||||
|
class NavigationDisplay {
|
||||||
|
static String getFilterTitle(BuildContext context, CollectionFilter? filter) {
|
||||||
|
final l10n = context.l10n;
|
||||||
|
if (filter == null) return l10n.drawerCollectionAll;
|
||||||
|
if (filter == FavouriteFilter.instance) return l10n.drawerCollectionFavourites;
|
||||||
|
if (filter == MimeFilter.image) return l10n.drawerCollectionImages;
|
||||||
|
if (filter == MimeFilter.video) return l10n.drawerCollectionVideos;
|
||||||
|
if (filter == TypeFilter.animated) return l10n.drawerCollectionAnimated;
|
||||||
|
if (filter == TypeFilter.motionPhoto) return l10n.drawerCollectionMotionPhotos;
|
||||||
|
if (filter == TypeFilter.panorama) return l10n.drawerCollectionPanoramas;
|
||||||
|
if (filter == TypeFilter.raw) return l10n.drawerCollectionRaws;
|
||||||
|
if (filter == TypeFilter.sphericalVideo) return l10n.drawerCollectionSphericalVideos;
|
||||||
|
return filter.getLabel(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
static String getPageTitle(BuildContext context, route) {
|
||||||
|
final l10n = context.l10n;
|
||||||
|
switch (route) {
|
||||||
|
case AlbumListPage.routeName:
|
||||||
|
return l10n.albumPageTitle;
|
||||||
|
case CountryListPage.routeName:
|
||||||
|
return l10n.countryPageTitle;
|
||||||
|
case TagListPage.routeName:
|
||||||
|
return l10n.tagPageTitle;
|
||||||
|
case AppDebugPage.routeName:
|
||||||
|
return 'Debug';
|
||||||
|
default:
|
||||||
|
return route;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static IconData? getPageIcon(String route) {
|
||||||
|
switch (route) {
|
||||||
|
case AlbumListPage.routeName:
|
||||||
|
return AIcons.album;
|
||||||
|
case CountryListPage.routeName:
|
||||||
|
return AIcons.location;
|
||||||
|
case TagListPage.routeName:
|
||||||
|
return AIcons.tag;
|
||||||
|
case AppDebugPage.routeName:
|
||||||
|
return AIcons.debug;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -31,6 +31,7 @@ class DisplaySection extends SettingsSection {
|
||||||
SettingsTileDisplayThemeBrightness(),
|
SettingsTileDisplayThemeBrightness(),
|
||||||
SettingsTileDisplayThemeColorMode(),
|
SettingsTileDisplayThemeColorMode(),
|
||||||
SettingsTileDisplayDisplayRefreshRateMode(),
|
SettingsTileDisplayDisplayRefreshRateMode(),
|
||||||
|
SettingsTileDisplayEnableBlurEffect(),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,3 +76,15 @@ class SettingsTileDisplayDisplayRefreshRateMode extends SettingsTile {
|
||||||
dialogTitle: context.l10n.settingsDisplayRefreshRateModeTitle,
|
dialogTitle: context.l10n.settingsDisplayRefreshRateModeTitle,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class SettingsTileDisplayEnableBlurEffect extends SettingsTile {
|
||||||
|
@override
|
||||||
|
String title(BuildContext context) => context.l10n.settingsViewerEnableOverlayBlurEffect;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) => SettingsSwitchListTile(
|
||||||
|
selector: (context, s) => s.enableOverlayBlurEffect,
|
||||||
|
onChanged: (v) => settings.enableOverlayBlurEffect = v,
|
||||||
|
title: title(context),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
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/settings/settings.dart';
|
||||||
import 'package:aves/widgets/common/extensions/build_context.dart';
|
import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||||
import 'package:aves/widgets/drawer/app_drawer.dart';
|
|
||||||
import 'package:aves/widgets/drawer/tile.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/tags_page.dart';
|
import 'package:aves/widgets/filter_grids/tags_page.dart';
|
||||||
|
import 'package:aves/widgets/navigation/drawer/app_drawer.dart';
|
||||||
|
import 'package:aves/widgets/navigation/drawer/tile.dart';
|
||||||
import 'package:aves/widgets/search/search_delegate.dart';
|
import 'package:aves/widgets/search/search_delegate.dart';
|
||||||
import 'package:aves/widgets/settings/navigation/drawer_tab_albums.dart';
|
import 'package:aves/widgets/settings/navigation/drawer_tab_albums.dart';
|
||||||
import 'package:aves/widgets/settings/navigation/drawer_tab_fixed.dart';
|
import 'package:aves/widgets/settings/navigation/drawer_tab_fixed.dart';
|
||||||
|
|
|
@ -3,8 +3,8 @@ import 'package:aves/model/source/collection_source.dart';
|
||||||
import 'package:aves/theme/icons.dart';
|
import 'package:aves/theme/icons.dart';
|
||||||
import 'package:aves/widgets/common/extensions/build_context.dart';
|
import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||||
import 'package:aves/widgets/common/identity/buttons.dart';
|
import 'package:aves/widgets/common/identity/buttons.dart';
|
||||||
import 'package:aves/widgets/drawer/tile.dart';
|
|
||||||
import 'package:aves/widgets/filter_grids/album_pick.dart';
|
import 'package:aves/widgets/filter_grids/album_pick.dart';
|
||||||
|
import 'package:aves/widgets/navigation/drawer/tile.dart';
|
||||||
import 'package:aves/widgets/settings/navigation/drawer_editor_banner.dart';
|
import 'package:aves/widgets/settings/navigation/drawer_editor_banner.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
|
@ -31,6 +31,7 @@ class NavigationSection extends SettingsSection {
|
||||||
@override
|
@override
|
||||||
FutureOr<List<SettingsTile>> tiles(BuildContext context) => [
|
FutureOr<List<SettingsTile>> tiles(BuildContext context) => [
|
||||||
SettingsTileNavigationHomePage(),
|
SettingsTileNavigationHomePage(),
|
||||||
|
SettingsTileShowBottomNavigationBar(),
|
||||||
SettingsTileNavigationDrawer(),
|
SettingsTileNavigationDrawer(),
|
||||||
SettingsTileNavigationConfirmationDialog(),
|
SettingsTileNavigationConfirmationDialog(),
|
||||||
SettingsTileNavigationKeepScreenOn(),
|
SettingsTileNavigationKeepScreenOn(),
|
||||||
|
@ -53,6 +54,18 @@ class SettingsTileNavigationHomePage extends SettingsTile {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class SettingsTileShowBottomNavigationBar extends SettingsTile {
|
||||||
|
@override
|
||||||
|
String title(BuildContext context) => context.l10n.settingsShowBottomNavigationBar;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) => SettingsSwitchListTile(
|
||||||
|
selector: (context, s) => s.showBottomNavigationBar,
|
||||||
|
onChanged: (v) => settings.showBottomNavigationBar = v,
|
||||||
|
title: title(context),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
class SettingsTileNavigationDrawer extends SettingsTile {
|
class SettingsTileNavigationDrawer extends SettingsTile {
|
||||||
@override
|
@override
|
||||||
String title(BuildContext context) => context.l10n.settingsNavigationDrawerTile;
|
String title(BuildContext context) => context.l10n.settingsNavigationDrawerTile;
|
||||||
|
|
|
@ -52,11 +52,6 @@ class ViewerOverlayPage extends StatelessWidget {
|
||||||
onChanged: (v) => settings.showOverlayThumbnailPreview = v,
|
onChanged: (v) => settings.showOverlayThumbnailPreview = v,
|
||||||
title: context.l10n.settingsViewerShowOverlayThumbnails,
|
title: context.l10n.settingsViewerShowOverlayThumbnails,
|
||||||
),
|
),
|
||||||
SettingsSwitchListTile(
|
|
||||||
selector: (context, s) => s.enableOverlayBlurEffect,
|
|
||||||
onChanged: (v) => settings.enableOverlayBlurEffect = v,
|
|
||||||
title: context.l10n.settingsViewerEnableOverlayBlurEffect,
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
{
|
{
|
||||||
"de": [
|
"de": [
|
||||||
"settingsSearchFieldLabel",
|
"settingsSearchFieldLabel",
|
||||||
"settingsSearchEmpty"
|
"settingsSearchEmpty",
|
||||||
|
"settingsShowBottomNavigationBar"
|
||||||
],
|
],
|
||||||
|
|
||||||
"es": [
|
"es": [
|
||||||
|
@ -16,22 +17,26 @@
|
||||||
"appPickDialogTitle",
|
"appPickDialogTitle",
|
||||||
"appPickDialogNone",
|
"appPickDialogNone",
|
||||||
"settingsSearchFieldLabel",
|
"settingsSearchFieldLabel",
|
||||||
"settingsSearchEmpty"
|
"settingsSearchEmpty",
|
||||||
|
"settingsShowBottomNavigationBar"
|
||||||
],
|
],
|
||||||
|
|
||||||
"fr": [
|
"fr": [
|
||||||
"settingsSearchFieldLabel",
|
"settingsSearchFieldLabel",
|
||||||
"settingsSearchEmpty"
|
"settingsSearchEmpty",
|
||||||
|
"settingsShowBottomNavigationBar"
|
||||||
],
|
],
|
||||||
|
|
||||||
"id": [
|
"id": [
|
||||||
"settingsSearchFieldLabel",
|
"settingsSearchFieldLabel",
|
||||||
"settingsSearchEmpty"
|
"settingsSearchEmpty",
|
||||||
|
"settingsShowBottomNavigationBar"
|
||||||
],
|
],
|
||||||
|
|
||||||
"it": [
|
"it": [
|
||||||
"settingsSearchFieldLabel",
|
"settingsSearchFieldLabel",
|
||||||
"settingsSearchEmpty"
|
"settingsSearchEmpty",
|
||||||
|
"settingsShowBottomNavigationBar"
|
||||||
],
|
],
|
||||||
|
|
||||||
"ja": [
|
"ja": [
|
||||||
|
@ -46,26 +51,31 @@
|
||||||
"appPickDialogTitle",
|
"appPickDialogTitle",
|
||||||
"appPickDialogNone",
|
"appPickDialogNone",
|
||||||
"settingsSearchFieldLabel",
|
"settingsSearchFieldLabel",
|
||||||
"settingsSearchEmpty"
|
"settingsSearchEmpty",
|
||||||
|
"settingsShowBottomNavigationBar"
|
||||||
],
|
],
|
||||||
|
|
||||||
"ko": [
|
"ko": [
|
||||||
"settingsSearchFieldLabel",
|
"settingsSearchFieldLabel",
|
||||||
"settingsSearchEmpty"
|
"settingsSearchEmpty",
|
||||||
|
"settingsShowBottomNavigationBar"
|
||||||
],
|
],
|
||||||
|
|
||||||
"pt": [
|
"pt": [
|
||||||
"settingsSearchFieldLabel",
|
"settingsSearchFieldLabel",
|
||||||
"settingsSearchEmpty"
|
"settingsSearchEmpty",
|
||||||
|
"settingsShowBottomNavigationBar"
|
||||||
],
|
],
|
||||||
|
|
||||||
"ru": [
|
"ru": [
|
||||||
"settingsSearchFieldLabel",
|
"settingsSearchFieldLabel",
|
||||||
"settingsSearchEmpty"
|
"settingsSearchEmpty",
|
||||||
|
"settingsShowBottomNavigationBar"
|
||||||
],
|
],
|
||||||
|
|
||||||
"zh": [
|
"zh": [
|
||||||
"settingsSearchFieldLabel",
|
"settingsSearchFieldLabel",
|
||||||
"settingsSearchEmpty"
|
"settingsSearchEmpty",
|
||||||
|
"settingsShowBottomNavigationBar"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue