perf(mobile): remove load of thumbnails in the image provider (#17773)

Remove loading of thumbnail in the image provider

* Removed the load of the thumbnail from the local and remote image provider as they shall provide the image, not the thumbnail. The thumbnail gets provided by the thumbnail provider.
* The thumbnail provider is used as the loadingBuilder and the image provider as the imageProvider. Therefore loading the thumbnail in the image provider loads it a second time which is completely redundant, uses precious time and yields no results.

Co-authored-by: Alex <alex.tran1502@gmail.com>
This commit is contained in:
Toni 2025-04-23 15:55:51 +02:00 committed by GitHub
parent bc5875ba8d
commit 1de2eae12d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 3 additions and 39 deletions

View File

@ -53,50 +53,35 @@ class ImmichLocalImageProvider extends ImageProvider<ImmichLocalImageProvider> {
ImageDecoderCallback decode, ImageDecoderCallback decode,
StreamController<ImageChunkEvent> chunkEvents, StreamController<ImageChunkEvent> chunkEvents,
) async* { ) async* {
ui.ImmutableBuffer? buffer;
try { try {
final local = asset.local; final local = asset.local;
if (local == null) { if (local == null) {
throw StateError('Asset ${asset.fileName} has no local data'); throw StateError('Asset ${asset.fileName} has no local data');
} }
var thumbBytes = await local
.thumbnailDataWithSize(const ThumbnailSize.square(256), quality: 80);
if (thumbBytes == null) {
throw StateError("Loading thumbnail for ${asset.fileName} failed");
}
buffer = await ui.ImmutableBuffer.fromUint8List(thumbBytes);
thumbBytes = null;
yield await decode(buffer);
buffer = null;
switch (asset.type) { switch (asset.type) {
case AssetType.image: case AssetType.image:
final File? file = await local.originFile; final File? file = await local.originFile;
if (file == null) { if (file == null) {
throw StateError("Opening file for asset ${asset.fileName} failed"); throw StateError("Opening file for asset ${asset.fileName} failed");
} }
buffer = await ui.ImmutableBuffer.fromFilePath(file.path); final buffer = await ui.ImmutableBuffer.fromFilePath(file.path);
yield await decode(buffer); yield await decode(buffer);
buffer = null;
break; break;
case AssetType.video: case AssetType.video:
final size = ThumbnailSize(width.ceil(), height.ceil()); final size = ThumbnailSize(width.ceil(), height.ceil());
thumbBytes = await local.thumbnailDataWithSize(size); final thumbBytes = await local.thumbnailDataWithSize(size);
if (thumbBytes == null) { if (thumbBytes == null) {
throw StateError("Failed to load preview for ${asset.fileName}"); throw StateError("Failed to load preview for ${asset.fileName}");
} }
buffer = await ui.ImmutableBuffer.fromUint8List(thumbBytes); final buffer = await ui.ImmutableBuffer.fromUint8List(thumbBytes);
thumbBytes = null;
yield await decode(buffer); yield await decode(buffer);
buffer = null;
break; break;
default: default:
throw StateError('Unsupported asset type ${asset.type}'); throw StateError('Unsupported asset type ${asset.type}');
} }
} catch (error, stack) { } catch (error, stack) {
log.severe('Error loading local image ${asset.fileName}', error, stack); log.severe('Error loading local image ${asset.fileName}', error, stack);
buffer?.dispose();
} finally { } finally {
chunkEvents.close(); chunkEvents.close();
} }

View File

@ -57,12 +57,6 @@ class ImmichRemoteImageProvider
AppSettingsEnum.loadOriginal.defaultValue, AppSettingsEnum.loadOriginal.defaultValue,
); );
/// Whether to load the preview thumbnail first or not
bool get _loadPreview => Store.get(
AppSettingsEnum.loadPreview.storeKey,
AppSettingsEnum.loadPreview.defaultValue,
);
// Streams in each stage of the image as we ask for it // Streams in each stage of the image as we ask for it
Stream<ui.Codec> _codec( Stream<ui.Codec> _codec(
ImmichRemoteImageProvider key, ImmichRemoteImageProvider key,
@ -70,21 +64,6 @@ class ImmichRemoteImageProvider
ImageDecoderCallback decode, ImageDecoderCallback decode,
StreamController<ImageChunkEvent> chunkEvents, StreamController<ImageChunkEvent> chunkEvents,
) async* { ) async* {
// Load a preview to the chunk events
if (_loadPreview) {
final preview = getThumbnailUrlForRemoteId(
key.assetId,
type: api.AssetMediaSize.thumbnail,
);
yield await ImageLoader.loadImageFromCache(
preview,
cache: cache,
decode: decode,
chunkEvents: chunkEvents,
);
}
// Load the higher resolution version of the image // Load the higher resolution version of the image
final url = getThumbnailUrlForRemoteId( final url = getThumbnailUrlForRemoteId(
key.assetId, key.assetId,