diff --git a/android/app/src/main/res/drawable-nodpi/banner.png b/android/app/src/main/res/drawable-nodpi/banner.png index 271aa70c9..c33433d6c 100644 Binary files a/android/app/src/main/res/drawable-nodpi/banner.png and b/android/app/src/main/res/drawable-nodpi/banner.png differ diff --git a/lib/widgets/collection/app_bar.dart b/lib/widgets/collection/app_bar.dart index eec20b726..a05caa289 100644 --- a/lib/widgets/collection/app_bar.dart +++ b/lib/widgets/collection/app_bar.dart @@ -174,7 +174,7 @@ class _CollectionAppBarState extends State with SingleTickerPr children: [ if (isTelevision) SizedBox( - height: tvActionButtonHeight, + height: ActionButton.getTelevisionButtonHeight(context), child: ListView( padding: const EdgeInsets.symmetric(horizontal: 8), scrollDirection: Axis.horizontal, @@ -197,7 +197,7 @@ class _CollectionAppBarState extends State with SingleTickerPr EntryQueryBar( queryNotifier: context.select>((query) => query.queryNotifier), focusNode: _queryBarFocusNode, - ) + ), ], ), transitionKey: isSelecting, @@ -210,19 +210,10 @@ class _CollectionAppBarState extends State with SingleTickerPr ); } - double get tvActionButtonHeight { - final text = [ - ...EntrySetActions.general, - ...EntrySetActions.pageBrowsing, - ...EntrySetActions.pageSelection, - ].map((action) => action.getText(context)).fold('', (prev, v) => v.length > prev.length ? v : prev); - return ActionButton.getSize(context, text, showCaption: true).height; - } - double get appBarContentHeight { double height = kToolbarHeight; if (device.isTelevision) { - height += tvActionButtonHeight; + height += ActionButton.getTelevisionButtonHeight(context); } if (showFilterBar) { height += FilterBar.preferredHeight; @@ -318,12 +309,14 @@ class _CollectionAppBarState extends State with SingleTickerPr return device.isTelevision ? _buildTelevisionActions( + context: context, appMode: appMode, selection: selection, isVisible: isVisible, canApply: canApply, ) : _buildMobileActions( + context: context, appMode: appMode, selection: selection, isVisible: isVisible, @@ -332,6 +325,7 @@ class _CollectionAppBarState extends State with SingleTickerPr } List _buildTelevisionActions({ + required BuildContext context, required AppMode appMode, required Selection selection, required bool Function(EntrySetAction action) isVisible, @@ -344,16 +338,18 @@ class _CollectionAppBarState extends State with SingleTickerPr ...isSelecting ? EntrySetActions.pageSelection : EntrySetActions.pageBrowsing, ].where(isVisible).map((action) { // TODO TLAD [tv] togglers cf `_toIconActionButton` + final enabled = canApply(action); return ActionButton( text: action.getText(context), icon: action.getIcon(), - enabled: canApply(action), - onPressed: canApply(action) ? () => _onActionSelected(action) : null, + enabled: enabled, + onPressed: enabled ? () => _onActionSelected(action) : null, ); }).toList(); } List _buildMobileActions({ + required BuildContext context, required AppMode appMode, required Selection selection, required bool Function(EntrySetAction action) isVisible, diff --git a/lib/widgets/filter_grids/common/app_bar.dart b/lib/widgets/filter_grids/common/app_bar.dart index 1beed106f..84dad963b 100644 --- a/lib/widgets/filter_grids/common/app_bar.dart +++ b/lib/widgets/filter_grids/common/app_bar.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'package:aves/app_mode.dart'; import 'package:aves/model/actions/chip_set_actions.dart'; +import 'package:aves/model/device.dart'; import 'package:aves/model/filters/filters.dart'; import 'package:aves/model/query.dart'; import 'package:aves/model/selection.dart'; @@ -17,6 +18,7 @@ import 'package:aves/widgets/common/search/route.dart'; import 'package:aves/widgets/filter_grids/common/action_delegates/chip_set.dart'; import 'package:aves/widgets/filter_grids/common/query_bar.dart'; import 'package:aves/widgets/search/search_delegate.dart'; +import 'package:aves/widgets/settings/common/quick_actions/action_button.dart'; import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart'; import 'package:provider/provider.dart'; @@ -125,6 +127,8 @@ class _FilterGridAppBarState query.enabled, builder: (context, queryEnabled, child) { ActionsBuilder actionsBuilder = widget.actionsBuilder ?? _buildActions; + final isTelevision = device.isTelevision; + final actions = actionsBuilder(context, appMode, selection, widget.actionDelegate); return AvesAppBar( contentHeight: appBarContentHeight, leading: _buildAppBarLeading( @@ -132,13 +136,25 @@ class _FilterGridAppBarState( + actions: isTelevision ? [] : actions, + bottom: Column( + children: [ + if (isTelevision) + SizedBox( + height: ActionButton.getTelevisionButtonHeight(context), + child: ListView( + padding: const EdgeInsets.symmetric(horizontal: 8), + scrollDirection: Axis.horizontal, + children: actions, + ), + ), + if (queryEnabled) + FilterQueryBar( queryNotifier: context.select>((query) => query.queryNotifier), focusNode: _queryBarFocusNode, - ) - : null, + ), + ], + ), transitionKey: isSelecting, ); }, @@ -146,11 +162,19 @@ class _FilterGridAppBarState().enabled; - return kToolbarHeight + (hasQuery ? FilterQueryBar.preferredHeight : .0); + double height = kToolbarHeight; + if (device.isTelevision) { + height += ActionButton.getTelevisionButtonHeight(context); + } + if (context.read().enabled) { + height += FilterQueryBar.preferredHeight; + } + return height; } - Widget _buildAppBarLeading({required bool hasDrawer, required bool isSelecting}) { + Widget? _buildAppBarLeading({required bool hasDrawer, required bool isSelecting}) { + if (device.isTelevision) return null; + if (!hasDrawer) { return const CloseButton(); } @@ -225,6 +249,56 @@ class _FilterGridAppBarState _buildTelevisionActions({ + required BuildContext context, + required Selection> selection, + required bool Function(ChipSetAction action) isVisible, + required bool Function(ChipSetAction action) canApply, + required CSAD actionDelegate, + }) { + final isSelecting = selection.isSelecting; + + return [ + ...ChipSetActions.general, + ...isSelecting ? ChipSetActions.selection : ChipSetActions.browsing, + ].where(isVisible).map((action) { + // TODO TLAD [tv] togglers cf `FilterGridAppBar.toMenuItem` + final enabled = canApply(action); + return ActionButton( + text: action.getText(context), + icon: action.getIcon(), + enabled: enabled, + onPressed: enabled ? () => _onActionSelected(context, action, actionDelegate) : null, + ); + }).toList(); + } + + List _buildMobileActions({ + required BuildContext context, + required Selection> selection, + required bool Function(ChipSetAction action) isVisible, + required bool Function(ChipSetAction action) canApply, + required CSAD actionDelegate, + }) { + final isSelecting = selection.isSelecting; + final quickActionButtons = (isSelecting ? selectionQuickActions : browsingQuickActions).where(isVisible).map( (action) => _toActionButton(context, actionDelegate, action, enabled: canApply(action)), ); diff --git a/lib/widgets/settings/common/quick_actions/action_button.dart b/lib/widgets/settings/common/quick_actions/action_button.dart index fc7962b3c..49ffc0a48 100644 --- a/lib/widgets/settings/common/quick_actions/action_button.dart +++ b/lib/widgets/settings/common/quick_actions/action_button.dart @@ -70,4 +70,9 @@ class ActionButton extends StatelessWidget { } return Size(width, height); } + + static double getTelevisionButtonHeight(BuildContext context) { + final text = 'whatever' * 42; + return ActionButton.getSize(context, text, showCaption: true).height; + } }