Commit Graph

212 Commits

Author SHA1 Message Date
Frank Stellmacher c61bcacd0d feat(mobile): comprehensive mobile UI overhaul (#238)
RandomMix: filters and genre mix panels collapse on mobile
- RandomAlbums / album grids: auto-fill favouring 3 columns at narrow widths
- BottomNav: More button opens a bottom sheet with remaining nav items
- MobileMoreOverlay: new sheet component with backdrop and slide-up animation
- Tracklist: mobile Title / Artist two-line stacked layout (Apple Music style)
- ArtistDetail: centred header (photo → name → buttons), icon-only buttons
  except Play All, collapsible Similar Artists (5 default), 2-column album
  grid, avatar glow derived from dominant cover colour
- Settings: fixed overflow in ReplayGain, Crossfade, mix rating filters,
  theme scheduler, and Next Track Buffering sections

Co-authored-by: kilyabin <65072190+kilyabin@users.noreply.github.com>
2026-04-21 12:10:02 +02:00
Psychotoxical 2d3be10c8f feat(users): show last-access timestamp per user
Maps Navidrome's lastAccessAt onto NdUser and renders it in the
User Management row as a localized relative time (Intl.RelativeTimeFormat
with the current i18n language). Tooltip carries the absolute
timestamp. Navidrome returns 0001-01-01 for never-accessed users —
detected and shown as the localized "Never" label.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 22:26:58 +02:00
Frank Stellmacher 459c9f688d feat(users): per-user library assignment + themed confirm modal (#222)
Adds Navidrome library assignment to the User Management settings
panel: GET /api/library + PUT /api/user/{id}/library wired through
new Rust commands. UserForm gets a checkbox picker (hidden for
admins, who auto-receive all libraries server-side) with inline
validation. User rows compacted to a single clickable line with
hover highlight; native confirm() replaced by a portal-based
ConfirmModal (theme-aware, ESC/Enter, vertically centered).

Co-authored-by: Psychotoxical <dev@psysonic.app>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 22:18:10 +02:00
Psychotoxical ccff7be499 chore(settings): drop Alpha badge on AudioMuse toggle
Also removes the now-unused `hotCacheAlphaBadge` i18n key from all
8 locales.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 23:53:10 +02:00
Psychotoxical dc819f3a2c feat(settings): admin-gated User Management tab via Navidrome REST API
Adds a dedicated Settings tab for managing Navidrome users (list, create,
edit, delete). Only visible to admins — gated by `/auth/login` probe on
mount. Uses Navidrome's native /api/user endpoints instead of Subsonic
(getUsers.view etc. return only the caller on Navidrome). All HTTP calls
go through new Rust commands to bypass WebView CORS.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 23:35:14 +02:00
kveld9 12bebdde06 some fixes 2026-04-19 14:23:14 -03:00
kveld9 ffffe268ab introducing floating bar with toggle 2026-04-19 13:01:31 -03:00
Psychotoxical 693766134b feat(mini-player): optional preload toggle for Linux + macOS
Adds a "Preload mini player" toggle in Settings → General → App behaviour
(off by default). When enabled, the mini webview is built hidden at app
start so the first open is instant, matching the Windows experience.
Costs one extra WebKit process running in the background (~50–100 MB).

Windows already pre-creates the mini unconditionally as a hang workaround
(commit 71fbc717); the toggle is hidden there and the invoke is skipped,
so that platform is untouched.

- authStore: new `preloadMiniPlayer: boolean` (default false) + setter.
- lib.rs: new `preload_mini_player` command; idempotent, no-op when the
  window already exists. Registered in the invoke handler.
- App.tsx: main window invokes `preload_mini_player` when the toggle is
  on and the platform is not Windows.
- Settings.tsx: toggle row under "Minimize to Tray", gated with
  `!IS_WINDOWS` so Windows users don't see it.
- i18n: `preloadMiniPlayer` + `preloadMiniPlayerDesc` added to all 8
  locales (en, de, es, fr, nb, nl, ru, zh).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 15:52:03 +02:00
Psychotoxical 16491f6321 feat(mini-player): custom titlebar with action icons; cover/meta/controls layout polish
- Drop the native titlebar on Windows + Linux (decorations: false in
  open_mini_player); macOS keeps the system titlebar with traffic lights.
- Add a slim 26 px custom titlebar with drag region, current track
  title, and the queue / pin / open-main / close action icons.
- Remove the bottom toolbar — those four buttons now live in the
  titlebar where they're easier to reach.
- Refresh the player layout: cover shrinks 112 → 84 px, the right
  column gets title / artist / transport in a single 84 px-tall block,
  progress bar spans the full width below.
- Add a miniPlayer i18n namespace (showQueue, hideQueue, pinOnTop,
  pinOff, openMainWindow, close, emptyQueue) localized for all 8
  supported locales — previously the tooltips were hard-coded English.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 13:28:28 +02:00
Psychotoxical 60da17f7cc feat(mini-player): user-bindable keyboard shortcut to toggle mini player
Adds an 'open-mini-player' entry to the in-app keybindings (Settings →
Shortcuts), default unbound. Pressing the chord from the main window
opens the mini and minimises main; pressing it from the mini hides the
mini and restores main — both paths invoke open_mini_player which
already handles the toggle.

The mini window has its own keydown listener (same pattern as Space /
arrows for play/skip) that reads the binding from useKeybindingsStore.
Binding changes in main propagate to an open mini through the existing
storage-event sync (now also covers psysonic_keybindings) so the user
doesn't need to restart the mini after rebinding.

Localized in all 8 supported locales.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 13:05:06 +02:00
Psychotoxical a48159d302 feat(queue): split tech bar into two lines when ReplayGain is present
The tech info strip in the queue header was a single ellipsised line, so
ReplayGain values (Track / Album / Peak) got cut off on tracks with a
full codec + bitrate + samplerate prefix. Now the strip wraps into two
lines whenever RG values exist:

- Line 1: codec · bitrate · bit depth/sample rate (unchanged)
- Line 2: 'ReplayGain · T … dB · A … dB · Peak …' — slightly smaller
  and dimmed for hierarchy, ellipsises independently if it still
  overflows.

Tracks without RG metadata stay one line as before. New i18n key
`queue.replayGain` ('ReplayGain') added to all 8 locales.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 12:24:46 +02:00
Kveld. eb747ba1ae introducing timer toggle player bar (#212) 2026-04-19 12:04:01 +02:00
Psychotoxical 6bd2bfc01c feat(changelog): replace auto-modal with sidebar banner + /whats-new page
Removes the giant startup changelog modal. After an update, a compact
neutral-palette pill now sits above Now Playing in the sidebar saying
"Changelog — vX.Y.Z". Clicking opens a proper /whats-new page in the
main content area; X dismisses. Page renders the current version's
CHANGELOG entry with inline Markdown (headings, lists, blockquotes,
hr, bold/italic/code, and real [label](url) links that open via the
Tauri shell plugin).

Visual tokens are hardcoded slate/gray/blue so the banner and page look
identical across every theme (dark, light, skeuomorphic, whatever) —
requested for consistent contrast. Auto-mark-as-seen removed from the
page; the banner only goes away on explicit dismiss, so users can
re-read as often as they want.

Settings → About gains a "Release notes" row with a link that resets
the seen-version and opens the page, so the banner can be retriggered
manually (also helpful for dev builds ahead of the current tag).

The existing "Show changelog on update" toggle now gates the banner
instead of the modal; description strings updated in all 8 locales.

fix(themes): WCAG contrast audit — mocha + winmedplayer + wista

Mocha (Catppuccin dark)
  .track-size used --ctp-overlay0 directly (3.36:1 on bg-app, 2.57
  on bg-card). Swapped to --text-muted → 7.37 / 5.65. Fix also lifts
  macchiato/frappe/latte which shared the failure.

WinMedPlayer (Luna)
  --text-muted #b8d0f8 (3.87:1 on bg-app) → #e8f0ff (5.28)
  --border   #2a5090 (1.31 on bg-app)   → #071027 (3.12, meets 3:1 UI)

Wista (Vista Aero)
  Lyrics pane sits on bg-sidebar #0e1e3e but used --text-primary
  (#0d1d3c) for active lines — 1.01:1, literally invisible. Added
  component overrides: .lyrics-line / .lyrics-status / word-synced
  variants → #aac8f0 (9.60), .lyrics-line.active → #ffffff (16.48).
  Palette: --warning #c8980c → #735a00 (2.37 → 5.91 on bg-app),
  --text-muted #4870a8 → #3f6aa0 (4.23 → 4.65 on bg-card).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 02:28:45 +02:00
Psychotoxical 89e8f43add feat(albums): compilation filter toggle in All Albums
Tri-state button (all / only compilations / hide compilations) in the
Albums page header, using the OpenSubsonic isCompilation tag from
Navidrome. Client-side filter via useMemo, no extra server calls.
Closes #65.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 22:33:45 +02:00
Psychotoxical c96eb0a805 feat(favorites): add genre column + Top Favorite Artists row
Genre column (toggleable via column picker) and a horizontally scrolling
Top Favorite Artists section between Radio Stations and Songs, aggregated
from starred tracks. Closes #87.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 22:24:14 +02:00
Psychotoxical 225609e93c fix(i18n): add common.close to en + de locales
The device-sync migration modal uses t('common.close') for its dismiss
button, but the key lived only inside scoped namespaces (where it had
different translations like "Verstanden" / "Got it"). Add the
straightforward "Schließen" / "Close" under common so the migration
modal shows the right label.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-18 19:54:51 +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 e201bc630c feat(updater): polish macOS update modal with countdown, trust badges, clean button states
- Footer buttons are now state-dependent: Skip / Remind later only show
  during idle; the install button no longer leaves a gap when it
  disappears, and "Remind later" stops shifting between states
- Post-install on macOS shows a 3-second visible restart countdown with
  a "Restart now" button instead of triggering an invisible relaunch
  that sometimes didn't actually fire
- macOS idle state now explains the in-place update model (no DMG
  download) and shows trust badges: "Notarized by Apple" + "Signature
  verified" as an at-a-glance trust signal
- Download state during install hides all secondary buttons so the
  progress bar stands alone
- New i18n keys in en/de; fr/nl/zh/nb/ru/es fall back to the English
  defaultValue until translated in a follow-up

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-18 17:44:50 +02:00
Maxim Isaev ba43ed867a feat(linux): add WebKitGTK smooth wheel scroll toggle in settings
Persist preference in auth store, sync from App on Linux, and expose a
Tauri command using webkit2gtk to toggle enable-smooth-scrolling at
runtime. Default on to match upstream; users may disable for discrete
GTK-style line steps.

Apply a one-time rehydrate migration so smooth scrolling stays on after
updates even if an older build persisted the wrong default.
2026-04-18 05:09:33 +03:00
kilyabin cd1417b604 feat: Apple-Music-like lyrics view with saving old-style 2026-04-18 01:58:17 +04:00
Psychotoxical 02c7a3fe22 feat(settings): collapse Discord sub-options under one header
"Fetch covers from Apple Music" and "Custom text templates" are now both
tucked into a single collapsible "Advanced Discord options" block (default
collapsed) that only appears when Discord Rich Presence is enabled.
Reduces vertical noise in Settings → General for the common case where
users just flip Rich Presence on and leave the defaults.

Uses the same chevron-rotate pattern as the font picker and contributors
list. Adds `settings.discordOptions` key in all 8 locales.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 21:52:16 +02: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
Frank Stellmacher b45bb95522 Merge pull request #201 from cucadmuh/feat/playback-source-indicator
feat(queue): playback source badge + preload-aware source tracking
2026-04-17 15:56:01 +02:00
Frank Stellmacher 9387ceca83 Merge pull request #198 from kveld9/feat/DRP-enhancement
feat: discord rich presence enhancement
2026-04-17 15:34:18 +02:00
Maxim Isaev c165669db5 feat(queue): show playback source in tech strip with preload tracking
Add source badges for offline, cache, and stream playback in the queue tech line, including localized tooltips across shipped locales.

Track Rust preload-ready events by stream track id and latch the selected source per track, with dev logs to debug preload/source mismatches during next-track handoff.
2026-04-17 16:34:11 +03:00
Psychotoxical c50addaacf fix(discord): remove dead fields, timeChanged invoke loop, and unsupported {paused} placeholder
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 15:33:58 +02:00
Frank Stellmacher 7e64ef8f2a Merge pull request #199 from kveld9/fix/csv-import-clean
fix: csv import improvements
2026-04-17 15:28:19 +02:00
kveld9 f3fb730fbc csv import improvements 2026-04-17 02:55:31 -03:00
kveld9 7b20965c1b fix locales 2026-04-16 20:56:20 -03:00
kveld9 28844e8456 release 2026-04-16 20:34:55 -03:00
Maxim Isaev 572eb81927 feat(queue): show ReplayGain metadata in current-track tech strip
Display track gain, album gain, and peak from file tags next to format,
bitrate, and sample rate so missing ReplayGain tags are obvious.

Refs: https://github.com/Psychotoxical/psysonic/issues/195
2026-04-16 23:15:13 +03:00
Psychotoxical 06902acd4b feat(help): add missing sections and questions (Device Sync, Internet Radio, CLI, Playlists, Infinite Queue, Lyrics sources, Audio device, Backup & Restore, Now Playing)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-16 20:10:40 +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 442ed9d191 feat(device-sync): manifest, cancel, font picker + sync status fix
- Write psysonic-sync.json to device after sync/deletions; auto-import
  on folder select when localStorage is empty (cross-platform handoff)
- Add cancel button during active sync: AtomicBool flag per job,
  tasks bail after acquiring semaphore, cancelled state in UI
- Fix sync status staying "pending": normalize template path separators
  to OS separator (Windows: '/' → '\') so compute_sync_paths and
  list_device_dir_files produce matching strings for Set comparison
- Add Geist and JetBrains Mono as variable fonts; font picker collapsible
- Fix device mount detection on Windows: removable drive letters (E:\)
  were incorrectly skipped alongside system roots; strip \?\ prefix
  from canonicalized paths before mount-point comparison

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 22:59:27 +02:00
Psychotoxical e23280c013 feat(sidebar): add split Mix navigation mode with separate sidebar entries
Extract ALL_NAV_ITEMS to src/config/navItems.ts and add randomMix/randomAlbums
nav items. A new toggle in Settings switches between a single "Build a Mix" hub
and separate "Random Mix" / "Random Albums" sidebar entries (randomNavMode in
authStore). Fixes reorder crash caused by hidden items being overwritten with
undefined during the merge step.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 22:27:53 +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
Psychotoxical 624bd6bff7 fix(i18n): add common.play key to all 8 locales (fix for PR #186)
The AlbumHeader and PlaylistDetail play buttons use t('common.play') which
was missing — 'Reproducir' would have appeared as fallback in all languages.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 18:05:14 +02:00
kveld9 fc90617e9c some fixes 2026-04-15 11:50:44 -03:00
kveld9 a44581e5d6 new feature: import spotify playlist with .csv 2026-04-15 11:19:31 -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 117be0d85e Merge pull request #184 from kveld9/feat/ux-redesign-favorites
feat: ux redesign favorites -- sortable columns, gender filter, age range filter, new columns.
2026-04-14 22:34:18 +02:00
kveld9 6996dacdf7 sortable columns, gender filter, age range filter, new columns. 2026-04-14 16:49:06 -03:00
Psychotoxical 9f4c7382aa feat: add 3 visual toggles (cover art background, playlist cover photo, show bitrate)
feat: add 3 visual toggles (cover art background, playlist cover photo, show bitrate)
2026-04-14 21:47:48 +02: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
kveld9 38e59d7a5e feat: add 3 visual toggles (cover art background, playlist cover photo, show bitrate) 2026-04-14 14:21:48 -03: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
cucadmuh 4207455440 fix(audio): Linux output device selection and watcher (#176)
* fix(audio): stabilize Linux output device picker and watcher

Keep pinned ALSA/cpal device ids stable when enumeration omits the active
sink or returns an equivalent name. Stop Linux device-watcher from clearing
the pin based on missing list entries; macOS and Windows still treat repeated
absence as unplugged. Settings refresh flow calls canonicalize and refetches
the list; add i18n for the out-of-list device label.

* fix(settings): sort audio output devices by label

cpal enumeration order is arbitrary; order the dropdown by readable label
and place the current OS default device first among concrete outputs.
2026-04-13 21:48:21 +02:00
Psychotoxical 27ea221130 chore(about): update contributors, remove feature tagline, limit changelog to 3
- Add missing contributions: cucadmuh (PR #144, #167, #173, #174),
  kveld9 (PR #168), nisarg-78 (PR #115)
- Remove aboutFeatures tag line from all 8 locales (too dynamic to maintain)
- Changelog section now shows only the 3 most recent versions

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-13 20:23:22 +02:00
cucadmuh 9cd4743d1c feat(settings): audio output device picker (labels, OS default, live refresh) (#173)
* feat(settings): clearer audio device labels for duplicate ALSA names

Show HDMI outputs as "Card (HDMI n)" from hdmi:DEV indices; include PCM and
optional subdevice for hw/plughw/sysdefault; label other ALSA plugins with
iface and PCM. When labels still collide, append a structured hint
(iface · card · PCM) instead of only truncating the raw device string.

* feat(settings): improve audio output device picker

Parse ALSA-style ids into clearer labels (HDMI with DEV index, PCM/subdevice
for hw/plughw/sysdefault). Disambiguate colliding labels; share stderr
suppression for Linux device enumeration.

Add audio_default_output_device_name and tag the matching list entry as the
current system output (i18n). While the Audio tab is open, refresh list and
mark on audio:device-changed and audio:device-reset without toggling the
refresh spinner. Show an error toast if listing devices fails.
2026-04-13 20:13:22 +02:00
Psychotoxical ec021516c7 fix(audio): device-reset false positive + stderr noise + i18n tooltip
- Device watcher requires 3 consecutive misses (~9 s) before triggering
  audio:device-reset, preventing false positives when ALSA temporarily
  hides a busy device from output_devices() enumeration
- Add stderr suppression to open_stream_for_device_and_rate (last source
  of ALSA terminal noise on Linux)
- Fix tooltip showing raw key 'common.refresh' — replaced with
  settings.audioOutputDeviceRefresh (added to all 8 locales)
- Device switch restarts track from beginning (no seek-back)

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