mirror of
https://github.com/kilyabin/psysonic.git
synced 2026-07-22 22:45:41 +00:00
ca502ad8336d2b1da97a3d276301db90828a3d31
10 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
d43a8c6691 |
fix(ui): square song-rail nav buttons (#982)
* fix(ui): square song-rail nav buttons to match other rails The song rail's prev/next (and reroll) buttons were circular while every other rail uses the square rounded-rect nav button. Align them. * docs: changelog for square song-rail nav buttons (#982) |
||
|
|
88df194808 |
fix(tracks): RC3 layout regressions + multi-artist links (#976)
* fix(tracks): RC3 layout regressions + multi-artist links - Restore vertical rhythm on the Tracks hub: the header/hero/rails/browse sections sat two wrapper divs below .tracks-page so its flex gap never reached them and they collapsed together. New .tracks-hub-stack re-applies the gap, fixing the tagline-touching-hero and Random-Pick-overlapping-hero spacing (the rail's nav buttons no longer ride into the box above). - Stop the sticky browse-table header going transparent on hover: its base background became opaque but the :hover rule still forced transparent, so rows bled through. Header now keeps its card background on hover. - Widen the Duration column (56px -> 72px; 56 -> 64 on mobile) so the "DURATION" header no longer clips/overruns. - Split multi-artist tracks into individually clickable artist links in both the "Track of the moment" hero and the browse list rows (OpenSubsonic artists[] with single-artist fallback), matching the album tracklist. * docs(changelog): Tracks RC3 spacing, Duration, header hover, multi-artist (#976) |
||
|
|
cc04a0c93d |
Distinct circular song cards with jump-to-album badge (#953)
* feat(tracks): distinct circular song cards with jump-to-album badge Single-track cards looked identical to album tiles, so clicking the body read as album behaviour even though it starts playback. Give them a round vinyl-style cover (square stays album-only) via a shared .cover-circle utility, and add a 'To album' badge under the artist that navigates to the track's album. Card click still plays; the badge is the explicit nav path. * i18n(tracks): add toAlbum label across 9 locales * docs(changelog): track-card redesign + to-album badge (#953) |
||
|
|
d3e5a6b704 |
feat: library browse navigation — restore filters, scroll, and search on back (#936)
* feat(albums): restore scroll position when returning from album detail Save in-page scroll and grid depth when opening an album from All Albums, then on browser back restore filters, preload enough rows, and apply scroll before revealing the grid to avoid a visible jump from the top. * feat(albums): smart back navigation and restore browse session on return Remember the originating route when opening album detail, restore All Albums filters/scroll on back (including explicit returnTo navigation), hide the grid until scroll is applied, and fix filters being cleared after albumBrowseRestore state is stripped from the location. * feat(search): restore Advanced Search session when returning from album Stash filters and results when leaving /search/advanced for album detail, then restore them on back navigation (POP or returnTo with advancedSearchRestore). * feat(search): restore Advanced Search album row scroll on return from album Save horizontal scrollLeft when opening an album from Advanced Search and reapply it via AlbumRow on return; keep main viewport at top. Add snapshot helpers and session stash fields; extend AlbumRow with restoreScrollLeft. * feat(search): restore Advanced Search session scroll and artist return path Save filters, main scroll, and album-row scroll when leaving to album or artist; restore without flash via hidden-until-ready. Add useNavigateToArtist, restoreMainViewportScroll helper, and AppShell scroll reset only on pathname change. * feat(search): speed up Advanced Search back restore and year-only queries Reveal the page right after sync scroll instead of blocking on full viewport and album-row restore. Retry local index without the ready gate during sync; use open-ended byYear params on network fallback, matching All Albums browse. * feat(search): restore Advanced Search artist row scroll on back Save leave snapshot when opening artist from ArtistCardLocal, persist artistRowScrollLeft in session stash, and keep row restore targets in refs so horizontal scroll survives finishLeaveRestoreUi like vertical scrollTop. * feat(nav): route mouse back on album/artist detail like UI back Trap history popstate when returnTo is set and call navigateAlbumDetailBack so browser/mouse back restores browse/search session the same way as the header button. * feat(artists): restore browse filters and scroll on back from artist detail Persist Artists page filters, view settings, and vertical scroll when opening an artist and returning via UI or mouse back, matching All Albums behavior. * feat(search): unify quick and advanced search; fix LiveSearch dismiss on Enter Serve /search and /search/advanced from one page with shared session restore and scroll snapshot. Reset live search overlay state when navigating to full search so the dropdown does not linger or reopen. * feat(tracks): unify with search session and restore scroll on back Route /tracks through AdvancedSearch with shared leave snapshot, song browse stash, and main-viewport scroll restore when returning from album or artist detail. Wait for hero/rails layout before applying scroll. * refactor(search): rename AdvancedSearch page to SearchBrowsePage The shared route shell serves /search, /search/advanced, and /tracks; rename the page component and refresh stale file references in comments. * feat(albums): restore New Releases and Random Albums on back from detail Unify album grid leave-restore with surface-scoped session stash, live scroll snapshot sync, and in-page scroll for Random Albums. Keep the same random batch when returning from album detail; Refresh fetches anew and scrolls up. * docs: add CHANGELOG and credits for PR #936 |
||
|
|
003b280a77 |
feat(enrichment): oximedia BPM/mood facts, mood search, and queue display (#863)
* feat(enrichment): oximedia BPM/mood facts, mood search, and queue UI Run client-side oximedia analysis after CPU seed and persist BPM, mood JSON, and searchable mood_tag facts. Add product mood groups (joy/sadness/dance/work/ romance) with Advanced Search filter on the local index, queue BPM/mood display, migration 008 mood_tag index, and refreshed licenses for oximedia crates. * fix(enrichment): keep mood_groups module comment in English * feat(search): virtual mood groups, anger filter, and Advanced Search UX Expand mood search via overlapping virtual groups (tag expansion only), add anger/Злость group, skip album/artist shortcuts for track-only filters, and simplify mood search UI (songs-only, hide type tabs). Fix CustomSelect spurious scrollbar on short option lists. * feat(analysis): unified track analysis plan and enqueue path Add TrackAnalysisPlan (waveform, LUFS, enrichment) with a single enqueue_track_analysis entry for all byte-backed triggers. Run enrichment when cache is full but library facts are missing; route playback, cache, and backfill through the planner. Fix browseTextSearch LocalSearchOpts tsc gap and remove obsolete read_seed_bytes_if_needed helper. * fix(analysis): wire playback dispatch, preload enrichment, and UI refresh Route stream, gapless, preload, and local-file playback through analysis_dispatch so BPM/mood enrichment runs when waveform/LUFS are already cached. Fix audio_preload cache-hit and hot-cache paths, emit preload-cancelled for retry, and add analysis:enrichment-updated plus content_cache_coverage key resolution. * fix(audio): preload local files from disk and stop analysis retry loop Seed hot/offline next tracks via LocalFilePlayback (512 MiB) instead of copying into the RAM preload slot. Keep bytePreloadingId set after preload-ready so progress ticks do not re-invoke audio_preload every second. * fix(enrichment): clippy, album bpm filter routing, and queue mood display Clippy-clean analysis_dispatch and engine imports; restrict track-derived album routing to mood_group/mood_tag only so bpm is skipped on album queries. Log enrichment plan errors with retry-all plan; filter queue mood labels to oximedia ids. * fix(enrichment): simplify mood_tag backfill branch in plan_track_enrichment Remove empty if-block; keep same behaviour when backfill fails and moods row exists. * docs: CHANGELOG and credits for track enrichment PR #863 * docs(credits): track enrichment PR #863 contributor line * chore(enrichment): clippy-clean plan branch and trim dead exports Collapse mood_tag backfill if for clippy; remove unused moodGroupById and OXIMEDIA_MOOD_LABELS re-exports; stop poll when server BPM is already known. * fix(enrichment): close R2/S1–S3 limits and Song Info BPM fallback Return TrackEnrichmentOutcome::Failed on oximedia errors so retries are not masked as complete; extract mood Advanced Search SQL, unify top-3 mood tag selection in mood_groups with TS invariant tests, and show measured BPM in Song Info when tag BPM is missing or zero. * fix(enrichment): restore offline coverage and show mood in Song Info Add unit tests for offline download cancel/clear registry after the analysis seed refactor dropped read_seed_bytes coverage; show localized mood labels in Song Info when library enrichment facts exist. * fix(enrichment): soft mood scoring and unblock offline cancel tests Replace oximedia quadrant happy/excited mapping with valence/arousal soft scores across all mood tags for display, storage, and backfill; fix offline cancel unit tests that deadlocked by calling clear while holding the global offline_cancel_flags mutex. * fix(enrichment): dedupe joy cluster and cap mood display at two labels Never show happy and excited together; pick one tag per V/A cluster, tighten oximedia recalibration, and limit queue/Song Info to two moods that pass a relative score floor. * fix(enrichment): disable oximedia mood labels in UI and search tags Oximedia 0.1.7 mood is a spectral energy heuristic, not independent mood weights; valence correlates with loud/bright audio and false-labels metal and lyrical tracks as happy. Hide queue/Song Info mood and stop writing mood_tag facts until a reliable detector lands; keep V/A/moods JSON stored. * fix(enrichment): disable oximedia mood analysis and add BPM advanced search Stop planning, running, and storing oximedia mood facts; purge accumulated mood rows via migration 009. Hide mood filters in Advanced Search, expose BPM range filter with dual-storage resolution, and show a BPM column in song results when that filter is active. * feat(search): analysis BPM priority, source tooltip, and filter UX Prefer analysis track_fact over file tags for BPM resolution; show source in list tooltips. Validate BPM range on blur, add clear button, fix double tooltip. * fix(enrichment): prefer analysis BPM in Song Info and queue tech row Show measured track_fact BPM before file tags until analysis completes; pick the highest-confidence analysis fact when several exist. |
||
|
|
cb4d331f99 |
fix(library): browse-all-tracks shares the Search song-list view (#854)
* fix(library): browse-all-tracks shares the Search song-list view (#841) "Browse all tracks" rendered virtualized, transform-positioned rows inside its own scroll box, so the sticky column header got painted over while scrolling. Extract the Search / Advanced-Search song-list chrome (sticky header + plain SongRows + IntersectionObserver sentinel paging) into a shared PagedSongList and route all three through it; Browse now flows in the page like the Search pages, so the header can no longer be overlapped. Trade-off: Browse-all drops its bespoke row virtualization to match the Search pages (DOM grows with scroll as they do); paging is unchanged. Also removes the duplicated sentinel/observer in SearchResults and AdvancedSearch. # Conflicts: # src/components/VirtualSongList.tsx # src/pages/SearchResults.tsx * docs(changelog): browse-all-tracks sticky header fix (#854) |
||
|
|
d7b23b3c08 |
fix(ui): stable play/enqueue hover on album rails and mainstage cards (#787)
* fix(ui): stable play/enqueue hover on album rails and mainstage cards Horizontal Home rails (Discover): drop content-visibility:auto and scroll-snap, pin controls to cover hover, dim overlay via background. Grids and song cards: pointer-events on overlays so WebKitGTK/Wayland GPU does not lose :hover. * chore: CHANGELOG and credits for PR #787 |
||
|
|
70c2fdfbf9 |
Linux: session-native GDK/WebKit mitigations and in-page browse scroll (#731)
* feat(linux): session GDK defaults, nvidia-quirk, optional x11-legacy wrap Ship PSYSONIC_ALLOW_NATIVE_GDK from Nix/AUR instead of pinning WEBKIT_DISABLE_* and GDK x11. Add flake psysonic-x11-legacy for the old wrap; alias gdk-session to psysonic. Startup uses webkit2gtk-nvidia-quirk and Wayland-aware compositing; refresh Help (a45) and nixos-install docs. * fix(linux): session GDK and nvidia-quirk only; drop wrapper env heuristics Remove PSYSONIC_ALLOW_NATIVE_GDK and devShell GDK/WEBKIT exports; stop synthesizing GDK/WebKit vars in main.rs. Update Nix/AUR wrappers, install docs, CHANGELOG, and help FAQ with practical user-facing workarounds. * fix(linux): X11-pinned GDK uses DMABUF quirk path, not Wayland explicit-sync When GDK_BACKEND is forced to x11 on a wayland user session, webkit2gtk-nvidia-quirk would still apply __NV_DISABLE_EXPLICIT_SYNC and gray out the webview. Map that case to WEBKIT_DISABLE_DMABUF_RENDERER like native X11. * fix(ui): stabilize WebKitGTK/Wayland hover paint for nav and media cards Sidebar nav links avoid transition:all and promote icons with translateZ(0). Artist rows and album/artist/song cards use compositing hints; card shadows and borders no longer interpolate so cover zoom can stay smooth without jitter. * fix(ui): isolate artist/album card text and cover paint on WebKitGTK Promote cover blocks with contain/paint and text stacks with translateZ(0); use artist-card-info on the artists grid for the same layout as other cards. * feat(artists): in-page overlay scroll and locked main viewport Move list/grid into an inner OverlayScrollArea, stop sticky toolbar from owning the route scroll, align the rail with the main panel edge, and skip the main-route overlay thumb when the viewport cannot scroll vertically. * feat(browse): extend in-page overlay scroll to more library routes Reuse the locked main viewport pattern from Artists for Albums, Composers, Lossless albums, and New releases; wire VirtualCardGrid and scroll chrome to the matching in-page viewport ids. * fix(linux): improve Wayland GPU compositing text clarity in WebKitGTK Use on-demand hardware acceleration on main and mini webviews when the session is Wayland and compositing stays on; gate subpixel body AA on the same conditions via new Tauri probes. Document PSYSONIC_SKIP_WAYLAND_FONT_TUNING for opt-out and changelog. * fix(rust): satisfy clippy needless_return in Linux webkit helpers * fix(linux): tune Wayland text rendering with HW policy env and CSS Allow PSYSONIC_WEBKIT_WAYLAND_HW_POLICY to select WebKit hardware acceleration policy (never/always vs default on-demand). Extend Wayland font CSS to #root with geometricPrecision and text-size-adjust on html. * feat(linux): Wayland text presets in settings, safe WebKit apply, CPU default Persist profile to app config; apply WebKit policy at startup/mini only to avoid WebKitGTK hangs on live toggles. UI + CSS preview stays live; default preset is sharp (CPU-friendly). * fix(linux): map Wayland sharp preset to OnDemand WebKit policy HardwareAccelerationPolicy::Never at startup broke main-viewport wheel scrolling on WebKitGTK+Wayland; sharp vs balanced remains a CSS AA path. Use PSYSONIC_WEBKIT_WAYLAND_HW_POLICY for a true Never policy. * fix(rust): gate Linux-only Wayland WebKit helpers for Windows builds Re-export startup helpers only under cfg(linux) and drop non-Linux stubs so Windows compiles without unused-import and dead-code warnings. * chore(release): CHANGELOG + credits for Linux session/WebKit work (PR #731) Consolidate scattered incremental changelog notes into two [1.47.0] entries with PR link; remove duplicate Linux blocks from [1.46.0] Fixed. Append settings credit line for cucadmuh. |
||
|
|
3b94368ffa |
fix(ui): visual consistency sweep — shapes, buttons, hero, header alignment (#745)
* fix(ui): square shape across badges, pills and non-player buttons zunoz on Discord flagged inconsistent shapes for play buttons, badges and pills across the app. Unify to var(--radius-sm) for non-player surfaces so the same visual indicator looks identical wherever it appears. Player Bar, Fullscreen Player and Mini Player keep their circular shape as part of the player family; toggle switches, sliders, search input, pagination dots and theme overrides are left alone. Covers: hero play + nav arrows, album-card details button, album header icon buttons, playlist suggestion play, album-row nav arrows; .badge (incl. New / album-detail), genre pill, np chip/tag/badge, np-dash toolbar badge, radio filter chip, radio card chip, mp album plays pill, settings search-result badge, alphabet filter buttons, download hint, mobile search chip, artist release-group count, artist external link, all Orbit session pills, device-sync count badge; ServersTab "Aktiv" badge, PlaylistCard loading badge, AlbumRow / ArtistRow "more" buttons. * fix(composers): collapse empty space between virtual rows The composer grid uses text-only tiles (~78 px intrinsic) but estimateRowHeightPx scaled with cell width like the image variants, clamped to a 200 px maximum. On normal viewports every virtual row reserved ~200 px while the actual card was ~78 px, leaving ~120 px of empty space below each row. Pin the composer variant to min === max so the rowHeight is a fixed 88 px regardless of cell width. * fix(ui): unify secondary action buttons on btn-surface Action rows on the Artist, Album, Tracks, Favorites and Most Played pages mixed btn-ghost (borderless), btn-surface (bordered) and bare .btn (no variant, picked up bordered look in light themes only). Result was per-page and per-theme inconsistency — secondary buttons sometimes had borders, sometimes not. Unify on btn-surface for all secondary actions so the same affordance looks identical across pages and the difference between themes is just border tone, not border presence. - Tracks hero: Enqueue and Reroll buttons - AlbumHeader: Shuffle, Enqueue, Star, Share, Bio, Download and the Offline-cache states - MostPlayed: sort toggle and compilations filter (now matches the Albums page header) * fix(hero): make pagination dots visible on light backdrops The pagination dots used `rgba(255, 255, 255, 0.35)` which disappears against white-dominant cover art and on light themes, even under the hero gradient overlay. zunoz on Discord reported the inactive dots as effectively invisible. Bump inactive dots to 85 % white with a dark outline + drop shadow so they read against any backdrop, and switch the active dot to the accent color so the highlight reads as colour, not just width. Also opaque-fill `.badge` (`var(--accent)` + `--ctp-crust` text) so the hero pills do not disappear against light cover art either — base class previously used `--accent-dim` which is too transparent for badges per the existing badge rule. * fix(tracks): align Browse-all-tracks header with rows The Tracks page header sat outside the scroll container while rows sat inside it, so the scrollbar gutter shrank only the rows and the last header column drifted right of its row data. With OpenDyslexic selected the wider glyphs pushed "Duration" past the viewport edge entirely; zunoz on Discord reported it. Move SongListHeader inside the scroll container with position: sticky so header and rows share the same width budget. Sticky keeps the header visible while scrolling as a side benefit. * test(cardGridLayout): pin composer variant to fixed row height Guards the fix that collapsed the empty space between Composers grid rows. Re-introducing the `cellWidthPx + extra` scaling for composer would silently bring back ~120 px of dead space per virtual row, so the test asserts the fixed 88 px output across a wide cellWidth range. Image variants (artist / album / playlist) get baseline assertions so the composer case is documented as the deliberate exception, not an oversight. * docs(changelog): UI consistency sweep (PR #745) |
||
|
|
e0ff596a02 |
refactor(styles): split tracks.css into per-section files (#659)
tracks.css (539 LOC) → 8 per-section files in src/styles/tracks/ + an index.css. Same mechanic as the theme/components/layout splits. Concatenating reproduces the original byte stream (+1 trailing newline). Generated via /tmp/split-tracks-css.mjs. |