Files
2026-09-24 14:02:32 -04:00

234 lines
7.6 KiB
JavaScript

import { app } from "../../scripts/app.js";
/* -------------------------
Refresh Prompt
--------------------------- */
let refreshPromptShown = false;
let initialSetupComplete = false;
function showRefreshPrompt() {
if (!initialSetupComplete) return;
if (refreshPromptShown) return;
refreshPromptShown = true;
const prompt = document.createElement("div");
prompt.style.cssText = `
position: fixed;
top: 20px;
right: 20px;
background: #2a2a2a;
color: white;
padding: 16px 20px;
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0,0,0,0.5);
z-index: 10000;
display: flex;
align-items: center;
gap: 12px;
font-family: system-ui;
font-size: 14px;
`;
prompt.innerHTML = `
<span>Settings changed. Refresh to apply?</span>
<button>Refresh</button>
<button>Dismiss</button>
`;
const [refreshBtn, dismissBtn] = prompt.querySelectorAll("button");
refreshBtn.onclick = () => location.reload();
dismissBtn.onclick = () => prompt.remove();
setTimeout(() => {
prompt.style.opacity = "0";
setTimeout(() => prompt.remove(), 300);
}, 10000);
document.body.appendChild(prompt);
}
/* -------------------------
Extension
--------------------------- */
app.registerExtension({
name: "frontend.cleanup.ui",
settings: [
{
id: "FrontEndCleanup.UI.Move Actionbar to Top Bar",
name: "Move actionbar to top bar",
type: "boolean",
defaultValue: true,
onChange: showRefreshPrompt
},
{
id: "FrontEndCleanup.UI.Hide Subgraph Breadcrumb",
name: "Hide subgraph breadcrumb navigation",
type: "boolean",
defaultValue: false,
onChange: showRefreshPrompt
},
{
id: "FrontEndCleanup.UI.Hide Job Progress Panel",
name: "Hide job progress panel",
type: "boolean",
defaultValue: false,
onChange: showRefreshPrompt
},
{
id: "FrontEndCleanup.UI.Hide Error Triangle",
name: "Hide error triangle icon",
type: "boolean",
defaultValue: true,
onChange: showRefreshPrompt
},
{
id: "FrontEndCleanup.UI.Hide Login Button",
name: "Hide login / account button",
type: "boolean",
defaultValue: false,
onChange: showRefreshPrompt
}
],
async setup() {
const LOG = "[ComfyUI][FrontEndCleanup]";
// Inject CSS
const link = document.createElement("link");
link.rel = "stylesheet";
link.href = "extensions/ComfyUI_FrontEndCleanup/ui_cleanup.css";
document.head.appendChild(link);
const moveEnabled = app.ui.settings.getSettingValue(
"FrontEndCleanup.UI.Move Actionbar to Top Bar",
true
);
const hideSubgraph = app.ui.settings.getSettingValue(
"FrontEndCleanup.UI.Hide Subgraph Breadcrumb", true
);
const hideJobProgress = app.ui.settings.getSettingValue(
"FrontEndCleanup.UI.Hide Job Progress Panel", true
);
const hideErrorTriangle = app.ui.settings.getSettingValue(
"FrontEndCleanup.UI.Hide Error Triangle", true
);
const hideLogin = app.ui.settings.getSettingValue(
"FrontEndCleanup.UI.Hide Login Button", false
);
if (hideSubgraph) document.body.classList.add("ui_cleanup_hide_subgraph");
if (hideJobProgress) document.body.classList.add("ui_cleanup_hide_jobprogress");
if (hideErrorTriangle) document.body.classList.add("ui_cleanup_hide_error_triangle");
if (hideLogin) document.body.classList.add("ui_cleanup_hide_login");
if (moveEnabled) document.body.classList.add("ui_cleanup_move_actionbar");
/* -------------------------
SINGLE INSTANCE ENFORCER
-------------------------- */
function moveActionbar(actionbar) {
actionbar.classList.add("ui-moving");
actionbar.classList.remove("ui-mounted");
if (!moveEnabled) return;
const tabsContainer = document.querySelector(
".workflow-tabs-container > div > .flex.h-full.shrink-0.items-center"
);
if (!tabsContainer || !actionbar) return;
requestAnimationFrame(() => {
requestAnimationFrame(() => {
if (!document.body.contains(actionbar)) return;
// 🔥 REMOVE ALL OTHER ACTIONBARS
const all = document.querySelectorAll(".actionbar-container");
all.forEach(el => {
if (el !== actionbar) {
el.remove();
}
});
// Already correct after cleanup
if (!tabsContainer.contains(actionbar)) {
// Remove the leftover action bar card shell
document.querySelectorAll('[data-testid="action-bar-card"]').forEach(card => {
if (!card.contains(actionbar)) card.remove();
});
Object.assign(actionbar.style, {
border: "none",
boxShadow: "none",
background: "transparent",
height: "auto",
padding: "0 8px",
});
tabsContainer.appendChild(actionbar);
requestAnimationFrame(() => {
actionbar.classList.remove("ui-moving");
actionbar.classList.add("ui-mounted");
});
console.log(`${LOG} actionbar moved (deduped)`);
}
});
});
}
/* -------------------------
OBSERVER
-------------------------- */
const observer = new MutationObserver((mutations) => {
for (const m of mutations) {
for (const node of m.addedNodes) {
if (!(node instanceof HTMLElement)) continue;
if (node.matches?.(".actionbar-container")) {
moveActionbar(node);
}
const found = node.querySelector?.(".actionbar-container");
if (found) {
moveActionbar(found);
}
}
}
});
observer.observe(document.body, {
childList: true,
subtree: true,
});
/* -------------------------
INITIAL LOAD
-------------------------- */
setTimeout(() => {
const bars = document.querySelectorAll(".actionbar-container");
if (bars.length > 0) {
// Take the LAST one (most recent)
moveActionbar(bars[bars.length - 1]);
}
}, 500);
/* -------------------------
SAFETY LOOP
-------------------------- */
const interval = setInterval(() => {
const bars = document.querySelectorAll(".actionbar-container");
if (bars.length > 1) {
moveActionbar(bars[bars.length - 1]);
}
}, 1000);
setTimeout(() => clearInterval(interval), 15000);
setTimeout(() => {
initialSetupComplete = true;
}, 1000);
}
});