perf: reduce renderer and repository polling work
ForgeFlow quality gate / quality (push) Canceled after 0s

This commit is contained in:
NuklearRabbit
2026-08-01 14:24:53 +02:00
parent 258f0b1324
commit 13f4fe7cd0
5 changed files with 105 additions and 61 deletions
+9
View File
@@ -173,6 +173,7 @@ const ui = {
setupValidation: null,
activeDeployment: null,
operationPollTimer: null,
inputRenderTimer: null,
isMock: false,
refreshError: null,
autoRefreshPending: false,
@@ -190,6 +191,14 @@ const ui = {
auditEvents: [],
};
function scheduleInputRender(delay = 120) {
if (ui.inputRenderTimer) clearTimeout(ui.inputRenderTimer);
ui.inputRenderTimer = setTimeout(() => {
ui.inputRenderTimer = null;
render();
}, delay);
}
function selectedRepository() {
return (
ui.repositories.find(
+47 -38
View File
@@ -17,20 +17,32 @@ app.addEventListener("click", async (event) => {
app.addEventListener("input", (event) => {
if (event.target.id === "global-search") {
ui.search = event.target.value;
render();
document.querySelector("#global-search")?.focus();
scheduleInputRender();
} else if (event.target.id === "repo-filter") {
ui.repoSearch = event.target.value;
render();
document.querySelector("#repo-filter")?.focus();
scheduleInputRender();
} else if (event.target.id === "commit-message") {
ui.commitMessage = event.target.value;
const position = event.target.selectionStart;
render();
const next = document.querySelector("#commit-message");
if (next) {
next.focus();
next.setSelectionRange(position, position);
const repository = selectedRepository();
const hasSelection = Boolean(ui.selectedFiles.size || repository?.localStatus?.counts?.staged);
const ready = Boolean(hasSelection && ui.commitMessage.trim());
const blocker = !hasSelection
? "Select files or stage one or more hunks."
: ready
? ui.selectedFiles.size
? "Ready to commit. ForgeFlow stages the selected files automatically."
: "Ready to commit only the reviewed staged hunks."
: "Enter a commit message to enable commit and push.";
const readiness = document.querySelector(".commit-readiness");
if (readiness) {
readiness.classList.toggle("ready", ready);
readiness.classList.toggle("blocked", !ready);
readiness.innerHTML = `${icon(ready ? "check" : "warning")}<span>${escapeHtml(blocker)}</span>`;
}
for (const button of document.querySelectorAll('[data-action="commit-push"], [data-action="commit-only"]')) {
button.disabled = !ready;
if (ready) button.removeAttribute("title");
else button.title = blocker;
}
} else if (event.target.id === "setup-url")
ui.setupDraft.baseUrl = event.target.value;
@@ -38,7 +50,7 @@ app.addEventListener("input", (event) => {
ui.setupDraft.token = event.target.value;
else if (event.target.id === "palette-input") {
ui.paletteQuery = event.target.value;
render();
scheduleInputRender(60);
}
});
@@ -102,35 +114,32 @@ document.addEventListener("keydown", (event) => {
}
});
let pointerAnimationFrame = null;
let pendingPointer = null;
document.addEventListener("pointermove", (event) => {
const illustration = event.target.closest?.("[data-project-illustration]");
if (illustration) {
const bounds = illustration.getBoundingClientRect();
illustration.style.setProperty(
"--tilt-x",
`${((event.clientY - bounds.top) / bounds.height - 0.5) * -7}deg`,
);
illustration.style.setProperty(
"--tilt-y",
`${((event.clientX - bounds.left) / bounds.width - 0.5) * 9}deg`,
);
}
const diffPanel = event.target.closest?.(".diff-panel");
const atmosphere = diffPanel?.querySelector("[data-diff-atmosphere]");
if (atmosphere) {
const bounds = diffPanel.getBoundingClientRect();
atmosphere.style.setProperty(
"--diff-tilt-x",
`${((event.clientY - bounds.top) / bounds.height - 0.5) * -3}deg`,
);
atmosphere.style.setProperty(
"--diff-tilt-y",
`${((event.clientX - bounds.left) / bounds.width - 0.5) * 4}deg`,
);
}
pendingPointer = { target: event.target, clientX: event.clientX, clientY: event.clientY };
if (pointerAnimationFrame) return;
pointerAnimationFrame = requestAnimationFrame(() => {
pointerAnimationFrame = null;
const current = pendingPointer;
pendingPointer = null;
if (!current) return;
const illustration = current.target.closest?.("[data-project-illustration]");
if (illustration) {
const bounds = illustration.getBoundingClientRect();
illustration.style.setProperty("--tilt-x", `${((current.clientY - bounds.top) / bounds.height - 0.5) * -7}deg`);
illustration.style.setProperty("--tilt-y", `${((current.clientX - bounds.left) / bounds.width - 0.5) * 9}deg`);
}
const diffPanel = current.target.closest?.(".diff-panel");
const atmosphere = diffPanel?.querySelector("[data-diff-atmosphere]");
if (atmosphere) {
const bounds = diffPanel.getBoundingClientRect();
atmosphere.style.setProperty("--diff-tilt-x", `${((current.clientY - bounds.top) / bounds.height - 0.5) * -3}deg`);
atmosphere.style.setProperty("--diff-tilt-y", `${((current.clientX - bounds.left) / bounds.width - 0.5) * 4}deg`);
}
});
});
document.addEventListener("pointerout", (event) => {
const illustration = event.target.closest?.("[data-project-illustration]");
if (illustration && !illustration.contains(event.relatedTarget)) {