Commit Graph

309 Commits

Author SHA1 Message Date
Psychotoxical 02a4c43f61 docs: add psysonic-bin AUR badge and early-development warning
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 13:41:51 +02:00
Psychotoxical c49f6af38b perf: reduce CPU usage and unify next-track buffering settings
- Throttle audio:progress from 100ms to 500ms; WaveformSeek and
  FsSeekbar use imperative DOM updates instead of React re-renders
- Fix all usePlayerStore() calls without selectors across pages and
  components (useShallow / individual selectors throughout)
- Remove filter:blur and transform:scale from Hero, AlbumDetail and
  FullscreenPlayer backgrounds — eliminated expensive software
  compositing layers on WebKitGTK
- Replace translate3d with 2D translate in FS mesh and portrait
  animations; remove will-change:transform from mesh blobs
- Move Hot Cache section from Storage tab to Audio tab; group Preload
  and Hot Cache under a shared 'Next Track Buffering' section with a
  mutual-exclusivity note and auto-disable logic
- Add 'off' toggle to Preload (replaces Off button with toggle switch);
  enabling either method now automatically disables the other

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 13:38:33 +02:00
Maxim Isaev 69c0c5a907 merge: integrate origin/main into feat/audiomuse-navidrome 2026-04-10 13:04:34 +03:00
Maxim Isaev 4de577eede feat(navidrome): Instant Mix probe, ping identity, and AudioMuse UX
Parse type and serverVersion from Subsonic ping; persist per-server identity and
run a background Instant Mix probe (random songs + getSimilarSongs) for
Navidrome 0.60+. Hide the AudioMuse server toggle when the probe returns no
similar tracks; clear prefs when the server is no longer eligible.

Artist pages fall back to Last.fm similar artists when AudioMuse is enabled but
the server returns none. Instant Mix failures set a per-server issue flag with a
settings warning and toast. Settings description links the official plugin repo
via i18n Trans.
2026-04-10 13:02:46 +03:00
Psychotoxical c9dfbcc19f chore(settings): reset uiScale to 1.0 on startup while scaling is disabled
Users who had previously set a custom scale are silently reset to 100%
on next launch so they are not stuck at a broken zoom level. The stored
value is cleared in fontStore so the slider starts at 100% once the
feature is re-enabled.

Also credits nisrael for the ICY / AzuraCast PR #146.

TODO: remove the reset effect and re-enable the slider in Settings.tsx
when UI scaling is properly reworked.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 11:17:43 +02:00
Maxim Isaev 36f3d42dbe feat(discovery): Navidrome AudioMuse-AI client integration and library scoping
Add per-server toggle for AudioMuse-style discovery: Instant Mix via
getSimilarSongs, server similar artists instead of Last.fm on artist pages,
and higher similar-artist count in Now Playing when enabled.

When browsing a single music folder, filter similar/top song results by
album ids from that scope (Navidrome does not apply musicFolderId to those
endpoints). Request larger similar batches under a narrow scope.

Keep radio-from-track as two blocks (shuffled top songs, then shuffled
similar-by-artist) so it differs from Instant Mix. Show Alpha badge beside
the setting. Add research/ to .gitignore.
2026-04-10 12:07:32 +03:00
Psychotoxical 49f7fe5f6e feat: add ICY metadata and AzuraCast radio streaming support (#146)
feat: add ICY metadata and AzuraCast radio streaming support
2026-04-10 11:05:59 +02:00
Psychotoxical 28943f1ecb chore(settings): disable UI scale slider pending rework
Interface scaling is temporarily disabled in the Settings UI
(opacity + pointer-events: none) with a note that it will return
in a future update.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 11:04:21 +02:00
Nils Israel 46cefb5712 feat: add ICY metadata and AzuraCast radio streaming support
Agent-Logs-Url: https://github.com/nisrael/psysonic/sessions/88faada5-28bb-446f-b53b-46a0efef387e

Co-authored-by: GitHub Copilot <198982749+copilot@users.noreply.github.com>
Signed-off-by: Nils Israel <nils@sxda.io>
2026-04-10 10:38:59 +02:00
Psychotoxical 74985fe331 fix(audio): fall back to track gain when album gain is missing
In album gain mode, tracks without albumGain tags received no
ReplayGain adjustment at all. Now falls back to trackGain before
defaulting to 0 dB — fixes inconsistent loudness across albums
where only some tracks have albumGain metadata.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 01:12:06 +02:00
Psychotoxical 4861d99cb1 fix(statistics): library-scoped genre stats, cached fetches, duration i18n
fix(statistics): library-scoped genre stats, cached fetches, duration i18n
2026-04-10 01:11:29 +02:00
Maxim Isaev d2592839b0 i18n(ru): use «Популярное» for most-played nav, home, and page title
«Чаще всего» read awkwardly; «Популярное» matches the play-count sense
without sounding like a grammar exercise.
2026-04-10 02:06:24 +03:00
Maxim Isaev bbeb2f661e merge: integrate origin/main into fix/statistics-i18n-small-fixes 2026-04-10 01:42:14 +03:00
Psychotoxical 5f0fb5dcbd feat(audio): auto-switch to new audio output device at runtime
Adds a background device-watcher that polls the OS default output device
every 3 s via CPAL. When the device changes (Bluetooth headphones connecting,
USB DAC plugging in, etc.) the stream is reopened on the new device, the old
Sink is dropped (it was bound to the now-closed OutputStream), and
audio:device-changed is emitted to the frontend.

Frontend handler (TauriEventBridge): if playing, restarts the current track
from the saved position; if paused, clears the warm-pause flag so the next
resume uses the cold path (audio_play + seek) which creates a new Sink on
the new device.

Fixes #143 (audio through speakers after connecting Bluetooth headphones).
Also covers the intermittently reported single-channel output after long idle,
which can be caused by the OS reconfiguring the audio device in the background.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 00:40:12 +02:00
Maxim Isaev 6f6cb0fd6b fix(statistics): cache Subsonic stat fetches and localize duration units
Add 7-minute TTL caches (same idea as rating prefetch) for overview
album strips, random-song format sample, and paginated library
aggregates; key by server and music folder.

Introduce formatHumanHoursMinutes with common.duration* strings in all
locales for Statistics and playlist duration labels.

Refresh RU/ZH statistics and nav wording; fix zh playtime label.
2026-04-10 01:39:08 +03:00
Psychotoxical 15dc970f53 fix(audio): restore msg binding in DecodeError arm, use SlidersVertical for EQ icon
- Revert _msg → msg in DecodeError match arm; the variable is used in the
  debug_assertions eprintln! block so the underscore prefix caused a compile error
- Replace SlidersHorizontal with SlidersVertical (lucide-react) in PlayerBar,
  LiveSearch, and AdvancedSearch so the EQ/filter icon shows vertical bars

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 00:28:12 +02:00
Maxim Isaev fc40d235d0 fix(statistics): scope genre insights to selected music library
getGenres() ignores musicFolderId. Derive genre counts from the same
paginated getAlbumList('newest') scan used for playtime and totals,
using each album's genre and songCount.
2026-04-10 01:18:44 +03:00
Psychotoxical f304589ea1 fix(audio): suppress unused variable warning in DecodeError match arm
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 00:15:55 +02:00
Psychotoxical 22f7de45e8 fix(audio): set User-Agent header, add debug fetch logging
Set psysonic/<version> as User-Agent on the audio reqwest::Client to
prevent reverse proxies (nginx, Caddy, Traefik) from blocking requests
with a 403. Add #[cfg(debug_assertions)] logging in fetch_data to show
the exact URL, status, content-type and server header — useful for
diagnosing proxy-related 403s reported by users.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
app-v1.34.7
2026-04-09 23:52:02 +02:00
Psychotoxical 05da369aad chore(aur): bump pkgver to 1.34.7
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
v1.34.7
2026-04-09 23:29:11 +02:00
Psychotoxical 9671f89a48 chore: bump version to 1.34.7, add changelog
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 23:28:54 +02:00
Psychotoxical 9567a94dea feat(windows): replace GDI taskbar icons with embedded .ico assets
Strips the legacy monochrome GDI drawing code and loads high-quality
icons from embedded .ico files via CreateIconFromResourceEx. Fixes
windows 0.58 import paths (Controls→Shell subclassing, TaskbarList CLSID)
and adds proper cleanup for all four HICONs on WM_NCDESTROY.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 23:14:21 +02:00
Psychotoxical 1ba8619a37 chore: remove preview-update debug button, add GDI features, add contributor
- Remove debug "Preview Update Modal" button from Settings/About
- Add Win32_Graphics/Win32_Graphics_Gdi features for taskbar GDI icons
- Add sorensiimSalling contributor credit for Russian translation (PR #140)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 22:30:23 +02:00
kilyabin 973b472c1f fix: not translated lyricsServer* string to RU locale (#140) 2026-04-09 22:24:03 +02:00
Psychotoxical 20bf93c344 feat(windows): taskbar thumbnail toolbar with GDI media icons
Implements ITaskbarList3::ThumbBarAddButtons for Prev/Play-Pause/Next
buttons in the Windows taskbar thumbnail preview. Icons are drawn at
runtime via GDI (no binary assets). WndProc subclass intercepts
THBN_CLICKED and emits the same media:* events as souvlaki/tray.
update_taskbar_icon command swaps Play↔Pause icon on state change.
Frontend syncs via playerStore subscribe alongside mpris_set_playback.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 22:12:35 +02:00
Psychotoxical fd834314ba fix(audio): VLC-style frame dropping for corrupt MP3s, silence logs in release
Replace the fixed DECODE_MAX_RETRIES (3) loop with a consecutive-error counter
that tolerates up to 100 bad frames before giving up — matching how VLC handles
files with a handful of invalid main_data offset frames. Frame-drop logs are
wrapped in #[cfg(debug_assertions)] so production builds stay silent.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 21:42:38 +02:00
Psychotoxical a78c0fe9ac fix: font switching, layout scaling, embedded lyrics, folder opening
- fix(fonts): update CSS var declarations to @fontsource-variable naming
  ('Inter Variable', 'Outfit Variable', etc.) so dynamic font switching works
- fix(layout): 100vh → 100% on .app-shell to fix Windows WebView2 playerbar drift;
  1fr → minmax(0,1fr) in all grid-template-rows + remove min-height: 720px to fix
  Linux playerbar disappearing at high zoom or small window sizes
- fix(updater): replace shell open() with Rust open_folder command to bypass
  shell:allow-open capability scope blocking local paths on Windows
- fix(lyrics): add get_embedded_lyrics Tauri command (id3 crate for MP3 SYLT/USLT,
  lofty for FLAC SYNCEDLYRICS/LYRICS); fix parseLrc regex for LRC without fractional
  seconds; fix SubsonicStructuredLyrics to accept both synced and issynced fields

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 16:52:27 +02:00
Psychotoxical 9c57d4f887 feat(updater): professional update modal with skip, changelog, and OS-aware downloader
Replaces the small corner toast with a centered modal that appears on
startup when a newer GitHub release is detected (4 s delay).

Features:
- Skip this Version: stores skipped tag in localStorage, reappears only
  for newer releases
- Collapsible changelog: renders GitHub release body as markdown accordion
- OS-aware download: Windows → .exe installer, macOS → .dmg (aarch64
  preferred), Linux Arch → AUR hint (yay/pacman), Linux other → .AppImage/.deb
- In-app downloader: Rust download_update command streams to ~/Downloads/,
  emits update:download:progress every 250 ms for a real-time progress bar
- Post-download: Show in Folder button opens Downloads dir via shell.open
- Buttons: Download Now / Skip this Version / Remind me Later

Rust: check_arch_linux() reads /etc/arch-release + /etc/os-release
platform.ts: adds IS_MACOS, IS_WINDOWS alongside existing IS_LINUX
Settings About: Preview Update Modal button for testing
Fixes: renderInline regex had nested capture group causing undefined entries
in split() result → TypeError → React crash → WebKit white-screen freeze

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 13:23:48 +02:00
Psychotoxical 5d067b1f8b fix(app): hide resize grips in native fullscreen on all platforms
Previously onResized only tracked fullscreen on Linux. Now all platforms
set isWindowFullscreen, and an initial check on mount catches windows
that start maximized/fullscreened. CSS: .app-shell[data-fullscreen] .resizer
{ display: none } added in layout.css (shipped with updater commit).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 13:23:48 +02:00
Psychotoxical 48d0145dc8 fix(albums): align year filter inputs to button height and font size
Input padding and font-size now match adjacent .btn elements so the
year filter row no longer has mixed heights.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 13:23:48 +02:00
Psychotoxical 0da92c2fa1 fix(radio): prevent macOS WKWebView crash + shuffle Artist Radio queue
- Remove currentTime from Zustand persist partialize: it caused 100ms
  localStorage writes that grew with the queue, crashing WKWebView SQLite
  after ~10 min of Artist Radio on macOS
- Trim old played radio tracks from queue (keep last 5) to cap localStorage
  payload size during proactive radio top-up in next()
- Add reconnect logic for internet radio stall events (max 5 retries)
- Shuffle initial Artist Radio queue via Fisher-Yates so positions 2+
  are drawn from similar-artist tracks, not predictable top-5 tracks

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 13:23:48 +02:00
Psychotoxical 4e3efa3814 feat: self-host fonts via @fontsource-variable, remove Google Fonts CDN
Replaces all Google Fonts CDN references (index.html preconnect/stylesheet
and theme.css @import) with local @fontsource-variable npm packages.
All 10 UI fonts now bundle as WOFF2 into dist/assets/ — app renders
correctly without any internet connection.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 13:23:48 +02:00
Psychotoxical 77085a544e chore(credits): add missing contributor PRs to Settings page
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 13:23:48 +02:00
Psychotoxical 8ffecb4b7c Merge pull request #138 from cucadmuh/fix/statistics-music-folder-totals
fix(statistics): scope album and song totals to selected music library
2026-04-09 12:48:02 +02:00
Maxim Isaev c569ff5f34 fix(statistics): scope album and song totals to selected music library
getGenres() is not musicFolder-scoped, so summing genre counts showed
global totals while other statistics respected the library filter.
Derive album and track counts from the same paginated getAlbumList
pass used for playtime, with the same 5000-album cap and ≥ prefix when
capped.
2026-04-09 00:59:16 +03:00
Psychotoxical d16a99a6f9 docs(help): add 11 new FAQ entries for undocumented features
Ratings (q37-q39): how to rate songs/albums/artists, click active star to
remove rating, Skip-to-1★ and rating filter for mixes. Folder Browser (q40).
Settings: Theme Scheduler (q41), UI Scale (q42), Seekbar styles (q43),
AutoEQ (q44), Replay Gain (q45), Hot Cache (q46). Offline: playlist
caching and toggle (q47). All 7 locales updated.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
app-v1.34.6
2026-04-08 22:52:36 +02:00
Psychotoxical 9b239892ef chore: bump version to 1.34.6, add changelog
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
v1.34.6
2026-04-08 22:36:59 +02:00
Psychotoxical ba670bd1e8 feat: fix UI freezes in ZIP and offline cache downloads
ZIP downloads (PlaylistDetail, Albums, NewReleases, RandomAlbums) now use
invoke('download_zip') via Rust streaming instead of fetch+blob+arrayBuffer,
eliminating JS heap saturation on large files. Progress shown in ZipDownloadOverlay.

Offline cache downloads (600+ songs) no longer freeze the UI: transient job
state moved to a separate non-persisted offlineJobStore, reducing localStorage
writes from ~1200 down to 2 for an entire download. Also adds playlist offline
toggle — clicking the cache button when already cached removes it from cache.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 22:33:23 +02:00
Psychotoxical c1e57b4c06 fix(home): recently added albums title links to /new-releases instead of /albums 2026-04-08 18:56:39 +02:00
Psychotoxical fbe68116cc chore(aur): bump pkgver to 1.34.5 app-v1.34.5 2026-04-08 18:05:26 +02:00
Psychotoxical dba0c26480 docs(changelog): add v1.34.5 release notes
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
v1.34.5
2026-04-08 18:04:03 +02:00
Psychotoxical 3643a78cd6 perf: drastically reduce background API requests to Navidrome (v1.34.5)
- NowPlaying polling: only active while dropdown is open + respects
  Page Visibility API — was firing every 10s unconditionally (~8.6k req/day)
- Connection check interval: 30s → 120s (4× reduction)
- Queue sync debounce: 1.5s → 5s (prevents burst on rapid skip)
- Rating prefetch: add 7-minute in-memory TTL cache for artist/album
  ratings — repeated random album loads no longer re-fetch known ratings

Fixes server log flooding reported by users behind reverse proxies (Traefik).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 18:04:03 +02:00
Psychotoxical 1e4b851e9e feat: disable native decorations on Linux, hide custom TitleBar for tiling WMs
feat: disable native decorations on Linux, hide custom TitleBar for t…
2026-04-08 17:49:38 +02:00
kilyabin 37799fb861 feat: disable native decorations on Linux, hide custom TitleBar for tiling WMs
On tiling window managers (Hyprland, Sway, i3, bspwm, AwesomeWM, Openbox, etc.)
     the window has no title bar at all — neither native nor custom. On stacking DEs
     (GNOME, KDE, XFCE) the custom TitleBar can be toggled in settings as before.

     Native decorations are disabled on all Linux at startup. The frontend checks
     is_tiling_wm() to decide whether to render the custom TitleBar:
     - DE (GNOME/KDE): custom TitleBar shown (user-toggleable in settings)
     - Tiling WM: no TitleBar at all, setting hidden from Settings page

     Detection is based on environment variables:
     - HYPRLAND_INSTANCE_SIGNATURE, SWAYSOCK, I3SOCK (direct compositor signatures)
     - XDG_CURRENT_DESKTOP check for known tiling WMs

     Changes:
     - Added is_tiling_wm_cmd() Tauri command for frontend detection
     - Native decorations disabled on all Linux at startup
     - TitleBar not rendered on tiling WMs
     - Custom TitleBar setting hidden in Settings for tiling WMs
2026-04-08 19:36:39 +04:00
Psychotoxical 099516121e perf(fullscreen): fix dynamic accent color delay via direct fetch + cache
- Bypass ImageCache 5-slot queue: fetch cover art directly, create blob URL
  for canvas extraction, revoke immediately after use
- Module-level cache (artKey → accent) avoids re-fetching within the same
  album — same-cover tracks get the color instantly
- Keep previous color visible on cache miss instead of flashing to theme color

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 16:13:48 +02:00
Psychotoxical 9047a44480 perf(fullscreen): extract dynamic accent from already-loaded cover blob
Previously a separate getCachedUrl call fetched the 300px cover art just
for color extraction, racing with the 500px fetch for display. Now reuses
resolvedCoverUrl directly — color appears as soon as the display image is
ready, with no redundant network request.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 15:56:18 +02:00
Psychotoxical 47fcade3b3 feat(settings): show hint in theme picker when scheduler is active
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 15:51:43 +02:00
Psychotoxical d832dfb253 fix(statistics): remove Top Rated Songs/Artists sections
The implementation was unreliable (depended on starred songs + session-only
overrides) so the sections are removed entirely. All PR#130 rating logic
(StarRating, setRating API calls, userRatingOverrides) is untouched.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 15:37:12 +02:00
Psychotoxical 041d946b58 feat(settings): 12-hour AM/PM time format for English locale in theme scheduler
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 15:23:46 +02:00
Psychotoxical 64d8b1cbd3 fix(titlebar): window drag, resize grips and mobile-mode grid for custom titlebar
- Add core:window:allow-start-dragging capability so data-tauri-drag-region
  actually works (was silently blocked without this permission)
- Add CSS resize grips (bottom-left + bottom-right) that replace the native
  GTK grip lost when decorations: false
- Add [data-mobile][data-titlebar] grid override so the titlebar renders
  correctly in narrow-window mode instead of being hidden

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 15:13:58 +02:00