mirror of
https://github.com/narrrl/narl-workspace.git
synced 2026-11-03 16:41:27 +01:00
vault prompt: appears at once and stays put between questions
The password box rose into place like the [y/N] prompt, a 380 ms slide and fade, and was taken down and put up again for every question: twice for :vault, three times for :passwd, and right after the command line closed for :unlock. Whatever was typed in that time went into a field still moving and half transparent. It now appears without an entrance, and an answer puts it away a turn later, so a question that follows straight on takes over the same box. Password managers are asked to leave the field alone; it is not the login.
This commit is contained in:
1 parent
e4e3e2b5aa
commit
b19fb21fc4
2 files changed
+23
-5
No files matched your search
@@ -3,6 +3,12 @@
|
||||
* The password `workspace.askSecret` asks for, in the same place as the
|
||||
* `[y/N]` prompt. A masked field of its own rather than the command line, so
|
||||
* a password never shows on screen or lands in the command history.
|
||||
*
|
||||
* It appears at once rather than rising into place like the `[y/N]` prompt:
|
||||
* it is where the next keys go, and a field still sliding and fading in
|
||||
* under them reads as a stutter. Password managers are asked to leave the
|
||||
* field alone: it is not the login, and their menus redrawn on every key
|
||||
* are a flicker of their own.
|
||||
*/
|
||||
import { workspace } from './store.svelte'
|
||||
|
||||
@@ -38,6 +44,10 @@
|
||||
type="password"
|
||||
autocomplete="off"
|
||||
spellcheck="false"
|
||||
data-1p-ignore
|
||||
data-lpignore="true"
|
||||
data-bwignore
|
||||
data-form-type="other"
|
||||
bind:this={input}
|
||||
bind:value
|
||||
{onkeydown}
|
||||
@@ -67,7 +77,6 @@
|
||||
border-bottom: 0;
|
||||
border-radius: var(--radius-l) var(--radius-l) 0 0;
|
||||
font-size: 13px;
|
||||
animation: rise var(--t-slow) var(--ease-snap) both;
|
||||
}
|
||||
.text { flex: none; color: var(--light); }
|
||||
input {
|
||||
|
||||
@@ -125,7 +125,7 @@ class Workspace {
|
||||
*/
|
||||
prompt = $state<{ text: string; resolve: (yes: boolean) => void } | null>(null)
|
||||
/** A password asked for in the same place, typed into a masked field. */
|
||||
secret = $state<{ text: string; resolve: (value: string | null) => void } | null>(null)
|
||||
secret = $state.raw<{ text: string; resolve: (value: string | null) => void } | null>(null)
|
||||
/** The vault, as last heard from the server; null until asked. */
|
||||
vault = $state<VaultStatus | null>(null)
|
||||
media = $state<MediaFile[]>([])
|
||||
@@ -217,13 +217,22 @@ class Workspace {
|
||||
askSecret(text: string): Promise<string | null> {
|
||||
this.secret?.resolve(null)
|
||||
return new Promise((resolve) => {
|
||||
this.secret = {
|
||||
let answered = false
|
||||
const asked = {
|
||||
text,
|
||||
resolve: (value) => {
|
||||
this.secret = null
|
||||
resolve: (value: string | null) => {
|
||||
if (answered) return
|
||||
answered = true
|
||||
// Put away a turn later, so a question that follows straight on —
|
||||
// the second of two passwords — takes over the same box instead
|
||||
// of a new one appearing under the fingers already typing it.
|
||||
setTimeout(() => {
|
||||
if (this.secret === asked) this.secret = null
|
||||
})
|
||||
resolve(value)
|
||||
},
|
||||
}
|
||||
this.secret = asked
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user