Commit Graph
100 Commits
Author SHA1 Message Date
vicrodh d8bd93374f feat(search): use Qobuz API most_popular field directly
Replace heuristic-based most popular detection with Qobuz's actual
most_popular field from the catalog/search endpoint.

- Add CATALOG_SEARCH endpoint path
- Make app_id() and get_http() public on QobuzClient
- Add MostPopularItem enum with tagged serialization (artists/albums/tracks)
- Update search_all to use catalog/search and parse most_popular field
- Update SearchView template to use allResults.most_popular with new types
- Add MostPopularItem type to searchState store
2026-02-01 01:33:17 -06:00
vicrodh aa16a9276b feat(search): Most Popular can now show artist, album, or track
The Most Popular result in search now intelligently determines
the best match based on query:
- Exact name match: artist > album > track
- Starts with match: artist > album > track
- Fallback: first artist, then album, then track

Added track card display for when a track is the most popular result.
2026-02-01 01:13:06 -06:00
vicrodh d5cbd32fce feat(library): add folder search filter in settings 2026-02-01 01:07:42 -06:00
vicrodh c025e7b8ae fix(library): make entire folder row clickable to toggle checkbox 2026-02-01 01:06:12 -06:00
vicrodh a55c85348d fix(settings): simplify subscription display to inline text with separator 2026-02-01 01:04:20 -06:00
vicrodh 46d91af88f fix(settings): center account card content with symmetric padding 2026-02-01 01:02:37 -06:00
vicrodh d650670ef3 fix(settings): improve streaming-only copy and account card alignment
- Update "Streaming Only" description to be less technical:
  "Disables temporary cache. Not recommended without a fast connection.
  Offline library tracks always play first."
- Fix account card vertical centering with explicit align-self on
  avatar, info container, and logout button
2026-02-01 00:53:33 -06:00
vicrodh c2fcdcec32 feat(settings): add Streaming Only toggle to audio settings
Adds UI toggle for streaming_only mode that skips L1/L2 cache writes.
When enabled, tracks are streamed fresh each time but offline cache
still works for downloaded tracks (local-first principle).
2026-02-01 00:39:12 -06:00
vicrodh b4944aa527 feat(audio): add streaming-only mode backend
Add streaming_only setting that skips L1+L2 cache writes while still
respecting offline cache (local-first). When enabled:
- download_and_stream() skips final cache.insert()
- Standard download path skips cache.insert()
- Offline cache continues to work normally

This reduces storage usage for users who prefer pure streaming.
2026-02-01 00:37:26 -06:00
vicrodh eb9d9dbb15 fix: revert to hi-res-gray.svg (hi-res.svg has poor text contrast) 2026-02-01 00:16:36 -06:00
vicrodh 03cee3f9fc fix: add fixed-width icon container (24px) and use hi-res.svg instead of hi-res-gray.svg 2026-02-01 00:14:08 -06:00
vicrodh 8c7af66d05 fix: increase quality badge min-width to 136px for consistent sizing 2026-02-01 00:07:49 -06:00
vicrodh f8825d98dd fix: set fixed heights for quality badge (36px) and audio badges row (20px) to prevent size changes 2026-02-01 00:02:59 -06:00
vicrodh adc0742fdb fix: maintain consistent badge width by always reserving space for downgrade indicator 2026-01-31 23:58:47 -06:00
vicrodh eaf250383a fix: move loadStatus call to mouseenter handler to prevent re-render loop 2026-01-31 23:51:12 -06:00
vicrodh ae81b1c3c4 Fix quality setting and device name display issues (#34)
- Clear both L1 memory and L2 disk caches when quality setting changes
  This ensures cached tracks at wrong quality are removed
- Fix device name not showing in popup on first hover
  Now refreshes status on each hover instead of only when null
- Add quality downgrade indicator when stream quality is lower than
  track's original quality (shows yellow arrow with tooltip)
- Store original track quality values for comparison with actual stream
2026-01-31 23:46:02 -06:00
vicrodh 8b7e4dab27 feat: show actual stream quality in player UI
Issue #34 - Display actual stream quality, not track metadata

Backend changes:
- Add sample_rate and bit_depth to PlaybackEvent
- Add stream quality tracking to SharedState
- Extract bit_depth from FLAC/M4A headers in streaming path
- Player sets stream quality when decoding audio

Frontend changes:
- Update PlaybackEvent interface with new fields
- Update currentTrack with actual stream quality from backend

This allows the UI to show the actual quality being played (e.g., 44.1kHz
when streaming a 192kHz track at CD Quality) instead of the track's
maximum advertised quality.
2026-01-31 23:32:29 -06:00
vicrodh 38b7ea7aef fix: enforce streaming quality setting by clearing cache on change
Issue #34 - Max quality setting not respected

Changes:
- Remove 'Prefer Highest Available' toggle (was dead code, conflicted with quality dropdown)
- Clear playback cache (L1+L2) when streaming quality changes
- Show toast notification when cache is cleared
- Add description to streaming quality setting
- Update i18n for new messages (en/es)

This ensures the quality setting takes effect immediately, important for:
- Users with metered internet connections
- Users with hardware sample rate limitations (e.g., DACs limited to 96kHz)

The Qobuz API respects format_id and downsamples server-side, so this
change guarantees the correct quality is fetched for new streams.
2026-01-31 23:15:09 -06:00
vicrodh f83eed1076 debug: add quality logging to diagnose issue #34
- Log requested vs returned format_id and sample_rate in get_stream_url_with_fallback
- Log quality_str, parsed quality, and format_id in play_track and prefetch_track commands
- Add console.log in getStreamingQuality for frontend debugging

This will help diagnose why 192kHz is played despite lower quality settings.
2026-01-31 20:54:05 -06:00
vicrodh e1771db099 docs: update CONTRIBUTING.md to require PRs target pre-release
- Add branch workflow section explaining pre-release integration
- Clarify that all PRs must target pre-release, not main
- Update maintainer procedure for new workflow
- Add release procedure section
2026-01-31 20:08:03 -06:00
vicrodh 583bf8f774 Merge PR #35: Make release sort options on artist detail view sticky and global 2026-01-31 20:07:13 -06:00
vicrodh 38b92bb8d8 chore: update package-lock.json after reinstall 2026-01-31 17:17:23 -06:00
vicrodh 6e55e36652 fix: use proper i18n keys in TrackReplacementModal
Added playlist-specific keys for search button, cancel, loading,
and preview instead of generic common.* keys that didn't exist.
2026-01-31 17:05:46 -06:00
vicrodh 90f24ff122 fix: pass onFindReplacement to TrackMenu from TrackRow
Added missing onFindReplacement to TrackMenuActions interface and
pass it through to TrackMenu component.
2026-01-31 17:02:04 -06:00
vicrodh 2ffd9df133 feat: add "Find available version" option for unavailable tracks
- Add TrackReplacementModal to search for replacement tracks
- Add onFindReplacement action to TrackMenu context menu
- Show replacement option only for owned playlists with unavailable tracks
- Replacement searches by track title + artist
- Shows quality info (bit depth, sample rate) to help user choose
- Supports preview playback before confirming
- Replace old track with new one in playlist

Also fix tooltip for unavailable tracks to show a complete message
instead of "is no longer available" (now shows "Track no longer
available in Qobuz library")
2026-01-31 16:45:23 -06:00
vicrodh faefc68381 fix: maintain column alignment for unavailable tracks
Add placeholders for favorite and download columns when hidden to
prevent column misalignment in unavailable tracks.
2026-01-31 16:36:46 -06:00
vicrodh d46a08465c feat: unavailable track handling with icon in track number column
- Add isUnavailable prop to TrackRow to show AlertCircle instead of track number
- Show unavailable icon only for user's own playlists (not Qobuz official playlists)
- Gray out unavailable tracks in both owned and non-owned playlists
- Remove all interactions for unavailable tracks in non-owned playlists
- Keep only "remove from playlist" option for unavailable tracks in owned playlists
- Create unavailableTracksStore for persisting unavailable track IDs to localStorage
- Load unavailable tracks on app startup in bootstrap.ts
- Auto-mark tracks as unavailable when playback fails with TrackUnavailable error
2026-01-31 16:20:23 -06:00
vicrodh 503e86eeb4 feat: gray out unavailable tracks with info icon in playlist view
- Add streamable field to PlaylistTrack and DisplayTrack interfaces
- Add isTrackRemovedFromQobuz() check for tracks with streamable: false
- Show red AlertCircle icon for unavailable tracks
- Gray out and apply grayscale filter to unavailable track rows
- Limit menu actions to only 'Remove from Playlist' for removed tracks
- Hide favorite and download buttons for removed tracks
- Keep wrapper interactive for context menu access
2026-01-31 16:15:04 -06:00
vicrodh e68c3128b6 feat: auto-skip unavailable tracks with user-friendly error
Backend:
- Add TrackUnavailable error type for tracks removed from Qobuz
- Validate stream URL response - detect missing URL with restrictions
- Add SampleRestrictedByRightHolders to restriction check
- Return specific error when track is unavailable vs quality unavailable

Frontend:
- Detect track unavailable errors in playTrack()
- Show friendly toast: Track title is no longer available
- Auto-skip to next track in queue after 500ms delay
- Add i18n translations (en/es) for trackUnavailable message
2026-01-31 16:10:26 -06:00
vicrodh 3926209b0d fix(auth): persist ToS acceptance in Rust/SQLite backend
ToS acceptance was stored in localStorage which gets cleared on app
updates, causing users to re-login frequently. Now stores ToS state
in SQLite (~/.local/share/qbz/legal_settings.db) which survives
updates.

- Add legal_settings.rs with SQLite storage for ToS acceptance
- Update qobuzLegalStore.ts to use Rust invoke commands
- LoginView now loads ToS from Rust before auto-login check
- Migration from localStorage for existing users

Closes #31
2026-01-30 14:49:39 -06:00
vicrodh fe7816f6c6 feat(audio): add S/PDIF (iec958:) devices to bit-perfect category
Digital outputs like S/PDIF transmit audio as-is without DA/AD conversion,
making them bit-perfect by nature. Now iec958: devices get the BP badge.

Updated group label to "Bit-perfect (Hardware / Digital)" to reflect
both direct hardware access (hw:) and digital outputs (iec958:).
2026-01-30 11:55:31 -06:00
vicrodh 5b03af41bc feat(audio): add alsa-utils help modal with distro-specific install commands
- Add check_alsa_utils_installed and get_linux_distro Tauri commands
- Detect Linux distribution from /etc/os-release
- Show appropriate package manager command for each distro
- Add (?) help icon next to ALSA Direct device dropdown in Settings
- Modal explains why alsa-utils is needed for bit-perfect detection
- Updated PKGBUILDs to list alsa-utils as optdepend
2026-01-30 11:43:34 -06:00
vicrodh 2838b25738 Replace 'Downloading' with 'Caching' in logs 2026-01-30 11:37:55 -06:00
vicrodh f67b13e27e Add grouped device dropdown for PipeWire with USB/HDMI categorization
Backend changes:
- Add device_bus and is_hardware fields to AudioDevice
- Parse PipeWire Flags (HARDWARE) and device.bus property from pactl output

Frontend changes:
- DeviceDropdown now supports both ALSA and PipeWire backends
- ALSA grouping: Defaults, Bit-perfect, Plugin Hardware, Other
- PipeWire grouping: Defaults, USB Audio (BP capable), HDMI/DisplayPort, Other HW, Virtual
- BP badge shown for USB Audio devices in PipeWire mode
2026-01-30 11:18:09 -06:00
vicrodh 0ccdd9981f Add supported sample rates detection and display for ALSA devices
Backend changes:
- Add supported_sample_rates field to AudioDevice struct
- Detect common audio sample rates (44.1, 48, 88.2, 96, 176.4, 192, 352.8, 384 kHz)
- Use CPAL's supported_output_configs() to check rate support for hw: devices

Frontend changes:
- Display sample rates as subtitle in DeviceDropdown (e.g., "44.1, 48, 96, 192 kHz")
- Only shown for bit-perfect devices where detection is available
- Search not sensitive to sample rates field (per user request)
2026-01-30 11:11:05 -06:00
vicrodh 91fa7c7f5f Add grouped device dropdown for ALSA Direct audio output selection
- New DeviceDropdown component with grouped options:
  - Defaults (System Default, default ALSA)
  - Bit-perfect (Auto-detected) - hw:X,Y devices with BP badge
  - Plugin Hardware - plughw:X,Y devices
  - Other Outputs - remaining devices
- Only shows for ALSA Direct backend, other backends use regular dropdown
- Pure UI change, no backend modifications
2026-01-30 11:01:16 -06:00
vicrodh df8bdb7ac0 Add ticker animation for artist names and sorting to album sections in Favorites browse view
- Artist names in sidepanel now animate with ticker effect on hover when text overflows
- Each album section (Discography, EPs & Singles, Live Albums) now has a sort dropdown
- Sort options: Default, Newest, Oldest, A-Z, Z-A
- Use sorted arrays for rendering instead of raw grouped arrays
2026-01-30 10:17:06 -06:00
vicrodh 8840da39a5 feat(favorites): show Discography, EPs & Singles, and Live Albums in browse view
- Group albums by category: Discography, EPs & Singles, Live Albums
- Exclude tributes and compilations (others) from display
- Each section has its own header that scrolls with content
- Updated footer: "To view compilations and other content, go to..."
- All content scrolls together (sections + footer)
2026-01-30 09:53:31 -06:00
vicrodh bf836a6bfb fix(favorites): remove redundant artist count from sidepanel column 2026-01-30 09:10:21 -06:00
vicrodh efe0f7143b fix(favorites): full height layout and remove horizontal scrollbar
- Add no-outer-scroll class when sidepanel mode is active
- Set up proper flex container hierarchy for full height:
  - .favorites-view becomes flex column container
  - .content gets flex: 1 with min-height: 0
  - ViewTransition wrapper gets flex: 1 via :global selector
- Fix negative margins to match parent padding (was -32px, now -8px/-18px)
- Reduce artist column width to 240px (matches LocalLibrary)
- Fix album column right padding to 8px
2026-01-30 09:07:52 -06:00
vicrodh 93baa9f47c fix(favorites): artist column height and scroll container structure
- Add artist count header like LocalLibrary
- Remove sticky positioning from group headers (caused overlap)
- Restructure albums area with scroll wrapper containing both grid and footer
- Footer now scrolls with album grid (visible at bottom after scrolling)
- Match LocalLibrary CSS patterns for proper independent scrolling
2026-01-30 08:55:13 -06:00
vicrodh b7c4684f03 fix(favorites): independent scrolling and button style in browse view
- Fix toggle button to use control-btn icon-only style (matches Library)
- Add proper background/hover states to the toggle button
- Fix two-column layout for independent scrolling:
  - Artist list scrolls independently from albums grid
  - Added scroll optimization properties (overscroll-behavior, contain)
  - Adjusted padding and margins for edge-to-edge layout
- Increased album card grid size to 180px (matches LocalLibrary)
2026-01-30 08:45:34 -06:00
vicrodh 8341d2bb63 feat(favorites): add browse view for artists with Qobuz albums
Implements a two-column sidepanel view for Favorites > Artists:
- Left column shows artists grouped A-Z with sticky headers
- Right column shows selected artist's Discography albums
- Albums are filtered to show only studio albums (not EPs, Singles, Live)
- Proper AlbumCard with artwork, favorite button, and quality badge
- Footer link to navigate to full artist page for other album types
- Alpha index in toolbar for quick navigation
- Toggle button to switch between grid and browse views
- View mode persists to localStorage

Also exports categorizeAlbum from qobuzAdapters for reuse.
2026-01-30 08:40:08 -06:00
vicrodh 7b5cf5e0a6 feat(settings): add theme filter, collapsible sections, and compact account
- Add Kurosaki light theme (cream/gold color palette)
- Add theme type filter button (dark/light/all) to cycle through themes
- Make Offline Library and Storage sections collapsible with descriptions
- Compact Account section with inline layout and subscription badge
- Navigation items now use i18n translation keys for reactive labels
2026-01-30 08:40:01 -06:00
vicrodh 2e9bbf2558 fix(sidebar): move favorites popover outside aside to fix z-index
The popover appeared behind other elements when the sidebar was
collapsed because it was inside the .content div which has
overflow:hidden. Moving it outside the aside tag resolves this.
2026-01-30 08:39:54 -06:00
vicrodh 15c9b17222 fix(sidebar): add proper nav-item styles for Favorites inline layout 2026-01-30 00:32:38 -06:00
vicrodh 71d5a4c53a fix(sidebar): hybrid Favorites style like Home with expandable items
- Use nav-item style with heart icon (like Home)
- Add chevron button next to label for expand/collapse
- Show indented sub-items (Artists, Albums, Tracks) when expanded
- Collapsed sidebar shows heart icon with popover menu
2026-01-30 00:25:45 -06:00
vicrodh 5bb27b919f fix(sidebar): match Favorites section style with Playlists
- Restructure Favorites to use same layout as Playlists section
- Use section header with collapse button on the right
- Use NavigationItem components for sub-items
- Match padding, fonts, and hover states
2026-01-30 00:19:17 -06:00
vicrodh 442794fa81 fix(sidebar): button nesting and persist collapse state
- Change nested button to span with role="button" for favorites chevron
- Add localStorage persistence for collapse state of:
  - Favorites section (expanded/collapsed)
  - Playlists section (collapsed/expanded)
  - Local Library section (collapsed/expanded)
- Folder collapse state intentionally not persisted
2026-01-30 00:12:12 -06:00
vicrodh 75aab4edb5 feat(sidebar): add collapsible Favorites section
- Add chevron button to expand/collapse Favorites sub-items
- Show Artists, Tracks, Albums as nested items when expanded
- Respect user's tab order from favorites preferences
- Add popover menu for collapsed sidebar mode
- Use translations for all labels
2026-01-30 00:07:27 -06:00
vicrodh 0ef72c2499 remove debug logging for track metadata 2026-01-29 23:34:11 -06:00
vicrodh 9790e43b48 hide unimplemented playback settings, widen TrackInfoModal
- Hide Crossfade and Normalize Volume (not implemented in backend)
- TrackInfoModal: 560px -> 728px (30% wider)
2026-01-29 23:25:34 -06:00
vicrodh 822e42f484 fix(modals): use theme CSS variables instead of hardcoded colors
TrackInfoModal and AlbumCreditsModal now properly respect theme colors:
- background: var(--bg-secondary) instead of rgba(26, 26, 26, 0.95)
- border: var(--border-subtle) instead of rgba(255, 255, 255, 0.08)
- text colors: var(--text-muted) instead of #888888
2026-01-29 23:23:33 -06:00
vicrodh b412f6c448 hide gapless playback setting until properly implemented (issue #29) 2026-01-29 23:04:39 -06:00
vicrodh 10788f877f feat(tracks): add streamable field infrastructure for unavailable tracks
Adds streamable field throughout the stack to detect tracks that have
been removed from Qobuz but still appear in playlists/favorites:

Backend (Rust):
- QueueTrack: add streamable field with default true
- PersistedQueueTrack: add streamable for session persistence
- radio.rs: log warning when non-streamable track is encountered

Frontend:
- BackendQueueTrack: add streamable? field
- QobuzTrack, Track, PlaylistTrack types: add streamable
- qobuzAdapters.ts: include streamable in track conversions
- trackActions.ts: all queue builders now include streamable
- +page.svelte: debug logging includes streamable field

This prepares the infrastructure for graying out unavailable tracks
in the UI (to be implemented when we can reproduce the issue).

Refs: User report about "Failed to fetch audio" for removed tracks
2026-01-29 22:50:02 -06:00
vicrodh 7ce5b402c4 fix(player): reset player UI when queue ends
When the last track in the queue finishes playing, now properly:
- Stop playback via backend
- Clear current track (removes "now playing" indicator)
- Reset player bar state
2026-01-29 22:00:47 -06:00
vicrodh 12801eabed refactor(sort): improve sort dropdown UX with inline direction toggle
FavoritesView Albums:
- Change from combined sort modes to sortBy + sortDirection
- Click option to select, click again to toggle direction
- Show arrow indicator on selected option

PlaylistDetailView:
- Remove separate Ascending/Descending options
- Integrate direction toggle into each sortable option
- Default and Custom Order remain direction-insensitive
2026-01-29 21:52:27 -06:00
vicrodh 96b0d12bfe style(LocalLibrary): homogenize filter dropdown and artist alpha-index
- Reduce filter panel text sizes from 13px to 12px for consistency
- Update artist alpha-index to use same styling as albums/tracks tabs
- Replace boxed buttons with clean text-only alpha letters
2026-01-29 21:36:16 -06:00
vicrodh 154b39b6a8 refactor(ui): compact filter and sort buttons, two-column filter panel in LocalLibrary 2026-01-29 21:30:06 -06:00
vicrodh 16adbd4682 refactor(ui): move alpha-index inline in LocalLibrary albums and tracks tabs 2026-01-29 21:22:52 -06:00
vicrodh fcde0a90b3 refactor(ui): redesign Favorites header layout with inline alpha-index 2026-01-29 21:14:36 -06:00
vicrodh 0ca6d923a2 fix(ui): compact Favorites header, move alpha-index to horizontal position 2026-01-29 20:30:04 -06:00
vicrodh 6935aeb552 fix(ui): vertically center action buttons in Favorites 2026-01-29 20:18:07 -06:00
vicrodh c0fdfbc6a6 fix(ui): fix double scrollbar in Favorites tracks tab, replace Play All with circle buttons 2026-01-29 20:15:51 -06:00
vicrodh a401327ab3 fix(ui): remove unwanted fixed track-list-header from FavoritesView 2026-01-29 20:10:10 -06:00
vicrodh fae962d59b feat(ui): add ViewTransition to LocalLibraryView and all tabs
- Outer view slides down on initial mount (200ms, 12px)
- Each tab content (albums, artists, tracks) slides up on tab change
- Uses {#key activeTab} to re-trigger transition on tab switch
- Simple transition without spinner fadeout logic
2026-01-29 20:07:39 -06:00
vicrodh f910b222d3 fix(ui): add slide-down transition to spinner on tab change in FavoritesView
When switching tabs, the loading spinner now animates with slide-down
transition (200ms, 12px) using {#key activeTab} to re-trigger on tab change.
This completes the animation flow: spinner slides down -> fadeout -> content slides up
2026-01-29 20:02:08 -06:00
vicrodh df17f859e0 feat(ui): add ViewTransition to PlaylistDetail and PlaylistManager views
- PlaylistDetailView: outer slide-down (200ms), spinner fadeout, content slide-up
- PlaylistManagerView: outer slide-down (200ms), spinner fadeout, content slide-up
- Matches the FavoritesView transition pattern
2026-01-29 19:58:06 -06:00
vicrodh 4ce7694290 fix(ui): add initial slide-down transition to FavoritesView
Wrap entire FavoritesView in ViewTransition with direction="down" so the
initial view (header + spinner) slides down on first load.

Complete flow:
0. Initial view appears with slide-down transition (200ms, 12px)
1. Loading spinner shows while syncing
2. When sync completes, spinner fades out (200ms)
3. Content appears with slide-up transition (200ms, 12px)
2026-01-29 19:54:39 -06:00
vicrodh b5a437d0d0 feat(ui): add ViewTransition to Album and Favorites views
- Add ViewTransition wrapper to AlbumDetailView (200ms, 12px slide up)
- Add ViewTransition to FavoritesView content sections (tracks, albums, artists, playlists)
- Add spinner fadeout animation (200ms) before content transition in FavoritesView
- Both loading spinner and playlists loading spinner now fade out smoothly
2026-01-29 19:50:46 -06:00
vicrodh 4c606e029e feat(favorites): implement local SQLite persistence for favorites
This ensures favorites sync properly across all views (album detail,
continue listening, etc.) by using local persistence as the source
of truth for UI, with API calls for actual operations.

Backend (Rust):
- Add favorites_cache.rs module with SQLite tables:
  - favorite_tracks (track_id INTEGER PRIMARY KEY)
  - favorite_albums (album_id TEXT PRIMARY KEY)
  - favorite_artists (artist_id INTEGER PRIMARY KEY)
- Add Tauri commands for cache operations:
  - get_cached_favorite_* - read from local cache
  - cache_favorite_* / uncache_favorite_* - add/remove single items
  - sync_cached_favorite_* - bulk sync from API data
  - clear_favorites_cache - for logout

Frontend:
- Rewrite favoritesStore.ts to use persistence:
  - loadFavorites(): Load from cache first, then sync from API
  - toggleFavorite(): API call first → update cache on success
  - No optimistic updates - UI shows loading state until confirmed
- Rewrite albumFavoritesStore.ts with same pattern
- Create artistFavoritesStore.ts for artist favorites
- Update +page.svelte to load all favorites on login
- Update FavoritesView to sync cache when loading from API

Sync strategy:
- On login: Fetch from Qobuz API → sync to local cache
- On toggle: API call → on success → update local cache → notify UI
- FavoritesView reads from API and syncs local cache
- All other views read from local cache (instant UI)
2026-01-29 19:42:04 -06:00
vicrodh defd2f0fe1 fix(favorites): ensure favorites sync with Qobuz API and show loading state
Issues fixed:
- playbackService was bypassing the favorites store, causing UI desync
- Album favorites weren't loaded on login (only track favorites were)
- No visual feedback while favorite API call was in progress

Changes:
- Add toggling state tracking to favoritesStore and albumFavoritesStore
- Add isTrackToggling() and isAlbumToggling() exports
- Prevent double-toggle while API call is in progress
- Update TrackRow and AlbumCard to show pulse animation while toggling
- Update playbackService to use store's toggle (centralized API calls)
- Load both track and album favorites on login
2026-01-29 19:24:13 -06:00
vicrodh 4858faa696 fix(ui): adjust UserCard icon sizes
- Increase settings gear icon from 14px to 18px
- Increase QBZ logo from 28px to 30px
- Remove border-radius from logo (was clipping the icon)
2026-01-29 19:12:19 -06:00
vicrodh 8db47aaee0 fix(ui): remove flicker-causing effect and add view transition to Settings
- Remove problematic $effect that ran loadPlaybackPreferences() on every
  render, causing a state update loop and visual flicker
- The function is already called in onMount, so the duplicate was redundant
- Add ViewTransition wrapper for consistent subtle animation (200ms fade+slide)
2026-01-29 19:09:01 -06:00
vicrodh 65ffabbf1d feat(ui): navigate to search on 3rd char + add subtle view transition
- Only navigate to search page after 3 characters typed
- Sync still happens immediately from 1st character
- Remove auto-navigate on focus (let user type first)
- Add ViewTransition component for reusable subtle animations
- Apply 200ms fade+slide transition to SearchView

cc
2026-01-29 19:04:29 -06:00
vicrodh a13f153a63 feat(ui): convert sidebar search button to synced input field
- Replace search button with actual text input in sidebar
- Add X button to clear search when text is present
- Sync sidebar input 1:1 with SearchView input (bidirectional)
- Typing in sidebar navigates to search page and triggers search
- Clearing sidebar input resets search page to standby state
- Add subscribeSearchQuery and setSearchQuery to searchState store

cc
2026-01-29 18:52:06 -06:00
vicrodh 6a756a7aeb fix(ui): use fixed positioning to eliminate scroll flash
Redesigned dropdown architecture:
- Menu uses position:fixed instead of absolute
- Menu rendered outside dropdown container (sibling, not child)
- Position calculated in pixels before menu opens
- Completely removes menu from document flow

This eliminates the momentary scroll flash that occurred when
dropdowns opened and temporarily expanded the page.

cc
2026-01-29 17:34:47 -06:00
vicrodh 669e9dbf4a fix(ui): use dynamic item height for compact mode dropdowns
Account for 36px items in compact mode vs 40px in normal mode when
calculating menu max-height and options container height.

cc
2026-01-29 17:03:25 -06:00
vicrodh 5421bb9eb1 fix(ui): rewrite Dropdown with smart positioning and search
- Add search input when options > 5
- Implement smart positioning to dodge viewport edges
- Fixed height showing 4 items when searchable
- Add scroll snap for clean item display
- Recalculate position on scroll/resize

cc
2026-01-29 16:57:04 -06:00
vicrodh fb0ab88b51 fix: refresh theme palettes and names
cx
2026-01-29 16:33:45 -06:00
vicrodh 21b1950857 feat: add Mira theme and reorder list
cx
2026-01-29 13:57:23 -06:00
vicrodh 0056d74824 chore: update theme slugs
cx
2026-01-29 13:54:10 -06:00
vicrodh 7f9a580a8c feat: rename new theme labels
cx
2026-01-29 13:30:32 -06:00
vicrodh 56c61499d9 fix: move track header outside virtualized container
- Header now outside .track-sections.virtualized (like LocalLibraryView)
- Use calc() height for virtualized section to give explicit dimensions
- Removes complex flex/absolute positioning that was breaking layout
2026-01-29 12:05:46 -06:00
vicrodh c1e6bd1a92 fix: virtualized track list height using absolute positioning 2026-01-29 12:03:21 -06:00
vicrodh 3163a893c6 fix: track list layout in Favorites Tracks view
- Fix virtualized container not showing tracks
- Remove conflicting height: 100% properties
- Add overflow: hidden to prevent extra scrollbar
- Add flex-shrink: 0 to header to prevent compression
2026-01-29 11:58:47 -06:00
vicrodh cd84f15ee2 feat: add Album column and header to Favorites Tracks view
- Add track list header with columns: #, Title, Album, Duration,
  Quality, Favorite icon, Download icon
- Album column is hidden when grouping by album (redundant)
- Add getTrackAlbum and showAlbum props to VirtualizedTrackList
- Style matches PlaylistDetailView for consistency
2026-01-29 11:51:53 -06:00
vicrodh 19d84326b8 fix: enable resume for streaming tracks
Previously, streaming tracks could not be resumed after pause timeout
because current_audio_data was never set for streaming playback.

Changes:
- Store BufferedMediaSource in current_streaming_source for streaming tracks
- On resume, check if streaming source has complete data and use it
- Clear streaming source on Stop and when switching to non-streaming play
- Log buffered bytes when streaming not complete yet

This allows users to pause streaming tracks and resume them after the
download completes, instead of getting "no audio data available" error.
2026-01-29 11:23:58 -06:00
vicrodh 873895709a fix: dropdown positioning in Favorites view
- Add z-index: 1000 to dropdown-container to appear above sidebar
- Change dropdown alignment from right: 0 to left: 0 for natural
  left-to-right opening
- Affects all tabs: Albums, Tracks, Artists
2026-01-29 10:21:56 -06:00
vicrodh 7269642464 fix: dropdown z-index and volume persistence
- Fix Favorites Albums group dropdown appearing behind sidebar
  (z-index 10 -> 100)
- Persist volume level to localStorage between sessions
- Allow changing volume when nothing is playing (volume
  applies when playback starts)
2026-01-29 10:12:34 -06:00
vicrodh af55c9a0fa chore: update android icons in static folder (UserCard, AboutModal) 2026-01-29 08:57:03 -06:00
vicrodh 56faddf2dc chore: update app logo to v3
New logo design with vinyl/gear motif, replacing old GPT-generated logo.
Updated all icon sizes for Tauri, Windows Store, favicon, and static assets.
2026-01-29 01:22:05 -06:00
vicrodh e570caa115 fix(playlist): increase sort dropdown min-width to 200px 2026-01-28 23:02:16 -06:00
vicrodh a75addbb42 fix(playlist): increase sort dropdown min-width to 180px 2026-01-28 23:01:21 -06:00
vicrodh 84f8b5f8c9 fix(playlist): align sort dropdown caret to right edge 2026-01-28 23:00:35 -06:00
vicrodh 9e44dad677 fix(playlist): prevent text wrapping in sort dropdown 2026-01-28 22:59:44 -06:00
vicrodh f0fa6a1e26 fix(suggestions): prevent layout jump during animations with fixed height 2026-01-28 22:56:30 -06:00
vicrodh 48cdb2750f chore(suggestions): remove debug artist count text 2026-01-28 21:36:13 -06:00
vicrodh f1b0b85119 feat(suggestions): smooth animations for add/dismiss tracks
- Add fade/slide transitions when tracks are added or dismissed
- Show success state (checkmark + green highlight) before fade out
- Add track to local state without page reload
- Update sidebar counts via callbacks
- Disable buttons during adding animation
2026-01-28 21:28:26 -06:00
vicrodh 95fcb4ed4e feat(suggestions): adaptive artist selection and duplicate filtering
- Add extractAdaptiveArtists() for dynamic seed artist count based on playlist size
- Mix 60% top artists (coherence) + 40% random (discovery) for variety
- Filter duplicates by title+artist, not just track ID
- Catches same song from compilations, live albums, remasters, etc.
- Deduplicate within suggestion pool itself
2026-01-28 21:14:32 -06:00