From f607cf6c52bb718a7a4d5d4438bcfbd7f4b45863 Mon Sep 17 00:00:00 2001 From: Thibault Deckers Date: Sat, 3 Dec 2022 20:28:47 +0100 Subject: [PATCH] #420 tag editor review --- lib/model/settings/defaults.dart | 4 ++ lib/model/settings/settings.dart | 11 ++++ lib/widgets/common/expandable_filter_row.dart | 19 ++++--- .../entry_editors/edit_tags_dialog.dart | 50 +++++++++++-------- .../viewer/overlay/details/rating_tags.dart | 4 +- 5 files changed, 56 insertions(+), 32 deletions(-) diff --git a/lib/model/settings/defaults.dart b/lib/model/settings/defaults.dart index b45e542d8..f8879a9ec 100644 --- a/lib/model/settings/defaults.dart +++ b/lib/model/settings/defaults.dart @@ -109,6 +109,10 @@ class SettingsDefaults { static const coordinateFormat = CoordinateFormat.dms; static const unitSystem = UnitSystem.metric; + // tag editor + + static const tagEditorCurrentFilterSectionExpanded = true; + // rendering static const imageBackground = EntryBackground.white; diff --git a/lib/model/settings/settings.dart b/lib/model/settings/settings.dart index d1c767f4d..792370986 100644 --- a/lib/model/settings/settings.dart +++ b/lib/model/settings/settings.dart @@ -139,6 +139,10 @@ class Settings extends ChangeNotifier { static const coordinateFormatKey = 'coordinates_format'; static const unitSystemKey = 'unit_system'; + // tag editor + + static const tagEditorCurrentFilterSectionExpandedKey = 'tag_editor_current_filter_section_expanded'; + // map static const mapStyleKey = 'info_map_style'; static const mapDefaultCenterKey = 'map_default_center'; @@ -623,6 +627,12 @@ class Settings extends ChangeNotifier { set unitSystem(UnitSystem newValue) => setAndNotify(unitSystemKey, newValue.toString()); + // tag editor + + bool get tagEditorCurrentFilterSectionExpanded => getBool(tagEditorCurrentFilterSectionExpandedKey) ?? SettingsDefaults.tagEditorCurrentFilterSectionExpanded; + + set tagEditorCurrentFilterSectionExpanded(bool newValue) => setAndNotify(tagEditorCurrentFilterSectionExpandedKey, newValue); + // map EntryMapStyle? get mapStyle { @@ -961,6 +971,7 @@ class Settings extends ChangeNotifier { case videoGestureDoubleTapTogglePlayKey: case videoGestureSideDoubleTapSeekKey: case subtitleShowOutlineKey: + case tagEditorCurrentFilterSectionExpandedKey: case saveSearchHistoryKey: case filePickerShowHiddenFilesKey: case screenSaverFillScreenKey: diff --git a/lib/widgets/common/expandable_filter_row.dart b/lib/widgets/common/expandable_filter_row.dart index 90d25c482..cafcf96b2 100644 --- a/lib/widgets/common/expandable_filter_row.dart +++ b/lib/widgets/common/expandable_filter_row.dart @@ -7,7 +7,7 @@ import 'package:flutter/material.dart'; class TitledExpandableFilterRow extends StatelessWidget { final String title; - final Iterable filters; + final List filters; final ValueNotifier expandedNotifier; final bool showGenericIcon; final HeroType Function(CollectionFilter filter)? heroTypeBuilder; @@ -65,9 +65,10 @@ class TitledExpandableFilterRow extends StatelessWidget { } class ExpandableFilterRow extends StatelessWidget { - final Iterable filters; + final List filters; final bool isExpanded; - final bool showGenericIcon; + final bool removable, showGenericIcon; + final Widget? Function(CollectionFilter)? leadingBuilder; final HeroType Function(CollectionFilter filter)? heroTypeBuilder; final FilterCallback onTap; final OffsetFilterCallback? onLongPress; @@ -79,7 +80,9 @@ class ExpandableFilterRow extends StatelessWidget { super.key, required this.filters, required this.isExpanded, + this.removable = false, this.showGenericIcon = true, + this.leadingBuilder, this.heroTypeBuilder, required this.onTap, required this.onLongPress, @@ -101,7 +104,6 @@ class ExpandableFilterRow extends StatelessWidget { } Widget _buildExpanded() { - final filterList = filters.toList(); return Container( key: const Key('wrap'), padding: const EdgeInsets.symmetric(horizontal: horizontalPadding), @@ -111,13 +113,12 @@ class ExpandableFilterRow extends StatelessWidget { child: Wrap( spacing: horizontalPadding, runSpacing: verticalPadding, - children: filterList.map(_buildChip).toList(), + children: filters.map(_buildChip).toList(), ), ); } Widget _buildCollapsed() { - final filterList = filters.toList(); final list = Container( key: const Key('list'), // specify transparent as a workaround to prevent @@ -128,10 +129,10 @@ class ExpandableFilterRow extends StatelessWidget { scrollDirection: Axis.horizontal, padding: const EdgeInsets.symmetric(horizontal: horizontalPadding), itemBuilder: (context, index) { - return index < filterList.length ? _buildChip(filterList[index]) : const SizedBox(); + return index < filters.length ? _buildChip(filters[index]) : const SizedBox(); }, separatorBuilder: (context, index) => const SizedBox(width: 8), - itemCount: filterList.length, + itemCount: filters.length, ), ); return list; @@ -142,7 +143,9 @@ class ExpandableFilterRow extends StatelessWidget { // key `album-{path}` is expected by test driver key: Key(filter.key), filter: filter, + removable: removable, showGenericIcon: showGenericIcon, + leadingOverride: leadingBuilder?.call(filter), heroType: heroTypeBuilder?.call(filter) ?? HeroType.onTap, onTap: onTap, onLongPress: onLongPress, diff --git a/lib/widgets/dialogs/entry_editors/edit_tags_dialog.dart b/lib/widgets/dialogs/entry_editors/edit_tags_dialog.dart index 99bc07eef..e2969d8e8 100644 --- a/lib/widgets/dialogs/entry_editors/edit_tags_dialog.dart +++ b/lib/widgets/dialogs/entry_editors/edit_tags_dialog.dart @@ -81,7 +81,7 @@ class _TagEditorPageState extends State { return ListView( children: [ Padding( - padding: const EdgeInsetsDirectional.only(start: 8), + padding: const EdgeInsetsDirectional.only(start: 8, end: 16), child: Row( crossAxisAlignment: CrossAxisAlignment.end, children: [ @@ -108,7 +108,17 @@ class _TagEditorPageState extends State { tooltip: l10n.tagEditorPageAddTagTooltip, ); }, - ) + ), + Selector( + selector: (context, s) => s.tagEditorCurrentFilterSectionExpanded, + builder: (context, isExpanded, child) { + return IconButton( + icon: Icon(isExpanded ? AIcons.collapse : AIcons.expand), + onPressed: sortedTags.isEmpty ? null : () => settings.tagEditorCurrentFilterSectionExpanded = !isExpanded, + tooltip: isExpanded ? MaterialLocalizations.of(context).expandedIconTapHint : MaterialLocalizations.of(context).collapsedIconTapHint, + ); + }, + ), ], ), ), @@ -131,22 +141,18 @@ class _TagEditorPageState extends State { ), ), ), - secondChild: Padding( - padding: const EdgeInsets.symmetric(horizontal: 8), - child: Wrap( - spacing: 8, - runSpacing: 8, - children: sortedTags.map((kv) { - return AvesFilterChip( - filter: kv.key, - removable: true, - showGenericIcon: false, - leadingOverride: showCount ? _TagCount(count: kv.value) : null, - onTap: _removeTag, - onLongPress: null, - ); - }).toList(), - ), + secondChild: ExpandableFilterRow( + filters: sortedTags.map((kv) => kv.key).toList(), + isExpanded: context.select((v) => v.tagEditorCurrentFilterSectionExpanded), + removable: true, + showGenericIcon: false, + leadingBuilder: showCount + ? (filter) => _TagCount( + count: sortedTags.firstWhere((kv) => kv.key == filter).value, + ) + : null, + onTap: _removeTag, + onLongPress: null, ), crossFadeState: sortedTags.isEmpty ? CrossFadeState.showFirst : CrossFadeState.showSecond, duration: Durations.tagEditorTransition, @@ -154,14 +160,14 @@ class _TagEditorPageState extends State { ), const Divider(height: 0), _FilterRow( - title: l10n.tagEditorSectionRecent, - filters: recentFilters, + title: l10n.statsTopTagsSectionTitle, + filters: topTagFilters, expandedNotifier: _expandedSectionNotifier, onTap: _addTag, ), _FilterRow( - title: l10n.statsTopTagsSectionTitle, - filters: topTagFilters, + title: l10n.tagEditorSectionRecent, + filters: recentFilters, expandedNotifier: _expandedSectionNotifier, onTap: _addTag, ), diff --git a/lib/widgets/viewer/overlay/details/rating_tags.dart b/lib/widgets/viewer/overlay/details/rating_tags.dart index 92aced804..2b8dd0fb1 100644 --- a/lib/widgets/viewer/overlay/details/rating_tags.dart +++ b/lib/widgets/viewer/overlay/details/rating_tags.dart @@ -36,13 +36,13 @@ class OverlayRatingTagsRow extends AnimatedWidget { return Row( children: [ if (ratingString.isNotEmpty) ...[ - Text(ratingString), + Text(ratingString, strutStyle: Constants.overflowStrutStyle), if (hasTags) const Text(Constants.separator), ], if (hasTags) ...[ DecoratedIcon(AIcons.tag, size: ViewerDetailOverlayContent.iconSize, shadows: ViewerDetailOverlayContent.shadows(context)), const SizedBox(width: ViewerDetailOverlayContent.iconPadding), - Expanded(child: Text(tags)), + Expanded(child: Text(tags, strutStyle: Constants.overflowStrutStyle)), ], ], );