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;