mirror of
https://github.com/immich-app/immich.git
synced 2026-05-16 20:42:12 -04:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 977dc71d95 |
@@ -9,11 +9,7 @@ import 'package:flutter/painting.dart';
|
|||||||
/// Codec is disposed through the MultiFrameImageStreamCompleter's internals onDispose method
|
/// Codec is disposed through the MultiFrameImageStreamCompleter's internals onDispose method
|
||||||
class AnimatedImageStreamCompleter extends MultiFrameImageStreamCompleter {
|
class AnimatedImageStreamCompleter extends MultiFrameImageStreamCompleter {
|
||||||
void Function()? _onLastListenerRemoved;
|
void Function()? _onLastListenerRemoved;
|
||||||
int _listenerCount = 0;
|
ImageStreamListener? _cacheListener;
|
||||||
// True once any image or the codec has been provided.
|
|
||||||
// Until then the image cache holds one listener, so "last real listener gone"
|
|
||||||
// is _listenerCount == 1, not 0.
|
|
||||||
bool didProvideImage = false;
|
|
||||||
|
|
||||||
AnimatedImageStreamCompleter._({
|
AnimatedImageStreamCompleter._({
|
||||||
required super.codec,
|
required super.codec,
|
||||||
@@ -38,18 +34,15 @@ class AnimatedImageStreamCompleter extends MultiFrameImageStreamCompleter {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (initialImage != null) {
|
if (initialImage != null) {
|
||||||
self.didProvideImage = true;
|
|
||||||
self.setImage(initialImage);
|
self.setImage(initialImage);
|
||||||
}
|
}
|
||||||
|
|
||||||
stream.listen(
|
stream.listen(
|
||||||
(item) {
|
(item) {
|
||||||
if (item is ImageInfo) {
|
if (item is ImageInfo) {
|
||||||
self.didProvideImage = true;
|
|
||||||
self.setImage(item);
|
self.setImage(item);
|
||||||
} else if (item is ui.Codec) {
|
} else if (item is ui.Codec) {
|
||||||
if (!codecCompleter.isCompleted) {
|
if (!codecCompleter.isCompleted) {
|
||||||
self.didProvideImage = true;
|
|
||||||
codecCompleter.complete(item);
|
codecCompleter.complete(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -60,8 +53,6 @@ class AnimatedImageStreamCompleter extends MultiFrameImageStreamCompleter {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
onDone: () {
|
onDone: () {
|
||||||
// also complete if we are done but no error occurred, and we didn't call complete yet
|
|
||||||
// could happen on cancellation
|
|
||||||
if (!codecCompleter.isCompleted) {
|
if (!codecCompleter.isCompleted) {
|
||||||
codecCompleter.completeError(StateError('Stream closed without providing a codec'));
|
codecCompleter.completeError(StateError('Stream closed without providing a codec'));
|
||||||
}
|
}
|
||||||
@@ -73,24 +64,20 @@ class AnimatedImageStreamCompleter extends MultiFrameImageStreamCompleter {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void addListener(ImageStreamListener listener) {
|
void addListener(ImageStreamListener listener) {
|
||||||
|
_cacheListener ??= listener;
|
||||||
super.addListener(listener);
|
super.addListener(listener);
|
||||||
_listenerCount++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void removeListener(ImageStreamListener listener) {
|
void removeListener(ImageStreamListener listener) {
|
||||||
super.removeListener(listener);
|
super.removeListener(listener);
|
||||||
_listenerCount--;
|
if (listener != _cacheListener) {
|
||||||
|
_cancel();
|
||||||
final bool onlyCacheListenerLeft = _listenerCount == 1 && !didProvideImage;
|
|
||||||
final bool noListenersAfterCodec = _listenerCount == 0 && didProvideImage;
|
|
||||||
|
|
||||||
if (onlyCacheListenerLeft || noListenersAfterCodec) {
|
|
||||||
final onLastListenerRemoved = _onLastListenerRemoved;
|
|
||||||
if (onLastListenerRemoved != null) {
|
|
||||||
_onLastListenerRemoved = null;
|
|
||||||
onLastListenerRemoved();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _cancel() {
|
||||||
|
_onLastListenerRemoved?.call();
|
||||||
|
_onLastListenerRemoved = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-21
@@ -10,9 +10,7 @@ import 'package:flutter/painting.dart';
|
|||||||
/// An ImageStreamCompleter with support for loading multiple images.
|
/// An ImageStreamCompleter with support for loading multiple images.
|
||||||
class OneFramePlaceholderImageStreamCompleter extends ImageStreamCompleter {
|
class OneFramePlaceholderImageStreamCompleter extends ImageStreamCompleter {
|
||||||
void Function()? _onLastListenerRemoved;
|
void Function()? _onLastListenerRemoved;
|
||||||
int _listenerCount = 0;
|
ImageStreamListener? _cacheListener;
|
||||||
// True once setImage() has been called at least once.
|
|
||||||
bool didProvideImage = false;
|
|
||||||
|
|
||||||
/// The constructor to create an OneFramePlaceholderImageStreamCompleter. The [images]
|
/// The constructor to create an OneFramePlaceholderImageStreamCompleter. The [images]
|
||||||
/// should be the primary images to display (typically asynchronously as they load).
|
/// should be the primary images to display (typically asynchronously as they load).
|
||||||
@@ -23,17 +21,12 @@ class OneFramePlaceholderImageStreamCompleter extends ImageStreamCompleter {
|
|||||||
ImageInfo? initialImage,
|
ImageInfo? initialImage,
|
||||||
InformationCollector? informationCollector,
|
InformationCollector? informationCollector,
|
||||||
void Function()? onLastListenerRemoved,
|
void Function()? onLastListenerRemoved,
|
||||||
}) {
|
}) : _onLastListenerRemoved = onLastListenerRemoved {
|
||||||
if (initialImage != null) {
|
if (initialImage != null) {
|
||||||
didProvideImage = true;
|
|
||||||
setImage(initialImage);
|
setImage(initialImage);
|
||||||
}
|
}
|
||||||
_onLastListenerRemoved = onLastListenerRemoved;
|
|
||||||
images.listen(
|
images.listen(
|
||||||
(image) {
|
(image) => setImage(image),
|
||||||
didProvideImage = true;
|
|
||||||
setImage(image);
|
|
||||||
},
|
|
||||||
onError: (Object error, StackTrace stack) {
|
onError: (Object error, StackTrace stack) {
|
||||||
reportError(
|
reportError(
|
||||||
context: ErrorDescription('resolving a single-frame image stream'),
|
context: ErrorDescription('resolving a single-frame image stream'),
|
||||||
@@ -48,23 +41,20 @@ class OneFramePlaceholderImageStreamCompleter extends ImageStreamCompleter {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void addListener(ImageStreamListener listener) {
|
void addListener(ImageStreamListener listener) {
|
||||||
|
_cacheListener ??= listener;
|
||||||
super.addListener(listener);
|
super.addListener(listener);
|
||||||
_listenerCount = _listenerCount + 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void removeListener(ImageStreamListener listener) {
|
void removeListener(ImageStreamListener listener) {
|
||||||
super.removeListener(listener);
|
super.removeListener(listener);
|
||||||
_listenerCount = _listenerCount - 1;
|
if (listener != _cacheListener) {
|
||||||
|
_cancel();
|
||||||
final bool onlyCacheListenerLeft = _listenerCount == 1 && !didProvideImage;
|
|
||||||
final bool noListenersAfterImage = _listenerCount == 0 && didProvideImage;
|
|
||||||
|
|
||||||
final onLastListenerRemoved = _onLastListenerRemoved;
|
|
||||||
|
|
||||||
if (onLastListenerRemoved != null && (noListenersAfterImage || onlyCacheListenerLeft)) {
|
|
||||||
_onLastListenerRemoved = null;
|
|
||||||
onLastListenerRemoved();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _cancel() {
|
||||||
|
_onLastListenerRemoved?.call();
|
||||||
|
_onLastListenerRemoved = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-4
@@ -1194,10 +1194,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: meta
|
name: meta
|
||||||
sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394"
|
sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.17.0"
|
version: "1.16.0"
|
||||||
mime:
|
mime:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -1897,10 +1897,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: test_api
|
name: test_api
|
||||||
sha256: ab2726c1a94d3176a45960b6234466ec367179b87dd74f1611adb1f3b5fb9d55
|
sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.7.7"
|
version: "0.7.6"
|
||||||
thumbhash:
|
thumbhash:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
|||||||
Reference in New Issue
Block a user