diff --git a/app/static/js/vault.js b/app/static/js/vault.js
index 3758d9f..eade3bd 100644
--- a/app/static/js/vault.js
+++ b/app/static/js/vault.js
@@ -480,8 +480,8 @@ const Vault = (() => {
_sortOrder === "folder"
? Object.keys(groups).sort()
: ["(No folder)", ..._folders.map((f) => f.name)].filter(
- (k) => groups[k],
- );
+ (k) => groups[k],
+ );
Object.keys(groups).forEach((k) => {
if (!keys.includes(k)) keys.push(k);
});
@@ -549,7 +549,7 @@ const Vault = (() => {
case "card":
subText = item.plain.card_number
? "•••• " +
- String(item.plain.card_number).replace(/\s/g, "").slice(-4)
+ String(item.plain.card_number).replace(/\s/g, "").slice(-4)
: "";
break;
case "bank":
@@ -634,6 +634,8 @@ const Vault = (() => {
// Wire the bulk-select checkbox.
const checkbox = li.querySelector(".item-checkbox");
if (checkbox) {
+ // Stop the click from bubbling to the li (which would open the modal).
+ checkbox.addEventListener("click", (e) => e.stopPropagation());
checkbox.addEventListener("change", () => {
if (checkbox.checked) {
_selectedIds.add(item.id);
@@ -714,7 +716,18 @@ const Vault = (() => {
confirmDeleteItem(item);
},
);
- li.addEventListener("click", () => openModal("edit", item));
+ li.addEventListener("click", (e) => {
+ if (_selectMode) {
+ // Toggle the checkbox when the row itself is clicked (not the checkbox).
+ const cb = li.querySelector(".item-checkbox");
+ if (cb && e.target !== cb) {
+ cb.checked = !cb.checked;
+ cb.dispatchEvent(new Event("change"));
+ }
+ return;
+ }
+ openModal("edit", item);
+ });
return li;
}
@@ -1112,9 +1125,9 @@ const Vault = (() => {
0,
Math.round(
100 -
- (weak.length / total) * 40 -
- (reused.length / total) * 30 -
- (old.length / total) * 15,
+ (weak.length / total) * 40 -
+ (reused.length / total) * 30 -
+ (old.length / total) * 15,
),
);
const cls =
@@ -1264,16 +1277,16 @@ const Vault = (() => {
- ${
- hasFields
- ? '
'
- : '
Could not decrypt this item.
'
+ ${hasFields
+ ? '
'
+ : '
Could not decrypt this item.
'
}
`;
@@ -2721,8 +2732,8 @@ const Vault = (() => {
const typeLabel = transports.includes("internal")
? "📱 Device"
: transports.some((t) => ["usb", "nfc", "ble", "smart-card"].includes(t))
- ? "🔑 Security key"
- : "🔑 Passkey";
+ ? "🔑 Security key"
+ : "🔑 Passkey";
return `
${escHtml(c.name)}
@@ -2985,16 +2996,15 @@ const Vault = (() => {
${isFirstTime ? "🔐 MFA enabled — save your backup codes" : "🔐 New backup codes"}
- ${
- isFirstTime
- ? `
+ ${isFirstTime
+ ? `
These codes let you sign in if you lose access to your authenticator app.
Save them now — they will not be shown again.
`
- : `
+ : `
Your previous codes have been invalidated. Save these new codes securely.
`
- }
+ }
${codesHtml}
@@ -3503,14 +3513,14 @@ const Vault = (() => {
const pool = !_activeFilter
? _items
: _activeFilter.type === "itemType"
- ? _items.filter((i) => i.item_type === _activeFilter.value)
- : _activeFilter.type === "folder"
- ? _items.filter((i) => i.folder_id === _activeFilter.value)
- : _activeFilter.type === "tag"
- ? _items.filter((i) =>
- (i.plain?.tags || []).includes(_activeFilter.value),
- )
- : _items;
+ ? _items.filter((i) => i.item_type === _activeFilter.value)
+ : _activeFilter.type === "folder"
+ ? _items.filter((i) => i.folder_id === _activeFilter.value)
+ : _activeFilter.type === "tag"
+ ? _items.filter((i) =>
+ (i.plain?.tags || []).includes(_activeFilter.value),
+ )
+ : _items;
renderItemList(
pool.filter((item) => {
const p = item.plain || {};
@@ -3719,7 +3729,7 @@ const Vault = (() => {
if (
(mode === "add" &&
(document.getElementById("field-type").value || "password") ===
- "password") ||
+ "password") ||
(mode === "edit" && (item?.item_type || "password") === "password")
) {
initPasswordFieldEnhancements();
@@ -3984,7 +3994,7 @@ const Vault = (() => {
"X-CSRFToken": csrfToken(),
},
body: JSON.stringify({ refresh_token: refreshToken }),
- }).catch(() => {});
+ }).catch(() => { });
VaultSession.clear();
SharingSession.clear();
sessionStorage.removeItem("access_token");
@@ -4089,11 +4099,11 @@ const Vault = (() => {
// Auto-clear clipboard after 30 seconds — industry-standard hygiene.
if (_clipboardClearTimer) clearTimeout(_clipboardClearTimer);
_clipboardClearTimer = setTimeout(() => {
- navigator.clipboard.writeText("").catch(() => {});
+ navigator.clipboard.writeText("").catch(() => { });
_clipboardClearTimer = null;
}, 30_000);
})
- .catch(() => {});
+ .catch(() => { });
}
function escHtml(str) {
@@ -4713,4 +4723,4 @@ const Vault = (() => {
}
})();
-document.addEventListener("DOMContentLoaded", Vault.init);
+document.addEventListener("DOMContentLoaded", Vault.init);
\ No newline at end of file