Commit Graph
70 Commits
Author SHA1 Message Date
HoneyandClaude Sonnet 4.6 502427d02c fix: preload next track 30s early to survive Android Doze network gap
When the current song ends, Android's battery optimization briefly kills
background network access. By starting the next song's stream request while
the current track is still playing (and Chrome holds an active audio session),
the buffer is ready before the gap hits. The same URL is reused by the main
element so Chrome can serve from its in-memory buffer.

Also reset _trackChanging on play() failure to avoid permanently suppressing
pause events.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-03 20:40:25 +02:00
HoneyandClaude Sonnet 4.6 89e169b70a fix: prevent notification close on skip and background audio stall
- playCurrent: set _trackChanging flag and update media session metadata
  before changing src, so the pause event fired by src-swap does not
  set playbackState='paused' and dismiss the Samsung cover screen notification
- Remove stalled->load() handler that silently paused audio with no recovery
- Error handler now retries regardless of paused state (load() causes paused)
- Add .catch() to audio.play() in playCurrent

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-03 20:23:51 +02:00
Honey 7744ae85db fix: Scrub lag fix and Volume control for Audiobooks 2026-05-03 17:20:02 +02:00
Honey 0d8b8b6f5d fix: Bug fixes Scrub lag Chapter track last chapter Mini bar stays over music Resume ABS doesn't stop music 2026-05-03 16:47:17 +02:00
HoneyandClaude Sonnet 4.6 598c108214 fix: detect YTM artist channel expansion in getYtmVideoUrls; revert PWA MediaSession changes
- ytdlp.js: watch for [youtube:tab] in yt-dlp output during flat-playlist step;
  return [] when channel expansion is detected so cascade falls through to ytsearch
- Revert player.js / main.js / state.js PWA _changingTrack changes (not effective)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-03 01:11:36 +02:00
Honey a5959b19b8 fix: pwa changes 2026-05-02 21:27:57 +02:00
HoneyandClaude Sonnet 4.6 d9b9151f50 feat: persist shuffle and repeat state across reloads/updates
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 09:55:32 +02:00
HoneyandClaude Sonnet 4.6 c8c3670ca0 fix: eliminate mobile bg flash — double rAF + will-change:opacity
new Image() onload fires when bytes are downloaded but GPU decode of the
blurred layer hasn't happened yet on mobile. Double rAF defers the opacity
swap until after the browser has actually painted the new background.
will-change:opacity keeps the layers on dedicated compositor layers so
the blur doesn't need to be recomputed on every opacity transition.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 09:52:02 +02:00
HoneyandClaude Sonnet 4.6 af0c2d6eb2 fix: preload bg image before crossfade to eliminate black flash
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 09:39:50 +02:00
HoneyandClaude Sonnet 4.6 e0a518fa13 fix: deduplicate NP background crossfade — skip if URL unchanged
_syncNpDirect is called 2-3x per skip from different call sites;
the crossfade now no-ops when the cover URL hasn't changed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 09:36:08 +02:00
HoneyandClaude Sonnet 4.6 97a4cc756d fix: crossfade now-playing background instead of hard flash
Two-layer opacity crossfade replaces the broken background-image transition.
New image loads on the hidden layer, then both opacity values swap smoothly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 09:29:54 +02:00
HoneyandClaude Sonnet 4.6 e75d90e165 fix: eliminate flash on skip, refresh home on nav
- renderQueue: in-place active-class update when queue unchanged — no DOM rebuild, no image reload
- updatePlayerUI: update img.src directly instead of replacing innerHTML
- _syncNpDirect: same img.src update for now-playing cover
- navigate('home'): always reloads home data so new albums appear without restart

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 09:21:12 +02:00
HoneyandClaude Sonnet 4.6 b575e38726 feat: add cover art to queue panel, remove redundant sidebar queue nav item
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 09:07:07 +02:00
HoneyandClaude Sonnet 4.6 a61436669e fix: per-span hover highlight, use • as artist separator everywhere
- CSS: target #player-artist-name span:hover and #np-artist-name span:hover so only the hovered artist name highlights, not all at once
- change artist separator from / to • in song items, player bar, now playing overlay, album header

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 00:51:38 +02:00
HoneyandClaude Sonnet 4.6 a31953d17e fix: split multi-artists in player bar and now playing overlay, fix broken onclick
- player bar: fix onclick broken by JSON.stringify producing double-quoted strings inside double-quoted HTML attribute; use single-quoted JS args instead
- now playing overlay: np-artist-name now splits artists and each is individually clickable (closes NP then navigates to artist)
- remove wrapper onclick from both np-artist-name and player-artist-name in HTML

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 00:45:10 +02:00
HoneyandClaude Sonnet 4.6 e029a8f900 fix: split multi-artists in player bar, each name navigates to own artist profile
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 00:39:23 +02:00
HoneyandClaude Sonnet 4.6 16b7faee2b refactor: split views.js and ui.js into focused modules
Extract 3 new files from oversized source files:
- src/components.js (~86 lines): makeCard, makeAlbumCard, makeSongItem,
  makeGlobalTrackItem, mkSection — reusable DOM builders
- src/spotify.js (~187 lines): loadSpotifyImporter, resolveSpotifyLink,
  clearSpotifyPreview, spotifyDlAll, and private render/artwork helpers
- src/nowplaying.js (~255 lines): openNowPlaying, closeNowPlaying,
  syncNowPlaying, switchNpTab, full lyrics engine, renderNpQueue,
  npGoArtist/Album, openNpMenu/closeNpMenu

views.js: 1121 → 864 lines
ui.js:     706 → 462 lines

Update imports in main.js, player.js, views.js accordingly.
Build verified: 15 modules, no errors.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 19:20:00 +02:00
HoneyandClaude Sonnet 4.6 e31ddec843 fix(mobile): restore playback state + MediaSession stability
- _restoreLastPlayed: set audio.src + call updateMediaSession so play
  button works immediately and notification shows artwork on app open
- visibilitychange: re-register all MediaSession handlers after screen
  unlock, fold/flip, or background return (fixes vanishing notification)
- Stall watchdog (3s interval): detects frozen audio in background and
  calls play() to recover; also catches missed 'ended' events so
  auto-advance works reliably when screen is off
- stalled/error listeners: attempt audio reload on network hiccup

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 18:53:25 +02:00
HoneyandClaude Sonnet 4.6 fbabdf8269 feat: synced lyrics view in Now Playing overlay
Adds a Lyrics tab to the NP overlay using Navidrome's getLyricsBySongId
endpoint. Synced lyrics auto-scroll and highlight the current line as
the track plays; tapping a line seeks to that position. Falls back to
plain text for unsynced lyrics.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 18:42:45 +02:00
HoneyandClaude Sonnet 4.6 9aded56713 Migrate to Vite + ES module architecture
Split monolithic app.js (~1850 lines) into maintainable ES modules:
- src/state.js  — shared mutable state (S object)
- src/utils.js  — md5, esc, formatDur, toast
- src/api.js    — Subsonic API, Navidrome REST, iTunes API
- src/player.js — playback, transport, queue, media session, preview
- src/views.js  — navigation, page loaders, card makers, search
- src/ui.js     — all modals, overlays, sidebar, settings
- src/pwa.js    — service worker registration + update banner
- src/main.js   — app init, connect, window globals

Updated Dockerfile to multi-stage (Node build → nginx serve).
Static assets (sw.js, manifest.json, icon.svg) moved to public/.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 13:01:34 +02:00