mirror of
https://github.com/zarzet/SpotiFLAC-Mobile.git
synced 2026-06-07 07:04:00 +02:00
30973a8e78
Add lyrics_provider as a new extension type alongside metadata_provider and
download_provider. Extensions implementing fetchLyrics() are called before
built-in providers, giving user-installed extensions highest priority.
Built-in lyrics cascade is now configurable from Download Settings:
- Reorderable provider list (LRCLIB, Musixmatch, Netease, Apple Music, QQ Music)
- Per-provider options: Netease translation/romanization, Apple/QQ multi-person
word-by-word speaker tags, Musixmatch language code
- Provider order and options synced to Go backend on app start and on change
Go backend changes:
- New lyrics_provider manifest type with validation (extension_manifest.go)
- ExtensionProviderWrapper.FetchLyrics() with Goja JS bridge (extension_providers.go)
- Configurable SetLyricsProviderOrder/GetLyricsProviderOrder cascade (lyrics.go)
- LyricsFetchOptions struct for per-provider settings (lyrics.go)
- Extracted tryLRCLIB() helper, randomized LRCLIB User-Agent (lyrics.go)
- Refactored msToLRCTimestamp to separate msToLRCTimestampInline (lyrics.go)
- New provider source files: lyrics_apple.go, lyrics_musixmatch.go,
lyrics_netease.go, lyrics_qqmusic.go
- JSON export functions for lyrics settings (exports.go)
- hasLyricsProvider field in extension manager JSON output
Platform channels:
- Android (MainActivity.kt): setLyricsProviders, getLyricsProviders,
getAvailableLyricsProviders, setLyricsFetchOptions, getLyricsFetchOptions
- iOS (AppDelegate.swift): same 5 method channel handlers for iOS parity
Flutter side:
- Extension model: hasLyricsProvider field + Lyrics Provider capability badge
- Settings model: lyricsProviders, lyricsIncludeTranslationNetease,
lyricsIncludeRomanizationNetease, lyricsMultiPersonWordByWord,
musixmatchLanguage fields with generated serialization
- Settings provider: setters + _syncLyricsSettingsToBackend()
- Download settings UI: provider picker, toggle switches, language picker
- Platform bridge: lyrics provider/options methods
Docs: lyrics provider extension documentation in site/docs.html
CHANGELOG: updated with lyrics provider and search feature entries
121 lines
6.1 KiB
Dart
121 lines
6.1 KiB
Dart
// GENERATED CODE - DO NOT MODIFY BY HAND
|
|
|
|
part of 'settings.dart';
|
|
|
|
// **************************************************************************
|
|
// JsonSerializableGenerator
|
|
// **************************************************************************
|
|
|
|
AppSettings _$AppSettingsFromJson(Map<String, dynamic> json) => AppSettings(
|
|
defaultService: json['defaultService'] as String? ?? 'tidal',
|
|
audioQuality: json['audioQuality'] as String? ?? 'LOSSLESS',
|
|
filenameFormat: json['filenameFormat'] as String? ?? '{title} - {artist}',
|
|
downloadDirectory: json['downloadDirectory'] as String? ?? '',
|
|
storageMode: json['storageMode'] as String? ?? 'app',
|
|
downloadTreeUri: json['downloadTreeUri'] as String? ?? '',
|
|
autoFallback: json['autoFallback'] as bool? ?? true,
|
|
embedLyrics: json['embedLyrics'] as bool? ?? true,
|
|
maxQualityCover: json['maxQualityCover'] as bool? ?? true,
|
|
isFirstLaunch: json['isFirstLaunch'] as bool? ?? true,
|
|
concurrentDownloads: (json['concurrentDownloads'] as num?)?.toInt() ?? 1,
|
|
checkForUpdates: json['checkForUpdates'] as bool? ?? true,
|
|
updateChannel: json['updateChannel'] as String? ?? 'stable',
|
|
hasSearchedBefore: json['hasSearchedBefore'] as bool? ?? false,
|
|
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,
|
|
spotifyClientId: json['spotifyClientId'] as String? ?? '',
|
|
spotifyClientSecret: json['spotifyClientSecret'] as String? ?? '',
|
|
useCustomSpotifyCredentials:
|
|
json['useCustomSpotifyCredentials'] as bool? ?? true,
|
|
metadataSource: json['metadataSource'] as String? ?? 'deezer',
|
|
enableLogging: json['enableLogging'] as bool? ?? false,
|
|
useExtensionProviders: json['useExtensionProviders'] as bool? ?? true,
|
|
searchProvider: json['searchProvider'] as String?,
|
|
separateSingles: json['separateSingles'] as bool? ?? false,
|
|
albumFolderStructure:
|
|
json['albumFolderStructure'] as String? ?? 'artist_album',
|
|
showExtensionStore: json['showExtensionStore'] as bool? ?? true,
|
|
locale: json['locale'] as String? ?? 'system',
|
|
lyricsMode: json['lyricsMode'] as String? ?? 'embed',
|
|
tidalHighFormat: json['tidalHighFormat'] as String? ?? 'mp3_320',
|
|
useAllFilesAccess: json['useAllFilesAccess'] as bool? ?? false,
|
|
autoExportFailedDownloads:
|
|
json['autoExportFailedDownloads'] as bool? ?? false,
|
|
downloadNetworkMode: json['downloadNetworkMode'] as String? ?? 'any',
|
|
localLibraryEnabled: json['localLibraryEnabled'] as bool? ?? false,
|
|
localLibraryPath: json['localLibraryPath'] as String? ?? '',
|
|
localLibraryShowDuplicates:
|
|
json['localLibraryShowDuplicates'] as bool? ?? true,
|
|
hasCompletedTutorial: json['hasCompletedTutorial'] as bool? ?? false,
|
|
lyricsProviders:
|
|
(json['lyricsProviders'] as List<dynamic>?)
|
|
?.map((e) => e as String)
|
|
.toList() ??
|
|
const ['lrclib', 'musixmatch', 'netease', 'apple_music', 'qqmusic'],
|
|
lyricsIncludeTranslationNetease:
|
|
json['lyricsIncludeTranslationNetease'] as bool? ?? false,
|
|
lyricsIncludeRomanizationNetease:
|
|
json['lyricsIncludeRomanizationNetease'] as bool? ?? false,
|
|
lyricsMultiPersonWordByWord:
|
|
json['lyricsMultiPersonWordByWord'] as bool? ?? true,
|
|
musixmatchLanguage: json['musixmatchLanguage'] as String? ?? '',
|
|
);
|
|
|
|
Map<String, dynamic> _$AppSettingsToJson(
|
|
AppSettings instance,
|
|
) => <String, dynamic>{
|
|
'defaultService': instance.defaultService,
|
|
'audioQuality': instance.audioQuality,
|
|
'filenameFormat': instance.filenameFormat,
|
|
'downloadDirectory': instance.downloadDirectory,
|
|
'storageMode': instance.storageMode,
|
|
'downloadTreeUri': instance.downloadTreeUri,
|
|
'autoFallback': instance.autoFallback,
|
|
'embedLyrics': instance.embedLyrics,
|
|
'maxQualityCover': instance.maxQualityCover,
|
|
'isFirstLaunch': instance.isFirstLaunch,
|
|
'concurrentDownloads': instance.concurrentDownloads,
|
|
'checkForUpdates': instance.checkForUpdates,
|
|
'updateChannel': instance.updateChannel,
|
|
'hasSearchedBefore': instance.hasSearchedBefore,
|
|
'folderOrganization': instance.folderOrganization,
|
|
'useAlbumArtistForFolders': instance.useAlbumArtistForFolders,
|
|
'usePrimaryArtistOnly': instance.usePrimaryArtistOnly,
|
|
'filterContributingArtistsInAlbumArtist':
|
|
instance.filterContributingArtistsInAlbumArtist,
|
|
'historyViewMode': instance.historyViewMode,
|
|
'historyFilterMode': instance.historyFilterMode,
|
|
'askQualityBeforeDownload': instance.askQualityBeforeDownload,
|
|
'spotifyClientId': instance.spotifyClientId,
|
|
'spotifyClientSecret': instance.spotifyClientSecret,
|
|
'useCustomSpotifyCredentials': instance.useCustomSpotifyCredentials,
|
|
'metadataSource': instance.metadataSource,
|
|
'enableLogging': instance.enableLogging,
|
|
'useExtensionProviders': instance.useExtensionProviders,
|
|
'searchProvider': instance.searchProvider,
|
|
'separateSingles': instance.separateSingles,
|
|
'albumFolderStructure': instance.albumFolderStructure,
|
|
'showExtensionStore': instance.showExtensionStore,
|
|
'locale': instance.locale,
|
|
'lyricsMode': instance.lyricsMode,
|
|
'tidalHighFormat': instance.tidalHighFormat,
|
|
'useAllFilesAccess': instance.useAllFilesAccess,
|
|
'autoExportFailedDownloads': instance.autoExportFailedDownloads,
|
|
'downloadNetworkMode': instance.downloadNetworkMode,
|
|
'localLibraryEnabled': instance.localLibraryEnabled,
|
|
'localLibraryPath': instance.localLibraryPath,
|
|
'localLibraryShowDuplicates': instance.localLibraryShowDuplicates,
|
|
'hasCompletedTutorial': instance.hasCompletedTutorial,
|
|
'lyricsProviders': instance.lyricsProviders,
|
|
'lyricsIncludeTranslationNetease': instance.lyricsIncludeTranslationNetease,
|
|
'lyricsIncludeRomanizationNetease': instance.lyricsIncludeRomanizationNetease,
|
|
'lyricsMultiPersonWordByWord': instance.lyricsMultiPersonWordByWord,
|
|
'musixmatchLanguage': instance.musixmatchLanguage,
|
|
};
|