mirror of
https://github.com/zarzet/SpotiFLAC-Mobile.git
synced 2026-07-08 13:48:05 +02:00
feat: add extended metadata (genre, label, copyright) support
- Add genre, label, copyright fields to ExtTrackMetadata and DownloadResponse - Add utils.randomUserAgent() for extensions to get random User-Agent strings - Fix VM race condition panic by adding mutex locks to all provider methods - Fix Tidal release date fallback when req.ReleaseDate is empty - Display genre, label, copyright in track metadata screen - Store extended metadata in download history for persistence - Add trackGenre, trackLabel, trackCopyright localization strings
This commit is contained in:
@@ -1688,6 +1688,12 @@ abstract class AppLocalizations {
|
||||
/// **'Found {count} tracks in CSV. Add them to download queue?'**
|
||||
String dialogImportPlaylistMessage(int count);
|
||||
|
||||
/// Label shown in quality picker for CSV import
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'{count} tracks from CSV'**
|
||||
String csvImportTracks(int count);
|
||||
|
||||
/// Snackbar - track added to download queue
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
@@ -2870,6 +2876,24 @@ abstract class AppLocalizations {
|
||||
/// **'Release date'**
|
||||
String get trackReleaseDate;
|
||||
|
||||
/// Metadata label - music genre
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Genre'**
|
||||
String get trackGenre;
|
||||
|
||||
/// Metadata label - record label
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Label'**
|
||||
String get trackLabel;
|
||||
|
||||
/// Metadata label - copyright information
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Copyright'**
|
||||
String get trackCopyright;
|
||||
|
||||
/// Metadata label - download date
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
|
||||
@@ -910,6 +910,11 @@ class AppLocalizationsDe extends AppLocalizations {
|
||||
return 'Found $count tracks in CSV. Add them to download queue?';
|
||||
}
|
||||
|
||||
@override
|
||||
String csvImportTracks(int count) {
|
||||
return '$count tracks from CSV';
|
||||
}
|
||||
|
||||
@override
|
||||
String snackbarAddedToQueue(String trackName) {
|
||||
return 'Added \"$trackName\" to queue';
|
||||
@@ -1584,6 +1589,15 @@ class AppLocalizationsDe extends AppLocalizations {
|
||||
@override
|
||||
String get trackReleaseDate => 'Release date';
|
||||
|
||||
@override
|
||||
String get trackGenre => 'Genre';
|
||||
|
||||
@override
|
||||
String get trackLabel => 'Label';
|
||||
|
||||
@override
|
||||
String get trackCopyright => 'Copyright';
|
||||
|
||||
@override
|
||||
String get trackDownloaded => 'Downloaded';
|
||||
|
||||
|
||||
@@ -897,6 +897,11 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||
return 'Found $count tracks in CSV. Add them to download queue?';
|
||||
}
|
||||
|
||||
@override
|
||||
String csvImportTracks(int count) {
|
||||
return '$count tracks from CSV';
|
||||
}
|
||||
|
||||
@override
|
||||
String snackbarAddedToQueue(String trackName) {
|
||||
return 'Added \"$trackName\" to queue';
|
||||
@@ -1571,6 +1576,15 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||
@override
|
||||
String get trackReleaseDate => 'Release date';
|
||||
|
||||
@override
|
||||
String get trackGenre => 'Genre';
|
||||
|
||||
@override
|
||||
String get trackLabel => 'Label';
|
||||
|
||||
@override
|
||||
String get trackCopyright => 'Copyright';
|
||||
|
||||
@override
|
||||
String get trackDownloaded => 'Downloaded';
|
||||
|
||||
|
||||
@@ -897,6 +897,11 @@ class AppLocalizationsEs extends AppLocalizations {
|
||||
return 'Found $count tracks in CSV. Add them to download queue?';
|
||||
}
|
||||
|
||||
@override
|
||||
String csvImportTracks(int count) {
|
||||
return '$count tracks from CSV';
|
||||
}
|
||||
|
||||
@override
|
||||
String snackbarAddedToQueue(String trackName) {
|
||||
return 'Added \"$trackName\" to queue';
|
||||
@@ -1571,6 +1576,15 @@ class AppLocalizationsEs extends AppLocalizations {
|
||||
@override
|
||||
String get trackReleaseDate => 'Release date';
|
||||
|
||||
@override
|
||||
String get trackGenre => 'Genre';
|
||||
|
||||
@override
|
||||
String get trackLabel => 'Label';
|
||||
|
||||
@override
|
||||
String get trackCopyright => 'Copyright';
|
||||
|
||||
@override
|
||||
String get trackDownloaded => 'Downloaded';
|
||||
|
||||
|
||||
@@ -897,6 +897,11 @@ class AppLocalizationsFr extends AppLocalizations {
|
||||
return 'Found $count tracks in CSV. Add them to download queue?';
|
||||
}
|
||||
|
||||
@override
|
||||
String csvImportTracks(int count) {
|
||||
return '$count tracks from CSV';
|
||||
}
|
||||
|
||||
@override
|
||||
String snackbarAddedToQueue(String trackName) {
|
||||
return 'Added \"$trackName\" to queue';
|
||||
@@ -1571,6 +1576,15 @@ class AppLocalizationsFr extends AppLocalizations {
|
||||
@override
|
||||
String get trackReleaseDate => 'Release date';
|
||||
|
||||
@override
|
||||
String get trackGenre => 'Genre';
|
||||
|
||||
@override
|
||||
String get trackLabel => 'Label';
|
||||
|
||||
@override
|
||||
String get trackCopyright => 'Copyright';
|
||||
|
||||
@override
|
||||
String get trackDownloaded => 'Downloaded';
|
||||
|
||||
|
||||
@@ -897,6 +897,11 @@ class AppLocalizationsHi extends AppLocalizations {
|
||||
return 'Found $count tracks in CSV. Add them to download queue?';
|
||||
}
|
||||
|
||||
@override
|
||||
String csvImportTracks(int count) {
|
||||
return '$count tracks from CSV';
|
||||
}
|
||||
|
||||
@override
|
||||
String snackbarAddedToQueue(String trackName) {
|
||||
return 'Added \"$trackName\" to queue';
|
||||
@@ -1571,6 +1576,15 @@ class AppLocalizationsHi extends AppLocalizations {
|
||||
@override
|
||||
String get trackReleaseDate => 'Release date';
|
||||
|
||||
@override
|
||||
String get trackGenre => 'Genre';
|
||||
|
||||
@override
|
||||
String get trackLabel => 'Label';
|
||||
|
||||
@override
|
||||
String get trackCopyright => 'Copyright';
|
||||
|
||||
@override
|
||||
String get trackDownloaded => 'Downloaded';
|
||||
|
||||
|
||||
@@ -903,6 +903,11 @@ class AppLocalizationsId extends AppLocalizations {
|
||||
return 'Ditemukan $count lagu di CSV. Tambahkan ke antrian unduhan?';
|
||||
}
|
||||
|
||||
@override
|
||||
String csvImportTracks(int count) {
|
||||
return '$count tracks from CSV';
|
||||
}
|
||||
|
||||
@override
|
||||
String snackbarAddedToQueue(String trackName) {
|
||||
return 'Menambahkan \"$trackName\" ke antrian';
|
||||
@@ -1581,6 +1586,15 @@ class AppLocalizationsId extends AppLocalizations {
|
||||
@override
|
||||
String get trackReleaseDate => 'Tanggal rilis';
|
||||
|
||||
@override
|
||||
String get trackGenre => 'Genre';
|
||||
|
||||
@override
|
||||
String get trackLabel => 'Label';
|
||||
|
||||
@override
|
||||
String get trackCopyright => 'Copyright';
|
||||
|
||||
@override
|
||||
String get trackDownloaded => 'Diunduh';
|
||||
|
||||
|
||||
@@ -897,6 +897,11 @@ class AppLocalizationsJa extends AppLocalizations {
|
||||
return 'Found $count tracks in CSV. Add them to download queue?';
|
||||
}
|
||||
|
||||
@override
|
||||
String csvImportTracks(int count) {
|
||||
return '$count tracks from CSV';
|
||||
}
|
||||
|
||||
@override
|
||||
String snackbarAddedToQueue(String trackName) {
|
||||
return 'Added \"$trackName\" to queue';
|
||||
@@ -1571,6 +1576,15 @@ class AppLocalizationsJa extends AppLocalizations {
|
||||
@override
|
||||
String get trackReleaseDate => 'Release date';
|
||||
|
||||
@override
|
||||
String get trackGenre => 'Genre';
|
||||
|
||||
@override
|
||||
String get trackLabel => 'Label';
|
||||
|
||||
@override
|
||||
String get trackCopyright => 'Copyright';
|
||||
|
||||
@override
|
||||
String get trackDownloaded => 'Downloaded';
|
||||
|
||||
|
||||
@@ -897,6 +897,11 @@ class AppLocalizationsKo extends AppLocalizations {
|
||||
return 'Found $count tracks in CSV. Add them to download queue?';
|
||||
}
|
||||
|
||||
@override
|
||||
String csvImportTracks(int count) {
|
||||
return '$count tracks from CSV';
|
||||
}
|
||||
|
||||
@override
|
||||
String snackbarAddedToQueue(String trackName) {
|
||||
return 'Added \"$trackName\" to queue';
|
||||
@@ -1571,6 +1576,15 @@ class AppLocalizationsKo extends AppLocalizations {
|
||||
@override
|
||||
String get trackReleaseDate => 'Release date';
|
||||
|
||||
@override
|
||||
String get trackGenre => 'Genre';
|
||||
|
||||
@override
|
||||
String get trackLabel => 'Label';
|
||||
|
||||
@override
|
||||
String get trackCopyright => 'Copyright';
|
||||
|
||||
@override
|
||||
String get trackDownloaded => 'Downloaded';
|
||||
|
||||
|
||||
@@ -897,6 +897,11 @@ class AppLocalizationsNl extends AppLocalizations {
|
||||
return 'Found $count tracks in CSV. Add them to download queue?';
|
||||
}
|
||||
|
||||
@override
|
||||
String csvImportTracks(int count) {
|
||||
return '$count tracks from CSV';
|
||||
}
|
||||
|
||||
@override
|
||||
String snackbarAddedToQueue(String trackName) {
|
||||
return 'Added \"$trackName\" to queue';
|
||||
@@ -1571,6 +1576,15 @@ class AppLocalizationsNl extends AppLocalizations {
|
||||
@override
|
||||
String get trackReleaseDate => 'Release date';
|
||||
|
||||
@override
|
||||
String get trackGenre => 'Genre';
|
||||
|
||||
@override
|
||||
String get trackLabel => 'Label';
|
||||
|
||||
@override
|
||||
String get trackCopyright => 'Copyright';
|
||||
|
||||
@override
|
||||
String get trackDownloaded => 'Downloaded';
|
||||
|
||||
|
||||
@@ -897,6 +897,11 @@ class AppLocalizationsPt extends AppLocalizations {
|
||||
return 'Found $count tracks in CSV. Add them to download queue?';
|
||||
}
|
||||
|
||||
@override
|
||||
String csvImportTracks(int count) {
|
||||
return '$count tracks from CSV';
|
||||
}
|
||||
|
||||
@override
|
||||
String snackbarAddedToQueue(String trackName) {
|
||||
return 'Added \"$trackName\" to queue';
|
||||
@@ -1571,6 +1576,15 @@ class AppLocalizationsPt extends AppLocalizations {
|
||||
@override
|
||||
String get trackReleaseDate => 'Release date';
|
||||
|
||||
@override
|
||||
String get trackGenre => 'Genre';
|
||||
|
||||
@override
|
||||
String get trackLabel => 'Label';
|
||||
|
||||
@override
|
||||
String get trackCopyright => 'Copyright';
|
||||
|
||||
@override
|
||||
String get trackDownloaded => 'Downloaded';
|
||||
|
||||
|
||||
@@ -919,6 +919,11 @@ class AppLocalizationsRu extends AppLocalizations {
|
||||
return 'Найдено $count треков в CSV. Добавить их в очередь загрузки?';
|
||||
}
|
||||
|
||||
@override
|
||||
String csvImportTracks(int count) {
|
||||
return '$count tracks from CSV';
|
||||
}
|
||||
|
||||
@override
|
||||
String snackbarAddedToQueue(String trackName) {
|
||||
return '\"$trackName\" добавлен в очередь';
|
||||
@@ -1603,6 +1608,15 @@ class AppLocalizationsRu extends AppLocalizations {
|
||||
@override
|
||||
String get trackReleaseDate => 'Дата выхода';
|
||||
|
||||
@override
|
||||
String get trackGenre => 'Genre';
|
||||
|
||||
@override
|
||||
String get trackLabel => 'Label';
|
||||
|
||||
@override
|
||||
String get trackCopyright => 'Copyright';
|
||||
|
||||
@override
|
||||
String get trackDownloaded => 'Скачано';
|
||||
|
||||
|
||||
@@ -897,6 +897,11 @@ class AppLocalizationsZh extends AppLocalizations {
|
||||
return 'Found $count tracks in CSV. Add them to download queue?';
|
||||
}
|
||||
|
||||
@override
|
||||
String csvImportTracks(int count) {
|
||||
return '$count tracks from CSV';
|
||||
}
|
||||
|
||||
@override
|
||||
String snackbarAddedToQueue(String trackName) {
|
||||
return 'Added \"$trackName\" to queue';
|
||||
@@ -1571,6 +1576,15 @@ class AppLocalizationsZh extends AppLocalizations {
|
||||
@override
|
||||
String get trackReleaseDate => 'Release date';
|
||||
|
||||
@override
|
||||
String get trackGenre => 'Genre';
|
||||
|
||||
@override
|
||||
String get trackLabel => 'Label';
|
||||
|
||||
@override
|
||||
String get trackCopyright => 'Copyright';
|
||||
|
||||
@override
|
||||
String get trackDownloaded => 'Downloaded';
|
||||
|
||||
|
||||
@@ -619,6 +619,13 @@
|
||||
"dialogImportPlaylistTitle": "Import Playlist",
|
||||
"@dialogImportPlaylistTitle": {"description": "Dialog title - import CSV playlist"},
|
||||
"dialogImportPlaylistMessage": "Found {count} tracks in CSV. Add them to download queue?",
|
||||
"csvImportTracks": "{count} tracks from CSV",
|
||||
"@csvImportTracks": {
|
||||
"description": "Label shown in quality picker for CSV import",
|
||||
"placeholders": {
|
||||
"count": {"type": "int"}
|
||||
}
|
||||
},
|
||||
"@dialogImportPlaylistMessage": {
|
||||
"description": "Dialog message - import playlist confirmation",
|
||||
"placeholders": {
|
||||
@@ -1153,6 +1160,12 @@
|
||||
"@trackAudioQuality": {"description": "Metadata label - audio quality"},
|
||||
"trackReleaseDate": "Release date",
|
||||
"@trackReleaseDate": {"description": "Metadata label - release date"},
|
||||
"trackGenre": "Genre",
|
||||
"@trackGenre": {"description": "Metadata label - music genre"},
|
||||
"trackLabel": "Label",
|
||||
"@trackLabel": {"description": "Metadata label - record label"},
|
||||
"trackCopyright": "Copyright",
|
||||
"@trackCopyright": {"description": "Metadata label - copyright information"},
|
||||
"trackDownloaded": "Downloaded",
|
||||
"@trackDownloaded": {"description": "Metadata label - download date"},
|
||||
"trackCopyLyrics": "Copy lyrics",
|
||||
|
||||
@@ -45,6 +45,9 @@ class DownloadHistoryItem {
|
||||
final String? quality;
|
||||
final int? bitDepth;
|
||||
final int? sampleRate;
|
||||
final String? genre;
|
||||
final String? label;
|
||||
final String? copyright;
|
||||
|
||||
const DownloadHistoryItem({
|
||||
required this.id,
|
||||
@@ -65,6 +68,9 @@ class DownloadHistoryItem {
|
||||
this.quality,
|
||||
this.bitDepth,
|
||||
this.sampleRate,
|
||||
this.genre,
|
||||
this.label,
|
||||
this.copyright,
|
||||
});
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
@@ -86,6 +92,9 @@ class DownloadHistoryItem {
|
||||
'quality': quality,
|
||||
'bitDepth': bitDepth,
|
||||
'sampleRate': sampleRate,
|
||||
'genre': genre,
|
||||
'label': label,
|
||||
'copyright': copyright,
|
||||
};
|
||||
|
||||
factory DownloadHistoryItem.fromJson(Map<String, dynamic> json) =>
|
||||
@@ -108,6 +117,9 @@ class DownloadHistoryItem {
|
||||
quality: json['quality'] as String?,
|
||||
bitDepth: json['bitDepth'] as int?,
|
||||
sampleRate: json['sampleRate'] as int?,
|
||||
genre: json['genre'] as String?,
|
||||
label: json['label'] as String?,
|
||||
copyright: json['copyright'] as String?,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1016,7 +1028,13 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
}
|
||||
|
||||
/// Embed metadata and cover to a FLAC file after M4A conversion
|
||||
Future<void> _embedMetadataAndCover(String flacPath, Track track) async {
|
||||
Future<void> _embedMetadataAndCover(
|
||||
String flacPath,
|
||||
Track track, {
|
||||
String? genre,
|
||||
String? label,
|
||||
String? copyright,
|
||||
}) async {
|
||||
final settings = ref.read(settingsProvider);
|
||||
|
||||
String? coverPath;
|
||||
@@ -1083,6 +1101,20 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
metadata['ISRC'] = track.isrc!;
|
||||
}
|
||||
|
||||
// Extended metadata from enrichment (genre, label, copyright)
|
||||
if (genre != null && genre.isNotEmpty) {
|
||||
metadata['GENRE'] = genre;
|
||||
_log.d('Adding GENRE: $genre');
|
||||
}
|
||||
if (label != null && label.isNotEmpty) {
|
||||
metadata['ORGANIZATION'] = label;
|
||||
_log.d('Adding ORGANIZATION (label): $label');
|
||||
}
|
||||
if (copyright != null && copyright.isNotEmpty) {
|
||||
metadata['COPYRIGHT'] = copyright;
|
||||
_log.d('Adding COPYRIGHT: $copyright');
|
||||
}
|
||||
|
||||
_log.d('Metadata map content: $metadata');
|
||||
|
||||
try {
|
||||
@@ -1809,7 +1841,22 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
);
|
||||
}
|
||||
|
||||
await _embedMetadataAndCover(flacPath, finalTrack);
|
||||
// Get extended metadata from backend response
|
||||
final backendGenre = result['genre'] as String?;
|
||||
final backendLabel = result['label'] as String?;
|
||||
final backendCopyright = result['copyright'] as String?;
|
||||
|
||||
if (backendGenre != null || backendLabel != null || backendCopyright != null) {
|
||||
_log.d('Extended metadata from backend - Genre: $backendGenre, Label: $backendLabel, Copyright: $backendCopyright');
|
||||
}
|
||||
|
||||
await _embedMetadataAndCover(
|
||||
flacPath,
|
||||
finalTrack,
|
||||
genre: backendGenre ?? genre,
|
||||
label: backendLabel ?? label,
|
||||
copyright: backendCopyright,
|
||||
);
|
||||
_log.d('Metadata and cover embedded successfully');
|
||||
} catch (e) {
|
||||
_log.w('Warning: Failed to embed metadata/cover: $e');
|
||||
@@ -1920,6 +1967,9 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
final backendBitDepth = result['actual_bit_depth'] as int?;
|
||||
final backendSampleRate = result['actual_sample_rate'] as int?;
|
||||
final backendISRC = result['isrc'] as String?;
|
||||
final backendGenre = result['genre'] as String?;
|
||||
final backendLabel = result['label'] as String?;
|
||||
final backendCopyright = result['copyright'] as String?;
|
||||
|
||||
_log.d('Saving to history - coverUrl: ${trackToDownload.coverUrl}');
|
||||
|
||||
@@ -1970,6 +2020,9 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
quality: actualQuality,
|
||||
bitDepth: historyBitDepth,
|
||||
sampleRate: historySampleRate,
|
||||
genre: backendGenre,
|
||||
label: backendLabel,
|
||||
copyright: backendCopyright,
|
||||
),
|
||||
);
|
||||
|
||||
|
||||
+57
-30
@@ -355,37 +355,64 @@ class _HomeTabState extends ConsumerState<HomeTab> with AutomaticKeepAliveClient
|
||||
// ignore: use_build_context_synchronously
|
||||
final l10n = context.l10n;
|
||||
|
||||
final confirmed = await showDialog<bool>(
|
||||
context: this.context,
|
||||
builder: (dialogCtx) => AlertDialog(
|
||||
title: Text(l10n.dialogImportPlaylistTitle),
|
||||
content: Text(l10n.dialogImportPlaylistMessage(tracks.length)),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(dialogCtx, false),
|
||||
child: Text(l10n.dialogCancel),
|
||||
),
|
||||
FilledButton(
|
||||
onPressed: () => Navigator.pop(dialogCtx, true),
|
||||
child: Text(l10n.dialogImport),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
if (confirmed == true) {
|
||||
ref.read(downloadQueueProvider.notifier).addMultipleToQueue(tracks, settings.defaultService);
|
||||
if (mounted) {
|
||||
ScaffoldMessenger.of(this.context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(l10n.snackbarAddedTracksToQueue(tracks.length)),
|
||||
action: SnackBarAction(
|
||||
label: l10n.snackbarViewQueue,
|
||||
onPressed: () {
|
||||
},
|
||||
// Show quality picker if enabled in settings
|
||||
if (settings.askQualityBeforeDownload) {
|
||||
DownloadServicePicker.show(
|
||||
this.context,
|
||||
trackName: l10n.csvImportTracks(tracks.length),
|
||||
artistName: l10n.dialogImportPlaylistTitle,
|
||||
onSelect: (quality, service) {
|
||||
ref.read(downloadQueueProvider.notifier).addMultipleToQueue(
|
||||
tracks,
|
||||
service,
|
||||
qualityOverride: quality,
|
||||
);
|
||||
if (mounted) {
|
||||
ScaffoldMessenger.of(this.context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(l10n.snackbarAddedTracksToQueue(tracks.length)),
|
||||
action: SnackBarAction(
|
||||
label: l10n.snackbarViewQueue,
|
||||
onPressed: () {},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
} else {
|
||||
// Use default settings without quality picker
|
||||
final confirmed = await showDialog<bool>(
|
||||
context: this.context,
|
||||
builder: (dialogCtx) => AlertDialog(
|
||||
title: Text(l10n.dialogImportPlaylistTitle),
|
||||
content: Text(l10n.dialogImportPlaylistMessage(tracks.length)),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(dialogCtx, false),
|
||||
child: Text(l10n.dialogCancel),
|
||||
),
|
||||
),
|
||||
);
|
||||
FilledButton(
|
||||
onPressed: () => Navigator.pop(dialogCtx, true),
|
||||
child: Text(l10n.dialogImport),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
if (confirmed == true) {
|
||||
ref.read(downloadQueueProvider.notifier).addMultipleToQueue(tracks, settings.defaultService);
|
||||
if (mounted) {
|
||||
ScaffoldMessenger.of(this.context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(l10n.snackbarAddedTracksToQueue(tracks.length)),
|
||||
action: SnackBarAction(
|
||||
label: l10n.snackbarViewQueue,
|
||||
onPressed: () {},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,6 +119,9 @@ class _TrackMetadataScreenState extends ConsumerState<TrackMetadataScreen> {
|
||||
int? get discNumber => item.discNumber;
|
||||
String? get releaseDate => item.releaseDate;
|
||||
String? get isrc => item.isrc;
|
||||
String? get genre => item.genre;
|
||||
String? get label => item.label;
|
||||
String? get copyright => item.copyright;
|
||||
|
||||
String get cleanFilePath {
|
||||
final path = item.filePath;
|
||||
@@ -519,6 +522,12 @@ class _TrackMetadataScreenState extends ConsumerState<TrackMetadataScreen> {
|
||||
_MetadataItem(context.l10n.trackAudioQuality, audioQualityStr),
|
||||
if (releaseDate != null && releaseDate!.isNotEmpty)
|
||||
_MetadataItem(context.l10n.trackReleaseDate, releaseDate!),
|
||||
if (genre != null && genre!.isNotEmpty)
|
||||
_MetadataItem(context.l10n.trackGenre, genre!),
|
||||
if (label != null && label!.isNotEmpty)
|
||||
_MetadataItem(context.l10n.trackLabel, label!),
|
||||
if (copyright != null && copyright!.isNotEmpty)
|
||||
_MetadataItem(context.l10n.trackCopyright, copyright!),
|
||||
if (isrc != null && isrc!.isNotEmpty)
|
||||
_MetadataItem('ISRC', isrc!),
|
||||
];
|
||||
|
||||
Reference in New Issue
Block a user