#290 slideshow: animated zoom effect
This commit is contained in:
parent
1fa68f082f
commit
6df9456372
17 changed files with 115 additions and 18 deletions
|
@ -14,7 +14,8 @@ All notable changes to this project will be documented in this file.
|
|||
- Stats: top albums
|
||||
- Stats: open full top listings
|
||||
- Video: option for muted auto play
|
||||
- Slideshow: option for no transition
|
||||
- Slideshow / Screen saver: option for no transition
|
||||
- Slideshow / Screen saver: animated zoom effect
|
||||
- Widget: tap action setting
|
||||
- Wallpaper: scroll effect option
|
||||
|
||||
|
|
|
@ -715,6 +715,7 @@
|
|||
"settingsSlideshowRepeat": "Repeat",
|
||||
"settingsSlideshowShuffle": "Shuffle",
|
||||
"settingsSlideshowFillScreen": "Fill screen",
|
||||
"settingsSlideshowAnimatedZoomEffect": "Animated zoom effect",
|
||||
"settingsSlideshowTransitionTile": "Transition",
|
||||
"settingsSlideshowTransitionDialogTitle": "Transition",
|
||||
"settingsSlideshowIntervalTile": "Interval",
|
||||
|
|
|
@ -534,6 +534,7 @@
|
|||
"settingsSlideshowRepeat": "Répéter",
|
||||
"settingsSlideshowShuffle": "Aléatoire",
|
||||
"settingsSlideshowFillScreen": "Remplir l’écran",
|
||||
"settingsSlideshowAnimatedZoomEffect": "Effet de zoom animé",
|
||||
"settingsSlideshowTransitionTile": "Transition",
|
||||
"settingsSlideshowTransitionDialogTitle": "Transition",
|
||||
"settingsSlideshowIntervalTile": "Intervalle",
|
||||
|
|
|
@ -534,6 +534,7 @@
|
|||
"settingsSlideshowRepeat": "반복",
|
||||
"settingsSlideshowShuffle": "순서섞기",
|
||||
"settingsSlideshowFillScreen": "화면 채우기",
|
||||
"settingsSlideshowAnimatedZoomEffect": "애니메이션 확대/축소 효과",
|
||||
"settingsSlideshowTransitionTile": "전환 효과",
|
||||
"settingsSlideshowTransitionDialogTitle": "전환 효과",
|
||||
"settingsSlideshowIntervalTile": "교체 주기",
|
||||
|
|
|
@ -129,6 +129,7 @@ class SettingsDefaults {
|
|||
static const slideshowRepeat = false;
|
||||
static const slideshowShuffle = false;
|
||||
static const slideshowFillScreen = false;
|
||||
static const slideshowAnimatedZoomEffect = true;
|
||||
static const slideshowTransition = ViewerTransition.fade;
|
||||
static const slideshowVideoPlayback = SlideshowVideoPlayback.playMuted;
|
||||
static const slideshowInterval = SlideshowInterval.s5;
|
||||
|
|
|
@ -151,6 +151,7 @@ class Settings extends ChangeNotifier {
|
|||
|
||||
// screen saver
|
||||
static const screenSaverFillScreenKey = 'screen_saver_fill_screen';
|
||||
static const screenSaverAnimatedZoomEffectKey = 'screen_saver_animated_zoom_effect';
|
||||
static const screenSaverTransitionKey = 'screen_saver_transition';
|
||||
static const screenSaverVideoPlaybackKey = 'screen_saver_video_playback';
|
||||
static const screenSaverIntervalKey = 'screen_saver_interval';
|
||||
|
@ -160,6 +161,7 @@ class Settings extends ChangeNotifier {
|
|||
static const slideshowRepeatKey = 'slideshow_loop';
|
||||
static const slideshowShuffleKey = 'slideshow_shuffle';
|
||||
static const slideshowFillScreenKey = 'slideshow_fill_screen';
|
||||
static const slideshowAnimatedZoomEffectKey = 'slideshow_animated_zoom_effect';
|
||||
static const slideshowTransitionKey = 'slideshow_transition';
|
||||
static const slideshowVideoPlaybackKey = 'slideshow_video_playback';
|
||||
static const slideshowIntervalKey = 'slideshow_interval';
|
||||
|
@ -649,6 +651,10 @@ class Settings extends ChangeNotifier {
|
|||
|
||||
set screenSaverFillScreen(bool newValue) => setAndNotify(screenSaverFillScreenKey, newValue);
|
||||
|
||||
bool get screenSaverAnimatedZoomEffect => getBoolOrDefault(screenSaverAnimatedZoomEffectKey, SettingsDefaults.slideshowAnimatedZoomEffect);
|
||||
|
||||
set screenSaverAnimatedZoomEffect(bool newValue) => setAndNotify(screenSaverAnimatedZoomEffectKey, newValue);
|
||||
|
||||
ViewerTransition get screenSaverTransition => getEnumOrDefault(screenSaverTransitionKey, SettingsDefaults.slideshowTransition, ViewerTransition.values);
|
||||
|
||||
set screenSaverTransition(ViewerTransition newValue) => setAndNotify(screenSaverTransitionKey, newValue.toString());
|
||||
|
@ -679,6 +685,10 @@ class Settings extends ChangeNotifier {
|
|||
|
||||
set slideshowFillScreen(bool newValue) => setAndNotify(slideshowFillScreenKey, newValue);
|
||||
|
||||
bool get slideshowAnimatedZoomEffect => getBoolOrDefault(slideshowAnimatedZoomEffectKey, SettingsDefaults.slideshowAnimatedZoomEffect);
|
||||
|
||||
set slideshowAnimatedZoomEffect(bool newValue) => setAndNotify(slideshowAnimatedZoomEffectKey, newValue);
|
||||
|
||||
ViewerTransition get slideshowTransition => getEnumOrDefault(slideshowTransitionKey, SettingsDefaults.slideshowTransition, ViewerTransition.values);
|
||||
|
||||
set slideshowTransition(ViewerTransition newValue) => setAndNotify(slideshowTransitionKey, newValue.toString());
|
||||
|
@ -880,9 +890,11 @@ class Settings extends ChangeNotifier {
|
|||
case saveSearchHistoryKey:
|
||||
case filePickerShowHiddenFilesKey:
|
||||
case screenSaverFillScreenKey:
|
||||
case screenSaverAnimatedZoomEffectKey:
|
||||
case slideshowRepeatKey:
|
||||
case slideshowShuffleKey:
|
||||
case slideshowFillScreenKey:
|
||||
case slideshowAnimatedZoomEffectKey:
|
||||
if (newValue is bool) {
|
||||
settingsStore.setBool(key, newValue);
|
||||
} else {
|
||||
|
|
|
@ -41,6 +41,7 @@ class Durations {
|
|||
static const thumbnailScrollerShadeAnimation = Duration(milliseconds: 150);
|
||||
static const viewerVideoPlayerTransition = Duration(milliseconds: 500);
|
||||
static const viewerActionFeedbackAnimation = Duration(milliseconds: 600);
|
||||
static const viewerHorizontalPageAnimation = Duration(seconds: 1);
|
||||
|
||||
// info animations
|
||||
static const mapStyleSwitchAnimation = Duration(milliseconds: 300);
|
||||
|
|
|
@ -45,7 +45,7 @@ class ScaleBoundaries extends Equatable {
|
|||
);
|
||||
}
|
||||
|
||||
double _scaleForLevel(ScaleLevel level) {
|
||||
double scaleForLevel(ScaleLevel level) {
|
||||
final factor = level.factor;
|
||||
switch (level.ref) {
|
||||
case ScaleReference.contained:
|
||||
|
@ -61,18 +61,18 @@ class ScaleBoundaries extends Equatable {
|
|||
double get originalScale => 1.0 / window.devicePixelRatio;
|
||||
|
||||
double get minScale => {
|
||||
_scaleForLevel(_minScale),
|
||||
scaleForLevel(_minScale),
|
||||
_allowOriginalScaleBeyondRange ? originalScale : double.infinity,
|
||||
initialScale,
|
||||
}.fold(double.infinity, min);
|
||||
|
||||
double get maxScale => {
|
||||
_scaleForLevel(_maxScale),
|
||||
scaleForLevel(_maxScale),
|
||||
_allowOriginalScaleBeyondRange ? originalScale : double.negativeInfinity,
|
||||
initialScale,
|
||||
}.fold(0, max);
|
||||
|
||||
double get initialScale => _scaleForLevel(_initialScale);
|
||||
double get initialScale => scaleForLevel(_initialScale);
|
||||
|
||||
Offset get _viewportCenter => viewportSize.center(Offset.zero);
|
||||
|
||||
|
|
|
@ -32,6 +32,11 @@ class ScreenSaverSettingsPage extends StatelessWidget {
|
|||
onChanged: (v) => settings.screenSaverFillScreen = v,
|
||||
title: context.l10n.settingsSlideshowFillScreen,
|
||||
),
|
||||
SettingsSwitchListTile(
|
||||
selector: (context, s) => s.screenSaverAnimatedZoomEffect,
|
||||
onChanged: (v) => settings.screenSaverAnimatedZoomEffect = v,
|
||||
title: context.l10n.settingsSlideshowAnimatedZoomEffect,
|
||||
),
|
||||
SettingsSelectionListTile<ViewerTransition>(
|
||||
values: ViewerTransition.values,
|
||||
getName: (context, v) => v.getName(context),
|
||||
|
|
|
@ -36,6 +36,11 @@ class ViewerSlideshowPage extends StatelessWidget {
|
|||
onChanged: (v) => settings.slideshowFillScreen = v,
|
||||
title: context.l10n.settingsSlideshowFillScreen,
|
||||
),
|
||||
SettingsSwitchListTile(
|
||||
selector: (context, s) => s.slideshowAnimatedZoomEffect,
|
||||
onChanged: (v) => settings.slideshowAnimatedZoomEffect = v,
|
||||
title: context.l10n.settingsSlideshowAnimatedZoomEffect,
|
||||
),
|
||||
SettingsSelectionListTile<ViewerTransition>(
|
||||
values: ViewerTransition.values,
|
||||
getName: (context, v) => v.getName(context),
|
||||
|
|
|
@ -1,20 +1,25 @@
|
|||
import 'dart:async';
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:aves/model/entry.dart';
|
||||
import 'package:aves/model/settings/enums/enums.dart';
|
||||
import 'package:aves/theme/durations.dart';
|
||||
import 'package:aves/widgets/common/magnifier/scale/scale_level.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
class ViewerController {
|
||||
final ValueNotifier<AvesEntry?> entryNotifier = ValueNotifier(null);
|
||||
final ScaleLevel initialScale;
|
||||
final ViewerTransition transition;
|
||||
final Duration? autopilotInterval;
|
||||
final bool autopilotAnimatedZoom;
|
||||
final bool repeat;
|
||||
|
||||
late final ScaleLevel _initialScale;
|
||||
late final ValueNotifier<bool> _autopilotNotifier;
|
||||
Timer? _playTimer;
|
||||
final StreamController _streamController = StreamController.broadcast();
|
||||
final Map<TickerProvider, AnimationController> _autopilotAnimationControllers = {};
|
||||
ScaleLevel? _autopilotInitialScale;
|
||||
|
||||
Stream<dynamic> get _events => _streamController.stream;
|
||||
|
||||
|
@ -26,13 +31,22 @@ class ViewerController {
|
|||
|
||||
set autopilot(bool enabled) => _autopilotNotifier.value = enabled;
|
||||
|
||||
ScaleLevel get initialScale => _autopilotInitialScale ?? _initialScale;
|
||||
|
||||
static final _autopilotScaleTweens = [
|
||||
Tween<double>(begin: 1, end: 1.2),
|
||||
Tween<double>(begin: 1.2, end: 1),
|
||||
];
|
||||
|
||||
ViewerController({
|
||||
this.initialScale = const ScaleLevel(ref: ScaleReference.contained),
|
||||
ScaleLevel initialScale = const ScaleLevel(ref: ScaleReference.contained),
|
||||
this.transition = ViewerTransition.parallax,
|
||||
this.repeat = false,
|
||||
bool autopilot = false,
|
||||
this.autopilotInterval,
|
||||
this.autopilotAnimatedZoom = false,
|
||||
}) {
|
||||
_initialScale = initialScale;
|
||||
_autopilotNotifier = ValueNotifier(autopilot);
|
||||
_autopilotNotifier.addListener(_onAutopilotChange);
|
||||
_onAutopilotChange();
|
||||
|
@ -40,21 +54,53 @@ class ViewerController {
|
|||
|
||||
void dispose() {
|
||||
_autopilotNotifier.removeListener(_onAutopilotChange);
|
||||
_clearAutopilotAnimations();
|
||||
_stopPlayTimer();
|
||||
_streamController.close();
|
||||
}
|
||||
|
||||
void _stopPlayTimer() {
|
||||
_playTimer?.cancel();
|
||||
}
|
||||
|
||||
void _onAutopilotChange() {
|
||||
_clearAutopilotAnimations();
|
||||
_stopPlayTimer();
|
||||
if (autopilot && autopilotInterval != null) {
|
||||
_playTimer = Timer.periodic(autopilotInterval!, (_) => _streamController.add(ViewerShowNextEvent()));
|
||||
_streamController.add(const ViewerOverlayToggleEvent(visible: false));
|
||||
}
|
||||
}
|
||||
|
||||
void _stopPlayTimer() => _playTimer?.cancel();
|
||||
|
||||
void _clearAutopilotAnimations() => _autopilotAnimationControllers.keys.toSet().forEach((v) => stopAutopilotAnimation(vsync: v));
|
||||
|
||||
void stopAutopilotAnimation({required TickerProvider vsync}) => _autopilotAnimationControllers.remove(vsync)?.dispose();
|
||||
|
||||
void startAutopilotAnimation({
|
||||
required TickerProvider vsync,
|
||||
required void Function({required ScaleLevel scaleLevel}) onUpdate,
|
||||
}) {
|
||||
stopAutopilotAnimation(vsync: vsync);
|
||||
if (!autopilot || !autopilotAnimatedZoom) return;
|
||||
|
||||
final scaleLevelRef = _initialScale.ref;
|
||||
final scaleFactorTween = _autopilotScaleTweens[Random().nextInt(_autopilotScaleTweens.length)];
|
||||
_autopilotInitialScale = ScaleLevel(ref: scaleLevelRef, factor: scaleFactorTween.begin!);
|
||||
|
||||
final animationController = AnimationController(
|
||||
duration: autopilotInterval,
|
||||
vsync: vsync,
|
||||
);
|
||||
animationController.addListener(() => onUpdate.call(
|
||||
scaleLevel: ScaleLevel(
|
||||
ref: scaleLevelRef,
|
||||
factor: scaleFactorTween.evaluate(CurvedAnimation(
|
||||
parent: animationController,
|
||||
curve: Curves.linear,
|
||||
)),
|
||||
),
|
||||
));
|
||||
_autopilotAnimationControllers[vsync] = animationController;
|
||||
Future.delayed(Durations.viewerHorizontalPageAnimation).then((_) => _autopilotAnimationControllers[vsync]?.forward());
|
||||
}
|
||||
}
|
||||
|
||||
@immutable
|
||||
|
|
|
@ -90,7 +90,7 @@ class _MultiEntryScrollerState extends State<MultiEntryScroller> with AutomaticK
|
|||
key: const Key('image_view'),
|
||||
mainEntry: mainEntry,
|
||||
pageEntry: pageEntry ?? mainEntry,
|
||||
initialScale: viewerController.initialScale,
|
||||
viewerController: viewerController,
|
||||
onDisposed: () => widget.onViewDisposed(mainEntry, pageEntry),
|
||||
);
|
||||
}
|
||||
|
@ -139,7 +139,7 @@ class _SingleEntryScrollerState extends State<SingleEntryScroller> with Automati
|
|||
return EntryPageView(
|
||||
mainEntry: mainEntry,
|
||||
pageEntry: pageEntry ?? mainEntry,
|
||||
initialScale: viewerController.initialScale,
|
||||
viewerController: widget.viewerController,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -229,7 +229,7 @@ class _ViewerVerticalPageViewState extends State<ViewerVerticalPageView> {
|
|||
if (animate) {
|
||||
pageController.animateToPage(
|
||||
target,
|
||||
duration: const Duration(seconds: 1),
|
||||
duration: Durations.viewerHorizontalPageAnimation,
|
||||
curve: Curves.easeInOutCubic,
|
||||
);
|
||||
} else {
|
||||
|
|
|
@ -43,6 +43,7 @@ class _ScreenSaverPageState extends State<ScreenSaverPage> with WidgetsBindingOb
|
|||
repeat: true,
|
||||
autopilot: true,
|
||||
autopilotInterval: settings.screenSaverInterval.getDuration(),
|
||||
autopilotAnimatedZoom: settings.screenSaverAnimatedZoomEffect,
|
||||
);
|
||||
source.stateNotifier.addListener(_onSourceStateChanged);
|
||||
_initSlideshowCollection();
|
||||
|
|
|
@ -45,6 +45,7 @@ class _SlideshowPageState extends State<SlideshowPage> {
|
|||
repeat: settings.slideshowRepeat,
|
||||
autopilot: true,
|
||||
autopilotInterval: settings.slideshowInterval.getDuration(),
|
||||
autopilotAnimatedZoom: settings.slideshowAnimatedZoomEffect,
|
||||
);
|
||||
_initSlideshowCollection();
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ import 'package:aves/widgets/common/magnifier/scale/scale_boundaries.dart';
|
|||
import 'package:aves/widgets/common/magnifier/scale/scale_level.dart';
|
||||
import 'package:aves/widgets/common/magnifier/scale/state.dart';
|
||||
import 'package:aves/widgets/common/thumbnail/image.dart';
|
||||
import 'package:aves/widgets/viewer/controller.dart';
|
||||
import 'package:aves/widgets/viewer/hero.dart';
|
||||
import 'package:aves/widgets/viewer/notifications.dart';
|
||||
import 'package:aves/widgets/viewer/video/conductor.dart';
|
||||
|
@ -35,7 +36,7 @@ import 'package:tuple/tuple.dart';
|
|||
|
||||
class EntryPageView extends StatefulWidget {
|
||||
final AvesEntry mainEntry, pageEntry;
|
||||
final ScaleLevel initialScale;
|
||||
final ViewerController viewerController;
|
||||
final VoidCallback? onDisposed;
|
||||
|
||||
static const decorationCheckSize = 20.0;
|
||||
|
@ -44,7 +45,7 @@ class EntryPageView extends StatefulWidget {
|
|||
super.key,
|
||||
required this.mainEntry,
|
||||
required this.pageEntry,
|
||||
required this.initialScale,
|
||||
required this.viewerController,
|
||||
this.onDisposed,
|
||||
});
|
||||
|
||||
|
@ -52,7 +53,7 @@ class EntryPageView extends StatefulWidget {
|
|||
State<EntryPageView> createState() => _EntryPageViewState();
|
||||
}
|
||||
|
||||
class _EntryPageViewState extends State<EntryPageView> {
|
||||
class _EntryPageViewState extends State<EntryPageView> with SingleTickerProviderStateMixin {
|
||||
late ValueNotifier<ViewState> _viewStateNotifier;
|
||||
late MagnifierController _magnifierController;
|
||||
final List<StreamSubscription> _subscriptions = [];
|
||||
|
@ -72,6 +73,8 @@ class _EntryPageViewState extends State<EntryPageView> {
|
|||
|
||||
AvesEntry get entry => widget.pageEntry;
|
||||
|
||||
ViewerController get viewerController => widget.viewerController;
|
||||
|
||||
// use the high res photo as cover for the video part of a motion photo
|
||||
ImageProvider get videoCoverUriImage => mainEntry.isMotionPhoto ? mainEntry.uriImage : entry.uriImage;
|
||||
|
||||
|
@ -112,9 +115,16 @@ class _EntryPageViewState extends State<EntryPageView> {
|
|||
_videoCoverStream = videoCoverUriImage.resolve(ImageConfiguration.empty);
|
||||
_videoCoverStream!.addListener(_videoCoverStreamListener);
|
||||
}
|
||||
viewerController.startAutopilotAnimation(
|
||||
vsync: this,
|
||||
onUpdate: ({required scaleLevel}) {
|
||||
final scale = _magnifierController.scaleBoundaries.scaleForLevel(scaleLevel);
|
||||
_magnifierController.update(scale: scale, source: ChangeSource.animation);
|
||||
});
|
||||
}
|
||||
|
||||
void _unregisterWidget(EntryPageView oldWidget) {
|
||||
viewerController.stopAutopilotAnimation(vsync: this);
|
||||
_videoCoverStream?.removeListener(_videoCoverStreamListener);
|
||||
_videoCoverStream = null;
|
||||
_videoCoverInfoNotifier.value = null;
|
||||
|
@ -385,7 +395,7 @@ class _EntryPageViewState extends State<EntryPageView> {
|
|||
allowOriginalScaleBeyondRange: !isWallpaperMode,
|
||||
minScale: minScale,
|
||||
maxScale: maxScale,
|
||||
initialScale: widget.initialScale,
|
||||
initialScale: viewerController.initialScale,
|
||||
scaleStateCycle: scaleStateCycle,
|
||||
applyScale: applyScale,
|
||||
onTap: (c, s, a, p) => _onTap(alignment: a),
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
"albumGroupType",
|
||||
"albumMimeTypeMixed",
|
||||
"settingsDisabled",
|
||||
"settingsSlideshowAnimatedZoomEffect",
|
||||
"settingsWidgetOpenPage",
|
||||
"statsTopAlbumsSectionTitle",
|
||||
"wallpaperUseScrollEffect"
|
||||
|
@ -24,6 +25,7 @@
|
|||
"albumGroupType",
|
||||
"albumMimeTypeMixed",
|
||||
"settingsDisabled",
|
||||
"settingsSlideshowAnimatedZoomEffect",
|
||||
"settingsWidgetOpenPage",
|
||||
"statsTopAlbumsSectionTitle",
|
||||
"wallpaperUseScrollEffect"
|
||||
|
@ -54,6 +56,7 @@
|
|||
"searchMetadataSectionTitle",
|
||||
"settingsDisabled",
|
||||
"settingsConfirmationAfterMoveToBinItems",
|
||||
"settingsSlideshowAnimatedZoomEffect",
|
||||
"settingsWidgetOpenPage",
|
||||
"statsTopAlbumsSectionTitle",
|
||||
"viewerInfoLabelDescription",
|
||||
|
@ -74,6 +77,7 @@
|
|||
"albumGroupType",
|
||||
"albumMimeTypeMixed",
|
||||
"settingsDisabled",
|
||||
"settingsSlideshowAnimatedZoomEffect",
|
||||
"settingsWidgetOpenPage",
|
||||
"statsTopAlbumsSectionTitle",
|
||||
"wallpaperUseScrollEffect"
|
||||
|
@ -89,6 +93,7 @@
|
|||
"albumGroupType",
|
||||
"albumMimeTypeMixed",
|
||||
"settingsDisabled",
|
||||
"settingsSlideshowAnimatedZoomEffect",
|
||||
"settingsWidgetOpenPage",
|
||||
"statsTopAlbumsSectionTitle",
|
||||
"wallpaperUseScrollEffect"
|
||||
|
@ -120,6 +125,7 @@
|
|||
"settingsDisabled",
|
||||
"settingsConfirmationAfterMoveToBinItems",
|
||||
"settingsViewerGestureSideTapNext",
|
||||
"settingsSlideshowAnimatedZoomEffect",
|
||||
"settingsWidgetOpenPage",
|
||||
"statsTopAlbumsSectionTitle",
|
||||
"viewerInfoLabelDescription",
|
||||
|
@ -140,6 +146,7 @@
|
|||
"albumGroupType",
|
||||
"albumMimeTypeMixed",
|
||||
"settingsDisabled",
|
||||
"settingsSlideshowAnimatedZoomEffect",
|
||||
"settingsWidgetOpenPage",
|
||||
"statsTopAlbumsSectionTitle",
|
||||
"wallpaperUseScrollEffect"
|
||||
|
@ -155,6 +162,7 @@
|
|||
"albumGroupType",
|
||||
"albumMimeTypeMixed",
|
||||
"settingsDisabled",
|
||||
"settingsSlideshowAnimatedZoomEffect",
|
||||
"settingsWidgetOpenPage",
|
||||
"statsTopAlbumsSectionTitle",
|
||||
"wallpaperUseScrollEffect"
|
||||
|
@ -170,6 +178,7 @@
|
|||
"albumGroupType",
|
||||
"albumMimeTypeMixed",
|
||||
"settingsDisabled",
|
||||
"settingsSlideshowAnimatedZoomEffect",
|
||||
"settingsWidgetOpenPage",
|
||||
"statsTopAlbumsSectionTitle",
|
||||
"wallpaperUseScrollEffect"
|
||||
|
@ -220,6 +229,7 @@
|
|||
"settingsSlideshowRepeat",
|
||||
"settingsSlideshowShuffle",
|
||||
"settingsSlideshowFillScreen",
|
||||
"settingsSlideshowAnimatedZoomEffect",
|
||||
"settingsSlideshowTransitionTile",
|
||||
"settingsSlideshowTransitionDialogTitle",
|
||||
"settingsSlideshowIntervalTile",
|
||||
|
@ -245,6 +255,7 @@
|
|||
"albumGroupType",
|
||||
"albumMimeTypeMixed",
|
||||
"settingsDisabled",
|
||||
"settingsSlideshowAnimatedZoomEffect",
|
||||
"settingsWidgetOpenPage",
|
||||
"statsTopAlbumsSectionTitle",
|
||||
"wallpaperUseScrollEffect"
|
||||
|
|
Loading…
Reference in a new issue