diff --git a/CHANGELOG.md b/CHANGELOG.md index a1392714b..d6763f3ea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ All notable changes to this project will be documented in this file. - support for animated PNG - Info: added day filter with item date - Widget: option to update image on tap +- Slideshow / Screen saver: option for random transition ### Changed diff --git a/lib/model/settings/enums/viewer_transition.dart b/lib/model/settings/enums/viewer_transition.dart index b97b5b77c..81aefe62a 100644 --- a/lib/model/settings/enums/viewer_transition.dart +++ b/lib/model/settings/enums/viewer_transition.dart @@ -1,5 +1,8 @@ +import 'dart:math'; + import 'package:aves/widgets/viewer/controls/controller.dart'; import 'package:aves_model/aves_model.dart'; +import 'package:collection/collection.dart'; import 'package:flutter/widgets.dart'; extension ExtraViewerTransition on ViewerTransition { @@ -15,6 +18,46 @@ extension ExtraViewerTransition on ViewerTransition { return PageTransitionEffects.fade(pageController, index, zoomIn: true); case ViewerTransition.none: return PageTransitionEffects.none(pageController, index); + case ViewerTransition.random: + return _ViewerTransitionRandomizer.getBuilder(pageController, index); } } } + +class _ViewerTransitionRandomizer { + static const options = [ + ViewerTransition.slide, + ViewerTransition.parallax, + ViewerTransition.fade, + ViewerTransition.zoomIn, + ]; + + static final List<(int, ViewerTransition)> _indexedTransitions = []; + + static TransitionBuilder getBuilder( + PageController pageController, + int index, + ) => + (context, child) { + final negative = pageController.hasClients && pageController.position.haveDimensions && (pageController.page! - index).isNegative; + final transition = _getTransition(negative ? index - 1 : index); + final builder = transition.builder(pageController, index); + return builder(context, child); + }; + + static ViewerTransition _getTransition(int transitionIndex) { + var indexedTransition = _indexedTransitions.firstWhereOrNull((v) => v.$1 == transitionIndex); + if (indexedTransition != null) { + _indexedTransitions.remove(indexedTransition); + } else { + indexedTransition = (transitionIndex, options[Random().nextInt(options.length)]); + } + _indexedTransitions.insert(0, indexedTransition); + while (_indexedTransitions.length > 3) { + _indexedTransitions.removeLast(); + } + + final (_, transition) = indexedTransition; + return transition; + } +} diff --git a/lib/view/src/settings/enums.dart b/lib/view/src/settings/enums.dart index dedfc4018..8b7abc0c5 100644 --- a/lib/view/src/settings/enums.dart +++ b/lib/view/src/settings/enums.dart @@ -251,6 +251,8 @@ extension ExtraViewerTransitionView on ViewerTransition { return context.l10n.viewerTransitionZoomIn; case ViewerTransition.none: return context.l10n.viewerTransitionNone; + case ViewerTransition.random: + return context.l10n.widgetDisplayedItemRandom; } } } diff --git a/plugins/aves_model/lib/src/settings/enums.dart b/plugins/aves_model/lib/src/settings/enums.dart index 2508a8f3b..3f327feca 100644 --- a/plugins/aves_model/lib/src/settings/enums.dart +++ b/plugins/aves_model/lib/src/settings/enums.dart @@ -40,7 +40,7 @@ enum VideoLoopMode { never, shortOnly, always } enum VideoResumptionMode { never, ask, always } -enum ViewerTransition { slide, parallax, fade, zoomIn, none } +enum ViewerTransition { slide, parallax, fade, zoomIn, none, random } enum WidgetDisplayedItem { random, mostRecent }