keys: passwords, titles and names without the pointer

A keystore or encrypted key asks for its password as soon as it is
opened, asks again after a wrong one, and Enter on the file pane asks
once more after Escape — the button was the only way in before. Enter on
a sealed file opens the vault the same way.

`:name` on its own, while writing, moves up into the title, and Enter,
Escape, Down or Tab there goes back into the text; the title could not be
reached from the editor at all. `R` starts the command line from the
current name — of the row, the open document, the card or the list —
instead of an empty one.

`s` on a shared document and `y` both ask y/N before they cut readers
off: y is what a vim hand presses to yank, and it retired the live link
without a word.
This commit is contained in:
nvrl committed 2026-10-20 13:44:37 +02:00
1 parent 4bf8634991
commit 007fb1d3e3
7 files changed
+109 -27

No files matched your search

+23 -6
View File
@@ -354,7 +354,8 @@
return true
case 'R':
// On an empty list there is no card to rename, so it is the list.
cmdline = workspace.card ? ':name ' : ':name! '
// The name is there to be edited, not typed again from nothing.
cmdline = workspace.card ? `:name ${workspace.card.title}` : `:name! ${workspace.list?.name ?? ''}`
return true
case 'D':
cmdline = ':due '
@@ -574,6 +575,7 @@
case 'l':
case 'ArrowRight':
event.preventDefault()
if (key === 'Enter' && reading && hooks.fileAction()) break
if (workspace.open && workspace.selected?.id === workspace.open.id) focusPane('document')
else void workspace.guard(() => workspace.openSelected())
break
@@ -616,11 +618,15 @@
event.preventDefault()
void runCommand('board')
break
case 'R':
// Renaming needs a name typed, and names are typed on the command line.
case 'R': {
// Renaming needs a name typed, and names are typed on the command
// line — starting from the one it has, so a typo is a fix, not a retype.
event.preventDefault()
cmdline = ':name '
const target = workspace.target
const current = target && target.id === workspace.open?.id ? workspace.draft.name : (target?.name ?? '')
cmdline = `:name ${current.trim()}`
break
}
case 'h':
case 'ArrowLeft':
// Leftwards at every depth: from the document to the list, from the
@@ -640,12 +646,23 @@
void runCommand('d')
break
case 's':
// Sharing is a key away; taking a link back from its readers asks first.
event.preventDefault()
void runCommand(workspace.target?.shared ? 'unshare' : 'share')
void (async () => {
const target = workspace.target
if (target?.shared && !(await workspace.ask(`stop sharing "${target.name.trim() || target.slug}"? the link stops working`))) return
void runCommand(target?.shared ? 'unshare' : 'share')
})()
break
case 'y':
// A vim hand presses y to yank; here it retires the link readers have,
// so it asks first.
event.preventDefault()
void runCommand('link')
void (async () => {
const target = workspace.target
if (!target?.shared) return void runCommand('link')
if (await workspace.ask(`new share link for "${target.name.trim() || target.slug}"? the current one stops working`)) void runCommand('link')
})()
break
case 'n':
event.preventDefault()