Frank Stellmacher 2bea55bedd feat(playlists): suggestion-row preview UX (#365)
* feat(playlists): suggestion-row preview UX (30s preview, double-click play-next, scroll keep)

Reworks the interaction on the suggestion rows below a playlist so users
can audition songs before deciding what to do with them.

- New "Preview" pill button left of each track title plays a 30-second
  mid-song sample via a parallel HTML5 audio element. The main player
  pauses on the first preview and auto-resumes when the preview ends.
  Switching previews chains without re-resuming. External main-player
  playback (spacebar, mediakey) cancels the preview without resuming.
  Animated underline shows the 30 s progress.
- Double-click the row to insert the song at queueIndex + 1 and skip to
  it ("Play next"). Single-click is intentionally inert so a stray click
  next to the preview button no longer drops a song into the queue by
  accident. Tooltip on the row makes the affordance discoverable.
- The + button still adds to the playlist, and now restores the
  .main-content scroll position so the page no longer jumps to the top
  after pressing it.
- i18n keys in all 8 locales: playlists.preview / previewStop / previewShort
  / previewStopShort / suggestionDoubleClickPlayNext.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(playlists): WebKitGTK NULL-instance crash on preview teardown

cucadmuh hit GLib-GObject-CRITICAL: invalid (NULL) pointer instance /
g_signal_connect_data assertion failed, with the UI freezing after
clicking a preview button. Root cause was the audio-element lifecycle:

- `audio.src = ''` to "stop" leaves WebKitGTK's GStreamer playbin in a
  half-initialized state. The next signal_connect dereferences NULL.
- Creating `new Audio()` per click stacked half-torn-down playbins
  during rapid switches.
- `loadedmetadata` listeners on orphaned audio elements could call
  play() on an already-discarded instance.

Fix: reuse one <audio> element per component, tear down the source
via removeAttribute('src') + load() (which resets the playbin
cleanly), and gate async listeners behind a session counter so stale
metadata events on switched-away previews are ignored.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(playlists): icon-based action buttons + add-on-doubleclick + hint

- Replace text-pill Preview button with circular icon button + animated
  SVG progress ring (Play/Square icon swap when active).
- New Play-next button (filled accent circle, white triangle) sits
  left of the Preview button — explicit affordance for the action that
  used to be a hidden double-click.
- Double-click on a suggestion row now triggers Add-to-playlist (the
  same action as the + button on the right) — discoverable shortcut
  for mouse users.
- Subtitle under the Suggested Songs header announces the add-on-
  doubleclick affordance, in all 8 locales.
- Drop the now-obsolete previewShort / previewStopShort short-label
  keys (text replaced by icons); rename suggestionDoubleClickPlayNext
  → playNextSuggestion to match its new role on the Play-next button.
- Keep the session-counter guard from the prior commit so async
  loadedmetadata handlers from a switched-away preview can't play()
  on a discarded element.

Note: header column labels visually drift from the data columns when
suggestion rows have the action buttons; left as-is for now.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(playlists): apply LUFS pre-analysis attenuation to suggestion previews

When the main player is on loudness normalization, analysed tracks come
out reduced toward target while the unanalysed preview <audio> blasts
the file at its natural level — cucadmuh reported the previews are
audibly louder than the playlist playback.

Apply the user's stored pre-analysis attenuation (the slider value, not
the target-offset effective form) as a linear gain on the preview's
audio.volume. Default −4.5 dB lands the preview at ~60% of the player
volume, which roughly tracks how aggressively the Rust engine pulls
naturally-loud tracks toward target.

If the engine is off, behavior is unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* style(playlists): use chevron icon for suggestion preview button

Distinguishes the preview button from the adjacent play-next button
by mirroring the Play Next chevron from the context menu.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 23:02:31 +02:00
2026-04-29 20:37:17 +03:00
2026-04-29 12:54:07 +02:00

Psysonic

Psysonic Logo

The Ultimate Desktop Client for Self-Hosted Music Libraries

Fast. Beautiful. Native. Feature-packed. Built primarily for Navidrome. Also compatible with Gonic, Airsonic, LMS and other Subsonic-compatible servers with partial feature support.


Latest Release GitHub Stars License GPLv3 Tauri v2 Discord Community Telegram Community AUR psysonic AUR psysonic-bin Cachix



No telemetry • Native performance • Massive feature set • Community driven


Psysonic Screenshot


Warning

Psysonic is under heavy active development. Bugs and rough edges are to be expected. We reserve the right to change, remove, or rework existing features at any time without prior notice.

Server Compatibility

Psysonic is optimized first and foremost for Navidrome.

Many advanced functions integrate directly with Navidrome APIs for the best possible experience. Other Subsonic-compatible servers generally work well, but some features may be limited depending on server capabilities.

Why Psysonic?

Most Subsonic clients feel like web wrappers.

Psysonic does not.

It is a true desktop experience built with Rust, Tauri v2, and React for users who care about speed, aesthetics, customization, and serious music library management.

If you host your own music, this is what the premium experience should feel like.


Core Features

Playback Engine

  • Gapless playback
  • Crossfade
  • ReplayGain support
  • Smart Loudness Normalization
  • Infinite Queue
  • Smart Radio sessions
  • High responsiveness with low memory usage

Audio Tools

  • 10-band Equalizer
  • Presets
  • AutoEQ headphone correction
  • Per-device optimization

Library Power

  • Lightning-fast search
  • Albums / Artists / Tracks / Genres
  • Ratings system
  • Multi-select bulk actions
  • Drag & drop playlist management
  • Huge library friendly

Lyrics & Discovery

  • Synced lyrics with seek support
  • Auto-scroll sidebar lyrics
  • Fullscreen lyric mode
  • Last.fm scrobbling
  • Similar artists / love tracks / stats

Personalization

  • Huge theme collection
  • Catppuccin / Nord inspired styles
  • Glassmorphism effects
  • Font customization
  • Zoom controls
  • Keybind remapping
  • Theme Scheduler (day/night auto switch)

Power User Extras

  • CLI controls
  • USB / portable sync
  • Backup & restore settings
  • In-app auto updater
  • LAN / remote auto switching

Orbit (Upcoming)

Listen Together. In Sync. Soon.

Currently in final development and testing. Orbit will introduce synchronized shared listening sessions directly inside Psysonic.

  • Host-controlled playback
  • Join via link
  • Shared listening sessions
  • Guest song suggestions
  • Real-time queue interaction

Rolling out in an upcoming release. Community feedback will help shape the final experience.


Platforms

OS Support
Windows Native Installer (certificate pending)
macOS Signed DMG
Linux AppImage / DEB / RPM / AUR (psysonic, psysonic-bin) / NixOS

Supports 8 languages and growing.


Install

Linux

curl -fsSL https://raw.githubusercontent.com/Psychotoxical/psysonic/main/scripts/install.sh | sudo bash

Windows

Download the latest installer from Releases.

SmartScreen warnings may appear until the code-signing certificate is active.

macOS

Download the signed DMG from Releases.


Development

git clone https://github.com/Psychotoxical/psysonic.git
cd psysonic
npm install
npm run tauri:dev

Build release:

npm run tauri:build

Privacy First

  • No telemetry
  • No spyware nonsense
  • No analytics harvesting
  • Your library stays yours

Community

Join Discord, report bugs, suggest features, share themes, shape the future.


License

GNU GPL v3.0


Stop using boring music clients.

Use Psysonic.

S
Description
fork a psysonic player for contrib
Readme 58 MiB
Languages
TypeScript 68.9%
Rust 25.7%
CSS 4.7%
JavaScript 0.3%
Shell 0.2%