diff --git a/lib/widgets/common/identity/empty.dart b/lib/widgets/common/identity/empty.dart index 580d3444d..ccefa90f7 100644 --- a/lib/widgets/common/identity/empty.dart +++ b/lib/widgets/common/identity/empty.dart @@ -1,5 +1,8 @@ +import 'package:aves/theme/durations.dart'; import 'package:aves/widgets/common/extensions/media_query.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/scheduler.dart'; +import 'package:flutter_staggered_animations/flutter_staggered_animations.dart'; import 'package:provider/provider.dart'; class EmptyContent extends StatelessWidget { @@ -23,6 +26,7 @@ class EmptyContent extends StatelessWidget { @override Widget build(BuildContext context) { final color = Theme.of(context).colorScheme.primary.withOpacity(.5); + final durations = context.watch(); return Padding( padding: safeBottom ? EdgeInsets.only( @@ -33,26 +37,36 @@ class EmptyContent extends StatelessWidget { alignment: alignment, child: Column( mainAxisSize: MainAxisSize.min, - children: [ - if (icon != null) ...[ - Icon( - icon, - size: 64, - color: color, + children: AnimationConfiguration.toStaggeredList( + duration: durations.staggeredAnimation, + delay: durations.staggeredAnimationDelay * timeDilation, + childAnimationBuilder: (child) => SlideAnimation( + verticalOffset: 50.0, + child: FadeInAnimation( + child: child, ), - const SizedBox(height: 16) - ], - if (text.isNotEmpty) - Text( - text, - style: TextStyle( + ), + children: [ + if (icon != null) ...[ + Icon( + icon, + size: 64, color: color, - fontSize: fontSize, ), - textAlign: TextAlign.center, - ), - if (bottom != null) bottom!, - ], + const SizedBox(height: 16) + ], + if (text.isNotEmpty) + Text( + text, + style: TextStyle( + color: color, + fontSize: fontSize, + ), + textAlign: TextAlign.center, + ), + if (bottom != null) bottom!, + ], + ), ), ), ); diff --git a/lib/widgets/explorer/explorer_page.dart b/lib/widgets/explorer/explorer_page.dart index 0b784b0bd..1527d518b 100644 --- a/lib/widgets/explorer/explorer_page.dart +++ b/lib/widgets/explorer/explorer_page.dart @@ -32,6 +32,7 @@ import 'package:collection/collection.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart'; +import 'package:flutter_staggered_animations/flutter_staggered_animations.dart'; import 'package:provider/provider.dart'; class ExplorerPage extends StatefulWidget { @@ -95,33 +96,45 @@ class _ExplorerPageState extends State { children: [ Expanded( child: ValueListenableBuilder>( - valueListenable: _contents, - builder: (context, contents, child) { - if (contents.isEmpty) { - final source = context.read(); - final album = _getAlbumPath(source, Directory(_currentDirectoryPath)); - return Center( - child: EmptyContent( - icon: AIcons.folder, - text: '', - bottom: album != null - ? AvesFilterChip( - filter: AlbumFilter(album, source.getAlbumDisplayName(context, album)), - maxWidth: double.infinity, - onTap: (filter) => _goToCollectionPage(context, filter), - onLongPress: null, - ) - : null, - ), - ); - } - return ListView.builder( - itemCount: contents.length, - itemBuilder: (context, index) { - return index < contents.length ? _buildContentLine(context, contents[index]) : const SizedBox(); - }, + valueListenable: _contents, + builder: (context, contents, child) { + if (contents.isEmpty) { + final source = context.read(); + final album = _getAlbumPath(source, Directory(_currentDirectoryPath)); + return Center( + child: EmptyContent( + icon: AIcons.folder, + text: '', + bottom: album != null + ? AvesFilterChip( + filter: AlbumFilter(album, source.getAlbumDisplayName(context, album)), + maxWidth: double.infinity, + onTap: (filter) => _goToCollectionPage(context, filter), + onLongPress: null, + ) + : null, + ), ); - }), + } + final durations = context.watch(); + return AnimationLimiter( + key: ValueKey(_currentDirectoryPath), + child: ListView( + children: AnimationConfiguration.toStaggeredList( + duration: durations.staggeredAnimation, + delay: durations.staggeredAnimationDelay * timeDilation, + childAnimationBuilder: (child) => SlideAnimation( + verticalOffset: 50.0, + child: FadeInAnimation( + child: child, + ), + ), + children: contents.map((v) => _buildContentLine(context, v)).toList(), + ), + ), + ); + }, + ), ), const Divider(height: 0), Padding(