#559 fixes for font scale
This commit is contained in:
parent
c6230df01d
commit
07e13bc8ac
18 changed files with 257 additions and 209 deletions
|
@ -23,7 +23,6 @@ import 'package:aves/widgets/common/action_controls/togglers/favourite.dart';
|
||||||
import 'package:aves/widgets/common/action_controls/togglers/title_search.dart';
|
import 'package:aves/widgets/common/action_controls/togglers/title_search.dart';
|
||||||
import 'package:aves/widgets/common/app_bar/app_bar_subtitle.dart';
|
import 'package:aves/widgets/common/app_bar/app_bar_subtitle.dart';
|
||||||
import 'package:aves/widgets/common/app_bar/app_bar_title.dart';
|
import 'package:aves/widgets/common/app_bar/app_bar_title.dart';
|
||||||
import 'package:aves/widgets/common/basic/font_size_icon_theme.dart';
|
|
||||||
import 'package:aves/widgets/common/basic/popup/container.dart';
|
import 'package:aves/widgets/common/basic/popup/container.dart';
|
||||||
import 'package:aves/widgets/common/basic/popup/expansion_panel.dart';
|
import 'package:aves/widgets/common/basic/popup/expansion_panel.dart';
|
||||||
import 'package:aves/widgets/common/basic/popup/menu_row.dart';
|
import 'package:aves/widgets/common/basic/popup/menu_row.dart';
|
||||||
|
@ -145,7 +144,12 @@ class _CollectionAppBarState extends State<CollectionAppBar> with SingleTickerPr
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void didChangeMetrics() => _updateStatusBarHeight();
|
void didChangeMetrics() {
|
||||||
|
// when top padding changes
|
||||||
|
_updateStatusBarHeight();
|
||||||
|
// when text scale factor changes
|
||||||
|
_updateAppBarHeight();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
@ -377,15 +381,12 @@ class _CollectionAppBarState extends State<CollectionAppBar> with SingleTickerPr
|
||||||
final browsingQuickActions = settings.collectionBrowsingQuickActions;
|
final browsingQuickActions = settings.collectionBrowsingQuickActions;
|
||||||
final selectionQuickActions = isTrash ? [EntrySetAction.delete, EntrySetAction.restore] : settings.collectionSelectionQuickActions;
|
final selectionQuickActions = isTrash ? [EntrySetAction.delete, EntrySetAction.restore] : settings.collectionSelectionQuickActions;
|
||||||
final quickActionButtons = (isSelecting ? selectionQuickActions : browsingQuickActions).where(isVisible).map(
|
final quickActionButtons = (isSelecting ? selectionQuickActions : browsingQuickActions).where(isVisible).map(
|
||||||
(action) => FontSizeIconTheme(
|
(action) => _buildButtonIcon(context, action, enabled: canApply(action), selection: selection),
|
||||||
child: _buildButtonIcon(context, action, enabled: canApply(action), selection: selection),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return [
|
return [
|
||||||
...quickActionButtons,
|
...quickActionButtons,
|
||||||
FontSizeIconTheme(
|
PopupMenuButton<EntrySetAction>(
|
||||||
child: PopupMenuButton<EntrySetAction>(
|
|
||||||
// key is expected by test driver
|
// key is expected by test driver
|
||||||
key: const Key('appbar-menu-button'),
|
key: const Key('appbar-menu-button'),
|
||||||
itemBuilder: (context) {
|
itemBuilder: (context) {
|
||||||
|
@ -437,7 +438,6 @@ class _CollectionAppBarState extends State<CollectionAppBar> with SingleTickerPr
|
||||||
await _onActionSelected(action);
|
await _onActionSelected(action);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -299,6 +299,18 @@ class _CollectionSectionedContentState extends State<_CollectionSectionedContent
|
||||||
|
|
||||||
ScrollController get scrollController => widget.scrollController;
|
ScrollController get scrollController => widget.scrollController;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_appBarHeightNotifier.addListener(_onAppBarHeightChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_appBarHeightNotifier.removeListener(_onAppBarHeightChanged);
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final scrollView = AnimationLimiter(
|
final scrollView = AnimationLimiter(
|
||||||
|
@ -339,6 +351,8 @@ class _CollectionSectionedContentState extends State<_CollectionSectionedContent
|
||||||
child: selector,
|
child: selector,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _onAppBarHeightChanged() => setState(() {});
|
||||||
}
|
}
|
||||||
|
|
||||||
class _CollectionScaler extends StatelessWidget {
|
class _CollectionScaler extends StatelessWidget {
|
||||||
|
@ -485,7 +499,7 @@ class _CollectionScrollViewState extends State<_CollectionScrollView> with Widge
|
||||||
return settings.useTvLayout ? scrollView : _buildDraggableScrollView(scrollView, widget.collection);
|
return settings.useTvLayout ? scrollView : _buildDraggableScrollView(scrollView, widget.collection);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildDraggableScrollView(ScrollView scrollView, CollectionLens collection) {
|
Widget _buildDraggableScrollView(Widget scrollView, CollectionLens collection) {
|
||||||
return ValueListenableBuilder<double>(
|
return ValueListenableBuilder<double>(
|
||||||
valueListenable: widget.appBarHeightNotifier,
|
valueListenable: widget.appBarHeightNotifier,
|
||||||
builder: (context, appBarHeight, child) {
|
builder: (context, appBarHeight, child) {
|
||||||
|
@ -550,7 +564,7 @@ class _CollectionScrollViewState extends State<_CollectionScrollView> with Widge
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
ScrollView _buildScrollView(Widget appBar, CollectionLens collection) {
|
Widget _buildScrollView(Widget appBar, CollectionLens collection) {
|
||||||
return CustomScrollView(
|
return CustomScrollView(
|
||||||
key: widget.scrollableKey,
|
key: widget.scrollableKey,
|
||||||
primary: true,
|
primary: true,
|
||||||
|
|
|
@ -62,9 +62,9 @@ class DraggableScrollbar extends StatefulWidget {
|
||||||
final double Function(double scrollOffset, double offsetIncrement)? dragOffsetSnapper;
|
final double Function(double scrollOffset, double offsetIncrement)? dragOffsetSnapper;
|
||||||
|
|
||||||
/// The view that will be scrolled with the scroll thumb
|
/// The view that will be scrolled with the scroll thumb
|
||||||
final ScrollView child;
|
final Widget child;
|
||||||
|
|
||||||
DraggableScrollbar({
|
const DraggableScrollbar({
|
||||||
super.key,
|
super.key,
|
||||||
required this.backgroundColor,
|
required this.backgroundColor,
|
||||||
required this.scrollThumbSize,
|
required this.scrollThumbSize,
|
||||||
|
@ -78,7 +78,7 @@ class DraggableScrollbar extends StatefulWidget {
|
||||||
required this.labelTextBuilder,
|
required this.labelTextBuilder,
|
||||||
required this.crumbTextBuilder,
|
required this.crumbTextBuilder,
|
||||||
required this.child,
|
required this.child,
|
||||||
}) : assert(child.scrollDirection == Axis.vertical);
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<DraggableScrollbar> createState() => _DraggableScrollbarState();
|
State<DraggableScrollbar> createState() => _DraggableScrollbarState();
|
||||||
|
|
|
@ -25,8 +25,6 @@ class _WheelSelectorState<T> extends State<WheelSelector<T>> {
|
||||||
late final FixedExtentScrollController _controller;
|
late final FixedExtentScrollController _controller;
|
||||||
final ValueNotifier<bool> _focusedNotifier = ValueNotifier(false);
|
final ValueNotifier<bool> _focusedNotifier = ValueNotifier(false);
|
||||||
|
|
||||||
static const itemSize = Size(40, 40);
|
|
||||||
|
|
||||||
ValueNotifier<T> get valueNotifier => widget.valueNotifier;
|
ValueNotifier<T> get valueNotifier => widget.valueNotifier;
|
||||||
|
|
||||||
List<T> get values => widget.values;
|
List<T> get values => widget.values;
|
||||||
|
@ -51,6 +49,7 @@ class _WheelSelectorState<T> extends State<WheelSelector<T>> {
|
||||||
const background = Colors.transparent;
|
const background = Colors.transparent;
|
||||||
final foreground = DefaultTextStyle.of(context).style.color!;
|
final foreground = DefaultTextStyle.of(context).style.color!;
|
||||||
final transitionDuration = context.select<DurationsData, Duration>((v) => v.formTransition);
|
final transitionDuration = context.select<DurationsData, Duration>((v) => v.formTransition);
|
||||||
|
final itemSize = Size.square(40 * context.select<MediaQueryData, double>((mq) => mq.textScaleFactor));
|
||||||
|
|
||||||
return FocusableActionDetector(
|
return FocusableActionDetector(
|
||||||
shortcuts: const {
|
shortcuts: const {
|
||||||
|
|
|
@ -130,7 +130,7 @@ class SectionHeader<T> extends StatelessWidget {
|
||||||
final para = RenderParagraph(
|
final para = RenderParagraph(
|
||||||
TextSpan(
|
TextSpan(
|
||||||
children: [
|
children: [
|
||||||
// as of Flutter v2.8.1, `RenderParagraph` fails to lay out `WidgetSpan` offscreen
|
// as of Flutter v3.7.7, `RenderParagraph` fails to lay out `WidgetSpan` offscreen
|
||||||
// so we use a hair space times a magic number to match width
|
// so we use a hair space times a magic number to match width
|
||||||
TextSpan(
|
TextSpan(
|
||||||
// 23 hair spaces match a width of 40.0
|
// 23 hair spaces match a width of 40.0
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import 'package:aves/model/settings/settings.dart';
|
import 'package:aves/model/settings/settings.dart';
|
||||||
import 'package:aves/theme/durations.dart';
|
import 'package:aves/theme/durations.dart';
|
||||||
import 'package:aves/widgets/aves_app.dart';
|
import 'package:aves/widgets/aves_app.dart';
|
||||||
|
import 'package:aves/widgets/common/basic/font_size_icon_theme.dart';
|
||||||
import 'package:aves/widgets/common/basic/insets.dart';
|
import 'package:aves/widgets/common/basic/insets.dart';
|
||||||
import 'package:aves/widgets/common/fx/blurred.dart';
|
import 'package:aves/widgets/common/fx/blurred.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
@ -65,8 +66,10 @@ class AvesAppBar extends StatelessWidget {
|
||||||
tag: leadingHeroTag,
|
tag: leadingHeroTag,
|
||||||
flightShuttleBuilder: _flightShuttleBuilder,
|
flightShuttleBuilder: _flightShuttleBuilder,
|
||||||
transitionOnUserGestures: true,
|
transitionOnUserGestures: true,
|
||||||
|
child: FontSizeIconTheme(
|
||||||
child: leading!,
|
child: leading!,
|
||||||
),
|
),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
: const SizedBox(width: 16),
|
: const SizedBox(width: 16),
|
||||||
Expanded(
|
Expanded(
|
||||||
|
@ -78,6 +81,7 @@ class AvesAppBar extends StatelessWidget {
|
||||||
transitionOnUserGestures: true,
|
transitionOnUserGestures: true,
|
||||||
child: AnimatedSwitcher(
|
child: AnimatedSwitcher(
|
||||||
duration: context.read<DurationsData>().iconAnimation,
|
duration: context.read<DurationsData>().iconAnimation,
|
||||||
|
child: FontSizeIconTheme(
|
||||||
child: Row(
|
child: Row(
|
||||||
key: ValueKey(transitionKey),
|
key: ValueKey(transitionKey),
|
||||||
children: [
|
children: [
|
||||||
|
@ -89,6 +93,7 @@ class AvesAppBar extends StatelessWidget {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -13,7 +13,6 @@ import 'package:aves/model/vaults/details.dart';
|
||||||
import 'package:aves/model/vaults/vaults.dart';
|
import 'package:aves/model/vaults/vaults.dart';
|
||||||
import 'package:aves/theme/durations.dart';
|
import 'package:aves/theme/durations.dart';
|
||||||
import 'package:aves/theme/icons.dart';
|
import 'package:aves/theme/icons.dart';
|
||||||
import 'package:aves/widgets/common/basic/font_size_icon_theme.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/aves_filter_chip.dart';
|
import 'package:aves/widgets/common/identity/aves_filter_chip.dart';
|
||||||
import 'package:aves/widgets/common/identity/buttons/captioned_button.dart';
|
import 'package:aves/widgets/common/identity/buttons/captioned_button.dart';
|
||||||
|
@ -210,16 +209,13 @@ class _AlbumPickPageState extends State<_AlbumPickPage> {
|
||||||
return [
|
return [
|
||||||
if (widget.moveType != null)
|
if (widget.moveType != null)
|
||||||
..._quickActions.where(isVisible).map(
|
..._quickActions.where(isVisible).map(
|
||||||
(action) => FontSizeIconTheme(
|
(action) => IconButton(
|
||||||
child: IconButton(
|
|
||||||
icon: action.getIcon(),
|
icon: action.getIcon(),
|
||||||
onPressed: () => onActionSelected(action),
|
onPressed: () => onActionSelected(action),
|
||||||
tooltip: action.getText(context),
|
tooltip: action.getText(context),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
PopupMenuButton<ChipSetAction>(
|
||||||
FontSizeIconTheme(
|
|
||||||
child: PopupMenuButton<ChipSetAction>(
|
|
||||||
itemBuilder: (context) {
|
itemBuilder: (context) {
|
||||||
return _menuActions.where((v) => v == null || isVisible(v)).map((action) {
|
return _menuActions.where((v) => v == null || isVisible(v)).map((action) {
|
||||||
if (action == null) return const PopupMenuDivider();
|
if (action == null) return const PopupMenuDivider();
|
||||||
|
@ -236,7 +232,6 @@ class _AlbumPickPageState extends State<_AlbumPickPage> {
|
||||||
onActionSelected(action);
|
onActionSelected(action);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ import 'package:aves/model/settings/settings.dart';
|
||||||
import 'package:aves/theme/durations.dart';
|
import 'package:aves/theme/durations.dart';
|
||||||
import 'package:aves/theme/icons.dart';
|
import 'package:aves/theme/icons.dart';
|
||||||
import 'package:aves/theme/themes.dart';
|
import 'package:aves/theme/themes.dart';
|
||||||
|
import 'package:aves/widgets/common/basic/font_size_icon_theme.dart';
|
||||||
import 'package:aves/widgets/common/basic/text_dropdown_button.dart';
|
import 'package:aves/widgets/common/basic/text_dropdown_button.dart';
|
||||||
import 'package:aves/widgets/common/extensions/build_context.dart';
|
import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||||
import 'package:aves/widgets/common/fx/transitions.dart';
|
import 'package:aves/widgets/common/fx/transitions.dart';
|
||||||
|
@ -168,6 +169,7 @@ class _TileViewDialogState<S, G, L> extends State<TileViewDialog<S, G, L>> with
|
||||||
|
|
||||||
final label = ConstrainedBox(
|
final label = ConstrainedBox(
|
||||||
constraints: const BoxConstraints(minHeight: kMinInteractiveDimension),
|
constraints: const BoxConstraints(minHeight: kMinInteractiveDimension),
|
||||||
|
child: FontSizeIconTheme(
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
Icon(icon),
|
Icon(icon),
|
||||||
|
@ -181,6 +183,7 @@ class _TileViewDialogState<S, G, L> extends State<TileViewDialog<S, G, L>> with
|
||||||
if (trailing != null) trailing,
|
if (trailing != null) trailing,
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
final selector = TextDropdownButton<T>(
|
final selector = TextDropdownButton<T>(
|
||||||
values: options.map((v) => v.value).toList(),
|
values: options.map((v) => v.value).toList(),
|
||||||
|
|
|
@ -11,7 +11,6 @@ import 'package:aves/theme/durations.dart';
|
||||||
import 'package:aves/widgets/common/action_controls/togglers/title_search.dart';
|
import 'package:aves/widgets/common/action_controls/togglers/title_search.dart';
|
||||||
import 'package:aves/widgets/common/app_bar/app_bar_subtitle.dart';
|
import 'package:aves/widgets/common/app_bar/app_bar_subtitle.dart';
|
||||||
import 'package:aves/widgets/common/app_bar/app_bar_title.dart';
|
import 'package:aves/widgets/common/app_bar/app_bar_title.dart';
|
||||||
import 'package:aves/widgets/common/basic/font_size_icon_theme.dart';
|
|
||||||
import 'package:aves/widgets/common/basic/popup/menu_row.dart';
|
import 'package:aves/widgets/common/basic/popup/menu_row.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/aves_app_bar.dart';
|
import 'package:aves/widgets/common/identity/aves_app_bar.dart';
|
||||||
|
@ -75,7 +74,7 @@ class FilterGridAppBar<T extends CollectionFilter, CSAD extends ChipSetActionDel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _FilterGridAppBarState<T extends CollectionFilter, CSAD extends ChipSetActionDelegate<T>> extends State<FilterGridAppBar<T, CSAD>> with SingleTickerProviderStateMixin {
|
class _FilterGridAppBarState<T extends CollectionFilter, CSAD extends ChipSetActionDelegate<T>> extends State<FilterGridAppBar<T, CSAD>> with SingleTickerProviderStateMixin, WidgetsBindingObserver {
|
||||||
final List<StreamSubscription> _subscriptions = [];
|
final List<StreamSubscription> _subscriptions = [];
|
||||||
late AnimationController _browseToSelectAnimation;
|
late AnimationController _browseToSelectAnimation;
|
||||||
final ValueNotifier<bool> _isSelectingNotifier = ValueNotifier(false);
|
final ValueNotifier<bool> _isSelectingNotifier = ValueNotifier(false);
|
||||||
|
@ -105,6 +104,7 @@ class _FilterGridAppBarState<T extends CollectionFilter, CSAD extends ChipSetAct
|
||||||
vsync: this,
|
vsync: this,
|
||||||
);
|
);
|
||||||
_isSelectingNotifier.addListener(_onActivityChanged);
|
_isSelectingNotifier.addListener(_onActivityChanged);
|
||||||
|
WidgetsBinding.instance.addObserver(this);
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) => _updateAppBarHeight());
|
WidgetsBinding.instance.addPostFrameCallback((_) => _updateAppBarHeight());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,9 +118,16 @@ class _FilterGridAppBarState<T extends CollectionFilter, CSAD extends ChipSetAct
|
||||||
_subscriptions
|
_subscriptions
|
||||||
..forEach((sub) => sub.cancel())
|
..forEach((sub) => sub.cancel())
|
||||||
..clear();
|
..clear();
|
||||||
|
WidgetsBinding.instance.removeObserver(this);
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void didChangeMetrics() {
|
||||||
|
// when text scale factor changes
|
||||||
|
_updateAppBarHeight();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final appMode = context.watch<ValueNotifier<AppMode>>().value;
|
final appMode = context.watch<ValueNotifier<AppMode>>().value;
|
||||||
|
@ -320,15 +327,12 @@ class _FilterGridAppBarState<T extends CollectionFilter, CSAD extends ChipSetAct
|
||||||
final isSelecting = selection.isSelecting;
|
final isSelecting = selection.isSelecting;
|
||||||
|
|
||||||
final quickActionButtons = (isSelecting ? selectionQuickActions : browsingQuickActions).where(isVisible).map(
|
final quickActionButtons = (isSelecting ? selectionQuickActions : browsingQuickActions).where(isVisible).map(
|
||||||
(action) => FontSizeIconTheme(
|
(action) => _buildButtonIcon(context, actionDelegate, action, enabled: canApply(action)),
|
||||||
child: _buildButtonIcon(context, actionDelegate, action, enabled: canApply(action)),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return [
|
return [
|
||||||
...quickActionButtons,
|
...quickActionButtons,
|
||||||
FontSizeIconTheme(
|
PopupMenuButton<ChipSetAction>(
|
||||||
child: PopupMenuButton<ChipSetAction>(
|
|
||||||
itemBuilder: (context) {
|
itemBuilder: (context) {
|
||||||
final generalMenuItems = ChipSetActions.general.where(isVisible).map(
|
final generalMenuItems = ChipSetActions.general.where(isVisible).map(
|
||||||
(action) => FilterGridAppBar.toMenuItem(context, action, enabled: canApply(action)),
|
(action) => FilterGridAppBar.toMenuItem(context, action, enabled: canApply(action)),
|
||||||
|
@ -367,7 +371,6 @@ class _FilterGridAppBarState<T extends CollectionFilter, CSAD extends ChipSetAct
|
||||||
_onActionSelected(context, action, actionDelegate);
|
_onActionSelected(context, action, actionDelegate);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -485,9 +485,31 @@ class _FilterSectionedContentState<T extends CollectionFilter> extends State<_Fi
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
_registerWidget(widget);
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) => _checkInitHighlight());
|
WidgetsBinding.instance.addPostFrameCallback((_) => _checkInitHighlight());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void didUpdateWidget(covariant _FilterSectionedContent<T> oldWidget) {
|
||||||
|
super.didUpdateWidget(oldWidget);
|
||||||
|
_unregisterWidget(oldWidget);
|
||||||
|
_registerWidget(widget);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_unregisterWidget(widget);
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _registerWidget(_FilterSectionedContent<T> widget) {
|
||||||
|
widget.appBarHeightNotifier.addListener(_onAppBarHeightChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _unregisterWidget(_FilterSectionedContent<T> widget) {
|
||||||
|
widget.appBarHeightNotifier.removeListener(_onAppBarHeightChanged);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final scrollView = AnimationLimiter(
|
final scrollView = AnimationLimiter(
|
||||||
|
@ -527,6 +549,8 @@ class _FilterSectionedContentState<T extends CollectionFilter> extends State<_Fi
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _onAppBarHeightChanged() => setState(() {});
|
||||||
|
|
||||||
Future<void> _checkInitHighlight() async {
|
Future<void> _checkInitHighlight() async {
|
||||||
final highlightInfo = context.read<HighlightInfo>();
|
final highlightInfo = context.read<HighlightInfo>();
|
||||||
final filter = highlightInfo.clear();
|
final filter = highlightInfo.clear();
|
||||||
|
@ -631,7 +655,7 @@ class _FilterScrollView<T extends CollectionFilter> extends StatelessWidget {
|
||||||
return settings.useTvLayout ? scrollView : _buildDraggableScrollView(scrollView);
|
return settings.useTvLayout ? scrollView : _buildDraggableScrollView(scrollView);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildDraggableScrollView(ScrollView scrollView) {
|
Widget _buildDraggableScrollView(Widget scrollView) {
|
||||||
return ValueListenableBuilder<double>(
|
return ValueListenableBuilder<double>(
|
||||||
valueListenable: appBarHeightNotifier,
|
valueListenable: appBarHeightNotifier,
|
||||||
builder: (context, appBarHeight, child) {
|
builder: (context, appBarHeight, child) {
|
||||||
|
@ -672,7 +696,7 @@ class _FilterScrollView<T extends CollectionFilter> extends StatelessWidget {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
ScrollView _buildScrollView(BuildContext context) {
|
Widget _buildScrollView(BuildContext context) {
|
||||||
return CustomScrollView(
|
return CustomScrollView(
|
||||||
key: scrollableKey,
|
key: scrollableKey,
|
||||||
controller: scrollController,
|
controller: scrollController,
|
||||||
|
|
|
@ -16,7 +16,6 @@ class MapInfoRow extends StatelessWidget {
|
||||||
final ValueNotifier<AvesEntry?> entryNotifier;
|
final ValueNotifier<AvesEntry?> entryNotifier;
|
||||||
|
|
||||||
static const double iconPadding = 8.0;
|
static const double iconPadding = 8.0;
|
||||||
static const double iconSize = 16.0;
|
|
||||||
static const double _interRowPadding = 2.0;
|
static const double _interRowPadding = 2.0;
|
||||||
|
|
||||||
const MapInfoRow({
|
const MapInfoRow({
|
||||||
|
@ -66,6 +65,8 @@ class MapInfoRow extends StatelessWidget {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static double getIconSize(BuildContext context) => 16.0 * context.select<MediaQueryData, double>((mq) => mq.textScaleFactor);
|
||||||
}
|
}
|
||||||
|
|
||||||
class _AddressRow extends StatefulWidget {
|
class _AddressRow extends StatefulWidget {
|
||||||
|
@ -103,7 +104,7 @@ class _AddressRowState extends State<_AddressRow> {
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
const SizedBox(width: MapInfoRow.iconPadding),
|
const SizedBox(width: MapInfoRow.iconPadding),
|
||||||
const Icon(AIcons.location, size: MapInfoRow.iconSize),
|
Icon(AIcons.location, size: MapInfoRow.getIconSize(context)),
|
||||||
const SizedBox(width: MapInfoRow.iconPadding),
|
const SizedBox(width: MapInfoRow.iconPadding),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Container(
|
child: Container(
|
||||||
|
@ -173,7 +174,7 @@ class _DateRow extends StatelessWidget {
|
||||||
return Row(
|
return Row(
|
||||||
children: [
|
children: [
|
||||||
const SizedBox(width: MapInfoRow.iconPadding),
|
const SizedBox(width: MapInfoRow.iconPadding),
|
||||||
const Icon(AIcons.date, size: MapInfoRow.iconSize),
|
Icon(AIcons.date, size: MapInfoRow.getIconSize(context)),
|
||||||
const SizedBox(width: MapInfoRow.iconPadding),
|
const SizedBox(width: MapInfoRow.iconPadding),
|
||||||
Text(
|
Text(
|
||||||
dateText,
|
dateText,
|
||||||
|
|
|
@ -2,6 +2,7 @@ import 'dart:async';
|
||||||
|
|
||||||
import 'package:aves/theme/durations.dart';
|
import 'package:aves/theme/durations.dart';
|
||||||
import 'package:aves/theme/icons.dart';
|
import 'package:aves/theme/icons.dart';
|
||||||
|
import 'package:aves/widgets/common/basic/font_size_icon_theme.dart';
|
||||||
import 'package:aves_utils/aves_utils.dart';
|
import 'package:aves_utils/aves_utils.dart';
|
||||||
import 'package:aves/utils/constants.dart';
|
import 'package:aves/utils/constants.dart';
|
||||||
import 'package:aves/widgets/common/basic/scaffold.dart';
|
import 'package:aves/widgets/common/basic/scaffold.dart';
|
||||||
|
@ -151,7 +152,7 @@ class _QuickActionEditorBodyState<T extends Object> extends State<QuickActionEdi
|
||||||
padding: const EdgeInsets.all(16),
|
padding: const EdgeInsets.all(16),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
const Icon(AIcons.info),
|
const FontSizeIconTheme(child: Icon(AIcons.info)),
|
||||||
const SizedBox(width: 16),
|
const SizedBox(width: 16),
|
||||||
Expanded(child: Text(widget.bannerText)),
|
Expanded(child: Text(widget.bannerText)),
|
||||||
],
|
],
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import 'package:aves/theme/icons.dart';
|
import 'package:aves/theme/icons.dart';
|
||||||
|
import 'package:aves/widgets/common/basic/font_size_icon_theme.dart';
|
||||||
import 'package:aves/widgets/common/extensions/build_context.dart';
|
import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
@ -11,7 +12,7 @@ class DrawerEditorBanner extends StatelessWidget {
|
||||||
padding: const EdgeInsets.all(16),
|
padding: const EdgeInsets.all(16),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
const Icon(AIcons.info),
|
const FontSizeIconTheme(child: Icon(AIcons.info)),
|
||||||
const SizedBox(width: 16),
|
const SizedBox(width: 16),
|
||||||
Expanded(child: Text(context.l10n.settingsNavigationDrawerBanner)),
|
Expanded(child: Text(context.l10n.settingsNavigationDrawerBanner)),
|
||||||
],
|
],
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import 'package:aves/services/common/services.dart';
|
import 'package:aves/services/common/services.dart';
|
||||||
import 'package:aves/theme/icons.dart';
|
import 'package:aves/theme/icons.dart';
|
||||||
|
import 'package:aves/widgets/common/basic/font_size_icon_theme.dart';
|
||||||
import 'package:aves/widgets/common/basic/scaffold.dart';
|
import 'package:aves/widgets/common/basic/scaffold.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/empty.dart';
|
import 'package:aves/widgets/common/identity/empty.dart';
|
||||||
|
@ -96,7 +97,7 @@ class _Header extends StatelessWidget {
|
||||||
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16),
|
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
const Icon(AIcons.info),
|
const FontSizeIconTheme(child: Icon(AIcons.info)),
|
||||||
const SizedBox(width: 16),
|
const SizedBox(width: 16),
|
||||||
Expanded(child: Text(context.l10n.settingsStorageAccessBanner)),
|
Expanded(child: Text(context.l10n.settingsStorageAccessBanner)),
|
||||||
],
|
],
|
||||||
|
|
|
@ -3,6 +3,7 @@ import 'package:aves/model/filters/path.dart';
|
||||||
import 'package:aves/model/settings/settings.dart';
|
import 'package:aves/model/settings/settings.dart';
|
||||||
import 'package:aves/theme/durations.dart';
|
import 'package:aves/theme/durations.dart';
|
||||||
import 'package:aves/theme/icons.dart';
|
import 'package:aves/theme/icons.dart';
|
||||||
|
import 'package:aves/widgets/common/basic/font_size_icon_theme.dart';
|
||||||
import 'package:aves/widgets/common/basic/scaffold.dart';
|
import 'package:aves/widgets/common/basic/scaffold.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/aves_filter_chip.dart';
|
import 'package:aves/widgets/common/identity/aves_filter_chip.dart';
|
||||||
|
@ -176,7 +177,7 @@ class _Banner extends StatelessWidget {
|
||||||
padding: const EdgeInsets.all(16),
|
padding: const EdgeInsets.all(16),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
const Icon(AIcons.info),
|
const FontSizeIconTheme(child: Icon(AIcons.info)),
|
||||||
const SizedBox(width: 16),
|
const SizedBox(width: 16),
|
||||||
Expanded(child: Text(bannerText)),
|
Expanded(child: Text(bannerText)),
|
||||||
],
|
],
|
||||||
|
|
|
@ -128,8 +128,7 @@ class _SettingsPageState extends State<SettingsPage> with FeedbackMixin {
|
||||||
onPressed: () => _goToSearch(context),
|
onPressed: () => _goToSearch(context),
|
||||||
tooltip: MaterialLocalizations.of(context).searchFieldLabel,
|
tooltip: MaterialLocalizations.of(context).searchFieldLabel,
|
||||||
),
|
),
|
||||||
FontSizeIconTheme(
|
PopupMenuButton<SettingsAction>(
|
||||||
child: PopupMenuButton<SettingsAction>(
|
|
||||||
itemBuilder: (context) {
|
itemBuilder: (context) {
|
||||||
return [
|
return [
|
||||||
PopupMenuItem(
|
PopupMenuItem(
|
||||||
|
@ -148,8 +147,7 @@ class _SettingsPageState extends State<SettingsPage> with FeedbackMixin {
|
||||||
_onActionSelected(action);
|
_onActionSelected(action);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
].map((v) => FontSizeIconTheme(child: v)).toList(),
|
||||||
],
|
|
||||||
),
|
),
|
||||||
body: GestureAreaProtectorStack(
|
body: GestureAreaProtectorStack(
|
||||||
child: SafeArea(
|
child: SafeArea(
|
||||||
|
|
|
@ -97,7 +97,7 @@ class _InfoRowGroupState extends State<InfoRowGroup> {
|
||||||
|
|
||||||
// compute the size of keys and space in order to align values
|
// compute the size of keys and space in order to align values
|
||||||
final textScaleFactor = MediaQuery.textScaleFactorOf(context);
|
final textScaleFactor = MediaQuery.textScaleFactorOf(context);
|
||||||
final keySizes = Map.fromEntries(keyValues.keys.map((key) => MapEntry(key, _getSpanWidth(TextSpan(text: key, style: _keyStyle), textScaleFactor))));
|
final keySizes = Map.fromEntries(keyValues.keys.map((key) => MapEntry(key, _getSpanWidth(TextSpan(text: _buildTextValue(key), style: _keyStyle), textScaleFactor))));
|
||||||
|
|
||||||
final lastKey = keyValues.keys.last;
|
final lastKey = keyValues.keys.last;
|
||||||
return LayoutBuilder(
|
return LayoutBuilder(
|
||||||
|
@ -115,15 +115,11 @@ class _InfoRowGroupState extends State<InfoRowGroup> {
|
||||||
final spanBuilder = spanBuilders[key] ?? _buildTextValueSpans;
|
final spanBuilder = spanBuilders[key] ?? _buildTextValueSpans;
|
||||||
final thisSpaceSize = max(0.0, (baseValueX - keySizes[key]!)) + InfoRowGroup.keyValuePadding;
|
final thisSpaceSize = max(0.0, (baseValueX - keySizes[key]!)) + InfoRowGroup.keyValuePadding;
|
||||||
|
|
||||||
// each text span embeds and pops a Bidi isolate,
|
|
||||||
// so that layout of the spans follows the directionality of the locale
|
|
||||||
// (e.g. keys on the right for RTL locale, whatever the key intrinsic directionality)
|
|
||||||
// and each span respects the directionality of its inner text only
|
|
||||||
return [
|
return [
|
||||||
TextSpan(text: '${Constants.fsi}$key${Constants.pdi}', style: _keyStyle),
|
TextSpan(text: _buildTextValue(key), style: _keyStyle),
|
||||||
WidgetSpan(
|
WidgetSpan(
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
width: thisSpaceSize,
|
width: thisSpaceSize / textScaleFactor,
|
||||||
// as of Flutter v3.0.0, the underline decoration from the following `TextSpan`
|
// as of Flutter v3.0.0, the underline decoration from the following `TextSpan`
|
||||||
// is applied to the `WidgetSpan` too, so we add a dummy `Text` as a workaround
|
// is applied to the `WidgetSpan` too, so we add a dummy `Text` as a workaround
|
||||||
child: const Text(''),
|
child: const Text(''),
|
||||||
|
@ -161,8 +157,14 @@ class _InfoRowGroupState extends State<InfoRowGroup> {
|
||||||
recognizer = TapGestureRecognizer()..onTap = () => setState(() => _expandedKeys.add(key));
|
recognizer = TapGestureRecognizer()..onTap = () => setState(() => _expandedKeys.add(key));
|
||||||
}
|
}
|
||||||
|
|
||||||
return [TextSpan(text: '${Constants.fsi}$value${Constants.pdi}', recognizer: recognizer)];
|
return [TextSpan(text: _buildTextValue(value), recognizer: recognizer)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// each text span embeds and pops a Bidi isolate,
|
||||||
|
// so that layout of the spans follows the directionality of the locale
|
||||||
|
// (e.g. keys on the right for RTL locale, whatever the key intrinsic directionality)
|
||||||
|
// and each span respects the directionality of its inner text only
|
||||||
|
String _buildTextValue(String value) => '${Constants.fsi}$value${Constants.pdi}';
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef InfoValueSpanBuilder = List<InlineSpan> Function(BuildContext context, String key, String value);
|
typedef InfoValueSpanBuilder = List<InlineSpan> Function(BuildContext context, String key, String value);
|
||||||
|
|
|
@ -50,13 +50,15 @@ class InfoAppBar extends StatelessWidget {
|
||||||
return SliverAppBar(
|
return SliverAppBar(
|
||||||
leading: useTvLayout
|
leading: useTvLayout
|
||||||
? null
|
? null
|
||||||
: IconButton(
|
: FontSizeIconTheme(
|
||||||
|
child: IconButton(
|
||||||
// key is expected by test driver
|
// key is expected by test driver
|
||||||
key: const Key('back-button'),
|
key: const Key('back-button'),
|
||||||
icon: const Icon(AIcons.goUp),
|
icon: const Icon(AIcons.goUp),
|
||||||
onPressed: onBackPressed,
|
onPressed: onBackPressed,
|
||||||
tooltip: context.l10n.viewerInfoBackToViewerTooltip,
|
tooltip: context.l10n.viewerInfoBackToViewerTooltip,
|
||||||
),
|
),
|
||||||
|
),
|
||||||
automaticallyImplyLeading: false,
|
automaticallyImplyLeading: false,
|
||||||
title: SliverAppBarTitleWrapper(
|
title: SliverAppBarTitleWrapper(
|
||||||
child: InteractiveAppBarTitle(
|
child: InteractiveAppBarTitle(
|
||||||
|
@ -73,8 +75,7 @@ class InfoAppBar extends StatelessWidget {
|
||||||
tooltip: MaterialLocalizations.of(context).searchFieldLabel,
|
tooltip: MaterialLocalizations.of(context).searchFieldLabel,
|
||||||
),
|
),
|
||||||
if (entry.canEdit)
|
if (entry.canEdit)
|
||||||
FontSizeIconTheme(
|
PopupMenuButton<EntryAction>(
|
||||||
child: PopupMenuButton<EntryAction>(
|
|
||||||
itemBuilder: (context) => [
|
itemBuilder: (context) => [
|
||||||
...commonActions.map((action) => _toMenuItem(context, action, enabled: actionDelegate.canApply(entry, action))),
|
...commonActions.map((action) => _toMenuItem(context, action, enabled: actionDelegate.canApply(entry, action))),
|
||||||
if (formatSpecificActions.isNotEmpty) ...[
|
if (formatSpecificActions.isNotEmpty) ...[
|
||||||
|
@ -92,8 +93,7 @@ class InfoAppBar extends StatelessWidget {
|
||||||
actionDelegate.onActionSelected(context, entry, collection, action);
|
actionDelegate.onActionSelected(context, entry, collection, action);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
].map((v) => FontSizeIconTheme(child: v)).toList(),
|
||||||
],
|
|
||||||
floating: true,
|
floating: true,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue