app.addEventListener("click", async (event) => { const target = event.target.closest("[data-action]"); if (!target) return; const action = target.dataset.action; let repository = selectedRepository(); if (target.dataset.repositoryId) { const actionRepository = ui.repositories.find( (item) => String(item.id) === String(target.dataset.repositoryId), ); if (actionRepository) repository = actionRepository; } const handlers = [handleShellActions, handleInventoryActions, handleDeploymentProfileActions, handleDeploymentOperationActions, handleSetupAndSettingsActions, handleRecoveryActions, handleCommandActions]; for (const handler of handlers) if (await handler(event, target, action, repository)) return; }); app.addEventListener("input", (event) => { if (event.target.id === "global-search") { ui.search = event.target.value; render(); document.querySelector("#global-search")?.focus(); } else if (event.target.id === "repo-filter") { ui.repoSearch = event.target.value; render(); document.querySelector("#repo-filter")?.focus(); } 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); } } else if (event.target.id === "setup-url") ui.setupDraft.baseUrl = event.target.value; else if (event.target.id === "setup-token") ui.setupDraft.token = event.target.value; else if (event.target.id === "palette-input") { ui.paletteQuery = event.target.value; render(); } }); app.addEventListener("change", async (event) => { if (event.target.matches("[data-file-select]")) { const filePath = event.target.dataset.fileSelect; if (event.target.checked) ui.selectedFiles.add(filePath); else ui.selectedFiles.delete(filePath); render(); } else if (event.target.id === "appearance-select") { ui.boot.state = await window.forgeflow.setAppearance(event.target.value); applyTheme(event.target.value); render(); } else if (event.target.id === "action-profile-select") { ui.selectedProfileId = event.target.value; render(); } else if (event.target.id === "profile-provider") { ui.modal.provider = event.target.value; render(); } else if (event.target.id === "server-auth-type") { ui.modal.authType = event.target.value; render(); } }); document.addEventListener("keydown", (event) => { if ( (event.key === "Enter" || event.key === " ") && event.target.matches('.file-row[data-action="select-file"]') ) { event.preventDefault(); event.target.click(); return; } if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "k") { event.preventDefault(); ui.paletteQuery = ""; ui.modal = { type: "command-palette" }; render(); return; } if ( (event.ctrlKey || event.metaKey) && event.key === "Enter" && ui.currentView === "repository" ) { const button = document.querySelector( '[data-action="commit-push"]:not(:disabled)', ); if (button) button.click(); } if (event.key === "F5") { event.preventDefault(); refreshRepositories(true); } if (event.key === "Escape" && ui.modal) { ui.modal = null; render(); } }); 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`, ); } }); document.addEventListener("pointerout", (event) => { const illustration = event.target.closest?.("[data-project-illustration]"); if (illustration && !illustration.contains(event.relatedTarget)) { illustration.style.removeProperty("--tilt-x"); illustration.style.removeProperty("--tilt-y"); } const diffPanel = event.target.closest?.(".diff-panel"); if (diffPanel && !diffPanel.contains(event.relatedTarget)) { const atmosphere = diffPanel.querySelector("[data-diff-atmosphere]"); atmosphere?.style.removeProperty("--diff-tilt-x"); atmosphere?.style.removeProperty("--diff-tilt-y"); } }); window.addEventListener("error", (event) => { window.forgeflow .reportRendererEvent?.("error", "uncaught-error", { message: event.message, filename: event.filename, line: event.lineno, column: event.colno, stack: event.error?.stack, }) .catch(() => {}); }); window.addEventListener("unhandledrejection", (event) => { const reason = event.reason; window.forgeflow .reportRendererEvent?.("error", "unhandled-rejection", { message: reason?.message || String(reason || "Unknown rejection"), stack: reason?.stack, }) .catch(() => {}); }); bootstrap();