diff --git a/lib/constants/music_services.dart b/lib/constants/music_services.dart new file mode 100644 index 00000000..4851c397 --- /dev/null +++ b/lib/constants/music_services.dart @@ -0,0 +1,15 @@ +/// Canonical service / provider identifiers shared across the app. +/// +/// These values must stay in sync with the provider ids reported by the Go +/// backend and by extensions; use them instead of raw string literals when +/// comparing or dispatching on a service id. +abstract final class MusicServices { + static const spotify = 'spotify'; + static const deezer = 'deezer'; + static const tidal = 'tidal'; + static const qobuz = 'qobuz'; + static const amazon = 'amazon'; + + /// Pseudo-service for tracks that only exist in the local library. + static const local = 'local'; +} diff --git a/lib/screens/settings/lyrics_provider_priority_page.dart b/lib/screens/settings/lyrics_provider_priority_page.dart index f91ad0f4..2137b004 100644 --- a/lib/screens/settings/lyrics_provider_priority_page.dart +++ b/lib/screens/settings/lyrics_provider_priority_page.dart @@ -4,6 +4,7 @@ import 'package:spotiflac_android/l10n/l10n.dart'; import 'package:spotiflac_android/providers/settings_provider.dart'; import 'package:spotiflac_android/widgets/priority_settings_scaffold.dart'; import 'package:spotiflac_android/widgets/settings_group.dart'; +import 'package:spotiflac_android/constants/music_services.dart'; class LyricsProviderPriorityPage extends ConsumerStatefulWidget { const LyricsProviderPriorityPage({super.key}); @@ -215,13 +216,13 @@ class _LyricsProviderPriorityPageState description: context.l10n.lyricsProviderQqMusicDesc, icon: Icons.queue_music, ); - case 'spotify': + case MusicServices.spotify: return _LyricsProviderInfo( name: 'Spotify', description: context.l10n.lyricsProviderExtensionDesc, icon: Icons.graphic_eq, ); - case 'deezer': + case MusicServices.deezer: return _LyricsProviderInfo( name: 'Deezer', description: context.l10n.lyricsProviderExtensionDesc, diff --git a/lib/screens/track_metadata_actions.dart b/lib/screens/track_metadata_actions.dart index bff11828..71a9ac77 100644 --- a/lib/screens/track_metadata_actions.dart +++ b/lib/screens/track_metadata_actions.dart @@ -272,11 +272,11 @@ extension _TrackMetadataFileActions on _TrackMetadataScreenState { IconData _getServiceIcon(String service) { switch (service.toLowerCase()) { - case 'tidal': + case MusicServices.tidal: return Icons.waves; - case 'qobuz': + case MusicServices.qobuz: return Icons.album; - case 'amazon': + case MusicServices.amazon: return Icons.shopping_cart; default: return Icons.cloud_download; @@ -285,11 +285,11 @@ extension _TrackMetadataFileActions on _TrackMetadataScreenState { Color _getServiceColor(String service, ColorScheme colorScheme) { switch (service.toLowerCase()) { - case 'tidal': + case MusicServices.tidal: return const Color(0xFF0077B5); - case 'qobuz': + case MusicServices.qobuz: return const Color(0xFF0052CC); - case 'amazon': + case MusicServices.amazon: return const Color(0xFFFF9900); default: return colorScheme.primary; diff --git a/lib/screens/track_metadata_cards.dart b/lib/screens/track_metadata_cards.dart index 5d3cfbb0..11898e54 100644 --- a/lib/screens/track_metadata_cards.dart +++ b/lib/screens/track_metadata_cards.dart @@ -368,15 +368,15 @@ extension _TrackMetadataCards on _TrackMetadataScreenState { fallbackService: _service.toLowerCase(), ); String buttonLabel; - if (openService == 'deezer') { + if (openService == MusicServices.deezer) { buttonLabel = context.l10n.trackOpenInDeezer; - } else if (openService == 'amazon') { + } else if (openService == MusicServices.amazon) { buttonLabel = context.l10n.trackOpenInService( 'Amazon Music', ); - } else if (openService == 'tidal') { + } else if (openService == MusicServices.tidal) { buttonLabel = context.l10n.trackOpenInService('Tidal'); - } else if (openService == 'qobuz') { + } else if (openService == MusicServices.qobuz) { buttonLabel = context.l10n.trackOpenInService('Qobuz'); } else { buttonLabel = context.l10n.trackOpenInSpotify; @@ -417,19 +417,19 @@ extension _TrackMetadataCards on _TrackMetadataScreenState { Uri? appUri; String serviceName; - if (openService == 'deezer') { + if (openService == MusicServices.deezer) { webUrl = 'https://www.deezer.com/track/$rawId'; appUri = Uri.parse('deezer://www.deezer.com/track/$rawId'); serviceName = 'Deezer'; - } else if (openService == 'amazon') { + } else if (openService == MusicServices.amazon) { webUrl = 'https://music.amazon.com/search/$rawId'; appUri = Uri.parse('amznm://search/$rawId'); serviceName = 'Amazon Music'; - } else if (openService == 'tidal') { + } else if (openService == MusicServices.tidal) { webUrl = 'https://listen.tidal.com/track/$rawId'; appUri = Uri.parse('tidal://track/$rawId'); serviceName = 'Tidal'; - } else if (openService == 'qobuz') { + } else if (openService == MusicServices.qobuz) { webUrl = 'https://play.qobuz.com/track/$rawId'; appUri = Uri.parse('qobuz://track/$rawId'); serviceName = 'Qobuz'; @@ -518,13 +518,13 @@ extension _TrackMetadataCards on _TrackMetadataScreenState { final cleanId = _displayServiceTrackId(_spotifyId!); String idLabel; switch (idService) { - case 'deezer': + case MusicServices.deezer: idLabel = 'Deezer ID'; - case 'amazon': + case MusicServices.amazon: idLabel = 'Amazon ASIN'; - case 'tidal': + case MusicServices.tidal: idLabel = 'Tidal ID'; - case 'qobuz': + case MusicServices.qobuz: idLabel = 'Qobuz ID'; default: idLabel = 'Spotify ID'; diff --git a/lib/screens/track_metadata_screen.dart b/lib/screens/track_metadata_screen.dart index b60490c3..185db9e1 100644 --- a/lib/screens/track_metadata_screen.dart +++ b/lib/screens/track_metadata_screen.dart @@ -30,6 +30,7 @@ import 'package:spotiflac_android/utils/nav_bar_inset.dart'; import 'package:spotiflac_android/widgets/audio_analysis_widget.dart'; import 'package:spotiflac_android/widgets/cached_cover_image.dart'; import 'package:spotiflac_android/widgets/settings_group.dart'; +import 'package:spotiflac_android/constants/music_services.dart'; part 'track_metadata_edit_sheet.dart'; part 'track_metadata_cards.dart'; @@ -787,7 +788,7 @@ class _TrackMetadataScreenState extends ConsumerState { String? get _localCoverPath => _isLocalItem ? _localLibraryItem!.coverPath : null; String? get _spotifyId => _isLocalItem ? null : _downloadItem!.spotifyId; - String get _service => _isLocalItem ? 'local' : _downloadItem!.service; + String get _service => _isLocalItem ? MusicServices.local : _downloadItem!.service; DateTime get _addedAt { if (_isLocalItem) { final modTime = _localLibraryItem!.fileModTime; @@ -915,19 +916,19 @@ class _TrackMetadataScreenState extends ConsumerState { if (raw.isEmpty) return fallbackService; final spotifyTrackIdPattern = RegExp(r'^[A-Za-z0-9]{22}$'); - if (raw.startsWith('deezer:')) return 'deezer'; - if (raw.startsWith('tidal:')) return 'tidal'; - if (raw.startsWith('qobuz:')) return 'qobuz'; - if (raw.startsWith('spotify:')) return 'spotify'; - if (spotifyTrackIdPattern.hasMatch(raw)) return 'spotify'; + if (raw.startsWith('deezer:')) return MusicServices.deezer; + if (raw.startsWith('tidal:')) return MusicServices.tidal; + if (raw.startsWith('qobuz:')) return MusicServices.qobuz; + if (raw.startsWith('spotify:')) return MusicServices.spotify; + if (spotifyTrackIdPattern.hasMatch(raw)) return MusicServices.spotify; final uri = Uri.tryParse(raw); if (uri != null) { final host = uri.host.toLowerCase(); - if (host.contains('spotify.com')) return 'spotify'; - if (host.contains('deezer.com')) return 'deezer'; - if (host.contains('tidal.com')) return 'tidal'; - if (host.contains('qobuz.com')) return 'qobuz'; + if (host.contains('spotify.com')) return MusicServices.spotify; + if (host.contains('deezer.com')) return MusicServices.deezer; + if (host.contains('tidal.com')) return MusicServices.tidal; + if (host.contains('qobuz.com')) return MusicServices.qobuz; } return fallbackService; diff --git a/lib/utils/provider_resource_ids.dart b/lib/utils/provider_resource_ids.dart index 546d6b87..6644afc8 100644 --- a/lib/utils/provider_resource_ids.dart +++ b/lib/utils/provider_resource_ids.dart @@ -1,10 +1,12 @@ +import 'package:spotiflac_android/constants/music_services.dart'; + /// Maps a legacy prefixed resource id (e.g. "deezer:123") to its provider id, /// or null when the value carries no known provider prefix. String? legacyProviderIdFromResourceId(String value) { - if (value.startsWith('deezer:')) return 'deezer'; - if (value.startsWith('qobuz:')) return 'qobuz'; - if (value.startsWith('tidal:')) return 'tidal'; - if (value.startsWith('spotify:')) return 'spotify'; + if (value.startsWith('deezer:')) return MusicServices.deezer; + if (value.startsWith('qobuz:')) return MusicServices.qobuz; + if (value.startsWith('tidal:')) return MusicServices.tidal; + if (value.startsWith('spotify:')) return MusicServices.spotify; return null; }