From f4fdd51ce98aaa77bccbf1b04c23c6aab925f29b Mon Sep 17 00:00:00 2001 From: "Dr.Lt.Data" Date: Fri, 19 Dec 2025 23:05:52 +0900 Subject: [PATCH] feat(preview): disable Manager preview method when ComfyUI native feature is available - Add detection for ComfyUI PR #11261 (per-queue preview override) - Return DISABLED status when native feature is detected - Improve UI loading state and prevent flash of enabled state - Add accessibility attributes and visual feedback for disabled state - Show user notification when feature transitions to native - Version bump to 3.39 --- glob/manager_core.py | 2 +- glob/manager_server.py | 50 ++++++++++++++++++++++--- js/comfyui-manager.js | 83 +++++++++++++++++++++++++++++++++++++++++- pyproject.toml | 2 +- 4 files changed, 128 insertions(+), 9 deletions(-) diff --git a/glob/manager_core.py b/glob/manager_core.py index 0bf9841b..a1173b05 100644 --- a/glob/manager_core.py +++ b/glob/manager_core.py @@ -44,7 +44,7 @@ import manager_migration from node_package import InstalledNodePackage -version_code = [3, 38, 3] +version_code = [3, 39] version_str = f"V{version_code[0]}.{version_code[1]}" + (f'.{version_code[2]}' if len(version_code) > 2 else '') diff --git a/glob/manager_server.py b/glob/manager_server.py index de2f1a89..b9391016 100644 --- a/glob/manager_server.py +++ b/glob/manager_server.py @@ -38,6 +38,25 @@ SECURITY_MESSAGE_NORMAL_MINUS_MODEL = "ERROR: Downloading models that are not in routes = PromptServer.instance.routes + +def has_per_queue_preview(): + """ + Check if ComfyUI PR #11261 (per-queue live preview override) is merged + + Returns: + bool: True if ComfyUI has per-queue preview feature + """ + try: + import latent_preview + return hasattr(latent_preview, 'set_preview_method') + except ImportError: + return False + + +# Detect ComfyUI per-queue preview override feature (PR #11261) +COMFYUI_HAS_PER_QUEUE_PREVIEW = has_per_queue_preview() + + def handle_stream(stream, prefix): stream.reconfigure(encoding=locale.getpreferredencoding(), errors='replace') for msg in stream: @@ -182,10 +201,19 @@ def set_preview_method(method): core.get_config()['preview_method'] = method -if args.preview_method == latent_preview.LatentPreviewMethod.NoPreviews: +if COMFYUI_HAS_PER_QUEUE_PREVIEW: + logging.info( + "[ComfyUI-Manager] ComfyUI per-queue preview override detected (PR #11261). " + "Manager's preview method feature is disabled. " + "Use ComfyUI's --preview-method CLI option or 'Settings > Execution > Live preview method'." + ) +elif args.preview_method == latent_preview.LatentPreviewMethod.NoPreviews: set_preview_method(core.get_config()['preview_method']) else: - logging.warning("[ComfyUI-Manager] Since --preview-method is set, ComfyUI-Manager's preview method feature will be ignored.") + logging.warning( + "[ComfyUI-Manager] Since --preview-method is set, " + "ComfyUI-Manager's preview method feature will be ignored." + ) def set_component_policy(mode): @@ -1482,13 +1510,25 @@ async def install_model(request): @routes.get("/manager/preview_method") async def preview_method(request): + # Setting change request if "value" in request.rel_url.query: + # Reject setting change if per-queue preview feature is available + if COMFYUI_HAS_PER_QUEUE_PREVIEW: + return web.Response(text="DISABLED", status=403) + + # Process normally if not available set_preview_method(request.rel_url.query['value']) core.write_config() - else: - return web.Response(text=core.manager_funcs.get_current_preview_method(), status=200) + return web.Response(status=200) - return web.Response(status=200) + # Status query request + else: + # Return DISABLED if per-queue preview feature is available + if COMFYUI_HAS_PER_QUEUE_PREVIEW: + return web.Response(text="DISABLED", status=200) + + # Return current value if not available + return web.Response(text=core.manager_funcs.get_current_preview_method(), status=200) @routes.get("/manager/db_mode") diff --git a/js/comfyui-manager.js b/js/comfyui-manager.js index 51440a9e..bcf7e9e5 100644 --- a/js/comfyui-manager.js +++ b/js/comfyui-manager.js @@ -976,17 +976,96 @@ class ManagerMenuDialog extends ComfyDialog { let preview_combo = document.createElement("select"); preview_combo.setAttribute("title", "Configure how latent variables will be decoded during preview in the sampling process."); preview_combo.className = "cm-menu-combo p-select p-component p-inputwrapper p-inputwrapper-filled"; + + // Loading state to prevent flash of enabled state + preview_combo.appendChild($el('option', { value: '', text: 'Loading...', disabled: true }, [])); preview_combo.appendChild($el('option', { value: 'auto', text: 'Auto' }, [])); preview_combo.appendChild($el('option', { value: 'taesd', text: 'TAESD (slow)' }, [])); preview_combo.appendChild($el('option', { value: 'latent2rgb', text: 'Latent2RGB (fast)' }, [])); preview_combo.appendChild($el('option', { value: 'none', text: 'None (very fast)' }, [])); + // Start disabled to prevent flash + preview_combo.disabled = true; + preview_combo.value = ''; + + // Fetch current state api.fetchApi('/manager/preview_method') .then(response => response.text()) - .then(data => { preview_combo.value = data; }); + .then(data => { + // Remove loading option + preview_combo.querySelector('option[value=""]')?.remove(); + + if (data === "DISABLED") { + // ComfyUI per-queue preview feature is active + preview_combo.disabled = true; + preview_combo.value = 'auto'; + + // Accessibility attributes + preview_combo.setAttribute("aria-disabled", "true"); + preview_combo.setAttribute("aria-label", + "Preview method setting (disabled - managed by ComfyUI). " + + "Use Settings > Execution > Live preview method instead." + ); + + // Tooltip for mouse users + preview_combo.setAttribute("title", + "This feature is now provided natively by ComfyUI. " + + "Please use 'Settings > Execution > Live preview method' instead." + ); + + // Visual feedback + preview_combo.style.opacity = '0.6'; + preview_combo.style.cursor = 'not-allowed'; + } else { + // Manager feature is active + preview_combo.disabled = false; + preview_combo.value = data; + + // Accessibility for enabled state + preview_combo.setAttribute("aria-label", + "Preview method setting. Select how latent variables are decoded during preview." + ); + } + }) + .catch(error => { + console.error('[ComfyUI-Manager] Failed to fetch preview method status:', error); + // Error recovery: fallback to enabled + preview_combo.querySelector('option[value=""]')?.remove(); + preview_combo.disabled = false; + preview_combo.value = 'auto'; + }); preview_combo.addEventListener('change', function (event) { - api.fetchApi(`/manager/preview_method?value=${event.target.value}`); + // Ignore if disabled + if (preview_combo.disabled) { + event.preventDefault(); + return; + } + + // Normal operation + api.fetchApi(`/manager/preview_method?value=${event.target.value}`) + .then(response => { + if (response.status === 403) { + // Feature transitioned to native + alert( + 'This feature is now provided natively by ComfyUI.\n' + + 'Please use \'Settings > Execution > Live preview method\' instead.' + ); + preview_combo.disabled = true; + preview_combo.style.opacity = '0.6'; + preview_combo.style.cursor = 'not-allowed'; + + // Update aria attributes + preview_combo.setAttribute("aria-disabled", "true"); + preview_combo.setAttribute("aria-label", + "Preview method setting (disabled - managed by ComfyUI). " + + "Use Settings > Execution > Live preview method instead." + ); + } + }) + .catch(error => { + console.error('[ComfyUI-Manager] Preview method update failed:', error); + }); }); const previewSetttingItem = createSettingsCombo("Preview method", preview_combo); diff --git a/pyproject.toml b/pyproject.toml index 728c86ca..a22828b4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [project] name = "comfyui-manager" description = "ComfyUI-Manager provides features to install and manage custom nodes for ComfyUI, as well as various functionalities to assist with ComfyUI." -version = "3.38.3" +version = "3.39" license = { file = "LICENSE.txt" } dependencies = ["GitPython", "PyGithub", "matrix-nio", "transformers", "huggingface-hub>0.20", "typer", "rich", "typing-extensions", "toml", "uv", "chardet"]