ux(luci): render strategy auto-tuner inline inside section modal with visual textarea feedback

This commit is contained in:
Dushnilin
2026-07-29 12:59:44 +03:00
parent 14270430d2
commit b82f98288a
@@ -7398,7 +7398,7 @@ function createSectionContent(section) {
attachNfqws2RemoteValidation,
);
/* zapret2 Strategy Tuner & Visual Builder Widget */
/* zapret2 Strategy Tuner & Visual Builder Widget (INLINE) */
o = section.taboption("settings", form.DummyValue, "_zapret2_tune_widget", "");
o.modalonly = true;
o.depends("action", "zapret2");
@@ -7409,124 +7409,125 @@ function createSectionContent(section) {
document.querySelector(`.cbi-option-nfqws2_opt textarea`);
if (el) {
el.value = val;
el.style.transition = "border-color 0.3s ease, box-shadow 0.3s ease";
el.style.borderColor = "#5cb85c";
el.style.boxShadow = "0 0 8px rgba(92, 184, 92, 0.5)";
setTimeout(() => {
el.style.borderColor = "";
el.style.boxShadow = "";
}, 2000);
el.dispatchEvent(new Event("change", { bubbles: true }));
}
uci.set(UCI_PACKAGE, section_id, "nfqws2_opt", val);
};
const tuneStatusDiv = E("div", { class: "zapret2-tune-status", style: "margin-top: 8px; display: none;" });
const sectionDomain = (uci.get(UCI_PACKAGE, section_id, "domain") || [])[0] || "googlevideo.com";
const domainInput = E("input", { type: "text", class: "cbi-input-text", style: "width: 180px; font-size: 0.85em;", value: sectionDomain });
const modeSelect = E("select", { class: "cbi-input-select", style: "width: 150px; font-size: 0.85em;" }, [
E("option", { value: "express" }, _("Express scan (~5-10s)")),
E("option", { value: "deep" }, _("Deep scan (~20s)"))
]);
const resultsContainer = E("div", { style: "margin-top: 8px; max-height: 200px; overflow-y: auto;" });
const statusText = E("div", { style: "margin-top: 6px; font-size: 0.88em; font-weight: bold; color: var(--cbi-link-color, #3c96d4);" }, "");
const runTuneModal = () => {
const sectionDomain = (uci.get(UCI_PACKAGE, section_id, "domain") || [])[0] || "googlevideo.com";
const domainInput = E("input", { type: "text", class: "cbi-input-text", style: "width: 100%; font-size: 0.9em;", value: sectionDomain });
const modeSelect = E("select", { class: "cbi-input-select", style: "width: 100%; font-size: 0.9em;" }, [
E("option", { value: "express" }, _("Express scan (~5-10s)")),
E("option", { value: "deep" }, _("Deep scan (~20s)"))
]);
const resultsContainer = E("div", { style: "margin-top: 12px; max-height: 220px; overflow-y: auto;" });
const statusText = E("div", { style: "margin-top: 8px; font-weight: bold; color: var(--cbi-link-color, #3c96d4);" }, "");
const startBtn = E("button", { class: "btn cbi-button cbi-button-action", type: "button", style: "padding: 2px 10px; font-size: 0.85em;" }, _("Start Auto-Tune"));
const modalContent = E("div", { style: "padding: 8px 4px;" }, [
E("div", { class: "cbi-value", style: "margin-bottom: 8px;" }, [
E("label", { class: "cbi-value-title", style: "font-size: 0.9em;" }, _("Test domain:")),
E("div", { class: "cbi-value-field" }, domainInput)
]),
E("div", { class: "cbi-value", style: "margin-bottom: 8px;" }, [
E("label", { class: "cbi-value-title", style: "font-size: 0.9em;" }, _("Scan mode:")),
E("div", { class: "cbi-value-field" }, modeSelect)
]),
statusText,
resultsContainer
]);
const inlineTuneCard = E("div", {
class: "zapret2-inline-tuner-card",
style: "display: none; margin-top: 8px; padding: 10px; border: 1px solid var(--cbi-border-color, #404040); background: rgba(0,0,0,0.2); border-radius: 4px;"
}, [
E("div", { style: "display: flex; flex-wrap: wrap; gap: 10px; align-items: center;" }, [
E("span", { style: "font-size: 0.85em; color: #888;" }, _("Test domain:")), domainInput,
E("span", { style: "font-size: 0.85em; color: #888;" }, _("Scan mode:")), modeSelect,
startBtn
]),
statusText,
resultsContainer
]);
const startBtn = E("button", { class: "btn cbi-button cbi-button-action", type: "button" }, _("Start Auto-Tune"));
const closeBtn = E("button", { class: "btn cbi-button cbi-button-neutral", type: "button" }, _("Close"));
startBtn.addEventListener("click", (e) => {
e.preventDefault();
const targetDomain = domainInput.value.trim() || "googlevideo.com";
const selectedMode = modeSelect.value;
startBtn.disabled = true;
statusText.style.color = "var(--cbi-link-color, #3c96d4)";
statusText.textContent = _("Running strategy probes...");
resultsContainer.innerHTML = "";
startBtn.addEventListener("click", () => {
const targetDomain = domainInput.value.trim() || "googlevideo.com";
const selectedMode = modeSelect.value;
startBtn.disabled = true;
statusText.textContent = _("Running strategy probes...");
resultsContainer.innerHTML = "";
fs.exec("/usr/bin/tachyon", ["zapret2_tune", section_id, targetDomain, selectedMode])
.then((res) => {
startBtn.disabled = false;
let data = null;
try {
data = JSON.parse(res.stdout || "{}");
} catch (err) {
statusText.style.color = "var(--cbi-color-warning, #d9534f)";
statusText.textContent = _("Failed to parse tuner response.");
return;
}
fs.exec("/usr/bin/tachyon", ["zapret2_tune", section_id, targetDomain, selectedMode])
.then((res) => {
startBtn.disabled = false;
let data = null;
try {
data = JSON.parse(res.stdout || "{}");
} catch (e) {
statusText.textContent = _("Failed to parse tuner response.");
return;
}
if (!data || !data.success || !data.winning_strategy) {
statusText.style.color = "var(--cbi-color-warning, #d9534f)";
statusText.textContent = (data && data.message) ? data.message : _("No working desync strategy found for this domain.");
} else {
statusText.style.color = "var(--cbi-color-success, #5cb85c)";
statusText.textContent = _("Auto-Tune complete! Winning strategy: ") + (data.winning_preset_name || "");
}
if (!data || !data.success || !data.winning_strategy) {
statusText.style.color = "var(--cbi-color-warning, #d9534f)";
statusText.textContent = (data && data.message) ? data.message : _("No working desync strategy found for this domain.");
} else {
statusText.style.color = "var(--cbi-color-success, #5cb85c)";
statusText.textContent = _("Auto-Tune complete! Winning strategy: ") + (data.winning_preset_name || "");
}
const rows = (data.results || []).map((r) => {
const applyBtn = E("button", { class: "btn cbi-button cbi-button-save", type: "button", style: "padding: 1px 6px; font-size: 0.8em;" }, _("Apply"));
applyBtn.addEventListener("click", () => {
setNfqws2OptTextarea(r.opt);
if (typeof ui !== "undefined" && ui.addNotification) {
ui.addNotification(null, E("p", {}, _("Strategy applied to section!")), "info");
}
});
return E("tr", { style: r.success ? "background: rgba(0,255,0,0.05);" : "opacity: 0.6;" }, [
E("td", { style: "padding: 4px; font-size: 0.85em; font-weight: bold;" }, r.name),
E("td", { style: "padding: 4px; font-size: 0.85em;" }, r.success ? `${r.rtt_ms} ms (${r.message})` : _("Failed")),
E("td", { style: "padding: 4px;" }, applyBtn)
]);
const rows = (data.results || []).map((r) => {
const applyBtn = E("button", { class: "btn cbi-button cbi-button-save", type: "button", style: "padding: 1px 6px; font-size: 0.8em;" }, _("Apply"));
applyBtn.addEventListener("click", (evt) => {
evt.preventDefault();
setNfqws2OptTextarea(r.opt);
if (typeof ui !== "undefined" && ui.addNotification) {
ui.addNotification(null, E("p", {}, _("Strategy applied to section!")), "info");
}
});
const table = E("table", { class: "table", style: "width: 100%; border-collapse: collapse;" }, [
E("thead", {}, [
E("tr", {}, [
E("th", { style: "text-align: left; font-size: 0.85em;" }, _("Preset")),
E("th", { style: "text-align: left; font-size: 0.85em;" }, _("Status / RTT")),
E("th", { style: "text-align: left; font-size: 0.85em;" }, _("Action"))
])
]),
E("tbody", {}, rows)
return E("tr", { style: r.success ? "background: rgba(0,255,0,0.05);" : "opacity: 0.6;" }, [
E("td", { style: "padding: 4px; font-size: 0.85em; font-weight: bold;" }, r.name),
E("td", { style: "padding: 4px; font-size: 0.85em;" }, r.success ? `${r.rtt_ms} ms (${r.message})` : _("Failed")),
E("td", { style: "padding: 4px;" }, applyBtn)
]);
resultsContainer.appendChild(table);
if (data.winning_strategy) {
setNfqws2OptTextarea(data.winning_strategy);
}
})
.catch((err) => {
startBtn.disabled = false;
statusText.textContent = _("Error running tuner: ") + err;
});
});
closeBtn.addEventListener("click", () => {
if (typeof ui !== "undefined" && ui.hideModal) {
ui.hideModal();
}
});
const table = E("table", { class: "table", style: "width: 100%; border-collapse: collapse; margin-top: 6px;" }, [
E("thead", {}, [
E("tr", {}, [
E("th", { style: "text-align: left; font-size: 0.85em;" }, _("Preset")),
E("th", { style: "text-align: left; font-size: 0.85em;" }, _("Status / RTT")),
E("th", { style: "text-align: left; font-size: 0.85em;" }, _("Action"))
])
]),
E("tbody", {}, rows)
]);
if (typeof ui !== "undefined" && ui.showModal) {
ui.showModal(_("zapret2 Strategy Auto-Tuner"), [modalContent, E("div", { class: "right" }, [startBtn, " ", closeBtn])]);
}
};
resultsContainer.appendChild(table);
if (data.winning_strategy) {
setNfqws2OptTextarea(data.winning_strategy);
}
})
.catch((err) => {
startBtn.disabled = false;
statusText.style.color = "var(--cbi-color-warning, #d9534f)";
statusText.textContent = _("Error running tuner: ") + err;
});
});
const tuneBtn = E("button", {
class: "btn cbi-button cbi-button-action",
type: "button",
style: "margin-top: 6px; margin-bottom: 10px; font-weight: bold; background-color: var(--cbi-link-color, #2b78e4); color: #fff;"
style: "margin-top: 6px; margin-bottom: 6px; font-weight: bold; background-color: var(--cbi-link-color, #2b78e4); color: #fff;"
}, _("Auto-Tune Strategy"));
tuneBtn.addEventListener("click", (e) => {
e.preventDefault();
runTuneModal();
if (inlineTuneCard.style.display === "none") {
inlineTuneCard.style.display = "block";
} else {
inlineTuneCard.style.display = "none";
}
});
const methodSelect = E("select", { class: "cbi-input-select", style: "width: 140px; font-size: 0.85em;" }, [
@@ -7582,8 +7583,8 @@ function createSectionContent(section) {
return E("div", { class: "zapret2-tune-field" }, [
tuneBtn,
builderDetails,
tuneStatusDiv
inlineTuneCard,
builderDetails
]);
};