diff --git a/lib/widgets/about/translators.dart b/lib/widgets/about/translators.dart index 2f6bcba83..24ed0b8bf 100644 --- a/lib/widgets/about/translators.dart +++ b/lib/widgets/about/translators.dart @@ -34,6 +34,7 @@ class AboutTranslators extends StatelessWidget { Contributor('Igor Sorocean', 'sorocean.igor@gmail.com'), Contributor('JY3', 'GeeyunJY3@gmail.com'), Contributor('Gediminas Murauskas', 'muziejusinfo@gmail.com'), + Contributor('Oğuz Ersen', 'oguz@ersen.moe'), // Contributor('Allan Nordhøy', 'epost@anotheragency.no'), // Contributor('Piotr K', '1337.kelt@gmail.com'), // Contributor('امیر جهانگرد', 'ijahangard.a@gmail.com'), diff --git a/lib/widgets/common/expandable_filter_row.dart b/lib/widgets/common/expandable_filter_row.dart index 96b3f7fdc..90d25c482 100644 --- a/lib/widgets/common/expandable_filter_row.dart +++ b/lib/widgets/common/expandable_filter_row.dart @@ -5,8 +5,8 @@ import 'package:aves/utils/constants.dart'; import 'package:aves/widgets/common/identity/aves_filter_chip.dart'; import 'package:flutter/material.dart'; -class ExpandableFilterRow extends StatelessWidget { - final String? title; +class TitledExpandableFilterRow extends StatelessWidget { + final String title; final Iterable filters; final ValueNotifier expandedNotifier; final bool showGenericIcon; @@ -14,9 +14,9 @@ class ExpandableFilterRow extends StatelessWidget { final FilterCallback onTap; final OffsetFilterCallback? onLongPress; - const ExpandableFilterRow({ + const TitledExpandableFilterRow({ super.key, - this.title, + required this.title, required this.filters, required this.expandedNotifier, this.showGenericIcon = true, @@ -25,41 +25,85 @@ class ExpandableFilterRow extends StatelessWidget { required this.onLongPress, }); - static const double horizontalPadding = 8; - static const double verticalPadding = 8; - @override Widget build(BuildContext context) { if (filters.isEmpty) return const SizedBox(); - final hasTitle = title != null && title!.isNotEmpty; + final isExpanded = expandedNotifier.value == title; - final isExpanded = hasTitle && expandedNotifier.value == title; - - Widget? titleRow; - if (hasTitle) { - titleRow = Padding( - padding: const EdgeInsets.all(16), - child: Row( - children: [ - Text( - title!, - style: Constants.knownTitleTextStyle, - ), - const Spacer(), - IconButton( - icon: Icon(isExpanded ? AIcons.collapse : AIcons.expand), - onPressed: () => expandedNotifier.value = isExpanded ? null : title, - tooltip: isExpanded ? MaterialLocalizations.of(context).expandedIconTapHint : MaterialLocalizations.of(context).collapsedIconTapHint, - ), - ], + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.all(16), + child: Row( + children: [ + Text( + title, + style: Constants.knownTitleTextStyle, + ), + const Spacer(), + IconButton( + icon: Icon(isExpanded ? AIcons.collapse : AIcons.expand), + onPressed: () => expandedNotifier.value = isExpanded ? null : title, + tooltip: isExpanded ? MaterialLocalizations.of(context).expandedIconTapHint : MaterialLocalizations.of(context).collapsedIconTapHint, + ), + ], + ), ), - ); - } + ExpandableFilterRow( + filters: filters, + isExpanded: isExpanded, + showGenericIcon: showGenericIcon, + heroTypeBuilder: heroTypeBuilder, + onTap: onTap, + onLongPress: onLongPress, + ), + ], + ); + } +} +class ExpandableFilterRow extends StatelessWidget { + final Iterable filters; + final bool isExpanded; + final bool showGenericIcon; + final HeroType Function(CollectionFilter filter)? heroTypeBuilder; + final FilterCallback onTap; + final OffsetFilterCallback? onLongPress; + + static const double horizontalPadding = 8; + static const double verticalPadding = 8; + + const ExpandableFilterRow({ + super.key, + required this.filters, + required this.isExpanded, + this.showGenericIcon = true, + this.heroTypeBuilder, + required this.onTap, + required this.onLongPress, + }); + + @override + Widget build(BuildContext context) { + if (filters.isEmpty) return const SizedBox(); + return AnimatedSwitcher( + duration: Durations.filterRowExpandAnimation, + layoutBuilder: (currentChild, previousChildren) => Stack( + children: [ + ...previousChildren, + if (currentChild != null) currentChild, + ], + ), + child: isExpanded ? _buildExpanded() : _buildCollapsed(), + ); + } + + Widget _buildExpanded() { final filterList = filters.toList(); - final wrap = Container( - key: Key('wrap$title'), + return Container( + key: const Key('wrap'), padding: const EdgeInsets.symmetric(horizontal: horizontalPadding), // specify transparent as a workaround to prevent // chip border clipping when the floating app bar is fading @@ -67,11 +111,15 @@ class ExpandableFilterRow extends StatelessWidget { child: Wrap( spacing: horizontalPadding, runSpacing: verticalPadding, - children: filterList.map(_buildFilterChip).toList(), + children: filterList.map(_buildChip).toList(), ), ); + } + + Widget _buildCollapsed() { + final filterList = filters.toList(); final list = Container( - key: Key('list$title'), + key: const Key('list'), // specify transparent as a workaround to prevent // chip border clipping when the floating app bar is fading color: Colors.transparent, @@ -80,34 +128,16 @@ class ExpandableFilterRow extends StatelessWidget { scrollDirection: Axis.horizontal, padding: const EdgeInsets.symmetric(horizontal: horizontalPadding), itemBuilder: (context, index) { - return index < filterList.length ? _buildFilterChip(filterList[index]) : const SizedBox(); + return index < filterList.length ? _buildChip(filterList[index]) : const SizedBox(); }, separatorBuilder: (context, index) => const SizedBox(width: 8), itemCount: filterList.length, ), ); - final filterChips = isExpanded ? wrap : list; - return titleRow != null - ? Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - titleRow, - AnimatedSwitcher( - duration: Durations.filterRowExpandAnimation, - layoutBuilder: (currentChild, previousChildren) => Stack( - children: [ - ...previousChildren, - if (currentChild != null) currentChild, - ], - ), - child: filterChips, - ), - ], - ) - : filterChips; + return list; } - Widget _buildFilterChip(CollectionFilter filter) { + Widget _buildChip(CollectionFilter filter) { return AvesFilterChip( // key `album-{path}` is expected by test driver key: Key(filter.key), diff --git a/lib/widgets/dialogs/entry_editors/edit_tags_dialog.dart b/lib/widgets/dialogs/entry_editors/edit_tags_dialog.dart index bed1fe719..99bc07eef 100644 --- a/lib/widgets/dialogs/entry_editors/edit_tags_dialog.dart +++ b/lib/widgets/dialogs/entry_editors/edit_tags_dialog.dart @@ -245,7 +245,7 @@ class _FilterRow extends StatelessWidget { Widget build(BuildContext context) { return filters.isEmpty ? const SizedBox() - : ExpandableFilterRow( + : TitledExpandableFilterRow( title: title, filters: filters, expandedNotifier: expandedNotifier, diff --git a/lib/widgets/search/search_delegate.dart b/lib/widgets/search/search_delegate.dart index 1525ae9c1..e6259006a 100644 --- a/lib/widgets/search/search_delegate.dart +++ b/lib/widgets/search/search_delegate.dart @@ -132,14 +132,24 @@ class CollectionSearchDelegate extends AvesSearchDelegate { required List filters, HeroType Function(CollectionFilter filter)? heroTypeBuilder, }) { - return ExpandableFilterRow( - title: title, - filters: filters, - expandedNotifier: _expandedSectionNotifier, - heroTypeBuilder: heroTypeBuilder, - onTap: (filter) => _select(context, filter is QueryFilter ? QueryFilter(filter.query) : filter), - onLongPress: AvesFilterChip.showDefaultLongPressMenu, - ); + void onTap(filter) => _select(context, filter is QueryFilter ? QueryFilter(filter.query) : filter); + const onLongPress = AvesFilterChip.showDefaultLongPressMenu; + return title != null + ? TitledExpandableFilterRow( + title: title, + filters: filters, + expandedNotifier: _expandedSectionNotifier, + heroTypeBuilder: heroTypeBuilder, + onTap: onTap, + onLongPress: onLongPress, + ) + : ExpandableFilterRow( + filters: filters, + isExpanded: false, + heroTypeBuilder: heroTypeBuilder, + onTap: onTap, + onLongPress: onLongPress, + ); } Widget _buildDateFilters(BuildContext context, _ContainQuery containQuery) { diff --git a/untranslated.json b/untranslated.json index b0838f92e..dbd663a5a 100644 --- a/untranslated.json +++ b/untranslated.json @@ -593,20 +593,6 @@ "filePickerUseThisFolder" ], - "de": [ - "filterAspectRatioLandscapeLabel", - "filterAspectRatioPortraitLabel", - "filterNoAddressLabel", - "subtitlePositionTop", - "subtitlePositionBottom", - "widgetDisplayedItemRandom", - "widgetDisplayedItemMostRecent", - "settingsViewerShowRatingTags", - "settingsSubtitleThemeTextPositionTile", - "settingsSubtitleThemeTextPositionDialogTitle", - "settingsWidgetDisplayedItem" - ], - "el": [ "filterAspectRatioLandscapeLabel", "filterAspectRatioPortraitLabel", @@ -614,13 +600,6 @@ "settingsViewerShowRatingTags" ], - "es": [ - "filterAspectRatioLandscapeLabel", - "filterAspectRatioPortraitLabel", - "filterNoAddressLabel", - "settingsViewerShowRatingTags" - ], - "fa": [ "appName", "welcomeMessage", @@ -1215,13 +1194,6 @@ "filePickerUseThisFolder" ], - "fr": [ - "filterAspectRatioLandscapeLabel", - "filterAspectRatioPortraitLabel", - "filterNoAddressLabel", - "settingsViewerShowRatingTags" - ], - "gl": [ "entryInfoActionExportMetadata", "filterAspectRatioLandscapeLabel", @@ -1721,145 +1693,6 @@ "settingsWidgetDisplayedItem" ], - "ko": [ - "filterAspectRatioLandscapeLabel", - "filterAspectRatioPortraitLabel", - "filterNoAddressLabel", - "settingsViewerShowRatingTags" - ], - - "lt": [ - "filterAspectRatioLandscapeLabel", - "filterAspectRatioPortraitLabel", - "filterNoAddressLabel", - "settingsViewerShowRatingTags" - ], - - "nb": [ - "videoActionCaptureFrame", - "videoActionSelectStreams", - "entryInfoActionEditLocation", - "entryInfoActionExportMetadata", - "filterAspectRatioLandscapeLabel", - "filterAspectRatioPortraitLabel", - "filterNoAddressLabel", - "coordinateFormatDms", - "mapStyleHuaweiNormal", - "mapStyleHuaweiTerrain", - "mapStyleStamenToner", - "mapStyleStamenWatercolor", - "keepScreenOnViewerOnly", - "subtitlePositionTop", - "subtitlePositionBottom", - "viewerTransitionFade", - "widgetDisplayedItemRandom", - "widgetDisplayedItemMostRecent", - "albumTierSpecial", - "storageAccessDialogMessage", - "restrictedAccessDialogMessage", - "notEnoughSpaceDialogMessage", - "missingSystemFilePickerDialogMessage", - "unsupportedTypeDialogMessage", - "binEntriesConfirmationDialogMessage", - "deleteEntriesConfirmationDialogMessage", - "moveUndatedConfirmationDialogMessage", - "setCoverDialogLatest", - "hideFilterConfirmationDialogMessage", - "deleteSingleAlbumConfirmationDialogMessage", - "deleteMultiAlbumConfirmationDialogMessage", - "editEntryDateDialogExtractFromTitle", - "editEntryDateDialogShift", - "editEntryDateDialogSourceFileModifiedDate", - "editEntryLocationDialogTitle", - "editEntryLocationDialogSetCustom", - "locationPickerUseThisLocationButton", - "removeEntryMetadataMotionPhotoXmpWarningDialogMessage", - "videoStreamSelectionDialogText", - "videoStreamSelectionDialogTrack", - "videoStreamSelectionDialogNoSelection", - "viewDialogLayoutSectionTitle", - "viewDialogReverseSortOrder", - "tileLayoutMosaic", - "collectionDeleteFailureFeedback", - "collectionCopyFailureFeedback", - "collectionMoveFailureFeedback", - "collectionRenameFailureFeedback", - "collectionEditFailureFeedback", - "collectionExportFailureFeedback", - "collectionCopySuccessFeedback", - "collectionMoveSuccessFeedback", - "collectionRenameSuccessFeedback", - "collectionEditSuccessFeedback", - "collectionSelectSectionTooltip", - "collectionDeselectSectionTooltip", - "albumGroupTier", - "settingsConfirmationBeforeDeleteItems", - "settingsConfirmationBeforeMoveToBinItems", - "settingsConfirmationBeforeMoveUndatedItems", - "settingsConfirmationAfterMoveToBinItems", - "settingsNavigationDrawerBanner", - "settingsThumbnailOverlayTile", - "settingsThumbnailOverlayPageTitle", - "settingsThumbnailShowFavouriteIcon", - "settingsThumbnailShowTagIcon", - "settingsThumbnailShowLocationIcon", - "settingsThumbnailShowMotionPhotoIcon", - "settingsThumbnailShowRating", - "settingsThumbnailShowRawIcon", - "settingsThumbnailShowVideoDuration", - "settingsCollectionQuickActionsTile", - "settingsCollectionQuickActionEditorPageTitle", - "settingsCollectionQuickActionTabBrowsing", - "settingsCollectionQuickActionTabSelecting", - "settingsCollectionBrowsingQuickActionEditorBanner", - "settingsCollectionSelectionQuickActionEditorBanner", - "settingsViewerSectionTitle", - "settingsViewerGestureSideTapNext", - "settingsViewerUseCutout", - "settingsViewerMaximumBrightness", - "settingsMotionPhotoAutoPlay", - "settingsImageBackground", - "settingsViewerQuickActionEditorBanner", - "settingsViewerQuickActionEditorDisplayedButtonsSectionTitle", - "settingsViewerQuickActionEditorAvailableButtonsSectionTitle", - "settingsViewerQuickActionEmpty", - "settingsViewerOverlayTile", - "settingsViewerOverlayPageTitle", - "settingsViewerShowOverlayOnOpening", - "settingsViewerShowRatingTags", - "settingsViewerShowShootingDetails", - "settingsViewerEnableOverlayBlurEffect", - "settingsSlideshowShuffle", - "settingsSubtitleThemeSample", - "settingsSubtitleThemeTextPositionTile", - "settingsSubtitleThemeTextPositionDialogTitle", - "settingsAllowInstalledAppAccess", - "settingsAllowMediaManagement", - "settingsHiddenFiltersBanner", - "settingsHiddenFiltersEmpty", - "settingsHiddenItemsTabPaths", - "settingsHiddenPathsBanner", - "addPathTooltip", - "settingsStorageAccessTile", - "settingsStorageAccessBanner", - "settingsStorageAccessEmpty", - "settingsTimeToTakeActionTile", - "settingsThemeColorHighlights", - "settingsDisplayRefreshRateModeTile", - "settingsDisplayRefreshRateModeDialogTitle", - "settingsWidgetDisplayedItem", - "statsWithGps", - "viewerErrorDoesNotExist", - "mapAttributionStamen", - "mapEmptyRegion", - "viewerInfoOpenEmbeddedFailureFeedback", - "viewerInfoSearchEmpty", - "wallpaperUseScrollEffect", - "tagEditorSectionPlaceholders", - "tagPlaceholderCountry", - "tagPlaceholderPlace" - ], - "nl": [ "entryInfoActionExportMetadata", "filterAspectRatioLandscapeLabel", @@ -2779,19 +2612,10 @@ "filePickerUseThisFolder" ], - "tr": [ - "filterAspectRatioLandscapeLabel", - "filterAspectRatioPortraitLabel", - "filterNoAddressLabel", - "settingsViewerShowRatingTags" - ], - "zh": [ "filterAspectRatioLandscapeLabel", "filterAspectRatioPortraitLabel", "filterNoAddressLabel", - "aboutLicensesFlutterPackagesSectionTitle", - "aboutLicensesDartPackagesSectionTitle", "settingsViewerShowRatingTags" ] }