#437 tv: filter app bar

This commit is contained in:
Thibault Deckers 2022-12-13 21:02:58 +01:00
parent 6c71752f18
commit 163056bd84
4 changed files with 97 additions and 22 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.7 KiB

After

Width:  |  Height:  |  Size: 6.9 KiB

View file

@ -174,7 +174,7 @@ class _CollectionAppBarState extends State<CollectionAppBar> 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<CollectionAppBar> with SingleTickerPr
EntryQueryBar(
queryNotifier: context.select<Query, ValueNotifier<String>>((query) => query.queryNotifier),
focusNode: _queryBarFocusNode,
)
),
],
),
transitionKey: isSelecting,
@ -210,19 +210,10 @@ class _CollectionAppBarState extends State<CollectionAppBar> 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<CollectionAppBar> 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<CollectionAppBar> with SingleTickerPr
}
List<Widget> _buildTelevisionActions({
required BuildContext context,
required AppMode appMode,
required Selection<AvesEntry> selection,
required bool Function(EntrySetAction action) isVisible,
@ -344,16 +338,18 @@ class _CollectionAppBarState extends State<CollectionAppBar> 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<Widget> _buildMobileActions({
required BuildContext context,
required AppMode appMode,
required Selection<AvesEntry> selection,
required bool Function(EntrySetAction action) isVisible,

View file

@ -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<T extends CollectionFilter, CSAD extends ChipSetAct
selector: (context, query) => query.enabled,
builder: (context, queryEnabled, child) {
ActionsBuilder<T, CSAD> 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<T extends CollectionFilter, CSAD extends ChipSetAct
isSelecting: isSelecting,
),
title: _buildAppBarTitle(isSelecting),
actions: actionsBuilder(context, appMode, selection, widget.actionDelegate),
bottom: queryEnabled
? FilterQueryBar<T>(
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<T>(
queryNotifier: context.select<Query, ValueNotifier<String>>((query) => query.queryNotifier),
focusNode: _queryBarFocusNode,
)
: null,
),
],
),
transitionKey: isSelecting,
);
},
@ -146,11 +162,19 @@ class _FilterGridAppBarState<T extends CollectionFilter, CSAD extends ChipSetAct
}
double get appBarContentHeight {
final hasQuery = context.read<Query>().enabled;
return kToolbarHeight + (hasQuery ? FilterQueryBar.preferredHeight : .0);
double height = kToolbarHeight;
if (device.isTelevision) {
height += ActionButton.getTelevisionButtonHeight(context);
}
if (context.read<Query>().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<T extends CollectionFilter, CSAD extends ChipSetAct
selectedFilters: selectedFilters,
);
return device.isTelevision
? _buildTelevisionActions(
context: context,
selection: selection,
isVisible: isVisible,
canApply: canApply,
actionDelegate: actionDelegate,
)
: _buildMobileActions(
context: context,
selection: selection,
isVisible: isVisible,
canApply: canApply,
actionDelegate: actionDelegate,
);
}
List<Widget> _buildTelevisionActions({
required BuildContext context,
required Selection<FilterGridItem<T>> 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<Widget> _buildMobileActions({
required BuildContext context,
required Selection<FilterGridItem<T>> 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)),
);

View file

@ -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;
}
}