diff --git a/CHANGELOG.md b/CHANGELOG.md
index acf5448cc..07e5763a0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,12 +6,19 @@ All notable changes to this project will be documented in this file.
### Added
+- Collection / Albums / Countries / Tags: list view (scalable like the grid view)
- moving, editing or deleting multiple items can be cancelled
+- Viewer: option to auto play motion photos (after a small delay to show first the high-res photo)
### Changed
- upgraded Flutter to stable v2.8.1
+### Fixed
+
+- Collection: more consistent scroll bar thumb position to match the viewport
+- Settings: fixed file selection to import settings on older devices
+
## [v1.5.7] - 2021-12-01
### Added
diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/model/provider/MediaStoreImageProvider.kt b/android/app/src/main/kotlin/deckers/thibault/aves/model/provider/MediaStoreImageProvider.kt
index 2811f3f22..4e4a305d1 100644
--- a/android/app/src/main/kotlin/deckers/thibault/aves/model/provider/MediaStoreImageProvider.kt
+++ b/android/app/src/main/kotlin/deckers/thibault/aves/model/provider/MediaStoreImageProvider.kt
@@ -565,6 +565,7 @@ class MediaStoreImageProvider : ImageProvider() {
throw Exception("unsupported Android version")
}
+ Log.d(LOG_TAG, "rename content at uri=$mediaUri")
val uri = StorageUtils.getMediaStoreScopedStorageSafeUri(mediaUri, mimeType)
// `IS_PENDING` is necessary for `TITLE`, not for `DISPLAY_NAME`
diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb
index 816a4468c..8de93e51d 100644
--- a/lib/l10n/app_en.arb
+++ b/lib/l10n/app_en.arb
@@ -816,6 +816,8 @@
"@settingsViewerUseCutout": {},
"settingsViewerMaximumBrightness": "Maximum brightness",
"@settingsViewerMaximumBrightness": {},
+ "settingsMotionPhotoAutoPlay": "Auto play motion photos",
+ "@settingsMotionPhotoAutoPlay": {},
"settingsImageBackground": "Image background",
"@settingsImageBackground": {},
diff --git a/lib/l10n/app_fr.arb b/lib/l10n/app_fr.arb
index e25a14c4d..965aa0ce9 100644
--- a/lib/l10n/app_fr.arb
+++ b/lib/l10n/app_fr.arb
@@ -381,6 +381,7 @@
"settingsSectionViewer": "Visionneuse",
"settingsViewerUseCutout": "Utiliser la zone d’encoche",
"settingsViewerMaximumBrightness": "Luminosité maximale",
+ "settingsMotionPhotoAutoPlay": "Lecture automatique des photos animées",
"settingsImageBackground": "Arrière-plan de l’image",
"settingsViewerQuickActionsTile": "Actions rapides",
diff --git a/lib/l10n/app_ko.arb b/lib/l10n/app_ko.arb
index 6dc73b269..5ec0b4db0 100644
--- a/lib/l10n/app_ko.arb
+++ b/lib/l10n/app_ko.arb
@@ -381,6 +381,7 @@
"settingsSectionViewer": "뷰어",
"settingsViewerUseCutout": "컷아웃 영역 사용",
"settingsViewerMaximumBrightness": "최대 밝기",
+ "settingsMotionPhotoAutoPlay": "모션 포토 자동 재생",
"settingsImageBackground": "이미지 배경",
"settingsViewerQuickActionsTile": "빠른 작업",
diff --git a/lib/model/settings/defaults.dart b/lib/model/settings/defaults.dart
index cf13171fd..96ff24077 100644
--- a/lib/model/settings/defaults.dart
+++ b/lib/model/settings/defaults.dart
@@ -67,6 +67,7 @@ class SettingsDefaults {
static const enableOverlayBlurEffect = true; // `enableOverlayBlurEffect` has a contextual default value
static const viewerUseCutout = true;
static const viewerMaxBrightness = false;
+ static const enableMotionPhotoAutoPlay = false;
// video
static const videoQuickActions = [
diff --git a/lib/model/settings/settings.dart b/lib/model/settings/settings.dart
index f5b9ac2c2..3716eb79e 100644
--- a/lib/model/settings/settings.dart
+++ b/lib/model/settings/settings.dart
@@ -83,6 +83,8 @@ class Settings extends ChangeNotifier {
static const enableOverlayBlurEffectKey = 'enable_overlay_blur_effect';
static const viewerUseCutoutKey = 'viewer_use_cutout';
static const viewerMaxBrightnessKey = 'viewer_max_brightness';
+ static const enableMotionPhotoAutoPlayKey = 'motion_photo_auto_play';
+ static const imageBackgroundKey = 'image_background';
// video
static const videoQuickActionsKey = 'video_quick_actions';
@@ -104,9 +106,6 @@ class Settings extends ChangeNotifier {
static const coordinateFormatKey = 'coordinates_format';
static const unitSystemKey = 'unit_system';
- // rendering
- static const imageBackgroundKey = 'image_background';
-
// search
static const saveSearchHistoryKey = 'save_search_history';
static const searchHistoryKey = 'search_history';
@@ -365,6 +364,14 @@ class Settings extends ChangeNotifier {
set viewerMaxBrightness(bool newValue) => setAndNotify(viewerMaxBrightnessKey, newValue);
+ bool get enableMotionPhotoAutoPlay => getBoolOrDefault(enableMotionPhotoAutoPlayKey, SettingsDefaults.enableMotionPhotoAutoPlay);
+
+ set enableMotionPhotoAutoPlay(bool newValue) => setAndNotify(enableMotionPhotoAutoPlayKey, newValue);
+
+ EntryBackground get imageBackground => getEnumOrDefault(imageBackgroundKey, SettingsDefaults.imageBackground, EntryBackground.values);
+
+ set imageBackground(EntryBackground newValue) => setAndNotify(imageBackgroundKey, newValue.toString());
+
// video
List get videoQuickActions => getEnumListOrDefault(videoQuickActionsKey, SettingsDefaults.videoQuickActions, VideoAction.values);
@@ -427,12 +434,6 @@ class Settings extends ChangeNotifier {
set unitSystem(UnitSystem newValue) => setAndNotify(unitSystemKey, newValue.toString());
- // rendering
-
- EntryBackground get imageBackground => getEnumOrDefault(imageBackgroundKey, SettingsDefaults.imageBackground, EntryBackground.values);
-
- set imageBackground(EntryBackground newValue) => setAndNotify(imageBackgroundKey, newValue.toString());
-
// search
bool get saveSearchHistory => getBoolOrDefault(saveSearchHistoryKey, SettingsDefaults.saveSearchHistory);
@@ -613,6 +614,7 @@ class Settings extends ChangeNotifier {
case enableOverlayBlurEffectKey:
case viewerUseCutoutKey:
case viewerMaxBrightnessKey:
+ case enableMotionPhotoAutoPlayKey:
case enableVideoHardwareAccelerationKey:
case enableVideoAutoPlayKey:
case subtitleShowOutlineKey:
@@ -633,12 +635,12 @@ class Settings extends ChangeNotifier {
case albumSortFactorKey:
case countrySortFactorKey:
case tagSortFactorKey:
+ case imageBackgroundKey:
case videoLoopModeKey:
case subtitleTextAlignmentKey:
case infoMapStyleKey:
case coordinateFormatKey:
case unitSystemKey:
- case imageBackgroundKey:
case accessibilityAnimationsKey:
case timeToTakeActionKey:
if (value is String) {
diff --git a/lib/theme/durations.dart b/lib/theme/durations.dart
index b071be57c..33060b455 100644
--- a/lib/theme/durations.dart
+++ b/lib/theme/durations.dart
@@ -59,6 +59,7 @@ class Durations {
static const collectionScrollMonitoringTimerDelay = Duration(milliseconds: 100);
static const highlightJumpDelay = Duration(milliseconds: 400);
static const highlightScrollInitDelay = Duration(milliseconds: 800);
+ static const motionPhotoAutoPlayDelay = Duration(milliseconds: 700);
static const videoOverlayHideDelay = Duration(milliseconds: 500);
static const videoProgressTimerInterval = Duration(milliseconds: 300);
static const doubleBackTimerDelay = Duration(milliseconds: 1000);
diff --git a/lib/widgets/settings/viewer/viewer.dart b/lib/widgets/settings/viewer/viewer.dart
index ec62009e8..3e0ddb026 100644
--- a/lib/widgets/settings/viewer/viewer.dart
+++ b/lib/widgets/settings/viewer/viewer.dart
@@ -42,6 +42,14 @@ class ViewerSection extends StatelessWidget {
title: Text(context.l10n.settingsViewerMaximumBrightness),
),
),
+ Selector(
+ selector: (context, s) => s.enableMotionPhotoAutoPlay,
+ builder: (context, current, child) => SwitchListTile(
+ value: current,
+ onChanged: (v) => settings.enableMotionPhotoAutoPlay = v,
+ title: Text(context.l10n.settingsMotionPhotoAutoPlay),
+ ),
+ ),
Selector(
selector: (context, s) => s.imageBackground,
builder: (context, current, child) => ListTile(
diff --git a/lib/widgets/viewer/entry_viewer_stack.dart b/lib/widgets/viewer/entry_viewer_stack.dart
index fbac83b33..f9004e3ba 100644
--- a/lib/widgets/viewer/entry_viewer_stack.dart
+++ b/lib/widgets/viewer/entry_viewer_stack.dart
@@ -630,7 +630,7 @@ class _EntryViewerStackState extends State with FeedbackMixin,
// auto play/pause when changing page
Future _onPageChange() async {
await _pauseVideoControllers();
- if (settings.enableVideoAutoPlay) {
+ if (settings.enableVideoAutoPlay || (entry.isMotionPhoto && settings.enableMotionPhotoAutoPlay)) {
final page = multiPageController.page;
final pageInfo = multiPageInfo.getByIndex(page)!;
if (pageInfo.isVideo) {
@@ -644,6 +644,13 @@ class _EntryViewerStackState extends State with FeedbackMixin,
_multiPageControllerPageListeners[multiPageController] = _onPageChange;
multiPageController.pageNotifier.addListener(_onPageChange);
await _onPageChange();
+
+ if (entry.isMotionPhoto && settings.enableMotionPhotoAutoPlay) {
+ await Future.delayed(Durations.motionPhotoAutoPlayDelay);
+ if (entry == _entryNotifier.value) {
+ multiPageController.page = 1;
+ }
+ }
}
}
diff --git a/lib/widgets/viewer/visual/entry_page_view.dart b/lib/widgets/viewer/visual/entry_page_view.dart
index 0d9666b5f..38a05b853 100644
--- a/lib/widgets/viewer/visual/entry_page_view.dart
+++ b/lib/widgets/viewer/visual/entry_page_view.dart
@@ -63,6 +63,9 @@ class _EntryPageViewState extends State {
AvesEntry get entry => widget.pageEntry;
+ // use the high res photo as cover for the video part of a motion photo
+ ImageProvider get videoCoverUriImage => mainEntry.isMotionPhoto ? mainEntry.uriImage : entry.uriImage;
+
static const initialScale = ScaleLevel(ref: ScaleReference.contained);
static const minScale = ScaleLevel(ref: ScaleReference.contained);
static const maxScale = ScaleLevel(factor: 2.0);
@@ -98,7 +101,7 @@ class _EntryPageViewState extends State {
_subscriptions.add(_magnifierController.scaleBoundariesStream.listen(_onViewScaleBoundariesChanged));
if (entry.isVideo) {
_videoCoverStreamListener = ImageStreamListener((image, _) => _videoCoverInfoNotifier.value = image);
- _videoCoverStream = entry.uriImage.resolve(ImageConfiguration.empty);
+ _videoCoverStream = videoCoverUriImage.resolve(ImageConfiguration.empty);
_videoCoverStream!.addListener(_videoCoverStreamListener);
}
}
@@ -248,7 +251,7 @@ class _EntryPageViewState extends State {
controller: coverController,
displaySize: coverSize,
child: Image(
- image: entry.uriImage,
+ image: videoCoverUriImage,
),
);
}
diff --git a/untranslated.json b/untranslated.json
index c783aff7e..4d2157c53 100644
--- a/untranslated.json
+++ b/untranslated.json
@@ -3,6 +3,7 @@
"menuActionConfigureView",
"viewDialogTabLayout",
"tileLayoutGrid",
- "tileLayoutList"
+ "tileLayoutList",
+ "settingsMotionPhotoAutoPlay"
]
}