feat: add SongLink region setting and fix track metadata lookup with name+artist fallback

- Add configurable SongLink region (userCountry) setting with picker UI
- Pass songLinkRegion through download request payload to Go backend
- Go backend: thread-safe global SongLink region with per-request override
- Fix downloaded track not recognized in collection tap: add findByTrackAndArtist
  fallback in download history lookup chain (Spotify ID → ISRC → name+artist)
- Apply same name+artist fallback to isDownloaded check in track options sheet
- Add missing library_database.dart import for LocalLibraryItem
This commit is contained in:
zarzet
2026-02-19 19:16:55 +07:00
parent ab72a10578
commit 882afd938b
9 changed files with 446 additions and 19 deletions
@@ -232,6 +232,22 @@ class DownloadHistoryState {
DownloadHistoryItem? getByIsrc(String isrc) => _byIsrc[isrc];
DownloadHistoryItem? findByTrackAndArtist(
String trackName,
String artistName,
) {
final normalizedTrack = trackName.trim().toLowerCase();
final normalizedArtist = artistName.trim().toLowerCase();
if (normalizedTrack.isEmpty) return null;
for (final item in items) {
if (item.trackName.trim().toLowerCase() == normalizedTrack &&
item.artistName.trim().toLowerCase() == normalizedArtist) {
return item;
}
}
return null;
}
DownloadHistoryState copyWith({List<DownloadHistoryItem>? items}) {
return DownloadHistoryState(items: items ?? this.items);
}
@@ -3111,6 +3127,7 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
safRelativeDir: relativeDir,
safFileName: fileName,
safOutputExt: outputExt,
songLinkRegion: settings.songLinkRegion,
);
return PlatformBridge.downloadByStrategy(
+21
View File
@@ -15,6 +15,7 @@ final _log = AppLogger('SettingsProvider');
class SettingsNotifier extends Notifier<AppSettings> {
static const List<int> _youtubeOpusSupportedBitrates = [128, 256];
static const List<int> _youtubeMp3SupportedBitrates = [128, 256, 320];
static final RegExp _isoRegionPattern = RegExp(r'^[A-Z]{2}$');
final Future<SharedPreferences> _prefs = SharedPreferences.getInstance();
final FlutterSecureStorage _secureStorage = const FlutterSecureStorage();
@@ -36,6 +37,7 @@ class SettingsNotifier extends Notifier<AppSettings> {
await _runMigrations(prefs);
await _normalizeYouTubeBitratesIfNeeded();
await _normalizeSongLinkRegionIfNeeded();
}
await _loadSpotifyClientSecret(prefs);
@@ -165,6 +167,19 @@ class SettingsNotifier extends Notifier<AppSettings> {
await _saveSettings();
}
String _normalizeSongLinkRegion(String region) {
final normalized = region.trim().toUpperCase();
if (_isoRegionPattern.hasMatch(normalized)) return normalized;
return 'US';
}
Future<void> _normalizeSongLinkRegionIfNeeded() async {
final normalized = _normalizeSongLinkRegion(state.songLinkRegion);
if (normalized == state.songLinkRegion) return;
state = state.copyWith(songLinkRegion: normalized);
await _saveSettings();
}
Future<void> _loadSpotifyClientSecret(SharedPreferences prefs) async {
final storedSecret = await _secureStorage.read(
key: _spotifyClientSecretKey,
@@ -483,6 +498,12 @@ class SettingsNotifier extends Notifier<AppSettings> {
_syncNetworkCompatibilitySettingsToBackend();
}
void setSongLinkRegion(String region) {
final normalized = _normalizeSongLinkRegion(region);
state = state.copyWith(songLinkRegion: normalized);
_saveSettings();
}
void setLocalLibraryEnabled(bool enabled) {
state = state.copyWith(localLibraryEnabled: enabled);
_saveSettings();