Commit Graph

187 Commits

Author SHA1 Message Date
Psychotoxical da38b411b0 feat(ux): redesign genre filter as portal popover
Trigger button with count badge, portal-rendered popover with search
input and full scrollable checkbox list (no 60-item cap). Selected
genres sort to the top. Replaces the inline tagbox that ate header
space and cut off the alphabetical list.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 22:24:32 +02:00
Psychotoxical 66c0ecbc1f fix(windows): tray double-click flicker + GPU use when minimized
1. Tray double-click (reported by @cucadmuh's brother-in-law):
   Windows fires a Click event on *both* halves of a double-click, so
   our left-click handler toggled visibility twice — the window popped
   up and immediately vanished. Switch the Windows branch to the
   `TrayIconEvent::DoubleClick` variant (Windows-only in tray-icon);
   other platforms keep the Click-on-Up behaviour. Matches the standard
   Windows tray convention (Discord, Telegram, etc).

2. GPU use while minimized:
   WebView2 on Windows keeps compositing infinite CSS animations
   (mesh-aura-a/b, portrait-drift, eq-bounce, track-pulse, led-pulse …)
   even when the window is minimized — steady visible GPU load on
   systems that should be idle. App.tsx now toggles a
   `data-app-hidden="true"` attribute on <html> on `visibilitychange`,
   and a single CSS rule pauses every `animation` at once via
   `animation-play-state: paused !important`. Zero cost when visible,
   catches all current and future infinite animations without
   per-element listeners.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-18 20:20:24 +02:00
Psychotoxical a2f880da0d feat(device-sync): fixed cross-OS naming scheme + playlist folders
Replace the user-configurable filename template with a fixed scheme so
syncing the same library across Linux/Windows/macOS no longer re-downloads
files just because the template string differs by OS.

Track layout on the device:
  {AlbumArtist}/{Album}/{TrackNum:02d} - {Title}.{ext}
  Playlists/{PlaylistName}/{Index:02d} - {Artist} - {Title}.{ext}
  Playlists/{PlaylistName}/{PlaylistName}.m3u8

Playlist tracks go into a self-contained folder with a sibling-referencing
Extended M3U, instead of being scattered across the album tree with an
external .m3u8 — the stick stays tidy even for 50-artist playlists.

Rust (lib.rs):
- TrackSyncInfo: drop disc_number/year (not used in fixed schema), add
  album_artist, duration, playlist_name, playlist_index
- sanitize_path_component strengthens empty-result handling via new
  sanitize_or() which falls back to "Unknown Artist/Album/Title"
- build_track_path() dispatches on playlist context — playlist tracks
  get the "Playlists/{Name}/…" shape, album tracks the traditional tree
- albumArtist resolution: the server's albumArtist tag, falling back to
  the track artist (empty-string treated as missing)
- calculate_sync_payload: dedup key is now (source_id, track_id) instead
  of track_id alone, so a track appearing in both an album and a playlist
  ends up on the device in both locations; playlist context is embedded
  into the response JSON as _playlistName / _playlistIndex so the follow-
  up sync_batch_to_device call can route each track correctly
- write_playlist_m3u8: rewritten — writes into the playlist folder with
  sibling filenames instead of a top-level .m3u8 with ../relative paths
- New rename_device_files command: atomic renames (per-entry result,
  skip-if-exists, skip-if-source-missing) plus empty-dir cleanup. Used
  by the migration flow
- write_device_manifest: v2 format, drops filenameTemplate field
- Drop the `template` parameter from sync_track_to_device,
  compute_sync_paths, calculate_sync_payload, sync_batch_to_device

Frontend:
- DeviceSyncStore: drop filenameTemplate from state and persist
- DeviceSync.tsx: strip template editor UI (presets, token buttons, live
  preview); replace with a compact read-only schema info card
- trackToSyncInfo(track, url, playlistCtx?): optional playlist context
  parameter. Tracks coming back from calculate_sync_payload with embedded
  _playlistName/_playlistIndex fall through via the same parameter
- compute_sync_paths / write_playlist_m3u8 / delete paths now pass the
  playlist context per-source so status checks + deletions hit the right
  files (album tree vs playlist folder)
- Album-Artist fallback: frontend falls back to track artist when the
  server has no albumArtist tag (empty strings treated as missing) —
  "Unknown Artist" is only used as a last-resort placeholder
- New migration flow: "Reorganize existing files…" button opens a modal
  that reads the legacy filenameTemplate from the v1 manifest, computes
  per-track (old, new) rename pairs, detects collisions (two old files
  mapping onto one new path), and executes via rename_device_files.
  Playlist-only tracks are left for the next sync to re-download into
  the new playlist folder
- Small JS-side applyLegacyTemplate() helper: only used by the migration
  preview so we can diff old paths against the current files on disk
- CSS: device-sync-schema-section / -code / -hint, migrate-modal +
  summary + warning + result layout

i18n (en + de):
- Remove dead keys: filenameTemplate, templatePreview, templateHint,
  templatePresetStandard/MultiDisc/AltFolder, tokenSlashHint
- Add schemaLabel, schemaHint, migrateButton/Title/Tooltip/Loading/
  NothingToDo/NoTemplate/FilesToRename/Unchanged/Collisions/
  PreviewNote/Executing/Success/Failed/ShowErrors/Start

Other locales (fr/nl/zh/nb/ru/es) fall through to the English defaultValue
until translated in a follow-up pass.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-18 19:30:25 +02:00
Psychotoxical 77edfaa867 perf(fs-player): cut CPU under WebKitGTK software compositing
WebKitGTK on Linux runs with WEBKIT_DISABLE_COMPOSITING_MODE=1, so every
GPU-only effect is software-rasterised per frame. The fullscreen player
piled up large blur shadows, per-line scale transforms, oversized
radial-gradients with color-mix() and a 60 fps rAF spring on top — CPU
saturated and FPS dropped to ~10.

Linux-only via existing html.no-compositing class:
- Apple-style lyrics: drop transform: scale and 48 px / 32 px text-shadow
- Rail-style lyrics: drop 28 px text-shadow + scaleX
- Track title: 40 px glow → 6 px drop-shadow
- Album art wrap + play button: drop accent-coloured outer glows
- Mesh blobs: flatten 130 % radial-gradient + color-mix to solid #06060e
  and remove the 400 ms background transition
- Portrait wrap: drop translateZ(0) GPU-layer hint
- FS art: instant cover swap (no opacity crossfade)
- SpringScroller: replace rAF spring with native scrollTo({behavior:'smooth'})
- FsSeekbar: cache last applied values, skip identical DOM writes

Dynamic accent on title / seekbar / play button is preserved.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 01:06:04 +02:00
kilyabin cd1417b604 feat: Apple-Music-like lyrics view with saving old-style 2026-04-18 01:58:17 +04:00
Psychotoxical 34b4445c13 feat(lyrics): YouLyPlus karaoke + fix(macos): suppress mic prompt
Two independent user-facing fixes rolled together.

── Lyrics: YouLyPlus provider (issue #172) ──
Adds word-by-word synced (karaoke) lyrics as an alternative lyrics mode.
Backed by the public lyricsplus aggregator (Apple Music / Spotify /
Musixmatch / QQ Music) — no API keys on our side, subscription costs are
borne by the backend operator. Five mirrors are tried on network failure.

Settings → Lyrics now exposes a mode radio (Standard vs YouLyPlus) plus
a static-only toggle. YouLyPlus misses silently fall back to the existing
server + LRCLIB + Netease pipeline so obscure tracks still resolve. The
drag-to-reorder source list is hidden in YouLyPlus mode since the
external aggregator manages its own source priority.

Rendering: per-word spans on each line, active word highlighted with
accent-tinted glow. Subscribed imperatively via usePlayerStore.subscribe
so 500 ms progress ticks do not re-render the whole lyrics block. The
Fullscreen Player reuses the same pattern; the 5-line rail layout is
unchanged. white-space: pre on .fs-lyric-word preserves the trailing
spaces the API embeds in each syllabus token (flex context would
otherwise collapse them).

i18n: new keys in all 8 locales (de, en, fr, nl, nb, ru, es, zh).

── macOS mic-prompt suppression ──
Ships a vendored cpal 0.15.3 at patches/cpal-0.15.3/ wired via
[patch.crates-io]. The only change is in src/host/coreaudio/macos/mod.rs:
audio_unit_from_device now unconditionally uses IOType::DefaultOutput for
output streams instead of conditionally choosing HalOutput.

AUHAL (HalOutput) is classified as input-capable by macOS TCC and
triggers the microphone-permission dialog at first launch / after each
update even for playback-only apps. Previous attempts (removing
NSMicrophoneUsageDescription, setting com.apple.security.device.audio-input
false in Entitlements.plist) did not suppress the prompt because TCC
fires at AudioUnit instantiation, not at plist level. The upstream fix
in cpal PR #1070 / cpal 0.17 only helps when the pinned device equals
the system default; always-DefaultOutput covers all cases.

Tradeoff: per-device output selection is a no-op on macOS — the stream
always follows the system default. Settings.tsx surfaces this via
audioOutputDeviceMacNotice (hides the CustomSelect on macOS) and skips
audio_list_devices + device-watcher effects there. Matches the behaviour
of Apple Music / Spotify on macOS.

Also removes the now-obsolete com.apple.security.device.audio-input
entitlement (sandbox is disabled anyway, so it was ignored).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 21:30:31 +02:00
Psychotoxical 7db42d74ef feat: tracklist column reset, device sync cross-platform template fix, filename template builder, privacy policy
- Add "Reset to defaults" button to column picker in AlbumTrackList, PlaylistDetail, Favorites (all 8 locales)
- Fix device sync cross-OS status detection: store filenameTemplate in manifest, use it for path computation on import
- Redesign filename template UI: preset buttons (Standard/Multi-Disc/Alt. Folder), clickable token chips ({artist}, {album}, etc.), clear button
- Fix suggestions section in PlaylistDetail missing album column rendering
- Add PRIVACY.md documenting all third-party integrations (Last.fm, LRCLIB, Apple Music, Discord); link from README

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-16 19:47:41 +02:00
Psychotoxical d248a78acc fix(tracklist): revert overflow-x:visible regression from PR #188
.content-body has overflow-x:hidden — setting overflow-x:visible on
.tracklist would clip wide tables instead of scrolling them. Keep auto.
Also remove Spanish code comments (contributors are international).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 18:35:28 +02:00
Psychotoxical a4d8dd41fd Merge pull request #188 from kveld9/fix/tracklist-picker-overflow 2026-04-15 18:34:36 +02:00
Psychotoxical 7cd0eaf9e1 Merge pull request #190 from kveld9/feat/playlist-csv-import
feature: spotify CSV playlist import
2026-04-15 18:09:27 +02:00
kveld9 a44581e5d6 new feature: import spotify playlist with .csv 2026-04-15 11:19:31 -03:00
kveld9 eb061bd9de fix album tracklist column picker cutoff and scroll containment issues 2026-04-14 23:27:57 -03:00
Maxim Isaev c75297fcf6 feat(cli): completions, library/audio commands, server switcher
Embed bash and zsh completion scripts and add a `completions` subcommand.
Extend the player CLI (library, audio device, instant mix) and surface
`music_library` in snapshots. Add a shared active-server switcher in the
header and locales; instant mix can reseed the queue from CLI and UI.
2026-04-15 01:47:46 +03:00
Psychotoxical d34de09673 feat(device-sync): overhaul Device Sync page
- New two-panel layout with live album search (search3, 300ms debounce)
  and 10 random albums when search is empty — replaces full paginated load
- Pre-sync summary modal: shows files to add/delete, net change, available
  space; Proceed button disabled when space is insufficient
- calculate_sync_payload now filters already-synced tracks (path exists on
  device) so add_bytes/add_count reflect the true delta
- Space check accounts for pending deletions: addBytes > availableBytes + delBytes
- Separate deviceSyncJobStore for ephemeral job progress state
- Removable drive detection + auto-poll every 5 s via sysinfo
- Desired-state diff: de-selecting a synced source stages it for deletion
  instead of silently removing it
- Status badges (Synced / Pending / Deletion) with matching row highlights
- Live-Search badge () and Zufallsalben section label (⇌) in album browser
- Status summary row height aligned with search field (52 px)
- i18n: all new keys added to all 8 locales (en/de/fr/nl/nb/zh/ru/es)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 21:37:35 +02:00
Psychotoxical 17a5c92174 feat(device-sync): USB/SD card sync page (WIP)
Adds a new Device Sync page for transferring music from Navidrome to
USB drives or SD cards. Sidebar entry is hidden by default.

- Four new Tauri commands: sync_track_to_device, compute_sync_paths,
  list_device_dir_files, delete_device_file
- Filename template engine with cross-platform path sanitization
- 4-concurrent-worker download, live progress via device:sync:progress event
- Persistent source list (albums/playlists/artists) with checkbox deletion
- Expandable artist tree in browser panel (per-album selection)
- i18n: DE + EN complete; other locales have stub keys

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 00:02:13 +02:00
kilyabin 1b55e88cd5 fix(fullscreen-player): stop mesh blob and portrait animations in no-compositing mode (#175)
In software compositing (WEBKIT_DISABLE_COMPOSITING_MODE=1), WebKit renders
entirely on the CPU. The mesh blob animations were not covered by the
no-compositing overrides: blob-a occupies 130×130% of the viewport, so each
frame the CPU had to composite a surface larger than the screen. On high-DPI
displays (e.g. 8K) this drops the fullscreen player to ~10 FPS.

- Stop mesh blob pan animations (static gradients are preserved)
- Stop portrait drift animation (filter was already removed)
- Remove box-shadow from the seekbar played bar (its width changes on every
  playback tick; in software mode each change triggers a box-shadow repaint)
2026-04-13 20:46:56 +02:00
kveld9 94323e91fa fixed bugs 2026-04-12 17:53:52 -03:00
kveld9 bef6941a2b feat: add multi-selection and context menu for playlist management 2026-04-12 17:53:52 -03:00
Psychotoxical fee454da5d fix(folder-browser): correct --bg-base to --bg-app in filter bar; add cucadmuh PR #165
--bg-base is undefined — sticky filter bar would have rendered transparent.
Also added PR #165 to cucadmuh's contributions in Settings About.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 18:44:40 +02:00
Psychotoxical 7e50c7af40 feat(folder-browser): per-column filter keyboard flow
feat(folder-browser): per-column filter keyboard flow
2026-04-12 18:41:08 +02:00
Maxim Isaev a12d6a4015 feat(folder-browser): add per-column filter and queue append hotkey flow
Add Ctrl+F filtering for the active Folder Browser column with keyboard handoff between filter and rows, and clear right-side filters when parent selection changes.

When pressing Shift+Enter on a filtered track list, append visible tracks to the queue instead of replacing the current queue.
2026-04-12 14:08:36 +03:00
Psychotoxical 600af0e527 feat: bulk multi-select + drag in PlaylistDetail, Favorites, and artist context menu (#157)
- PlaylistDetail: Ctrl/Cmd+Click enters select mode; bulk drag emits
  { type: 'songs', tracks } when ≥2 selected; filtered-view rows now
  also draggable as single songs
- Favorites songs: full multi-select system — Ctrl+Click, Shift+Click,
  header toggle-all checkbox, bulk-selected highlight, bulk drag to
  queue, bulk-bar with Add to Playlist + Clear
- ContextMenu: ArtistToPlaylistSubmenu resolves all artist album songs
  and forwards to AddToPlaylistSubmenu
- Locale: common.clearSelection + playlists.addSelected in all 7 locales

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 12:34:33 +02:00
Psychotoxical 6a8422ad1f fix(artists): add hover effect to alphabet filter buttons
Buttons were built with inline styles — no :hover possible. Replaced with
.artists-alpha-btn CSS class: accent-colored hover with subtle glow ring,
active state unchanged.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 11:52:31 +02:00
Psychotoxical 8f45f7230e fix(statistics): accurate counts for large libraries + album-artist tooltip
Remove the 10-page cap in fetchStatisticsLibraryAggregates — the loop now runs until
the server returns a partial page, so albums/songs/playtime reflect the full library
regardless of size (previously capped at 5,000 albums). Switched sort type from
'newest' to 'alphabeticalByName' for a stable pagination order.

Add a tooltip on the Artists stat card explaining it shows album artists only (Subsonic
API limitation — track-level featured/guest artists without their own album are not
included). Tooltip added in all 8 locales. Labels with a tooltip get a dotted underline
and cursor:help as visual hint.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 11:47:41 +02:00
cucadmuh ae2e1bcb97 feat(folder-browser): keyboard nav, context menus, now-playing path UX
Adds full keyboard navigation (arrow keys, Enter, Ctrl+Enter for context menu) across Folder Browser columns. Context menus for all row types with keyboard-operable submenus and star-rating control via arrow keys + Enter. Now-playing path is visually emphasized and stays stable; rebuilds on hotkey re-invoke or active-path follow-along. Adaptive column layout for deep trees with right-side visibility priority. New configurable 'Open Folder Browser' keybinding. StarRating animation sync for keyboard-driven changes. All 7 locales updated.
2026-04-12 11:27:26 +02:00
kilyabin 3d07a877f2 feat(fullscreen): performance fixes + appearance settings
Adds no_compositing_mode Tauri command; frontend adds html.no-compositing on Linux to replace GPU-only CSS effects (backdrop-filter, filter, mask-image) with software-friendly equivalents.

Settings → Appearance → Fullscreen Player: toggle for artist portrait visibility + 0–80% dimming slider.

Fix: long words in lyric lines now wrap correctly.
2026-04-12 11:26:44 +02:00
kilyabin bf38a286cd feat(nav): merge Random Mix & Albums into Build a Mix hub
Replaces two sidebar entries (Random Mix, Random Albums) with a single 'Build a Mix' item (Wand2 icon) at /random. Landing page shows two cards — Mix by Tracks and Mix by Albums — with glow-on-hover. Old routes updated throughout. All 7 locales updated.
2026-04-12 11:26:27 +02:00
Psychotoxical b9b8f3fc15 feat(tracklist): multi-select + psyDnD, filter/sort, settings & UI polish
- AlbumTrackList: extract TrackRow as React.memo, selection state moved to
  selectionStore (Zustand) for O(1) re-renders per toggle; Ctrl/Cmd+Click
  enters select mode; drag selected tracks as {type:'songs'} payload;
  selection clears on outside click or song-list change
- QueuePanel: handle 'songs' multi-track drop type; whitelist drag types to
  suppress drop feedback for non-queue drags (lyrics grip etc.)
- AlbumDetail + PlaylistDetail: filter/sort toolbar (title/artist, natural
  order); disc grouping bypassed when sorted; playlist reorder DnD disabled
  while filter active
- useTracklistColumns: 'known' field auto-shows newly added columns for
  existing users
- PlayerBar: mute/unmute restores previous volume via premuteVolumeRef
  instead of hardcoded 0.7
- Settings/Input: reset buttons restyled as RotateCcw icon above card,
  matching HomeCustomizer layout
- i18n: filterSongs, sortNatural, sortByTitle, sortByArtist keys across
  all 7 locales
- components.css: album-card-title/artist nowrap to keep playlist grid
  cards uniform height

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-11 11:42:47 +02:00
Psychotoxical 549677ffd4 feat(random-mix): context-aware remix button + genre reset chip
Remix button now targets the active context: relabels to "{{genre}} neu
mixen" when a genre is selected and re-fetches that genre instead of the
global random pool. "Alle Songs" chip added as first genre option to
reset back to the full library mix without leaving the page.

Also fixes album-grid cards stretching to full page height on macOS
WebKit (align-items: start on .album-grid-wrap).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 22:19:22 +02:00
Psychotoxical 1cc674e4ee fix(ui): icon updates, remove mic button, theme fixes
- LiveSearch: replace SlidersVertical with TextSearch for advanced search
- AlbumHeader: add Highlighter icon for artist bio button
- PlayerBar: remove unused lyrics/mic button
- components.css: album-detail-badge always opaque (accent bg, white text)
- theme: Middle Earth — remove sidebar stripes, fix queue/artist/bio contrast
- theme: Toy Tale — fix muted text, queue tabs, sidebar labels, divider
- theme: Tetrastack — brighten purple/blue palette, raise text-muted contrast
- theme: Horde & Alliance — remove repeating sidebar line pattern

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 17:05:20 +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
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 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 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 5848c621fd feat(folder-browser): Miller columns directory navigation
New page /folders with macOS Finder-style column layout:
- getMusicDirectory / getMusicIndexes / getMusicFolders Subsonic API methods
- Root level uses getIndexes.view (music folder IDs are not getMusicDirectory IDs)
- Columns fill available width with flex: 1, min-width: 200px
- Auto-scroll to rightmost column on expand
- Cancelled-flag prevents stale state on fast navigation
- Clicking a track plays it in the context of the current column's tracks
- FolderOpen/Folder/Music icons, accent-colored selection, ellipsis truncation
- Hidden in sidebar by default (user can enable in Settings)
- i18n: EN DE FR NL NB ZH RU

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 14:40:29 +02:00
Psychotoxical e64d151079 feat(settings): theme scheduler, UI scale, CustomSelect scroll fix
- Time-based theme scheduler: auto-switches between day/night theme
  based on configurable times; setInterval re-checks every minute
- UI scale slider (80–150%) via CSS zoom on document root; preset
  buttons aligned to actual slider positions
- CustomSelect: scroll listener keeps dropdown anchored on scroll
- All features i18n in 7 languages

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 12:23:24 +02:00
Psychotoxical dbb53bfa70 release: bump to v1.34.4
Song ratings in context menu + player bar, entity ratings (PR #130),
5 new seekbar styles, custom Linux title bar, album multi-select,
mix rating filter, top-rated stats, compilation filter, scroll reset.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 11:13:23 +02:00
Maxim Isaev 0c2ac13fed merge: integrate origin/main into feat/improve-rating-ux
Resolve conflicts in RandomAlbums (keep mix rating filter with batch ZIP/offline
selection from upstream) and Settings (SeekbarPreview + mix filter constants).
2026-04-08 05:04:12 +03:00
Maxim Isaev 705c80ef07 feat(ratings): Subsonic entity ratings and StarRating UX
Probe OpenSubsonic after connect; persist album/artist ratings via setRating when supported. Add shared StarRating (repeat same star to clear, pulse and shrink animations, hover freeze after clear). Widen tracklist duration column and bump narrow saved widths in localStorage. Use StarRating in AlbumHeader, track lists, and playlist rows.
2026-04-08 01:09:17 +03:00
Psychotoxical 5be7f7cabd feat(albums): add multi-select to Albums, New Releases, and Random Albums
Select multiple albums to add them to the offline cache or download
each as a separate ZIP. Action buttons appear inline in the topbar
when at least one album is selected; title shows selection count.
AlbumCard gains selectionMode/selected/onToggleSelect props with a
checkmark overlay and selected outline.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 23:04:44 +02:00
Psychotoxical 4182b67732 feat(most-played): add toggle to filter compilation artists
Toggle button in the Top Artists section header hides known compilation
artist names (Various Artists, VA, Soundtracks, OST, etc.) from the
ranking. Default off. Active state shown in accent color.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 22:20:35 +02:00
Psychotoxical 4b8b6ae797 feat(most-played): add dedicated Most Played page (#86)
New sidebar item (TrendingUp icon, /most-played route) with:

- Top Artists section: derived by grouping frequent albums by artistId
  and summing playCount — no extra API calls needed. Shows up to 10
  artists as a responsive grid with avatar, rank and total play count.
- Top Albums section: paginated list using getAlbumList('frequent'),
  50 albums per batch with a "Load more" button. Each row shows rank,
  cover thumbnail (44px), album name, artist (navigates to artist
  page), year and play count.
- Sort toggle (most plays first / fewest plays first).

Also adds playCount?: number to SubsonicAlbum — Navidrome returns this
field in getAlbumList2?type=frequent but it was missing from the type.

Closes #86

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 20:00:07 +02:00
Psychotoxical 9319c40fde feat(fs-player): adaptive dynamic accent color from album cover
Extracts the most vibrant pixel from an 8×8 downscaled album cover via
the Canvas API and applies it as --dynamic-fs-accent on the .fs-player
root element.  All accent-colored FS player elements use
var(--dynamic-fs-accent, var(--accent)) as fallback so the theme accent
is restored automatically when the FS player closes.

Elements updated:
- .fs-track-title (color + text-shadow)
- .fs-btn.active, .fs-btn-heart.active/:hover
- .fs-btn-play and :hover (background + box-shadow)
- .fs-seekbar-played (background + box-shadow)
- .fs-mesh-blob-a/-b (radial-gradient via color-mix at 14%/8% opacity)
- .fs-art-wrap box-shadow glow (color-mix at 70% opacity)
- MicVocal lyrics-toggle inline style

Color safety: WCAG 4.5:1 contrast against near-black FS background
enforced by progressively lightening in HSL space (ensureContrast).

Pure math functions unit-tested with vitest (28 tests, 0 deps beyond
vitest itself).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 19:14:20 +02:00
Psychotoxical 5ec8fa8ba3 fix(fullscreen): remove letter-spacing from track title to fix optical misalignment
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 12:46:27 +02:00
Psychotoxical 51c118806e feat(fullscreen): track name on top, large & bold; artist name below, small
Swap DOM order and styles in the info cluster:
- fs-track-title: clamp(28px,4.5vw,68px) / weight 900 / var(--accent) — primary
- fs-artist-name: clamp(13px,1.5vw,22px) / weight 400 / 55% opacity — secondary
- fs-cluster gap: 12px → 8px (denser hierarchy)
- fs-meta: margin-top: 4px for breathing room after artist name

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 12:44:32 +02:00
Psychotoxical fc653941c2 fix(lyrics): allow line wrapping in fullscreen lyrics overlay
Increase slot height from 3.6vh → 6vh (CSS + JS factor 0.036 → 0.06)
so that long lyric lines can wrap onto a second line without being clipped.

Fixed height on .fs-lyric-line is kept intentional — rail math requires
uniform slots. 2 wrapped lines at 2vh font / 1.4 line-height = 5.6vh,
comfortably inside the 6vh slot. font-size adjusted from 2.2vh → 2vh.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 12:36:06 +02:00
Psychotoxical 8add62a502 perf(lyrics): fix CPU spikes during lyric transitions; fix release workflow
CSS: remove `font-weight` from transition list on `.fs-lyric-line` — it
triggers layout reflow on every animation frame when the active line changes.
Replaced with `transform: scaleX(1.015)` on `.fsl-active` (compositor-only).
Added `contain: layout style` to `.fs-lyrics-overlay` to isolate reflows.

Cargo.lock: update for thread-priority crate (added in previous audio commit).

CI: replace delete-asset workaround with `updaterJsonKeepUniversal: false`
to prevent tauri-action from uploading a latest.json with wrong signature.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 12:30:32 +02:00
Psychotoxical d73f348339 feat: v1.34.1 — fullscreen lyrics overlay, FsArt crossfade, lyrics toggle, contributor updates
- FullscreenPlayer: synced lyrics overlay (5-line rail, mask fade, click-to-seek)
- FullscreenPlayer: FsArt crossfade component with onLoad pattern, 300px art, next-track pre-fetch
- FullscreenPlayer: MicVocal lyrics toggle button next to heart (persisted in authStore)
- FullscreenPlayer: idle system — only close button auto-hides, cluster+seekbar always visible
- LyricsPane: refactored to use shared useLyrics hook (no double-fetch with FS overlay)
- authStore: showFullscreenLyrics field (default true)
- i18n: fsLyricsToggle key added to all 7 locales; ru2.ts removed (merged into ru.ts)
- Settings: Contributors updated (nisrael, cucadmuh, kilyabin); logout moved to Server tab as btn-danger
- theme.css: btn-danger style added

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 23:00:33 +02:00
Psychotoxical 50ac1b8284 feat: v1.34.0 — Mobile UI Early Preview, Russian 2, macOS network fix
Co-authored-by: kilyabin <kilyabin@users.noreply.github.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 12:46:13 +02:00
Psychotoxical 8cd4cdcd64 feat: v1.33.0 — Fullscreen Player redesign, Norwegian, configurable preload
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 02:00:48 +02:00