feat(song-info): show absolute file path on Navidrome via native API (#504)

* feat(song-info): show absolute file path on Navidrome via native API

Subsonic's `getSong.view` returns at most a relative path (or none on
Navidrome), so the Path row in the Song Info modal stayed empty for
most users. Feishin and the Navidrome web client surface the full
server-side path by hitting Navidrome's native `/api/song/{id}` instead.

Added an `nd_get_song_path` Tauri command that logs in to the native
API with the active server's credentials, fetches the song, and returns
the `path` string. Wired it into `SongInfoModal`: the Subsonic
`getSong` call still drives the rest of the dialog, and the native call
runs in parallel only when the active server's identity is
"navidrome". When it returns a path, that absolute path replaces the
relative Subsonic value; native-API failures are silent and the modal
falls back to whatever Subsonic provided.

No token cache yet — the modal is opened occasionally enough that one
fresh login per call is fine.

Closes discussion #479.

* docs: changelog entry for PR #504

Logs the Navidrome native-API absolute file path support for the
Song Info dialog in v1.46.0 "## Added".

* docs: settings contributor entry for PR #504, drop competitor mention

Adds the song-info absolute path bullet to Psychotoxical's contributors
list in Settings, and rewords the existing CHANGELOG entry so neither
text references competing clients.
This commit is contained in:
Frank Stellmacher
2026-05-07 20:22:55 +02:00
committed by GitHub
parent 726f3f0ff2
commit a41e3a624a
6 changed files with 95 additions and 3 deletions
+24
View File
@@ -107,3 +107,27 @@ export async function ndUpdateUser(
export async function ndDeleteUser(serverUrl: string, token: string, id: string): Promise<void> {
await invoke('nd_delete_user', { serverUrl, token, id });
}
/**
* Fetch the absolute filesystem path of a song from Navidrome's native API.
* Subsonic `getSong.view` only returns a relative path (or none on Navidrome);
* the native `/api/song/:id` endpoint returns the absolute path the server
* stores the file at, the same way Feishin and the Navidrome web client get it.
*
* Returns `null` when the server doesn't expose the field (non-admin on some
* Navidrome configurations) or when the call fails — the Song Info modal then
* falls back to whatever the Subsonic response had.
*/
export async function ndGetSongPath(
serverUrl: string,
username: string,
password: string,
id: string,
): Promise<string | null> {
try {
const raw = await invoke<string | null>('nd_get_song_path', { serverUrl, username, password, id });
return raw && raw.length > 0 ? raw : null;
} catch {
return null;
}
}