Add Ignore button to auto-detect warnings for permanent per-value dismissal
The × close button only hid the warning for the current send — the same detection reappeared on every subsequent send with no way to silence it. Added an Ignore button to each item in both the on-send warning (showAutoDetectWarning) and the pre-send input scanner warning (showPreSendWarning). Clicking Ignore: - Adds the specific value to an in-memory Set (ignoredDetections) - Persists it to ss_ignored_detections in storage - Removes that item from the current warning; closes the popup if empty On page load, ss_ignored_detections is read from storage so ignores survive page reloads. Ignored values are also filtered before auto-redaction in the fetch interceptor, so they are not redacted either. https://claude.ai/code/session_01CwcZK8nqL8pyBH9AxDs9qo
This commit is contained in:
@@ -220,6 +220,18 @@
|
|||||||
.ss-ps-add:hover { background: rgba(74, 222, 128, 0.15); }
|
.ss-ps-add:hover { background: rgba(74, 222, 128, 0.15); }
|
||||||
.ss-ps-add:disabled { border-color: #333; cursor: default; }
|
.ss-ps-add:disabled { border-color: #333; cursor: default; }
|
||||||
|
|
||||||
|
.ss-ad-ignore {
|
||||||
|
margin-left: 4px;
|
||||||
|
padding: 2px 6px;
|
||||||
|
font-size: 11px;
|
||||||
|
background: transparent;
|
||||||
|
border: 1px solid #555;
|
||||||
|
border-radius: 4px;
|
||||||
|
color: #888;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.ss-ad-ignore:hover { border-color: #888; color: #ccc; }
|
||||||
|
|
||||||
/* Floating reveal mode indicator */
|
/* Floating reveal mode indicator */
|
||||||
.ss-reveal-badge {
|
.ss-reveal-badge {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
|
|||||||
+40
-3
@@ -16,6 +16,8 @@
|
|||||||
let mappings = [];
|
let mappings = [];
|
||||||
let identity = {};
|
let identity = {};
|
||||||
let settings = { enabled: true, revealMode: false, showHighlights: false };
|
let settings = { enabled: true, revealMode: false, showHighlights: false };
|
||||||
|
// Values the user has permanently dismissed from auto-detect warnings
|
||||||
|
let ignoredDetections = new Set();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const configEl = document.querySelector('script[data-ss-config]');
|
const configEl = document.querySelector('script[data-ss-config]');
|
||||||
@@ -278,7 +280,8 @@
|
|||||||
// 4. Auto-detect: scan the FINAL text for unconfigured PII
|
// 4. Auto-detect: scan the FINAL text for unconfigured PII
|
||||||
// Auto-redact if enabled, otherwise just warn
|
// Auto-redact if enabled, otherwise just warn
|
||||||
if (settings.autoDetect !== false) {
|
if (settings.autoDetect !== false) {
|
||||||
const warnings = autoDetectPII(finalText, identity, { detectProperNouns: settings.detectProperNouns === true });
|
const warnings = autoDetectPII(finalText, identity, { detectProperNouns: settings.detectProperNouns === true })
|
||||||
|
.filter(w => !ignoredDetections.has(w.value));
|
||||||
if (warnings.length > 0) {
|
if (warnings.length > 0) {
|
||||||
// Auto-redact detected PII in the outbound text
|
// Auto-redact detected PII in the outbound text
|
||||||
if (settings.autoRedactDetected !== false) {
|
if (settings.autoRedactDetected !== false) {
|
||||||
@@ -516,6 +519,7 @@
|
|||||||
<span class="ss-ad-type">${w.name}</span>
|
<span class="ss-ad-type">${w.name}</span>
|
||||||
<code class="ss-ad-value">${w.value.length > 30 ? w.value.slice(0, 27) + '...' : w.value}</code>
|
<code class="ss-ad-value">${w.value.length > 30 ? w.value.slice(0, 27) + '...' : w.value}</code>
|
||||||
<span class="ss-ad-hint">${w.hint}</span>
|
<span class="ss-ad-hint">${w.hint}</span>
|
||||||
|
<button class="ss-ad-ignore" data-value="${encodeURIComponent(w.value)}" title="Never warn about this again">Ignore</button>
|
||||||
</div>`
|
</div>`
|
||||||
).join('');
|
).join('');
|
||||||
|
|
||||||
@@ -533,11 +537,24 @@
|
|||||||
|
|
||||||
warningEl.classList.add('visible');
|
warningEl.classList.add('visible');
|
||||||
|
|
||||||
// Close button
|
// Close button — hides for this session
|
||||||
warningEl.querySelector('.ss-ad-close').addEventListener('click', () => {
|
warningEl.querySelector('.ss-ad-close').addEventListener('click', () => {
|
||||||
warningEl.classList.remove('visible');
|
warningEl.classList.remove('visible');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Ignore buttons — permanently dismiss a specific value
|
||||||
|
warningEl.querySelectorAll('.ss-ad-ignore').forEach(btn => {
|
||||||
|
btn.addEventListener('click', () => {
|
||||||
|
const val = decodeURIComponent(btn.dataset.value);
|
||||||
|
ignoredDetections.add(val);
|
||||||
|
setStorageData('ss_ignored_detections', [...ignoredDetections]);
|
||||||
|
btn.closest('.ss-ad-item').remove();
|
||||||
|
if (!warningEl.querySelector('.ss-ad-item')) {
|
||||||
|
warningEl.classList.remove('visible');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
// Auto-dismiss after 15 seconds
|
// Auto-dismiss after 15 seconds
|
||||||
if (warningTimeout) clearTimeout(warningTimeout);
|
if (warningTimeout) clearTimeout(warningTimeout);
|
||||||
warningTimeout = setTimeout(() => {
|
warningTimeout = setTimeout(() => {
|
||||||
@@ -1348,6 +1365,7 @@
|
|||||||
${settings.autoAddDetected !== false
|
${settings.autoAddDetected !== false
|
||||||
? `<button class="ss-ps-add" data-real="${encodeURIComponent(w.value)}" data-fake="${encodeURIComponent(fake)}" data-cat="${w.category}" title="Add mapping: ${displayVal} → ${fake}">+</button>`
|
? `<button class="ss-ps-add" data-real="${encodeURIComponent(w.value)}" data-fake="${encodeURIComponent(fake)}" data-cat="${w.category}" title="Add mapping: ${displayVal} → ${fake}">+</button>`
|
||||||
: ''}
|
: ''}
|
||||||
|
<button class="ss-ad-ignore" data-value="${encodeURIComponent(w.value)}" title="Never warn about this again">Ignore</button>
|
||||||
</div>`;
|
</div>`;
|
||||||
}).join('');
|
}).join('');
|
||||||
|
|
||||||
@@ -1410,6 +1428,19 @@
|
|||||||
btn.disabled = true;
|
btn.disabled = true;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Ignore buttons — permanently dismiss a specific value
|
||||||
|
preSendWarningEl.querySelectorAll('.ss-ad-ignore').forEach(btn => {
|
||||||
|
btn.addEventListener('click', () => {
|
||||||
|
const val = decodeURIComponent(btn.dataset.value);
|
||||||
|
ignoredDetections.add(val);
|
||||||
|
setStorageData('ss_ignored_detections', [...ignoredDetections]);
|
||||||
|
btn.closest('.ss-ps-item').remove();
|
||||||
|
if (!preSendWarningEl.querySelector('.ss-ps-item')) {
|
||||||
|
preSendWarningEl.classList.remove('visible');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replace all occurrences of `real` with `fake` in an input or contenteditable element
|
// Replace all occurrences of `real` with `fake` in an input or contenteditable element
|
||||||
@@ -1464,7 +1495,8 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const warnings = autoDetectPII(text, identity, { detectProperNouns: settings.detectProperNouns === true });
|
const warnings = autoDetectPII(text, identity, { detectProperNouns: settings.detectProperNouns === true })
|
||||||
|
.filter(w => !ignoredDetections.has(w.value));
|
||||||
if (warnings.length > 0) {
|
if (warnings.length > 0) {
|
||||||
showPreSendWarning(warnings, target);
|
showPreSendWarning(warnings, target);
|
||||||
} else if (preSendWarningEl) {
|
} else if (preSendWarningEl) {
|
||||||
@@ -1542,6 +1574,11 @@
|
|||||||
document.addEventListener('DOMContentLoaded', boot);
|
document.addEventListener('DOMContentLoaded', boot);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Load permanently-ignored detections from storage
|
||||||
|
getStorageData('ss_ignored_detections').then(data => {
|
||||||
|
if (Array.isArray(data)) ignoredDetections = new Set(data);
|
||||||
|
});
|
||||||
|
|
||||||
// Also update badge when settings change
|
// Also update badge when settings change
|
||||||
const origCheckReveal = checkRevealToggle;
|
const origCheckReveal = checkRevealToggle;
|
||||||
checkRevealToggle = function () {
|
checkRevealToggle = function () {
|
||||||
|
|||||||
Reference in New Issue
Block a user