diff --git a/lib/widgets/media_card.dart b/lib/widgets/media_card.dart index 15fb6741..bbaa5525 100644 --- a/lib/widgets/media_card.dart +++ b/lib/widgets/media_card.dart @@ -650,6 +650,15 @@ class _MediaCardList extends StatelessWidget { } } +Widget _buildPosterLoadingPlaceholder(BuildContext context, String _) { + return ColoredBox(color: Theme.of(context).colorScheme.surfaceContainerHighest, child: const SizedBox.expand()); +} + +IconData _mediaPosterFallbackIcon(MediaItem item) { + if (item.isShow || item.isSeason || item.isEpisode) return Symbols.tv_rounded; + return Symbols.movie_rounded; +} + Widget _buildPosterImage( BuildContext context, Object item, { @@ -660,11 +669,9 @@ Widget _buildPosterImage( double? knownHeight, }) { String? posterUrl; - IconData fallbackIcon = Symbols.movie_rounded; if (item is MediaPlaylist) { posterUrl = item.displayImagePath; - fallbackIcon = Symbols.playlist_play_rounded; return OptimizedMediaImage.playlist( client: isOffline ? null : context.tryGetMediaClientWithFallback(item.serverId), @@ -672,6 +679,7 @@ Widget _buildPosterImage( width: knownWidth ?? double.infinity, height: knownHeight ?? double.infinity, fit: BoxFit.cover, + placeholder: _buildPosterLoadingPlaceholder, localFilePath: localPosterPath, ); } else if (item is MediaItem) { @@ -684,6 +692,7 @@ Widget _buildPosterImage( final useRememberedFallback = posterFallbackUrl != null && _hasFailedPosterUrl(primaryPosterUrl); posterUrl = useRememberedFallback ? posterFallbackUrl : primaryPosterUrl; final mediaClient = isOffline ? null : context.tryGetMediaClientWithFallback(item.serverId); + final fallbackIcon = _mediaPosterFallbackIcon(item); Widget image; @@ -695,6 +704,8 @@ Widget _buildPosterImage( width: knownWidth ?? double.infinity, height: knownHeight ?? double.infinity, fit: BoxFit.cover, + placeholder: _buildPosterLoadingPlaceholder, + fallbackIcon: fallbackIcon, localFilePath: localPosterPath, ); } else { @@ -704,6 +715,8 @@ Widget _buildPosterImage( width: knownWidth ?? double.infinity, height: knownHeight ?? double.infinity, fit: BoxFit.cover, + placeholder: _buildPosterLoadingPlaceholder, + fallbackIcon: fallbackIcon, errorWidget: posterFallbackUrl == null || useRememberedFallback ? null : (_, _, _) { @@ -714,6 +727,8 @@ Widget _buildPosterImage( width: knownWidth ?? double.infinity, height: knownHeight ?? double.infinity, fit: BoxFit.cover, + placeholder: _buildPosterLoadingPlaceholder, + fallbackIcon: fallbackIcon, ); }, localFilePath: localPosterPath, @@ -729,7 +744,7 @@ Widget _buildPosterImage( } return SkeletonLoader( - child: Center(child: AppIcon(fallbackIcon, fill: 1, size: 40, color: Colors.white54)), + child: const Center(child: AppIcon(Symbols.movie_rounded, fill: 1, size: 40, color: Colors.white54)), ); } diff --git a/lib/widgets/optimized_media_image.dart b/lib/widgets/optimized_media_image.dart index 5477f18c..88e52ca0 100644 --- a/lib/widgets/optimized_media_image.dart +++ b/lib/widgets/optimized_media_image.dart @@ -101,6 +101,7 @@ class OptimizedMediaImage extends StatelessWidget { bool enableTranscoding = true, String? cacheKey, Alignment alignment = Alignment.center, + IconData? fallbackIcon, String? localFilePath, }) : this._( key: key, @@ -116,7 +117,7 @@ class OptimizedMediaImage extends StatelessWidget { enableTranscoding: enableTranscoding, cacheKey: cacheKey, alignment: alignment, - fallbackIcon: Symbols.movie_rounded, + fallbackIcon: fallbackIcon ?? Symbols.movie_rounded, imageType: ImageType.poster, localFilePath: localFilePath, ); @@ -136,6 +137,7 @@ class OptimizedMediaImage extends StatelessWidget { bool enableTranscoding = true, String? cacheKey, Alignment alignment = Alignment.center, + IconData? fallbackIcon, String? localFilePath, }) : this._( key: key, @@ -151,7 +153,7 @@ class OptimizedMediaImage extends StatelessWidget { enableTranscoding: enableTranscoding, cacheKey: cacheKey, alignment: alignment, - fallbackIcon: Symbols.video_library_rounded, + fallbackIcon: fallbackIcon ?? Symbols.video_library_rounded, imageType: ImageType.thumb, localFilePath: localFilePath, ); @@ -328,7 +330,7 @@ class OptimizedMediaImage extends StatelessWidget { if (wasSynchronouslyLoaded) return child; return AnimatedSwitcher( duration: const Duration(milliseconds: 300), - child: frame != null ? child : _buildPlaceholder(context), + child: frame != null ? child : _buildPlaceholder(context, imageUrl), ); }, ); @@ -346,8 +348,10 @@ class OptimizedMediaImage extends StatelessWidget { ); } - Widget _buildPlaceholder(BuildContext context) => - _surfacePlaceholder(context, icon: fallbackIcon, iconColor: Colors.white54); + Widget _buildPlaceholder(BuildContext context, String imageUrl) { + if (placeholder != null) return placeholder!(context, imageUrl); + return _surfacePlaceholder(context, icon: fallbackIcon, iconColor: Colors.white54); + } Widget _buildErrorWidget(BuildContext context, dynamic _) => _surfacePlaceholder(context, icon: fallbackIcon ?? Symbols.broken_image_rounded, fillParent: true);