refactor: use extension method for image to url string

This commit is contained in:
Kingkor Roy Tirtho 2024-03-21 00:18:43 +06:00
parent 6673e5a8a8
commit 7545ff6415
27 changed files with 99 additions and 90 deletions

View File

@ -4,6 +4,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:spotify/spotify.dart'; import 'package:spotify/spotify.dart';
import 'package:spotube/components/shared/playbutton_card.dart'; import 'package:spotube/components/shared/playbutton_card.dart';
import 'package:spotube/extensions/context.dart'; import 'package:spotube/extensions/context.dart';
import 'package:spotube/extensions/image.dart';
import 'package:spotube/provider/proxy_playlist/proxy_playlist_provider.dart'; import 'package:spotube/provider/proxy_playlist/proxy_playlist_provider.dart';
import 'package:spotube/provider/spotify/spotify.dart'; import 'package:spotube/provider/spotify/spotify.dart';
import 'package:spotube/services/audio_player/audio_player.dart'; import 'package:spotube/services/audio_player/audio_player.dart';
@ -49,8 +50,7 @@ class AlbumCard extends HookConsumerWidget {
} }
return PlaybuttonCard( return PlaybuttonCard(
imageUrl: TypeConversionUtils.image_X_UrlString( imageUrl: album.images.asUrlString(
album.images,
placeholder: ImagePlaceholder.collection, placeholder: ImagePlaceholder.collection,
), ),
margin: const EdgeInsets.symmetric(horizontal: 10), margin: const EdgeInsets.symmetric(horizontal: 10),

View File

@ -6,6 +6,7 @@ import 'package:skeletonizer/skeletonizer.dart';
import 'package:spotify/spotify.dart'; import 'package:spotify/spotify.dart';
import 'package:spotube/components/shared/image/universal_image.dart'; import 'package:spotube/components/shared/image/universal_image.dart';
import 'package:spotube/extensions/context.dart'; import 'package:spotube/extensions/context.dart';
import 'package:spotube/extensions/image.dart';
import 'package:spotube/hooks/utils/use_breakpoint_value.dart'; import 'package:spotube/hooks/utils/use_breakpoint_value.dart';
import 'package:spotube/hooks/utils/use_brightness_value.dart'; import 'package:spotube/hooks/utils/use_brightness_value.dart';
import 'package:spotube/provider/blacklist_provider.dart'; import 'package:spotube/provider/blacklist_provider.dart';
@ -20,8 +21,7 @@ class ArtistCard extends HookConsumerWidget {
Widget build(BuildContext context, ref) { Widget build(BuildContext context, ref) {
final theme = Theme.of(context); final theme = Theme.of(context);
final backgroundImage = UniversalImage.imageProvider( final backgroundImage = UniversalImage.imageProvider(
TypeConversionUtils.image_X_UrlString( artist.images.asUrlString(
artist.images,
placeholder: ImagePlaceholder.artist, placeholder: ImagePlaceholder.artist,
), ),
); );

View File

@ -4,6 +4,7 @@ import 'package:spotify/spotify.dart';
import 'package:spotube/collections/spotube_icons.dart'; import 'package:spotube/collections/spotube_icons.dart';
import 'package:spotube/components/shared/image/universal_image.dart'; import 'package:spotube/components/shared/image/universal_image.dart';
import 'package:spotube/extensions/image.dart';
import 'package:spotube/utils/type_conversion_utils.dart'; import 'package:spotube/utils/type_conversion_utils.dart';
class SimpleTrackTile extends HookWidget { class SimpleTrackTile extends HookWidget {
@ -21,8 +22,7 @@ class SimpleTrackTile extends HookWidget {
leading: ClipRRect( leading: ClipRRect(
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
child: UniversalImage( child: UniversalImage(
path: TypeConversionUtils.image_X_UrlString( path: (track.album?.images).asUrlString(
track.album?.images,
placeholder: ImagePlaceholder.artist, placeholder: ImagePlaceholder.artist,
), ),
height: 40, height: 40,

View File

@ -5,6 +5,7 @@ import 'package:spotify/spotify.dart';
import 'package:spotube/collections/spotube_icons.dart'; import 'package:spotube/collections/spotube_icons.dart';
import 'package:spotube/components/shared/image/universal_image.dart'; import 'package:spotube/components/shared/image/universal_image.dart';
import 'package:spotube/extensions/context.dart'; import 'package:spotube/extensions/context.dart';
import 'package:spotube/extensions/image.dart';
import 'package:spotube/provider/download_manager_provider.dart'; import 'package:spotube/provider/download_manager_provider.dart';
import 'package:spotube/services/download_manager/download_status.dart'; import 'package:spotube/services/download_manager/download_status.dart';
import 'package:spotube/services/sourced_track/sourced_track.dart'; import 'package:spotube/services/sourced_track/sourced_track.dart';
@ -51,8 +52,7 @@ class DownloadItem extends HookConsumerWidget {
child: UniversalImage( child: UniversalImage(
height: 40, height: 40,
width: 40, width: 40,
path: TypeConversionUtils.image_X_UrlString( path: (track.album?.images).asUrlString(
track.album?.images,
placeholder: ImagePlaceholder.albumArt, placeholder: ImagePlaceholder.albumArt,
), ),
), ),

View File

@ -18,6 +18,7 @@ import 'package:spotube/components/shared/image/universal_image.dart';
import 'package:spotube/components/shared/panels/sliding_up_panel.dart'; import 'package:spotube/components/shared/panels/sliding_up_panel.dart';
import 'package:spotube/extensions/constrains.dart'; import 'package:spotube/extensions/constrains.dart';
import 'package:spotube/extensions/context.dart'; import 'package:spotube/extensions/context.dart';
import 'package:spotube/extensions/image.dart';
import 'package:spotube/hooks/utils/use_custom_status_bar_color.dart'; import 'package:spotube/hooks/utils/use_custom_status_bar_color.dart';
import 'package:spotube/hooks/utils/use_palette_color.dart'; import 'package:spotube/hooks/utils/use_palette_color.dart';
import 'package:spotube/models/local_track.dart'; import 'package:spotube/models/local_track.dart';
@ -59,8 +60,7 @@ class PlayerView extends HookConsumerWidget {
}, [mediaQuery.lgAndUp]); }, [mediaQuery.lgAndUp]);
String albumArt = useMemoized( String albumArt = useMemoized(
() => TypeConversionUtils.image_X_UrlString( () => (currentTrack?.album?.images).asUrlString(
currentTrack?.album?.images,
placeholder: ImagePlaceholder.albumArt, placeholder: ImagePlaceholder.albumArt,
), ),
[currentTrack?.album?.images], [currentTrack?.album?.images],

View File

@ -3,6 +3,7 @@ import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:spotify/spotify.dart'; import 'package:spotify/spotify.dart';
import 'package:spotube/components/shared/playbutton_card.dart'; import 'package:spotube/components/shared/playbutton_card.dart';
import 'package:spotube/extensions/image.dart';
import 'package:spotube/provider/proxy_playlist/proxy_playlist_provider.dart'; import 'package:spotube/provider/proxy_playlist/proxy_playlist_provider.dart';
import 'package:spotube/provider/spotify/spotify.dart'; import 'package:spotube/provider/spotify/spotify.dart';
import 'package:spotube/services/audio_player/audio_player.dart'; import 'package:spotube/services/audio_player/audio_player.dart';
@ -43,8 +44,7 @@ class PlaylistCard extends HookConsumerWidget {
margin: const EdgeInsets.symmetric(horizontal: 10), margin: const EdgeInsets.symmetric(horizontal: 10),
title: playlist.name!, title: playlist.name!,
description: playlist.description, description: playlist.description,
imageUrl: TypeConversionUtils.image_X_UrlString( imageUrl: playlist.images.asUrlString(
playlist.images,
placeholder: ImagePlaceholder.collection, placeholder: ImagePlaceholder.collection,
), ),
isPlaying: isPlaylistPlaying, isPlaying: isPlaylistPlaying,

View File

@ -14,6 +14,7 @@ import 'package:spotube/collections/spotube_icons.dart';
import 'package:spotube/components/shared/image/universal_image.dart'; import 'package:spotube/components/shared/image/universal_image.dart';
import 'package:spotube/extensions/constrains.dart'; import 'package:spotube/extensions/constrains.dart';
import 'package:spotube/extensions/context.dart'; import 'package:spotube/extensions/context.dart';
import 'package:spotube/extensions/image.dart';
import 'package:spotube/provider/spotify/spotify.dart'; import 'package:spotube/provider/spotify/spotify.dart';
import 'package:spotube/provider/spotify_provider.dart'; import 'package:spotube/provider/spotify_provider.dart';
import 'package:spotube/utils/type_conversion_utils.dart'; import 'package:spotube/utils/type_conversion_utils.dart';
@ -163,8 +164,7 @@ class PlaylistCreateDialog extends HookConsumerWidget {
children: [ children: [
UniversalImage( UniversalImage(
path: field.value?.path ?? path: field.value?.path ??
TypeConversionUtils.image_X_UrlString( (updatingPlaylist?.images).asUrlString(
updatingPlaylist?.images,
placeholder: ImagePlaceholder.collection, placeholder: ImagePlaceholder.collection,
), ),
height: 200, height: 200,

View File

@ -14,6 +14,7 @@ import 'package:spotube/components/player/player_controls.dart';
import 'package:spotube/components/player/volume_slider.dart'; import 'package:spotube/components/player/volume_slider.dart';
import 'package:spotube/extensions/constrains.dart'; import 'package:spotube/extensions/constrains.dart';
import 'package:spotube/extensions/context.dart'; import 'package:spotube/extensions/context.dart';
import 'package:spotube/extensions/image.dart';
import 'package:spotube/hooks/utils/use_brightness_value.dart'; import 'package:spotube/hooks/utils/use_brightness_value.dart';
import 'package:spotube/models/logger.dart'; import 'package:spotube/models/logger.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@ -39,8 +40,7 @@ class BottomPlayer extends HookConsumerWidget {
String albumArt = useMemoized( String albumArt = useMemoized(
() => playlist.activeTrack?.album?.images?.isNotEmpty == true () => playlist.activeTrack?.album?.images?.isNotEmpty == true
? TypeConversionUtils.image_X_UrlString( ? (playlist.activeTrack?.album?.images).asUrlString(
playlist.activeTrack?.album?.images,
index: (playlist.activeTrack?.album?.images?.length ?? 1) - 1, index: (playlist.activeTrack?.album?.images?.length ?? 1) - 1,
placeholder: ImagePlaceholder.albumArt, placeholder: ImagePlaceholder.albumArt,
) )

View File

@ -11,6 +11,7 @@ import 'package:spotube/collections/spotube_icons.dart';
import 'package:spotube/components/shared/image/universal_image.dart'; import 'package:spotube/components/shared/image/universal_image.dart';
import 'package:spotube/extensions/constrains.dart'; import 'package:spotube/extensions/constrains.dart';
import 'package:spotube/extensions/context.dart'; import 'package:spotube/extensions/context.dart';
import 'package:spotube/extensions/image.dart';
import 'package:spotube/hooks/utils/use_brightness_value.dart'; import 'package:spotube/hooks/utils/use_brightness_value.dart';
import 'package:spotube/hooks/controllers/use_sidebarx_controller.dart'; import 'package:spotube/hooks/controllers/use_sidebarx_controller.dart';
import 'package:spotube/provider/download_manager_provider.dart'; import 'package:spotube/provider/download_manager_provider.dart';
@ -244,8 +245,7 @@ class SidebarFooter extends HookConsumerWidget {
final me = ref.watch(meProvider); final me = ref.watch(meProvider);
final data = me.asData?.value; final data = me.asData?.value;
final avatarImg = TypeConversionUtils.image_X_UrlString( final avatarImg = (data?.images).asUrlString(
data?.images,
index: (data?.images?.length ?? 1) - 1, index: (data?.images?.length ?? 1) - 1,
placeholder: ImagePlaceholder.artist, placeholder: ImagePlaceholder.artist,
); );

View File

@ -7,6 +7,7 @@ import 'package:spotify/spotify.dart';
import 'package:spotube/components/playlist/playlist_create_dialog.dart'; import 'package:spotube/components/playlist/playlist_create_dialog.dart';
import 'package:spotube/components/shared/image/universal_image.dart'; import 'package:spotube/components/shared/image/universal_image.dart';
import 'package:spotube/extensions/context.dart'; import 'package:spotube/extensions/context.dart';
import 'package:spotube/extensions/image.dart';
import 'package:spotube/provider/spotify/spotify.dart'; import 'package:spotube/provider/spotify/spotify.dart';
import 'package:spotube/utils/type_conversion_utils.dart'; import 'package:spotube/utils/type_conversion_utils.dart';
@ -105,8 +106,7 @@ class PlaylistAddTrackDialog extends HookConsumerWidget {
return CheckboxListTile( return CheckboxListTile(
secondary: CircleAvatar( secondary: CircleAvatar(
backgroundImage: UniversalImage.imageProvider( backgroundImage: UniversalImage.imageProvider(
TypeConversionUtils.image_X_UrlString( playlist.images.asUrlString(
playlist.images,
placeholder: ImagePlaceholder.collection, placeholder: ImagePlaceholder.collection,
), ),
), ),

View File

@ -17,6 +17,7 @@ import 'package:spotube/components/shared/heart_button.dart';
import 'package:spotube/components/shared/image/universal_image.dart'; import 'package:spotube/components/shared/image/universal_image.dart';
import 'package:spotube/extensions/constrains.dart'; import 'package:spotube/extensions/constrains.dart';
import 'package:spotube/extensions/context.dart'; import 'package:spotube/extensions/context.dart';
import 'package:spotube/extensions/image.dart';
import 'package:spotube/models/local_track.dart'; import 'package:spotube/models/local_track.dart';
import 'package:spotube/provider/authentication_provider.dart'; import 'package:spotube/provider/authentication_provider.dart';
import 'package:spotube/provider/blacklist_provider.dart'; import 'package:spotube/provider/blacklist_provider.dart';
@ -294,8 +295,8 @@ class TrackOptions extends HookConsumerWidget {
child: ClipRRect( child: ClipRRect(
borderRadius: BorderRadius.circular(10), borderRadius: BorderRadius.circular(10),
child: UniversalImage( child: UniversalImage(
path: TypeConversionUtils.image_X_UrlString(track.album!.images, path: track.album!.images
placeholder: ImagePlaceholder.albumArt), .asUrlString(placeholder: ImagePlaceholder.albumArt),
fit: BoxFit.cover, fit: BoxFit.cover,
), ),
), ),

View File

@ -13,6 +13,7 @@ import 'package:spotube/components/shared/links/link_text.dart';
import 'package:spotube/components/shared/track_tile/track_options.dart'; import 'package:spotube/components/shared/track_tile/track_options.dart';
import 'package:spotube/extensions/constrains.dart'; import 'package:spotube/extensions/constrains.dart';
import 'package:spotube/extensions/duration.dart'; import 'package:spotube/extensions/duration.dart';
import 'package:spotube/extensions/image.dart';
import 'package:spotube/models/local_track.dart'; import 'package:spotube/models/local_track.dart';
import 'package:spotube/provider/blacklist_provider.dart'; import 'package:spotube/provider/blacklist_provider.dart';
import 'package:spotube/provider/proxy_playlist/proxy_playlist_provider.dart'; import 'package:spotube/provider/proxy_playlist/proxy_playlist_provider.dart';
@ -135,8 +136,7 @@ class TrackTile extends HookConsumerWidget {
child: AspectRatio( child: AspectRatio(
aspectRatio: 1, aspectRatio: 1,
child: UniversalImage( child: UniversalImage(
path: TypeConversionUtils.image_X_UrlString( path: (track.album?.images).asUrlString(
track.album?.images,
placeholder: ImagePlaceholder.albumArt, placeholder: ImagePlaceholder.albumArt,
), ),
fit: BoxFit.cover, fit: BoxFit.cover,

28
lib/extensions/image.dart Normal file
View File

@ -0,0 +1,28 @@
import 'package:spotify/spotify.dart';
import 'package:spotube/collections/assets.gen.dart';
import 'package:spotube/utils/primitive_utils.dart';
import 'package:spotube/utils/type_conversion_utils.dart';
import 'package:collection/collection.dart';
extension SpotifyImageExtensions on List<Image>? {
String asUrlString({
int index = 1,
required ImagePlaceholder placeholder,
}) {
final String placeholderUrl = {
ImagePlaceholder.albumArt: Assets.albumPlaceholder.path,
ImagePlaceholder.artist: Assets.userPlaceholder.path,
ImagePlaceholder.collection: Assets.placeholder.path,
ImagePlaceholder.online:
"https://avatars.dicebear.com/api/bottts/${PrimitiveUtils.uuid.v4()}.png",
}[placeholder]!;
final sortedImage = this?.sorted((a, b) => a.width!.compareTo(b.width!));
return sortedImage != null && sortedImage.isNotEmpty
? sortedImage[
index > sortedImage.length - 1 ? sortedImage.length - 1 : index]
.url!
: placeholderUrl;
}
}

View File

@ -25,11 +25,11 @@ void useGetStoragePermissions(WidgetRef ref) {
if (hasNoStoragePerm) { if (hasNoStoragePerm) {
await Permission.storage.request(); await Permission.storage.request();
if (isMounted()) ref.refresh(localTracksProvider); if (isMounted()) ref.invalidate(localTracksProvider);
} }
if (hasNoAudioPerm) { if (hasNoAudioPerm) {
await Permission.audio.request(); await Permission.audio.request();
if (isMounted()) ref.refresh(localTracksProvider); if (isMounted()) ref.invalidate(localTracksProvider);
} }
}, },
null, null,

View File

@ -4,6 +4,7 @@ import 'package:spotify/spotify.dart';
import 'package:spotube/components/shared/tracks_view/track_view.dart'; import 'package:spotube/components/shared/tracks_view/track_view.dart';
import 'package:spotube/components/shared/tracks_view/track_view_props.dart'; import 'package:spotube/components/shared/tracks_view/track_view_props.dart';
import 'package:spotube/extensions/context.dart'; import 'package:spotube/extensions/context.dart';
import 'package:spotube/extensions/image.dart';
import 'package:spotube/provider/spotify/spotify.dart'; import 'package:spotube/provider/spotify/spotify.dart';
import 'package:spotube/utils/type_conversion_utils.dart'; import 'package:spotube/utils/type_conversion_utils.dart';
@ -23,8 +24,7 @@ class AlbumPage extends HookConsumerWidget {
return InheritedTrackView( return InheritedTrackView(
collectionId: album.id!, collectionId: album.id!,
image: TypeConversionUtils.image_X_UrlString( image: album.images.asUrlString(
album.images,
placeholder: ImagePlaceholder.albumArt, placeholder: ImagePlaceholder.albumArt,
), ),
title: album.name!, title: album.name!,

View File

@ -5,6 +5,7 @@ import 'package:spotify/spotify.dart';
import 'package:spotube/collections/spotube_icons.dart'; import 'package:spotube/collections/spotube_icons.dart';
import 'package:spotube/components/shared/image/universal_image.dart'; import 'package:spotube/components/shared/image/universal_image.dart';
import 'package:spotube/extensions/constrains.dart'; import 'package:spotube/extensions/constrains.dart';
import 'package:spotube/extensions/image.dart';
import 'package:spotube/provider/spotify/spotify.dart'; import 'package:spotube/provider/spotify/spotify.dart';
import 'package:spotube/utils/type_conversion_utils.dart'; import 'package:spotube/utils/type_conversion_utils.dart';
import 'package:url_launcher/url_launcher_string.dart'; import 'package:url_launcher/url_launcher_string.dart';
@ -18,8 +19,7 @@ class ArtistPageFooter extends ConsumerWidget {
final ThemeData(:textTheme) = Theme.of(context); final ThemeData(:textTheme) = Theme.of(context);
final mediaQuery = MediaQuery.of(context); final mediaQuery = MediaQuery.of(context);
final artistImage = TypeConversionUtils.image_X_UrlString( final artistImage = artist.images.asUrlString(
artist.images,
placeholder: ImagePlaceholder.artist, placeholder: ImagePlaceholder.artist,
); );
final summary = ref.watch(artistWikipediaSummaryProvider(artist)); final summary = ref.watch(artistWikipediaSummaryProvider(artist));

View File

@ -8,6 +8,7 @@ import 'package:spotube/collections/spotube_icons.dart';
import 'package:spotube/components/shared/image/universal_image.dart'; import 'package:spotube/components/shared/image/universal_image.dart';
import 'package:spotube/extensions/constrains.dart'; import 'package:spotube/extensions/constrains.dart';
import 'package:spotube/extensions/context.dart'; import 'package:spotube/extensions/context.dart';
import 'package:spotube/extensions/image.dart';
import 'package:spotube/hooks/utils/use_breakpoint_value.dart'; import 'package:spotube/hooks/utils/use_breakpoint_value.dart';
import 'package:spotube/provider/authentication_provider.dart'; import 'package:spotube/provider/authentication_provider.dart';
import 'package:spotube/provider/blacklist_provider.dart'; import 'package:spotube/provider/blacklist_provider.dart';
@ -44,8 +45,7 @@ class ArtistPageHeader extends HookConsumerWidget {
BlacklistedElement.artist(artistId, artist.name!), BlacklistedElement.artist(artistId, artist.name!),
); );
final image = TypeConversionUtils.image_X_UrlString( final image = artist.images.asUrlString(
artist.images,
placeholder: ImagePlaceholder.artist, placeholder: ImagePlaceholder.artist,
); );

View File

@ -15,6 +15,7 @@ import 'package:spotube/components/shared/image/universal_image.dart';
import 'package:spotube/components/shared/page_window_title_bar.dart'; import 'package:spotube/components/shared/page_window_title_bar.dart';
import 'package:spotube/extensions/constrains.dart'; import 'package:spotube/extensions/constrains.dart';
import 'package:spotube/extensions/context.dart'; import 'package:spotube/extensions/context.dart';
import 'package:spotube/extensions/image.dart';
import 'package:spotube/models/spotify/recommendation_seeds.dart'; import 'package:spotube/models/spotify/recommendation_seeds.dart';
import 'package:spotube/provider/spotify/spotify.dart'; import 'package:spotube/provider/spotify/spotify.dart';
import 'package:spotube/provider/spotify_provider.dart'; import 'package:spotube/provider/spotify_provider.dart';
@ -84,8 +85,7 @@ class PlaylistGeneratorPage extends HookConsumerWidget {
autocompleteOptionBuilder: (option, onSelected) => ListTile( autocompleteOptionBuilder: (option, onSelected) => ListTile(
leading: CircleAvatar( leading: CircleAvatar(
backgroundImage: UniversalImage.imageProvider( backgroundImage: UniversalImage.imageProvider(
TypeConversionUtils.image_X_UrlString( option.images.asUrlString(
option.images,
placeholder: ImagePlaceholder.artist, placeholder: ImagePlaceholder.artist,
), ),
), ),
@ -117,8 +117,7 @@ class PlaylistGeneratorPage extends HookConsumerWidget {
selectedSeedBuilder: (artist) => Chip( selectedSeedBuilder: (artist) => Chip(
avatar: CircleAvatar( avatar: CircleAvatar(
backgroundImage: UniversalImage.imageProvider( backgroundImage: UniversalImage.imageProvider(
TypeConversionUtils.image_X_UrlString( artist.images.asUrlString(
artist.images,
placeholder: ImagePlaceholder.artist, placeholder: ImagePlaceholder.artist,
), ),
), ),
@ -163,8 +162,7 @@ class PlaylistGeneratorPage extends HookConsumerWidget {
autocompleteOptionBuilder: (option, onSelected) => ListTile( autocompleteOptionBuilder: (option, onSelected) => ListTile(
leading: CircleAvatar( leading: CircleAvatar(
backgroundImage: UniversalImage.imageProvider( backgroundImage: UniversalImage.imageProvider(
TypeConversionUtils.image_X_UrlString( (option.album?.images).asUrlString(
option.album?.images,
placeholder: ImagePlaceholder.artist, placeholder: ImagePlaceholder.artist,
), ),
), ),

View File

@ -11,6 +11,7 @@ import 'package:spotube/components/shared/image/universal_image.dart';
import 'package:spotube/components/shared/themed_button_tab_bar.dart'; import 'package:spotube/components/shared/themed_button_tab_bar.dart';
import 'package:spotube/extensions/constrains.dart'; import 'package:spotube/extensions/constrains.dart';
import 'package:spotube/extensions/context.dart'; import 'package:spotube/extensions/context.dart';
import 'package:spotube/extensions/image.dart';
import 'package:spotube/hooks/utils/use_custom_status_bar_color.dart'; import 'package:spotube/hooks/utils/use_custom_status_bar_color.dart';
import 'package:spotube/hooks/utils/use_palette_color.dart'; import 'package:spotube/hooks/utils/use_palette_color.dart';
import 'package:spotube/pages/lyrics/plain_lyrics.dart'; import 'package:spotube/pages/lyrics/plain_lyrics.dart';
@ -28,8 +29,7 @@ class LyricsPage extends HookConsumerWidget {
Widget build(BuildContext context, ref) { Widget build(BuildContext context, ref) {
final playlist = ref.watch(ProxyPlaylistNotifier.provider); final playlist = ref.watch(ProxyPlaylistNotifier.provider);
String albumArt = useMemoized( String albumArt = useMemoized(
() => TypeConversionUtils.image_X_UrlString( () => (playlist.activeTrack?.album?.images).asUrlString(
playlist.activeTrack?.album?.images,
index: (playlist.activeTrack?.album?.images?.length ?? 1) - 1, index: (playlist.activeTrack?.album?.images?.length ?? 1) - 1,
placeholder: ImagePlaceholder.albumArt, placeholder: ImagePlaceholder.albumArt,
), ),

View File

@ -6,6 +6,7 @@ import 'package:spotube/components/shared/tracks_view/sections/body/use_is_user_
import 'package:spotube/components/shared/tracks_view/track_view.dart'; import 'package:spotube/components/shared/tracks_view/track_view.dart';
import 'package:spotube/components/shared/tracks_view/track_view_props.dart'; import 'package:spotube/components/shared/tracks_view/track_view_props.dart';
import 'package:spotube/extensions/context.dart'; import 'package:spotube/extensions/context.dart';
import 'package:spotube/extensions/image.dart';
import 'package:spotube/provider/spotify/spotify.dart'; import 'package:spotube/provider/spotify/spotify.dart';
import 'package:spotube/utils/type_conversion_utils.dart'; import 'package:spotube/utils/type_conversion_utils.dart';
@ -30,8 +31,7 @@ class PlaylistPage extends HookConsumerWidget {
return InheritedTrackView( return InheritedTrackView(
collectionId: playlist.id!, collectionId: playlist.id!,
image: TypeConversionUtils.image_X_UrlString( image: playlist.images.asUrlString(
playlist.images,
placeholder: ImagePlaceholder.collection, placeholder: ImagePlaceholder.collection,
), ),
pagination: PaginationProps( pagination: PaginationProps(

View File

@ -12,6 +12,7 @@ import 'package:spotube/components/shared/links/link_text.dart';
import 'package:spotube/components/shared/page_window_title_bar.dart'; import 'package:spotube/components/shared/page_window_title_bar.dart';
import 'package:spotube/components/shared/track_tile/track_options.dart'; import 'package:spotube/components/shared/track_tile/track_options.dart';
import 'package:spotube/extensions/context.dart'; import 'package:spotube/extensions/context.dart';
import 'package:spotube/extensions/image.dart';
import 'package:spotube/provider/proxy_playlist/proxy_playlist_provider.dart'; import 'package:spotube/provider/proxy_playlist/proxy_playlist_provider.dart';
import 'package:spotube/provider/spotify/spotify.dart'; import 'package:spotube/provider/spotify/spotify.dart';
import 'package:spotube/services/audio_player/audio_player.dart'; import 'package:spotube/services/audio_player/audio_player.dart';
@ -60,8 +61,7 @@ class TrackPage extends HookConsumerWidget {
decoration: BoxDecoration( decoration: BoxDecoration(
image: DecorationImage( image: DecorationImage(
image: UniversalImage.imageProvider( image: UniversalImage.imageProvider(
TypeConversionUtils.image_X_UrlString( track.album!.images.asUrlString(
track.album!.images,
placeholder: ImagePlaceholder.albumArt, placeholder: ImagePlaceholder.albumArt,
), ),
), ),
@ -104,8 +104,7 @@ class TrackPage extends HookConsumerWidget {
ClipRRect( ClipRRect(
borderRadius: BorderRadius.circular(10), borderRadius: BorderRadius.circular(10),
child: UniversalImage( child: UniversalImage(
path: TypeConversionUtils.image_X_UrlString( path: track.album!.images.asUrlString(
track.album!.images,
placeholder: ImagePlaceholder.albumArt, placeholder: ImagePlaceholder.albumArt,
), ),
height: 200, height: 200,

View File

@ -9,6 +9,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:metadata_god/metadata_god.dart'; import 'package:metadata_god/metadata_god.dart';
import 'package:path/path.dart'; import 'package:path/path.dart';
import 'package:spotify/spotify.dart'; import 'package:spotify/spotify.dart';
import 'package:spotube/extensions/image.dart';
import 'package:spotube/provider/user_preferences/user_preferences_provider.dart'; import 'package:spotube/provider/user_preferences/user_preferences_provider.dart';
import 'package:spotube/services/download_manager/download_manager.dart'; import 'package:spotube/services/download_manager/download_manager.dart';
import 'package:spotube/services/sourced_track/enums.dart'; import 'package:spotube/services/sourced_track/enums.dart';
@ -52,8 +53,10 @@ class DownloadManagerProvider extends ChangeNotifier {
} }
final imageBytes = await downloadImage( final imageBytes = await downloadImage(
TypeConversionUtils.image_X_UrlString(track.album?.images, (track.album?.images).asUrlString(
placeholder: ImagePlaceholder.albumArt, index: 1), placeholder: ImagePlaceholder.albumArt,
index: 1,
),
); );
final metadata = Metadata( final metadata = Metadata(

View File

@ -10,6 +10,7 @@ import 'package:http/http.dart';
import 'package:palette_generator/palette_generator.dart'; import 'package:palette_generator/palette_generator.dart';
import 'package:spotify/spotify.dart'; import 'package:spotify/spotify.dart';
import 'package:spotube/components/shared/image/universal_image.dart'; import 'package:spotube/components/shared/image/universal_image.dart';
import 'package:spotube/extensions/image.dart';
import 'package:spotube/models/local_track.dart'; import 'package:spotube/models/local_track.dart';
import 'package:spotube/models/logger.dart'; import 'package:spotube/models/logger.dart';
@ -522,8 +523,7 @@ class ProxyPlaylistNotifier extends PersistedStateNotifier<ProxyPlaylist>
final palette = await PaletteGenerator.fromImageProvider( final palette = await PaletteGenerator.fromImageProvider(
UniversalImage.imageProvider( UniversalImage.imageProvider(
TypeConversionUtils.image_X_UrlString( (state.activeTrack?.album?.images).asUrlString(
state.activeTrack?.album?.images,
placeholder: ImagePlaceholder.albumArt, placeholder: ImagePlaceholder.albumArt,
), ),
height: 50, height: 50,

View File

@ -2,6 +2,7 @@ import 'package:audio_service/audio_service.dart';
import 'package:flutter_desktop_tools/flutter_desktop_tools.dart'; import 'package:flutter_desktop_tools/flutter_desktop_tools.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:spotify/spotify.dart'; import 'package:spotify/spotify.dart';
import 'package:spotube/extensions/image.dart';
import 'package:spotube/provider/proxy_playlist/proxy_playlist_provider.dart'; import 'package:spotube/provider/proxy_playlist/proxy_playlist_provider.dart';
import 'package:spotube/services/audio_services/mobile_audio_service.dart'; import 'package:spotube/services/audio_services/mobile_audio_service.dart';
import 'package:spotube/services/audio_services/windows_audio_service.dart'; import 'package:spotube/services/audio_services/windows_audio_service.dart';
@ -50,10 +51,11 @@ class AudioServices {
duration: track is SourcedTrack duration: track is SourcedTrack
? track.sourceInfo.duration ? track.sourceInfo.duration
: Duration(milliseconds: track.durationMs ?? 0), : Duration(milliseconds: track.durationMs ?? 0),
artUri: Uri.parse(TypeConversionUtils.image_X_UrlString( artUri: Uri.parse(
track.album?.images ?? <Image>[], (track.album?.images).asUrlString(
placeholder: ImagePlaceholder.albumArt, placeholder: ImagePlaceholder.albumArt,
)), ),
),
playable: true, playable: true,
)); ));
} }

View File

@ -2,6 +2,7 @@ import 'dart:io';
import 'package:dbus/dbus.dart'; import 'package:dbus/dbus.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:spotube/extensions/image.dart';
import 'package:spotube/provider/proxy_playlist/proxy_playlist.dart'; import 'package:spotube/provider/proxy_playlist/proxy_playlist.dart';
import 'package:spotube/provider/proxy_playlist/proxy_playlist_provider.dart'; import 'package:spotube/provider/proxy_playlist/proxy_playlist_provider.dart';
@ -309,8 +310,7 @@ class _MprisMediaPlayer2Player extends DBusObject {
(await audioPlayer.duration)?.inMicroseconds ?? 0, (await audioPlayer.duration)?.inMicroseconds ?? 0,
), ),
"mpris:artUrl": DBusString( "mpris:artUrl": DBusString(
TypeConversionUtils.image_X_UrlString( (playlist.activeTrack?.album?.images).asUrlString(
playlist.activeTrack?.album?.images,
placeholder: ImagePlaceholder.albumArt, placeholder: ImagePlaceholder.albumArt,
), ),
), ),

View File

@ -3,6 +3,7 @@ import 'dart:async';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:smtc_windows/smtc_windows.dart'; import 'package:smtc_windows/smtc_windows.dart';
import 'package:spotify/spotify.dart'; import 'package:spotify/spotify.dart';
import 'package:spotube/extensions/image.dart';
import 'package:spotube/provider/proxy_playlist/proxy_playlist_provider.dart'; import 'package:spotube/provider/proxy_playlist/proxy_playlist_provider.dart';
import 'package:spotube/services/audio_player/audio_player.dart'; import 'package:spotube/services/audio_player/audio_player.dart';
import 'package:spotube/services/audio_player/playback_state.dart'; import 'package:spotube/services/audio_player/playback_state.dart';
@ -80,16 +81,18 @@ class WindowsAudioService {
if (!smtc.enabled) { if (!smtc.enabled) {
await smtc.enableSmtc(); await smtc.enableSmtc();
} }
await smtc.updateMetadata(MusicMetadata( await smtc.updateMetadata(
MusicMetadata(
title: track.name!, title: track.name!,
albumArtist: track.artists?.firstOrNull?.name ?? "Unknown", albumArtist: track.artists?.firstOrNull?.name ?? "Unknown",
artist: TypeConversionUtils.artists_X_String<Artist>(track.artists ?? []), artist:
TypeConversionUtils.artists_X_String<Artist>(track.artists ?? []),
album: track.album?.name ?? "Unknown", album: track.album?.name ?? "Unknown",
thumbnail: TypeConversionUtils.image_X_UrlString( thumbnail: (track.album?.images).asUrlString(
track.album?.images ?? [],
placeholder: ImagePlaceholder.albumArt, placeholder: ImagePlaceholder.albumArt,
), ),
)); ),
);
} }
void dispose() { void dispose() {

View File

@ -2,14 +2,11 @@
import 'dart:io'; import 'dart:io';
import 'package:collection/collection.dart';
import 'package:flutter/widgets.dart' hide Image; import 'package:flutter/widgets.dart' hide Image;
import 'package:metadata_god/metadata_god.dart'; import 'package:metadata_god/metadata_god.dart';
import 'package:path/path.dart'; import 'package:path/path.dart';
import 'package:spotube/collections/assets.gen.dart';
import 'package:spotube/components/shared/links/anchor_button.dart'; import 'package:spotube/components/shared/links/anchor_button.dart';
import 'package:spotify/spotify.dart'; import 'package:spotify/spotify.dart';
import 'package:spotube/utils/primitive_utils.dart';
import 'package:spotube/utils/service_utils.dart'; import 'package:spotube/utils/service_utils.dart';
enum ImagePlaceholder { enum ImagePlaceholder {
@ -20,28 +17,6 @@ enum ImagePlaceholder {
} }
abstract class TypeConversionUtils { abstract class TypeConversionUtils {
static String image_X_UrlString(
List<Image>? images, {
int index = 1,
required ImagePlaceholder placeholder,
}) {
final String placeholderUrl = {
ImagePlaceholder.albumArt: Assets.albumPlaceholder.path,
ImagePlaceholder.artist: Assets.userPlaceholder.path,
ImagePlaceholder.collection: Assets.placeholder.path,
ImagePlaceholder.online:
"https://avatars.dicebear.com/api/bottts/${PrimitiveUtils.uuid.v4()}.png",
}[placeholder]!;
final sortedImage = images?.sorted((a, b) => a.width!.compareTo(b.width!));
return sortedImage != null && sortedImage.isNotEmpty
? sortedImage[
index > sortedImage.length - 1 ? sortedImage.length - 1 : index]
.url!
: placeholderUrl;
}
static String artists_X_String<T extends ArtistSimple>(List<T> artists) { static String artists_X_String<T extends ArtistSimple>(List<T> artists) {
return artists.map((e) => e.name?.replaceAll(",", " ")).join(", "); return artists.map((e) => e.name?.replaceAll(",", " ")).join(", ");
} }