- Now Playing: add "Dynamische Hintergrundfarbe" toggle in Theme settings;
when on, np-bg uses higher saturation/brightness so the cover color really
shows through the blurred background
- Settings modal: extend to bottom nav on mobile (was leaving ~74px dead space
for the player bar which the overlay already covers at z-index 200)
- Android: fix onTrackChanged always staying on the first song — the snapshot
from MediaController can lag behind ExoPlayer on auto-advance, causing the
stale currentIndex to overwrite the correct p.index; now only advance to
a higher live index (for rapid-skip catch-up) and use p.trackId directly
instead of the potentially-stale snapshot id for the queue-mismatch guard
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Change overlay from position:absolute to position:fixed so it isn't
clipped by main-content's overflow-y:auto
- Set overlay top dynamically from header.offsetHeight so it always
anchors exactly below the sticky header
- Responsive max-height: accounts for player bar + bottom nav on mobile
- Hide logo text on ≤359px screens to keep search pill wide enough
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replaces the hidden toggle-based mobile search bar with a permanently
visible pill-shaped search input in the header row, next to the logo.
- Search is always visible — no button click required
- Typing shows a floating overlay with library results (artists, albums,
songs) without navigating away from the current page
- Clearing the input or navigating to any page closes the overlay silently
- The ✕ clear button appears only while text is present
- navigate() now calls closeHeaderSearch() so results disappear cleanly
when tapping any result or bottom nav tab
- Old toggleMobileSearch / closeMobileSearch kept as no-op stubs for safety
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- views.js: skip ASCII word-match when artist name is non-ASCII so Japanese
artists (e.g. ヨルシカ) resolve correctly to an iTunes artist ID
- index.html + styles.css: collapsible Sort-Tags section in edit modal
- ui.js: pre-fill sort fields from romaji index; include in save body
- novasonic-server.js: accept manual titleSort/artistSort/albumArtistSort/albumSort
overrides; fall back to auto-computed romaji when not provided
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Normalize •, ·, ;, , separators on save (both edit and download paths)
- Fix ndSong scope bug (was inaccessible outside try block in edit-metadata)
- Apply _normalizeArtists to artist/albumArtist before ffmpeg tags and file rename
- Storage format: Artist A;Artist B (no space, Navidrome/MusicBrainz style)
- Display format: Artist A; Artist B (space, via _fmtArtists in frontend)
- Show separator hint below label in metadata editor fields
- Remove hover effect on player bar song title
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Naming convention (download + edit-metadata):
Before: {01 - }Title.ext
After: {01 - }Artist1, Artist2 - Title.ext
- ytdlp.js: builds fileBase with artist prefix; findExistingTrack checks
both new and old format so existing files aren't re-downloaded
- metadata.js: findExistingTrack accepts optional safeArtist param
- novasonic-server.js: file rename on title edit now includes artist
(falls back to Navidrome's stored artist if not provided in body)
Song list subtitle: hide album name when album === title (singles where
the album is named after the track appear to duplicate the title)
Player bar: removed .player-title:hover underline/colour effect
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- New src/soundcloud.js: resolves SoundCloud URLs via yt-dlp --dump-single-json,
renders track/playlist preview with per-track download buttons
- Backend POST /api/soundcloud/resolve: extracts metadata (title, artist, genre,
artwork, duration) directly from SoundCloud — no iTunes lookup needed
- ytdlp.js: sourceUrl param — if set, downloads directly from URL instead of
ytsearch cascade (used for SoundCloud tracks)
- Spotify importer page renamed to Song Importer, now contains both
Spotify and SoundCloud sections in one view
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Info modal gets an edit pencil button that switches to edit form
- Editable fields: title, artist, album, genre, year, track#, disc#, total tracks
- Cover art: upload your own image or auto-fetch from Cover Art Archive via MusicBrainz
- MusicBrainz button queries /api/musicbrainz/lookup and autofills all fields
- Save POSTs to /api/edit-metadata which rewrites tags via ffmpeg and triggers Navidrome rescan
- Backend: GET /api/musicbrainz/lookup + POST /api/edit-metadata endpoints
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Shuffle now shuffles the queue array once (current song first, rest
randomised behind it) instead of picking a random index on every skip.
Toggling shuffle off restores the original queue order. Removed the
'once' repeat state added in the previous commit.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Scrobble timer: 12s → 15s
- Play count moved after action buttons, shown as "23×" (distinct from duration)
- Song star/menu buttons always visible (removed opacity:0 hover-only rule)
- Artist all-songs page: added star + 3-dots to every row (same as top songs)
- Hero card: picks from full recent+frequent pool (was capped at first 5 = all frequent)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Scrobbling:
- Replace end-of-track scrobble with 12s timer approach
- Android: schedule on onTrackChanged, cancel on pause
- Web: schedule in playCurrent, cancel in togglePlay pause + onEnded
- Skip/new track resets the timer automatically (new song ID)
Artist top songs:
- Add star button and 3-dots context menu to every top song row
- Topsong grid expanded to 5 columns to fit action buttons
Settings — play count toggle:
- New "Bibliothek" section with toggle switch
- When on: shows play count in album/playlist song rows
- Artist page always shows play count regardless of toggle
- Persisted in ns_cfg localStorage
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Scrobble to Navidrome on auto-advance (Android) and track end (web)
so type=recent and type=frequent are accurate for the hero card
- Genre section: pill chips → grid cards with colored left bars
- Top 15 genres shown by default (sorted by song count), expand toggle
- Genre card: click → genre detail page with full song list
- Genre card: hover play button → shuffle-play without navigating
- Genre detail page reuses album-detail layout (back btn, stats, song list)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Home view:
- Add hero card (random pick from recent+frequent combined pool)
- Add genre browser chips (sorted by song count, tap = shuffle-play)
Android sync fix:
- Add currentId to getState() snapshot so JS can verify song identity
- onReady: reset stale localStorage queue when native song ID mismatches
- onTrackChanged: reject stale old-queue callbacks by ID verification
- onPlaybackStateChanged safety net: ID-guard prevents wrong-queue index corruption
- connectToService: call updateStateSnapshot() before onReady so getState() is never empty
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
.player-status-row had min-height:16px + margin-top:3px = 19px of permanent
invisible space, making player-info ~63px tall on desktop. Centered in 112px
this pushed the title to ~25px from top instead of ~34px.
Switched badges from opacity:0 (still in layout) to display:none, removed
min-height — row collapses to 0 when no badge is active so player-info
is only as tall as the visible title+album+artist rows (~44px), and
align-items:center on player-track places them at the true bar midpoint.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Desktop: player-track had align-self:center (from grid align-items:center),
collapsing it to 52px content height. align-items:center inside it then
centered against 52px, not the full 112px bar — text appeared at top.
align-self:stretch forces player-track to fill the bar height so internal
centering works correctly.
Mobile: padding:14px 12px was too symmetric — art filled the 46px content
area exactly and touched the progress strip. Changed to padding:6px 12px 14px
(6px top breathing room, 14px bottom for progress strip, ~54px content area).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
padding:0 12px 14px meant zero top padding, so align-items:center placed
content in the top 60px of the 74px bar — visually 7px above center.
Changed to padding:14px 12px (symmetric) so art+text center at exactly
37px, the visual midpoint of the bar. Progress strip stays absolute at bottom.
Artist color changed from hardcoded gold to var(--accent) in both the
bottom bar and Now Playing UI so it follows the active theme.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- line-height:1.2 on title and artist rows keeps the text block within
the 46px art circle so it no longer overflows above/below
- Artist name uses accent color (gold) in both the bottom bar and the
Now Playing UI, making it immediately distinguishable from the album
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Bottom bar: player-info is now a centered flex column so text block
aligns properly against the art circle
- Now playing: split artist·album line into album (above) + artist (below)
matching the bottom bar layout; removed np-album-sep reference
- Removed stale np-album-sep style.display call from player.js
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds a synchronous inline script that checks localStorage before first
paint and sets html.ns-authed, hiding #setup-screen via CSS immediately.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
-webkit-tap-highlight-color was only on 2 specific elements; every
div/song-item/card still showed a blue flash on tap in Android WebView.
*:focus{outline:none} replaces the button-only rule and covers clickable
divs as well.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- initProgressScrub: pass noTouch=true for the bottom mini-bar so touch
events are never registered on it; only mouse events remain (desktop-only).
The now-playing scrubber is unchanged and keeps full touch support.
- Export seekToMs(ms) from player.js; use it in the lyrics click handler
instead of S.audio.currentTime which has no effect when HAS_BRIDGE
(native ExoPlayer handles playback, not the HTML audio element).
- styles.css: add will-change:transform to .player and .np-overlay to keep
them on GPU compositor layers during the swipe gesture; tweak NP open
transition to cubic-bezier(.4,0,.2,1) for a snappier feel.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- button:focus{outline:none} — removes the blue tap-highlight box in WebView
- Playlist reorder: replaced always-on drag handles with explicit 'Neu anordnen'
mode. Handles only appear after tapping the button; a sticky Speichern/Abbrechen
bar appears above the list. Touch drag is now fully supported. Context-menu
(long-press) is blocked while reorder mode is active to prevent conflicts.
- styles.css: .pl-drag-handle always visible when pl-draggable (no hover needed)
- Edit modal footer: wrap buttons on small screens so Save doesn't overflow
- Edit modal overlay: remove backdrop-filter:blur — causes WebView compositor
glitch where 3/4 of the modal disappears after returning from background
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- fillRadioQueue: use addToQueue instead of setQueue so toggling radio mode
no longer resets position to 0 on the current song
- loadStarred: pass noArtistLink/noAlbumLink to prevent accidental navigation
taps on mobile (matches playlist behavior)
- styles.css: add pointer:coarse alongside hover:none so song-actions are
visible on Android WebView which may report hover:hover
- components.js: remove inline download button from song row; keep only star
and 3-dots (download stays accessible via context menu)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add ⋮ button to every song-item triggering the context menu (same as right-click)
- Show song-actions always visible on touch devices via @media (hover:none)
- Search results: songs now render as makeSongItem rows instead of cards
(artists/albums remain as horizontal card rows)
- Fix Android app opening system settings on every launch after notification
permission denial — now only redirects to settings once using notif_settings_shown flag
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Picker is only ~90px wide; single-line label+input+OK was too cramped.
Now stacks vertically so input gets full row width minus the OK button.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When absPlayItem() paused S.audio, the stale canplay listener from the
last playCurrent() call still had a matching _playGen value and would
call S.audio.play() — triggering absInterrupt() which immediately paused
the ABS audio. Fix: export cancelMusicAutoplay() that bumps _playGen
before pausing, invalidating any pending canplay/guard callbacks.
Also shrink OK button and widen time input in sleep timer.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Mobile needs the button since there's no keyboard Enter key in all cases.
Button is compact and styled to match the accent color.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Remove OK button and expand-on-click from sleep timer custom row
- Always show label + plain number input (no spinners, Enter to confirm)
- Update README with all current features (Spotify importer, ABS, lyrics, filters, etc.)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Drag handle appears on hover, moves items in DOM, syncs order to
songs array, and saves to Navidrome via createPlaylist 800ms after
last drop (debounced to avoid rapid API calls).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>