feat: add resolve API with SongLink fallback, fix multi-artist tags (#288), and cleanup

Resolve API (api.zarz.moe):
- Refactor songlink.go: Spotify URLs use resolve API, non-Spotify uses SongLink API
- Add SongLink fallback when resolve API fails for Spotify (two-layer resilience)
- Remove dead code: page parser, XOR-obfuscated keys, legacy helpers

Multi-artist tag fix (#288):
- Add RewriteSplitArtistTags() in Go to rewrite ARTIST/ALBUMARTIST as split Vorbis comments
- Wire method channel handler in Android (MainActivity.kt) and iOS (AppDelegate.swift)
- Add PlatformBridge.rewriteSplitArtistTags() in Dart
- Call native FLAC rewriter after FFmpeg embed when split_vorbis mode is active
- Extract deezerTrackArtistDisplay() helper to use Contributors in album/playlist tracks

Code cleanup:
- Remove unused imports, dead code, and redundant comments across Go and Dart
- Fix build: remove stale getQobuzDebugKey() reference in deezer_download.go
This commit is contained in:
zarzet
2026-04-01 02:45:19 +07:00
parent 7c4309955e
commit d034144e9c
63 changed files with 427 additions and 1046 deletions
@@ -2430,6 +2430,41 @@ class MainActivity: FlutterFragmentActivity() {
}
result.success(response)
}
"rewriteSplitArtistTags" -> {
val filePath = call.argument<String>("file_path") ?: ""
val artist = call.argument<String>("artist") ?: ""
val albumArtist = call.argument<String>("album_artist") ?: ""
val response = withContext(Dispatchers.IO) {
if (filePath.startsWith("content://")) {
val uri = Uri.parse(filePath)
val tempPath = copyUriToTemp(uri, ".flac")
?: return@withContext errorJson("Failed to copy SAF file to temp")
try {
val raw = Gobackend.rewriteSplitArtistTagsExport(tempPath, artist, albumArtist)
val obj = JSONObject(raw)
if (!obj.optBoolean("success", false)) {
return@withContext raw
}
if (!writeUriFromPath(uri, tempPath)) {
return@withContext errorJson("Failed to write rewritten tags back to SAF file")
}
obj.put("file_path", filePath)
obj.toString()
} catch (e: Exception) {
errorJson("Failed to rewrite split artist tags in SAF file: ${e.message}")
} finally {
try {
File(tempPath).delete()
} catch (_: Exception) {}
}
} else {
Gobackend.rewriteSplitArtistTagsExport(filePath, artist, albumArtist)
}
}
result.success(response)
}
"cleanupConnections" -> {
withContext(Dispatchers.IO) {
Gobackend.cleanupConnections()