fix(clipboard): copy toasts reflect the configured clear delay
The "clears in 30s" suffix was hardcoded in ~14 toasts. Single helper
clipClearSuffix() reads clipboardClearSeconds (''=Never); prefixes concatenated
to it. Cheatsheet text made generic "(auto-clears)".
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1106,6 +1106,13 @@ function toast(msg, type) {
|
||||
|
||||
function $(sel, root) { return (root || document).querySelector(sel); }
|
||||
function $$(sel, root) { return Array.from((root || document).querySelectorAll(sel)); }
|
||||
// Toast suffix for a just-copied secret, honouring the auto-clear setting.
|
||||
// '' when the user disabled auto-clear (Never).
|
||||
function clipClearSuffix() {
|
||||
const s = state.clipboardClearSeconds;
|
||||
return s > 0 ? ' · clears in ' + s + 's' : '';
|
||||
}
|
||||
|
||||
function el(tag, props, ...kids) {
|
||||
const e = document.createElement(tag);
|
||||
if (props) for (const k in props) {
|
||||
@@ -4205,7 +4212,7 @@ function buildCustomFieldRow(field, idx, rerender) {
|
||||
if (!v) return;
|
||||
if (Bridge.active) Bridge.copySecure(v, 30000);
|
||||
else { try { navigator.clipboard.writeText(v); } catch (_) {} }
|
||||
toast('Copied · clears in 30s');
|
||||
toast('Copied' + clipClearSuffix());
|
||||
});
|
||||
|
||||
const delBtn = el('button', { class: 'icon-btn icon-btn-sm', type: 'button',
|
||||
@@ -4366,10 +4373,10 @@ function soPasswordField(plain) {
|
||||
copy.appendChild(icon('i-copy'));
|
||||
copy.addEventListener('click', () => {
|
||||
if (Bridge.copySecure(input.value, 30000)) {
|
||||
toast('Copied · clears in 30s');
|
||||
toast('Copied' + clipClearSuffix());
|
||||
} else {
|
||||
navigator.clipboard.writeText(input.value).then(() => {
|
||||
toast('Copied · clears in 30s');
|
||||
toast('Copied' + clipClearSuffix());
|
||||
setTimeout(() => navigator.clipboard.writeText('').catch(()=>{}), 30000);
|
||||
});
|
||||
}
|
||||
@@ -4497,10 +4504,10 @@ function soTotpField(plainSecret) {
|
||||
try {
|
||||
const t = await generateTOTP(secret);
|
||||
if (Bridge.copySecure(t.code, 30000)) {
|
||||
toast('Code copied · clears in 30s');
|
||||
toast('Code copied' + clipClearSuffix());
|
||||
} else {
|
||||
navigator.clipboard.writeText(t.code).then(() => {
|
||||
toast('Code copied · clears in 30s');
|
||||
toast('Code copied' + clipClearSuffix());
|
||||
setTimeout(() => navigator.clipboard.writeText('').catch(()=>{}), 30000);
|
||||
});
|
||||
}
|
||||
@@ -5418,9 +5425,9 @@ async function copyPassword(entry) {
|
||||
const p = await decryptPwd(entry.encrypted_password, entry.iv);
|
||||
if (p === '[ERROR]') return toast('Cannot decrypt', 'error');
|
||||
if (Bridge.copySecure(p, 30000)) {
|
||||
toast('Password copied · clears in 30s');
|
||||
toast('Password copied' + clipClearSuffix());
|
||||
} else {
|
||||
navigator.clipboard.writeText(p).then(() => toast('Password copied · clears in 30s'));
|
||||
navigator.clipboard.writeText(p).then(() => toast('Password copied' + clipClearSuffix()));
|
||||
setTimeout(() => navigator.clipboard.writeText('').catch(()=>{}), 30000);
|
||||
}
|
||||
touchEntry(entry.id);
|
||||
@@ -7334,10 +7341,10 @@ async function init() {
|
||||
$('#genCopy').addEventListener('click', () => {
|
||||
if (!genCurrent) return;
|
||||
if (Bridge.copySecure(genCurrent, 30000)) {
|
||||
toast('Copied · clears in 30s');
|
||||
toast('Copied' + clipClearSuffix());
|
||||
} else {
|
||||
navigator.clipboard.writeText(genCurrent).then(() => {
|
||||
toast('Copied · clears in 30s');
|
||||
toast('Copied' + clipClearSuffix());
|
||||
setTimeout(() => navigator.clipboard.writeText('').catch(()=>{}), 30000);
|
||||
});
|
||||
}
|
||||
|
||||
+3
-3
@@ -152,7 +152,7 @@ async function quickSearchPickEntry(entry, mode) {
|
||||
if (!u) { toast('No username on this entry', 'warning'); return; }
|
||||
if (Bridge.active) Bridge.copySecure(u, 30000);
|
||||
else { try { await navigator.clipboard.writeText(u); } catch (_) {} }
|
||||
toast('Username copied · clears in 30s');
|
||||
toast('Username copied' + clipClearSuffix());
|
||||
} else {
|
||||
const pwd = await decryptPwd(entry.encrypted_password, entry.iv);
|
||||
if (pwd === '[ERROR]') { toast('Decryption error', 'error'); return; }
|
||||
@@ -202,7 +202,7 @@ const CHEATSHEET_GROUPS = [
|
||||
title: 'On each card',
|
||||
items: [
|
||||
{ keys: [{ icon: 'i-globe' }], desc: 'Open the site in your default browser' },
|
||||
{ keys: [{ icon: 'i-copy' }], desc: 'Copy password to the secure clipboard (auto-clears in 30s)' },
|
||||
{ keys: [{ icon: 'i-copy' }], desc: 'Copy password to the secure clipboard (auto-clears)' },
|
||||
{ keys: ['Click card'], desc: 'Open the entry details / edit panel' },
|
||||
],
|
||||
},
|
||||
@@ -306,7 +306,7 @@ async function openHistoryModal(entryId) {
|
||||
copy.addEventListener('click', () => {
|
||||
if (Bridge.active) Bridge.copySecure(plain, 30000);
|
||||
else { try { navigator.clipboard.writeText(plain); } catch (_) {} }
|
||||
toast('Copied · clears in 30s');
|
||||
toast('Copied' + clipClearSuffix());
|
||||
});
|
||||
preview.appendChild(copy);
|
||||
|
||||
|
||||
+2
-2
@@ -733,10 +733,10 @@ async function doGenerateRecoveryKey() {
|
||||
// running embedded, navigator.clipboard with manual scrub
|
||||
// otherwise.
|
||||
if (Bridge.copySecure(code, 30000)) {
|
||||
toast('Recovery code copied · clears in 30s');
|
||||
toast('Recovery code copied' + clipClearSuffix());
|
||||
} else {
|
||||
navigator.clipboard.writeText(code).then(() => {
|
||||
toast('Recovery code copied · clears in 30s');
|
||||
toast('Recovery code copied' + clipClearSuffix());
|
||||
setTimeout(() => navigator.clipboard.writeText('').catch(()=>{}), 30000);
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user