Detail view renders a signature block with a large monospace rotating code and
a thin SVG countdown ring that sweeps via CSS transition. The ticker polls
get_totp every second and is stopped on teardown (back/edit/trash/Escape/e/d/t).
Form has a two-button kind toggle (TOTP / Steam Guard) that re-renders in place
while preserving entered values. TOTP uses digits=6 kind='totp'; Steam uses
digits=5 kind='steam'. Both default to algorithm='sha1' period_seconds=30.
Keyboard shortcuts on detail: Escape=back, e=edit, d=trash, t=copy-code.
Guarded against stealing keystrokes from editable targets.
Wires totp.renderDetail / totp.renderForm into both dispatchers and calls
totp.teardown() alongside the other types so tickers can't leak across views.
Closes T8 of the extension 1C-β1 plan (5/5 typed-item modules in place;
only T9 picker and T10 acceptance remain).
- C1: escapeHtml now escapes " and ' so values stored in data-field-value
attributes (concealed rows, copyable rows) round-trip correctly. Prior
impl silently truncated passwords containing quotes. +3 regression tests.
- C2: centralize view-teardown. login.ts exports teardown() that stops
the TOTP ticker and removes the active keydown handler; item-detail.ts
and item-form.ts dispatchers call it before rendering the next view;
each button handler also calls teardown() locally for belt-and-suspenders.
- C3: restore alpha's keyboard shortcuts on login detail view: c
(copy username), p (copy password), t (copy TOTP), f (autofill), e
(edit), d (trash), plus Escape (back). All gated by the
is-editable-target guard so they don't eat keystrokes inside form fields.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Bug: item-list's global "/" shortcut (focus search) and "+" shortcut
(new item) fired even when focus was inside any input/textarea other
than the list's own search field. This ate forward-slashes typed into
the setup wizard's host-url field and the add/edit form's notes area,
and would have done the same for any printable shortcut in a future
text field.
Root cause: the handler was attached to `document`, stays attached
when the user opens an item (and its click-handler navigated without
removing the listener), and only excluded the search field by id.
Fix:
- Add isEditableTarget() helper — returns true for
INPUT/TEXTAREA/SELECT and contenteditable elements. Global shortcut
handlers bail early when this fires, passing the keystroke through
to the field.
- Apply the same guard in item-detail.ts (previously only guarded
against INPUT, missing TEXTAREA + contenteditable).
- Remove handleListKeydown on row-click so it doesn't linger on
detail/edit views even before the route-transition keydown
listeners install.
- Escape in the list view still works from inside an editable
field — only the printable-character interceptions are gated.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Rewrites item-detail.ts to dispatch on item.type: login gets the full
detail view (url, username, masked password + copy, TOTP with 30s
countdown, notes, group, autofill/edit/trash/back buttons). Non-login
types get a coming-soon placeholder; those grow full UIs in later slices.
Fixes Slice 4 review I1: the old autofill path sent a malformed
fill_credentials payload ({ username, password } — no id/capturedTab).
The new handler uses the (capturedTabId, capturedUrl) pair snapshotted
at popup-open and calls fill_credentials with { id, capturedTabId,
capturedUrl }, matching the SW's handler signature that enforces the
M5 + TOCTOU checks.
TOTP poll now calls get_totp on a 1s timer and renders the 30s countdown
bar against expires_at. @ts-nocheck removed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Git-moves the three popup components so history survives the content
rewrite that follows in Tasks 22–24:
- entry-list.ts → item-list.ts
- entry-detail.ts → item-detail.ts
- entry-form.ts → item-form.ts
Also renames the exported render functions (renderEntryList →
renderItemList, etc.) and updates popup.ts imports + render switch.
The files still wear @ts-nocheck and reference the old Entry type;
content rewriting happens in Tasks 22–24.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>