keys act on the focused pane, deletes ask y/N in place

dd, x, i, R, s, y and :mv used the open document whenever one was open,
so walking the list and pressing dd deleted the document beside it. They
now act on the row under the cursor while the list has focus. Deletes ask
an in-app y/N naming the node instead of confirm(), and the board no
longer lets tree keys through to the hidden list.
This commit is contained in:
nvrl committed 2026-10-19 14:39:38 +02:00
1 parent 4ded89b0e7
commit d9b78170d8
6 files changed
+149 -28

No files matched your search

+36 -5
View File
@@ -9,6 +9,7 @@
import Login from './lib/Login.svelte'
import Overview from './lib/Overview.svelte'
import MediaBrowser from './lib/MediaBrowser.svelte'
import Prompt from './lib/Prompt.svelte'
import Rail from './lib/Rail.svelte'
import Shared from './lib/Shared.svelte'
import Sidebar from './lib/Sidebar.svelte'
@@ -58,6 +59,23 @@
}
})
/*
* A pending `[y/N]` takes the next key before anything else sees it — the
* editor included, where `y` would otherwise start a yank. Only `y` agrees;
* every other key, Escape among them, declines.
*/
$effect(() => {
const answer = (event: KeyboardEvent) => {
const prompt = workspace.prompt
if (!prompt || ['Shift', 'Control', 'Alt', 'Meta', 'CapsLock'].includes(event.key)) return
event.preventDefault()
event.stopPropagation()
prompt.resolve(event.key === 'y' || event.key === 'Y')
}
window.addEventListener('keydown', answer, true)
return () => window.removeEventListener('keydown', answer, true)
})
// Guard against losing a half-written entry to a stray refresh.
$effect(() => {
if (!workspace.dirty) return
@@ -178,9 +196,9 @@
/*
* The board reads the same keys as the list, one dimension wider: h/l walk
* the lists, j/k the cards, and the shifted pair takes the card along. Only
* `:` and `?` fall through to the keys below, because everything else would
* act on a tree that is not on screen.
* the lists, j/k the cards, and the shifted pair takes the card along.
* Nothing falls through to the tree keys, because they would act on a tree
* that is not on screen.
*/
function boardKey(key: string): boolean {
switch (key) {
@@ -331,7 +349,12 @@
workspace.cardCursor = 0
return
}
if (key === 'g') {
if (previous === 'd' && key === 'd') {
event.preventDefault()
void runCommand('delete')
return
}
if (key === 'g' || key === 'd') {
pending = key
return
}
@@ -339,6 +362,12 @@
event.preventDefault()
return
}
if (key === ':' || key === '?') {
event.preventDefault()
if (key === ':') cmdline = ':'
else void runCommand('help')
}
return
}
/*
@@ -444,7 +473,7 @@
break
case 's':
event.preventDefault()
void runCommand(workspace.selected?.shared ? 'unshare' : 'share')
void runCommand(workspace.target?.shared ? 'unshare' : 'share')
break
case 'y':
event.preventDefault()
@@ -543,6 +572,8 @@
<CommandLine initial={cmdline} close={() => (cmdline = null)} />
{/if}
<Prompt />
{#if workspace.overlay !== 'none'}
<!-- svelte-ignore a11y_click_events_have_key_events, a11y_no_static_element_interactions, a11y_no_noninteractive_tabindex -->
<div class="overlay" tabindex="-1" bind:this={overlayEl} onclick={(e) => e.target === e.currentTarget && (workspace.overlay = 'none')}