Autofocus the lockscreen

This commit is contained in:
Timothy Farrell 2026-05-15 21:08:37 +00:00
parent c0231fcd26
commit 84f861a06a
2 changed files with 33 additions and 15 deletions

47
dist/index.html vendored
View File

@ -2326,6 +2326,20 @@ function merge_text_nodes(text) {
//#endregion //#endregion
//#region node_modules/svelte/src/internal/client/dom/elements/misc.js //#region node_modules/svelte/src/internal/client/dom/elements/misc.js
/** /**
* @param {HTMLElement} dom
* @param {boolean} value
* @returns {void}
*/
function autofocus(dom, value) {
if (value) {
const body = document.body;
dom.autofocus = true;
queue_micro_task(() => {
if (document.activeElement === body) dom.focus();
});
}
}
/**
* The child of a textarea actually corresponds to the defaultValue property, so we need * The child of a textarea actually corresponds to the defaultValue property, so we need
* to remove it upon hydration to avoid a bug when someone resets the form value. * to remove it upon hydration to avoid a bug when someone resets the form value.
* @param {HTMLTextAreaElement} dom * @param {HTMLTextAreaElement} dom
@ -4817,7 +4831,10 @@ var app$1 = new AppStore();
* @returns {string} * @returns {string}
*/ */
function generateId() { function generateId() {
return `${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 10)}`; const timestamp = Date.now().toString(36);
const randomBytes = new Uint8Array(4);
crypto.getRandomValues(randomBytes);
return `${timestamp}_${Array.from(randomBytes).map((b) => b.toString(16).padStart(2, "0")).join("").slice(0, 8)}`;
} }
/** /**
* @typedef {Object} CredentialEntry * @typedef {Object} CredentialEntry
@ -4955,7 +4972,7 @@ function validateGroup(name) {
* *
* The derived encryption key is kept in memory only — never written to disk. * The derived encryption key is kept in memory only — never written to disk.
*/ */
var PBKDF2_ITERATIONS = 1e5; var PBKDF2_ITERATIONS = 6e5;
var SALT_LENGTH = 16; var SALT_LENGTH = 16;
var IV_LENGTH = 12; var IV_LENGTH = 12;
/** /**
@ -5088,9 +5105,19 @@ function generatePassword({ length = 16, uppercase = true, lowercase = true, dig
charset = charset.split("").filter((c) => !excludeSet.has(c)).join(""); charset = charset.split("").filter((c) => !excludeSet.has(c)).join("");
} }
if (!charset) throw new Error("Password charset is empty — enable at least one character type"); if (!charset) throw new Error("Password charset is empty — enable at least one character type");
const randomValues = crypto.getRandomValues(new Uint8Array(length)); const charsetLength = charset.length;
const maxValid = 256 - 256 % charsetLength;
const randomBytes = new Uint8Array(length * 2);
let password = ""; let password = "";
for (let i = 0; i < length; i++) password += charset[randomValues[i] % charset.length]; let byteIdx = 0;
while (password.length < length) {
if (byteIdx >= randomBytes.length) {
crypto.getRandomValues(randomBytes);
byteIdx = 0;
}
const byte = randomBytes[byteIdx++];
if (byte < maxValid) password += charset[byte % charsetLength];
}
return password; return password;
} }
//#endregion //#endregion
@ -5536,17 +5563,6 @@ async function exportAll() {
}; };
} }
/** /**
* Convert a base64 string back to Uint8Array.
* @param {string} base64
* @returns {Uint8Array}
*/
function base64ToUint8Array(base64) {
const binary = atob(base64);
const bytes = new Uint8Array(binary.length);
for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
return bytes;
}
/**
* Import data from a previously exported JSON object. * Import data from a previously exported JSON object.
* *
* Requires the source vault's master password to decrypt entries, then * Requires the source vault's master password to decrypt entries, then
@ -5682,6 +5698,7 @@ function LockScreen($$anchor, $$props) {
var div_3 = child(form); var div_3 = child(form);
var input = sibling(child(div_3), 2); var input = sibling(child(div_3), 2);
remove_input_defaults(input); remove_input_defaults(input);
autofocus(input, true);
reset(div_3); reset(div_3);
var node_1 = sibling(div_3, 2); var node_1 = sibling(div_3, 2);
var consequent_1 = ($$anchor) => { var consequent_1 = ($$anchor) => {

View File

@ -95,6 +95,7 @@
bind:value={masterPassword} bind:value={masterPassword}
placeholder="Enter master password" placeholder="Enter master password"
autocomplete="current-password" autocomplete="current-password"
autofocus
disabled={loading} disabled={loading}
/> />
</div> </div>