// ComfyUI Endless 🌊✨ Fontifier - Fully Fixed Version (function waitForHelpers() { if (typeof window.EndlessHelpers === 'undefined') { console.warn("⏳ Waiting for EndlessHelpers to be ready..."); setTimeout(waitForHelpers, 100); // Retry every 100ms return; } // Load helpers from window const { registerEndlessTool, injectEndlessToolsButton, showEndlessToolMenu, onThemeChange, getComfyUIColors, toRGBA, blendColors, addButtonHoverEffects, makeDraggable } = window.EndlessHelpers; // === ORIGINAL COMFYUI DEFAULTS === const originalValues = { NODE_TEXT_SIZE: LiteGraph.NODE_TEXT_SIZE || 14, NODE_SUBTEXT_SIZE: LiteGraph.NODE_SUBTEXT_SIZE || 12, NODE_TITLE_HEIGHT: LiteGraph.NODE_TITLE_HEIGHT || 30, DEFAULT_GROUP_FONT: LiteGraph.DEFAULT_GROUP_FONT || 24, NODE_FONT: LiteGraph.NODE_FONT || 'Arial', NODE_SLOT_HEIGHT: LiteGraph.NODE_SLOT_HEIGHT || 20, NODE_WIDGET_HEIGHT: LiteGraph.NODE_WIDGET_HEIGHT || 20, WIDGET_TEXT_SIZE: 12, GLOBAL_SCALE: 1 }; const saved = localStorage.getItem("endless_fontifier_defaults"); let currentValues = saved ? JSON.parse(saved) : { ...originalValues }; let dialogOpenValues = null; let currentDialog = null; let handlersSetup = false; let escHandler = null; let unregisterThemeCallback = null; let isPreviewMode = false; function createFontifierDialog() { if (currentDialog) return; const colors = getComfyUIColors(); const dialog = document.createElement("div"); dialog.id = "fontifier-dialog"; dialog.style.cssText = ` position: absolute; z-index: 9999; top: 100px; left: 100px; width: 320px; background: ${colors.dialogBg || colors.menu || 'rgba(20, 20, 20, 0.95)'}; color: ${colors.inputText || '#fff'}; font-family: sans-serif; border: 1px solid ${colors.border}; border-radius: 10px; box-shadow: ${colors.shadow || '0 0 20px rgba(0,0,0,0.5)'}; padding: 10px; `; // Clean up any existing style tags const existingStyle = document.getElementById('fontifier-dialog-style'); if (existingStyle) existingStyle.remove(); // Themed style block const style = document.createElement("style"); style.id = "fontifier-dialog-style"; style.textContent = createStyleCSS(colors); document.head.appendChild(style); dialog.innerHTML = `
Endless 🌊✨ Drag Bar

Fontifier Settings

`; document.body.appendChild(dialog); makeDraggable(dialog, dialog.querySelector('#drag-bar')); setupDialogHandlers(dialog); currentDialog = dialog; // Store the values when dialog opens for cancel functionality dialogOpenValues = { ...currentValues }; // Set current values in the dialog updateDialogValues(dialog); // Live theme updating without closing dialog unregisterThemeCallback = onThemeChange(() => { if (currentDialog) { updateDialogTheme(); } }); } function createStyleCSS(colors) { return ` .fontifier-setting { margin-bottom: 10px; } .fontifier-row { display: flex; align-items: center; gap: 6px; } .fontifier-row input[type="range"] { flex-grow: 1; } .fontifier-row input[type="number"] { width: 50px; background: ${colors.inputBg || '#222'}; border: 1px solid ${colors.border || '#999'}; color: ${colors.inputText || '#ddd'}; border-radius: 4px; padding: 2px; } #fontifier-dialog button { flex-grow: 1; padding: 6px; background: ${colors.inputBg || '#222'}; border: 1px solid ${colors.border || '#999'}; color: ${colors.inputText || '#ddd'}; border-radius: 4px; cursor: pointer; } #fontifier-dialog button:hover { background: ${colors.buttonHoverBg || colors.hoverBg || blendColors(colors.inputBg || '#222', '#ffffff', 0.1)}; } #fontifier-dialog #apply-btn { background: ${toRGBA(colors.accent || '#4CAF50', 0.3)}; border-color: ${colors.accent || '#4CAF50'}; } #fontifier-dialog #cancel-btn { background: ${toRGBA(colors.errorText || '#f44336', 0.3)}; border-color: ${colors.errorText || '#f44336'}; } #fontifier-dialog select { background: ${colors.inputBg || '#222'}; border: 1px solid ${colors.border || '#999'}; color: ${colors.inputText || '#ddd'}; border-radius: 4px; padding: 4px; } `; } function updateDialogTheme() { if (!currentDialog) return; const newColors = getComfyUIColors(); // Update main dialog styling currentDialog.style.background = newColors.dialogBg || newColors.menu || 'rgba(20, 20, 20, 0.95)'; currentDialog.style.color = newColors.inputText || '#fff'; currentDialog.style.borderColor = newColors.border || '#999'; currentDialog.style.boxShadow = newColors.shadow || '0 0 20px rgba(0,0,0,0.5)'; // Update drag bar const dragBar = currentDialog.querySelector('#drag-bar'); if (dragBar) { dragBar.style.background = newColors.menuSecondary || '#2a2a2a'; } // Update preview indicator const previewIndicator = currentDialog.querySelector('#preview-indicator'); if (previewIndicator) { previewIndicator.style.color = newColors.accent || '#4CAF50'; } // Update the style tag with new colors const styleTag = document.getElementById('fontifier-dialog-style'); if (styleTag) { styleTag.textContent = createStyleCSS(newColors); } } function updateDialogValues(dialog) { dialog.querySelector('#global-scale').value = currentValues.GLOBAL_SCALE || 1; dialog.querySelector('#global-scale-num').value = currentValues.GLOBAL_SCALE || 1; dialog.querySelector('#node-text-size').value = currentValues.NODE_TEXT_SIZE; dialog.querySelector('#node-text-size-num').value = currentValues.NODE_TEXT_SIZE; dialog.querySelector('#node-subtext-size').value = currentValues.NODE_SUBTEXT_SIZE; dialog.querySelector('#node-subtext-size-num').value = currentValues.NODE_SUBTEXT_SIZE; dialog.querySelector('#title-height').value = currentValues.NODE_TITLE_HEIGHT; dialog.querySelector('#title-height-num').value = currentValues.NODE_TITLE_HEIGHT; dialog.querySelector('#slot-height').value = currentValues.NODE_SLOT_HEIGHT; dialog.querySelector('#slot-height-num').value = currentValues.NODE_SLOT_HEIGHT; dialog.querySelector('#group-font-size').value = currentValues.DEFAULT_GROUP_FONT; dialog.querySelector('#group-font-size-num').value = currentValues.DEFAULT_GROUP_FONT; dialog.querySelector('#widget-text-size').value = currentValues.WIDGET_TEXT_SIZE; dialog.querySelector('#widget-text-size-num').value = currentValues.WIDGET_TEXT_SIZE; dialog.querySelector('#font-family').value = currentValues.NODE_FONT; } function setupDialogHandlers(dialog) { if (handlersSetup) return; handlersSetup = true; addButtonHoverEffects(dialog); const elements = [ 'global-scale', 'node-text-size', 'node-subtext-size', 'title-height', 'slot-height', 'group-font-size', 'widget-text-size' ]; elements.forEach(id => { const slider = dialog.querySelector(`#${id}`); const numberInput = dialog.querySelector(`#${id}-num`); if (slider && numberInput) { slider.oninput = () => { numberInput.value = slider.value; if (isPreviewMode) showPreviewIndicator(); }; numberInput.oninput = () => { // Enforce min/max constraints const min = parseFloat(numberInput.min); const max = parseFloat(numberInput.max); let value = parseFloat(numberInput.value); if (value < min) value = min; if (value > max) value = max; numberInput.value = value; slider.value = value; if (isPreviewMode) showPreviewIndicator(); }; } }); const saveBtn = dialog.querySelector('#save-defaults-btn'); if (saveBtn) { saveBtn.onclick = () => { localStorage.setItem("endless_fontifier_defaults", JSON.stringify(currentValues)); alert("🌊 Fontifier defaults saved! They'll auto-load next time."); }; } dialog.querySelector('#apply-btn').onclick = () => { applyChanges(dialog, true); hidePreviewIndicator(); closeDialog(); }; dialog.querySelector('#preview-btn').onclick = () => { applyChanges(dialog, false); showPreviewIndicator(); }; dialog.querySelector('#reset-btn').onclick = () => { localStorage.removeItem("endless_fontifier_defaults"); currentValues = { ...originalValues }; applySettingsToComfyUI(originalValues); updateDialogValues(dialog); hidePreviewIndicator(); alert("🔁 Fontifier reset to ComfyUI defaults."); }; dialog.querySelector('#cancel-btn').onclick = () => { applySettingsToComfyUI(dialogOpenValues); hidePreviewIndicator(); closeDialog(); }; escHandler = e => { if (e.key === 'Escape') { applySettingsToComfyUI(dialogOpenValues); hidePreviewIndicator(); closeDialog(); } }; document.addEventListener('keydown', escHandler); } function showPreviewIndicator() { if (!currentDialog) return; isPreviewMode = true; const indicator = currentDialog.querySelector('#preview-indicator'); if (indicator) indicator.style.display = 'block'; } function hidePreviewIndicator() { if (!currentDialog) return; isPreviewMode = false; const indicator = currentDialog.querySelector('#preview-indicator'); if (indicator) indicator.style.display = 'none'; } function applyChanges(dialog, permanent = false) { const globalScale = parseFloat(dialog.querySelector('#global-scale').value); const baseValues = { NODE_TEXT_SIZE: parseInt(dialog.querySelector('#node-text-size').value), NODE_SUBTEXT_SIZE: parseInt(dialog.querySelector('#node-subtext-size').value), NODE_TITLE_HEIGHT: parseInt(dialog.querySelector('#title-height').value), NODE_SLOT_HEIGHT: parseInt(dialog.querySelector('#slot-height').value), DEFAULT_GROUP_FONT: parseInt(dialog.querySelector('#group-font-size').value), FONT_FAMILY: dialog.querySelector('#font-family').value, NODE_FONT: dialog.querySelector('#font-family').value, WIDGET_TEXT_SIZE: parseInt(dialog.querySelector('#widget-text-size').value), GLOBAL_SCALE: globalScale }; // Apply global scaling to font sizes const scaledValues = { ...baseValues, NODE_TEXT_SIZE: Math.round(baseValues.NODE_TEXT_SIZE * globalScale), NODE_SUBTEXT_SIZE: Math.round(baseValues.NODE_SUBTEXT_SIZE * globalScale), DEFAULT_GROUP_FONT: Math.round(baseValues.DEFAULT_GROUP_FONT * globalScale), WIDGET_TEXT_SIZE: Math.round(baseValues.WIDGET_TEXT_SIZE * globalScale) }; applySettingsToComfyUI(scaledValues); if (permanent) { currentValues = { ...baseValues }; // Store unscaled values isPreviewMode = false; } } function applySettingsToComfyUI(settings) { LiteGraph.NODE_TEXT_SIZE = settings.NODE_TEXT_SIZE; LiteGraph.NODE_SUBTEXT_SIZE = settings.NODE_SUBTEXT_SIZE; LiteGraph.NODE_TITLE_HEIGHT = settings.NODE_TITLE_HEIGHT; LiteGraph.NODE_SLOT_HEIGHT = settings.NODE_SLOT_HEIGHT; LiteGraph.DEFAULT_GROUP_FONT = settings.DEFAULT_GROUP_FONT; LiteGraph.DEFAULT_GROUP_FONT_SIZE = settings.DEFAULT_GROUP_FONT; LiteGraph.NODE_FONT = settings.NODE_FONT; LiteGraph.DEFAULT_FONT = settings.NODE_FONT; LiteGraph.GROUP_FONT = settings.NODE_FONT; if (window.app?.canvas) { window.app.canvas.setDirty(true, true); setTimeout(() => window.app.canvas.draw(true, true), 100); } const styleId = "fontifier-widget-text-style"; let styleTag = document.getElementById(styleId); if (!styleTag) { styleTag = document.createElement('style'); styleTag.id = styleId; document.head.appendChild(styleTag); } styleTag.textContent = ` .litegraph input, .litegraph select, .litegraph textarea { font-size: ${settings.WIDGET_TEXT_SIZE}px !important; font-family: ${settings.NODE_FONT} !important; } #fontifier-dialog input, #fontifier-dialog select, #fontifier-dialog textarea { font-size: 14px !important; font-family: Arial !important; } `; } function closeDialog() { if (currentDialog) currentDialog.remove(); if (escHandler) document.removeEventListener('keydown', escHandler); if (unregisterThemeCallback) unregisterThemeCallback(); // Clean up the style tag const styleTag = document.getElementById('fontifier-dialog-style'); if (styleTag) styleTag.remove(); currentDialog = null; handlersSetup = false; escHandler = null; unregisterThemeCallback = null; isPreviewMode = false; } // Wait for app to be ready before initializing function waitForApp() { if (typeof window.app !== 'undefined' && window.app?.canvas) { // Initialize with saved defaults once app is ready applySettingsToComfyUI(currentValues); return; } setTimeout(waitForApp, 100); } waitForApp(); // Register into Endless Tools menu registerEndlessTool("Fontifier", createFontifierDialog); })();