mirror of
https://github.com/zarzet/SpotiFLAC-Mobile.git
synced 2026-06-04 05:38:12 +02:00
feat: add filterContributingArtistsInAlbumArtist setting - new option to strip contributing artists from Album Artist metadata - applies to folder organization and metadata embedding - collapsible Artist Name Filters section in download settings UI
This commit is contained in:
+34
-16
@@ -21,6 +21,7 @@ class AppSettings {
|
||||
final String folderOrganization;
|
||||
final bool useAlbumArtistForFolders;
|
||||
final bool usePrimaryArtistOnly; // Strip featured artists from folder name
|
||||
final bool filterContributingArtistsInAlbumArtist;
|
||||
final String historyViewMode;
|
||||
final String historyFilterMode;
|
||||
final bool askQualityBeforeDownload;
|
||||
@@ -36,18 +37,24 @@ class AppSettings {
|
||||
final bool showExtensionStore;
|
||||
final String locale;
|
||||
final String lyricsMode;
|
||||
final String tidalHighFormat; // Format for Tidal HIGH quality: 'mp3_320', 'opus_256', or 'opus_128'
|
||||
final bool useAllFilesAccess; // Android 13+ only: enable MANAGE_EXTERNAL_STORAGE
|
||||
final bool autoExportFailedDownloads; // Auto export failed downloads to TXT file
|
||||
final String downloadNetworkMode; // 'any' = WiFi + Mobile, 'wifi_only' = WiFi only
|
||||
|
||||
final String
|
||||
tidalHighFormat; // Format for Tidal HIGH quality: 'mp3_320', 'opus_256', or 'opus_128'
|
||||
final bool
|
||||
useAllFilesAccess; // Android 13+ only: enable MANAGE_EXTERNAL_STORAGE
|
||||
final bool
|
||||
autoExportFailedDownloads; // Auto export failed downloads to TXT file
|
||||
final String
|
||||
downloadNetworkMode; // 'any' = WiFi + Mobile, 'wifi_only' = WiFi only
|
||||
|
||||
// Local Library Settings
|
||||
final bool localLibraryEnabled; // Enable local library scanning
|
||||
final String localLibraryPath; // Path to scan for audio files
|
||||
final bool localLibraryShowDuplicates; // Show indicator when searching for existing tracks
|
||||
|
||||
final bool
|
||||
localLibraryShowDuplicates; // Show indicator when searching for existing tracks
|
||||
|
||||
// Tutorial/Onboarding
|
||||
final bool hasCompletedTutorial; // Track if user has completed the app tutorial
|
||||
final bool
|
||||
hasCompletedTutorial; // Track if user has completed the app tutorial
|
||||
|
||||
const AppSettings({
|
||||
this.defaultService = 'tidal',
|
||||
@@ -67,6 +74,7 @@ class AppSettings {
|
||||
this.folderOrganization = 'none',
|
||||
this.useAlbumArtistForFolders = true,
|
||||
this.usePrimaryArtistOnly = false,
|
||||
this.filterContributingArtistsInAlbumArtist = false,
|
||||
this.historyViewMode = 'grid',
|
||||
this.historyFilterMode = 'all',
|
||||
this.askQualityBeforeDownload = true,
|
||||
@@ -112,6 +120,7 @@ class AppSettings {
|
||||
String? folderOrganization,
|
||||
bool? useAlbumArtistForFolders,
|
||||
bool? usePrimaryArtistOnly,
|
||||
bool? filterContributingArtistsInAlbumArtist,
|
||||
String? historyViewMode,
|
||||
String? historyFilterMode,
|
||||
bool? askQualityBeforeDownload,
|
||||
@@ -157,18 +166,25 @@ class AppSettings {
|
||||
folderOrganization: folderOrganization ?? this.folderOrganization,
|
||||
useAlbumArtistForFolders:
|
||||
useAlbumArtistForFolders ?? this.useAlbumArtistForFolders,
|
||||
usePrimaryArtistOnly:
|
||||
usePrimaryArtistOnly ?? this.usePrimaryArtistOnly,
|
||||
usePrimaryArtistOnly: usePrimaryArtistOnly ?? this.usePrimaryArtistOnly,
|
||||
filterContributingArtistsInAlbumArtist:
|
||||
filterContributingArtistsInAlbumArtist ??
|
||||
this.filterContributingArtistsInAlbumArtist,
|
||||
historyViewMode: historyViewMode ?? this.historyViewMode,
|
||||
historyFilterMode: historyFilterMode ?? this.historyFilterMode,
|
||||
askQualityBeforeDownload: askQualityBeforeDownload ?? this.askQualityBeforeDownload,
|
||||
askQualityBeforeDownload:
|
||||
askQualityBeforeDownload ?? this.askQualityBeforeDownload,
|
||||
spotifyClientId: spotifyClientId ?? this.spotifyClientId,
|
||||
spotifyClientSecret: spotifyClientSecret ?? this.spotifyClientSecret,
|
||||
useCustomSpotifyCredentials: useCustomSpotifyCredentials ?? this.useCustomSpotifyCredentials,
|
||||
useCustomSpotifyCredentials:
|
||||
useCustomSpotifyCredentials ?? this.useCustomSpotifyCredentials,
|
||||
metadataSource: metadataSource ?? this.metadataSource,
|
||||
enableLogging: enableLogging ?? this.enableLogging,
|
||||
useExtensionProviders: useExtensionProviders ?? this.useExtensionProviders,
|
||||
searchProvider: clearSearchProvider ? null : (searchProvider ?? this.searchProvider),
|
||||
useExtensionProviders:
|
||||
useExtensionProviders ?? this.useExtensionProviders,
|
||||
searchProvider: clearSearchProvider
|
||||
? null
|
||||
: (searchProvider ?? this.searchProvider),
|
||||
separateSingles: separateSingles ?? this.separateSingles,
|
||||
albumFolderStructure: albumFolderStructure ?? this.albumFolderStructure,
|
||||
showExtensionStore: showExtensionStore ?? this.showExtensionStore,
|
||||
@@ -176,12 +192,14 @@ class AppSettings {
|
||||
lyricsMode: lyricsMode ?? this.lyricsMode,
|
||||
tidalHighFormat: tidalHighFormat ?? this.tidalHighFormat,
|
||||
useAllFilesAccess: useAllFilesAccess ?? this.useAllFilesAccess,
|
||||
autoExportFailedDownloads: autoExportFailedDownloads ?? this.autoExportFailedDownloads,
|
||||
autoExportFailedDownloads:
|
||||
autoExportFailedDownloads ?? this.autoExportFailedDownloads,
|
||||
downloadNetworkMode: downloadNetworkMode ?? this.downloadNetworkMode,
|
||||
// Local Library
|
||||
localLibraryEnabled: localLibraryEnabled ?? this.localLibraryEnabled,
|
||||
localLibraryPath: localLibraryPath ?? this.localLibraryPath,
|
||||
localLibraryShowDuplicates: localLibraryShowDuplicates ?? this.localLibraryShowDuplicates,
|
||||
localLibraryShowDuplicates:
|
||||
localLibraryShowDuplicates ?? this.localLibraryShowDuplicates,
|
||||
// Tutorial
|
||||
hasCompletedTutorial: hasCompletedTutorial ?? this.hasCompletedTutorial,
|
||||
);
|
||||
|
||||
@@ -24,6 +24,8 @@ AppSettings _$AppSettingsFromJson(Map<String, dynamic> json) => AppSettings(
|
||||
folderOrganization: json['folderOrganization'] as String? ?? 'none',
|
||||
useAlbumArtistForFolders: json['useAlbumArtistForFolders'] as bool? ?? true,
|
||||
usePrimaryArtistOnly: json['usePrimaryArtistOnly'] as bool? ?? false,
|
||||
filterContributingArtistsInAlbumArtist:
|
||||
json['filterContributingArtistsInAlbumArtist'] as bool? ?? false,
|
||||
historyViewMode: json['historyViewMode'] as String? ?? 'grid',
|
||||
historyFilterMode: json['historyFilterMode'] as String? ?? 'all',
|
||||
askQualityBeforeDownload: json['askQualityBeforeDownload'] as bool? ?? true,
|
||||
@@ -72,6 +74,8 @@ Map<String, dynamic> _$AppSettingsToJson(AppSettings instance) =>
|
||||
'folderOrganization': instance.folderOrganization,
|
||||
'useAlbumArtistForFolders': instance.useAlbumArtistForFolders,
|
||||
'usePrimaryArtistOnly': instance.usePrimaryArtistOnly,
|
||||
'filterContributingArtistsInAlbumArtist':
|
||||
instance.filterContributingArtistsInAlbumArtist,
|
||||
'historyViewMode': instance.historyViewMode,
|
||||
'historyFilterMode': instance.historyFilterMode,
|
||||
'askQualityBeforeDownload': instance.askQualityBeforeDownload,
|
||||
|
||||
@@ -1197,11 +1197,18 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
String albumFolderStructure = 'artist_album',
|
||||
bool useAlbumArtistForFolders = true,
|
||||
bool usePrimaryArtistOnly = false,
|
||||
bool filterContributingArtistsInAlbumArtist = false,
|
||||
}) async {
|
||||
String baseDir = state.outputDir;
|
||||
final normalizedAlbumArtist = _normalizeOptionalString(track.albumArtist);
|
||||
var folderArtist = useAlbumArtistForFolders
|
||||
? _normalizeOptionalString(track.albumArtist) ?? track.artistName
|
||||
? normalizedAlbumArtist ?? track.artistName
|
||||
: track.artistName;
|
||||
if (useAlbumArtistForFolders &&
|
||||
filterContributingArtistsInAlbumArtist &&
|
||||
normalizedAlbumArtist != null) {
|
||||
folderArtist = _extractPrimaryArtist(folderArtist);
|
||||
}
|
||||
if (usePrimaryArtistOnly) {
|
||||
folderArtist = _extractPrimaryArtist(folderArtist);
|
||||
}
|
||||
@@ -1309,6 +1316,15 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
return artist;
|
||||
}
|
||||
|
||||
String _resolveAlbumArtistForMetadata(Track track, AppSettings settings) {
|
||||
var albumArtist =
|
||||
_normalizeOptionalString(track.albumArtist) ?? track.artistName;
|
||||
if (settings.filterContributingArtistsInAlbumArtist) {
|
||||
albumArtist = _extractPrimaryArtist(albumArtist);
|
||||
}
|
||||
return albumArtist;
|
||||
}
|
||||
|
||||
bool _isSafMode(AppSettings settings) {
|
||||
return Platform.isAndroid &&
|
||||
settings.storageMode == 'saf' &&
|
||||
@@ -1333,10 +1349,17 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
String albumFolderStructure = 'artist_album',
|
||||
bool useAlbumArtistForFolders = true,
|
||||
bool usePrimaryArtistOnly = false,
|
||||
bool filterContributingArtistsInAlbumArtist = false,
|
||||
}) async {
|
||||
final normalizedAlbumArtist = _normalizeOptionalString(track.albumArtist);
|
||||
var folderArtist = useAlbumArtistForFolders
|
||||
? _normalizeOptionalString(track.albumArtist) ?? track.artistName
|
||||
? normalizedAlbumArtist ?? track.artistName
|
||||
: track.artistName;
|
||||
if (useAlbumArtistForFolders &&
|
||||
filterContributingArtistsInAlbumArtist &&
|
||||
normalizedAlbumArtist != null) {
|
||||
folderArtist = _extractPrimaryArtist(folderArtist);
|
||||
}
|
||||
if (usePrimaryArtistOnly) {
|
||||
folderArtist = _extractPrimaryArtist(folderArtist);
|
||||
}
|
||||
@@ -1752,6 +1775,10 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
try {
|
||||
final settings = ref.read(settingsProvider);
|
||||
final extensionState = ref.read(extensionProvider);
|
||||
final resolvedAlbumArtist = _resolveAlbumArtistForMetadata(
|
||||
track,
|
||||
settings,
|
||||
);
|
||||
|
||||
if (!settings.useExtensionProviders) return;
|
||||
|
||||
@@ -1766,8 +1793,7 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
'title': track.name,
|
||||
'artist': track.artistName,
|
||||
'album': track.albumName,
|
||||
'album_artist':
|
||||
_normalizeOptionalString(track.albumArtist) ?? track.artistName,
|
||||
'album_artist': resolvedAlbumArtist,
|
||||
'track_number': track.trackNumber ?? 1,
|
||||
'disc_number': track.discNumber ?? 1,
|
||||
'isrc': track.isrc ?? '',
|
||||
@@ -1827,7 +1853,7 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
Track _buildTrackForMetadataEmbedding(
|
||||
Track baseTrack,
|
||||
Map<String, dynamic> backendResult,
|
||||
String? normalizedAlbumArtist,
|
||||
String resolvedAlbumArtist,
|
||||
) {
|
||||
final backendTrackNum = _parsePositiveInt(backendResult['track_number']);
|
||||
final backendDiscNum = _parsePositiveInt(backendResult['disc_number']);
|
||||
@@ -1850,7 +1876,7 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
name: baseTrack.name,
|
||||
artistName: baseTrack.artistName,
|
||||
albumName: backendAlbum ?? baseTrack.albumName,
|
||||
albumArtist: normalizedAlbumArtist,
|
||||
albumArtist: resolvedAlbumArtist,
|
||||
coverUrl: baseTrack.coverUrl,
|
||||
duration: baseTrack.duration,
|
||||
isrc: baseTrack.isrc,
|
||||
@@ -1914,8 +1940,7 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
'ALBUM': track.albumName,
|
||||
};
|
||||
|
||||
final albumArtist =
|
||||
_normalizeOptionalString(track.albumArtist) ?? track.artistName;
|
||||
final albumArtist = _resolveAlbumArtistForMetadata(track, settings);
|
||||
metadata['ALBUMARTIST'] = albumArtist;
|
||||
|
||||
if (track.trackNumber != null) {
|
||||
@@ -2057,8 +2082,7 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
'ALBUM': track.albumName,
|
||||
};
|
||||
|
||||
final albumArtist =
|
||||
_normalizeOptionalString(track.albumArtist) ?? track.artistName;
|
||||
final albumArtist = _resolveAlbumArtistForMetadata(track, settings);
|
||||
metadata['ALBUMARTIST'] = albumArtist;
|
||||
|
||||
if (track.trackNumber != null) {
|
||||
@@ -2222,8 +2246,7 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
'ALBUM': track.albumName,
|
||||
};
|
||||
|
||||
final albumArtist =
|
||||
_normalizeOptionalString(track.albumArtist) ?? track.artistName;
|
||||
final albumArtist = _resolveAlbumArtistForMetadata(track, settings);
|
||||
metadata['ALBUMARTIST'] = albumArtist;
|
||||
|
||||
if (track.trackNumber != null) {
|
||||
@@ -2741,8 +2764,9 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
|
||||
_log.d('Track coverUrl after enrichment: ${trackToDownload.coverUrl}');
|
||||
|
||||
final normalizedAlbumArtist = _normalizeOptionalString(
|
||||
trackToDownload.albumArtist,
|
||||
final resolvedAlbumArtist = _resolveAlbumArtistForMetadata(
|
||||
trackToDownload,
|
||||
settings,
|
||||
);
|
||||
|
||||
final quality = item.qualityOverride ?? state.audioQuality;
|
||||
@@ -2755,6 +2779,8 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
albumFolderStructure: settings.albumFolderStructure,
|
||||
useAlbumArtistForFolders: settings.useAlbumArtistForFolders,
|
||||
usePrimaryArtistOnly: settings.usePrimaryArtistOnly,
|
||||
filterContributingArtistsInAlbumArtist:
|
||||
settings.filterContributingArtistsInAlbumArtist,
|
||||
)
|
||||
: '';
|
||||
String? appOutputDir;
|
||||
@@ -2767,6 +2793,8 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
albumFolderStructure: settings.albumFolderStructure,
|
||||
useAlbumArtistForFolders: settings.useAlbumArtistForFolders,
|
||||
usePrimaryArtistOnly: settings.usePrimaryArtistOnly,
|
||||
filterContributingArtistsInAlbumArtist:
|
||||
settings.filterContributingArtistsInAlbumArtist,
|
||||
);
|
||||
var effectiveOutputDir = initialOutputDir;
|
||||
var effectiveSafMode = isSafMode;
|
||||
@@ -2972,7 +3000,7 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
trackName: trackToDownload.name,
|
||||
artistName: trackToDownload.artistName,
|
||||
albumName: trackToDownload.albumName,
|
||||
albumArtist: normalizedAlbumArtist ?? trackToDownload.artistName,
|
||||
albumArtist: resolvedAlbumArtist,
|
||||
coverUrl: trackToDownload.coverUrl ?? '',
|
||||
outputDir: outputDir,
|
||||
filenameFormat: state.filenameFormat,
|
||||
@@ -3021,6 +3049,8 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
albumFolderStructure: settings.albumFolderStructure,
|
||||
useAlbumArtistForFolders: settings.useAlbumArtistForFolders,
|
||||
usePrimaryArtistOnly: settings.usePrimaryArtistOnly,
|
||||
filterContributingArtistsInAlbumArtist:
|
||||
settings.filterContributingArtistsInAlbumArtist,
|
||||
);
|
||||
final fallbackResult = await runDownload(
|
||||
useSaf: false,
|
||||
@@ -3358,7 +3388,7 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
final finalTrack = _buildTrackForMetadataEmbedding(
|
||||
trackToDownload,
|
||||
result,
|
||||
normalizedAlbumArtist,
|
||||
resolvedAlbumArtist,
|
||||
);
|
||||
|
||||
final backendGenre = result['genre'] as String?;
|
||||
@@ -3522,7 +3552,7 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
final finalTrack = _buildTrackForMetadataEmbedding(
|
||||
trackToDownload,
|
||||
result,
|
||||
normalizedAlbumArtist,
|
||||
resolvedAlbumArtist,
|
||||
);
|
||||
|
||||
final backendGenre = result['genre'] as String?;
|
||||
@@ -3582,7 +3612,7 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
final finalTrack = _buildTrackForMetadataEmbedding(
|
||||
trackToDownload,
|
||||
result,
|
||||
normalizedAlbumArtist,
|
||||
resolvedAlbumArtist,
|
||||
);
|
||||
final backendGenre = result['genre'] as String?;
|
||||
final backendLabel = result['label'] as String?;
|
||||
@@ -3642,7 +3672,7 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
final finalTrack = _buildTrackForMetadataEmbedding(
|
||||
trackToDownload,
|
||||
result,
|
||||
normalizedAlbumArtist,
|
||||
resolvedAlbumArtist,
|
||||
);
|
||||
final backendGenre = result['genre'] as String?;
|
||||
final backendLabel = result['label'] as String?;
|
||||
@@ -3679,7 +3709,7 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
final finalTrack = _buildTrackForMetadataEmbedding(
|
||||
trackToDownload,
|
||||
result,
|
||||
normalizedAlbumArtist,
|
||||
resolvedAlbumArtist,
|
||||
);
|
||||
final backendGenre = result['genre'] as String?;
|
||||
final backendLabel = result['label'] as String?;
|
||||
@@ -3926,9 +3956,8 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
_log.d('Saving to history - coverUrl: ${trackToDownload.coverUrl}');
|
||||
|
||||
final historyAlbumArtist =
|
||||
(normalizedAlbumArtist != null &&
|
||||
normalizedAlbumArtist != trackToDownload.artistName)
|
||||
? normalizedAlbumArtist
|
||||
resolvedAlbumArtist != trackToDownload.artistName
|
||||
? resolvedAlbumArtist
|
||||
: null;
|
||||
|
||||
final isMp3 = filePath.endsWith('.mp3');
|
||||
|
||||
@@ -236,6 +236,11 @@ class SettingsNotifier extends Notifier<AppSettings> {
|
||||
_saveSettings();
|
||||
}
|
||||
|
||||
void setFilterContributingArtistsInAlbumArtist(bool enabled) {
|
||||
state = state.copyWith(filterContributingArtistsInAlbumArtist: enabled);
|
||||
_saveSettings();
|
||||
}
|
||||
|
||||
void setHistoryViewMode(String mode) {
|
||||
state = state.copyWith(historyViewMode: mode);
|
||||
_saveSettings();
|
||||
|
||||
@@ -25,6 +25,7 @@ class _DownloadSettingsPageState extends ConsumerState<DownloadSettingsPage> {
|
||||
static const _builtInServices = ['tidal', 'qobuz', 'amazon'];
|
||||
int _androidSdkVersion = 0;
|
||||
bool _hasAllFilesAccess = false;
|
||||
bool _artistFolderFiltersExpanded = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@@ -363,19 +364,53 @@ class _DownloadSettingsPageState extends ConsumerState<DownloadSettingsPage> {
|
||||
onChanged: (value) => ref
|
||||
.read(settingsProvider.notifier)
|
||||
.setUseAlbumArtistForFolders(value),
|
||||
showDivider: false,
|
||||
),
|
||||
SettingsItem(
|
||||
icon: Icons.filter_alt_outlined,
|
||||
title: 'Artist Name Filters',
|
||||
subtitle: _getArtistFolderFilterSubtitle(
|
||||
context,
|
||||
usePrimaryArtistOnly: settings.usePrimaryArtistOnly,
|
||||
filterAlbumArtistContributors:
|
||||
settings.filterContributingArtistsInAlbumArtist,
|
||||
),
|
||||
SettingsSwitchItem(
|
||||
icon: Icons.person_outline,
|
||||
title: context.l10n.downloadUsePrimaryArtistOnly,
|
||||
subtitle: settings.usePrimaryArtistOnly
|
||||
? context.l10n.downloadUsePrimaryArtistOnlyEnabled
|
||||
: context.l10n.downloadUsePrimaryArtistOnlyDisabled,
|
||||
value: settings.usePrimaryArtistOnly,
|
||||
onChanged: (value) => ref
|
||||
.read(settingsProvider.notifier)
|
||||
.setUsePrimaryArtistOnly(value),
|
||||
showDivider: false,
|
||||
trailing: Icon(
|
||||
_artistFolderFiltersExpanded
|
||||
? Icons.expand_less
|
||||
: Icons.expand_more,
|
||||
),
|
||||
onTap: () {
|
||||
setState(() {
|
||||
_artistFolderFiltersExpanded =
|
||||
!_artistFolderFiltersExpanded;
|
||||
});
|
||||
},
|
||||
showDivider: !_artistFolderFiltersExpanded,
|
||||
),
|
||||
if (_artistFolderFiltersExpanded)
|
||||
SettingsSwitchItem(
|
||||
icon: Icons.person_outline,
|
||||
title: context.l10n.downloadUsePrimaryArtistOnly,
|
||||
subtitle: settings.usePrimaryArtistOnly
|
||||
? context.l10n.downloadUsePrimaryArtistOnlyEnabled
|
||||
: context.l10n.downloadUsePrimaryArtistOnlyDisabled,
|
||||
value: settings.usePrimaryArtistOnly,
|
||||
onChanged: (value) => ref
|
||||
.read(settingsProvider.notifier)
|
||||
.setUsePrimaryArtistOnly(value),
|
||||
),
|
||||
if (_artistFolderFiltersExpanded)
|
||||
SettingsSwitchItem(
|
||||
icon: Icons.group_remove_outlined,
|
||||
title: 'Filter contributing artists in Album Artist',
|
||||
subtitle: settings.filterContributingArtistsInAlbumArtist
|
||||
? 'Album Artist metadata uses primary artist only'
|
||||
: 'Keep full Album Artist metadata value',
|
||||
value: settings.filterContributingArtistsInAlbumArtist,
|
||||
onChanged: (value) => ref
|
||||
.read(settingsProvider.notifier)
|
||||
.setFilterContributingArtistsInAlbumArtist(value),
|
||||
showDivider: false,
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -937,7 +972,10 @@ class _DownloadSettingsPageState extends ConsumerState<DownloadSettingsPage> {
|
||||
if (ctx.mounted) {
|
||||
ScaffoldMessenger.of(ctx).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(validation.errorReason ?? context.l10n.setupIcloudNotSupported),
|
||||
content: Text(
|
||||
validation.errorReason ??
|
||||
context.l10n.setupIcloudNotSupported,
|
||||
),
|
||||
backgroundColor: Theme.of(ctx).colorScheme.error,
|
||||
duration: const Duration(seconds: 4),
|
||||
),
|
||||
@@ -1000,6 +1038,20 @@ class _DownloadSettingsPageState extends ConsumerState<DownloadSettingsPage> {
|
||||
}
|
||||
}
|
||||
|
||||
String _getArtistFolderFilterSubtitle(
|
||||
BuildContext context, {
|
||||
required bool usePrimaryArtistOnly,
|
||||
required bool filterAlbumArtistContributors,
|
||||
}) {
|
||||
final statuses = <String>[
|
||||
usePrimaryArtistOnly ? 'Primary only: On' : 'Primary only: Off',
|
||||
filterAlbumArtistContributors
|
||||
? 'Album Artist metadata: Primary only'
|
||||
: 'Album Artist metadata: Full',
|
||||
];
|
||||
return statuses.join(' | ');
|
||||
}
|
||||
|
||||
String _getLyricsModeLabel(BuildContext context, String mode) {
|
||||
switch (mode) {
|
||||
case 'external':
|
||||
@@ -1456,9 +1508,7 @@ class _ServiceChip extends StatelessWidget {
|
||||
|
||||
return Expanded(
|
||||
child: Material(
|
||||
color: isSelected
|
||||
? colorScheme.primaryContainer
|
||||
: unselectedColor,
|
||||
color: isSelected ? colorScheme.primaryContainer : unselectedColor,
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
child: InkWell(
|
||||
onTap: onTap,
|
||||
|
||||
Reference in New Issue
Block a user