Files
auto-login/src/popup/config-form.ts
T

168 lines
5.2 KiB
TypeScript
Raw Normal View History

2026-09-17 23:00:47 +08:00
/**
* 添加配置表单:表单字段、草稿持久化(弹窗关闭后不丢失)、
* 添加按钮提交、"填入当前域名"按钮。
*/
import { t } from "../i18n.js";
import { resolveAlias } from "../ui-utils.js";
2026-09-17 23:00:47 +08:00
import type { DomainConfig } from "../types.js";
import { $ } from "./dom";
import type { PopupCtx } from "./context";
const domainInput = $("domain");
const aliasInput = $("alias");
const usernameInput = $("username");
const passwordInput = $("password");
const autoSubmitSelect = $("autoSubmit");
const enabledCheckbox = $("enabled");
const delayMsInput = $("delayMs");
const usernameSelectorInput = $("usernameSelector");
const passwordSelectorInput = $("passwordSelector");
const submitSelectorInput = $("submitSelector");
const addBtn = $("addBtn");
const fillDomainBtn = $("fillDomain");
const DRAFT_KEY = "formDraft";
const draftFields = [
domainInput,
aliasInput,
usernameInput,
passwordInput,
autoSubmitSelect,
usernameSelectorInput,
passwordSelectorInput,
submitSelectorInput,
enabledCheckbox,
delayMsInput,
2026-09-17 23:00:47 +08:00
];
export function initConfigForm(ctx: PopupCtx) {
function saveDraft() {
const draft = {
domain: domainInput.value,
alias: aliasInput.value,
username: usernameInput.value,
password: passwordInput.value,
autoSubmit: autoSubmitSelect.value,
usernameSelector: usernameSelectorInput.value,
passwordSelector: passwordSelectorInput.value,
submitSelector: submitSelectorInput.value,
enabled: enabledCheckbox.checked,
delayMs: delayMsInput.value,
};
chrome.storage.local.set({ [DRAFT_KEY]: draft });
}
async function loadDraft() {
const data = await chrome.storage.local.get(DRAFT_KEY);
const draft = data[DRAFT_KEY];
if (!draft) return;
domainInput.value = draft.domain || "";
aliasInput.value = draft.alias || "";
usernameInput.value = draft.username || "";
passwordInput.value = draft.password || "";
autoSubmitSelect.value = draft.autoSubmit || "true";
usernameSelectorInput.value = draft.usernameSelector || "";
passwordSelectorInput.value = draft.passwordSelector || "";
submitSelectorInput.value = draft.submitSelector || "";
enabledCheckbox.checked = draft.enabled !== false;
delayMsInput.value = draft.delayMs || "";
addBtn.textContent = t("addConfigBtn");
}
function clearDraft() {
chrome.storage.local.remove(DRAFT_KEY);
}
function resetForm() {
domainInput.value = "";
aliasInput.value = "";
usernameInput.value = "";
passwordInput.value = "";
autoSubmitSelect.value = "true";
usernameSelectorInput.value = "";
passwordSelectorInput.value = "";
submitSelectorInput.value = "";
enabledCheckbox.checked = true;
delayMsInput.value = "";
addBtn.textContent = t("addConfigBtn");
clearDraft();
}
// 表单内容实时存入草稿,弹窗关闭后不丢失
draftFields.forEach((el) => {
el.addEventListener("input", saveDraft);
el.addEventListener("change", saveDraft);
});
addBtn.addEventListener("click", async () => {
const domain = domainInput.value.trim();
const username = usernameInput.value.trim();
const password = passwordInput.value;
if (!domain || !username || !password) {
ctx.showToast(t("toastRequired"));
return;
}
// 申请站点访问权限必须紧跟用户手势,因此放在其它 await 之前
const authorized = await Perms.requestForDomain(domain);
2026-09-17 23:00:47 +08:00
const config: DomainConfig = {
id: EnvStore.genCfgId(),
domain,
alias: aliasInput.value.trim() || (await resolveAlias(domain)) || null,
2026-09-17 23:00:47 +08:00
username,
password,
autoSubmit: autoSubmitSelect.value === "true",
usernameSelector: usernameSelectorInput.value.trim() || null,
passwordSelector: passwordSelectorInput.value.trim() || null,
submitSelector: submitSelectorInput.value.trim() || null,
enabled: enabledCheckbox.checked,
delayMs: delayMsInput.value ? Number(delayMsInput.value) : null,
};
const configs = await EnvStore.loadConfigs();
configs.push(config);
ctx.showToast(authorized ? t("toastAdded") : t("toastUnauthorized"));
2026-09-17 23:00:47 +08:00
await EnvStore.saveConfigs(configs);
resetForm();
ctx.renderConfigList();
ctx.renderEnvSelect();
ctx.refreshEnvManage();
});
// 填入当前标签页域名
fillDomainBtn.addEventListener("click", async () => {
const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
if (!tab) {
2026-09-17 23:00:47 +08:00
ctx.showToast(t("toastNoTab"));
return;
}
if (!tab.url) {
// 未授权时读不到地址:提示用户点扩展图标重新授予 activeTab
ctx.showToast(t("toastNoTabUrl"));
return;
}
2026-09-17 23:00:47 +08:00
try {
const u = new URL(tab.url);
const host = u.host;
if (!host) {
ctx.showToast(t("toastNoDomain"));
return;
}
const value = u.pathname && u.pathname !== "/" ? host + u.pathname : host;
domainInput.value = value;
if (tab.title) aliasInput.value = tab.title;
saveDraft();
ctx.showToast(t("toastDomainFilled", value));
} catch {
ctx.showToast(t("toastUrlParseFail"));
}
});
return { resetForm, saveDraft, loadDraft };
}