Release 1.6.1: fix subscription button stuck disabled and improve import parsing.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Navis
2026-07-28 09:00:59 +03:00
co-authored by Cursor
parent 68a48b05ef
commit 740517dbfb
16 changed files with 258 additions and 68 deletions
+36 -8
View File
@@ -555,6 +555,7 @@
let formHydrated = false;
let dirty = false;
let profiles = [];
let metaHoldUntil = 0;
function markDirty() { dirty = true; }
[
@@ -571,6 +572,7 @@
function setMeta(text, kind) {
meta.textContent = text || "";
meta.style.color = kind === "err" ? "var(--danger)" : kind === "ok" ? "var(--accent)" : "var(--muted)";
if (kind === "ok" || kind === "err") metaHoldUntil = Date.now() + 8000;
}
function fillProfiles(list, active) {
@@ -640,6 +642,8 @@
pingBtn.disabled = busy;
updCheckBtn.disabled = busy;
updateBtn.disabled = busy;
subBtn.disabled = busy;
subUrl.disabled = busy;
btn.disabled = busy;
fillProfiles(state.profiles || [], state.active_profile || state.profile);
@@ -670,7 +674,10 @@
} else {
detail = "Вставьте ссылку naive или hysteria2://";
}
if (!busy) setMeta(detail, state.core_ready === false ? "err" : "");
if (!busy && Date.now() > metaHoldUntil) {
setMeta(detail, state.core_ready === false ? "err" : "");
metaHoldUntil = 0;
}
}
async function refresh(opts) {
@@ -682,7 +689,7 @@
async function withBusy(fn) {
if (busy) return;
busy = true;
[btn, coreBtn, saveBtn, addBtn, delBtn, profile, pingBtn, updCheckBtn, updateBtn, subBtn].forEach((b) => { if (b) b.disabled = true; });
paintButtonsLocked(true);
try {
await fn();
} finally {
@@ -691,11 +698,17 @@
await refresh({ syncForm: true });
} catch (e) {
setMeta(String(e), "err");
[btn, coreBtn, saveBtn, addBtn, delBtn, profile, pingBtn, updCheckBtn, updateBtn, subBtn].forEach((b) => { if (b) b.disabled = false; });
paintButtonsLocked(false);
}
}
}
function paintButtonsLocked(locked) {
[btn, coreBtn, saveBtn, addBtn, delBtn, profile, pingBtn, updCheckBtn, updateBtn, subBtn, subUrl].forEach((b) => {
if (b) b.disabled = locked;
});
}
profile.addEventListener("change", () => withBusy(async () => {
await selectProfile(profile.value);
dirty = false;
@@ -780,15 +793,30 @@
shopBtn.addEventListener("click", openShop);
shopLink.addEventListener("click", openShop);
async function runImportSubscription() {
const url = subUrl.value.trim();
if (!url) {
setMeta("Вставьте URL подписки", "err");
return;
}
setMeta("Загрузка подписки…");
const n = await importSubscription(url);
formHydrated = false;
dirty = false;
setMeta("Импортировано профилей: " + n, "ok");
}
subBtn.addEventListener("click", () => withBusy(async () => {
try {
setMeta("Загрузка подписки…");
const n = await importSubscription(subUrl.value.trim());
formHydrated = false;
dirty = false;
setMeta("Импортировано профилей: " + n, "ok");
await runImportSubscription();
} catch (e) { setMeta(String(e), "err"); }
}));
subUrl.addEventListener("keydown", (e) => {
if (e.key === "Enter") {
e.preventDefault();
subBtn.click();
}
});
pingBtn.addEventListener("click", () => withBusy(async () => {
try {