feat: quick-search fill modes + editable custom-field combobox + JS build gate

Quick search (Ctrl+Shift+Q fill mode)
- Enter / left-click → full autofill (username + Tab + password), like
  Ctrl+Shift+L.
- Shift+Enter / right-click → username only (new Delphi username-only
  SendInput path via field=user; ExecuteAutofill AUsernameOnly param).
- Ctrl+Enter / Ctrl+click → password only.
- Copy mode (tray / palette) unchanged: Enter/left = password,
  Shift+Enter/right = username.
- Clipboard fix: copy-then-minimise no longer wipes the just-copied
  password — MinimizeToTray takes an AClearClipboard flag (False on the
  quick-search copy path, driven by app/minimize?keepclip=1). The 30s
  auto-clear still guards it.
- Right-click on a result row suppresses the native/custom context menu
  (preventDefault + stopPropagation).

Editable custom-field combobox
- Option-backed custom fields (card brand, expiry year/month, etc.) now
  render a custom editable combobox instead of a locked <select>: an
  arrow drops a menu of ALL options (a native <datalist> filtered to the
  typed text, which confused users), while the input stays freely
  typeable for values not in the list. Storage shape unchanged.
- Outside-click closes the menu via the existing slideover mousedown
  handler; item mousedown + preventDefault so blur doesn't race the pick.

Build safety
- BuildAssets.ps1 runs `node --check` on every embedded .js before
  generating assets.res. A syntax error now aborts the asset build
  (exit 1, file + line logged) instead of shipping a dead bundle that
  only surfaces after a full Delphi rebuild. Node is optional: absent →
  warn and continue.

Docs
- CODE_AUDIT.md: full static-analysis report (security, latent bugs,
  maintainability, future features, prioritized action plan).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
r-zakarya
2026-07-03 08:13:25 +01:00
parent 7440d07793
commit 3076fec710
7 changed files with 507 additions and 73 deletions
+33
View File
@@ -1591,6 +1591,39 @@ input[type="range"]::-webkit-slider-thumb {
padding: 4px 8px;
font-size: 12px;
}
/* Editable combobox for option-backed custom fields (card brand, expiry
year…). Input fills the cell; the arrow drops a menu of ALL options. */
.so-combo { position: relative; display: flex; align-items: center; }
.so-combo-input { flex: 1; padding-right: 24px !important; width: 100%; }
.so-combo-arrow {
position: absolute; right: 2px; top: 50%;
transform: translateY(-50%);
display: flex; align-items: center; justify-content: center;
width: 20px; height: 20px;
background: transparent; border: 0; padding: 0;
color: var(--text-faint); cursor: pointer;
}
.so-combo-arrow svg { width: 14px; height: 14px; }
.so-combo-arrow:hover { color: var(--text); }
.so-combo-menu {
position: absolute; top: calc(100% + 2px); left: 0; right: 0;
z-index: 20;
max-height: 200px; overflow-y: auto;
background: var(--bg-elev-2);
border: 1px solid var(--border);
border-radius: var(--radius-sm);
box-shadow: var(--shadow);
padding: 4px;
}
.so-combo-menu.is-hidden { display: none; }
.so-combo-item {
padding: 6px 10px;
font-size: 12px;
border-radius: 4px;
cursor: pointer;
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.so-combo-item:hover { background: var(--accent); color: #fff; }
.so-custom-secret-toggle {
background: var(--bg);
border: 1px solid var(--border);