#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
- Viewer: optionally show description on overlay
- Collection: unlocated/untagged overlay icons
- Czech translation (thanks vesp)
### Changed

View file

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

View file

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

View file

@ -22,6 +22,10 @@ enum SlideshowVideoPlayback { skip, playMuted, playWithSound }
enum SubtitlePosition { top, bottom }
enum ThumbnailOverlayLocationIcon { located, unlocated, none }
enum ThumbnailOverlayTagIcon { tagged, untagged, none }
enum UnitSystem { metric, imperial }
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 collectionSelectionQuickActionsKey = 'collection_selection_quick_actions';
static const showThumbnailFavouriteKey = 'show_thumbnail_favourite';
static const showThumbnailTagKey = 'show_thumbnail_tag';
static const showThumbnailLocationKey = 'show_thumbnail_location';
static const thumbnailLocationIconKey = 'thumbnail_location_icon';
static const thumbnailTagIconKey = 'thumbnail_tag_icon';
static const showThumbnailMotionPhotoKey = 'show_thumbnail_motion_photo';
static const showThumbnailRatingKey = 'show_thumbnail_rating';
static const showThumbnailRawKey = 'show_thumbnail_raw';
@ -484,13 +484,13 @@ class Settings extends ChangeNotifier {
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;
@ -1006,8 +1006,6 @@ class Settings extends ChangeNotifier {
case setMetadataDateBeforeFileOpKey:
case collectionSortReverseKey:
case showThumbnailFavouriteKey:
case showThumbnailTagKey:
case showThumbnailLocationKey:
case showThumbnailMotionPhotoKey:
case showThumbnailRatingKey:
case showThumbnailRawKey:
@ -1054,6 +1052,8 @@ class Settings extends ChangeNotifier {
case homePageKey:
case collectionGroupFactorKey:
case collectionSortFactorKey:
case thumbnailLocationIconKey:
case thumbnailTagIconKey:
case albumGroupFactorKey:
case albumSortFactorKey:
case countrySortFactorKey:

View file

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

View file

@ -1,5 +1,7 @@
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/widgets/common/identity/aves_icons.dart';
import 'package:flutter/material.dart';
@ -7,13 +9,14 @@ import 'package:provider/provider.dart';
class GridTheme extends StatelessWidget {
final double extent;
final bool? showLocation, showTrash;
final bool showLocation;
final bool? showTrash;
final Widget child;
const GridTheme({
super.key,
required this.extent,
this.showLocation,
this.showLocation = true,
this.showTrash,
required this.child,
});
@ -32,11 +35,11 @@ class GridTheme extends StatelessWidget {
fontSize: fontSize,
highlightBorderWidth: highlightBorderWidth,
showFavourite: settings.showThumbnailFavourite,
showLocation: showLocation ?? settings.showThumbnailLocation,
locationIcon: showLocation ? settings.thumbnailLocationIcon : ThumbnailOverlayLocationIcon.none,
tagIcon: settings.thumbnailTagIcon,
showMotionPhoto: settings.showThumbnailMotionPhoto,
showRating: settings.showThumbnailRating,
showRaw: settings.showThumbnailRaw,
showTag: settings.showThumbnailTag,
showTrash: showTrash ?? true,
showVideoDuration: settings.showThumbnailVideoDuration,
);
@ -46,21 +49,55 @@ class GridTheme extends StatelessWidget {
}
}
typedef GridThemeIconBuilder = List<Widget> Function(BuildContext context, AvesEntry entry);
class GridThemeData {
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.fontSize,
required this.highlightBorderWidth,
required this.showFavourite,
required this.showLocation,
required ThumbnailOverlayLocationIcon locationIcon,
required ThumbnailOverlayTagIcon tagIcon,
required this.showMotionPhoto,
required this.showRating,
required this.showRaw,
required this.showTag,
required this.showTrash,
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 {
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;
@override
Widget build(BuildContext context) {
return const OverlayIcon(
icon: AIcons.tag,
return OverlayIcon(
icon: icon,
iconScale: scale,
relativeOffset: Offset(.05, .05),
relativeOffset: const Offset(.05, .05),
);
}
}
class GpsIcon extends StatelessWidget {
const GpsIcon({super.key});
class LocationIcon extends StatelessWidget {
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
Widget build(BuildContext context) {
return const OverlayIcon(
icon: AIcons.location,
return OverlayIcon(
icon: icon,
);
}
}
@ -181,10 +193,9 @@ class RatingIcon extends StatelessWidget {
@override
Widget build(BuildContext context) {
final gridTheme = context.watch<GridThemeData>();
return DefaultTextStyle(
style: TextStyle(
fontSize: gridTheme.fontSize,
fontSize: context.select<GridThemeData, double>((t) => t.fontSize),
),
child: OverlayIcon(
icon: AIcons.rating,

View file

@ -4,7 +4,6 @@ import 'package:aves/model/entry.dart';
import 'package:aves/model/highlight.dart';
import 'package:aves/widgets/common/fx/sweeper.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:provider/provider.dart';
@ -18,26 +17,8 @@ class ThumbnailEntryOverlay extends StatelessWidget {
@override
Widget build(BuildContext context) {
final children = [
if (entry.isFavourite && context.select<GridThemeData, bool>((t) => t.showFavourite)) const FavouriteIcon(),
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),
];
final iconBuilder = context.select<GridThemeData, GridThemeIconBuilder>((t) => t.iconBuilder);
final children = iconBuilder(context, entry);
if (children.isEmpty) return const SizedBox();
return Align(
alignment: AlignmentDirectional.bottomStart,

View file

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

View file

@ -43,6 +43,8 @@ class SettingsSwitchListTile extends StatelessWidget {
final String? subtitle;
final Widget? trailing;
static const disabledOpacity = .2;
const SettingsSwitchListTile({
super.key,
required this.selector,
@ -63,7 +65,7 @@ class SettingsSwitchListTile extends StatelessWidget {
children: [
Expanded(child: titleWidget),
AnimatedOpacity(
opacity: current ? 1 : .2,
opacity: current ? 1 : disabledOpacity,
duration: Durations.toggleableTransitionAnimation,
child: trailing,
),
@ -87,6 +89,7 @@ class SettingsSelectionListTile<T extends Enum> extends StatelessWidget {
final T Function(BuildContext, Settings) selector;
final ValueChanged<T> onSelection;
final String tileTitle;
final WidgetBuilder? trailingBuilder;
final String? dialogTitle;
final TextBuilder<T>? optionSubtitleBuilder;
@ -97,6 +100,7 @@ class SettingsSelectionListTile<T extends Enum> extends StatelessWidget {
required this.selector,
required this.onSelection,
required this.tileTitle,
this.trailingBuilder,
this.dialogTitle,
this.optionSubtitleBuilder,
});
@ -105,20 +109,31 @@ class SettingsSelectionListTile<T extends Enum> extends StatelessWidget {
Widget build(BuildContext context) {
return Selector<Settings, T>(
selector: selector,
builder: (context, current, child) => ListTile(
title: Text(tileTitle),
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,
builder: (context, current, child) {
Widget titleWidget = Text(tileTitle);
if (trailingBuilder != null) {
titleWidget = Row(
children: [
Expanded(child: titleWidget),
trailingBuilder!(context),
],
);
}
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/theme/colors.dart';
import 'package:aves/theme/durations.dart';
import 'package:aves/theme/icons.dart';
import 'package:aves/widgets/common/extensions/build_context.dart';
import 'package:aves/widgets/common/identity/aves_icons.dart';
import 'package:aves/widgets/settings/common/tiles.dart';
import 'package:aves/widgets/settings/settings_definition.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
@ -14,8 +19,8 @@ class ThumbnailOverlayPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
final iconSize = IconTheme.of(context).size! * MediaQuery.textScaleFactorOf(context);
final iconColor = context.select<AvesColorsData, Color>((v) => v.neutral);
final iconSize = _getIconSize(context);
final iconColor = _getIconColor(context);
return Scaffold(
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(
selector: (context, s) => s.showThumbnailMotionPhoto,
onChanged: (v) => settings.showThumbnailMotionPhoto = v,
@ -99,9 +81,86 @@ class ThumbnailOverlayPage extends StatelessWidget {
onChanged: (v) => settings.showThumbnailVideoDuration = v,
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
..collectionBrowsingQuickActions = SettingsDefaults.collectionBrowsingQuickActions
..showThumbnailFavourite = false
..showThumbnailTag = false
..showThumbnailLocation = false
..thumbnailLocationIcon = ThumbnailOverlayLocationIcon.none
..thumbnailTagIcon = ThumbnailOverlayTagIcon.none
..hiddenFilters = {}
// viewer
..viewerQuickActions = SettingsDefaults.viewerQuickActions

View file

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