diff --git a/index.html b/index.html index b949def..3cf5573 100644 --- a/index.html +++ b/index.html @@ -691,6 +691,19 @@ automatically when the app is minimised — no manual setup needed.

+
+ + Auto-clear copied secrets after + Only clears if you haven't copied something else since. + + +
diff --git a/js/app.js b/js/app.js index 2da266d..ff01c02 100644 --- a/js/app.js +++ b/js/app.js @@ -68,12 +68,15 @@ const Bridge = (() => { active, // Copy text to clipboard, excluded from Win+V history. - // clearAfterMs: Delphi auto-clears after this many ms (0 = never). + // clearAfterMs: 0 = never auto-clear (username copies). Any positive + // value means "auto-clear this secret" and is overridden by the user's + // clipboardClearSeconds setting (0 there = user disabled auto-clear). // Returns true when the bridge handled the copy, false as fallback signal. copySecure(text, clearAfterMs = 30000) { if (!active) return false; + const ms = clearAfterMs > 0 ? (state.clipboardClearSeconds * 1000) : 0; cmd('cmd://clipboard/copy?text=' + encodeURIComponent(text) + - '&clear=' + clearAfterMs); + '&clear=' + ms); return true; }, @@ -646,6 +649,7 @@ const state = { recoveryConfigured: false, // refreshed by refreshRecoveryStatus on Settings open autofillEnabled: localStorage.getItem('autofillEnabled') !== '0', // default ON autofillClearField: localStorage.getItem('autofillClearField') !== '0', // default ON + clipboardClearSeconds: parseInt(localStorage.getItem('clipboardClearSeconds') ?? '30', 10), // 0 = never autofillFailBalloon: localStorage.getItem('autofillFailBalloon') !== '0', // default ON // Hotkey combos. Each combo = { ctrl, shift, alt, win, key }. // key is the uppercase character or VK label ('A'..'Z', '0'..'9', @@ -6365,6 +6369,7 @@ function openSettings() { $('#settingTrayNotifRow').style.display = Bridge.active ? '' : 'none'; $('#settingTrashPurge').value = String(state.trashAutoPurgeDays || 0); $('#settingPasswordExpiry').value = String(state.passwordExpiryDays || 0); + $('#settingClipboardClear').value = String(state.clipboardClearSeconds ?? 30); $('#settingEditorPosition').value = state.editorPosition || 'right'; $('#settingConfirmUnsaved').checked = state.confirmOnUnsaved !== false; // PIN unlock — only meaningful when DPAPI is available. @@ -6761,6 +6766,8 @@ const SYNCED_SETTING_KEYS = [ 'autofillClearField', // Tray balloon when a fill fails while the window is hidden (default ON). 'autofillFailBalloon', + // Seconds before a copied secret is auto-cleared (0 = never). Default 30. + 'clipboardClearSeconds', ]; // Sets `data-editor-position` on so CSS can swap the slideover @@ -6847,6 +6854,9 @@ async function loadServerSettings() { case 'autofillFailBalloon': localStorage.setItem('autofillFailBalloon', v ? '1' : '0'); break; + case 'clipboardClearSeconds': + localStorage.setItem('clipboardClearSeconds', String(v)); + break; } }); // Apply visual settings immediately. @@ -7531,6 +7541,13 @@ async function init() { if (n === 0) toast('Trash auto-purge disabled'); else toast('Trash will auto-purge after ' + n + ' days (next unlock)'); }); + $('#settingClipboardClear').addEventListener('change', e => { + const n = parseInt(e.target.value, 10) || 0; + state.clipboardClearSeconds = n; + localStorage.setItem('clipboardClearSeconds', String(n)); + saveServerSettings(); + toast(n === 0 ? 'Clipboard auto-clear disabled' : 'Copied secrets clear after ' + n + 's'); + }); $('#settingPasswordExpiry').addEventListener('change', e => { const n = parseInt(e.target.value, 10) || 0; state.passwordExpiryDays = n;