Skip to content

Develop - #32

Merged
EarMaster merged 7 commits into
mainfrom
develop
Oct 5, 2026
Merged

EarMaster merged 7 commits into
mainfrom
develop

Conversation

@EarMaster

Copy link
Copy Markdown
Owner

No description provided.

The CSP's `connect-src *` does not match custom schemes, so in a bundled build it
blocked Tauri's `ipc:` protocol. Tauri then fell back to postMessage for every
command without saying so. Since `save_asset` started taking a raw byte body in
1.6.3, that fallback turned every pasted image into JSON, and the command rejected
it with "Asset upload must send a raw body". Dropped images that were resized
first took the same path. Dev builds load from Vite with no CSP, which is why only
release builds broke. Allowing `ipc: http://ipc.localhost` puts release builds on
the IPC protocol dev builds already use.

The failure was invisible because the handlers only called console.error, which
goes nowhere in a release build. Attachment save failures in the editor and queue
now go through reportError, which takes an optional context so the log line says
what was being attempted.

Confirmed on a debug build with the release CSP: pasting logged the raw-body
error before the change.
On macOS, Tauri's drop handler only reads file paths, and a browser offers an
image as a promised file plus some mix of its bytes, its URL and a TIFF - never a
path. Browser drops therefore arrived empty and were ignored. The promise is
already gone when the drop reaches us (macOS reports it as such for Chromium and
Safari), so a new `read_dropped_image` command reads the drag pasteboard instead:
the original bytes when present (Chromium), else the image downloaded from its
URL (Safari), else the TIFF re-encoded as PNG. It writes a scratch file under
~/.stashpad/tmp/drop and hands back the path, so the drop takes the Finder path:
same resize, same save.

Drop positions were divided by devicePixelRatio, but Tauri passes on the
webview's own units: device pixels on Windows, CSS pixels on macOS and Linux. On
a Retina Mac every drop was hit-tested at half its coordinates. Every editor
also handled every drop that missed a card, so a drop into an editor opened on
a queue card was taken by the main editor too. The two then read the same drop
at once and collided in the scratch folder. Now exactly one place takes a drop:
the editor it landed in, a card outside any editor, or else the main editor.

Attachment failures now show as a warning chip in the editor, with a
`layout: "list"` tooltip that lists them; drop errors carry UiError codes
translated under errors.drop. Each case was checked by hand in a bundled debug
build. The drag-routing and coordinate handling have unit tests.
In a bundled app there is no terminal, so console.* and println! went nowhere:
78 frontend calls and 51 backend prints left no trace in the log users send. The
log plugin also only started once the app was set up, so settings validation,
the database migration and the credential store probe ran before it existed and
the keychain code kept a private buffer to replay its own lines.

A deferring logger is now installed first thing in run(); it holds early records
and replays them into the log plugin once the app handle exists, so nothing
started before setup is lost and the keychain buffer is gone. The webview logs
through $lib/utils/log, which writes to the console and forwards each line with
its level to a log_frontend command (replacing log_frontend_error). Every
println! became a log macro at a level matching what it reports. Release builds
keep info and up from the app and warn and up from everything else.

The file is capped at three files of 512 KB. Dev builds log to the terminal and to
stashpad-dev.log, so they no longer mix into the installed app's file, and the
CrabNebula devtools plugin is removed because the log crate allows one logger and
the two cannot coexist. Checked in a running debug build: early keychain lines and
frontend lines both reach the file. The ordering and bounding of early records, the
level filter and the frontend logger have unit tests.
The global shortcut plugin had a handler but nothing ever registered a shortcut
for it. The registration used to live in save_settings and was lost when that
file was split up; before that it ran only on a save, so it never survived a
restart. Pressing the shortcut set in Settings therefore did nothing on any
platform, with no error anywhere.

shortcuts.rs now registers settings.shortcuts["global_toggle"] in the setup hook
and again whenever save_settings sees it change. A failure never fails the save:
it is logged and kept for a global_shortcut_error command, and Settings shows it
beside the field. The plugin passes errors on as text, so a shortcut another app
already holds is recognised by rebuilding global-hotkey's own AlreadyRegistered
message for it rather than copying its wording. Only Windows and X11 report such
a clash; macOS registers non-exclusively and accepts it, so there is nothing to
detect there.

The picker wrote the =/+ key as "Plus", which the parser does not know, so such
a shortcut could never register; it writes "Equal" now. Tests cover every key
and modifier the picker can write. Checked in a running debug build, where the
saved shortcut registered at startup.
scratch_dir, write_scratch and file_name in browser_drop.rs are called only by the
macOS drop reader, so on Linux nothing used them and Clippy, which treats warnings
as errors in CI, failed the Ubuntu backend job on three dead-code findings. Every
commit since the browser-drop work failed it; macOS and Windows never saw it
because the code is live there, and Clippy only runs on Ubuntu.

The first two move into the macOS module that uses them. file_name stays outside it
because its tests run on every platform, and is compiled only on macOS and under
test. Clippy, rustfmt and the four browser_drop tests pass locally; the Linux
build itself can only be confirmed by CI.
The lockfile still named the app 1.9.0 in its two version fields, three releases
behind package.json. Nothing reads them at runtime, but a lockfile that
disagrees with its package.json is noise in every later diff, and a local npm
install kept rewriting them as an unrelated change.

Only those two fields: the same install also dropped the libc markers npm uses
to pick the right optional native packages on Linux, and those stay.
@EarMaster
EarMaster merged commit 3b1b805 into main Oct 5, 2026
21 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant