Album and playlist enqueues go through usePlayerStore.enqueue() directly,
never through hostEnqueueToOrbit, so the tracks never land in
state.queue. Our attribution map only covered state.queue entries, so
bulk-added rows rendered with no label at all.
Fall back to "Added by you" when a track is in the host's player queue
but has no state.queue entry — the host added it themselves by
definition (pre-session or bulk-add). The guest-side view already had
this fallback via base.host in useOrbitHost.ts.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Before: the guest queue already labelled guest-suggested tracks with
"Suggested by {user}", but host picks had no label — and the host's own
queue had no attribution at all. The host couldn't tell which upcoming
rows came from guests without checking the pending-approvals list.
- Guest queue: host-pick rows now show "Added by host" instead of hiding
the attribution line.
- Host queue: each row (and the current track) shows "Added by you" or
"Added by {user}" while an Orbit session is active. Lookup uses the
existing OrbitState.queue / currentTrack addedBy field, so no new
protocol fields.
New i18n keys (en+de+fr+nl+zh+nb+ru+es):
orbit.queueAddedByHost · queueAddedByYou · queueAddedByUser
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Guest outboxes are append-only from the host's POV — every sweep reads
the same playlist. `applyOutboxSnapshotsToState` was unconditionally
pushing every trackId in every snapshot into `state.queue`, so the
pending-approval list grew by one duplicate per tick for every unhandled
suggestion (visible as 4+ identical rows after ~10 s).
Dedupe against `(user, trackId)` already present in `state.queue` or
`state.currentTrack` before appending. A guest re-suggesting the same
track after it lands/plays is a rare enough case to live with for now.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Aligns orbit invites with the existing magic-string family (psysonic1- for
server invites, psysonic2- for library shares) by folding orbit into the
psysonic2- payload as a new k:'orbit' variant. The JSON body is
intentionally extendable so future layers (passwords, permissions,
invite expiry) can be added without a format migration.
- SharePayloadV1 split into EntitySharePayloadV1 + OrbitSharePayloadV1
- decodeSharePayloadFromText filters orbit out; orbit has its own decoder
- applySharePastePayload param narrowed to EntitySharePayloadV1
- buildOrbitShareLink / parseOrbitShareLink kept as thin wrappers
- slug parameter dropped (magic string is opaque, so the slug was
cosmetic-only in the old URL form); slugifyOrbitName removed as dead code
- joinModalLinkPlaceholder updated in all 8 locales
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Reverts #271, #292, #293, #294, #295, #296.
The flatpak CI pipeline itself works end-to-end, but the installed bundle
surfaced three separate manifest issues during smoke-test on Wayland+NVIDIA:
1. GDK_BACKEND is not set, so without an X11 display in the sandbox GTK
aborts with "Failed to initialize GTK".
2. libayatana-appindicator3 is not bundled in the GNOME 47 runtime, so
libappindicator-sys panics the main thread.
3. The release binary is compiled via \`cargo build --release\` rather than
\`cargo tauri build\`, so the \`custom-protocol\` feature is off and
Tauri falls back to devUrl — the window opens but shows
"Could not connect to localhost".
Rolling back so main stays on 1.43.0. A follow-up on the original PR
tracks the fixes needed before re-attempting.
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The flatpak-github-actions container runs as root, but the actions/checkout
workspace is owned by the runner user. Without a global safe.directory entry
git aborts later steps (notably gh release upload, which probes git
internally) with "fatal: detected dubious ownership".
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The \`app-v*\` tag referenced by the manifest only becomes a real git ref
when the Draft release is published, so the previous \`git ls-remote\`
lookup during CI always returned empty and flatpak-builder failed with
"unknown revision app-v<version>". Use \`github.ref_name\` and
\`github.sha\` directly — both exist when the workflow fires.
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds full Flatpak support for Psysonic including:
- Flatpak manifest (org.gnome.Platform 47 + rust-stable + node20)
with proper finish-args for MPRIS, Discord RPC, PulseAudio, Wayland/X11
- AppStream metainfo XML and .desktop entry
- In-app updater disabled at build time via VITE_PSYSONIC_FLATPAK=1
- CI job \`build-flatpak\` in release.yml: generates cargo/npm offline
sources, patches manifest with release tag/commit, builds bundle via
flatpak/flatpak-github-actions@v6, uploads .flatpak to GitHub release
- Release docs updated in CLAUDE.md (Flatpak bump and Flathub mirror flow)
Adds activeServerId to the Home useEffect dependencies so a server
switch triggered while the user is already on the Mainstage refetches
albums/artists instead of leaving stale covers (which broke against the
new server's cover URLs).
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Selecting playlists via the header toggle only exposed the delete action
through the right-click context menu. Add a visible Delete-selected button
next to Cancel that kicks off the same handleDeleteSelected flow, with a
tooltip hint when some of the selected playlists aren't deletable (foreign
owner). Button is only rendered when selection mode is on and at least one
playlist is selected.
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Ensure playlist card Play action uses tracks filtered by the active library and show filtered song count and duration in the list, so card metadata matches actual playback scope.
Open smart playlist editing from playlist cards, load rules via Navidrome single-playlist API with safer fallbacks, and keep edit visibility aligned with ownership rules.
Also add/clean smart playlist locale keys across all supported languages and preserve smarter autogenerated naming behavior.
Show edit/delete actions on hover in playlist cards, support opening metadata edit directly from the grid, and render smart playlist covers from active-library tracks. Playlist detail now filters displayed songs to the selected library instead of hiding whole playlists.
Move smart playlist creation and management into Playlists, including Navidrome-only gating, smart-name/icon presentation, and smarter refresh handling while server-side smart rules are being applied.
On PipeWire-based distros (Debian 13, Ubuntu 22+, Gnome-on-PipeWire, and
similar), cpal's default_output_device() resolves to the raw ALSA `default`
alias. During early app-start that alias sometimes routes to a null sink:
the stream opens without error, progress ticks run, but nothing reaches the
user. Closes#234.
Prefer the pipewire-alsa / pulse-alsa aliases explicitly before falling
back to cpal's default, but only on Linux — macOS / Windows paths are
untouched. Systems that don't expose either alias (pure ALSA, no PipeWire)
fall through to the original default-device path.
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>