diff --git a/lib/providers/download_queue_provider.dart b/lib/providers/download_queue_provider.dart index 9ea4c7e..b7a9684 100644 --- a/lib/providers/download_queue_provider.dart +++ b/lib/providers/download_queue_provider.dart @@ -2811,8 +2811,8 @@ class DownloadQueueNotifier extends Notifier { 'artist': track.artistName, 'album': track.albumName, 'album_artist': resolvedAlbumArtist, - 'track_number': track.trackNumber ?? 1, - 'disc_number': track.discNumber ?? 1, + 'track_number': track.trackNumber ?? 0, + 'disc_number': track.discNumber ?? 0, 'isrc': track.isrc ?? '', 'release_date': track.releaseDate ?? '', 'duration_ms': track.duration * 1000, @@ -4649,12 +4649,12 @@ class DownloadQueueNotifier extends Notifier { (trackToDownload.trackNumber != null && trackToDownload.trackNumber! > 0) ? trackToDownload.trackNumber! - : 1; + : 0; final normalizedDiscNumber = (trackToDownload.discNumber != null && trackToDownload.discNumber! > 0) ? trackToDownload.discNumber! - : 1; + : 0; String payloadSpotifyId = trackToDownload.id; String payloadQobuzId = ''; diff --git a/lib/providers/explore_provider.dart b/lib/providers/explore_provider.dart index f55892f..37c2ef2 100644 --- a/lib/providers/explore_provider.dart +++ b/lib/providers/explore_provider.dart @@ -19,6 +19,7 @@ class ExploreItem { final String? providerId; final String? albumId; final String? albumName; + final String? releaseDate; final int durationMs; const ExploreItem({ @@ -32,6 +33,7 @@ class ExploreItem { this.providerId, this.albumId, this.albumName, + this.releaseDate, this.durationMs = 0, }); @@ -47,6 +49,7 @@ class ExploreItem { providerId: json['provider_id'] as String?, albumId: json['album_id'] as String?, albumName: json['album_name'] as String?, + releaseDate: json['release_date']?.toString(), durationMs: json['duration_ms'] as int? ?? 0, ); } @@ -62,6 +65,7 @@ class ExploreItem { 'provider_id': providerId, 'album_id': albumId, 'album_name': albumName, + 'release_date': releaseDate, 'duration_ms': durationMs, }; } diff --git a/lib/screens/home_tab.dart b/lib/screens/home_tab.dart index a9219ad..d810513 100644 --- a/lib/screens/home_tab.dart +++ b/lib/screens/home_tab.dart @@ -1845,10 +1845,10 @@ class _HomeTabState extends ConsumerState albumName: item.albumName ?? '', albumId: item.albumId, duration: item.durationMs ~/ 1000, - trackNumber: 1, - discNumber: 1, + trackNumber: null, + discNumber: null, isrc: null, - releaseDate: null, + releaseDate: item.releaseDate, coverUrl: item.coverUrl, source: item.providerId ?? 'spotify-web', ); @@ -4272,6 +4272,8 @@ class _ExtensionAlbumScreenState extends ConsumerState { isrc: data['isrc']?.toString(), duration: (durationMs / 1000).round(), trackNumber: data['track_number'] as int?, + discNumber: data['disc_number'] as int?, + releaseDate: data['release_date']?.toString(), source: widget.extensionId, ); } @@ -4429,6 +4431,8 @@ class _ExtensionPlaylistScreenState isrc: data['isrc']?.toString(), duration: (durationMs / 1000).round(), trackNumber: data['track_number'] as int?, + discNumber: data['disc_number'] as int?, + releaseDate: data['release_date']?.toString(), source: widget.extensionId, ); } diff --git a/lib/screens/track_metadata_screen.dart b/lib/screens/track_metadata_screen.dart index f9e5a75..3f6b9aa 100644 --- a/lib/screens/track_metadata_screen.dart +++ b/lib/screens/track_metadata_screen.dart @@ -552,6 +552,36 @@ class _TrackMetadataScreenState extends ConsumerState { return parsed; } + String _displayServiceTrackId(String value) { + final raw = value.trim(); + if (raw.isEmpty) return raw; + final spotifyTrackIdPattern = RegExp(r'^[A-Za-z0-9]{22}$'); + + if (raw.startsWith('deezer:')) return raw.substring('deezer:'.length); + if (raw.startsWith('tidal:')) return raw.substring('tidal:'.length); + if (raw.startsWith('qobuz:')) return raw.substring('qobuz:'.length); + if (spotifyTrackIdPattern.hasMatch(raw)) return raw; + + if (raw.startsWith('spotify:')) { + final last = raw.split(':').last.trim(); + if (spotifyTrackIdPattern.hasMatch(last)) return last; + return raw; + } + + final uri = Uri.tryParse(raw); + if (uri != null && + uri.host.contains('spotify.com') && + uri.pathSegments.length >= 2 && + uri.pathSegments.first == 'track') { + final candidate = uri.pathSegments[1].trim(); + if (spotifyTrackIdPattern.hasMatch(candidate)) { + return candidate; + } + } + + return raw; + } + String? get _displayAudioQuality { final fileName = _extractFileNameFromPathOrUri(cleanFilePath); final fileExt = fileName.contains('.') @@ -1102,8 +1132,9 @@ class _TrackMetadataScreenState extends ConsumerState { Future _openServiceUrl(BuildContext context) async { if (_spotifyId == null) return; - final isDeezer = _spotifyId!.contains('deezer'); - final rawId = _spotifyId!.replaceAll('deezer:', ''); + final isDeezer = + _service.toLowerCase() == 'deezer' || _spotifyId!.startsWith('deezer:'); + final rawId = _displayServiceTrackId(_spotifyId!); final svc = _service.toLowerCase(); String webUrl; @@ -1192,8 +1223,9 @@ class _TrackMetadataScreenState extends ConsumerState { ]; if (!_isLocalItem && _spotifyId != null && _spotifyId!.isNotEmpty) { - final isDeezer = _spotifyId!.contains('deezer'); - final cleanId = _spotifyId!.replaceAll('deezer:', ''); + final isDeezer = + _service.toLowerCase() == 'deezer' || _spotifyId!.startsWith('deezer:'); + final cleanId = _displayServiceTrackId(_spotifyId!); String idLabel; if (isDeezer) { idLabel = 'Deezer ID'; diff --git a/lib/services/download_request_payload.dart b/lib/services/download_request_payload.dart index 29f4237..fc0e25f 100644 --- a/lib/services/download_request_payload.dart +++ b/lib/services/download_request_payload.dart @@ -53,8 +53,8 @@ class DownloadRequestPayload { this.artistTagMode = 'joined', this.embedLyrics = true, this.embedMaxQualityCover = true, - this.trackNumber = 1, - this.discNumber = 1, + this.trackNumber = 0, + this.discNumber = 0, this.totalTracks = 1, this.releaseDate = '', this.itemId = '',