feat: Add global window.magnifyGlass alias and use it to control glass preview visibility from the info panel.

This commit is contained in:
AEmotionStudio
2026-01-01 09:44:34 -08:00
parent 9e8b981bdc
commit 6ef88dbbc6
14 changed files with 168 additions and 24 deletions
+4
View File
@@ -141,5 +141,9 @@ export class PositionManager {
controlsElement.style.left = `${left}px`;
controlsElement.style.top = `${top}px`;
// Show controls now that they're positioned (initially hidden off-screen)
controlsElement.style.display = 'flex';
controlsElement.style.visibility = 'visible';
}
}
+7 -3
View File
@@ -129,6 +129,12 @@ export class UIManager {
// Insert before the panel in the document body, not as a child
document.body.appendChild(this.elements.controls);
// Hide and position off-screen initially - will be shown when magnify glass activates and positions them
this.elements.controls.style.display = 'none';
this.elements.controls.style.visibility = 'hidden';
this.elements.controls.style.left = '-9999px';
this.elements.controls.style.top = '-9999px';
// Add click event delegation for control buttons
this.elements.controls.addEventListener('click', (e: MouseEvent) => {
const target = e.target as HTMLElement;
@@ -288,9 +294,7 @@ export class UIManager {
if (this.stateManager.state.settings["🔍MagnifyGlass.InfoPanelEnabled"]) {
this.elements.panel.style.display = "block";
if (this.elements.controls) {
this.elements.controls.style.display = "flex";
}
// Controls are shown by positionFloatingControls() after proper positioning
// Apply user's opacity setting when showing (convert percentage to decimal)
const opacityPercent = this.stateManager.state.settings["🔍MagnifyGlass.InfoPanelOpacity"];
this.elements.panel.style.opacity = (opacityPercent / 100).toString();
+79
View File
@@ -108,7 +108,21 @@ export class WebGLRenderer {
this.gl = this.ui.glassCanvas.getContext("webgl", { preserveDrawingBuffer: true });
if (!this.gl) {
// Try webgl2 as fallback
this.gl = this.ui.glassCanvas.getContext("webgl2", { preserveDrawingBuffer: true }) as WebGLRenderingContext | null;
}
if (!this.gl) {
const isFirefox = navigator.userAgent.toLowerCase().includes('firefox');
const browserInstructions = isFirefox
? "Firefox: Go to about:config, search for 'webgl.disabled' and set it to 'false', then restart Firefox."
: "Check your browser settings to ensure WebGL is enabled.";
console.error("ComfyUI Magnifying Glass ERROR: WebGL not supported or context creation failed.");
console.error(`To fix: ${browserInstructions}`);
// Show user notification
this.showWebGLError(browserInstructions);
return;
}
@@ -354,4 +368,69 @@ export class WebGLRenderer {
this.gl.viewport(0, 0, this.gl.canvas.width, this.gl.canvas.height);
}
}
/**
* Show WebGL error notification to user.
* @param instructions - Browser-specific instructions to fix
*/
showWebGLError(instructions: string): void {
// Create a toast notification
const toast = document.createElement('div');
toast.id = 'magnifyglass-webgl-error';
toast.style.cssText = `
position: fixed;
bottom: 20px;
right: 20px;
max-width: 400px;
padding: 16px 20px;
background: linear-gradient(135deg, #ff4444 0%, #cc3333 100%);
color: white;
border-radius: 8px;
box-shadow: 0 4px 20px rgba(0,0,0,0.3);
font-family: system-ui, -apple-system, sans-serif;
font-size: 14px;
line-height: 1.5;
z-index: 100000;
animation: slideIn 0.3s ease-out;
`;
toast.innerHTML = `
<div style="display: flex; align-items: flex-start; gap: 12px;">
<span style="font-size: 24px;">⚠️</span>
<div>
<strong style="display: block; margin-bottom: 6px;">MagnifyGlass: WebGL Disabled</strong>
<span style="opacity: 0.9;">${instructions}</span>
<button onclick="this.parentElement.parentElement.parentElement.remove()"
style="display: block; margin-top: 10px; padding: 6px 12px; background: rgba(255,255,255,0.2);
border: 1px solid rgba(255,255,255,0.3); border-radius: 4px; color: white;
cursor: pointer; font-size: 12px;">
Dismiss
</button>
</div>
</div>
`;
// Add animation keyframes
if (!document.getElementById('magnifyglass-toast-style')) {
const style = document.createElement('style');
style.id = 'magnifyglass-toast-style';
style.textContent = `
@keyframes slideIn {
from { transform: translateX(100%); opacity: 0; }
to { transform: translateX(0); opacity: 1; }
}
`;
document.head.appendChild(style);
}
document.body.appendChild(toast);
// Auto-dismiss after 15 seconds
setTimeout(() => {
if (toast.parentElement) {
toast.style.animation = 'slideIn 0.3s ease-out reverse';
setTimeout(() => toast.remove(), 300);
}
}, 15000);
}
}
+1 -7
View File
@@ -42,13 +42,7 @@ function initializeInfoPanel() {
// Expose orchestrator globally if needed
window.infoPanelManager = infoPanel as any;
// Load CSS
const link = document.createElement("link");
link.rel = "stylesheet";
link.type = "text/css";
link.href = "extensions/comfyui-magnifyglass/style.css";
document.head.appendChild(link);
console.log("ComfyUI Magnify Info Panel: CSS loaded");
// CSS is loaded by UIManager.injectStyles() - no need to load separately
console.log("ComfyUI Magnify Info Panel: Extension initialized");
} catch (e) {
+1
View File
@@ -196,6 +196,7 @@ export interface ComfyCanvas {
declare global {
interface Window {
comfyUIMagnifyGlass?: MagnifyGlassInstance;
magnifyGlass?: MagnifyGlassInstance; // Alias used by info panel controls
comfyUIMagnifyGlassExtensions?: unknown[];
infoPanelManager?: { uiManager?: { updateTheme: (theme: string) => void } };
}
+2 -1
View File
@@ -171,7 +171,8 @@
.floating-controls {
position: fixed;
display: flex;
display: none;
/* Hidden initially - JS will show when positioned */
padding: 4px;
background: rgba(40, 40, 50, 0.95);
border: 1px solid rgba(255, 255, 255, 0.3);
+2
View File
@@ -115,6 +115,8 @@ class PositionManager {
top = Math.max(10, Math.min(top, window.innerHeight - controlsElement.offsetHeight - 10));
controlsElement.style.left = `${left}px`;
controlsElement.style.top = `${top}px`;
controlsElement.style.display = "flex";
controlsElement.style.visibility = "visible";
}
}
export {
File diff suppressed because one or more lines are too long
+4 -3
View File
@@ -85,6 +85,10 @@ class UIManager {
<button class="control-btn glass-btn" title="Toggle Glass Preview (G)" data-action="toggle-glass">${Icons.magnifyGlass}</button>
`;
document.body.appendChild(this.elements.controls);
this.elements.controls.style.display = "none";
this.elements.controls.style.visibility = "hidden";
this.elements.controls.style.left = "-9999px";
this.elements.controls.style.top = "-9999px";
this.elements.controls.addEventListener("click", (e) => {
const target = e.target;
const button = target.closest("button[data-action]");
@@ -213,9 +217,6 @@ class UIManager {
if (!this.elements.panel) return;
if (this.stateManager.state.settings["🔍MagnifyGlass.InfoPanelEnabled"]) {
this.elements.panel.style.display = "block";
if (this.elements.controls) {
this.elements.controls.style.display = "flex";
}
const opacityPercent = this.stateManager.state.settings["🔍MagnifyGlass.InfoPanelOpacity"];
this.elements.panel.style.opacity = (opacityPercent / 100).toString();
this.elements.panel.offsetHeight;
File diff suppressed because one or more lines are too long
+64
View File
@@ -72,7 +72,14 @@ class WebGLRenderer {
if (!this.ui.glassCanvas) return;
this.gl = this.ui.glassCanvas.getContext("webgl", { preserveDrawingBuffer: true });
if (!this.gl) {
this.gl = this.ui.glassCanvas.getContext("webgl2", { preserveDrawingBuffer: true });
}
if (!this.gl) {
const isFirefox = navigator.userAgent.toLowerCase().includes("firefox");
const browserInstructions = isFirefox ? "Firefox: Go to about:config, search for 'webgl.disabled' and set it to 'false', then restart Firefox." : "Check your browser settings to ensure WebGL is enabled.";
console.error("ComfyUI Magnifying Glass ERROR: WebGL not supported or context creation failed.");
console.error(`To fix: ${browserInstructions}`);
this.showWebGLError(browserInstructions);
return;
}
this.program = this.createShaderProgram(this.gl, this.vertexShaderSource, this.fragmentShaderSource);
@@ -257,6 +264,63 @@ class WebGLRenderer {
this.gl.viewport(0, 0, this.gl.canvas.width, this.gl.canvas.height);
}
}
/**
* Show WebGL error notification to user.
* @param instructions - Browser-specific instructions to fix
*/
showWebGLError(instructions) {
const toast = document.createElement("div");
toast.id = "magnifyglass-webgl-error";
toast.style.cssText = `
position: fixed;
bottom: 20px;
right: 20px;
max-width: 400px;
padding: 16px 20px;
background: linear-gradient(135deg, #ff4444 0%, #cc3333 100%);
color: white;
border-radius: 8px;
box-shadow: 0 4px 20px rgba(0,0,0,0.3);
font-family: system-ui, -apple-system, sans-serif;
font-size: 14px;
line-height: 1.5;
z-index: 100000;
animation: slideIn 0.3s ease-out;
`;
toast.innerHTML = `
<div style="display: flex; align-items: flex-start; gap: 12px;">
<span style="font-size: 24px;">⚠️</span>
<div>
<strong style="display: block; margin-bottom: 6px;">MagnifyGlass: WebGL Disabled</strong>
<span style="opacity: 0.9;">${instructions}</span>
<button onclick="this.parentElement.parentElement.parentElement.remove()"
style="display: block; margin-top: 10px; padding: 6px 12px; background: rgba(255,255,255,0.2);
border: 1px solid rgba(255,255,255,0.3); border-radius: 4px; color: white;
cursor: pointer; font-size: 12px;">
Dismiss
</button>
</div>
</div>
`;
if (!document.getElementById("magnifyglass-toast-style")) {
const style = document.createElement("style");
style.id = "magnifyglass-toast-style";
style.textContent = `
@keyframes slideIn {
from { transform: translateX(100%); opacity: 0; }
to { transform: translateX(0); opacity: 1; }
}
`;
document.head.appendChild(style);
}
document.body.appendChild(toast);
setTimeout(() => {
if (toast.parentElement) {
toast.style.animation = "slideIn 0.3s ease-out reverse";
setTimeout(() => toast.remove(), 300);
}
}, 15e3);
}
}
export {
WebGLRenderer
File diff suppressed because one or more lines are too long
-6
View File
@@ -22,12 +22,6 @@ function initializeInfoPanel() {
try {
const infoPanel = new InfoPanel(magnifyGlass);
window.infoPanelManager = infoPanel;
const link = document.createElement("link");
link.rel = "stylesheet";
link.type = "text/css";
link.href = "extensions/comfyui-magnifyglass/style.css";
document.head.appendChild(link);
console.log("ComfyUI Magnify Info Panel: CSS loaded");
console.log("ComfyUI Magnify Info Panel: Extension initialized");
} catch (e) {
console.error("ComfyUI Magnify Info Panel: Error during initialization:", e);
+1 -1
View File
@@ -1 +1 @@
{"version":3,"file":"magnify_info_panel.js","sources":["../src/magnify_info_panel.ts"],"sourcesContent":["/**\n * ComfyUI Magnify Info Panel - Main Entry Point\n * \n * Initializes the Info Panel extension.\n */\n\nimport { InfoPanel } from './info-panel';\n// @ts-ignore\nimport { app } from \"/scripts/app.js\";\n\n// We rely on the global 'app' object provided by ComfyUI\n// No need to import it as it's global, but TypeScript needs to know about it.\n// We handled this in types/comfyui.d.ts\n\napp.registerExtension({\n name: \"comfyui.magnify.info.panel\",\n init() {\n // Wait for magnify glass to be available\n const checkDependencies = () => {\n if (window.comfyUIMagnifyGlass) {\n initializeInfoPanel();\n } else {\n setTimeout(checkDependencies, 100);\n }\n };\n\n checkDependencies();\n }\n});\n\nfunction initializeInfoPanel() {\n const magnifyGlass = window.comfyUIMagnifyGlass;\n if (!magnifyGlass) {\n console.error(\"ComfyUI Magnify Info Panel: Failed to find MagnifyGlass instance.\");\n return;\n }\n\n try {\n // Initialize the info panel\n const infoPanel = new InfoPanel(magnifyGlass);\n\n // Expose orchestrator globally if needed\n window.infoPanelManager = infoPanel as any;\n\n // Load CSS\n const link = document.createElement(\"link\");\n link.rel = \"stylesheet\";\n link.type = \"text/css\";\n link.href = \"extensions/comfyui-magnifyglass/style.css\";\n document.head.appendChild(link);\n console.log(\"ComfyUI Magnify Info Panel: CSS loaded\");\n\n console.log(\"ComfyUI Magnify Info Panel: Extension initialized\");\n } catch (e) {\n console.error(\"ComfyUI Magnify Info Panel: Error during initialization:\", e);\n }\n}\n\n"],"names":[],"mappings":";;AAcA,IAAI,kBAAkB;AAAA,EAClB,MAAM;AAAA,EACN,OAAO;AAEH,UAAM,oBAAoB,MAAM;AAC5B,UAAI,OAAO,qBAAqB;AAC5B,4BAAA;AAAA,MACJ,OAAO;AACH,mBAAW,mBAAmB,GAAG;AAAA,MACrC;AAAA,IACJ;AAEA,sBAAA;AAAA,EACJ;AACJ,CAAC;AAED,SAAS,sBAAsB;AAC3B,QAAM,eAAe,OAAO;AAC5B,MAAI,CAAC,cAAc;AACf,YAAQ,MAAM,mEAAmE;AACjF;AAAA,EACJ;AAEA,MAAI;AAEA,UAAM,YAAY,IAAI,UAAU,YAAY;AAG5C,WAAO,mBAAmB;AAG1B,UAAM,OAAO,SAAS,cAAc,MAAM;AAC1C,SAAK,MAAM;AACX,SAAK,OAAO;AACZ,SAAK,OAAO;AACZ,aAAS,KAAK,YAAY,IAAI;AAC9B,YAAQ,IAAI,wCAAwC;AAEpD,YAAQ,IAAI,mDAAmD;AAAA,EACnE,SAAS,GAAG;AACR,YAAQ,MAAM,4DAA4D,CAAC;AAAA,EAC/E;AACJ;"}
{"version":3,"file":"magnify_info_panel.js","sources":["../src/magnify_info_panel.ts"],"sourcesContent":["/**\n * ComfyUI Magnify Info Panel - Main Entry Point\n * \n * Initializes the Info Panel extension.\n */\n\nimport { InfoPanel } from './info-panel';\n// @ts-ignore\nimport { app } from \"/scripts/app.js\";\n\n// We rely on the global 'app' object provided by ComfyUI\n// No need to import it as it's global, but TypeScript needs to know about it.\n// We handled this in types/comfyui.d.ts\n\napp.registerExtension({\n name: \"comfyui.magnify.info.panel\",\n init() {\n // Wait for magnify glass to be available\n const checkDependencies = () => {\n if (window.comfyUIMagnifyGlass) {\n initializeInfoPanel();\n } else {\n setTimeout(checkDependencies, 100);\n }\n };\n\n checkDependencies();\n }\n});\n\nfunction initializeInfoPanel() {\n const magnifyGlass = window.comfyUIMagnifyGlass;\n if (!magnifyGlass) {\n console.error(\"ComfyUI Magnify Info Panel: Failed to find MagnifyGlass instance.\");\n return;\n }\n\n try {\n // Initialize the info panel\n const infoPanel = new InfoPanel(magnifyGlass);\n\n // Expose orchestrator globally if needed\n window.infoPanelManager = infoPanel as any;\n\n // CSS is loaded by UIManager.injectStyles() - no need to load separately\n\n console.log(\"ComfyUI Magnify Info Panel: Extension initialized\");\n } catch (e) {\n console.error(\"ComfyUI Magnify Info Panel: Error during initialization:\", e);\n }\n}\n\n"],"names":[],"mappings":";;AAcA,IAAI,kBAAkB;AAAA,EAClB,MAAM;AAAA,EACN,OAAO;AAEH,UAAM,oBAAoB,MAAM;AAC5B,UAAI,OAAO,qBAAqB;AAC5B,4BAAA;AAAA,MACJ,OAAO;AACH,mBAAW,mBAAmB,GAAG;AAAA,MACrC;AAAA,IACJ;AAEA,sBAAA;AAAA,EACJ;AACJ,CAAC;AAED,SAAS,sBAAsB;AAC3B,QAAM,eAAe,OAAO;AAC5B,MAAI,CAAC,cAAc;AACf,YAAQ,MAAM,mEAAmE;AACjF;AAAA,EACJ;AAEA,MAAI;AAEA,UAAM,YAAY,IAAI,UAAU,YAAY;AAG5C,WAAO,mBAAmB;AAI1B,YAAQ,IAAI,mDAAmD;AAAA,EACnE,SAAS,GAAG;AACR,YAAQ,MAAM,4DAA4D,CAAC;AAAA,EAC/E;AACJ;"}