Commit Graph
100 Commits
Author SHA1 Message Date
vicrodh 8eb055d06e fix: use 230px images for album cards instead of 600px
Prioritize image.small (230px) over image.large (600px) for all
AlbumCard artwork and queue track thumbnails. Hero/detail views
retain 600px via getQobuzImageForSize(image, 'large').
2026-03-09 19:51:31 -06:00
vicrodh 12fec1979f feat: re-enable all scene discovery caches
- Metadata cache (artist location/genres, 30-day TTL)
- Scene cache (full discovery response for first page, 30-day TTL)
- Qobuz validation cache (per-artist name match, 30-day TTL)

Second visit to same scene loads instantly from cache.
2026-03-09 19:15:14 -06:00
vicrodh 6fb141f2ff feat: inline progress bar for load-more in scene discovery
When loading more results, the button is replaced by a compact
progress bar with percentage, reusing the same backend progress
events as the initial load.
2026-03-09 17:35:51 -06:00
vicrodh faa68d1079 feat: real progress bar and improved loading state for scene discovery
Backend emits 'scene-discovery-progress' events with phase, progress
percentage, and detail. Frontend listens and shows a real progress bar
(0-40% MB search, 40-95% Qobuz validation, 100% done).

Loading state: hides header, cycles icons (Music/Globe/Network) at
1.5s intervals in a 96px pulse circle, shows progress bar with
percentage text.
2026-03-09 17:29:14 -06:00
vicrodh 3050999d60 fix: genre filters behind toggle button, restore load-more at 100
- Genre filter buttons now hidden behind a Filter icon toggle in
  the nav bar, with badge showing active filter count
- Revert to 100 results with load-more pagination (200 was too slow)
2026-03-09 17:21:12 -06:00
vicrodh d9258e0b15 fix: standardize back button margins across all views (ADR-004)
All text-based .back-btn now use margin-top: 24px, margin-bottom: 24px,
color: var(--text-muted), padding: 0. Fixes inconsistent spacing when
navigating between views. Also change genre filter pills from pill
shape (border-radius: 16px) to rounded rectangle (8px).

13 views fixed + ADR-004 created.
2026-03-09 17:18:43 -06:00
vicrodh 75e07c77f0 fix: homologate scene view margins and remove load-more pagination
- Match back button margin-top/bottom (24px) with ArtistDetailView
- Add explicit padding-top/bottom: 0 to scene-view container
- Remove load-more pagination, load 200 artists at once
- Remove unused loadMore function and load-more CSS
2026-03-09 16:30:46 -06:00
vicrodh c790cff019 feat: add genre filter pills to scene discovery view
Extract unique genres from MB tags across all results and display
as clickable pills. Selecting genres filters artists client-side
(AND logic). Shows count ratio when filters active.
2026-03-09 16:27:32 -06:00
vicrodh da225499ef fix: pass known MBID from scene discovery to artist detail view
When navigating from scene discovery to artist detail, pass the
MBID we already have from MusicBrainz instead of resolving by
name. Fixes wrong metadata for homonymous artists (e.g. The
Warning MX vs The Warning US).

Also improve Qobuz validation to request 5 results and pick
the best match by albums_count for name collisions.
2026-03-09 16:21:19 -06:00
vicrodh 74b75c144d feat: filter overly broad genre tags from scene discovery queries
Tags like "latin", "rock", "pop", "electronic" return the entire
country's catalog as noise. These are now excluded from MB search
queries but kept for affinity scoring. If ALL genres are broad,
falls back to using them to avoid empty results.
2026-03-09 15:30:16 -06:00
vicrodh 2a82246f02 fix: scene view margins, flag size, jump-nav, and group dropdown
- Homologate margins with app-wide pattern (padding-left: 18px, padding-right: 8px)
- Flag size increased to 180px circular matching label pic dimensions
- Add alpha jump-nav sticky sidebar for grid view with grouping
- Replace simple group toggle with proper dropdown matching FavoritesView
2026-03-09 15:16:26 -06:00
vicrodh 277ac7a391 feat: rewrite scene discovery view to match Favorites Artists UX
- Country flag header from circle-flags CDN
- Client-side search filtering
- A-Z grouping toggle
- Grid/sidepanel view toggle with album browser
- Back button matching FavoritesView style
- Proper margins and layout matching existing views
- Scene label shows country name only
- Pass countryCode through location context for flag display
2026-03-09 15:04:33 -06:00
vicrodh eb199c9ba1 feat: add country_code to ArtistLocation, fix scene label
Store ISO 3166-1 alpha-2 country code (lowercase) in ArtistLocation
for flag display. Scene label now shows just country name instead of
"Country, City scene".
2026-03-09 14:15:05 -06:00
vicrodh e065af4d7e revert: show precise birth/founding location in sidebar
Restore "Born in: United Kingdom, Brixton" / "Founded in: United
Kingdom, Leyton" in the artist sidebar. The scene discovery search
uses country-level queries regardless, so the sidebar should show
the precise MB location data.
2026-03-09 14:08:07 -06:00
vicrodh 35b1626a7b simplify: search by country instead of subdivision in Lucene
MB Lucene is literal text match only - no hierarchy. Searching by
subdivision (England, California) misses most artists. Now search
directly by country: tag:"heavy metal" AND area:"United Kingdom".
Scoring handles regional relevance.
2026-03-09 14:06:51 -06:00
vicrodh 84bb4f387c feat: include country in Lucene area search for broader results
MB artists have beginarea as specific city (London, Birmingham) and
area as country (United Kingdom), never the subdivision (England).
Now the Lucene query includes the country: tag:"heavy metal" AND
(beginarea:"England" OR area:"England" OR area:"United Kingdom").
This finds all UK heavy metal artists instead of just the 9 that
literally have "England" as their area.
2026-03-09 14:01:43 -06:00
vicrodh 07961504f4 fix: load-more duplicates and stale metadata cache
- Add next_offset to LocationDiscoveryResponse for correct pagination
- Frontend uses MB-level offset instead of displayed artist count
- Frontend deduplicates by mbid when appending load-more results
- Stable sort by score desc + mbid asc for deterministic ordering
- Temporarily disable metadata cache (had stale display_name values)
2026-03-09 13:47:27 -06:00
vicrodh b20f5cd20e feat: show resolved subdivision in artist sidebar instead of birth city
Resolve city to top-level subdivision at metadata time so the artist
sidebar shows "United Kingdom, England" instead of "United Kingdom,
Brixton". Label changed from "Born in"/"Founded in" to "From" to
match the broader regional context of scene discovery.
2026-03-09 13:36:17 -06:00
vicrodh d6796fbe27 feat: walk UP to top-level subdivision for area resolution
Rewrite resolve_parent_subdivision to iteratively walk the hierarchy
until finding the subdivision whose parent is the country.
Brixton -> Lambeth -> Greater London -> England (under UK).
Los Angeles -> California (under US).
Max 5 hops to prevent infinite loops.

Also: bump per_genre_limit to 200, display limit to 50,
fix misleading log (showed original city instead of resolved name).
2026-03-09 13:32:07 -06:00
vicrodh 7aa707e7ee feat: smart area resolution for scene discovery
Resolve cities UP to subdivision level via MB area relations API:
- Leyton -> England, Los Angeles -> California, Brixton -> England
- Uses direction:"forward" to walk "part of" chain upward
- Two-level inline lookup for districts/boroughs (avoids recursive async)
- Bump per_genre_limit to 100 for broader coverage
2026-03-09 13:16:58 -06:00
vicrodh 9696b1d4f4 fix: pass city name separately for MB Lucene search, not compound display_name
Was searching beginarea:"United States, Los Angeles" which returns 0
results. Now passes just "Los Angeles" for the search query and builds
"United States, Los Angeles" display separately for the UI header.
2026-03-09 13:01:08 -06:00
vicrodh 694fd8dd9b feat: rewrite discovery to use genre+area Lucene search instead of blind browse
The browse API returns ALL artists from an area alphabetically with no
genre filtering. For LA that's 15K+ random artists. Now we search
tag:"thrash metal" AND beginarea:"Los Angeles" for each genre, giving
genre-relevant results directly from MusicBrainz.

Also adds dynamic loading messages that cycle through discovery steps
and temporarily disables all scene/validation caching for tuning.
2026-03-09 12:55:17 -06:00
vicrodh 82775ce63a feat: implement v2_discover_artists_by_location pipeline
Full scene discovery pipeline:
1. Resolve area MBID (if not provided) via MB area search
2. Check 30-day scene cache
3. Browse MB artists by area with tags
4. Score candidates with genre affinity algorithm
5. Validate top results against Qobuz catalog
6. Cache validation results individually (30-day TTL)
7. Cache full scene response for offset=0
2026-03-09 12:27:13 -06:00
vicrodh cc65fcc694 fix: artist_type comparison uses lowercase to match serde serialization
The Rust ArtistType enum uses serde(rename_all = "lowercase"), so
"Person" serializes as "person". Frontend was comparing against "Person"
causing all artists (including David Bowie) to show "Founded" instead
of "Born".
2026-03-09 12:18:14 -06:00
vicrodh 0f1595eba5 feat: add ArtistsByLocationView and wire scene discovery navigation
Create the artists-by-location view that displays scene discovery
results using VirtualizedFavoritesArtistGrid. Wire onLocationClick
from ArtistDetailView through +page.svelte to navigate to the new view.
2026-03-09 12:18:02 -06:00
vicrodh 4fc012e21c feat: add origin section to ArtistNetwork sidebar
Shows Founded/Born date and Founded in/Born in location from
MusicBrainz metadata. Location is a clickable link that will
navigate to the artistsByLocation scene discovery view.

Metadata fetched in parallel with relationships, cached 30 days.
Section hidden when MusicBrainz is disabled. Translations added
for en, es, de, fr.
2026-03-09 12:11:34 -06:00
vicrodh 3eb106493f feat: add v2_musicbrainz_get_artist_metadata command
Exposes artist location, life span, and affinity seeds to the
frontend. Caches results for 30 days. Reuses the existing
get_artist_with_relations API call, extracting area fields
that were previously ignored.
2026-03-09 12:07:17 -06:00
vicrodh 96ca640313 feat: add MusicBrainz location discovery backend foundation
- models.rs: Area, ArtistMetadata, ArtistLocation, LocationPrecision,
  AffinitySeeds, LocationCandidate, LocationDiscoveryResponse,
  ArtistBrowseResponse, AreaSearchResponse structs. Added area and
  begin_area fields to ArtistFullResponse and ArtistResult.

- client.rs: browse_artists_by_area (MB browse API by area MBID),
  search_area (resolve area name to MBID).

- cache.rs: mb_artist_metadata (30d), mb_scene_cache (30d),
  mb_qobuz_validation (30d) tables with get/set methods.

- genre_normalization.rs: normalize_genre, noisy tag filtering,
  extract_affinity_seeds, genre_summary. Covers rock, metal,
  electronic, hip-hop, jazz, and other genre families.

- location_discovery.rs: extract_metadata from ArtistFullResponse,
  resolve_location with city/state/country precision, country code
  to name mapping, affinity scoring, scene cache key builder,
  MB date formatting.
2026-03-09 12:04:51 -06:00
vicrodh d2430fa19f fix: migrate localStorage to user-scoped storage in views
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.
2026-03-09 11:22:34 -06:00
vicrodh fd3586cf70 refactor: replace setTimeout with tick() for DOM scroll query
handleViewArtistDiscography now uses await tick() instead of
setTimeout(100ms) to wait for the DOM update before scrolling
to the discography section.
2026-03-09 11:05:50 -06:00
vicrodh 620dc10a3a perf: batch queue-next calls into single IPC
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.
2026-03-09 11:02:18 -06:00
vicrodh 05e5b3f811 perf: replace JetBrains Mono with system monospace
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.
2026-03-09 10:59:03 -06:00
vicrodh 34b44f9ca8 perf: filter favoritesStore notifications by trackId
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.
2026-03-09 10:52:46 -06:00
vicrodh af7b72fde5 fix: add scrollable bottom padding to Favorites virtualized tabs
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.
2026-03-09 10:39:26 -06:00
vicrodh fe719a657d perf: self-host all fonts, remove Google Fonts CDN dependency
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.
2026-03-09 10:31:48 -06:00
vicrodh 4de2dea30c perf: remove permanent will-change: transform from virtual items
Removes will-change: transform from .virtual-item in all 4 virtualized
list components to avoid promoting 10-20 items to individual compositor
layers permanently.
2026-03-09 10:30:57 -06:00
vicrodh 3348108c40 perf: replace transition: all with specific properties (174 instances)
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
2026-03-09 10:30:47 -06:00
vicrodh 01e0974abc docs: add v1.1.19 release notes and update contributors
- TAG_DETAILS.md (GitHub release body)
- CHANGELOG_HIGHLIGHTS.md (website/compact)
- CHANGELOG_FULL.md (detailed changelog)
- Add @arminfelder to About modal contributors
- Remove stale BETA_TEST_CHECKLIST_1.1.15-rc-1.md
2026-03-09 00:46:02 -06:00
vicrodh 05f1a5ec13 chore: bump version to 1.1.19
- Cargo.toml, tauri.conf.json, package.json, snapcraft.yaml
- Regenerate Cargo.lock and package-lock.json
- Add metainfo release entry for 1.1.19
2026-03-09 00:35:42 -06:00
vicrodh 46a572a0e6 chore: clean up AUR packaging
- 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
2026-03-09 00:32:19 -06:00
vicrodh 26f20ceb3f fix: resolve tauri version mismatch and track Cargo.lock
- Update @tauri-apps/api from 2.9.1 to 2.10.1 (matches Rust crate 2.10.x)
- Update @tauri-apps/cli from 2.9.6 to 2.10.1
- Remove Cargo.lock from .gitignore (binary projects should track it)
- Fixes build errors for distro packagers (NixOS, etc.)

Closes #151
2026-03-09 00:23:49 -06:00
vicrodh 804a0fd6d5 feat: subtle corner vignettes using darkest album art color
- 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
2026-03-08 23:39:02 -06:00
vicrodh 21f70b958a feat: Comet visualizer adopts album art colors and fades on silence
- 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
2026-03-08 23:34:45 -06:00
vicrodh d6db593018 fix: Neon submenu positioning, width, and hover gap
- 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
2026-03-08 23:09:31 -06:00
vicrodh 5b1af6346e feat: amplify Comet visualizer music reactivity
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.
2026-03-08 23:03:57 -06:00
vicrodh 219609e528 fix: clean sidebar transition when switching between artists
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.
2026-03-08 22:51:54 -06:00
vicrodh a07ee71090 feat: tag-scoped thumbs down for discovery recommendations
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
2026-03-08 22:49:06 -06:00
vicrodh 9f709efdc6 fix: artist network sidebar UX and equalizer paused state
- 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
2026-03-08 22:40:29 -06:00
vicrodh e13fa48707 feat(immersive): show modal on performance auto-degrade with dismiss option
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.
2026-03-08 21:55:10 -06:00
vicrodh 017a081f7f feat(immersive): auto-degrade background on sustained low FPS
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.
2026-03-08 21:49:35 -06:00
vicrodh 776987856a fix: tray icon path for Flatpak and titlebar double-click maximize
- Fix Flatpak tray icon path (com.blitzfc.qbz, not com.blitzkriegfc.qbz)
- Fix titlebar double-click: prevent JS handler from firing on native
  drag regions, which caused double toggleMaximize (maximize then
  immediate restore)
- Improve tray click handlers to properly detect minimized state
2026-03-08 21:43:30 -06:00
vicrodh 572d23b935 feat: replace ListenBrainz co-listening with MusicBrainz tag-based discovery
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
2026-03-08 21:30:01 -06:00
vicrodh a029f30fa5 feat: show similarity percentage in discovery artists sidebar
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.
2026-03-08 15:47:33 -06:00
vicrodh cd0615350f refactor: switch discovery to ListenBrainz Labs similar-artists API
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.
2026-03-08 15:47:17 -06:00
vicrodh 501546fb55 feat: add ListenBrainz discovery pipeline for Artist Network sidebar
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.
2026-03-08 14:51:30 -06:00
vicrodh a2eabf08f1 fix: freeze equalizer animation when player is paused
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.
2026-03-08 13:24:12 -06:00
vicrodh 8c626c0e6a fix: poll output device name so it updates during playback
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.
2026-03-08 13:10:53 -06:00
vicrodh bdc24c5a2e fix: show configured device name when player has no active stream
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.
2026-03-08 13:04:51 -06:00
vicrodh 309c4b2cc2 fix: clear reco meta caches when image cache is cleared
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.
2026-03-08 12:56:35 -06:00
vicrodh 63b1161afe perf: optimize ML/reco module for home view loading
- 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
2026-03-08 12:52:52 -06:00
vicrodh 8a2c12ee41 perf: parallelize artist resolution and use small images for cards
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.
2026-03-08 12:41:00 -06:00
vicrodh f95620ba12 fix: apply home settings changes immediately without reload
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.
2026-03-08 12:28:38 -06:00
vicrodh 070589427b feat: apply image cache to all artist image components
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.
2026-03-08 12:20:26 -06:00
vicrodh 8379227a0e fix: hide image during cache resolution to show placeholder
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.
2026-03-08 10:57:23 -06:00
vicrodh 6b87554dbb feat: frontend image cache with size-aware loading and settings UI
- getQobuzImageForSize(): picks small (230px) for grids, large for hero
- cachedSrc Svelte action: resolves images through backend disk cache
- imageCacheService: in-memory URL map with dedup for pending requests
- AlbumCard uses cachedSrc action for artwork rendering
- Settings UI: Toggle for cache on/off, numeric input for max size (MB),
  stats display, clear button — uses existing Toggle and input styles
- Removed unused Artwork Thumbnails section (never showed data)
- i18n: added image cache keys to all 4 locales (en/es/de/fr)
2026-03-08 10:52:35 -06:00
vicrodh e8d6aa4f4f feat: add image cache backend with LRU eviction
- ImageCacheService: disk-based cache keyed by MD5 hash of URL
- LRU eviction by last-access time (not creation time)
- ImageCacheSettings: configurable max size (default 200MB), can disable
- v2 commands: get_cached_image, get/set settings, stats, clear cache
- Cache stored at ~/.cache/qbz/images/ with SQLite metadata
2026-03-08 10:37:42 -06:00
vicrodh 7cec1101d1 fix: make currentNavItemId reactive with $state()
Without $state(), Svelte 5 doesn't track changes to currentNavItemId,
so the scroll reset $effect never re-fires on same-view item changes.
2026-03-08 10:17:45 -06:00
vicrodh 3c783973b1 fix: reset scroll to top on forward navigation between same-view items
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.
2026-03-08 10:12:02 -06:00
vicrodh 150d80dfac feat: granular navigation history with per-item scroll position
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.
2026-03-08 10:05:45 -06:00
vicrodh c4b25b2b94 fix: remove unused .experimental-inline CSS selector 2026-03-08 09:49:08 -06:00
vicrodh 57702afc37 fix: respect force_dmabuf as full GPU opt-in for compositing too (#127)
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.
2026-03-08 09:43:57 -06:00
vicrodh 4a4a9a4213 fix: defensive graphics fixes for Flatpak Wayland blur stutter (#127)
- 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
2026-03-08 09:32:56 -06:00
vicrodh df37b2c15d fix: only re-categorize download group items, not other/compilation (#149)
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.
2026-03-07 23:07:10 -06:00
vicrodh 6bcfaa8f90 fix: label releases search bar grows from right, fixed nav height, homologate back button 2026-03-07 23:03:42 -06:00
vicrodh d9d3054921 ci: trigger APT repo update on release publish 2026-03-07 23:03:42 -06:00
vicrodh 5ae5543cda fix: remove position recall from session restore, always start from beginning
Position restore was unreliable (always showed 0:01). Session restore
now loads the track ready to play from start without seeking.
2026-03-07 23:03:28 -06:00
vicrodh 6baae44327 fix: map epSingle type and re-categorize items from download/other groups (#149)
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.
2026-03-07 23:03:20 -06:00
vicrodh 765287817b fix: backfill EPs & Singles when artist/page omits them (#149)
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.
2026-03-07 22:20:49 -06:00
vicrodh cffbce9faa fix: faster session restore and remember playback position
Move session restore to run immediately after playback preferences
load, before network-heavy initializations (favorites, offline
status, recommendation scores). This eliminates the multi-second
"No track playing" gap on slow storage.

Also restore the saved playback position visually and on first play
(seek to saved position, no auto-play).
2026-03-07 22:01:18 -06:00
vicrodh 6b67594842 docs: add APT repository install instructions to README 2026-03-06 16:25:54 -06:00
vicrodh 976fa201d5 docs: update README and link resolver comment for Spotify embed scraping
Remove Spotify API credential setup from README since playlist import
now uses embed scraping. Update resolve_via_odesli_and_search doc
comment to reflect the new Spotify data path.
2026-03-06 13:33:36 -06:00
vicrodh 727e5288e7 refactor(spotify): remove API dependency, use embed scraping only
Spotify client_credentials API access ends 2026-03-06. Remove all
API token/proxy code and the paginated fetch_playlist_with_token
function. Playlist imports now go straight to embed page scraping
(limited to ~50 tracks, no ISRC/album data).

Link resolver for Spotify tracks/albums also switched from API to
embed page scraping via new fetch_embed_metadata function.

Remove Spotify credentials from .env.example since they are no
longer needed.
2026-03-06 13:30:44 -06:00
vicrodh 9c841365f8 Revert "feat(theme): add System (Dark / Light) theme and rename System to Match Colors"
This reverts commit 82e358208a.
2026-03-06 12:46:32 -06:00
vicrodh 82e358208a feat(theme): add System (Dark / Light) theme and rename System to Match Colors
Add a new "System (Dark / Light)" theme option that toggles between
Dark and Light themes based on OS prefers-color-scheme, with a live
matchMedia listener for instant switching. Rename old "System" (auto
palette generation) to "Match Colors" for clarity.

Applies to main window, miniplayer, and bootstrap.

Closes #148
2026-03-06 11:27:14 -06:00
vicrodh 786ce883ac fix(library): extract track/disc number from file tags during backfill import
insert_qobuz_cached_track_direct was hardcoding track_number to 0,
causing all imported tracks to show wrong numbers. Now accepts
track_number and disc_number params, and both callers (backfill
downloads and offline cache sync) extract metadata from the audio
file via MetadataExtractor before inserting.

Also fix LocalLibraryView to use || instead of ?? for track_number
fallback, so 0 correctly falls back to index-based numbering.

Closes #147
2026-03-06 11:08:32 -06:00
vicrodh 36d5ff65b7 fix(search): add right-click context menu to search result tracks
Wire up oncontextmenu handlers to track rows in SearchView so
TrackMenu opens on right-click, matching behavior of other views.
2026-03-06 09:02:15 -06:00
vicrodh 5b9f5a75c2 feat(ui): add explicit content badge across entire app
Display parental_warning badge (E icon) next to track titles in all
views: TrackRow, QueuePanel, NowPlayingBar, ImmersivePlayer with all
13 visualizer panels, MiniPlayer surfaces, and AlbumDetailView.

Propagate parental_warning field through the full data chain from
Rust backend (qbz-models, queue, commands_v2, session_store, API
server) to frontend stores, adapters, and UI components. Badge uses
CSS mask technique with explicit.svg for theme compatibility.
2026-03-06 08:48:51 -06:00
vicrodh 6685566091 feat(label): add group-by-artist toggle and performance improvements
Add artist grouping option for Label Releases view and remove
expensive loadAllAlbums() call. Use v2_get_label_page for richer
label image data. Add groupByArtist i18n keys to all 4 locales.
2026-03-06 08:48:36 -06:00
vicrodh 4e6a52e453 feat(label): redesign Label Releases view with logo, sorting, and filters
- Replace generic icon with circular label logo (matches LabelView)
- Fix double close button in search: single X that clears and closes
- Add sort options: newest, oldest, title A-Z/Z-A, artist A-Z
- Add Hi-Res filter toggle
- Load all albums automatically when sorting/filtering
- i18n: add labelReleases keys to all 4 locales
- Search bar now replaces title area instead of floating separately

API analysis: Qobuz label endpoints have no server-side sort/filter
params, so all sorting and filtering is done client-side after
paginated fetch.
2026-03-05 14:33:42 -06:00
vicrodh 97f42f4fea fix(settings): remove gapless restrictions for DAC Passthrough and ALSA Direct
Gapless now works on all backends, so the UI constraints that disabled
it for DAC Passthrough and ALSA Direct are removed. Only streaming-only
mode still disables gapless (no cache available). Removed experimental
badge. Cleaned up unused i18n keys.
2026-03-05 12:20:15 -06:00
vicrodh 01fc32e611 feat(audio): enable gapless playback on ALSA Direct and default ON
ALSA Direct playback thread now supports gapless via mpsc channel:
when current source ends, it checks for a queued next source and
transitions seamlessly without draining the PCM buffer.

Format mismatch still blocks gapless (bit-perfect has priority).
Gapless now defaults to enabled for all backends.
2026-03-05 11:45:32 -06:00
vicrodh f1e2c99b5b fix(audio): hot-reload gapless and normalization settings to player
v2_set_audio_gapless_enabled, v2_set_audio_normalization_enabled, and
v2_set_audio_normalization_target now call player.reload_settings()
after writing to SQLite, so changes take effect immediately without
requiring an app restart.
2026-03-05 11:19:50 -06:00
vicrodh 5fae14d68d fix(audio): stop updating live gain during refinement passes
Only write to gain atomic on initial measurement. Refinements now
update the cache only, preventing audible volume changes within a
single track. Inter-track normalization still works via cached values.
2026-03-05 11:16:05 -06:00
vicrodh ec6c4c56ac fix(lastfm): use user-scoped storage for session restore on startup
bootstrap.ts used raw localStorage.getItem() while settings saved with
user-scoped setUserItem(), causing session key mismatch. Closes #143
2026-03-05 11:14:42 -06:00
vicrodh 87321a0ea6 fix(library): detect qobuz_purchase source on scan and clean stale downloads
insert_track() now checks downloaded_purchases table to set source.
get_downloaded_purchase_track_ids() verifies file existence and
auto-removes stale entries. Closes #115
2026-03-05 11:13:59 -06:00
vicrodh fa747ecf8b feat(library): add qobuz_purchase source badge with gold Qobuz icon
Distinguishes purchased downloads from offline cache and regular
library items with a gold-tinted Qobuz logo badge on album cards.
2026-03-05 11:13:52 -06:00
vicrodh 43df8a40e4 fix(purchases): restructure download paths to Artist/Album [FORMAT][Quality]/track
Embeds quality in album folder name instead of subfolder, so each
quality variant appears as a separate album in the local library.
Adds download error toast and fixes format labels to bracket notation.
Closes #116
2026-03-05 11:12:39 -06:00
vicrodh 3c50c1c14e feat(immersive): replace Tunnel visualizer icon with cube SVG 2026-03-05 11:12:04 -06:00
vicrodh 90018c6518 chore: remove AUR git and source workflow files
Keep only release-aur.yml (qbz-bin). The git and source
PKGBUILD variants don't need CI workflows.
2026-03-04 20:24:16 -06:00
vicrodh 955f5edd05 fix(svelte): resolve all remaining a11y and real warnings
Key discovery: Svelte 5 requires commas between svelte-ignore codes,
not spaces. Fixed separator in all multi-code ignore comments.

Additional fixes across 36 files:
- TrackMenu/AlbumMenu: add role="menu" and ignore comments to menus
- LocalLibraryTagEditorModal: link labels to inputs with for/id
- TrackReplacementModal/DACSetupWizard: fix dialog a11y
- BookletViewer: fix reactivity ($state for bookletLoaded)
- StackIcon/SearchPlaylistCard/QobuzPlaylistCard/FavoritePlaylistCard:
  fix state_referenced_locally with $derived()
- CoverflowPanel/HomeSettingsModal/FavoritesEditModal: fix reactivity
- ImmersiveHeader/FolderEditModal: replace deprecated svelte:component
- Toggle: add aria-label prop
- Various modals: add tabindex="-1" and role to dialogs
- Dropdown/DeviceDropdown: add proper listbox roles

Build output: 0 Svelte warnings (down from ~200)
2026-03-04 20:20:40 -06:00