Backend serves a staged APK so co-users self-serve the latest build:
- GET /api/apk streams APK_PATH (default /data/novasonic.apk) with the
android package content-type + attachment disposition; 404 if absent.
- GET /api/apk/info reports availability, size, mtime, and an optional
version from /data/novasonic.version.txt.
- Settings gets a "🤖 Android App" section that appears only when an APK is
present and shows version/size/date.
Maintainer updates the APK with:
docker cp app-release.apk novasonic-backend:/data/novasonic.apk
Android source is already tracked; only build artifacts stay out of git.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Settings dropdown: 15s (default), 30s, 1/3 of duration, 2/3 of duration, song end.
Duration-based modes use s.duration from Navidrome metadata (always available).
'end' mode skips the timer and fires the scrobble in onEnded (web) / onQueueEnded (native).
Skipping a song never scrobbles in any mode — _cancelScrobble() still runs on skip/pause.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>