#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: [
|
children: [
|
||||||
if (isTelevision)
|
if (isTelevision)
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: tvActionButtonHeight,
|
height: ActionButton.getTelevisionButtonHeight(context),
|
||||||
child: ListView(
|
child: ListView(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||||
scrollDirection: Axis.horizontal,
|
scrollDirection: Axis.horizontal,
|
||||||
|
@ -197,7 +197,7 @@ class _CollectionAppBarState extends State<CollectionAppBar> with SingleTickerPr
|
||||||
EntryQueryBar(
|
EntryQueryBar(
|
||||||
queryNotifier: context.select<Query, ValueNotifier<String>>((query) => query.queryNotifier),
|
queryNotifier: context.select<Query, ValueNotifier<String>>((query) => query.queryNotifier),
|
||||||
focusNode: _queryBarFocusNode,
|
focusNode: _queryBarFocusNode,
|
||||||
)
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
transitionKey: isSelecting,
|
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 get appBarContentHeight {
|
||||||
double height = kToolbarHeight;
|
double height = kToolbarHeight;
|
||||||
if (device.isTelevision) {
|
if (device.isTelevision) {
|
||||||
height += tvActionButtonHeight;
|
height += ActionButton.getTelevisionButtonHeight(context);
|
||||||
}
|
}
|
||||||
if (showFilterBar) {
|
if (showFilterBar) {
|
||||||
height += FilterBar.preferredHeight;
|
height += FilterBar.preferredHeight;
|
||||||
|
@ -318,12 +309,14 @@ class _CollectionAppBarState extends State<CollectionAppBar> with SingleTickerPr
|
||||||
|
|
||||||
return device.isTelevision
|
return device.isTelevision
|
||||||
? _buildTelevisionActions(
|
? _buildTelevisionActions(
|
||||||
|
context: context,
|
||||||
appMode: appMode,
|
appMode: appMode,
|
||||||
selection: selection,
|
selection: selection,
|
||||||
isVisible: isVisible,
|
isVisible: isVisible,
|
||||||
canApply: canApply,
|
canApply: canApply,
|
||||||
)
|
)
|
||||||
: _buildMobileActions(
|
: _buildMobileActions(
|
||||||
|
context: context,
|
||||||
appMode: appMode,
|
appMode: appMode,
|
||||||
selection: selection,
|
selection: selection,
|
||||||
isVisible: isVisible,
|
isVisible: isVisible,
|
||||||
|
@ -332,6 +325,7 @@ class _CollectionAppBarState extends State<CollectionAppBar> with SingleTickerPr
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Widget> _buildTelevisionActions({
|
List<Widget> _buildTelevisionActions({
|
||||||
|
required BuildContext context,
|
||||||
required AppMode appMode,
|
required AppMode appMode,
|
||||||
required Selection<AvesEntry> selection,
|
required Selection<AvesEntry> selection,
|
||||||
required bool Function(EntrySetAction action) isVisible,
|
required bool Function(EntrySetAction action) isVisible,
|
||||||
|
@ -344,16 +338,18 @@ class _CollectionAppBarState extends State<CollectionAppBar> with SingleTickerPr
|
||||||
...isSelecting ? EntrySetActions.pageSelection : EntrySetActions.pageBrowsing,
|
...isSelecting ? EntrySetActions.pageSelection : EntrySetActions.pageBrowsing,
|
||||||
].where(isVisible).map((action) {
|
].where(isVisible).map((action) {
|
||||||
// TODO TLAD [tv] togglers cf `_toIconActionButton`
|
// TODO TLAD [tv] togglers cf `_toIconActionButton`
|
||||||
|
final enabled = canApply(action);
|
||||||
return ActionButton(
|
return ActionButton(
|
||||||
text: action.getText(context),
|
text: action.getText(context),
|
||||||
icon: action.getIcon(),
|
icon: action.getIcon(),
|
||||||
enabled: canApply(action),
|
enabled: enabled,
|
||||||
onPressed: canApply(action) ? () => _onActionSelected(action) : null,
|
onPressed: enabled ? () => _onActionSelected(action) : null,
|
||||||
);
|
);
|
||||||
}).toList();
|
}).toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Widget> _buildMobileActions({
|
List<Widget> _buildMobileActions({
|
||||||
|
required BuildContext context,
|
||||||
required AppMode appMode,
|
required AppMode appMode,
|
||||||
required Selection<AvesEntry> selection,
|
required Selection<AvesEntry> selection,
|
||||||
required bool Function(EntrySetAction action) isVisible,
|
required bool Function(EntrySetAction action) isVisible,
|
||||||
|
|
|
@ -2,6 +2,7 @@ import 'dart:async';
|
||||||
|
|
||||||
import 'package:aves/app_mode.dart';
|
import 'package:aves/app_mode.dart';
|
||||||
import 'package:aves/model/actions/chip_set_actions.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/filters/filters.dart';
|
||||||
import 'package:aves/model/query.dart';
|
import 'package:aves/model/query.dart';
|
||||||
import 'package:aves/model/selection.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/action_delegates/chip_set.dart';
|
||||||
import 'package:aves/widgets/filter_grids/common/query_bar.dart';
|
import 'package:aves/widgets/filter_grids/common/query_bar.dart';
|
||||||
import 'package:aves/widgets/search/search_delegate.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/material.dart';
|
||||||
import 'package:flutter/scheduler.dart';
|
import 'package:flutter/scheduler.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
@ -125,6 +127,8 @@ class _FilterGridAppBarState<T extends CollectionFilter, CSAD extends ChipSetAct
|
||||||
selector: (context, query) => query.enabled,
|
selector: (context, query) => query.enabled,
|
||||||
builder: (context, queryEnabled, child) {
|
builder: (context, queryEnabled, child) {
|
||||||
ActionsBuilder<T, CSAD> actionsBuilder = widget.actionsBuilder ?? _buildActions;
|
ActionsBuilder<T, CSAD> actionsBuilder = widget.actionsBuilder ?? _buildActions;
|
||||||
|
final isTelevision = device.isTelevision;
|
||||||
|
final actions = actionsBuilder(context, appMode, selection, widget.actionDelegate);
|
||||||
return AvesAppBar(
|
return AvesAppBar(
|
||||||
contentHeight: appBarContentHeight,
|
contentHeight: appBarContentHeight,
|
||||||
leading: _buildAppBarLeading(
|
leading: _buildAppBarLeading(
|
||||||
|
@ -132,13 +136,25 @@ class _FilterGridAppBarState<T extends CollectionFilter, CSAD extends ChipSetAct
|
||||||
isSelecting: isSelecting,
|
isSelecting: isSelecting,
|
||||||
),
|
),
|
||||||
title: _buildAppBarTitle(isSelecting),
|
title: _buildAppBarTitle(isSelecting),
|
||||||
actions: actionsBuilder(context, appMode, selection, widget.actionDelegate),
|
actions: isTelevision ? [] : actions,
|
||||||
bottom: queryEnabled
|
bottom: Column(
|
||||||
? FilterQueryBar<T>(
|
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),
|
queryNotifier: context.select<Query, ValueNotifier<String>>((query) => query.queryNotifier),
|
||||||
focusNode: _queryBarFocusNode,
|
focusNode: _queryBarFocusNode,
|
||||||
)
|
),
|
||||||
: null,
|
],
|
||||||
|
),
|
||||||
transitionKey: isSelecting,
|
transitionKey: isSelecting,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -146,11 +162,19 @@ class _FilterGridAppBarState<T extends CollectionFilter, CSAD extends ChipSetAct
|
||||||
}
|
}
|
||||||
|
|
||||||
double get appBarContentHeight {
|
double get appBarContentHeight {
|
||||||
final hasQuery = context.read<Query>().enabled;
|
double height = kToolbarHeight;
|
||||||
return kToolbarHeight + (hasQuery ? FilterQueryBar.preferredHeight : .0);
|
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) {
|
if (!hasDrawer) {
|
||||||
return const CloseButton();
|
return const CloseButton();
|
||||||
}
|
}
|
||||||
|
@ -225,6 +249,56 @@ class _FilterGridAppBarState<T extends CollectionFilter, CSAD extends ChipSetAct
|
||||||
selectedFilters: selectedFilters,
|
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(
|
final quickActionButtons = (isSelecting ? selectionQuickActions : browsingQuickActions).where(isVisible).map(
|
||||||
(action) => _toActionButton(context, actionDelegate, action, enabled: canApply(action)),
|
(action) => _toActionButton(context, actionDelegate, action, enabled: canApply(action)),
|
||||||
);
|
);
|
||||||
|
|
|
@ -70,4 +70,9 @@ class ActionButton extends StatelessWidget {
|
||||||
}
|
}
|
||||||
return Size(width, height);
|
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