v1.2.10 — Fix Volume/Duration + Enable/Disable Consistency
🐛 Bug Fixes (3 fixes)
1. Volume and Max Duration Were Never Applied
Root cause: Theme songs in Jellyfin are served at:
/Audio/{itemId}/universal?UserId=...&DeviceId=...&...
The URL contains /Audio/ but does NOT contain "theme" or "/ThemeMedia/". The previous interceptor condition url.indexOf('theme') !== -1 never matched, so volume and duration were silently skipped.
Fix: Replaced URL-only detection with a viewshow-timing approach — mirrors exactly how Jellyfin's own themeMediaPlayer.js works:
- On
viewshowevent withserverId+idparams (detail page navigation), open an 8-second window - Any
/Audio/play within that window is the theme song - Window is consumed after first match to avoid affecting user-initiated music
2. Volume Override Didn't Stick
Root cause: Based on studying jellyfin/jellyfin-web PR #6673 ("Implement Theme Song Volume Control", closed), confirmed that Jellyfin's shared media player may restore its saved global volume after play() resolves. The previous volumechange listener removed itself after the first correction only.
Fix: Persistent volumechange guard with ownVolumeChange flag:
- Listener stays active for the element's lifetime (not removed after first correction)
ownVolumeChangeflag prevents infinite feedback loop when we set volume ourselves- Three
setTimeoutfallbacks (150ms / 500ms / 1200ms) ensure volume sticks even with delayed playback manager overrides
3. Enable/Disable Checkbox Was Inconsistent After Page Refresh
Root cause: Modal was reading enable state from localStorage ({userId}-enableThemeSongs), which could be absent or stale. The async fetch timing meant the two sources (server vs. localStorage) could show different values.
Fix: Server preferences are now the single source of truth:
- On every
fetchUserPreferences()call, our server preference is always synced to Jellyfin's localStorage key - Modal refreshes from server preferences only (no more localStorage read for display)
- Enable/disable state is now consistent across page loads and browser tabs
🔬 Research
Studied jellyfin/jellyfin-web source directly:
src/components/themeMediaPlayer.js— confirmedviewshowtiming approachsrc/scripts/settings/userSettings.js+appSettings.js— confirmed localStorage storage- PR #6673 — confirmed
HTMLMediaElement.play()intercept is the only viable volume control approach (Jellyfin's one shared media player means themeMediaPlayer.js can't set volume internally without affecting all playback)