#472 collection: unlocated/untagged overlay icons

This commit is contained in:
Thibault Deckers 2023-01-07 19:43:53 +01:00
parent a150f953ea
commit 8f9c91d963
16 changed files with 367 additions and 243 deletions

View file

@ -7,6 +7,7 @@ All notable changes to this project will be documented in this file.
### Added ### Added
- Viewer: optionally show description on overlay - Viewer: optionally show description on overlay
- Collection: unlocated/untagged overlay icons
- Czech translation (thanks vesp) - Czech translation (thanks vesp)
### Changed ### Changed

View file

@ -214,6 +214,12 @@
"subtitlePositionTop": "Top", "subtitlePositionTop": "Top",
"subtitlePositionBottom": "Bottom", "subtitlePositionBottom": "Bottom",
"thumbnailOverlayLocatedIcon": "Located icon",
"thumbnailOverlayUnlocatedIcon": "Unlocated icon",
"thumbnailOverlayTaggedIcon": "Tagged icon",
"thumbnailOverlayUntaggedIcon": "Untagged icon",
"videoPlaybackSkip": "Skip", "videoPlaybackSkip": "Skip",
"videoPlaybackMuted": "Play muted", "videoPlaybackMuted": "Play muted",
"videoPlaybackWithSound": "Play with sound", "videoPlaybackWithSound": "Play with sound",

View file

@ -57,8 +57,8 @@ class SettingsDefaults {
EntrySetAction.delete, EntrySetAction.delete,
]; ];
static const showThumbnailFavourite = true; static const showThumbnailFavourite = true;
static const showThumbnailTag = false; static const thumbnailLocationIcon = ThumbnailOverlayLocationIcon.none;
static const showThumbnailLocation = true; static const thumbnailTagIcon = ThumbnailOverlayTagIcon.none;
static const showThumbnailMotionPhoto = true; static const showThumbnailMotionPhoto = true;
static const showThumbnailRating = true; static const showThumbnailRating = true;
static const showThumbnailRaw = true; static const showThumbnailRaw = true;

View file

@ -22,6 +22,10 @@ enum SlideshowVideoPlayback { skip, playMuted, playWithSound }
enum SubtitlePosition { top, bottom } enum SubtitlePosition { top, bottom }
enum ThumbnailOverlayLocationIcon { located, unlocated, none }
enum ThumbnailOverlayTagIcon { tagged, untagged, none }
enum UnitSystem { metric, imperial } enum UnitSystem { metric, imperial }
enum VideoControls { play, playSeek, playOutside, none } enum VideoControls { play, playSeek, playOutside, none }

View file

@ -0,0 +1,29 @@
import 'package:aves/theme/icons.dart';
import 'package:aves/widgets/common/extensions/build_context.dart';
import 'package:flutter/material.dart';
import 'enums.dart';
extension ExtraThumbnailOverlayLocationIcon on ThumbnailOverlayLocationIcon {
String getName(BuildContext context) {
switch (this) {
case ThumbnailOverlayLocationIcon.located:
return context.l10n.thumbnailOverlayLocatedIcon;
case ThumbnailOverlayLocationIcon.unlocated:
return context.l10n.thumbnailOverlayUnlocatedIcon;
case ThumbnailOverlayLocationIcon.none:
return context.l10n.settingsDisabled;
}
}
IconData getIcon(BuildContext context) {
switch (this) {
case ThumbnailOverlayLocationIcon.located:
return AIcons.location;
case ThumbnailOverlayLocationIcon.unlocated:
return AIcons.locationUnlocated;
case ThumbnailOverlayLocationIcon.none:
return AIcons.location;
}
}
}

View file

@ -0,0 +1,29 @@
import 'package:aves/theme/icons.dart';
import 'package:aves/widgets/common/extensions/build_context.dart';
import 'package:flutter/material.dart';
import 'enums.dart';
extension ExtraThumbnailOverlayTagIcon on ThumbnailOverlayTagIcon {
String getName(BuildContext context) {
switch (this) {
case ThumbnailOverlayTagIcon.tagged:
return context.l10n.thumbnailOverlayTaggedIcon;
case ThumbnailOverlayTagIcon.untagged:
return context.l10n.thumbnailOverlayUntaggedIcon;
case ThumbnailOverlayTagIcon.none:
return context.l10n.settingsDisabled;
}
}
IconData getIcon(BuildContext context) {
switch (this) {
case ThumbnailOverlayTagIcon.tagged:
return AIcons.tag;
case ThumbnailOverlayTagIcon.untagged:
return AIcons.tagUntagged;
case ThumbnailOverlayTagIcon.none:
return AIcons.tag;
}
}
}

View file

@ -93,8 +93,8 @@ class Settings extends ChangeNotifier {
static const collectionBrowsingQuickActionsKey = 'collection_browsing_quick_actions'; static const collectionBrowsingQuickActionsKey = 'collection_browsing_quick_actions';
static const collectionSelectionQuickActionsKey = 'collection_selection_quick_actions'; static const collectionSelectionQuickActionsKey = 'collection_selection_quick_actions';
static const showThumbnailFavouriteKey = 'show_thumbnail_favourite'; static const showThumbnailFavouriteKey = 'show_thumbnail_favourite';
static const showThumbnailTagKey = 'show_thumbnail_tag'; static const thumbnailLocationIconKey = 'thumbnail_location_icon';
static const showThumbnailLocationKey = 'show_thumbnail_location'; static const thumbnailTagIconKey = 'thumbnail_tag_icon';
static const showThumbnailMotionPhotoKey = 'show_thumbnail_motion_photo'; static const showThumbnailMotionPhotoKey = 'show_thumbnail_motion_photo';
static const showThumbnailRatingKey = 'show_thumbnail_rating'; static const showThumbnailRatingKey = 'show_thumbnail_rating';
static const showThumbnailRawKey = 'show_thumbnail_raw'; static const showThumbnailRawKey = 'show_thumbnail_raw';
@ -484,14 +484,14 @@ class Settings extends ChangeNotifier {
set showThumbnailFavourite(bool newValue) => setAndNotify(showThumbnailFavouriteKey, newValue); set showThumbnailFavourite(bool newValue) => setAndNotify(showThumbnailFavouriteKey, newValue);
bool get showThumbnailTag => getBool(showThumbnailTagKey) ?? SettingsDefaults.showThumbnailTag; ThumbnailOverlayLocationIcon get thumbnailLocationIcon => getEnumOrDefault(thumbnailLocationIconKey, SettingsDefaults.thumbnailLocationIcon, ThumbnailOverlayLocationIcon.values);
set showThumbnailTag(bool newValue) => setAndNotify(showThumbnailTagKey, newValue); set thumbnailLocationIcon(ThumbnailOverlayLocationIcon newValue) => setAndNotify(thumbnailLocationIconKey, newValue.toString());
bool get showThumbnailLocation => getBool(showThumbnailLocationKey) ?? SettingsDefaults.showThumbnailLocation; ThumbnailOverlayTagIcon get thumbnailTagIcon => getEnumOrDefault(thumbnailTagIconKey, SettingsDefaults.thumbnailTagIcon, ThumbnailOverlayTagIcon.values);
set showThumbnailLocation(bool newValue) => setAndNotify(showThumbnailLocationKey, newValue);
set thumbnailTagIcon(ThumbnailOverlayTagIcon newValue) => setAndNotify(thumbnailTagIconKey, newValue.toString());
bool get showThumbnailMotionPhoto => getBool(showThumbnailMotionPhotoKey) ?? SettingsDefaults.showThumbnailMotionPhoto; bool get showThumbnailMotionPhoto => getBool(showThumbnailMotionPhotoKey) ?? SettingsDefaults.showThumbnailMotionPhoto;
set showThumbnailMotionPhoto(bool newValue) => setAndNotify(showThumbnailMotionPhotoKey, newValue); set showThumbnailMotionPhoto(bool newValue) => setAndNotify(showThumbnailMotionPhotoKey, newValue);
@ -1006,8 +1006,6 @@ class Settings extends ChangeNotifier {
case setMetadataDateBeforeFileOpKey: case setMetadataDateBeforeFileOpKey:
case collectionSortReverseKey: case collectionSortReverseKey:
case showThumbnailFavouriteKey: case showThumbnailFavouriteKey:
case showThumbnailTagKey:
case showThumbnailLocationKey:
case showThumbnailMotionPhotoKey: case showThumbnailMotionPhotoKey:
case showThumbnailRatingKey: case showThumbnailRatingKey:
case showThumbnailRawKey: case showThumbnailRawKey:
@ -1054,6 +1052,8 @@ class Settings extends ChangeNotifier {
case homePageKey: case homePageKey:
case collectionGroupFactorKey: case collectionGroupFactorKey:
case collectionSortFactorKey: case collectionSortFactorKey:
case thumbnailLocationIconKey:
case thumbnailTagIconKey:
case albumGroupFactorKey: case albumGroupFactorKey:
case albumSortFactorKey: case albumSortFactorKey:
case countrySortFactorKey: case countrySortFactorKey:

View file

@ -40,6 +40,7 @@ class AboutTranslators extends StatelessWidget {
Contributor('Linerly', 'linerly@protonmail.com'), Contributor('Linerly', 'linerly@protonmail.com'),
Contributor('Olexandr Mazur', 'rozihrash.ya6w7@simplelogin.com'), Contributor('Olexandr Mazur', 'rozihrash.ya6w7@simplelogin.com'),
Contributor('vesp', 'vesp@post.cz'), Contributor('vesp', 'vesp@post.cz'),
Contributor('Dan', 'denqwerta@gmail.com'),
// Contributor('SAMIRAH AIL', 'samiratalzahrani@gmail.com'), // Arabic // Contributor('SAMIRAH AIL', 'samiratalzahrani@gmail.com'), // Arabic
// Contributor('Salih Ail', 'rrrfff444@gmail.com'), // Arabic // Contributor('Salih Ail', 'rrrfff444@gmail.com'), // Arabic
// Contributor('Piotr K', '1337.kelt@gmail.com'), // Polish // Contributor('Piotr K', '1337.kelt@gmail.com'), // Polish

View file

@ -1,5 +1,7 @@
import 'dart:math'; import 'dart:math';
import 'package:aves/model/entry.dart';
import 'package:aves/model/settings/enums/enums.dart';
import 'package:aves/model/settings/settings.dart'; import 'package:aves/model/settings/settings.dart';
import 'package:aves/widgets/common/identity/aves_icons.dart'; import 'package:aves/widgets/common/identity/aves_icons.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@ -7,13 +9,14 @@ import 'package:provider/provider.dart';
class GridTheme extends StatelessWidget { class GridTheme extends StatelessWidget {
final double extent; final double extent;
final bool? showLocation, showTrash; final bool showLocation;
final bool? showTrash;
final Widget child; final Widget child;
const GridTheme({ const GridTheme({
super.key, super.key,
required this.extent, required this.extent,
this.showLocation, this.showLocation = true,
this.showTrash, this.showTrash,
required this.child, required this.child,
}); });
@ -32,11 +35,11 @@ class GridTheme extends StatelessWidget {
fontSize: fontSize, fontSize: fontSize,
highlightBorderWidth: highlightBorderWidth, highlightBorderWidth: highlightBorderWidth,
showFavourite: settings.showThumbnailFavourite, showFavourite: settings.showThumbnailFavourite,
showLocation: showLocation ?? settings.showThumbnailLocation, locationIcon: showLocation ? settings.thumbnailLocationIcon : ThumbnailOverlayLocationIcon.none,
tagIcon: settings.thumbnailTagIcon,
showMotionPhoto: settings.showThumbnailMotionPhoto, showMotionPhoto: settings.showThumbnailMotionPhoto,
showRating: settings.showThumbnailRating, showRating: settings.showThumbnailRating,
showRaw: settings.showThumbnailRaw, showRaw: settings.showThumbnailRaw,
showTag: settings.showThumbnailTag,
showTrash: showTrash ?? true, showTrash: showTrash ?? true,
showVideoDuration: settings.showThumbnailVideoDuration, showVideoDuration: settings.showThumbnailVideoDuration,
); );
@ -46,21 +49,55 @@ class GridTheme extends StatelessWidget {
} }
} }
typedef GridThemeIconBuilder = List<Widget> Function(BuildContext context, AvesEntry entry);
class GridThemeData { class GridThemeData {
final double iconSize, fontSize, highlightBorderWidth; final double iconSize, fontSize, highlightBorderWidth;
final bool showFavourite, showLocation, showMotionPhoto, showRating, showRaw, showTag, showTrash, showVideoDuration; final bool showFavourite, showMotionPhoto, showRating, showRaw, showTrash, showVideoDuration;
final bool showLocated, showUnlocated, showTagged, showUntagged;
late final GridThemeIconBuilder iconBuilder;
const GridThemeData({ GridThemeData({
required this.iconSize, required this.iconSize,
required this.fontSize, required this.fontSize,
required this.highlightBorderWidth, required this.highlightBorderWidth,
required this.showFavourite, required this.showFavourite,
required this.showLocation, required ThumbnailOverlayLocationIcon locationIcon,
required ThumbnailOverlayTagIcon tagIcon,
required this.showMotionPhoto, required this.showMotionPhoto,
required this.showRating, required this.showRating,
required this.showRaw, required this.showRaw,
required this.showTag,
required this.showTrash, required this.showTrash,
required this.showVideoDuration, required this.showVideoDuration,
}); }) : showLocated = locationIcon == ThumbnailOverlayLocationIcon.located,
showUnlocated = locationIcon == ThumbnailOverlayLocationIcon.unlocated,
showTagged = tagIcon == ThumbnailOverlayTagIcon.tagged,
showUntagged = tagIcon == ThumbnailOverlayTagIcon.untagged {
iconBuilder = (context, entry) {
final located = entry.hasGps;
final tagged = entry.tags.isNotEmpty;
return [
if (entry.isFavourite && showFavourite) const FavouriteIcon(),
if (tagged && showTagged) TagIcon.tagged(),
if (!tagged && showUntagged) TagIcon.untagged(),
if (located && showLocated) LocationIcon.located(),
if (!located && showUnlocated) LocationIcon.unlocated(),
if (entry.rating != 0 && showRating) RatingIcon(entry: entry),
if (entry.isVideo)
VideoIcon(entry: entry)
else if (entry.isAnimated)
const AnimatedImageIcon()
else ...[
if (entry.isRaw && showRaw) const RawIcon(),
if (entry.is360) const PanoramaIcon(),
],
if (entry.isMultiPage) ...[
if (entry.isMotionPhoto && showMotionPhoto) const MotionPhotoIcon(),
if (!entry.isMotionPhoto) MultiPageIcon(entry: entry),
],
if (entry.isGeotiff) const GeoTiffIcon(),
if (entry.trashed && showTrash) TrashIcon(trashDaysLeft: entry.trashDaysLeft),
];
};
}
} }

View file

@ -91,27 +91,39 @@ class FavouriteIcon extends StatelessWidget {
} }
class TagIcon extends StatelessWidget { class TagIcon extends StatelessWidget {
const TagIcon({super.key}); final IconData icon;
const TagIcon._private({required this.icon});
factory TagIcon.tagged() => const TagIcon._private(icon: AIcons.tag);
factory TagIcon.untagged() => const TagIcon._private(icon: AIcons.tagUntagged);
static const scale = .9; static const scale = .9;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return const OverlayIcon( return OverlayIcon(
icon: AIcons.tag, icon: icon,
iconScale: scale, iconScale: scale,
relativeOffset: Offset(.05, .05), relativeOffset: const Offset(.05, .05),
); );
} }
} }
class GpsIcon extends StatelessWidget { class LocationIcon extends StatelessWidget {
const GpsIcon({super.key}); final IconData icon;
const LocationIcon._private({required this.icon});
factory LocationIcon.located() => const LocationIcon._private(icon: AIcons.location);
factory LocationIcon.unlocated() => const LocationIcon._private(icon: AIcons.locationUnlocated);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return const OverlayIcon( return OverlayIcon(
icon: AIcons.location, icon: icon,
); );
} }
} }
@ -181,10 +193,9 @@ class RatingIcon extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final gridTheme = context.watch<GridThemeData>();
return DefaultTextStyle( return DefaultTextStyle(
style: TextStyle( style: TextStyle(
fontSize: gridTheme.fontSize, fontSize: context.select<GridThemeData, double>((t) => t.fontSize),
), ),
child: OverlayIcon( child: OverlayIcon(
icon: AIcons.rating, icon: AIcons.rating,

View file

@ -4,7 +4,6 @@ import 'package:aves/model/entry.dart';
import 'package:aves/model/highlight.dart'; import 'package:aves/model/highlight.dart';
import 'package:aves/widgets/common/fx/sweeper.dart'; import 'package:aves/widgets/common/fx/sweeper.dart';
import 'package:aves/widgets/common/grid/theme.dart'; import 'package:aves/widgets/common/grid/theme.dart';
import 'package:aves/widgets/common/identity/aves_icons.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
@ -18,26 +17,8 @@ class ThumbnailEntryOverlay extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final children = [ final iconBuilder = context.select<GridThemeData, GridThemeIconBuilder>((t) => t.iconBuilder);
if (entry.isFavourite && context.select<GridThemeData, bool>((t) => t.showFavourite)) const FavouriteIcon(), final children = iconBuilder(context, entry);
if (entry.tags.isNotEmpty && context.select<GridThemeData, bool>((t) => t.showTag)) const TagIcon(),
if (entry.hasGps && context.select<GridThemeData, bool>((t) => t.showLocation)) const GpsIcon(),
if (entry.rating != 0 && context.select<GridThemeData, bool>((t) => t.showRating)) RatingIcon(entry: entry),
if (entry.isVideo)
VideoIcon(entry: entry)
else if (entry.isAnimated)
const AnimatedImageIcon()
else ...[
if (entry.isRaw && context.select<GridThemeData, bool>((t) => t.showRaw)) const RawIcon(),
if (entry.is360) const PanoramaIcon(),
],
if (entry.isMultiPage) ...[
if (entry.isMotionPhoto && context.select<GridThemeData, bool>((t) => t.showMotionPhoto)) const MotionPhotoIcon(),
if (!entry.isMotionPhoto) MultiPageIcon(entry: entry),
],
if (entry.isGeotiff) const GeoTiffIcon(),
if (entry.trashed && context.select<GridThemeData, bool>((t) => t.showTrash)) TrashIcon(trashDaysLeft: entry.trashDaysLeft),
];
if (children.isEmpty) return const SizedBox(); if (children.isEmpty) return const SizedBox();
return Align( return Align(
alignment: AlignmentDirectional.bottomStart, alignment: AlignmentDirectional.bottomStart,

View file

@ -1,7 +1,6 @@
import 'dart:math'; import 'dart:math';
import 'package:aves/model/entry.dart'; import 'package:aves/model/entry.dart';
import 'package:aves/model/settings/settings.dart';
import 'package:aves/theme/durations.dart'; import 'package:aves/theme/durations.dart';
import 'package:aves/widgets/common/behaviour/known_extent_scroll_physics.dart'; import 'package:aves/widgets/common/behaviour/known_extent_scroll_physics.dart';
import 'package:aves/widgets/common/grid/theme.dart'; import 'package:aves/widgets/common/grid/theme.dart';
@ -95,7 +94,7 @@ class _ThumbnailScrollerState extends State<ThumbnailScroller> {
return GridTheme( return GridTheme(
extent: thumbnailExtent, extent: thumbnailExtent,
showLocation: widget.showLocation && settings.showThumbnailLocation, showLocation: widget.showLocation,
showTrash: false, showTrash: false,
child: SizedBox( child: SizedBox(
width: scrollable ? null : widthFor(entryCount), width: scrollable ? null : widthFor(entryCount),

View file

@ -43,6 +43,8 @@ class SettingsSwitchListTile extends StatelessWidget {
final String? subtitle; final String? subtitle;
final Widget? trailing; final Widget? trailing;
static const disabledOpacity = .2;
const SettingsSwitchListTile({ const SettingsSwitchListTile({
super.key, super.key,
required this.selector, required this.selector,
@ -63,7 +65,7 @@ class SettingsSwitchListTile extends StatelessWidget {
children: [ children: [
Expanded(child: titleWidget), Expanded(child: titleWidget),
AnimatedOpacity( AnimatedOpacity(
opacity: current ? 1 : .2, opacity: current ? 1 : disabledOpacity,
duration: Durations.toggleableTransitionAnimation, duration: Durations.toggleableTransitionAnimation,
child: trailing, child: trailing,
), ),
@ -87,6 +89,7 @@ class SettingsSelectionListTile<T extends Enum> extends StatelessWidget {
final T Function(BuildContext, Settings) selector; final T Function(BuildContext, Settings) selector;
final ValueChanged<T> onSelection; final ValueChanged<T> onSelection;
final String tileTitle; final String tileTitle;
final WidgetBuilder? trailingBuilder;
final String? dialogTitle; final String? dialogTitle;
final TextBuilder<T>? optionSubtitleBuilder; final TextBuilder<T>? optionSubtitleBuilder;
@ -97,6 +100,7 @@ class SettingsSelectionListTile<T extends Enum> extends StatelessWidget {
required this.selector, required this.selector,
required this.onSelection, required this.onSelection,
required this.tileTitle, required this.tileTitle,
this.trailingBuilder,
this.dialogTitle, this.dialogTitle,
this.optionSubtitleBuilder, this.optionSubtitleBuilder,
}); });
@ -105,20 +109,31 @@ class SettingsSelectionListTile<T extends Enum> extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Selector<Settings, T>( return Selector<Settings, T>(
selector: selector, selector: selector,
builder: (context, current, child) => ListTile( builder: (context, current, child) {
title: Text(tileTitle), Widget titleWidget = Text(tileTitle);
subtitle: AvesCaption(getName(context, current)), if (trailingBuilder != null) {
onTap: () => showSelectionDialog<T>( titleWidget = Row(
context: context, children: [
builder: (context) => AvesSelectionDialog<T>( Expanded(child: titleWidget),
initialValue: current, trailingBuilder!(context),
options: Map.fromEntries(values.map((v) => MapEntry(v, getName(context, v)))), ],
optionSubtitleBuilder: optionSubtitleBuilder, );
title: dialogTitle, }
return ListTile(
title: titleWidget,
subtitle: AvesCaption(getName(context, current)),
onTap: () => showSelectionDialog<T>(
context: context,
builder: (context) => AvesSelectionDialog<T>(
initialValue: current,
options: Map.fromEntries(values.map((v) => MapEntry(v, getName(context, v)))),
optionSubtitleBuilder: optionSubtitleBuilder,
title: dialogTitle,
),
onSelection: onSelection,
), ),
onSelection: onSelection, );
), },
),
); );
} }
} }

View file

@ -1,9 +1,14 @@
import 'package:aves/model/settings/enums/enums.dart';
import 'package:aves/model/settings/enums/thumbnail_overlay_location_icon.dart';
import 'package:aves/model/settings/enums/thumbnail_overlay_tag_icon.dart';
import 'package:aves/model/settings/settings.dart'; import 'package:aves/model/settings/settings.dart';
import 'package:aves/theme/colors.dart'; import 'package:aves/theme/colors.dart';
import 'package:aves/theme/durations.dart';
import 'package:aves/theme/icons.dart'; import 'package:aves/theme/icons.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_icons.dart'; import 'package:aves/widgets/common/identity/aves_icons.dart';
import 'package:aves/widgets/settings/common/tiles.dart'; import 'package:aves/widgets/settings/common/tiles.dart';
import 'package:aves/widgets/settings/settings_definition.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
@ -14,8 +19,8 @@ class ThumbnailOverlayPage extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final iconSize = IconTheme.of(context).size! * MediaQuery.textScaleFactorOf(context); final iconSize = _getIconSize(context);
final iconColor = context.select<AvesColorsData, Color>((v) => v.neutral); final iconColor = _getIconColor(context);
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
@ -38,29 +43,6 @@ class ThumbnailOverlayPage extends StatelessWidget {
), ),
), ),
), ),
SettingsSwitchListTile(
selector: (context, s) => s.showThumbnailTag,
onChanged: (v) => settings.showThumbnailTag = v,
title: context.l10n.settingsThumbnailShowTagIcon,
trailing: Padding(
padding: EdgeInsets.symmetric(horizontal: iconSize * (1 - TagIcon.scale) / 2),
child: Icon(
AIcons.tag,
size: iconSize * TagIcon.scale,
color: iconColor,
),
),
),
SettingsSwitchListTile(
selector: (context, s) => s.showThumbnailLocation,
onChanged: (v) => settings.showThumbnailLocation = v,
title: context.l10n.settingsThumbnailShowLocationIcon,
trailing: Icon(
AIcons.location,
size: iconSize,
color: iconColor,
),
),
SettingsSwitchListTile( SettingsSwitchListTile(
selector: (context, s) => s.showThumbnailMotionPhoto, selector: (context, s) => s.showThumbnailMotionPhoto,
onChanged: (v) => settings.showThumbnailMotionPhoto = v, onChanged: (v) => settings.showThumbnailMotionPhoto = v,
@ -99,9 +81,86 @@ class ThumbnailOverlayPage extends StatelessWidget {
onChanged: (v) => settings.showThumbnailVideoDuration = v, onChanged: (v) => settings.showThumbnailVideoDuration = v,
title: context.l10n.settingsThumbnailShowVideoDuration, title: context.l10n.settingsThumbnailShowVideoDuration,
), ),
SettingsTileThumbnailLocationIcon().build(context),
SettingsTileThumbnailTagIcon().build(context),
], ],
), ),
), ),
); );
} }
static double _getIconSize(BuildContext context) => IconTheme.of(context).size! * MediaQuery.textScaleFactorOf(context);
static Color _getIconColor(BuildContext context) => context.select<AvesColorsData, Color>((v) => v.neutral);
static Widget buildTrailingIcon({
required BuildContext context,
required Object key,
required IconData icon,
required bool disabled,
}) {
return Padding(
// Switch width (`_kSwitchWidth`) + tile content padding
padding: const EdgeInsetsDirectional.only(end: 59 + 16),
child: AnimatedSwitcher(
duration: context.read<DurationsData>().iconAnimation,
child: Icon(
icon,
key: ValueKey(key),
size: _getIconSize(context),
color: _getIconColor(context).withOpacity(disabled ? SettingsSwitchListTile.disabledOpacity : 1.0),
),
),
);
}
}
class SettingsTileThumbnailLocationIcon extends SettingsTile {
@override
String title(BuildContext context) => context.l10n.settingsThumbnailShowLocationIcon;
@override
Widget build(BuildContext context) => SettingsSelectionListTile<ThumbnailOverlayLocationIcon>(
values: ThumbnailOverlayLocationIcon.values,
getName: (context, v) => v.getName(context),
selector: (context, s) => s.thumbnailLocationIcon,
onSelection: (v) => settings.thumbnailLocationIcon = v,
tileTitle: title(context),
trailingBuilder: _buildTrailing,
);
Widget _buildTrailing(BuildContext context) {
final iconType = context.select<Settings, ThumbnailOverlayLocationIcon>((s) => s.thumbnailLocationIcon);
return ThumbnailOverlayPage.buildTrailingIcon(
context: context,
key: iconType,
icon: iconType.getIcon(context),
disabled: iconType == ThumbnailOverlayLocationIcon.none,
);
}
}
class SettingsTileThumbnailTagIcon extends SettingsTile {
@override
String title(BuildContext context) => context.l10n.settingsThumbnailShowTagIcon;
@override
Widget build(BuildContext context) => SettingsSelectionListTile<ThumbnailOverlayTagIcon>(
values: ThumbnailOverlayTagIcon.values,
getName: (context, v) => v.getName(context),
selector: (context, s) => s.thumbnailTagIcon,
onSelection: (v) => settings.thumbnailTagIcon = v,
tileTitle: title(context),
trailingBuilder: _buildTrailing,
);
Widget _buildTrailing(BuildContext context) {
final iconType = context.select<Settings, ThumbnailOverlayTagIcon>((s) => s.thumbnailTagIcon);
return ThumbnailOverlayPage.buildTrailingIcon(
context: context,
key: iconType,
icon: iconType.getIcon(context),
disabled: iconType == ThumbnailOverlayTagIcon.none,
);
}
} }

View file

@ -39,8 +39,8 @@ Future<void> configureAndLaunch() async {
..collectionSortFactor = EntrySortFactor.date ..collectionSortFactor = EntrySortFactor.date
..collectionBrowsingQuickActions = SettingsDefaults.collectionBrowsingQuickActions ..collectionBrowsingQuickActions = SettingsDefaults.collectionBrowsingQuickActions
..showThumbnailFavourite = false ..showThumbnailFavourite = false
..showThumbnailTag = false ..thumbnailLocationIcon = ThumbnailOverlayLocationIcon.none
..showThumbnailLocation = false ..thumbnailTagIcon = ThumbnailOverlayTagIcon.none
..hiddenFilters = {} ..hiddenFilters = {}
// viewer // viewer
..viewerQuickActions = SettingsDefaults.viewerQuickActions ..viewerQuickActions = SettingsDefaults.viewerQuickActions

View file

@ -148,6 +148,10 @@
"displayRefreshRatePreferLowest", "displayRefreshRatePreferLowest",
"subtitlePositionTop", "subtitlePositionTop",
"subtitlePositionBottom", "subtitlePositionBottom",
"thumbnailOverlayLocatedIcon",
"thumbnailOverlayUnlocatedIcon",
"thumbnailOverlayTaggedIcon",
"thumbnailOverlayUntaggedIcon",
"videoPlaybackSkip", "videoPlaybackSkip",
"videoPlaybackMuted", "videoPlaybackMuted",
"videoPlaybackWithSound", "videoPlaybackWithSound",
@ -594,6 +598,10 @@
], ],
"cs": [ "cs": [
"thumbnailOverlayLocatedIcon",
"thumbnailOverlayUnlocatedIcon",
"thumbnailOverlayTaggedIcon",
"thumbnailOverlayUntaggedIcon",
"settingsModificationWarningDialogMessage", "settingsModificationWarningDialogMessage",
"settingsViewerShowDescription", "settingsViewerShowDescription",
"settingsDisplayUseTvInterface" "settingsDisplayUseTvInterface"
@ -601,6 +609,10 @@
"de": [ "de": [
"columnCount", "columnCount",
"thumbnailOverlayLocatedIcon",
"thumbnailOverlayUnlocatedIcon",
"thumbnailOverlayTaggedIcon",
"thumbnailOverlayUntaggedIcon",
"settingsModificationWarningDialogMessage", "settingsModificationWarningDialogMessage",
"settingsViewerShowDescription", "settingsViewerShowDescription",
"settingsAccessibilityShowPinchGestureAlternatives", "settingsAccessibilityShowPinchGestureAlternatives",
@ -608,15 +620,20 @@
], ],
"el": [ "el": [
"thumbnailOverlayLocatedIcon",
"thumbnailOverlayUnlocatedIcon",
"thumbnailOverlayTaggedIcon",
"thumbnailOverlayUntaggedIcon",
"settingsModificationWarningDialogMessage", "settingsModificationWarningDialogMessage",
"settingsViewerShowDescription", "settingsViewerShowDescription",
"settingsDisplayUseTvInterface" "settingsDisplayUseTvInterface"
], ],
"es": [ "es": [
"settingsModificationWarningDialogMessage", "thumbnailOverlayLocatedIcon",
"settingsViewerShowDescription", "thumbnailOverlayUnlocatedIcon",
"settingsDisplayUseTvInterface" "thumbnailOverlayTaggedIcon",
"thumbnailOverlayUntaggedIcon"
], ],
"fa": [ "fa": [
@ -664,6 +681,10 @@
"displayRefreshRatePreferLowest", "displayRefreshRatePreferLowest",
"subtitlePositionTop", "subtitlePositionTop",
"subtitlePositionBottom", "subtitlePositionBottom",
"thumbnailOverlayLocatedIcon",
"thumbnailOverlayUnlocatedIcon",
"thumbnailOverlayTaggedIcon",
"thumbnailOverlayUntaggedIcon",
"videoPlaybackSkip", "videoPlaybackSkip",
"videoPlaybackMuted", "videoPlaybackMuted",
"videoPlaybackWithSound", "videoPlaybackWithSound",
@ -1087,8 +1108,10 @@
], ],
"fr": [ "fr": [
"settingsModificationWarningDialogMessage", "thumbnailOverlayLocatedIcon",
"settingsDisplayUseTvInterface" "thumbnailOverlayUnlocatedIcon",
"thumbnailOverlayTaggedIcon",
"thumbnailOverlayUntaggedIcon"
], ],
"gl": [ "gl": [
@ -1107,6 +1130,10 @@
"displayRefreshRatePreferLowest", "displayRefreshRatePreferLowest",
"subtitlePositionTop", "subtitlePositionTop",
"subtitlePositionBottom", "subtitlePositionBottom",
"thumbnailOverlayLocatedIcon",
"thumbnailOverlayUnlocatedIcon",
"thumbnailOverlayTaggedIcon",
"thumbnailOverlayUntaggedIcon",
"videoPlaybackSkip", "videoPlaybackSkip",
"videoPlaybackMuted", "videoPlaybackMuted",
"videoPlaybackWithSound", "videoPlaybackWithSound",
@ -1562,12 +1589,17 @@
], ],
"id": [ "id": [
"settingsModificationWarningDialogMessage", "thumbnailOverlayLocatedIcon",
"settingsViewerShowDescription", "thumbnailOverlayUnlocatedIcon",
"settingsDisplayUseTvInterface" "thumbnailOverlayTaggedIcon",
"thumbnailOverlayUntaggedIcon"
], ],
"it": [ "it": [
"thumbnailOverlayLocatedIcon",
"thumbnailOverlayUnlocatedIcon",
"thumbnailOverlayTaggedIcon",
"thumbnailOverlayUntaggedIcon",
"settingsModificationWarningDialogMessage", "settingsModificationWarningDialogMessage",
"settingsViewerShowDescription", "settingsViewerShowDescription",
"settingsDisplayUseTvInterface" "settingsDisplayUseTvInterface"
@ -1582,6 +1614,10 @@
"keepScreenOnVideoPlayback", "keepScreenOnVideoPlayback",
"subtitlePositionTop", "subtitlePositionTop",
"subtitlePositionBottom", "subtitlePositionBottom",
"thumbnailOverlayLocatedIcon",
"thumbnailOverlayUnlocatedIcon",
"thumbnailOverlayTaggedIcon",
"thumbnailOverlayUntaggedIcon",
"settingsModificationWarningDialogMessage", "settingsModificationWarningDialogMessage",
"settingsViewerShowDescription", "settingsViewerShowDescription",
"settingsAccessibilityShowPinchGestureAlternatives", "settingsAccessibilityShowPinchGestureAlternatives",
@ -1590,13 +1626,19 @@
], ],
"ko": [ "ko": [
"settingsModificationWarningDialogMessage", "thumbnailOverlayLocatedIcon",
"settingsDisplayUseTvInterface" "thumbnailOverlayUnlocatedIcon",
"thumbnailOverlayTaggedIcon",
"thumbnailOverlayUntaggedIcon"
], ],
"lt": [ "lt": [
"columnCount", "columnCount",
"keepScreenOnVideoPlayback", "keepScreenOnVideoPlayback",
"thumbnailOverlayLocatedIcon",
"thumbnailOverlayUnlocatedIcon",
"thumbnailOverlayTaggedIcon",
"thumbnailOverlayUntaggedIcon",
"settingsModificationWarningDialogMessage", "settingsModificationWarningDialogMessage",
"settingsViewerShowDescription", "settingsViewerShowDescription",
"settingsAccessibilityShowPinchGestureAlternatives", "settingsAccessibilityShowPinchGestureAlternatives",
@ -1609,6 +1651,10 @@
"entryActionShareVideoOnly", "entryActionShareVideoOnly",
"entryInfoActionRemoveLocation", "entryInfoActionRemoveLocation",
"keepScreenOnVideoPlayback", "keepScreenOnVideoPlayback",
"thumbnailOverlayLocatedIcon",
"thumbnailOverlayUnlocatedIcon",
"thumbnailOverlayTaggedIcon",
"thumbnailOverlayUntaggedIcon",
"settingsModificationWarningDialogMessage", "settingsModificationWarningDialogMessage",
"settingsViewerShowDescription", "settingsViewerShowDescription",
"settingsAccessibilityShowPinchGestureAlternatives", "settingsAccessibilityShowPinchGestureAlternatives",
@ -1627,6 +1673,10 @@
"keepScreenOnVideoPlayback", "keepScreenOnVideoPlayback",
"subtitlePositionTop", "subtitlePositionTop",
"subtitlePositionBottom", "subtitlePositionBottom",
"thumbnailOverlayLocatedIcon",
"thumbnailOverlayUnlocatedIcon",
"thumbnailOverlayTaggedIcon",
"thumbnailOverlayUntaggedIcon",
"widgetDisplayedItemRandom", "widgetDisplayedItemRandom",
"widgetDisplayedItemMostRecent", "widgetDisplayedItemMostRecent",
"settingsModificationWarningDialogMessage", "settingsModificationWarningDialogMessage",
@ -1641,90 +1691,24 @@
"nn": [ "nn": [
"columnCount", "columnCount",
"sourceStateLoading",
"sourceStateCataloguing", "sourceStateCataloguing",
"entryActionShareImageOnly",
"entryActionShareVideoOnly",
"entryInfoActionRemoveLocation", "entryInfoActionRemoveLocation",
"filterBinLabel",
"filterNoLocationLabel", "filterNoLocationLabel",
"filterTypeAnimatedLabel",
"filterTypeMotionPhotoLabel",
"filterTypePanoramaLabel",
"mapStyleOsmHot",
"mapStyleStamenToner",
"keepScreenOnVideoPlayback",
"accessibilityAnimationsKeep", "accessibilityAnimationsKeep",
"displayRefreshRatePreferHighest", "displayRefreshRatePreferHighest",
"displayRefreshRatePreferLowest", "displayRefreshRatePreferLowest",
"themeBrightnessLight", "thumbnailOverlayLocatedIcon",
"themeBrightnessDark", "thumbnailOverlayUnlocatedIcon",
"themeBrightnessBlack", "thumbnailOverlayTaggedIcon",
"viewerTransitionSlide", "thumbnailOverlayUntaggedIcon",
"viewerTransitionParallax",
"viewerTransitionFade",
"wallpaperTargetHome", "wallpaperTargetHome",
"wallpaperTargetHomeLock", "wallpaperTargetHomeLock",
"widgetDisplayedItemRandom",
"widgetOpenPageHome",
"restrictedAccessDialogMessage",
"notEnoughSpaceDialogMessage",
"missingSystemFilePickerDialogMessage",
"unsupportedTypeDialogMessage",
"nameConflictDialogSingleSourceMessage",
"nameConflictDialogMultipleSourceMessage",
"addShortcutDialogLabel",
"addShortcutButtonLabel",
"noMatchingAppDialogMessage",
"binEntriesConfirmationDialogMessage",
"deleteEntriesConfirmationDialogMessage",
"moveUndatedConfirmationDialogMessage",
"moveUndatedConfirmationDialogSetDate",
"videoResumeDialogMessage",
"videoStartOverButtonLabel",
"videoResumeButtonLabel",
"setCoverDialogLatest",
"setCoverDialogAuto",
"setCoverDialogCustom", "setCoverDialogCustom",
"hideFilterConfirmationDialogMessage",
"newAlbumDialogTitle",
"newAlbumDialogNameLabel",
"newAlbumDialogNameLabelAlreadyExistsHelper",
"newAlbumDialogStorageLabel",
"renameAlbumDialogLabel",
"renameAlbumDialogLabelAlreadyExistsHelper",
"renameEntrySetPageTitle",
"renameEntrySetPagePatternFieldLabel",
"renameEntrySetPageInsertTooltip",
"renameEntrySetPagePreviewSectionTitle",
"renameProcessorCounter",
"renameProcessorName",
"deleteSingleAlbumConfirmationDialogMessage",
"deleteMultiAlbumConfirmationDialogMessage",
"exportEntryDialogFormat",
"exportEntryDialogWidth",
"exportEntryDialogHeight",
"renameEntryDialogLabel",
"editEntryDialogCopyFromItem",
"editEntryDialogTargetFieldsHeader", "editEntryDialogTargetFieldsHeader",
"editEntryDateDialogTitle",
"editEntryDateDialogSetCustom", "editEntryDateDialogSetCustom",
"editEntryDateDialogCopyField",
"editEntryDateDialogExtractFromTitle",
"editEntryDateDialogShift",
"editEntryDateDialogSourceFileModifiedDate",
"durationDialogHours",
"durationDialogMinutes",
"durationDialogSeconds",
"editEntryLocationDialogTitle", "editEntryLocationDialogTitle",
"editEntryLocationDialogSetCustom", "editEntryLocationDialogSetCustom",
"editEntryLocationDialogChooseOnMap",
"editEntryLocationDialogLatitude",
"editEntryLocationDialogLongitude",
"locationPickerUseThisLocationButton", "locationPickerUseThisLocationButton",
"editEntryRatingDialogTitle",
"removeEntryMetadataDialogTitle",
"removeEntryMetadataDialogMore",
"removeEntryMetadataMotionPhotoXmpWarningDialogMessage", "removeEntryMetadataMotionPhotoXmpWarningDialogMessage",
"videoSpeedDialogLabel", "videoSpeedDialogLabel",
"videoStreamSelectionDialogVideo", "videoStreamSelectionDialogVideo",
@ -2010,86 +1994,25 @@
"settingsRemoveAnimationsDialogTitle", "settingsRemoveAnimationsDialogTitle",
"settingsTimeToTakeActionTile", "settingsTimeToTakeActionTile",
"settingsAccessibilityShowPinchGestureAlternatives", "settingsAccessibilityShowPinchGestureAlternatives",
"settingsDisplaySectionTitle",
"settingsThemeBrightnessTile", "settingsThemeBrightnessTile",
"settingsThemeBrightnessDialogTitle", "settingsThemeBrightnessDialogTitle",
"settingsThemeColorHighlights",
"settingsThemeEnableDynamicColor", "settingsThemeEnableDynamicColor",
"settingsDisplayRefreshRateModeTile", "settingsDisplayRefreshRateModeTile",
"settingsDisplayRefreshRateModeDialogTitle", "settingsDisplayRefreshRateModeDialogTitle",
"settingsDisplayUseTvInterface", "settingsDisplayUseTvInterface",
"settingsLanguageSectionTitle",
"settingsLanguageTile",
"settingsLanguagePageTitle",
"settingsCoordinateFormatTile",
"settingsCoordinateFormatDialogTitle",
"settingsUnitSystemTile",
"settingsUnitSystemDialogTitle",
"settingsScreenSaverPageTitle",
"settingsWidgetPageTitle",
"settingsWidgetShowOutline",
"settingsWidgetOpenPage", "settingsWidgetOpenPage",
"settingsWidgetDisplayedItem",
"settingsCollectionTile",
"statsPageTitle",
"statsWithGps", "statsWithGps",
"statsTopCountriesSectionTitle",
"statsTopPlacesSectionTitle",
"statsTopTagsSectionTitle",
"statsTopAlbumsSectionTitle",
"viewerOpenPanoramaButtonLabel",
"viewerSetWallpaperButtonLabel",
"viewerErrorUnknown",
"viewerErrorDoesNotExist",
"viewerInfoPageTitle", "viewerInfoPageTitle",
"viewerInfoBackToViewerTooltip",
"viewerInfoUnknown",
"viewerInfoLabelDescription", "viewerInfoLabelDescription",
"viewerInfoLabelTitle",
"viewerInfoLabelDate",
"viewerInfoLabelResolution",
"viewerInfoLabelSize",
"viewerInfoLabelUri",
"viewerInfoLabelPath",
"viewerInfoLabelDuration",
"viewerInfoLabelOwner",
"viewerInfoLabelCoordinates",
"viewerInfoLabelAddress",
"mapStyleDialogTitle",
"mapStyleTooltip",
"mapZoomInTooltip",
"mapZoomOutTooltip",
"mapPointNorthUpTooltip", "mapPointNorthUpTooltip",
"mapAttributionOsmHot", "mapAttributionOsmHot",
"mapAttributionStamen", "mapAttributionStamen",
"openMapPageTooltip",
"mapEmptyRegion", "mapEmptyRegion",
"viewerInfoOpenEmbeddedFailureFeedback", "viewerInfoOpenEmbeddedFailureFeedback",
"viewerInfoOpenLinkText",
"viewerInfoViewXmlLinkText",
"viewerInfoSearchFieldLabel",
"viewerInfoSearchEmpty",
"viewerInfoSearchSuggestionDate",
"viewerInfoSearchSuggestionDescription", "viewerInfoSearchSuggestionDescription",
"viewerInfoSearchSuggestionDimensions", "viewerInfoSearchSuggestionDimensions",
"viewerInfoSearchSuggestionResolution",
"viewerInfoSearchSuggestionRights",
"wallpaperUseScrollEffect", "wallpaperUseScrollEffect",
"tagEditorPageTitle", "tagEditorSectionPlaceholders"
"tagEditorPageNewTagFieldLabel",
"tagEditorPageAddTagTooltip",
"tagEditorSectionRecent",
"tagEditorSectionPlaceholders",
"tagPlaceholderCountry",
"tagPlaceholderPlace",
"panoramaEnableSensorControl",
"panoramaDisableSensorControl",
"sourceViewerPageTitle",
"filePickerShowHiddenFiles",
"filePickerDoNotShowHiddenFiles",
"filePickerOpenFrom",
"filePickerNoItems",
"filePickerUseThisFolder"
], ],
"pl": [ "pl": [
@ -2148,6 +2071,10 @@
"displayRefreshRatePreferLowest", "displayRefreshRatePreferLowest",
"subtitlePositionTop", "subtitlePositionTop",
"subtitlePositionBottom", "subtitlePositionBottom",
"thumbnailOverlayLocatedIcon",
"thumbnailOverlayUnlocatedIcon",
"thumbnailOverlayTaggedIcon",
"thumbnailOverlayUntaggedIcon",
"videoPlaybackSkip", "videoPlaybackSkip",
"videoPlaybackMuted", "videoPlaybackMuted",
"videoPlaybackWithSound", "videoPlaybackWithSound",
@ -2614,6 +2541,10 @@
"keepScreenOnVideoPlayback", "keepScreenOnVideoPlayback",
"subtitlePositionTop", "subtitlePositionTop",
"subtitlePositionBottom", "subtitlePositionBottom",
"thumbnailOverlayLocatedIcon",
"thumbnailOverlayUnlocatedIcon",
"thumbnailOverlayTaggedIcon",
"thumbnailOverlayUntaggedIcon",
"widgetDisplayedItemRandom", "widgetDisplayedItemRandom",
"widgetDisplayedItemMostRecent", "widgetDisplayedItemMostRecent",
"settingsModificationWarningDialogMessage", "settingsModificationWarningDialogMessage",
@ -2627,12 +2558,19 @@
], ],
"ro": [ "ro": [
"thumbnailOverlayLocatedIcon",
"thumbnailOverlayUnlocatedIcon",
"thumbnailOverlayTaggedIcon",
"thumbnailOverlayUntaggedIcon",
"settingsModificationWarningDialogMessage", "settingsModificationWarningDialogMessage",
"settingsViewerShowDescription",
"settingsDisplayUseTvInterface" "settingsDisplayUseTvInterface"
], ],
"ru": [ "ru": [
"thumbnailOverlayLocatedIcon",
"thumbnailOverlayUnlocatedIcon",
"thumbnailOverlayTaggedIcon",
"thumbnailOverlayUntaggedIcon",
"settingsModificationWarningDialogMessage", "settingsModificationWarningDialogMessage",
"settingsDisplayUseTvInterface" "settingsDisplayUseTvInterface"
], ],
@ -2658,6 +2596,10 @@
"keepScreenOnViewerOnly", "keepScreenOnViewerOnly",
"accessibilityAnimationsRemove", "accessibilityAnimationsRemove",
"accessibilityAnimationsKeep", "accessibilityAnimationsKeep",
"thumbnailOverlayLocatedIcon",
"thumbnailOverlayUnlocatedIcon",
"thumbnailOverlayTaggedIcon",
"thumbnailOverlayUntaggedIcon",
"widgetOpenPageViewer", "widgetOpenPageViewer",
"missingSystemFilePickerDialogMessage", "missingSystemFilePickerDialogMessage",
"unsupportedTypeDialogMessage", "unsupportedTypeDialogMessage",
@ -2983,18 +2925,24 @@
], ],
"tr": [ "tr": [
"settingsModificationWarningDialogMessage", "thumbnailOverlayLocatedIcon",
"settingsViewerShowDescription", "thumbnailOverlayUnlocatedIcon",
"settingsDisplayUseTvInterface" "thumbnailOverlayTaggedIcon",
"thumbnailOverlayUntaggedIcon"
], ],
"uk": [ "uk": [
"settingsModificationWarningDialogMessage", "thumbnailOverlayLocatedIcon",
"settingsViewerShowDescription", "thumbnailOverlayUnlocatedIcon",
"settingsDisplayUseTvInterface" "thumbnailOverlayTaggedIcon",
"thumbnailOverlayUntaggedIcon"
], ],
"zh": [ "zh": [
"thumbnailOverlayLocatedIcon",
"thumbnailOverlayUnlocatedIcon",
"thumbnailOverlayTaggedIcon",
"thumbnailOverlayUntaggedIcon",
"settingsModificationWarningDialogMessage", "settingsModificationWarningDialogMessage",
"settingsViewerShowDescription", "settingsViewerShowDescription",
"settingsAccessibilityShowPinchGestureAlternatives", "settingsAccessibilityShowPinchGestureAlternatives",
@ -3003,6 +2951,10 @@
"zh_Hant": [ "zh_Hant": [
"columnCount", "columnCount",
"thumbnailOverlayLocatedIcon",
"thumbnailOverlayUnlocatedIcon",
"thumbnailOverlayTaggedIcon",
"thumbnailOverlayUntaggedIcon",
"settingsModificationWarningDialogMessage", "settingsModificationWarningDialogMessage",
"settingsViewerShowDescription", "settingsViewerShowDescription",
"settingsAccessibilityShowPinchGestureAlternatives", "settingsAccessibilityShowPinchGestureAlternatives",