mirror of
https://github.com/olehomelchenko/astrolabe.git
synced 2026-08-08 02:02:33 +00:00
Add global keyboard EventRouter and unify publish (M6, §01D)
One module owns the document keydown listener and dispatches the shortcut map (Cmd/Ctrl+Shift+N / +K / +S / +, / Escape), platform-aware, via the single-source focus-utils interactive-context gate. Escape and Cmd/Ctrl+S run before the gate so save works while editing; the rest are suppressed mid-typing. Publish + its toast move into services/snippet-actions so the button and Cmd/Ctrl+S behave identically. Removes the ad-hoc keydown handler from App and Monaco's Cmd+S command.
This commit is contained in:
@@ -320,7 +320,17 @@ function onKeyDown(e: KeyboardEvent): void {
|
||||
|
||||
const mod = isMac ? e.metaKey : e.ctrlKey;
|
||||
|
||||
// --- Shortcuts: never fire while typing in an input or Monaco ----------
|
||||
// Cmd/Ctrl + S -> publish current draft. Checked BEFORE the interactive-context
|
||||
// gate: it is the canonical "save" shortcut (spec §01D mandates it override the
|
||||
// browser default), and publishing happens *while editing the draft in Monaco* —
|
||||
// gating it behind "not typing" would defeat its purpose.
|
||||
if (mod && !e.shiftKey && e.key.toLowerCase() === 's') {
|
||||
e.preventDefault(); // override the browser "save page" dialog
|
||||
useSnippetStore.getState().publishDraft();
|
||||
return;
|
||||
}
|
||||
|
||||
// --- Remaining shortcuts: never fire while typing in an input or Monaco ----
|
||||
if (isInInteractiveContext()) return;
|
||||
|
||||
// Cmd/Ctrl + Shift + N -> new snippet
|
||||
@@ -336,16 +346,12 @@ function onKeyDown(e: KeyboardEvent): void {
|
||||
toggleDatasets();
|
||||
return;
|
||||
}
|
||||
// Cmd/Ctrl + S -> publish current draft
|
||||
if (mod && e.key.toLowerCase() === 's') {
|
||||
e.preventDefault(); // override the browser "save page" dialog
|
||||
useSnippetStore.getState().publishDraft();
|
||||
return;
|
||||
}
|
||||
// Cmd/Ctrl + , -> settings (through the coordinator: snapshot + URL sync)
|
||||
// Cmd/Ctrl + , -> open the editor settings popover. Settings are distributed to
|
||||
// per-pane disclosure popovers, not a modal (spec §07), so this opens the editor
|
||||
// cluster (openSettingsPopover) — there is no 'settings' modal to open.
|
||||
if (mod && e.key === ',') {
|
||||
e.preventDefault();
|
||||
openModal('settings');
|
||||
openSettingsPopover('editor-settings');
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -392,9 +398,13 @@ by inserting a rung at the right priority — never by sprinkling
|
||||
`e.preventDefault()` so Cmd/Ctrl+S does not trigger "save page", Cmd/Ctrl+K
|
||||
does not focus the browser search bar, etc.
|
||||
|
||||
Note the asymmetry: **Escape is checked before the interactive-context gate**
|
||||
(you want Escape to dismiss a modal even while focus is in the editor), whereas
|
||||
all other shortcuts are checked **after** the gate (so they don't fire mid-typing).
|
||||
Note the asymmetry: **Escape and Cmd/Ctrl+S are checked before the
|
||||
interactive-context gate.** Escape, so it dismisses a modal even while focus is in
|
||||
the editor; Cmd/Ctrl+S, because publishing the draft is something you do _while_
|
||||
editing it — gating "save" behind "not typing" would defeat it (and it must
|
||||
override the browser's "save page" regardless). The remaining shortcuts (new
|
||||
snippet, toggle Datasets, settings) are checked **after** the gate, so they never
|
||||
fire mid-typing or steal a key the editor wants (e.g. Monaco's own Cmd+K chord).
|
||||
|
||||
### 2.2 The single-source helper: `orchestration/focus-utils.ts`
|
||||
|
||||
|
||||
Reference in New Issue
Block a user