#437 tv: filter app bar
This commit is contained in:
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 |
|
@ -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,
|
||||
|
|
|
@ -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)),
|
||||
);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue