mirror of
https://github.com/zarzet/SpotiFLAC-Mobile.git
synced 2026-05-13 12:34:59 +02:00
16ce6089fb
Remove Tidal from built-in provider registry (metadata, search, download, URL parsing) and delete tidal.go. Introduce extension runtime APIs for lyrics lookup (getLyricsLRC), ISRC existence check (checkISRCExists), and ISRC index management (addToISRCIndex). Refactor extension download response construction into normalizeExtensionDownloadResult/overlayExtensionDownloadMetadata helpers with AlreadyExists support and ISRC indexing. Switch download mirrors to DoRequestWithUserAgent for ISP blocking detection. Add 50+ new localization keys and accessibility labels across all supported locales.
293 lines
12 KiB
Dart
293 lines
12 KiB
Dart
import 'package:json_annotation/json_annotation.dart';
|
|
import 'package:spotiflac_android/utils/artist_utils.dart';
|
|
|
|
part 'settings.g.dart';
|
|
|
|
@JsonSerializable()
|
|
class AppSettings {
|
|
static const String homeFeedProviderOff = '__off__';
|
|
|
|
final String defaultService;
|
|
final String audioQuality;
|
|
final String filenameFormat;
|
|
final String downloadDirectory;
|
|
final String storageMode; // 'app' or 'saf'
|
|
final String downloadTreeUri; // SAF persistable tree URI
|
|
final bool autoFallback;
|
|
final bool embedMetadata; // Master switch for metadata/cover/lyrics embedding
|
|
final String
|
|
artistTagMode; // 'joined' or 'split_vorbis' for Vorbis-based formats
|
|
final bool embedLyrics;
|
|
final bool embedReplayGain; // Calculate and embed ReplayGain tags
|
|
final bool maxQualityCover;
|
|
final bool isFirstLaunch;
|
|
final int concurrentDownloads;
|
|
final bool checkForUpdates;
|
|
final String updateChannel;
|
|
final bool hasSearchedBefore;
|
|
final String folderOrganization;
|
|
final bool createPlaylistFolder;
|
|
final bool useAlbumArtistForFolders;
|
|
final bool usePrimaryArtistOnly; // Strip featured artists from folder name
|
|
final bool filterContributingArtistsInAlbumArtist;
|
|
final String historyViewMode;
|
|
final String historyFilterMode;
|
|
final bool askQualityBeforeDownload;
|
|
final bool enableLogging;
|
|
final bool useExtensionProviders;
|
|
final List<String>? downloadFallbackExtensionIds;
|
|
final String? searchProvider;
|
|
final String defaultSearchTab;
|
|
final String? homeFeedProvider;
|
|
final bool separateSingles;
|
|
final String singleFilenameFormat;
|
|
final String albumFolderStructure;
|
|
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 bool
|
|
networkCompatibilityMode; // Try HTTP + allow invalid TLS cert for API requests
|
|
final String
|
|
songLinkRegion; // SongLink userCountry region code used for platform lookup
|
|
|
|
final bool localLibraryEnabled; // Enable local library scanning
|
|
final String localLibraryPath; // Path to scan for audio files
|
|
final String
|
|
localLibraryBookmark; // Base64-encoded iOS security-scoped bookmark
|
|
final bool
|
|
localLibraryShowDuplicates; // Show indicator when searching for existing tracks
|
|
final String
|
|
localLibraryAutoScan; // Auto-scan mode: 'off', 'on_open', 'daily', 'weekly'
|
|
|
|
final bool
|
|
hasCompletedTutorial; // Track if user has completed the app tutorial
|
|
|
|
final List<String>
|
|
lyricsProviders; // Ordered list of enabled lyrics provider IDs
|
|
final bool
|
|
lyricsIncludeTranslationNetease; // Append translated lyrics (Netease)
|
|
final bool
|
|
lyricsIncludeRomanizationNetease; // Append romanized lyrics (Netease)
|
|
final bool
|
|
lyricsMultiPersonWordByWord; // Enable v1/v2 + [bg:] tags for Apple/QQ syllable lyrics
|
|
final String
|
|
musixmatchLanguage; // Optional ISO language code for Musixmatch localized lyrics
|
|
|
|
final String
|
|
lastSeenVersion; // Last app version the user has acknowledged (e.g. '3.7.0')
|
|
|
|
const AppSettings({
|
|
this.defaultService = '',
|
|
this.audioQuality = 'LOSSLESS',
|
|
this.filenameFormat = '{title} - {artist}',
|
|
this.downloadDirectory = '',
|
|
this.storageMode = 'app',
|
|
this.downloadTreeUri = '',
|
|
this.autoFallback = true,
|
|
this.embedMetadata = true,
|
|
this.artistTagMode = artistTagModeJoined,
|
|
this.embedLyrics = true,
|
|
this.embedReplayGain = false,
|
|
this.maxQualityCover = true,
|
|
this.isFirstLaunch = true,
|
|
this.concurrentDownloads = 1,
|
|
this.checkForUpdates = true,
|
|
this.updateChannel = 'stable',
|
|
this.hasSearchedBefore = false,
|
|
this.folderOrganization = 'none',
|
|
this.createPlaylistFolder = false,
|
|
this.useAlbumArtistForFolders = true,
|
|
this.usePrimaryArtistOnly = false,
|
|
this.filterContributingArtistsInAlbumArtist = false,
|
|
this.historyViewMode = 'grid',
|
|
this.historyFilterMode = 'all',
|
|
this.askQualityBeforeDownload = true,
|
|
this.enableLogging = false,
|
|
this.useExtensionProviders = true,
|
|
this.downloadFallbackExtensionIds,
|
|
this.searchProvider,
|
|
this.defaultSearchTab = 'all',
|
|
this.homeFeedProvider,
|
|
this.separateSingles = false,
|
|
this.singleFilenameFormat = '{title} - {artist}',
|
|
this.albumFolderStructure = 'artist_album',
|
|
this.showExtensionStore = true,
|
|
this.locale = 'system',
|
|
this.lyricsMode = 'embed',
|
|
this.tidalHighFormat = 'mp3_320',
|
|
this.useAllFilesAccess = false,
|
|
this.autoExportFailedDownloads = false,
|
|
this.downloadNetworkMode = 'any',
|
|
this.networkCompatibilityMode = false,
|
|
this.songLinkRegion = 'US',
|
|
this.localLibraryEnabled = false,
|
|
this.localLibraryPath = '',
|
|
this.localLibraryBookmark = '',
|
|
this.localLibraryShowDuplicates = true,
|
|
this.localLibraryAutoScan = 'off',
|
|
this.hasCompletedTutorial = false,
|
|
this.lyricsProviders = const [
|
|
'lrclib',
|
|
'musixmatch',
|
|
'netease',
|
|
'apple_music',
|
|
'qqmusic',
|
|
],
|
|
this.lyricsIncludeTranslationNetease = false,
|
|
this.lyricsIncludeRomanizationNetease = false,
|
|
this.lyricsMultiPersonWordByWord = false,
|
|
this.musixmatchLanguage = '',
|
|
this.lastSeenVersion = '',
|
|
});
|
|
|
|
AppSettings copyWith({
|
|
String? defaultService,
|
|
String? audioQuality,
|
|
String? filenameFormat,
|
|
String? downloadDirectory,
|
|
String? storageMode,
|
|
String? downloadTreeUri,
|
|
bool? autoFallback,
|
|
bool? embedMetadata,
|
|
String? artistTagMode,
|
|
bool? embedLyrics,
|
|
bool? embedReplayGain,
|
|
bool? maxQualityCover,
|
|
bool? isFirstLaunch,
|
|
int? concurrentDownloads,
|
|
bool? checkForUpdates,
|
|
String? updateChannel,
|
|
bool? hasSearchedBefore,
|
|
String? folderOrganization,
|
|
bool? createPlaylistFolder,
|
|
bool? useAlbumArtistForFolders,
|
|
bool? usePrimaryArtistOnly,
|
|
bool? filterContributingArtistsInAlbumArtist,
|
|
String? historyViewMode,
|
|
String? historyFilterMode,
|
|
bool? askQualityBeforeDownload,
|
|
bool? enableLogging,
|
|
bool? useExtensionProviders,
|
|
List<String>? downloadFallbackExtensionIds,
|
|
bool clearDownloadFallbackExtensionIds = false,
|
|
String? searchProvider,
|
|
bool clearSearchProvider = false,
|
|
String? defaultSearchTab,
|
|
String? homeFeedProvider,
|
|
bool clearHomeFeedProvider = false,
|
|
bool? separateSingles,
|
|
String? singleFilenameFormat,
|
|
String? albumFolderStructure,
|
|
bool? showExtensionStore,
|
|
String? locale,
|
|
String? lyricsMode,
|
|
String? tidalHighFormat,
|
|
bool? useAllFilesAccess,
|
|
bool? autoExportFailedDownloads,
|
|
String? downloadNetworkMode,
|
|
bool? networkCompatibilityMode,
|
|
String? songLinkRegion,
|
|
bool? localLibraryEnabled,
|
|
String? localLibraryPath,
|
|
String? localLibraryBookmark,
|
|
bool? localLibraryShowDuplicates,
|
|
String? localLibraryAutoScan,
|
|
bool? hasCompletedTutorial,
|
|
List<String>? lyricsProviders,
|
|
bool? lyricsIncludeTranslationNetease,
|
|
bool? lyricsIncludeRomanizationNetease,
|
|
bool? lyricsMultiPersonWordByWord,
|
|
String? musixmatchLanguage,
|
|
String? lastSeenVersion,
|
|
}) {
|
|
return AppSettings(
|
|
defaultService: defaultService ?? this.defaultService,
|
|
audioQuality: audioQuality ?? this.audioQuality,
|
|
filenameFormat: filenameFormat ?? this.filenameFormat,
|
|
downloadDirectory: downloadDirectory ?? this.downloadDirectory,
|
|
storageMode: storageMode ?? this.storageMode,
|
|
downloadTreeUri: downloadTreeUri ?? this.downloadTreeUri,
|
|
autoFallback: autoFallback ?? this.autoFallback,
|
|
embedMetadata: embedMetadata ?? this.embedMetadata,
|
|
artistTagMode: artistTagMode ?? this.artistTagMode,
|
|
embedLyrics: embedLyrics ?? this.embedLyrics,
|
|
embedReplayGain: embedReplayGain ?? this.embedReplayGain,
|
|
maxQualityCover: maxQualityCover ?? this.maxQualityCover,
|
|
isFirstLaunch: isFirstLaunch ?? this.isFirstLaunch,
|
|
concurrentDownloads: concurrentDownloads ?? this.concurrentDownloads,
|
|
checkForUpdates: checkForUpdates ?? this.checkForUpdates,
|
|
updateChannel: updateChannel ?? this.updateChannel,
|
|
hasSearchedBefore: hasSearchedBefore ?? this.hasSearchedBefore,
|
|
folderOrganization: folderOrganization ?? this.folderOrganization,
|
|
createPlaylistFolder: createPlaylistFolder ?? this.createPlaylistFolder,
|
|
useAlbumArtistForFolders:
|
|
useAlbumArtistForFolders ?? this.useAlbumArtistForFolders,
|
|
usePrimaryArtistOnly: usePrimaryArtistOnly ?? this.usePrimaryArtistOnly,
|
|
filterContributingArtistsInAlbumArtist:
|
|
filterContributingArtistsInAlbumArtist ??
|
|
this.filterContributingArtistsInAlbumArtist,
|
|
historyViewMode: historyViewMode ?? this.historyViewMode,
|
|
historyFilterMode: historyFilterMode ?? this.historyFilterMode,
|
|
askQualityBeforeDownload:
|
|
askQualityBeforeDownload ?? this.askQualityBeforeDownload,
|
|
enableLogging: enableLogging ?? this.enableLogging,
|
|
useExtensionProviders:
|
|
useExtensionProviders ?? this.useExtensionProviders,
|
|
downloadFallbackExtensionIds: clearDownloadFallbackExtensionIds
|
|
? null
|
|
: (downloadFallbackExtensionIds ?? this.downloadFallbackExtensionIds),
|
|
searchProvider: clearSearchProvider
|
|
? null
|
|
: (searchProvider ?? this.searchProvider),
|
|
defaultSearchTab: defaultSearchTab ?? this.defaultSearchTab,
|
|
homeFeedProvider: clearHomeFeedProvider
|
|
? null
|
|
: (homeFeedProvider ?? this.homeFeedProvider),
|
|
separateSingles: separateSingles ?? this.separateSingles,
|
|
singleFilenameFormat: singleFilenameFormat ?? this.singleFilenameFormat,
|
|
albumFolderStructure: albumFolderStructure ?? this.albumFolderStructure,
|
|
showExtensionStore: showExtensionStore ?? this.showExtensionStore,
|
|
locale: locale ?? this.locale,
|
|
lyricsMode: lyricsMode ?? this.lyricsMode,
|
|
tidalHighFormat: tidalHighFormat ?? this.tidalHighFormat,
|
|
useAllFilesAccess: useAllFilesAccess ?? this.useAllFilesAccess,
|
|
autoExportFailedDownloads:
|
|
autoExportFailedDownloads ?? this.autoExportFailedDownloads,
|
|
downloadNetworkMode: downloadNetworkMode ?? this.downloadNetworkMode,
|
|
networkCompatibilityMode:
|
|
networkCompatibilityMode ?? this.networkCompatibilityMode,
|
|
songLinkRegion: songLinkRegion ?? this.songLinkRegion,
|
|
localLibraryEnabled: localLibraryEnabled ?? this.localLibraryEnabled,
|
|
localLibraryPath: localLibraryPath ?? this.localLibraryPath,
|
|
localLibraryBookmark: localLibraryBookmark ?? this.localLibraryBookmark,
|
|
localLibraryShowDuplicates:
|
|
localLibraryShowDuplicates ?? this.localLibraryShowDuplicates,
|
|
localLibraryAutoScan: localLibraryAutoScan ?? this.localLibraryAutoScan,
|
|
hasCompletedTutorial: hasCompletedTutorial ?? this.hasCompletedTutorial,
|
|
lyricsProviders: lyricsProviders ?? this.lyricsProviders,
|
|
lyricsIncludeTranslationNetease:
|
|
lyricsIncludeTranslationNetease ??
|
|
this.lyricsIncludeTranslationNetease,
|
|
lyricsIncludeRomanizationNetease:
|
|
lyricsIncludeRomanizationNetease ??
|
|
this.lyricsIncludeRomanizationNetease,
|
|
lyricsMultiPersonWordByWord:
|
|
lyricsMultiPersonWordByWord ?? this.lyricsMultiPersonWordByWord,
|
|
musixmatchLanguage: musixmatchLanguage ?? this.musixmatchLanguage,
|
|
lastSeenVersion: lastSeenVersion ?? this.lastSeenVersion,
|
|
);
|
|
}
|
|
|
|
factory AppSettings.fromJson(Map<String, dynamic> json) =>
|
|
_$AppSettingsFromJson(json);
|
|
Map<String, dynamic> toJson() => _$AppSettingsToJson(this);
|
|
}
|