#560 video: action to lock viewer
This commit is contained in:
parent
3eb1b30552
commit
2e0b15787f
12 changed files with 278 additions and 43 deletions
|
@ -7,6 +7,7 @@ All notable changes to this project will be documented in this file.
|
|||
### Added
|
||||
|
||||
- Collection: optional support for Samsung and Sony burst patterns
|
||||
- Video: action to lock viewer
|
||||
- Info: improved state/place display (requires rescan, limited to AU/GB/IN/US)
|
||||
- Info: edit tags with state placeholder
|
||||
- improved support for system font scale
|
||||
|
|
|
@ -125,6 +125,8 @@
|
|||
"videoActionSetSpeed": "Playback speed",
|
||||
|
||||
"viewerActionSettings": "Settings",
|
||||
"viewerActionLock": "Lock viewer",
|
||||
"viewerActionUnlock": "Unlock viewer",
|
||||
|
||||
"slideshowActionResume": "Resume",
|
||||
"slideshowActionShowInCollection": "Show in Collection",
|
||||
|
|
|
@ -23,6 +23,7 @@ enum EntryAction {
|
|||
// vector
|
||||
viewSource,
|
||||
// video
|
||||
lockViewer,
|
||||
videoCaptureFrame,
|
||||
videoSelectStreams,
|
||||
videoSetSpeed,
|
||||
|
@ -88,7 +89,7 @@ class EntryActions {
|
|||
EntryAction.setAs,
|
||||
];
|
||||
|
||||
static const pageActions = [
|
||||
static const pageActions = {
|
||||
EntryAction.videoCaptureFrame,
|
||||
EntryAction.videoSelectStreams,
|
||||
EntryAction.videoSetSpeed,
|
||||
|
@ -100,7 +101,7 @@ class EntryActions {
|
|||
EntryAction.rotateCCW,
|
||||
EntryAction.rotateCW,
|
||||
EntryAction.flip,
|
||||
];
|
||||
};
|
||||
|
||||
static const trashed = [
|
||||
EntryAction.delete,
|
||||
|
@ -114,6 +115,7 @@ class EntryActions {
|
|||
EntryAction.videoSetSpeed,
|
||||
EntryAction.videoSelectStreams,
|
||||
EntryAction.videoSettings,
|
||||
EntryAction.lockViewer,
|
||||
];
|
||||
|
||||
static const videoPlayback = [
|
||||
|
@ -178,6 +180,8 @@ extension ExtraEntryAction on EntryAction {
|
|||
case EntryAction.viewSource:
|
||||
return context.l10n.entryActionViewSource;
|
||||
// video
|
||||
case EntryAction.lockViewer:
|
||||
return context.l10n.viewerActionLock;
|
||||
case EntryAction.videoCaptureFrame:
|
||||
return context.l10n.videoActionCaptureFrame;
|
||||
case EntryAction.videoToggleMute:
|
||||
|
@ -290,6 +294,8 @@ extension ExtraEntryAction on EntryAction {
|
|||
case EntryAction.viewSource:
|
||||
return AIcons.vector;
|
||||
// video
|
||||
case EntryAction.lockViewer:
|
||||
return AIcons.viewerLock;
|
||||
case EntryAction.videoCaptureFrame:
|
||||
return AIcons.captureFrame;
|
||||
case EntryAction.videoToggleMute:
|
||||
|
|
26
lib/model/settings/enums/accessibility_timeout.dart
Normal file
26
lib/model/settings/enums/accessibility_timeout.dart
Normal file
|
@ -0,0 +1,26 @@
|
|||
import 'package:aves/model/settings/enums/enums.dart';
|
||||
import 'package:aves/services/accessibility_service.dart';
|
||||
import 'package:aves/theme/durations.dart';
|
||||
|
||||
extension ExtraAccessibilityTimeout on AccessibilityTimeout {
|
||||
Future<Duration> getSnackBarDuration(bool hasAction) async {
|
||||
switch (this) {
|
||||
case AccessibilityTimeout.system:
|
||||
if (hasAction) {
|
||||
return Duration(milliseconds: await (AccessibilityService.getRecommendedTimeToTakeAction(Durations.opToastActionDisplay)));
|
||||
} else {
|
||||
return Duration(milliseconds: await (AccessibilityService.getRecommendedTimeToRead(Durations.opToastTextDisplay)));
|
||||
}
|
||||
case AccessibilityTimeout.s1:
|
||||
return const Duration(seconds: 1);
|
||||
case AccessibilityTimeout.s3:
|
||||
return const Duration(seconds: 3);
|
||||
case AccessibilityTimeout.s5:
|
||||
return const Duration(seconds: 5);
|
||||
case AccessibilityTimeout.s10:
|
||||
return const Duration(seconds: 10);
|
||||
case AccessibilityTimeout.s30:
|
||||
return const Duration(seconds: 30);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -139,6 +139,8 @@ class AIcons {
|
|||
static const IconData vaultConfigure = MdiIcons.shieldLockOutline;
|
||||
static const IconData videoSettings = Icons.video_settings_outlined;
|
||||
static const IconData view = Icons.grid_view_outlined;
|
||||
static const IconData viewerLock = Icons.lock_outline;
|
||||
static const IconData viewerUnlock = Icons.lock_open_outlined;
|
||||
static const IconData zoomIn = Icons.add_outlined;
|
||||
static const IconData zoomOut = Icons.remove_outlined;
|
||||
static const IconData collapse = Icons.expand_less_outlined;
|
||||
|
|
|
@ -2,9 +2,8 @@ import 'dart:async';
|
|||
import 'dart:math';
|
||||
|
||||
import 'package:aves/model/settings/enums/accessibility_animations.dart';
|
||||
import 'package:aves/model/settings/enums/enums.dart';
|
||||
import 'package:aves/model/settings/enums/accessibility_timeout.dart';
|
||||
import 'package:aves/model/settings/settings.dart';
|
||||
import 'package:aves/services/accessibility_service.dart';
|
||||
import 'package:aves/theme/durations.dart';
|
||||
import 'package:aves/theme/icons.dart';
|
||||
import 'package:aves/widgets/common/action_mixins/overlay_snack_bar.dart';
|
||||
|
@ -38,7 +37,7 @@ mixin FeedbackMixin {
|
|||
|
||||
// provide the messenger if feedback happens as the widget is disposed
|
||||
void showFeedbackWithMessenger(BuildContext context, ScaffoldMessengerState messenger, String message, [SnackBarAction? action]) {
|
||||
_getSnackBarDuration(action != null).then((duration) {
|
||||
settings.timeToTakeAction.getSnackBarDuration(action != null).then((duration) {
|
||||
final start = DateTime.now();
|
||||
final theme = Theme.of(context);
|
||||
final snackBarTheme = theme.snackBarTheme;
|
||||
|
@ -107,27 +106,6 @@ mixin FeedbackMixin {
|
|||
return horizontalPadding;
|
||||
}
|
||||
|
||||
Future<Duration> _getSnackBarDuration(bool hasAction) async {
|
||||
switch (settings.timeToTakeAction) {
|
||||
case AccessibilityTimeout.system:
|
||||
if (hasAction) {
|
||||
return Duration(milliseconds: await (AccessibilityService.getRecommendedTimeToTakeAction(Durations.opToastActionDisplay)));
|
||||
} else {
|
||||
return Duration(milliseconds: await (AccessibilityService.getRecommendedTimeToRead(Durations.opToastTextDisplay)));
|
||||
}
|
||||
case AccessibilityTimeout.s1:
|
||||
return const Duration(seconds: 1);
|
||||
case AccessibilityTimeout.s3:
|
||||
return const Duration(seconds: 3);
|
||||
case AccessibilityTimeout.s5:
|
||||
return const Duration(seconds: 5);
|
||||
case AccessibilityTimeout.s10:
|
||||
return const Duration(seconds: 10);
|
||||
case AccessibilityTimeout.s30:
|
||||
return const Duration(seconds: 30);
|
||||
}
|
||||
}
|
||||
|
||||
// report overlay for multiple operations
|
||||
|
||||
Future<void> showOpReport<T>({
|
||||
|
|
|
@ -2,6 +2,7 @@ import 'package:aves/model/actions/entry.dart';
|
|||
import 'package:aves/model/settings/settings.dart';
|
||||
import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||
import 'package:aves/widgets/settings/common/quick_actions/editor_page.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class ViewerActionEditorPage extends StatelessWidget {
|
||||
|
@ -9,7 +10,7 @@ class ViewerActionEditorPage extends StatelessWidget {
|
|||
|
||||
const ViewerActionEditorPage({super.key});
|
||||
|
||||
static const allAvailableActions = [
|
||||
static final allAvailableActions = [
|
||||
[
|
||||
EntryAction.share,
|
||||
EntryAction.edit,
|
||||
|
@ -26,10 +27,7 @@ class ViewerActionEditorPage extends StatelessWidget {
|
|||
],
|
||||
[
|
||||
...EntryActions.exportInternal,
|
||||
EntryAction.videoCaptureFrame,
|
||||
EntryAction.videoToggleMute,
|
||||
EntryAction.videoSetSpeed,
|
||||
EntryAction.videoSelectStreams,
|
||||
...EntryActions.video.whereNot((v) => v == EntryAction.videoSettings),
|
||||
],
|
||||
EntryActions.commonMetadataActions,
|
||||
];
|
||||
|
|
|
@ -92,6 +92,7 @@ class EntryActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAwareMix
|
|||
return targetEntry.isSvg;
|
||||
case EntryAction.videoCaptureFrame:
|
||||
return canWrite && targetEntry.isVideo;
|
||||
case EntryAction.lockViewer:
|
||||
case EntryAction.videoToggleMute:
|
||||
return !settings.useTvLayout && targetEntry.isVideo;
|
||||
case EntryAction.videoSelectStreams:
|
||||
|
@ -235,6 +236,9 @@ class EntryActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAwareMix
|
|||
case EntryAction.viewSource:
|
||||
_goToSourceViewer(context, targetEntry);
|
||||
break;
|
||||
case EntryAction.lockViewer:
|
||||
const LockViewNotification(locked: true).dispatch(context);
|
||||
break;
|
||||
// video
|
||||
case EntryAction.videoCaptureFrame:
|
||||
case EntryAction.videoToggleMute:
|
||||
|
|
|
@ -6,6 +6,13 @@ import 'package:aves_video/aves_video.dart';
|
|||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
@immutable
|
||||
class LockViewNotification extends Notification {
|
||||
final bool locked;
|
||||
|
||||
const LockViewNotification({required this.locked});
|
||||
}
|
||||
|
||||
@immutable
|
||||
class PopVisualNotification extends Notification {}
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ import 'package:aves/model/entry/extensions/props.dart';
|
|||
import 'package:aves/model/filters/filters.dart';
|
||||
import 'package:aves/model/filters/trash.dart';
|
||||
import 'package:aves/model/highlight.dart';
|
||||
import 'package:aves/model/settings/enums/accessibility_timeout.dart';
|
||||
import 'package:aves/model/settings/enums/enums.dart';
|
||||
import 'package:aves/model/settings/settings.dart';
|
||||
import 'package:aves/model/source/collection_lens.dart';
|
||||
|
@ -27,6 +28,7 @@ import 'package:aves/widgets/viewer/entry_vertical_pager.dart';
|
|||
import 'package:aves/widgets/viewer/hero.dart';
|
||||
import 'package:aves/widgets/viewer/multipage/conductor.dart';
|
||||
import 'package:aves/widgets/viewer/overlay/bottom.dart';
|
||||
import 'package:aves/widgets/viewer/overlay/locked.dart';
|
||||
import 'package:aves/widgets/viewer/overlay/panorama.dart';
|
||||
import 'package:aves/widgets/viewer/overlay/slideshow_buttons.dart';
|
||||
import 'package:aves/widgets/viewer/overlay/top.dart';
|
||||
|
@ -70,6 +72,7 @@ class _EntryViewerStackState extends State<EntryViewerStack> with EntryViewContr
|
|||
final AChangeNotifier _verticalScrollNotifier = AChangeNotifier();
|
||||
bool _overlayInitialized = false;
|
||||
final ValueNotifier<bool> _overlayVisible = ValueNotifier(true);
|
||||
final ValueNotifier<bool> _viewLocked = ValueNotifier(false);
|
||||
final ValueNotifier<bool> _overlayExpandedNotifier = ValueNotifier(false);
|
||||
late AnimationController _overlayAnimationController;
|
||||
late Animation<double> _overlayButtonScale, _overlayVideoControlScale, _overlayOpacity;
|
||||
|
@ -78,6 +81,7 @@ class _EntryViewerStackState extends State<EntryViewerStack> with EntryViewContr
|
|||
late VideoActionDelegate _videoActionDelegate;
|
||||
final ValueNotifier<HeroInfo?> _heroInfoNotifier = ValueNotifier(null);
|
||||
bool _isEntryTracked = true;
|
||||
Timer? _overlayHidingTimer;
|
||||
|
||||
@override
|
||||
bool get isViewingImage => _currentVerticalPage.value == imagePage;
|
||||
|
@ -147,6 +151,7 @@ class _EntryViewerStackState extends State<EntryViewerStack> with EntryViewContr
|
|||
));
|
||||
_overlayVisible.value = settings.showOverlayOnOpening && !viewerController.autopilot;
|
||||
_overlayVisible.addListener(_onOverlayVisibleChanged);
|
||||
_viewLocked.addListener(_onViewLockedChanged);
|
||||
_videoActionDelegate = VideoActionDelegate(
|
||||
collection: collection,
|
||||
);
|
||||
|
@ -170,9 +175,11 @@ class _EntryViewerStackState extends State<EntryViewerStack> with EntryViewContr
|
|||
_videoActionDelegate.dispose();
|
||||
_overlayAnimationController.dispose();
|
||||
_overlayVisible.dispose();
|
||||
_viewLocked.dispose();
|
||||
_overlayExpandedNotifier.dispose();
|
||||
_verticalPager.dispose();
|
||||
_heroInfoNotifier.dispose();
|
||||
_stopOverlayHidingTimer();
|
||||
WidgetsBinding.instance.removeObserver(this);
|
||||
_unregisterWidget(widget);
|
||||
super.dispose();
|
||||
|
@ -250,10 +257,24 @@ class _EntryViewerStackState extends State<EntryViewerStack> with EntryViewContr
|
|||
stream: device.supportPictureInPicture ? _floating.pipStatus$ : Stream.value(PiPStatus.disabled),
|
||||
builder: (context, snapshot) {
|
||||
var pipEnabled = snapshot.data == PiPStatus.enabled;
|
||||
return ValueListenableBuilder<bool>(
|
||||
valueListenable: _viewLocked,
|
||||
builder: (context, locked, child) {
|
||||
return Stack(
|
||||
children: [
|
||||
viewer,
|
||||
child!,
|
||||
if (!pipEnabled) ...[
|
||||
if (locked) ...[
|
||||
const Positioned.fill(
|
||||
child: AbsorbPointer(),
|
||||
),
|
||||
Positioned.fill(
|
||||
child: GestureDetector(
|
||||
onTap: () => _overlayVisible.value = !_overlayVisible.value,
|
||||
),
|
||||
),
|
||||
_buildViewerLockedBottomOverlay(),
|
||||
] else
|
||||
..._buildOverlays(availableSize).map(_decorateOverlay),
|
||||
const TopGestureAreaProtector(),
|
||||
const SideGestureAreaProtector(),
|
||||
|
@ -262,6 +283,9 @@ class _EntryViewerStackState extends State<EntryViewerStack> with EntryViewContr
|
|||
],
|
||||
);
|
||||
},
|
||||
child: viewer,
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
|
@ -301,6 +325,17 @@ class _EntryViewerStackState extends State<EntryViewerStack> with EntryViewContr
|
|||
}
|
||||
}
|
||||
|
||||
Widget _buildViewerLockedBottomOverlay() {
|
||||
return TooltipTheme(
|
||||
data: TooltipTheme.of(context).copyWith(
|
||||
preferBelow: false,
|
||||
),
|
||||
child: ViewerLockedOverlay(
|
||||
animationController: _overlayAnimationController,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildSlideshowBottomOverlay(Size availableSize) {
|
||||
return SizedBox.fromSize(
|
||||
size: availableSize,
|
||||
|
@ -491,6 +526,8 @@ class _EntryViewerStackState extends State<EntryViewerStack> with EntryViewContr
|
|||
}
|
||||
} else if (notification is ToggleOverlayNotification) {
|
||||
_overlayVisible.value = notification.visible ?? !_overlayVisible.value;
|
||||
} else if (notification is LockViewNotification) {
|
||||
_viewLocked.value = notification.locked;
|
||||
} else if (notification is VideoActionNotification) {
|
||||
_onVideoAction(
|
||||
context: context,
|
||||
|
@ -809,8 +846,12 @@ class _EntryViewerStackState extends State<EntryViewerStack> with EntryViewContr
|
|||
Future<void> _onOverlayVisibleChanged({bool animate = true}) async {
|
||||
if (!mounted) return;
|
||||
if (_overlayVisible.value) {
|
||||
if (_viewLocked.value) {
|
||||
await _startOverlayHidingTimer();
|
||||
} else {
|
||||
await AvesApp.showSystemUI();
|
||||
AvesApp.setSystemUIStyle(Theme.of(context));
|
||||
}
|
||||
if (animate) {
|
||||
await _overlayAnimationController.forward();
|
||||
} else {
|
||||
|
@ -835,4 +876,24 @@ class _EntryViewerStackState extends State<EntryViewerStack> with EntryViewContr
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _onViewLockedChanged() async {
|
||||
if (_viewLocked.value) {
|
||||
await AvesApp.hideSystemUI();
|
||||
await _startOverlayHidingTimer();
|
||||
} else {
|
||||
await AvesApp.showSystemUI();
|
||||
AvesApp.setSystemUIStyle(Theme.of(context));
|
||||
_stopOverlayHidingTimer();
|
||||
_overlayVisible.value = true;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _startOverlayHidingTimer() async {
|
||||
_stopOverlayHidingTimer();
|
||||
final duration = await settings.timeToTakeAction.getSnackBarDuration(true);
|
||||
_overlayHidingTimer = Timer(duration, () => _overlayVisible.value = false);
|
||||
}
|
||||
|
||||
void _stopOverlayHidingTimer() => _overlayHidingTimer?.cancel();
|
||||
}
|
||||
|
|
90
lib/widgets/viewer/overlay/locked.dart
Normal file
90
lib/widgets/viewer/overlay/locked.dart
Normal file
|
@ -0,0 +1,90 @@
|
|||
import 'dart:math';
|
||||
|
||||
import 'package:aves/theme/icons.dart';
|
||||
import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||
import 'package:aves/widgets/common/extensions/media_query.dart';
|
||||
import 'package:aves/widgets/common/identity/buttons/overlay_button.dart';
|
||||
import 'package:aves/widgets/viewer/controls/notifications.dart';
|
||||
import 'package:aves/widgets/viewer/overlay/viewer_buttons.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class ViewerLockedOverlay extends StatefulWidget {
|
||||
final AnimationController animationController;
|
||||
final EdgeInsets? viewInsets, viewPadding;
|
||||
|
||||
const ViewerLockedOverlay({
|
||||
super.key,
|
||||
required this.animationController,
|
||||
this.viewInsets,
|
||||
this.viewPadding,
|
||||
});
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _ViewerLockedOverlayState();
|
||||
}
|
||||
|
||||
class _ViewerLockedOverlayState extends State<ViewerLockedOverlay> {
|
||||
late Animation<double> _buttonScale;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_registerWidget(widget);
|
||||
}
|
||||
|
||||
@override
|
||||
void didUpdateWidget(covariant ViewerLockedOverlay oldWidget) {
|
||||
super.didUpdateWidget(oldWidget);
|
||||
_unregisterWidget(oldWidget);
|
||||
_registerWidget(widget);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_unregisterWidget(widget);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _registerWidget(ViewerLockedOverlay widget) {
|
||||
_buttonScale = CurvedAnimation(
|
||||
parent: widget.animationController,
|
||||
// a little bounce at the top
|
||||
curve: Curves.easeOutBack,
|
||||
);
|
||||
}
|
||||
|
||||
void _unregisterWidget(ViewerLockedOverlay widget) {
|
||||
// nothing
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Selector<MediaQueryData, double>(
|
||||
selector: (context, mq) => max(mq.effectiveBottomPadding, mq.systemGestureInsets.bottom),
|
||||
builder: (context, mqPaddingBottom, child) {
|
||||
final viewInsetsPadding = (widget.viewInsets ?? EdgeInsets.zero) + (widget.viewPadding ?? EdgeInsets.zero);
|
||||
return Container(
|
||||
alignment: AlignmentDirectional.bottomEnd,
|
||||
padding: EdgeInsets.only(bottom: mqPaddingBottom) + const EdgeInsets.all(ViewerButtonRowContent.padding),
|
||||
child: SafeArea(
|
||||
top: false,
|
||||
bottom: false,
|
||||
minimum: EdgeInsets.only(
|
||||
left: viewInsetsPadding.left,
|
||||
right: viewInsetsPadding.right,
|
||||
),
|
||||
child: OverlayButton(
|
||||
scale: _buttonScale,
|
||||
child: IconButton(
|
||||
icon: const Icon(AIcons.viewerUnlock),
|
||||
onPressed: () => const LockViewNotification(locked: false).dispatch(context),
|
||||
tooltip: context.l10n.viewerActionUnlock,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
|
@ -62,6 +62,8 @@
|
|||
"videoActionSelectStreams",
|
||||
"videoActionSetSpeed",
|
||||
"viewerActionSettings",
|
||||
"viewerActionLock",
|
||||
"viewerActionUnlock",
|
||||
"slideshowActionResume",
|
||||
"slideshowActionShowInCollection",
|
||||
"entryInfoActionEditDate",
|
||||
|
@ -623,6 +625,8 @@
|
|||
"videoActionSelectStreams",
|
||||
"videoActionSetSpeed",
|
||||
"viewerActionSettings",
|
||||
"viewerActionLock",
|
||||
"viewerActionUnlock",
|
||||
"slideshowActionResume",
|
||||
"slideshowActionShowInCollection",
|
||||
"entryInfoActionEditDate",
|
||||
|
@ -1181,6 +1185,8 @@
|
|||
],
|
||||
|
||||
"cs": [
|
||||
"viewerActionLock",
|
||||
"viewerActionUnlock",
|
||||
"settingsVideoEnablePip",
|
||||
"settingsCollectionBurstPatternsTile",
|
||||
"settingsCollectionBurstPatternsNone",
|
||||
|
@ -1194,6 +1200,8 @@
|
|||
"chipActionLock",
|
||||
"chipActionCreateVault",
|
||||
"chipActionConfigureVault",
|
||||
"viewerActionLock",
|
||||
"viewerActionUnlock",
|
||||
"albumTierVaults",
|
||||
"lengthUnitPixel",
|
||||
"lengthUnitPercent",
|
||||
|
@ -1230,6 +1238,8 @@
|
|||
|
||||
"el": [
|
||||
"chipActionGoToPlacePage",
|
||||
"viewerActionLock",
|
||||
"viewerActionUnlock",
|
||||
"vaultLockTypePattern",
|
||||
"settingsVideoEnablePip",
|
||||
"patternDialogEnter",
|
||||
|
@ -1246,12 +1256,16 @@
|
|||
],
|
||||
|
||||
"es": [
|
||||
"viewerActionLock",
|
||||
"viewerActionUnlock",
|
||||
"settingsCollectionBurstPatternsTile",
|
||||
"settingsCollectionBurstPatternsNone",
|
||||
"tagPlaceholderState"
|
||||
],
|
||||
|
||||
"eu": [
|
||||
"viewerActionLock",
|
||||
"viewerActionUnlock",
|
||||
"settingsCollectionBurstPatternsTile",
|
||||
"settingsCollectionBurstPatternsNone",
|
||||
"tagPlaceholderState"
|
||||
|
@ -1266,6 +1280,8 @@
|
|||
"videoActionPause",
|
||||
"videoActionPlay",
|
||||
"videoActionSelectStreams",
|
||||
"viewerActionLock",
|
||||
"viewerActionUnlock",
|
||||
"slideshowActionResume",
|
||||
"filterAspectRatioLandscapeLabel",
|
||||
"filterAspectRatioPortraitLabel",
|
||||
|
@ -1735,6 +1751,8 @@
|
|||
],
|
||||
|
||||
"fr": [
|
||||
"viewerActionLock",
|
||||
"viewerActionUnlock",
|
||||
"tagPlaceholderState"
|
||||
],
|
||||
|
||||
|
@ -1746,6 +1764,8 @@
|
|||
"chipActionConfigureVault",
|
||||
"entryActionShareImageOnly",
|
||||
"entryActionShareVideoOnly",
|
||||
"viewerActionLock",
|
||||
"viewerActionUnlock",
|
||||
"entryInfoActionExportMetadata",
|
||||
"entryInfoActionRemoveLocation",
|
||||
"filterAspectRatioLandscapeLabel",
|
||||
|
@ -2328,6 +2348,8 @@
|
|||
"videoActionSelectStreams",
|
||||
"videoActionSetSpeed",
|
||||
"viewerActionSettings",
|
||||
"viewerActionLock",
|
||||
"viewerActionUnlock",
|
||||
"slideshowActionResume",
|
||||
"slideshowActionShowInCollection",
|
||||
"entryInfoActionEditDate",
|
||||
|
@ -2946,6 +2968,8 @@
|
|||
"videoActionSelectStreams",
|
||||
"videoActionSetSpeed",
|
||||
"viewerActionSettings",
|
||||
"viewerActionLock",
|
||||
"viewerActionUnlock",
|
||||
"slideshowActionResume",
|
||||
"slideshowActionShowInCollection",
|
||||
"entryInfoActionEditDate",
|
||||
|
@ -3504,12 +3528,16 @@
|
|||
],
|
||||
|
||||
"id": [
|
||||
"viewerActionLock",
|
||||
"viewerActionUnlock",
|
||||
"settingsCollectionBurstPatternsTile",
|
||||
"settingsCollectionBurstPatternsNone",
|
||||
"tagPlaceholderState"
|
||||
],
|
||||
|
||||
"it": [
|
||||
"viewerActionLock",
|
||||
"viewerActionUnlock",
|
||||
"settingsCollectionBurstPatternsTile",
|
||||
"settingsCollectionBurstPatternsNone",
|
||||
"tagPlaceholderState"
|
||||
|
@ -3522,6 +3550,8 @@
|
|||
"chipActionLock",
|
||||
"chipActionCreateVault",
|
||||
"chipActionConfigureVault",
|
||||
"viewerActionLock",
|
||||
"viewerActionUnlock",
|
||||
"filterAspectRatioLandscapeLabel",
|
||||
"filterAspectRatioPortraitLabel",
|
||||
"filterNoAddressLabel",
|
||||
|
@ -3572,6 +3602,8 @@
|
|||
],
|
||||
|
||||
"ko": [
|
||||
"viewerActionLock",
|
||||
"viewerActionUnlock",
|
||||
"tagPlaceholderState"
|
||||
],
|
||||
|
||||
|
@ -3581,6 +3613,8 @@
|
|||
"chipActionLock",
|
||||
"chipActionCreateVault",
|
||||
"chipActionConfigureVault",
|
||||
"viewerActionLock",
|
||||
"viewerActionUnlock",
|
||||
"filterLocatedLabel",
|
||||
"filterTaggedLabel",
|
||||
"albumTierVaults",
|
||||
|
@ -3625,6 +3659,8 @@
|
|||
],
|
||||
|
||||
"nb": [
|
||||
"viewerActionLock",
|
||||
"viewerActionUnlock",
|
||||
"vaultLockTypePattern",
|
||||
"settingsVideoEnablePip",
|
||||
"patternDialogEnter",
|
||||
|
@ -3644,6 +3680,8 @@
|
|||
"chipActionConfigureVault",
|
||||
"entryActionShareImageOnly",
|
||||
"entryActionShareVideoOnly",
|
||||
"viewerActionLock",
|
||||
"viewerActionUnlock",
|
||||
"entryInfoActionExportMetadata",
|
||||
"entryInfoActionRemoveLocation",
|
||||
"filterAspectRatioLandscapeLabel",
|
||||
|
@ -3707,6 +3745,8 @@
|
|||
"chipActionLock",
|
||||
"chipActionCreateVault",
|
||||
"chipActionConfigureVault",
|
||||
"viewerActionLock",
|
||||
"viewerActionUnlock",
|
||||
"entryInfoActionRemoveLocation",
|
||||
"filterLocatedLabel",
|
||||
"filterNoLocationLabel",
|
||||
|
@ -4024,12 +4064,16 @@
|
|||
],
|
||||
|
||||
"pl": [
|
||||
"viewerActionLock",
|
||||
"viewerActionUnlock",
|
||||
"settingsCollectionBurstPatternsTile",
|
||||
"settingsCollectionBurstPatternsNone",
|
||||
"tagPlaceholderState"
|
||||
],
|
||||
|
||||
"pt": [
|
||||
"viewerActionLock",
|
||||
"viewerActionUnlock",
|
||||
"settingsCollectionBurstPatternsTile",
|
||||
"settingsCollectionBurstPatternsNone",
|
||||
"settingsVideoBackgroundModeDialogTitle",
|
||||
|
@ -4037,6 +4081,8 @@
|
|||
],
|
||||
|
||||
"ro": [
|
||||
"viewerActionLock",
|
||||
"viewerActionUnlock",
|
||||
"settingsCollectionBurstPatternsTile",
|
||||
"settingsCollectionBurstPatternsNone",
|
||||
"tagPlaceholderState"
|
||||
|
@ -4044,6 +4090,8 @@
|
|||
|
||||
"ru": [
|
||||
"chipActionLock",
|
||||
"viewerActionLock",
|
||||
"viewerActionUnlock",
|
||||
"vaultLockTypePattern",
|
||||
"settingsVideoEnablePip",
|
||||
"patternDialogEnter",
|
||||
|
@ -4071,6 +4119,8 @@
|
|||
"chipActionLock",
|
||||
"chipActionCreateVault",
|
||||
"chipActionConfigureVault",
|
||||
"viewerActionLock",
|
||||
"viewerActionUnlock",
|
||||
"filterLocatedLabel",
|
||||
"filterNoLocationLabel",
|
||||
"albumTierVaults",
|
||||
|
@ -4501,6 +4551,8 @@
|
|||
"chipActionLock",
|
||||
"chipActionCreateVault",
|
||||
"chipActionConfigureVault",
|
||||
"viewerActionLock",
|
||||
"viewerActionUnlock",
|
||||
"albumTierVaults",
|
||||
"lengthUnitPixel",
|
||||
"lengthUnitPercent",
|
||||
|
@ -4855,6 +4907,8 @@
|
|||
"chipActionLock",
|
||||
"chipActionCreateVault",
|
||||
"chipActionConfigureVault",
|
||||
"viewerActionLock",
|
||||
"viewerActionUnlock",
|
||||
"albumTierVaults",
|
||||
"lengthUnitPixel",
|
||||
"lengthUnitPercent",
|
||||
|
@ -4890,6 +4944,8 @@
|
|||
],
|
||||
|
||||
"uk": [
|
||||
"viewerActionLock",
|
||||
"viewerActionUnlock",
|
||||
"settingsCollectionBurstPatternsTile",
|
||||
"settingsCollectionBurstPatternsNone",
|
||||
"tagPlaceholderState"
|
||||
|
@ -4900,6 +4956,8 @@
|
|||
"chipActionLock",
|
||||
"chipActionCreateVault",
|
||||
"chipActionConfigureVault",
|
||||
"viewerActionLock",
|
||||
"viewerActionUnlock",
|
||||
"filterLocatedLabel",
|
||||
"filterTaggedLabel",
|
||||
"albumTierVaults",
|
||||
|
@ -4948,6 +5006,8 @@
|
|||
"chipActionLock",
|
||||
"chipActionCreateVault",
|
||||
"chipActionConfigureVault",
|
||||
"viewerActionLock",
|
||||
"viewerActionUnlock",
|
||||
"filterLocatedLabel",
|
||||
"filterTaggedLabel",
|
||||
"albumTierVaults",
|
||||
|
|
Loading…
Reference in a new issue