diff --git a/gui/src/admin-token-dialog.ts b/gui/src/admin-token-dialog.ts index b576cefb8f5..6db9abecf12 100644 --- a/gui/src/admin-token-dialog.ts +++ b/gui/src/admin-token-dialog.ts @@ -66,7 +66,11 @@ export function promptForAdminToken( username.name = "username"; username.autocomplete = "username"; username.value = ADMIN_TOKEN_USERNAME; - username.readOnly = true; + // ponytail: keep editable for iCloud Keychain — readonly breaks credential matching + username.readOnly = false; + username.setAttribute("aria-readonly", "true"); + username.autocapitalize = "none"; + username.spellcheck = false; accountField.append(accountLabel, username); const tokenField = document.createElement("div"); @@ -185,6 +189,8 @@ export function promptForAdminToken( document.body.append(dialog); if (typeof dialog.showModal === "function") dialog.showModal(); else dialog.setAttribute("open", ""); - queueMicrotask(() => password.focus()); + // ponytail: let WebKit scan the dialog before stealing focus — microtask races the autofill sheet + const raf = typeof requestAnimationFrame === "function" ? requestAnimationFrame : (cb: FrameRequestCallback) => setTimeout(cb, 16); + raf(() => password.focus()); }); } diff --git a/gui/tests/admin-token-dialog.test.ts b/gui/tests/admin-token-dialog.test.ts index 26d8ca05a2d..49c20ba7ad2 100644 --- a/gui/tests/admin-token-dialog.test.ts +++ b/gui/tests/admin-token-dialog.test.ts @@ -43,7 +43,8 @@ test("renders stable password-manager-compatible sign-in fields", async () => { expect(username?.id).toBe("opencodex-admin-token-dialog-username"); expect(form?.querySelector(`label[for="${username?.id}"]`)?.textContent).toBe("Account"); expect(username?.autocomplete).toBe("username"); - expect(username?.readOnly).toBe(true); + expect(username?.readOnly).toBe(false); + expect(username?.getAttribute("aria-readonly")).toBe("true"); expect(username?.value).toBe("OpenCodex"); expect(password?.id).toBe("opencodex-admin-token-dialog-password"); expect(form?.querySelector(`label[for="${password?.id}"]`)?.textContent).toBe("Admin token");