|
UnENVerse 0.42.6
Local-first desktop secrets manager — TypeScript frontend
|
import Settings;Functions | |
| function resetCapsProbe() | isVisible (el:HTMLElement) |
| Clears the platform calibration. | |
Variables | |
| const | EYE_OPEN |
| const | EYE_OFF |
| function export wireRevealButtons(root:ParentNode=document) const | CAPS_PROBE_QUORUM = 2 |
Wires every [data-reveal="<input id>"] button to toggle its input's type. | |
| let | _capsProbeAgreed = 0 |
| function topmostModal() let | _modalFocusWired = false |
| The open overlay nearest the top of the stack, or null. | |
| function resetCapsProbe() isVisible | ( | el:HTMLElement | ) |
Clears the platform calibration.
Test hook. The calibration describes the platform and so is deliberately session-lived; a test file that plays several different fake platforms inside one process has to reset it between them or the second one inherits the first's verdict. What the event says about Caps Lock, or null when the event cannot say.
getModifierState is missing on synthetic events and on old engines, and it is called on every keystroke in a password field, so this must never throw. Caps Lock per the platform, or null while the platform is not believed. Scores the platform's claim against a reading derived from a real character. Every overlay in this app is a div that gains a class, not a <dialog>.
That means the browser does nothing for us: focus stays wherever it was, Tab walks straight out of the modal into the grid behind it, and closing the modal leaves focus on an element that is now hidden — at which point a keyboard user is somewhere with no visible cursor and no way to tell where.
These are the three things a <dialog> would have done. Whether an element is actually on screen.
Not offsetParent !== null, which is the usual shorthand and wrong twice over: it is null for every position: fixed element even when visible — and every overlay in this app is fixed — and jsdom does no layout, so it is null for everything under test as well. Walking computed styles is correct in both, and also catches visibility: hidden, which offsetParent misses. Elements that can hold focus, in DOM order, excluding anything hidden.
| const EYE_OPEN |
| const EYE_OFF |
| function export wireRevealButtons (root: ParentNode = document) const CAPS_PROBE_QUORUM = 2 |
Wires every [data-reveal="<input id>"] button to toggle its input's type.
Assignment (onclick), not addEventListener: the unlock and relock screens are re-shown across a lock cycle, and stacking handlers there would toggle the field twice per click and leave it exactly as it was — the same bug showUnlockModal already guards against on the server-URL field. Puts a password field back in its masked state.
Called whenever a password screen opens. Without it, revealing a password once leaves every later visit to that screen showing plaintext — including the auto-lock screen, which is precisely the moment the user walked away from the machine. Shows hintId while Caps Lock is on and inputId has focus.
A masked field gives no feedback at all about case, so a Caps Lock slip on a master password reads as "wrong password" with no way to tell the difference.
**The state is derived from the character a key actually produced, never from ‘KeyboardEvent.getModifierState('CapsLock’).** WebKitGTK reports that from GDK's raw modifier mask, which is not the Caps Lock state: it was true on this app's unlock screen with Caps Lock off, so the hint appeared for every user, and keydown and keyup disagreed about it, so it flickered off again as soon as anyone typed. A cased letter is unambiguous evidence —aunshifted means off, A` unshifted means on, and holding Shift inverts both — and it is the same answer on every platform.
The cost was that the hint could not appear before the first letter is typed. That is the right trade against a warning that is confidently wrong all session — but it is not the only option, and [[_capsProbe]] buys most of it back: every derived reading is also used to check what ‘getModifierState('CapsLock’)` claimed, and once the platform has agreed with observed reality it is believed for the cheap paths (a click into the field, a press of the Caps Lock key itself) where there is no character to derive from. A platform that contradicts itself once is never asked again. Whether ‘getModifierState('CapsLock’)` has earned being believed on this platform, in this session.
unknown until typed characters have said what the lock really was; trusted after CAPS_PROBE_QUORUM consecutive agreements; untrusted permanently on the first disagreement — which is what WebKitGTK's always-true mask produces on the first lowercase letter anyone types.
There is deliberately no "consistently inverted" state. A mask that is always one value looks exactly like an inverted one until the lock changes, so believing an inversion would reintroduce the original bug in mirror image: a hint shown to every user, all session, from a platform that never knew. Disagreement is treated as evidence of lying, not of a sign error.
Module-level because it is a property of the platform, not of one field. Agreeing samples required before the platform's own claim is read.
| let _capsProbeAgreed = 0 |
| function topmostModal () let _modalFocusWired | ( | ) | = false |
The open overlay nearest the top of the stack, or null.