feat(frontend): replace audio file from track edit form (#1312)
UI for the new PUT /tracks/{id}/audio endpoint shipped in #1311. Lets
artists swap a track's audio without deleting + re-uploading (and losing
likes / comments / plays / the URL).
how it's wired:
- uploader.replaceAudio(trackId, file, title, onComplete) mirrors the
existing uploader.upload XHR + SSE flow but PUTs to a track-specific
endpoint with just the file. progress is surfaced via the same toast
pattern as the initial upload.
- portal/+page.svelte edit form gains an "audio file" section next to
the existing "artwork" section. picker → "replace audio" button →
picker clears immediately and the SSE flow continues in the toast.
- Player.svelte's track-load $effect now also fires on file_id change,
not just track id change. so when the currently-playing track gets a
new audio file, the <audio> element src reloads in place. on
successful replace, we fetch the fresh track row and reassign
player.currentTrack so the effect picks up the new file_id.
deliberately separate from the metadata "save changes" flow because
the upload + transcode + PDS write can take 30s+ and has its own SSE
progress; conflating it with the fast PATCH would block the form.
manual smoke depends on backend being deployed to staging.
Co-authored-by: Claude Opus 4 (1M context) <noreply@anthropic.com>
authored by