animation

This commit is contained in:
Alex 2025-07-08 14:56:01 -05:00
parent 596a3bd689
commit 382ce8c8f6
No known key found for this signature in database
GPG Key ID: 53CD082B3A5E1082
2 changed files with 38 additions and 62 deletions

View File

@ -186,6 +186,9 @@ class TimelineService {
Future<void> preCacheAssets(int index) => Future<void> preCacheAssets(int index) =>
_mutex.run(() => _loadAssets(index, 5)); _mutex.run(() => _loadAssets(index, 5));
BaseAsset getRandomAsset() =>
_buffer.elementAt(math.Random().nextInt(_buffer.length));
BaseAsset getAsset(int index) { BaseAsset getAsset(int index) {
if (!hasRange(index, 1)) { if (!hasRange(index, 1)) {
throw RangeError('TimelineService::getAsset Index out of range'); throw RangeError('TimelineService::getAsset Index out of range');

View File

@ -5,6 +5,7 @@ import 'package:immich_mobile/domain/services/timeline.service.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/extensions/translate_extensions.dart'; import 'package:immich_mobile/extensions/translate_extensions.dart';
import 'package:immich_mobile/presentation/widgets/images/image_provider.dart'; import 'package:immich_mobile/presentation/widgets/images/image_provider.dart';
import 'package:immich_mobile/presentation/widgets/images/thumb_hash_provider.dart';
import 'package:immich_mobile/providers/infrastructure/timeline.provider.dart'; import 'package:immich_mobile/providers/infrastructure/timeline.provider.dart';
import 'package:immich_mobile/providers/timeline/multiselect.provider.dart'; import 'package:immich_mobile/providers/timeline/multiselect.provider.dart';
@ -221,12 +222,12 @@ class _RandomAssetBackgroundState extends State<_RandomAssetBackground>
super.initState(); super.initState();
_zoomController = AnimationController( _zoomController = AnimationController(
duration: const Duration(seconds: 12), duration: const Duration(seconds: 10),
vsync: this, vsync: this,
); );
_fadeController = AnimationController( _fadeController = AnimationController(
duration: const Duration(milliseconds: 500), duration: const Duration(milliseconds: 600),
vsync: this, vsync: this,
); );
@ -294,18 +295,8 @@ class _RandomAssetBackgroundState extends State<_RandomAssetBackground>
return; return;
} }
final randomIndex = (widget.timelineService.totalAssets > 1)
? DateTime.now().millisecond % widget.timelineService.totalAssets
: 0;
final assets = widget.timelineService.getAssets(randomIndex, 1);
if (assets.isEmpty) {
return;
}
setState(() { setState(() {
_currentAsset = assets.first; _currentAsset = widget.timelineService.getRandomAsset();
}); });
await _fadeController.forward(); await _fadeController.forward();
@ -321,29 +312,19 @@ class _RandomAssetBackgroundState extends State<_RandomAssetBackground>
try { try {
if (widget.timelineService.totalAssets > 1) { if (widget.timelineService.totalAssets > 1) {
final randomIndex = setState(() {
DateTime.now().millisecond % widget.timelineService.totalAssets; _nextAsset = widget.timelineService.getRandomAsset();
final assets = widget.timelineService.getAssets(randomIndex, 1); });
if (assets.isNotEmpty && mounted) {
setState(() {
_nextAsset = assets.first;
});
await _fadeController.reverse(); await _fadeController.reverse();
if (mounted) { setState(() {
setState(() { _currentAsset = _nextAsset;
_currentAsset = _nextAsset; _nextAsset = null;
_nextAsset = null; });
});
_zoomController.reset();
await _fadeController.forward();
_startZoomCycle();
}
}
} else {
_zoomController.reset(); _zoomController.reset();
await _fadeController.forward();
_startZoomCycle(); _startZoomCycle();
} }
} catch (e) { } catch (e) {
@ -369,37 +350,29 @@ class _RandomAssetBackgroundState extends State<_RandomAssetBackground>
animation: animation:
Listenable.merge([_zoomAnimation, _panAnimation, _fadeAnimation]), Listenable.merge([_zoomAnimation, _panAnimation, _fadeAnimation]),
builder: (context, child) { builder: (context, child) {
return Transform.translate( return Transform.scale(
offset: Offset( scale: _zoomAnimation.value,
_panAnimation.value.dx * 100, child: FadeTransition(
_panAnimation.value.dy * 100, opacity: _fadeAnimation,
), child: SizedBox(
child: Transform.scale( width: double.infinity,
scale: _zoomAnimation.value, height: double.infinity,
child: FadeTransition( child: Image(
opacity: _fadeAnimation, alignment: Alignment.topRight,
child: SizedBox( image: getFullImageProvider(_currentAsset!),
width: double.infinity, fit: BoxFit.cover,
height: double.infinity, frameBuilder: (context, child, frame, wasSynchronouslyLoaded) {
child: Image( if (wasSynchronouslyLoaded || frame != null) {
image: getFullImageProvider(_currentAsset!), return child;
fit: BoxFit.cover, }
frameBuilder:
(context, child, frame, wasSynchronouslyLoaded) {
if (wasSynchronouslyLoaded || frame != null) {
return child;
}
return Container( return Container();
decoration: BoxDecoration(gradient: gradient), },
); errorBuilder: (context, error, stackTrace) {
}, return Container(
errorBuilder: (context, error, stackTrace) { decoration: BoxDecoration(gradient: gradient),
return Container( );
decoration: BoxDecoration(gradient: gradient), },
);
},
),
), ),
), ),
), ),