transition

This commit is contained in:
mertalev 2025-07-24 14:23:16 +03:00
parent b13bd8df98
commit 05e5d98d71
No known key found for this signature in database
GPG Key ID: DF6ABC77AAD98C95

View File

@ -4,6 +4,7 @@ import 'dart:ui' as ui;
import 'dart:ui'; import 'dart:ui';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:immich_mobile/constants/constants.dart'; import 'package:immich_mobile/constants/constants.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/entities/asset.entity.dart'; import 'package:immich_mobile/entities/asset.entity.dart';
@ -269,8 +270,14 @@ class _ThumbnailLeaf extends LeafRenderObjectWidget {
class _ThumbnailRenderBox extends RenderBox { class _ThumbnailRenderBox extends RenderBox {
ui.Image? _image; ui.Image? _image;
ui.Image? _previousImage;
BoxFit _fit; BoxFit _fit;
Gradient _placeholderGradient; Gradient _placeholderGradient;
DateTime _lastImageRequest;
double _crossFadeProgress = 1.0;
static const _fadeDuration = Duration(milliseconds: 100);
DateTime? _fadeStartTime;
@override @override
bool isRepaintBoundary = true; bool isRepaintBoundary = true;
@ -281,26 +288,56 @@ class _ThumbnailRenderBox extends RenderBox {
required Gradient placeholderGradient, required Gradient placeholderGradient,
}) : _image = image, }) : _image = image,
_fit = fit, _fit = fit,
_placeholderGradient = placeholderGradient; _placeholderGradient = placeholderGradient,
_lastImageRequest = DateTime.now();
@override @override
void paint(PaintingContext context, Offset offset) { void paint(PaintingContext context, Offset offset) {
final image = _image;
final rect = offset & size; final rect = offset & size;
if (image == null) { final canvas = context.canvas;
final paint = Paint();
paint.shader = _placeholderGradient.createShader(rect); if (_fadeStartTime != null) {
context.canvas.drawRect(rect, paint); final elapsed = DateTime.now().difference(_fadeStartTime!);
return; _crossFadeProgress =
(elapsed.inMilliseconds / _fadeDuration.inMilliseconds)
.clamp(0.0, 1.0);
if (_crossFadeProgress < 1.0) {
SchedulerBinding.instance.scheduleFrameCallback((_) {
markNeedsPaint();
});
} else {
// _previousImage?.dispose();
_previousImage = null;
_fadeStartTime = null;
}
} }
paintImage( if (_previousImage != null && _crossFadeProgress < 1.0) {
canvas: context.canvas, paintImage(
rect: rect, canvas: canvas,
image: image, rect: rect,
fit: _fit, image: _previousImage!,
filterQuality: FilterQuality.low, fit: _fit,
); filterQuality: FilterQuality.low,
opacity: 1.0 - _crossFadeProgress,
);
} else if (_image == null) {
final paint = Paint();
paint.shader = _placeholderGradient.createShader(rect);
canvas.drawRect(rect, paint);
}
if (_image != null) {
paintImage(
canvas: canvas,
rect: rect,
image: _image!,
fit: _fit,
filterQuality: FilterQuality.low,
opacity: _crossFadeProgress,
);
}
} }
@override @override
@ -309,10 +346,18 @@ class _ThumbnailRenderBox extends RenderBox {
} }
set image(ui.Image? value) { set image(ui.Image? value) {
if (_image != value) { if (_image == value) {
_image = value; return;
markNeedsPaint();
} }
final time = DateTime.now();
if (time.difference(_lastImageRequest).inMilliseconds >= 16) {
_fadeStartTime = DateTime.now();
_previousImage = _image;
}
_image = value;
_lastImageRequest = time;
markNeedsPaint();
} }
set fit(BoxFit value) { set fit(BoxFit value) {