211 lines
6.8 KiB
JavaScript
211 lines
6.8 KiB
JavaScript
// umbrella_inline.js — mounts the Cortex-OS graph inside Hermes WebUI's
|
|
// Workspace right panel. Plugin-only shim; the standalone page remains a
|
|
// fallback at /plugins/svrnty/umbrella.html.
|
|
(function () {
|
|
"use strict";
|
|
if (window.__svrntyUmbrellaInlineLoaded) return;
|
|
window.__svrntyUmbrellaInlineLoaded = true;
|
|
|
|
const LOG = (...a) => console.log("[svrnty-umbrella-inline]", ...a);
|
|
const ICON =
|
|
'<svg width="14" height="14" viewBox="0 0 24 24" fill="none" ' +
|
|
'stroke="currentColor" stroke-width="2" stroke-linecap="round" ' +
|
|
'stroke-linejoin="round" aria-hidden="true">' +
|
|
'<circle cx="5" cy="12" r="2"/><circle cx="12" cy="5" r="2"/>' +
|
|
'<circle cx="19" cy="12" r="2"/><circle cx="12" cy="19" r="2"/>' +
|
|
'<path d="M6.7 10.6l3.9-4"/><path d="M13.4 6.6l3.9 4"/>' +
|
|
'<path d="M17.3 13.4l-3.9 4"/><path d="M10.6 17.4l-3.9-4"/>' +
|
|
'<path d="M7 12h10"/></svg>';
|
|
|
|
let surface = null;
|
|
let graphOpen = false;
|
|
let previousHeading = "Workspace";
|
|
let previousPanelWidth = "";
|
|
let openedPanelForGraph = false;
|
|
|
|
function $(id) {
|
|
return document.getElementById(id);
|
|
}
|
|
|
|
function isWorkspacePanelOpen() {
|
|
const htmlState = document.documentElement.dataset.workspacePanel;
|
|
const panel = document.querySelector(".rightpanel");
|
|
return htmlState === "open" && !!panel && getComputedStyle(panel).pointerEvents !== "none";
|
|
}
|
|
|
|
function ensureSurface() {
|
|
if (surface && document.body.contains(surface)) return surface;
|
|
const panel = document.querySelector(".rightpanel");
|
|
const preview = $("previewArea");
|
|
if (!panel || !preview) return null;
|
|
surface = document.createElement("div");
|
|
surface.id = "svrntyUmbrellaInlineSurface";
|
|
surface.className = "svrnty-umbrella-inline-surface";
|
|
surface.dataset.open = "false";
|
|
surface.innerHTML =
|
|
'<iframe class="svrnty-umbrella-inline-frame" ' +
|
|
'title="Project graph" src="/plugins/svrnty/umbrella.html?inline=1"></iframe>';
|
|
preview.insertAdjacentElement("afterend", surface);
|
|
return surface;
|
|
}
|
|
|
|
function setWorkspaceSurfaces(mode) {
|
|
const fileTree = $("fileTree");
|
|
const empty = $("wsEmptyState");
|
|
const preview = $("previewArea");
|
|
const breadcrumb = $("breadcrumbBar");
|
|
const graph = ensureSurface();
|
|
if (!graph) return;
|
|
const showGraph = mode === "graph";
|
|
if (fileTree) fileTree.style.display = showGraph ? "none" : "";
|
|
if (empty) empty.style.display = showGraph ? "none" : empty.style.display;
|
|
if (preview) preview.style.display = showGraph ? "none" : "";
|
|
if (breadcrumb) breadcrumb.style.display = showGraph ? "none" : breadcrumb.style.display;
|
|
graph.dataset.open = showGraph ? "true" : "false";
|
|
}
|
|
|
|
function syncHeader(open) {
|
|
const heading = $("workspacePanelHeading");
|
|
const button = $("btnSvrntyWorkspaceGraph");
|
|
if (heading) {
|
|
if (open) {
|
|
previousHeading = heading.textContent || "Workspace";
|
|
heading.textContent = "Project Graph";
|
|
heading.title = "Project Graph";
|
|
} else {
|
|
heading.textContent = previousHeading || "Workspace";
|
|
heading.title = "Workspace root";
|
|
}
|
|
}
|
|
if (button) {
|
|
button.classList.toggle("active", open);
|
|
button.setAttribute("aria-pressed", open ? "true" : "false");
|
|
}
|
|
}
|
|
|
|
function resizeGraphSoon() {
|
|
const frame = surface && surface.querySelector("iframe");
|
|
if (!frame) return;
|
|
setTimeout(() => {
|
|
try {
|
|
const cy = frame.contentWindow && frame.contentWindow.cy;
|
|
if (cy) {
|
|
cy.resize();
|
|
cy.fit(null, 24);
|
|
}
|
|
} catch (_) {}
|
|
}, 250);
|
|
}
|
|
|
|
function expandPanelForGraph() {
|
|
const panel = document.querySelector(".rightpanel");
|
|
if (!panel) return;
|
|
previousPanelWidth = panel.style.width || "";
|
|
const current = panel.getBoundingClientRect().width || 0;
|
|
if (current < 480) {
|
|
panel.style.width = "500px";
|
|
}
|
|
}
|
|
|
|
function restorePanelWidth() {
|
|
const panel = document.querySelector(".rightpanel");
|
|
if (!panel) return;
|
|
panel.style.width = previousPanelWidth;
|
|
previousPanelWidth = "";
|
|
}
|
|
|
|
function openWorkspaceGraph() {
|
|
if (graphOpen) {
|
|
resizeGraphSoon();
|
|
return;
|
|
}
|
|
openedPanelForGraph = !isWorkspacePanelOpen();
|
|
if (typeof window.openWorkspacePanel === "function") {
|
|
window.openWorkspacePanel("browse");
|
|
} else if (typeof window.toggleWorkspacePanel === "function") {
|
|
window.toggleWorkspacePanel(true);
|
|
}
|
|
expandPanelForGraph();
|
|
graphOpen = true;
|
|
setWorkspaceSurfaces("graph");
|
|
syncHeader(true);
|
|
resizeGraphSoon();
|
|
LOG("opened inline graph");
|
|
}
|
|
|
|
function closeWorkspaceGraph() {
|
|
if (!graphOpen) return false;
|
|
graphOpen = false;
|
|
setWorkspaceSurfaces("workspace");
|
|
syncHeader(false);
|
|
restorePanelWidth();
|
|
if (openedPanelForGraph && typeof window.closeWorkspacePanel === "function") {
|
|
window.closeWorkspacePanel();
|
|
} else if (typeof window.renderBreadcrumb === "function") {
|
|
window.renderBreadcrumb();
|
|
}
|
|
openedPanelForGraph = false;
|
|
LOG("closed inline graph");
|
|
return true;
|
|
}
|
|
|
|
function injectButton() {
|
|
const actions = document.querySelector(".rightpanel .panel-actions");
|
|
if (!actions || $("btnSvrntyWorkspaceGraph")) return !!actions;
|
|
const refresh = $("btnRefreshPanel");
|
|
const btn = document.createElement("button");
|
|
btn.className = "panel-icon-btn has-tooltip has-tooltip--bottom svrnty-graph-btn";
|
|
btn.id = "btnSvrntyWorkspaceGraph";
|
|
btn.type = "button";
|
|
btn.dataset.tooltip = "Project graph";
|
|
btn.setAttribute("aria-label", "Open project graph");
|
|
btn.setAttribute("aria-pressed", "false");
|
|
btn.innerHTML = ICON;
|
|
btn.addEventListener("click", (event) => {
|
|
event.preventDefault();
|
|
event.stopPropagation();
|
|
openWorkspaceGraph();
|
|
});
|
|
if (refresh && refresh.parentElement === actions) {
|
|
refresh.insertAdjacentElement("afterend", btn);
|
|
} else {
|
|
actions.appendChild(btn);
|
|
}
|
|
ensureSurface();
|
|
return true;
|
|
}
|
|
|
|
function interceptCloseButton() {
|
|
const close = $("btnClearPreview");
|
|
if (!close || close.dataset.svrntyGraphCloseBound === "1") return !!close;
|
|
close.dataset.svrntyGraphCloseBound = "1";
|
|
close.addEventListener("click", (event) => {
|
|
if (!graphOpen) return;
|
|
event.preventDefault();
|
|
event.stopImmediatePropagation();
|
|
closeWorkspaceGraph();
|
|
}, true);
|
|
return true;
|
|
}
|
|
|
|
function init() {
|
|
const ok = injectButton() && interceptCloseButton();
|
|
if (!ok) {
|
|
requestAnimationFrame(init);
|
|
return;
|
|
}
|
|
window.SvrntyUmbrellaInline = {
|
|
open: openWorkspaceGraph,
|
|
close: closeWorkspaceGraph,
|
|
isOpen: () => graphOpen,
|
|
};
|
|
LOG("ready");
|
|
}
|
|
|
|
if (document.readyState === "loading") {
|
|
document.addEventListener("DOMContentLoaded", init);
|
|
} else {
|
|
init();
|
|
}
|
|
})();
|