feat(flutter): cosmetic reveal animations (Slice F)
Final slice of the per-item rendering pass. Wraps every tile widget in an AnimatedSwitcher between the skeleton placeholder and the real card. 220ms cross-fade with easeOut: tiles "settle into place" rather than hard-cutting from shimmer to content. Since each tile fades independently as its data lands — and the HydrationQueue's concurrency cap drains in a natural cascade — the overall feel is the staged "page builds piece by piece" effect we wanted, with no per-tile position math required. Bumps CachedNetworkImage fadeInDuration from zero to 120ms (server_ image.dart, discover_screen.dart). Imperceptible on cache hits since the image decodes synchronously; on cache misses the bytes fade in smoothly instead of popping. Slice 1's "zero fade" call was right about the 500ms default being a regression, but 120ms threads the needle. Playlist detail wraps its body in the same AnimatedSwitcher so the cold-load skeleton page cross-fades into the real track list. Tiles affected: home _AlbumTile / _ArtistTile / _TrackTile + liked _LikedAlbumTile / _LikedArtistTile / _LikedTrackRow + playlist _SkeletonBody / _Body. All keyed via ValueKey so AnimatedSwitcher detects the transition. End of the per-item pass. Net behavior: cold visits paint shaped pages instantly with skeletons, content cascades in as hydration lands; warm visits paint fully from drift in the first frame.
This commit is contained in:
@@ -208,7 +208,7 @@ class _ResultTile extends StatelessWidget {
|
||||
: CachedNetworkImage(
|
||||
imageUrl: row.imageUrl,
|
||||
fit: BoxFit.cover,
|
||||
fadeInDuration: Duration.zero,
|
||||
fadeInDuration: const Duration(milliseconds: 120),
|
||||
fadeOutDuration: Duration.zero,
|
||||
errorWidget: (_, __, ___) =>
|
||||
Icon(Icons.album, color: fs.ash),
|
||||
|
||||
Reference in New Issue
Block a user