ArtistDetailView sort preferences and PlaylistDetailView copied
playlists now use getUserItem/setUserItem for per-user scoping.
Added migrateLocalStorageV2 to handle qbz_ prefixed keys that
the original migration missed (only covered qbz- prefix). Runs
once per user independently from v1 migration.
Replace per-track loops in queueAlbumNextById,
queuePlaylistNextById, and handleAddAlbumToQueueNext with a
single addTracksToQueueNext() call that sends all tracks in one
invoke to v2_add_tracks_to_queue_next. Backend already reverses
order internally.
Use Courier New/system monospace for --font-mono instead of
bundling JetBrains Mono (270KB). Only used for log output
and duration displays where a custom font adds no value.
TrackRow instances now subscribe with their trackId, so toggling
one track's favorite only fires that row's callback instead of
all ~25 visible rows. Global listeners (FavoritesView, QueuePanel,
etc.) still receive all notifications.
Add 80px padding-bottom inside the virtual scroll containers for
tracks, albums, and artists tabs. This is scrollable space (not fixed)
that prevents the navigate-to-top button from covering the last item.
Remove @import for fonts.googleapis.com. Self-host JetBrains Mono,
Oswald, and LINE Seed JP with @font-face declarations. App now works
fully offline without external font requests.
Removes will-change: transform from .virtual-item in all 4 virtualized
list components to avoid promoting 10-20 items to individual compositor
layers permanently.
Replace transition: all across 63 files with explicit property lists
(color, background-color, border-color, opacity). Special cases:
- NowPlayingBar control-btn: includes transform for :active scale
- CoverflowPanel: transform + opacity for 3D carousel
- ImmersiveHeader: max-width + opacity for expand animation
- Remove aur-source and aur-git PKGBUILDs (non-functional, unmaintained)
- Only qbz-bin (prebuilt binary) is maintained on AUR
- Update maintainer email in aur/PKGBUILD
- Extract darkest saturated pixel from artwork (clamped to very dark)
- Render radial gradients at all 4 corners with source-over blending
- Bottom corners slightly stronger for track info text readability
- Bass-driven radius pulse and per-corner position drift for organic feel
- Dark color lerps smoothly on track change like the main palette
- Extract dominant hues from album artwork via canvas sampling
- Replace all hardcoded hue values with palette-derived colors
- Smooth palette transitions when track changes (lerp on hue circle)
- Add time-based mutation for continuous color evolution
- Wisps, rings, and clouds fade to near-invisible when silent
- Black hole shrinks significantly when no audio energy
- Remove shared dropdownFadeIn from submenu (caused translateX jump)
- Add dedicated submenuFadeIn animation (slide from left)
- Anchor submenu at bottom instead of top (no position jump)
- Reduce gap to 2px and add invisible hover bridge
- Match submenu width to parent dropdown width
Reduce frontend smoothing (0.72->0.52) for faster audio response.
Lower beat detection thresholds and cooldown for more frequent spawns.
Increase bass/high multipliers on wisp speed, width, alpha, tunnel ring
radius, ring stroke width, feedback zoom, and phase advance. Wisps now
visibly surge on beats, rings pulse with bass, and the whole scene
breathes with the music instead of appearing randomly animated.
Reset all sidebar data (relationships, discovery, MB state) immediately
on artist change to prevent stale content flash. Add subtle fade-in
animation on sidebar sections for smooth content appearance.
Add dismissal system for "You May Also Like" discovery artists. Dismissals
are scoped to the genre tag used for the search, so dismissing AC/DC from
electronic recommendations won't affect metal recommendations.
- New discovery_dismissals table in reco DB (tag + normalized artist name)
- v2_dismiss_discovery_artist command persists dismissal per tag
- Discovery pipeline filters dismissed artists for both primary and secondary tags
- Backend returns 8 results (frontend shows 6, keeps 2 reserves)
- Thumbs-down button appears on hover, instantly replaces with reserve
- Returns primaryTag in DiscoveryResponse for frontend dismiss context
- Sidebar opens by default with localStorage persistence
- Simplified header: "Artist Network" title + PanelRightClose icon
- Hide RELATIONSHIPS section when no data (no empty placeholder)
- Restore sidebar after queue/lyrics panel closes
- Clean up sidebar state on artist view destroy
- TrackRow: show track number instead of frozen bars when paused
Replace toast notification with a proper modal dialog when the
performance watchdog degrades background mode. Modal includes a
"Don't show again" checkbox that persists to localStorage.
Threshold: < 15 FPS sustained for 5 seconds (after 3s warmup).
User can always re-enable effects from Settings > Appearance.
Add performance watchdog to ImmersiveRenderer that monitors FPS after
a 3-second warmup period. If FPS stays below 15 for 5 consecutive
seconds, automatically degrades background mode (Full -> Lite -> Off),
persists the setting, and shows a toast notification.
ImmersiveBackground listens for the degradation event and switches
renderer in-place without requiring a full remount.
ListenBrainz similar-artists returned mainstream crossover artists (SOAD,
Led Zeppelin for Metallica) instead of genre-accurate results. Now uses
MusicBrainz tag search to find artists sharing the seed's primary genre tag
(e.g. "thrash metal" returns Megadeth, Slayer, Kreator, etc).
- Add search_artists_by_tag to MusicBrainz client
- Deterministic shuffle using seed MBID hash for variety across artists
- Secondary tag fallback when primary yields fewer than 5 results
- Rename label to "You May Also Like", limit results to 6
- Add Last.fm get_similar_artists method (unused, for future use)
- Add tags field to ArtistFullResponse model
- Tighten local history exclusion to play_count > 2
Display similarity score next to each discovery artist name. Update
DiscoveryArtist interface with similarityPercent field. Add i18n keys
for youMayAlsoLike section and sidebar layout improvements.
Replace lb-radio endpoint (popularity-based) with Labs similar-artists
POST endpoint that returns actual similarity scores. Add 85% threshold
filtering and expose similarityPercent field in DiscoveryArtist model.
Add v2_get_discovery_artists command that uses ListenBrainz lb-radio API
to find novel artist recommendations. Pipeline: fetch candidates from
ListenBrainz, filter out seed/similar/local-history artists, resolve on
Qobuz, filter blacklisted, return top 8 by affinity score.
Separate isActiveTrack (current track) from isPlaying (actively playing)
so the equalizer bars freeze via animation-play-state when paused instead
of always animating. Show Play icon on hover when paused, Pause when playing.
Also fix AlbumDetailView which was missing the isPlaybackActive check.
The device name was only read on mount and on hover, so it stayed
as "No device" until the user hovered the badges area. Now the
1-second poll also reads get_audio_output_status (cheap in-memory
read) alongside hardware status, keeping the device name current.
Fall back to settings.output_device when the player hasn't reported
a device yet (before first playback). Previously showed "No device"
even though a device was configured in audio settings. Also change
the final fallback from "No device" to "System Default" since no
configured device means the system default is being used.
When the user clears the image cache from settings, also clear
reco_album_meta, reco_track_meta, and reco_artist_meta tables.
This forces re-resolution from Tier 2/3 with the correct (small)
image URLs instead of keeping stale large (600px) URLs in Tier 1.
- Add composite indexes on reco_events for GROUP BY + ORDER BY queries
(event_type + album_id/track_id/artist_id + created_at DESC)
- Add composite index on reco_scores for scored lookups
(score_type + item_type + score DESC)
- Eliminate duplicate fallback queries in get_home_seeds_internal
by inlining the empty check into the scored branch
- Parallelize resolve_favorites with recent albums, tracks, and
artists (4-way tokio::try_join instead of 3 + sequential)
- Batch cache writes: collect all Tier 3 API results first, then
write to API cache and reco meta with single lock acquisitions
instead of locking per-item inside spawned tasks
Resolve albums, tracks, and artists concurrently with tokio::try_join
instead of sequentially. Artists were waiting behind album/track
resolution unnecessarily. Also change get_image() to prefer small
(230px) over large (600px) for card contexts, reducing download size.
Add loadHome({ showSkeletons: false }) to the settings subscription
callback so visibility toggles, reordering, and limit changes are
reflected in real-time instead of requiring a page reload.
Use cachedSrc action for artist images in SearchView, HomeView,
ArtistDetailView, VirtualizedFavoritesArtistGrid, and
VirtualizedFavoritesArtistList. Use size-aware image selection
(small instead of large) for grid/card contexts. Add opacity
transition for smooth placeholder-to-image loading.
Image is hidden (opacity 0) until the cached URL resolves, preventing
broken image icons. The disc placeholder shows through while loading.
Adds a subtle 150ms fade-in transition when the image appears.
When navigating from album(1) to album(2), the view type stays 'album'
so the scroll reset effect didn't trigger. Now tracks currentNavItemId
changes too, and explicitly scrolls to top for forward navigation while
preserving scroll restore on back/forward.
Navigation history now tracks itemId per entry (album, artist, playlist,
label, musician, purchase-album) so back/forward restores the exact page.
Scroll positions are saved per view+itemId key and restored on back/forward.
When user enables Force DMA-BUF in Developer Settings, skip the
NVIDIA+Wayland compositing disable. This setting signals "I want
full GPU acceleration" and should grant both DMA-BUF and compositing.
- Detect Flatpak sandbox at startup and log it
- In Flatpak on Wayland, unset DISPLAY to prevent WebKitGTK from
falling back to XWayland internally (causes CPU-GPU texture
round-trips that degrade CSS blur performance)
- Per-GPU Wayland paths: only disable compositing and DMA-BUF for
NVIDIA on Wayland. AMD/Intel get full GPU acceleration on native
Wayland (compositing enabled, DMA-BUF enabled)
- Change GitHub Releases Flatpak manifest from --socket=x11 to
--socket=fallback-x11 to match Flathub and prevent XWayland
on Wayland sessions
The "other" group contains podcast episodes with release_type "album"
that should stay in Others, not be moved to Albums. Only "download"
group items should be re-categorized since download is a distribution
channel, not a content classification.
The Qobuz artist/page API returns release groups with type "epSingle"
(not "ep" or "single"), and groups like "download" and "other" contain
mixed items (singles, albums) that should be re-categorized by each
item's individual release_type field.
The Qobuz artist/page endpoint sometimes excludes the EP/single
release group from its response. When this happens, fetch them
explicitly via get_releases_grid as a non-blocking backfill.