mirror of
https://github.com/immich-app/immich.git
synced 2026-05-18 13:32:16 -04:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| cb328c63cf | |||
| afc470e8f4 | |||
| b156ae46b6 | |||
| 67b1a9d99e | |||
| d4f7c2ae0a |
@@ -4,6 +4,7 @@ enum Setting<T> {
|
|||||||
tilesPerRow<int>(StoreKey.tilesPerRow, 4),
|
tilesPerRow<int>(StoreKey.tilesPerRow, 4),
|
||||||
groupAssetsBy<int>(StoreKey.groupAssetsBy, 0),
|
groupAssetsBy<int>(StoreKey.groupAssetsBy, 0),
|
||||||
showStorageIndicator<bool>(StoreKey.storageIndicator, true),
|
showStorageIndicator<bool>(StoreKey.storageIndicator, true),
|
||||||
|
loadPreview<bool>(StoreKey.loadPreview, true),
|
||||||
loadOriginal<bool>(StoreKey.loadOriginal, false),
|
loadOriginal<bool>(StoreKey.loadOriginal, false),
|
||||||
loadOriginalVideo<bool>(StoreKey.loadOriginalVideo, false),
|
loadOriginalVideo<bool>(StoreKey.loadOriginalVideo, false),
|
||||||
autoPlayVideo<bool>(StoreKey.autoPlayVideo, true),
|
autoPlayVideo<bool>(StoreKey.autoPlayVideo, true),
|
||||||
|
|||||||
@@ -45,7 +45,6 @@ mixin CancellableImageProviderMixin<T extends Object> on CancellableImageProvide
|
|||||||
|
|
||||||
completer.operation.valueOrCancellation().whenComplete(() {
|
completer.operation.valueOrCancellation().whenComplete(() {
|
||||||
cachedStream.removeListener(listener);
|
cachedStream.removeListener(listener);
|
||||||
cachedOperation = null;
|
|
||||||
});
|
});
|
||||||
cachedOperation = completer.operation;
|
cachedOperation = completer.operation;
|
||||||
return null;
|
return null;
|
||||||
@@ -106,18 +105,33 @@ mixin CancellableImageProviderMixin<T extends Object> on CancellableImageProvide
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Stream<ImageInfo> initialImageStream() async* {
|
Stream<ImageInfo> initialImageStream({required bool isFinal}) async* {
|
||||||
final cachedOperation = this.cachedOperation;
|
final cachedOperation = this.cachedOperation;
|
||||||
|
if (isCancelled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (cachedOperation == null) {
|
if (cachedOperation == null) {
|
||||||
|
// image resolved synchronously
|
||||||
|
isFinished = isFinal;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final cachedImage = await cachedOperation.valueOrCancellation();
|
final cachedImage = await cachedOperation.valueOrCancellation();
|
||||||
if (cachedImage != null && !isCancelled) {
|
if (isCancelled || cachedImage == null) {
|
||||||
yield cachedImage;
|
return;
|
||||||
}
|
}
|
||||||
|
isFinished = isFinal;
|
||||||
|
yield cachedImage;
|
||||||
} catch (e, stack) {
|
} catch (e, stack) {
|
||||||
|
if (isCancelled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (isFinal) {
|
||||||
|
isFinished = true;
|
||||||
|
PaintingBinding.instance.imageCache.evict(this);
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
_log.severe('Error loading initial image', e, stack);
|
_log.severe('Error loading initial image', e, stack);
|
||||||
} finally {
|
} finally {
|
||||||
this.cachedOperation = null;
|
this.cachedOperation = null;
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||||
import 'package:immich_mobile/domain/models/store.model.dart';
|
import 'package:immich_mobile/domain/models/setting.model.dart';
|
||||||
import 'package:immich_mobile/entities/store.entity.dart';
|
import 'package:immich_mobile/domain/services/setting.service.dart';
|
||||||
import 'package:immich_mobile/infrastructure/loaders/image_request.dart';
|
import 'package:immich_mobile/infrastructure/loaders/image_request.dart';
|
||||||
import 'package:immich_mobile/presentation/widgets/images/animated_image_stream_completer.dart';
|
import 'package:immich_mobile/presentation/widgets/images/animated_image_stream_completer.dart';
|
||||||
import 'package:immich_mobile/presentation/widgets/images/image_provider.dart';
|
import 'package:immich_mobile/presentation/widgets/images/image_provider.dart';
|
||||||
@@ -97,51 +97,55 @@ class LocalFullImageProvider extends CancellableImageProvider<LocalFullImageProv
|
|||||||
}
|
}
|
||||||
|
|
||||||
Stream<ImageInfo> _codec(LocalFullImageProvider key, ImageDecoderCallback decode) async* {
|
Stream<ImageInfo> _codec(LocalFullImageProvider key, ImageDecoderCallback decode) async* {
|
||||||
yield* initialImageStream();
|
final loadOriginal = AppSetting.get(Setting.loadOriginal);
|
||||||
|
final loadPreview = AppSetting.get(Setting.loadPreview);
|
||||||
|
yield* initialImageStream(isFinal: !loadOriginal && !loadPreview);
|
||||||
|
|
||||||
if (isCancelled) {
|
if (isCancelled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final loadOriginal = Store.get(StoreKey.loadOriginal, false);
|
if (loadPreview) {
|
||||||
final devicePixelRatio = PlatformDispatcher.instance.views.first.devicePixelRatio;
|
final devicePixelRatio = PlatformDispatcher.instance.views.first.devicePixelRatio;
|
||||||
var request = this.request = LocalImageRequest(
|
final previewRequest = request = LocalImageRequest(
|
||||||
localId: key.id,
|
localId: key.id,
|
||||||
size: Size(size.width * devicePixelRatio, size.height * devicePixelRatio),
|
size: Size(size.width * devicePixelRatio, size.height * devicePixelRatio),
|
||||||
assetType: key.assetType,
|
assetType: key.assetType,
|
||||||
);
|
);
|
||||||
yield* loadRequest(request, decode, isFinal: !loadOriginal);
|
yield* loadRequest(previewRequest, decode, isFinal: !loadOriginal);
|
||||||
|
|
||||||
|
if (isCancelled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!loadOriginal) {
|
if (!loadOriginal) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isCancelled) {
|
final originalRequest = request = LocalImageRequest(localId: key.id, assetType: key.assetType, size: Size.zero);
|
||||||
return;
|
yield* loadRequest(originalRequest, decode, isFinal: true);
|
||||||
}
|
|
||||||
|
|
||||||
request = this.request = LocalImageRequest(localId: key.id, assetType: key.assetType, size: Size.zero);
|
|
||||||
|
|
||||||
yield* loadRequest(request, decode, isFinal: true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Stream<Object> _animatedCodec(LocalFullImageProvider key, ImageDecoderCallback decode) async* {
|
Stream<Object> _animatedCodec(LocalFullImageProvider key, ImageDecoderCallback decode) async* {
|
||||||
yield* initialImageStream();
|
yield* initialImageStream(isFinal: false);
|
||||||
|
|
||||||
if (isCancelled) {
|
if (isCancelled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final devicePixelRatio = PlatformDispatcher.instance.views.first.devicePixelRatio;
|
if (AppSetting.get(Setting.loadPreview)) {
|
||||||
final previewRequest = request = LocalImageRequest(
|
final devicePixelRatio = PlatformDispatcher.instance.views.first.devicePixelRatio;
|
||||||
localId: key.id,
|
final previewRequest = request = LocalImageRequest(
|
||||||
size: Size(size.width * devicePixelRatio, size.height * devicePixelRatio),
|
localId: key.id,
|
||||||
assetType: key.assetType,
|
size: Size(size.width * devicePixelRatio, size.height * devicePixelRatio),
|
||||||
);
|
assetType: key.assetType,
|
||||||
yield* loadRequest(previewRequest, decode, isFinal: false);
|
);
|
||||||
|
yield* loadRequest(previewRequest, decode, isFinal: false);
|
||||||
|
|
||||||
if (isCancelled) {
|
if (isCancelled) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// always try original for animated, since previews don't support animation
|
// always try original for animated, since previews don't support animation
|
||||||
|
|||||||
@@ -107,31 +107,35 @@ class RemoteFullImageProvider extends CancellableImageProvider<RemoteFullImagePr
|
|||||||
}
|
}
|
||||||
|
|
||||||
Stream<ImageInfo> _codec(RemoteFullImageProvider key, ImageDecoderCallback decode) async* {
|
Stream<ImageInfo> _codec(RemoteFullImageProvider key, ImageDecoderCallback decode) async* {
|
||||||
yield* initialImageStream();
|
final isImage = assetType == AssetType.image;
|
||||||
|
final loadOriginal = isImage && AppSetting.get(Setting.loadOriginal);
|
||||||
|
final loadPreview = isImage && AppSetting.get(Setting.loadPreview);
|
||||||
|
yield* initialImageStream(isFinal: !loadOriginal && !loadPreview);
|
||||||
|
|
||||||
if (isCancelled) {
|
if (isCancelled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final previewRequest = request = RemoteImageRequest(
|
if (loadPreview) {
|
||||||
uri: getThumbnailUrlForRemoteId(
|
final previewRequest = request = RemoteImageRequest(
|
||||||
key.assetId,
|
uri: getThumbnailUrlForRemoteId(
|
||||||
type: AssetMediaSize.preview,
|
key.assetId,
|
||||||
thumbhash: key.thumbhash,
|
type: AssetMediaSize.preview,
|
||||||
edited: key.edited,
|
thumbhash: key.thumbhash,
|
||||||
),
|
edited: key.edited,
|
||||||
);
|
),
|
||||||
final loadOriginal = assetType == AssetType.image && AppSetting.get(Setting.loadOriginal);
|
);
|
||||||
yield* loadRequest(previewRequest, decode, isFinal: !loadOriginal);
|
yield* loadRequest(previewRequest, decode, isFinal: !loadOriginal);
|
||||||
|
|
||||||
|
if (isCancelled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!loadOriginal) {
|
if (!loadOriginal) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isCancelled) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final originalRequest = request = RemoteImageRequest(
|
final originalRequest = request = RemoteImageRequest(
|
||||||
uri: getOriginalUrlForRemoteId(key.assetId, edited: key.edited),
|
uri: getOriginalUrlForRemoteId(key.assetId, edited: key.edited),
|
||||||
);
|
);
|
||||||
@@ -139,24 +143,26 @@ class RemoteFullImageProvider extends CancellableImageProvider<RemoteFullImagePr
|
|||||||
}
|
}
|
||||||
|
|
||||||
Stream<Object> _animatedCodec(RemoteFullImageProvider key, ImageDecoderCallback decode) async* {
|
Stream<Object> _animatedCodec(RemoteFullImageProvider key, ImageDecoderCallback decode) async* {
|
||||||
yield* initialImageStream();
|
yield* initialImageStream(isFinal: false);
|
||||||
|
|
||||||
if (isCancelled) {
|
if (isCancelled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final previewRequest = request = RemoteImageRequest(
|
if (AppSetting.get(Setting.loadPreview)) {
|
||||||
uri: getThumbnailUrlForRemoteId(
|
final previewRequest = request = RemoteImageRequest(
|
||||||
key.assetId,
|
uri: getThumbnailUrlForRemoteId(
|
||||||
type: AssetMediaSize.preview,
|
key.assetId,
|
||||||
thumbhash: key.thumbhash,
|
type: AssetMediaSize.preview,
|
||||||
edited: key.edited,
|
thumbhash: key.thumbhash,
|
||||||
),
|
edited: key.edited,
|
||||||
);
|
),
|
||||||
yield* loadRequest(previewRequest, decode, isFinal: false);
|
);
|
||||||
|
yield* loadRequest(previewRequest, decode, isFinal: false);
|
||||||
|
|
||||||
if (isCancelled) {
|
if (isCancelled) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// always try original for animated, since previews don't support animation
|
// always try original for animated, since previews don't support animation
|
||||||
|
|||||||
Reference in New Issue
Block a user