Consolidates everything since v1.40.0 (public) into one coherent
release. v1.41.0 remains as an internal Draft on GitHub that was used
to verify the Cachix substituter pipeline and never went public — this
release folds its intended contents in and adds the mini-player feature
work, the player-bar time toggle (kveld9), the ReplayGain expand badge
and related UX polish on top.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- 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>
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>
Two regressions in the mini player's persistence story:
1. Window position was lost on every reopen. set_position() called on a
hidden window is unreliable on Linux WMs (Mutter, KWin re-centre on
show). Worse, the WM-induced re-centre fired WindowEvent::Moved with
the centre coords, which the throttled persister happily wrote to
disk — so the saved position turned into "centre" within seconds.
Fix:
- Initial open uses WebviewWindowBuilder::position() (logical pixels,
scaled via the primary monitor) so the window is created at the
right spot.
- Re-show path re-applies the saved position with set_position AFTER
show().
- Both paths call mark_mini_pos_programmatic() before triggering the
move; persist_mini_pos_throttled ignores Moved events within 1 s of
a programmatic mark, so WM-induced and self-induced moves no longer
overwrite the user's position.
2. The queue panel always opened collapsed regardless of the previous
session. Persist queueOpen to localStorage (psysonic_mini_queue_open)
and resize the window to the stored expanded height on mount when
the saved state was 'open'. Brief jump from 180 px to expanded is
unavoidable since localStorage only lives in the JS layer.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Per @cucadmuh's feedback: the presence of ReplayGain matters more than
the actual numbers. The tech bar now shows a small 'RG' pill on line 1
whenever the track has any RG metadata; hovering reveals the values via
tooltip, clicking persistently expands the second line.
- Source icon stays inline before the format string (was getting
separated from FLAC by the centred stack layout)
- Pill uses --accent-tinted color-mix so it adapts to every theme
- ChevronDown rotates on expand for a clear affordance
- New persisted state: themeStore.expandReplayGain (default collapsed)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The player bar occasionally renders fully black for one frame on Linux
(WebKitGTK with software compositing) when an unrelated layer elsewhere
in the page invalidates. `contain: layout paint` makes the bar its own
paint boundary so it can no longer be pulled into a surrounding dirty
rect.
No-op on Wayland-with-GPU and on Chromium-based webviews (Windows,
macOS) — those don't exhibit the flash to begin with.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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>
This iteration fills in the pieces that make the mini player usable as a
daily standalone window:
- Window position persists to <app_config_dir>/mini_player_pos.json on
every WindowEvent::Moved (throttled 250 ms); first launch lands in the
bottom-right of the main window's monitor.
- Queue keeps a 260 px floor when expanded (~2 visible rows). The
user-resized expanded height is restored on next toggle via
localStorage so reopening doesn't snap back to the default 440 px.
- set_mini_player_always_on_top(true) now forces a false-then-true cycle
so the WM re-evaluates the layer after a hide/show; the frontend also
re-asserts the pin state on mount and on window focus, so the user no
longer has to click the pin button twice for it to stick.
- Native scrollbar in the queue is hidden in favour of a JS-driven
overlay thumb so items use the full width of the queue area.
- PsyDnD reorder works inside the mini queue: drag emits 'mini:reorder',
the bridge calls reorderQueue on the source-of-truth store in main.
- Localized queue-item context menu (MiniContextMenu) with Play now /
Remove from queue / Open album / Go to artist / Favorite / Song info.
Cross-window actions forward to main via new bridge events
(mini:reorder, mini:remove, mini:navigate, mini:song-info); a
psy:navigate CustomEvent picked up by AppShell handles routing.
- Theme, font and language changes in main propagate live to the mini
via a 'storage' event listener that re-hydrates the persisted Zustand
stores and calls i18n.changeLanguage.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Native `title` attribute renders an unstyled OS tooltip and bypasses the
TooltipPortal — convention in this codebase is `data-tooltip="…"` so the
hover hint matches every other player-bar control.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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>
- Add Cachix badge to the top row linking to psysonic.cachix.org
- New NixOS/flakes feature bullet and a dedicated install block with
nix run quickstart, system-config hint, Cachix substituter setup, and
credit + PR link for @cucadmuh
- macOS install block: drop the xattr Gatekeeper workaround (obsolete
since v1.40.0 signed + notarized builds); replace with a note on the
in-app auto-updater
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Document NixOS/Home Manager installation from the upstream flake,
including Cachix substituter/key configuration, apply commands, and pinning.
Also add a README Linux note linking to the new NixOS guide.
Adds a queue panel that toggles via a new toolbar button and resizes the
mini window between 340×180 (collapsed) and 340×440 (expanded). Tracks
in the queue are clickable — click jumps to that index via a new
mini:jump event handled in the main-window bridge. The current track
auto-scrolls into view when the queue opens.
Resize uses a new resize_mini_player Rust command (more reliable than
JS setSize, which was silently no-op'ing because the
core:window:allow-set-size capability was missing). That capability is
now granted as well.
The mini player hydrates its initial state from the persisted
playerStore, so real content (cover, title, artist, queue) shows as
soon as React mounts instead of "—" while we wait for the first
mini:sync. Dynamic state (isPlaying, progress) still comes from
events.
Window sizing:
- inner_size bumped to 340×180 so the toolbar row isn't clipped
- mini label added to tauri-plugin-window-state denylist so old saved
sizes don't come back
- show_main_window now also hides the mini — clicking expand no longer
leaves both windows on screen
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The album count on local artist cards was rendered with hardcoded German
("Album"/"Alben"). Switched to the existing plural-aware i18n key which
covers all 8 locales (including Russian Slavic plurals).
Co-Authored-By: cucadmuh <cucadmuh@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
A second webview window (label "mini") with a compact player: album art,
title, artist, prev/play/next, progress bar, pin-on-top toggle, expand
back to main, close. Main minimizes on open and restores when the mini
is hidden or closed. Spacebar toggles, arrow keys skip tracks.
Cross-window sync: main window subscribes to playerStore and pushes
`mini:sync` via emitTo on track / play-state change. Audio progress
already broadcasts to all windows via `audio:progress`. Control actions
(prev/next/toggle) come back via `mini:control`; main-window restore
goes through a direct Rust command because WebKitGTK pauses JS in a
minimized webview.
Tiling-WM detection reused from existing `is_tiling_wm()` — always-on-top
is skipped on Hyprland/Sway/i3 since it's ignored there anyway.
Early alpha: no queue expand, no lyrics, no EQ, no drag-snap. Scope kept
deliberately tight for v1; follow-ups planned.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
cachix-action installs a post-build-hook via NIX_USER_CONF_FILES, but
the Determinate Nix daemon reads system nix.conf and never fires the
hook — only two early prep paths ever reached the cache, never the
actual psysonic output. Add an explicit closure push after the build;
Cachix dedupes, so redundancy is cheap.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds optional artist field to DeviceSyncSource and renders it inline
next to the album name ("Album · Artist") in the on-device list.
BrowserRow (left panel) uses the same inline format so albums in search,
random picks and under expanded artists all read consistently. Playlists
unchanged.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two sort buttons (A–Z Album / A–Z Artist) become one SortDropdown —
same portal popover pattern as the year and genre filters. Button
shows the current choice with an up/down arrow icon. Generic
component, reusable for other pages.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Clicking the mic button now toggles the lyrics settings panel instead
of outside-handler closing it and click re-opening it — trigger ref is
excluded from the outside-click check.
Panel is now a solid surface (no backdrop-blur, near-opaque background,
higher-contrast button text) so settings stay readable over the busy
fullscreen background.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replaces the inline From/To number inputs in the Albums header with a
single button that opens a popover — same pattern as the genre filter.
Button shows the active range (e.g. 2020–2024) with accent styling.
Header is now a homogeneous row of buttons.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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>
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>
Header with search/sort/genre/year controls now pins to top while
scrolling, so filters stay reachable. Nested .content-body (App.tsx
wraps routes) was becoming the sticky anchor and swallowing the effect —
fixed with .content-body .content-body { overflow: visible }.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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>
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>
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>
Major release consolidating several months of work into a single coherent
version. The 1.34.x patch series accumulated many small features; 1.40.0
packages them up and signals the infrastructure milestone (macOS signing
+ notarization + auto-updater) clearly.
Highlights (see CHANGELOG for the full rundown):
- macOS builds are signed with a Developer ID certificate and notarized
by Apple — no more Gatekeeper "unidentified developer" dialog
- In-app auto-update on macOS via the Tauri Updater plugin; polished
modal with trust badges, restart countdown, and state-dependent buttons
- Linux WebKitGTK wheel scroll toggle (PR #207 by cucadmuh)
- Device Sync: user-configurable filename template replaced with a
fixed cross-OS scheme; playlists now live in their own self-contained
folders with sibling-referencing .m3u8; one-shot migration tool for
existing sticks
- WCAG contrast audits for middle-earth and nucleo themes
- Contributors list in Settings → About updated (PRs #205, #206, #207)
Windows signing + Windows auto-updater are the remaining gap; 2.0.0 is
planned once both are active.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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>
The macOS updater pipeline is stable now, so restore full-platform
builds + the Nix cache refresh on every release. These were disabled
temporarily during v1.34.14–v1.34.23 iteration to cut turnaround time.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- 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>
No functional changes. Throwaway build to serve as the "latest" release
that v1.34.22 will find, download, verify, and install via the Tauri
Updater. Will be deleted once the updater round-trip is confirmed.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
A character was lost when the base64-encoded minisign public key was
transcribed into tauri.conf.json, producing a 41-byte decoded key
instead of the required 42 bytes. Every release built against that key
(v1.34.15 through v1.34.21) rejects any update manifest signature with
"Invalid encoding in minisign data". Replaced with the correct pubkey
read directly from ~/.tauri/psysonic-updater.key.pub.
v1.34.19 installed manually for testing cannot receive auto-updates
because the broken pubkey is baked into its binary; a fresh v1.34.22
install is required as the base for the updater test.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- AppUpdater.tsx: macOS now has a dedicated branch in the update modal —
no architecture-specific DMG asset shown (the Tauri Updater picks the
right platform from latest.json), clearer wording ("Downloads, verifies
and installs automatically"), and the primary button reads "Install
now" instead of "Download". Strings use defaultValue so locales without
the key fall back to English until translations catch up.
- Test release for the updater pipeline; CHANGELOG entry asks users to
ignore it. Will be deleted after the test.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Throwaway release to validate the macOS Tauri Updater end-to-end:
v1.34.19 (installed manually) → check() → latest.json → download +
install → relaunch. Contains no actual changes. CHANGELOG entry asks
users to ignore it; will be deleted after the test.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
tauri-action always re-packs Psysonic.app into .app.tar.gz after tauri
CLI finishes (regardless of includeUpdaterJson), so the .sig that tauri
CLI produces never matches the final tarball — and the sig tauri-action
was supposed to produce silently goes missing ("Signature not found for
the updater JSON. Skipping upload...").
Rather than fight the repack, sign the repacked tarball ourselves in a
follow-up step using `tauri signer sign` against the same private key
(from TAURI_SIGNING_PRIVATE_KEY), then upload the fresh .sig. tauri-
action still handles the DMG + .app.tar.gz upload; we only add the .sig.
Also removes an unused `std::rc::Rc` import in the vendored cpal patch.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Root cause: tauri-action runs a second "Packaging" pass after tauri CLI
finishes, which rewrites src-tauri/target/<target>/release/bundle/macos/
Psysonic.app.tar.gz with different bytes. The .sig produced by tauri CLI
no longer matches the new hash, so tauri-action silently deletes it —
leaving the directory with only .app and .app.tar.gz (no .sig for our
manifest generator to consume).
Fix: pass `includeUpdaterJson: false` to tauri-action so it skips the
repack + updater JSON upload entirely, then copy both the .app.tar.gz
and .app.tar.gz.sig produced by tauri CLI into the workspace root with
the expected asset names and `gh release upload` them.
Also disables build-linux and the Windows matrix entry during testing
to cut iteration time roughly in half.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Replace the glob find for the .sig file with an explicit target-based
path ($matrix → src-tauri/target/<target>-apple-darwin/release/bundle/
macos/Psysonic.app.tar.gz.sig) and dump directory listings so we can
see what tauri-action actually leaves behind if the path is wrong
- Skip verify-nix while we iterate fast on signing + updater (its auto-
commits of flake.lock / npmDepsHash cause rebase friction on every
release)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
tauri-action on macOS cross-target builds produces the .app.tar.gz.sig
locally but silently skips its upload ("Signature not found for the
updater JSON. Skipping upload..."), which caused generate-manifest to
abort on v1.34.15 because the .sig asset was absent.
New step after tauri-action locates the .sig under src-tauri/target/*/
release/bundle/macos/ and uploads it as Psysonic_aarch64.app.tar.gz.sig
or Psysonic_x64.app.tar.gz.sig — the exact filenames generate-update-
manifest.js expects.
Also bumps version to 1.34.16.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>