- 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>
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>
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>
- Bell icon in sidebar and mobile header with unread badge
- On download complete/error: saves notification to localStorage (survives reload)
- Playlist/album downloads: parses job log to list which tracks failed
- Panel toggles open with animation, click-outside closes it
- Each notification dismissable with X; "clear all" button
- Notifications capped at 100 entries in localStorage
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- 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>
- overflow-x:hidden prevents horizontal scroll indicator from
scale(1.2) transform on active line
- scrollbar-width:none + ::-webkit-scrollbar hide vertical scrollbar
- mask-image gradient fades lyrics at top/bottom edges so text
doesn't clip abruptly against the container border
- Active line scale reduced from 1.2 to 1.08 (less overflow risk)
- padding-top removed from lyrics-view (mask handles visual spacing)
- lyrics-plain gets padding-top:24px for better visual breathing room
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Prevents other lines from shifting when active line grows.
Adds subtle glow effect on active line for karaoke feel.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Hero height 220px mobile → 320px desktop (min-width: 769px)
- Larger artist name (46px) and more padding on desktop
- Overlay gradient now also darkens the right edge instead of fading to transparent
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>