From 809c99d5bba1102e244ab4a876baa6ce23e6a1e3 Mon Sep 17 00:00:00 2001 From: debont80 Date: Wed, 1 Jul 2026 11:17:23 -0400 Subject: [PATCH] fix(renderer): L138/L145 clipboard privacy+dedup, M14 state-driven settings search MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - L138: gate the clipboard check on the settings `loaded` flag (not just clipboardWatch), so it never reads using the pre-load fallback; the effect re-runs when loaded flips true so a pre-launch copied link is still offered. - L145: lastSeen is module-level, so a dismissed clipboard link stays suppressed across the hook's remount on a Downloads<->Library tab switch. - M14: SettingsView renders each card in a React-owned wrapper and drives its visibility from a `hidden` state array — the search no longer writes display:none onto a card's own DOM node. Matching still reads textContent (full label coverage, no per-card keyword upkeep). typecheck + 268 tests + eslint + prettier green. Co-Authored-By: Claude Opus 4.8 --- CODE-AUDIT.md | 20 ++++- src/renderer/src/components/SettingsView.tsx | 86 +++++++++++--------- src/renderer/src/useClipboardLink.ts | 25 ++++-- 3 files changed, 82 insertions(+), 49 deletions(-) diff --git a/CODE-AUDIT.md b/CODE-AUDIT.md index 6257598..67bd0e4 100644 --- a/CODE-AUDIT.md +++ b/CODE-AUDIT.md @@ -363,9 +363,14 @@ token system + shared primitives (UI/SIMP — high value, larger effort) · i18n those to the shared hook incrementally.* - [x] **M13 — Inconsistent secret-field masking.** `updateToken` uses `type="password"`; `proxy` (may carry `user:pass@`) and `youtubePoToken` (a token) are plain-text Inputs. -- [ ] **M14 — Settings search mutates React-owned DOM.** The search toggles each card's +- [x] **M14 — Settings search mutates React-owned DOM.** The search toggles each card's `el.style.display` directly; fragile (breaks if a card ever gets a conditional `style`) and - matches on `textContent` incl. hidden text. Prefer state-driven filtering. + matches on `textContent` incl. hidden text. Prefer state-driven filtering. *Fixed: each card renders + inside a React-owned wrapper whose visibility is driven by a `hidden` state array in + [SettingsView.tsx](src/renderer/src/components/SettingsView.tsx) — the filter no longer writes + `display` onto a card's own node, so a card setting its own inline style can't break it. Matching still + reads the wrapper's `textContent` (so search covers every visible label without hand-maintained + per-card keywords); the minor "matches hidden descendant text" point is unchanged and left as-is.* - [x] **M15 — Nested interactive controls in `role="button"` (a11y).** LibraryView's group header is a `role="button"` div containing `