desktop: a global hotkey opens a small window to write in, now with its lockfile
Android / Build, or is the channel already serving this? (push) Successful in 3s
CI & Build / Build now, or wait for Android? (push) Successful in 3s
CI & Build / Python lint (push) Successful in 4s
Desktop (Tauri) / Build, or is the channel already serving this? (push) Successful in 3s
CI & Build / TypeScript typecheck (push) Successful in 7s
CI & Build / Python tests (push) Successful in 13s
CI & Build / integration (push) Successful in 29s
CI & Build / Build & push image (push) Skipped
Desktop (Tauri) / Tauri desktop (Linux) (push) Failing after 1m5s
Desktop (Tauri) / Windows installer (cross-compiled) (push) Successful in 1m52s
Desktop (Tauri) / Update manifest (push) Skipped
Android / Kotlin + Rust (APK) (push) Successful in 7m22s
Android / Build, or is the channel already serving this? (push) Successful in 3s
CI & Build / Build now, or wait for Android? (push) Successful in 3s
CI & Build / Python lint (push) Successful in 4s
Desktop (Tauri) / Build, or is the channel already serving this? (push) Successful in 3s
CI & Build / TypeScript typecheck (push) Successful in 7s
CI & Build / Python tests (push) Successful in 13s
CI & Build / integration (push) Successful in 29s
CI & Build / Build & push image (push) Skipped
Desktop (Tauri) / Tauri desktop (Linux) (push) Failing after 1m5s
Desktop (Tauri) / Windows installer (cross-compiled) (push) Successful in 1m52s
Desktop (Tauri) / Update manifest (push) Skipped
Android / Kotlin + Rust (APK) (push) Successful in 7m22s
Restores42e06da, which was reverted only because Cargo.lock had not been updated for the new crate and every cargo invocation in CI passes `--locked`. Both desktop jobs failed on that line before compiling anything, so nothing about the code had been judged. The lockfile was generated in CI's own `ci-tauri:1.97` image — one container, `cargo fetch`, nothing built. `cargo fetch` and NOT `generate-lockfile`: the latter re-resolves from scratch and would have churned versions across the whole workspace to add one dependency. The diff is 67 insertions, zero deletions, six packages — tauri-plugin-global-shortcut plus global-hotkey, x11rb, x11rb-protocol, xkeysym and gethostname. Nothing existing moved. The feature itself, unchanged from42e06da: Press the combination anywhere and a small window arrives over whatever you were doing; type, Ctrl/Cmd+Enter, gone. The board never comes forward. There is no default shortcut on purpose — any default is a key combination taken away from something else on somebody's machine, silently, at install time. CommandOrControl+Shift+N is offered as a one-click suggestion. Stored and live are separate fields because they disagree: a combination another app holds is saved and does nothing when pressed, and a Wayland compositor may refuse global grabs outright. `capture_shortcut_set` registers before storing, so a refused combination is never written down as if it worked. The window hides rather than closes and keeps its text, so an interrupted capture is still there next press — which is what makes Escape safe. A failed save keeps it open too, rather than discarding the only copy of something just written in order to report a retryable problem. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01K3MMqUtzX1TJgA1oypvm1c
This commit is contained in:
@@ -5,6 +5,13 @@
|
||||
|
||||
interface TauriGlobal {
|
||||
core: { invoke: <T>(cmd: string, args?: Record<string, unknown>) => Promise<T> };
|
||||
// Also from `withGlobalTauri`. Needed because quick capture puts the app in TWO
|
||||
// windows, each with its own Pinia stores — a note saved in one is invisible to
|
||||
// the other until something says so, and an event is the only channel between
|
||||
// them that does not involve polling SQLite.
|
||||
event?: {
|
||||
listen: <T>(event: string, handler: (e: { payload: T }) => void) => Promise<() => void>;
|
||||
};
|
||||
}
|
||||
|
||||
declare global {
|
||||
@@ -192,3 +199,49 @@ export const updates = {
|
||||
*/
|
||||
install: () => invoke<void>("update_install"),
|
||||
};
|
||||
|
||||
|
||||
// --- Quick capture (#1899) ---------------------------------------------------
|
||||
|
||||
/**
|
||||
* The stored hotkey and whether the OS actually accepted it.
|
||||
*
|
||||
* They disagree more often than you would like: a combination can be saved and
|
||||
* refuse to register because a window manager or another app already holds it,
|
||||
* and on Wayland a compositor may refuse global grabs entirely. `registered:
|
||||
* false` alongside a non-empty `shortcut` is precisely that case, and the UI has
|
||||
* to say so — a hotkey that silently does nothing is worse than none, because
|
||||
* there is nothing to look at and nothing to fix.
|
||||
*/
|
||||
export interface CaptureShortcut {
|
||||
/** The stored combination, or "" when quick capture is off. */
|
||||
shortcut: string;
|
||||
registered: boolean;
|
||||
}
|
||||
|
||||
/** Offered as a starting point, never applied on the user's behalf. */
|
||||
export const SUGGESTED_CAPTURE_SHORTCUT = "CommandOrControl+Shift+N";
|
||||
|
||||
/** Fired at the main window after a capture is saved. */
|
||||
const CAPTURED_EVENT = "thoughtsync://captured";
|
||||
|
||||
export const capture = {
|
||||
shortcut: () => invoke<CaptureShortcut>("capture_shortcut_get"),
|
||||
/** Pass "" to turn quick capture off. Rejects if the system refuses it. */
|
||||
setShortcut: (shortcut: string) => invoke<CaptureShortcut>("capture_shortcut_set", { shortcut }),
|
||||
/** Hide the capture window; `saved` decides whether the board is told to reload. */
|
||||
done: (saved: boolean) => invoke<void>("capture_done", { saved }),
|
||||
};
|
||||
|
||||
/**
|
||||
* Run `handler` whenever a note is captured in the other window.
|
||||
*
|
||||
* Returns an unlisten function, or a no-op on the web build and on any desktop
|
||||
* runtime that does not expose the event API — the board simply keeps showing
|
||||
* what it has until its next load, which is a stale list rather than a broken one.
|
||||
*/
|
||||
export async function onCaptured(handler: () => void): Promise<() => void> {
|
||||
const events = window.__TAURI__?.event;
|
||||
if (!events) return () => {};
|
||||
return events.listen(CAPTURED_EVENT, () => handler());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user