feat(mobile): platform image providers (#20927)

* platform image providers

* use key

* fix cache manager

* more logs, cancel on dispose instead

* split into separate files

* fix saving to cache

* cancel multi-stage provider

* refactored `getInitialImage`

* only wait for disposal for full images

* cached image works

* formatting

* lower asset viewer ram usage

---------

Co-authored-by: Alex <alex.tran1502@gmail.com>
This commit is contained in:
Mert 2025-08-20 15:36:44 -04:00 committed by GitHub
parent 9ff37b6870
commit 99d6673503
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 669 additions and 306 deletions

View file

@ -1,14 +1,14 @@
import 'dart:convert' hide Codec;
import 'dart:ui';
import 'package:flutter/foundation.dart';
import 'package:flutter/rendering.dart';
import 'package:thumbhash/thumbhash.dart';
import 'package:immich_mobile/infrastructure/loaders/image_request.dart';
import 'package:immich_mobile/presentation/widgets/images/image_provider.dart';
import 'package:immich_mobile/presentation/widgets/images/one_frame_multi_image_stream_completer.dart';
class ThumbHashProvider extends ImageProvider<ThumbHashProvider> {
class ThumbHashProvider extends CancellableImageProvider<ThumbHashProvider>
with CancellableImageProviderMixin<ThumbHashProvider> {
final String thumbHash;
const ThumbHashProvider({required this.thumbHash});
ThumbHashProvider({required this.thumbHash});
@override
Future<ThumbHashProvider> obtainKey(ImageConfiguration configuration) {
@ -17,12 +17,11 @@ class ThumbHashProvider extends ImageProvider<ThumbHashProvider> {
@override
ImageStreamCompleter loadImage(ThumbHashProvider key, ImageDecoderCallback decode) {
return MultiFrameImageStreamCompleter(codec: _loadCodec(key, decode), scale: 1.0);
return OneFramePlaceholderImageStreamCompleter(_loadCodec(key, decode))..addOnLastListenerRemovedCallback(cancel);
}
Future<Codec> _loadCodec(ThumbHashProvider key, ImageDecoderCallback decode) async {
final image = thumbHashToRGBA(base64Decode(key.thumbHash));
return decode(await ImmutableBuffer.fromUint8List(rgbaToBmp(image)));
Stream<ImageInfo> _loadCodec(ThumbHashProvider key, ImageDecoderCallback decode) {
return loadRequest(ThumbhashImageRequest(thumbhash: key.thumbHash), decode);
}
@override