viewer: reset multipage controllers when entry metadata change
This commit is contained in:
parent
b6af664f52
commit
7ef87c125c
4 changed files with 40 additions and 5 deletions
|
@ -738,7 +738,12 @@ class AvesEntry {
|
||||||
}
|
}
|
||||||
|
|
||||||
// when the MIME type or the image itself changed (e.g. after rotation)
|
// when the MIME type or the image itself changed (e.g. after rotation)
|
||||||
Future<void> _onVisualFieldChanged(String oldMimeType, int? oldDateModifiedSecs, int oldRotationDegrees, bool oldIsFlipped) async {
|
Future<void> _onVisualFieldChanged(
|
||||||
|
String oldMimeType,
|
||||||
|
int? oldDateModifiedSecs,
|
||||||
|
int oldRotationDegrees,
|
||||||
|
bool oldIsFlipped,
|
||||||
|
) async {
|
||||||
if ((!MimeTypes.refersToSameType(oldMimeType, mimeType) && !MimeTypes.isVideo(oldMimeType)) || oldDateModifiedSecs != dateModifiedSecs || oldRotationDegrees != rotationDegrees || oldIsFlipped != isFlipped) {
|
if ((!MimeTypes.refersToSameType(oldMimeType, mimeType) && !MimeTypes.isVideo(oldMimeType)) || oldDateModifiedSecs != dateModifiedSecs || oldRotationDegrees != rotationDegrees || oldIsFlipped != isFlipped) {
|
||||||
await EntryCache.evict(uri, oldMimeType, oldDateModifiedSecs, oldRotationDegrees, oldIsFlipped);
|
await EntryCache.evict(uri, oldMimeType, oldDateModifiedSecs, oldRotationDegrees, oldIsFlipped);
|
||||||
imageChangeNotifier.notify();
|
imageChangeNotifier.notify();
|
||||||
|
|
|
@ -71,6 +71,9 @@ class _EntryViewerStackState extends State<EntryViewerStack> with EntryViewContr
|
||||||
final ValueNotifier<HeroInfo?> _heroInfoNotifier = ValueNotifier(null);
|
final ValueNotifier<HeroInfo?> _heroInfoNotifier = ValueNotifier(null);
|
||||||
bool _isEntryTracked = true;
|
bool _isEntryTracked = true;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool get isViewingImage => _currentVerticalPage.value == imagePage;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
late final ValueNotifier<AvesEntry?> entryNotifier;
|
late final ValueNotifier<AvesEntry?> entryNotifier;
|
||||||
|
|
||||||
|
|
|
@ -14,8 +14,11 @@ import 'package:provider/provider.dart';
|
||||||
|
|
||||||
// state controllers/monitors
|
// state controllers/monitors
|
||||||
mixin EntryViewControllerMixin<T extends StatefulWidget> on State<T> {
|
mixin EntryViewControllerMixin<T extends StatefulWidget> on State<T> {
|
||||||
|
final Map<AvesEntry, VoidCallback> _metadataChangeListeners = {};
|
||||||
final Map<MultiPageController, Future<void> Function()> _multiPageControllerPageListeners = {};
|
final Map<MultiPageController, Future<void> Function()> _multiPageControllerPageListeners = {};
|
||||||
|
|
||||||
|
bool get isViewingImage;
|
||||||
|
|
||||||
ValueNotifier<AvesEntry?> get entryNotifier;
|
ValueNotifier<AvesEntry?> get entryNotifier;
|
||||||
|
|
||||||
Future<void> initEntryControllers(AvesEntry? entry) async {
|
Future<void> initEntryControllers(AvesEntry? entry) async {
|
||||||
|
@ -27,16 +30,29 @@ mixin EntryViewControllerMixin<T extends StatefulWidget> on State<T> {
|
||||||
if (entry.isMultiPage) {
|
if (entry.isMultiPage) {
|
||||||
await _initMultiPageController(entry);
|
await _initMultiPageController(entry);
|
||||||
}
|
}
|
||||||
|
void listener() => _onMetadataChange(entry);
|
||||||
|
_metadataChangeListeners[entry] = listener;
|
||||||
|
entry.metadataChangeNotifier.addListener(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cleanEntryControllers(AvesEntry? entry) {
|
void cleanEntryControllers(AvesEntry? entry) {
|
||||||
if (entry == null) return;
|
if (entry == null) return;
|
||||||
|
|
||||||
|
final listener = _metadataChangeListeners.remove(entry);
|
||||||
|
if (listener != null) {
|
||||||
|
entry.metadataChangeNotifier.removeListener(listener);
|
||||||
|
}
|
||||||
if (entry.isMultiPage) {
|
if (entry.isMultiPage) {
|
||||||
_cleanMultiPageController(entry);
|
_cleanMultiPageController(entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _onMetadataChange(AvesEntry entry) {
|
||||||
|
debugPrint('reinitialize controllers for entry=$entry because metadata changed');
|
||||||
|
cleanEntryControllers(entry);
|
||||||
|
initEntryControllers(entry);
|
||||||
|
}
|
||||||
|
|
||||||
SlideshowVideoPlayback? get videoPlaybackOverride {
|
SlideshowVideoPlayback? get videoPlaybackOverride {
|
||||||
if (!mounted) return null;
|
if (!mounted) return null;
|
||||||
final appMode = context.read<ValueNotifier<AppMode>>().value;
|
final appMode = context.read<ValueNotifier<AppMode>>().value;
|
||||||
|
@ -50,7 +66,9 @@ mixin EntryViewControllerMixin<T extends StatefulWidget> on State<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _shouldAutoPlay(BuildContext context) {
|
bool _shouldAutoPlayVideo(BuildContext context) {
|
||||||
|
if (!isViewingImage) return false;
|
||||||
|
|
||||||
switch (videoPlaybackOverride) {
|
switch (videoPlaybackOverride) {
|
||||||
case SlideshowVideoPlayback.skip:
|
case SlideshowVideoPlayback.skip:
|
||||||
return false;
|
return false;
|
||||||
|
@ -62,11 +80,17 @@ mixin EntryViewControllerMixin<T extends StatefulWidget> on State<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool _shouldAutoPlayMotionPhoto(BuildContext context) {
|
||||||
|
if (!isViewingImage) return false;
|
||||||
|
|
||||||
|
return settings.enableMotionPhotoAutoPlay;
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> _initVideoController(AvesEntry entry) async {
|
Future<void> _initVideoController(AvesEntry entry) async {
|
||||||
final controller = context.read<VideoConductor>().getOrCreateController(entry);
|
final controller = context.read<VideoConductor>().getOrCreateController(entry);
|
||||||
setState(() {});
|
setState(() {});
|
||||||
|
|
||||||
if (_shouldAutoPlay(context)) {
|
if (_shouldAutoPlayVideo(context)) {
|
||||||
final resumeTimeMillis = await controller.getResumeTime(context);
|
final resumeTimeMillis = await controller.getResumeTime(context);
|
||||||
await _playVideo(controller, () => entry == entryNotifier.value, resumeTimeMillis: resumeTimeMillis);
|
await _playVideo(controller, () => entry == entryNotifier.value, resumeTimeMillis: resumeTimeMillis);
|
||||||
}
|
}
|
||||||
|
@ -93,7 +117,7 @@ mixin EntryViewControllerMixin<T extends StatefulWidget> on State<T> {
|
||||||
// auto play/pause when changing page
|
// auto play/pause when changing page
|
||||||
Future<void> _onPageChange() async {
|
Future<void> _onPageChange() async {
|
||||||
await pauseVideoControllers();
|
await pauseVideoControllers();
|
||||||
if (_shouldAutoPlay(context) || (entry.isMotionPhoto && settings.enableMotionPhotoAutoPlay)) {
|
if (_shouldAutoPlayVideo(context) || (entry.isMotionPhoto && _shouldAutoPlayMotionPhoto(context))) {
|
||||||
final page = multiPageController.page;
|
final page = multiPageController.page;
|
||||||
final pageInfo = multiPageInfo.getByIndex(page)!;
|
final pageInfo = multiPageInfo.getByIndex(page)!;
|
||||||
if (pageInfo.isVideo) {
|
if (pageInfo.isVideo) {
|
||||||
|
@ -111,7 +135,7 @@ mixin EntryViewControllerMixin<T extends StatefulWidget> on State<T> {
|
||||||
multiPageController.pageNotifier.addListener(_onPageChange);
|
multiPageController.pageNotifier.addListener(_onPageChange);
|
||||||
await _onPageChange();
|
await _onPageChange();
|
||||||
|
|
||||||
if (entry.isMotionPhoto && settings.enableMotionPhotoAutoPlay) {
|
if (entry.isMotionPhoto && _shouldAutoPlayMotionPhoto(context)) {
|
||||||
await Future.delayed(Durations.motionPhotoAutoPlayDelay);
|
await Future.delayed(Durations.motionPhotoAutoPlayDelay);
|
||||||
if (entry == entryNotifier.value) {
|
if (entry == entryNotifier.value) {
|
||||||
multiPageController.page = 1;
|
multiPageController.page = 1;
|
||||||
|
|
|
@ -75,6 +75,9 @@ class _EntryEditorState extends State<EntryEditor> with EntryViewControllerMixin
|
||||||
late VideoActionDelegate _videoActionDelegate;
|
late VideoActionDelegate _videoActionDelegate;
|
||||||
late final ViewerController _viewerController;
|
late final ViewerController _viewerController;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool get isViewingImage => true;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
final ValueNotifier<AvesEntry?> entryNotifier = ValueNotifier(null);
|
final ValueNotifier<AvesEntry?> entryNotifier = ValueNotifier(null);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue