mirror of
https://github.com/zarzet/SpotiFLAC-Mobile.git
synced 2026-07-03 19:27:57 +02:00
3278e32711
Prefer the in-app browser for signed-session verification challenges, normalize invalid saved modes to the new default, and keep the help dialog modal until the user explicitly dismisses it.
322 lines
13 KiB
Dart
322 lines
13 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 downloadDirectoryBookmark;
|
|
final String storageMode; // 'app' or 'saf'
|
|
final String downloadTreeUri; // SAF persistable tree URI
|
|
final bool autoFallback;
|
|
final bool embedMetadata;
|
|
final String
|
|
artistTagMode; // 'joined' or 'split_vorbis' for Vorbis-based formats
|
|
final bool embedLyrics;
|
|
final bool embedReplayGain;
|
|
final bool maxQualityCover;
|
|
final bool isFirstLaunch;
|
|
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
|
|
extensionVerificationBrowserMode; // 'external_first' or 'in_app_first'
|
|
final String locale;
|
|
final String lyricsMode;
|
|
final String
|
|
tidalHighFormat; // Legacy key for 320kbps lossy output format: 'mp3_320', 'aac_320', 'opus_256', or 'opus_128'
|
|
final bool
|
|
useAllFilesAccess; // Android 13+ only: enable MANAGE_EXTERNAL_STORAGE
|
|
final bool autoExportFailedDownloads;
|
|
final String
|
|
downloadNetworkMode; // 'any' = WiFi + Mobile, 'wifi_only' = WiFi only
|
|
final bool
|
|
networkCompatibilityMode; // Try HTTP + allow invalid TLS cert for API requests
|
|
final bool
|
|
allowLocalNetwork; // Allow requests to private/local network targets (local proxy / custom DNS)
|
|
final String
|
|
songLinkRegion; // SongLink userCountry region code used for platform lookup
|
|
final bool
|
|
nativeDownloadWorkerEnabled; // Experimental Android service-owned worker
|
|
|
|
final bool localLibraryEnabled;
|
|
final String localLibraryPath;
|
|
final String
|
|
localLibraryBookmark; // Base64-encoded iOS security-scoped bookmark
|
|
final bool localLibraryShowDuplicates;
|
|
final String
|
|
localLibraryAutoScan; // Auto-scan mode: 'off', 'on_open', 'daily', 'weekly'
|
|
|
|
final bool hasCompletedTutorial;
|
|
|
|
final List<String> lyricsProviders;
|
|
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 bool
|
|
lyricsAppleElrcWordSync; // Preserve Apple Music inline word timestamps for eLRC-capable players
|
|
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')
|
|
|
|
final bool deduplicateDownloads;
|
|
final bool saveDownloadHistory;
|
|
|
|
final String playerMode;
|
|
|
|
const AppSettings({
|
|
this.defaultService = '',
|
|
this.audioQuality = 'LOSSLESS',
|
|
this.filenameFormat = '{title} - {artist}',
|
|
this.downloadDirectory = '',
|
|
this.downloadDirectoryBookmark = '',
|
|
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.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.extensionVerificationBrowserMode = 'in_app_first',
|
|
this.locale = 'system',
|
|
this.lyricsMode = 'embed',
|
|
this.tidalHighFormat = 'mp3_320',
|
|
this.useAllFilesAccess = false,
|
|
this.autoExportFailedDownloads = false,
|
|
this.downloadNetworkMode = 'any',
|
|
this.networkCompatibilityMode = false,
|
|
this.allowLocalNetwork = false,
|
|
this.songLinkRegion = 'US',
|
|
this.nativeDownloadWorkerEnabled = false,
|
|
this.localLibraryEnabled = false,
|
|
this.localLibraryPath = '',
|
|
this.localLibraryBookmark = '',
|
|
this.localLibraryShowDuplicates = true,
|
|
this.localLibraryAutoScan = 'off',
|
|
this.hasCompletedTutorial = false,
|
|
this.lyricsProviders = const ['lrclib', 'apple_music'],
|
|
this.lyricsIncludeTranslationNetease = false,
|
|
this.lyricsIncludeRomanizationNetease = false,
|
|
this.lyricsMultiPersonWordByWord = false,
|
|
this.lyricsAppleElrcWordSync = false,
|
|
this.musixmatchLanguage = '',
|
|
this.lastSeenVersion = '',
|
|
this.deduplicateDownloads = true,
|
|
this.saveDownloadHistory = true,
|
|
this.playerMode = 'external',
|
|
});
|
|
|
|
AppSettings copyWith({
|
|
String? defaultService,
|
|
String? audioQuality,
|
|
String? filenameFormat,
|
|
String? downloadDirectory,
|
|
String? downloadDirectoryBookmark,
|
|
String? storageMode,
|
|
String? downloadTreeUri,
|
|
bool? autoFallback,
|
|
bool? embedMetadata,
|
|
String? artistTagMode,
|
|
bool? embedLyrics,
|
|
bool? embedReplayGain,
|
|
bool? maxQualityCover,
|
|
bool? isFirstLaunch,
|
|
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? extensionVerificationBrowserMode,
|
|
String? locale,
|
|
String? lyricsMode,
|
|
String? tidalHighFormat,
|
|
bool? useAllFilesAccess,
|
|
bool? autoExportFailedDownloads,
|
|
String? downloadNetworkMode,
|
|
bool? networkCompatibilityMode,
|
|
bool? allowLocalNetwork,
|
|
String? songLinkRegion,
|
|
bool? nativeDownloadWorkerEnabled,
|
|
bool? localLibraryEnabled,
|
|
String? localLibraryPath,
|
|
String? localLibraryBookmark,
|
|
bool? localLibraryShowDuplicates,
|
|
String? localLibraryAutoScan,
|
|
bool? hasCompletedTutorial,
|
|
List<String>? lyricsProviders,
|
|
bool? lyricsIncludeTranslationNetease,
|
|
bool? lyricsIncludeRomanizationNetease,
|
|
bool? lyricsMultiPersonWordByWord,
|
|
bool? lyricsAppleElrcWordSync,
|
|
String? musixmatchLanguage,
|
|
String? lastSeenVersion,
|
|
bool? deduplicateDownloads,
|
|
bool? saveDownloadHistory,
|
|
String? playerMode,
|
|
}) {
|
|
return AppSettings(
|
|
defaultService: defaultService ?? this.defaultService,
|
|
audioQuality: audioQuality ?? this.audioQuality,
|
|
filenameFormat: filenameFormat ?? this.filenameFormat,
|
|
downloadDirectory: downloadDirectory ?? this.downloadDirectory,
|
|
downloadDirectoryBookmark:
|
|
downloadDirectoryBookmark ?? this.downloadDirectoryBookmark,
|
|
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,
|
|
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,
|
|
extensionVerificationBrowserMode:
|
|
extensionVerificationBrowserMode ??
|
|
this.extensionVerificationBrowserMode,
|
|
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,
|
|
allowLocalNetwork: allowLocalNetwork ?? this.allowLocalNetwork,
|
|
songLinkRegion: songLinkRegion ?? this.songLinkRegion,
|
|
nativeDownloadWorkerEnabled:
|
|
nativeDownloadWorkerEnabled ?? this.nativeDownloadWorkerEnabled,
|
|
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,
|
|
lyricsAppleElrcWordSync:
|
|
lyricsAppleElrcWordSync ?? this.lyricsAppleElrcWordSync,
|
|
musixmatchLanguage: musixmatchLanguage ?? this.musixmatchLanguage,
|
|
lastSeenVersion: lastSeenVersion ?? this.lastSeenVersion,
|
|
deduplicateDownloads: deduplicateDownloads ?? this.deduplicateDownloads,
|
|
saveDownloadHistory: saveDownloadHistory ?? this.saveDownloadHistory,
|
|
playerMode: playerMode ?? this.playerMode,
|
|
);
|
|
}
|
|
|
|
factory AppSettings.fromJson(Map<String, dynamic> json) =>
|
|
_$AppSettingsFromJson(json);
|
|
Map<String, dynamic> toJson() => _$AppSettingsToJson(this);
|
|
}
|