From e4b6fcf9d320c2a28c8fa9b008bf40483a3edf51 Mon Sep 17 00:00:00 2001 From: noembryo Date: Sun, 16 Aug 2026 15:46:15 +0300 Subject: [PATCH] 1.4.0 --- README.md | 14 +- __init__.py | 3 +- load_image_from_path.py | 371 +++++++++++++++++++++ nodes.py | 3 + pyproject.toml | 3 +- stuff/LoadImageFromPath.jpg | Bin 0 -> 66503 bytes web/js/load_image_from_path.js | 591 +++++++++++++++++++++++++++++++++ 7 files changed, 979 insertions(+), 6 deletions(-) create mode 100644 load_image_from_path.py create mode 100644 stuff/LoadImageFromPath.jpg create mode 100644 web/js/load_image_from_path.js diff --git a/README.md b/README.md index be9f500..fe95cdd 100644 --- a/README.md +++ b/README.md @@ -50,21 +50,27 @@ For the custom text integration, there is a variable (can be specified by the us _**After changing the `.json` file, we must reload the ComfyUI page, so the node can reload the updated file.**_ +--- +## Load Image (from path) +![LoadImage](https://raw.githubusercontent.com/noembryo/ComfyUI-noEmbryo/master/stuff/LoadImageFromPath.png) +A node lets you load an image from any path in your computer, either by pasting an address, or by using a file picker to browse your drives. +It also displays the image in the node. +It's an enhanced version of the "[Load Image From Path (Enhanced)](https://github.com/Chaoses-Ib/ComfyUI_Ib_CustomNodes#load-image-from-path-enhanced)" from [`ComfyUI_Ib_CustomNodes`](ComfyUI_Ib_CustomNodes). --- ## Resolution Scale -![Demo workflow](https://raw.githubusercontent.com/noembryo/ComfyUI-noEmbryo/master/stuff/res_scale1.png) +![ResolutionScale](https://raw.githubusercontent.com/noembryo/ComfyUI-noEmbryo/master/stuff/res_scale1.png) A simple node that outputs the resolution of an image using the dimensions of an input image or some custom user-defined dimensions, using a Scale Factor. If there is an input image connected, setting either `width` or `height` to 0 will use the other dimension to scale the image (but always multiple of 4). --- ## Regex Text Chopper -![Demo workflow](https://raw.githubusercontent.com/noembryo/ComfyUI-noEmbryo/master/stuff/regex_text.png) +![RegExChopper](https://raw.githubusercontent.com/noembryo/ComfyUI-noEmbryo/master/stuff/regex_text.png) A node that "chops" a text using a regular expression and outputs the chopped parts of the text. --- ## Auto Save Workflow -![Demo workflow](https://raw.githubusercontent.com/noembryo/ComfyUI-noEmbryo/master/stuff/auto_save_workflow.png) +![AutoSaveWorkflow](https://raw.githubusercontent.com/noembryo/ComfyUI-noEmbryo/master/stuff/auto_save_workflow.png) This node can save the current workflow to a `.json` file, every time a generation job is run. - **UI controls** - **save_directory** is the directory where the `.json` file will be saved. @@ -82,7 +88,7 @@ This node can save the current workflow to a `.json` file, every time a generati **The PromptTermList nodes are now obsolete, and can mostly be replaced by the [Json Prompt Loader](#json-prompt-loader) node. I won't remove them for compatibility reasons, but I would recommend using the [JsonPromptLoader](#json-prompt-loader) node instead.** -![Demo workflow](https://raw.githubusercontent.com/noembryo/ComfyUI-noEmbryo/master/stuff/Screen2.png) +![PromptTermList](https://raw.githubusercontent.com/noembryo/ComfyUI-noEmbryo/master/stuff/Screen2.png) These are some nodes that help with the creation of Prompts inside [ComfyUI](https://github.com/comfyanonymous/ComfyUI). ### Usage diff --git a/__init__.py b/__init__.py index f99e10a..68fb1b9 100644 --- a/__init__.py +++ b/__init__.py @@ -10,6 +10,7 @@ import os import io from os.path import isfile, join, isdir import importlib +import types from aiohttp import web from server import PromptServer @@ -24,7 +25,7 @@ NODE_DISPLAY_NAME_MAPPINGS = {} node_list = [ "nodes", - # "load_image_from_dir", + # "load_image_from_path", ] for module_name in node_list: diff --git a/load_image_from_path.py b/load_image_from_path.py new file mode 100644 index 0000000..c8197fe --- /dev/null +++ b/load_image_from_path.py @@ -0,0 +1,371 @@ +import hashlib +from pathlib import Path +from typing import Iterable +import os +import json +import shutil + +from PIL import (Image, ImageOps, ImageSequence, ImageFile, UnidentifiedImageError, ) +import numpy as np +import torch + +import folder_paths +from aiohttp import web +from server import PromptServer + + +def _pillow(fn, arg): + prev_value = None + try: + x = fn(arg) + except (OSError, UnidentifiedImageError, ValueError): + # PIL issues #4472 and #2445, also fixes ComfyUI issue #3416 + prev_value = ImageFile.LOAD_TRUNCATED_IMAGES + ImageFile.LOAD_TRUNCATED_IMAGES = True + x = fn(arg) + finally: + if prev_value is not None: + ImageFile.LOAD_TRUNCATED_IMAGES = prev_value + return x + + +def _pil_to_image_mask(img: 'Image.Image | Iterable[Image.Image]', + output_image: 'list[torch.Tensor] | None', + output_mask: 'list[torch.Tensor] | None'): + output_images = [] + output_masks = [] + w, h = None, None + + excluded_formats = ['MPO'] + + if not isinstance(img, Iterable): + if img.format not in excluded_formats: + img = ImageSequence.Iterator(img) + else: + img = [img] + + for i in img: + i: Image.Image + i = _pillow(ImageOps.exif_transpose, i) + + if i.mode == 'I': + i = i.point(lambda x: x * (1 / 255)) + + if len(output_images) == 0 and len(output_masks) == 0: + w = i.size[0] + h = i.size[1] + elif i.size[0] != w or i.size[1] != h: + continue + + if output_image is not None: + image = i.convert("RGB") + + image = np.array(image).astype(np.float32) / 255.0 + image = torch.from_numpy(image)[None,] + output_images.append(image) + + if output_mask is not None: + if 'A' in i.getbands(): + mask = np.array(i.getchannel('A')).astype(np.float32) / 255.0 + mask = 1. - torch.from_numpy(mask) + elif i.mode == 'P' and 'transparency' in i.info: + # https://github.com/comfyanonymous/ComfyUI/pull/7539 + mask = np.array(i.convert('RGBA').getchannel('A')).astype( + np.float32) / 255.0 + mask = 1. - torch.from_numpy(mask) + else: + mask = torch.zeros((64, 64), dtype=torch.float32, device="cpu") + # (H, W) -> (1, H, W) + mask = mask.unsqueeze(0) + output_masks.append(mask) + + if len(output_images) > 1: + if output_image is not None: + output_image[:] = [torch.cat(output_images, dim=0)] + if output_mask is not None: + output_mask[:] = [torch.cat(output_masks, dim=0)] + else: + if output_image is not None: + output_image[:] = [output_images[0]] + if output_mask is not None: + output_mask[:] = [output_masks[0]] + + +class LoadImageFromPath: + @classmethod + def INPUT_TYPES(cls): + return {"required": + {"image": ("STRING", + {"default": r"ComfyUI_00001_-assets\ComfyUI_00001_.png " + r"[output]"})}, + } + + CATEGORY = "noEmbryo" + + RETURN_TYPES = ("IMAGE", "MASK") + FUNCTION = "load_image" + + @staticmethod + def load_image(image): + image_path = LoadImageFromPath._resolve_path(image) + + i = _pillow(Image.open, image_path) + + image = [] + mask = [] + _pil_to_image_mask(i, image, mask) + return image[0], mask[0] + + @staticmethod + def _resolve_path(image) -> Path: + # Keep support for the old annotated forms + name, base_dir = folder_paths.annotated_filepath(image) + if base_dir is not None: + # Annotated path – still go through the secure helper + return Path(folder_paths.get_annotated_filepath(image)) + + # noinspection PyTypeChecker + p = Path(image).expanduser() # No annotation → treat as a real filesystem path + if not p.is_absolute(): + # Relative path without annotation → relative to input (old behaviour) + p = Path(folder_paths.get_input_directory()) / p + return p.resolve() + + @classmethod + def IS_CHANGED(cls, image): + image_path = LoadImageFromPath._resolve_path(image) + m = hashlib.sha256() + with open(image_path, 'rb') as f: + m.update(f.read()) + return m.digest().hex() + + @classmethod + def VALIDATE_INPUTS(cls, image): + if image is None: + return True + try: + image_path = LoadImageFromPath._resolve_path(image) + except ValueError as e: + return str(e) + if not image_path.exists(): + return "Invalid image path: {}".format(image_path) + if not image_path.is_file(): + return "Path is not a file: {}".format(image_path) + return True + + +# Global cache to track image paths and ClipSpace mappings +_image_path_cache = {} +_clipspace_mappings = {} # Maps expected filename -> actual filename + + +class LoadImageFromPathEnhanced(LoadImageFromPath): + @classmethod + def INPUT_TYPES(cls): + return {"required": {"image": ("STRING", {"default": ""})}, } + + CATEGORY = "image" + RETURN_TYPES = ("IMAGE", "MASK", "STRING") + RETURN_NAMES = ("IMAGE", "MASK", "path") + FUNCTION = "load_image_enhanced" + + def load_image_enhanced(self, image): + # Get the full path + image_path = LoadImageFromPath._resolve_path(image) + + # Call the parent class's load_image method + image_tensor, mask = super().load_image(image) + + # Register this image in our cache for mask editor support + filename = os.path.basename(str(image_path)) + _image_path_cache[filename] = str(image_path) + _image_path_cache[str(image_path)] = str(image_path) + + # Return image, mask, AND the original input path string + return image_tensor, mask, image + + +# Middleware to handle clipspace file resolution +@web.middleware +async def clipspace_resolver_middleware(request, handler): + """ + Middleware to intercept /api/view requests and resolve clipspace filename mismatches. + This fixes the issue where mask editor looks for 'clipspace-mask-X.png' but + the actual file is 'clipspace-painted-masked-X.png' + """ + if request.path == '/api/view': + filename = request.query.get('filename', '') + subfolder = request.query.get('subfolder', '') + + # Only intercept clipspace requests looking for 'clipspace-mask-' files + if subfolder == 'clipspace' and filename.startswith('clipspace-mask-'): + input_dir = folder_paths.get_input_directory() + clipspace_dir = os.path.join(input_dir, 'clipspace') + + # Check if the requested file exists + requested_path = os.path.join(clipspace_dir, filename) + + if not os.path.exists(requested_path): + # Try to find the actual file with 'painted-masked' naming + number = filename.replace('clipspace-mask-', '').replace('.png', '') + alternative_filename = f'clipspace-painted-masked-{number}.png' + alternative_path = os.path.join(clipspace_dir, alternative_filename) + + if os.path.exists(alternative_path): + # Create a symlink or copy to the expected filename + try: + # Try symlink first (faster) + if os.name != 'nt': # Unix-like systems + if not os.path.exists(requested_path): + os.symlink(alternative_path, requested_path) + else: # Windows - use copy instead + shutil.copy2(alternative_path, requested_path) + except Exception as e: + print(f"[IB] Could not create link/copy: {e}") + + # Continue with normal handling + return await handler(request) + + +# Register middleware +PromptServer.instance.app.middlewares.append(clipspace_resolver_middleware) + + +# Server endpoints for file browsing +@PromptServer.instance.routes.get("/noembryo/browse_directory") +async def browse_directory(request): + """Browse directories and return file listings""" + try: + path = request.query.get('path', '') + sort_method = request.query.get('sort', 'name_asc') + + if not path: + if os.name == 'nt': + drives = [f"{d}:\\" for d in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' if + os.path.exists(f"{d}:\\")] + return web.json_response( + {'directories': drives, 'files': [], 'current_path': '', + 'parent_path': None, # Up stays disabled on the drive list + 'sort_method': sort_method}) + else: # Unix-like + path = os.path.expanduser('~') + + path = os.path.abspath(path) + + if not os.path.exists(path) or not os.path.isdir(path): + return web.json_response({'error': 'Invalid path'}, status=400) + + directories = [] + files = [] + + try: + items = [] + for item in os.listdir(path): + if item.startswith('.'): + continue + + item_path = os.path.join(path, item) + try: + if os.path.isdir(item_path): + item_type = 'directory' + stat = os.stat(item_path) + elif os.path.isfile(item_path): + ext = os.path.splitext(item)[1].lower() + if ext in ['.png', '.jpg', '.jpeg', '.bmp', '.gif', '.webp', + '.tiff', '.tif']: + item_type = 'file' + stat = os.stat(item_path) + else: + continue + else: + continue + except (PermissionError, OSError): + continue + + items.append({'name': item, 'type': item_type, 'path': item_path, + 'modified': stat.st_mtime}) + + # Apply sorting + if sort_method == 'name_asc': + items.sort(key=lambda x: x['name'].lower()) + elif sort_method == 'name_desc': + items.sort(key=lambda x: x['name'].lower(), reverse=True) + elif sort_method == 'date_desc': + items.sort(key=lambda x: x['modified'], reverse=True) + elif sort_method == 'date_asc': + items.sort(key=lambda x: x['modified']) + + for item in items: + if item['type'] == 'directory': + directories.append(item['name']) + else: + files.append(item['name']) + + except PermissionError: + return web.json_response({'error': 'Permission denied'}, status=403) + + # parent_path = os.path.dirname(path) if path != os.path.dirname(path) else None + parent = os.path.dirname(path) + if parent == path: # At a filesystem root (e.g. "D:\" on Windows or "/" on Unix) + if os.name == 'nt': + parent_path = '' # empty string → show drive list + else: + parent_path = None # already at / + else: + parent_path = parent + + return web.json_response( + {'directories': directories, 'files': files, 'current_path': path, + 'parent_path': parent_path, 'sort_method': sort_method}) + + except Exception as e: + return web.json_response({'error': str(e)}, status=500) + + +@PromptServer.instance.routes.get("/noembryo/get_image_preview") +async def get_image_preview(request): + """Get a preview of an image at the given path""" + try: + image_path = request.query.get('path', '') + + if not image_path or not os.path.exists(image_path): + return web.json_response({'error': 'Invalid image path'}, status=400) + + img = _pillow(Image.open, image_path) + img = _pillow(ImageOps.exif_transpose, img) + + max_size = (512, 512) + img.thumbnail(max_size, Image.Resampling.LANCZOS) + + from io import BytesIO + import base64 + + buffer = BytesIO() + img.save(buffer, format='PNG') + img_str = base64.b64encode(buffer.getvalue()).decode() + + return web.json_response( + {'preview': f'data:image/png;base64,{img_str}', 'width': img.width, + 'height': img.height}) + + except Exception as e: + return web.json_response({'error': str(e)}, status=500) + + +@PromptServer.instance.routes.get("/noembryo/serve_image") +async def serve_image(request): + """Serve image file directly""" + try: + image_path = request.query.get('path', '') + + if not image_path or not os.path.exists(image_path): + return web.Response(status=404, text='Image not found') + + response = web.FileResponse(image_path) + response.headers['Access-Control-Allow-Origin'] = '*' + response.headers['Access-Control-Allow-Methods'] = 'GET, OPTIONS' + response.headers['Access-Control-Allow-Headers'] = '*' + return response + + except Exception as e: + return web.Response(status=500, text=f'Error serving image: {str(e)}') diff --git a/nodes.py b/nodes.py index 772ac78..3fb36e6 100644 --- a/nodes.py +++ b/nodes.py @@ -3,6 +3,7 @@ import json from os.path import realpath, join, dirname, isabs, splitext, basename from datetime import datetime import folder_paths +from .load_image_from_path import LoadImageFromPathEnhanced MANIFEST = {"name": "noEmbryo Nodes", "version": (1, 0, 3), @@ -476,6 +477,7 @@ NODE_CLASS_MAPPINGS = {f"JsonPromptLoader -{__author__}": JsonPromptLoader, f"Resolution Scale -{__author__}": ResolutionScale, f"Regex Text Chopper -{__author__}": RegExTextChopper, f"Auto Save Workflow -{__author__}": AutoSaveWorkflow, + f"Load Image (from path) -{__author__}": LoadImageFromPathEnhanced, "PromptTermList1": PromptTermList1, "PromptTermList2": PromptTermList2, "PromptTermList3": PromptTermList3, @@ -488,6 +490,7 @@ NODE_DISPLAY_NAME_MAPPINGS = {f"JsonPromptLoader -{__author__}": f"Json Prompt L f"Resolution Scale -{__author__}": f"Resolution Scale /{__author__}", f"Regex Text Chopper -{__author__}": f"Regex Text Chopper /{__author__}", f"Auto Save Workflow -{__author__}": f"Auto Save Workflow /{__author__}", + f"Load Image (from path) -{__author__}": f"Load Image (from path) /{__author__}", "PromptTermList1": f"PromptTermList 1 /{__author__}", "PromptTermList2": f"PromptTermList 2 /{__author__}", "PromptTermList3": f"PromptTermList 3 /{__author__}", diff --git a/pyproject.toml b/pyproject.toml index 0c9dbf5..98013cb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,13 +2,14 @@ name = "comfyui-noembryo" description = """ A collection of nodes for ComyUI. +* "Load Image (from path)" is a node lets you load an image from any path in your computer, and also displays the image in the node. * "JsonPromptLoader" is a node that enhances a propt using a .json file with `item:prompt` pairs. * "Resolution Scale" is a node that resizes an image using pixels or scale factor. * "Regex Text Chopper" is a node that cuts text based on regex. * "Auto Save Workflow" can save the current workflow to a .json file automatically. * "PromptTermList (1-6)" nodes to help with the creation of Prompts. """ -version = "1.3.2" +version = "1.4.0" license = {text = "MIT License"} [project.urls] diff --git a/stuff/LoadImageFromPath.jpg b/stuff/LoadImageFromPath.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3c2bb844b3da1dc846b16ab0e0f94a4adc205395 GIT binary patch literal 66503 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 literal 0 HcmV?d00001 diff --git a/web/js/load_image_from_path.js b/web/js/load_image_from_path.js new file mode 100644 index 0000000..ca859d0 --- /dev/null +++ b/web/js/load_image_from_path.js @@ -0,0 +1,591 @@ +import {app} from "../../scripts/app.js"; +import {api} from "../../scripts/api.js"; + +// Store last browsed path +let lastBrowsedPath = ''; + +/** Return the directory of a path string (handles Windows/Unix + [input]/[output]/[temp] suffixes). */ +function dirnameOf(pathStr) { + if (!pathStr || typeof pathStr !== 'string') return ''; + // Strip annotation like " foo.png [output]" + let p = pathStr.replace(/\s*\[[^\]]+\]\s*$/, '').trim(); + if (!p) return ''; + // Remove trailing slash + p = p.replace(/[/\\]+$/, ''); + const lastSep = Math.max(p.lastIndexOf('/'), p.lastIndexOf('\\')); + if (lastSep <= 0) return p; // bare filename or drive root + return p.substring(0, lastSep); // directory part +} + +// File browser dialog +class FileBrowserDialog { + constructor(initialPath) { + // Prefer the path that is already in the node, then fall back to last browsed + const fromWidget = dirnameOf(initialPath); + this.currentPath = fromWidget || lastBrowsedPath || ''; + this.initialFilePath = initialPath || null; // ← keep the full path + this.selectedFile = null; + this.callback = null; + } + + async show(callback) { + this.callback = callback; + + // Create dialog overlay + const overlay = document.createElement('div'); + overlay.style.cssText = ` + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(0, 0, 0, 0.8); + display: flex; + justify-content: center; + align-items: center; + z-index: 10000; + `; + + // Make overlay focusable + overlay.tabIndex = -1; + overlay.focus(); + + // Create dialog container + const dialog = document.createElement('div'); + dialog.style.cssText = ` + background: #2a2a2a; + border: 1px solid #555; + border-radius: 6px; + width: 85%; + max-width: 900px; + height: 75%; + display: flex; + flex-direction: column; + color: #eee; + font-family: system-ui, sans-serif; + font-size: 13px; + box-shadow: 0 10px 30px rgba(0,0,0,0.5); + `; + + // Create header with view controls + const header = document.createElement('div'); + header.style.cssText = ` + padding: 12px 15px; + border-bottom: 1px solid #444; + display: flex; + justify-content: space-between; + align-items: center; + background: #333; + `; + header.innerHTML = ` +

Select Image

+
+ + +
+ `; + + // Create path display - EDITABLE VERSION + const pathDisplay = document.createElement('div'); + pathDisplay.id = 'pathDisplay'; + pathDisplay.style.cssText = ` + padding: 8px 15px; + background: #333; + border-bottom: 1px solid #444; + font-family: 'Courier New', monospace; + font-size: 11px; + display: flex; + align-items: center; + gap: 8px; + color: #ccc; + `; + + // Create browser content area + const content = document.createElement('div'); + content.id = 'browserContent'; + content.style.cssText = ` + flex: 1; + overflow-y: auto; + padding: 4px; + background: #1a1a1a; + `; + + // Create preview area + const previewArea = document.createElement('div'); + previewArea.id = 'previewArea'; + previewArea.style.cssText = ` + border-top: 1px solid #444; + padding: 12px 15px; + display: flex; + gap: 12px; + align-items: center; + min-height: 80px; + background: #2a2a2a; + font-size: 12px; + `; + + // Create footer with buttons + const footer = document.createElement('div'); + footer.style.cssText = ` + padding: 12px 15px; + border-top: 1px solid #444; + display: flex; + justify-content: flex-end; + gap: 8px; + background: #333; + `; + footer.innerHTML = ` + + + `; + + dialog.appendChild(header); + dialog.appendChild(pathDisplay); + dialog.appendChild(content); + dialog.appendChild(previewArea); + dialog.appendChild(footer); + overlay.appendChild(dialog); + document.body.appendChild(overlay); + + + const escHandler = (e) => { + // Don't steal keys while typing in the path box, except Esc + const inPathInput = e.target && e.target.id === 'pathInput'; + + if (e.key === 'Escape') { + e.preventDefault(); + close(); + return; + } + + if (inPathInput) return; // let Enter in the path box still mean "Go" + + if (e.key === 'Enter') { + e.preventDefault(); + if (this.selectedFile) { + selectAndClose(); // same as clicking "Select" + } + return; + } + + if (e.key === 'ArrowLeft') { + e.preventDefault(); + document.getElementById('prevImg')?.click(); + } else if (e.key === 'ArrowRight') { + e.preventDefault(); + document.getElementById('nextImg')?.click(); + } else if (e.key === 'ArrowUp') { + e.preventDefault(); + document.getElementById('prevImg')?.click(); + } else if (e.key === 'ArrowDown') { + e.preventDefault(); + document.getElementById('nextImg')?.click(); + } + }; + document.addEventListener('keydown', escHandler); + + + // Close function + const close = () => { + document.removeEventListener('keydown', escHandler); + document.body.removeChild(overlay); + }; + + // Event handlers + overlay.querySelector('#closeBrowser').onclick = close; + overlay.querySelector('#cancelBrowser').onclick = close; + + const selectAndClose = () => { + if (this.selectedFile) { + const separator = this.selectedFile.includes('\\') ? '\\' : '/'; + lastBrowsedPath = this.selectedFile.substring(0, this.selectedFile.lastIndexOf(separator)); + this.callback(this.selectedFile); + close(); + } + }; + + overlay.querySelector('#selectFile').onclick = selectAndClose; + + // Add the sort change handler + const sortSelect = overlay.querySelector('#sortMethod'); + sortSelect.onchange = () => { + this.loadDirectory(this.currentPath); + }; + + // Load initial directory + await this.loadDirectory(this.currentPath); + } + + async loadDirectory(path) { + this.currentPath = path; + const content = document.getElementById('browserContent'); + const pathDisplay = document.getElementById('pathDisplay'); + const previewArea = document.getElementById('previewArea'); + + content.innerHTML = '
Loading...
'; + previewArea.innerHTML = ''; + this.selectedFile = null; + document.getElementById('selectFile').disabled = true; + + try { + const sortMethod = document.getElementById('sortMethod') ? document.getElementById('sortMethod').value : 'name_asc'; + const response = await api.fetchApi(`/noembryo/browse_directory?path=${encodeURIComponent(path)}&sort=${encodeURIComponent(sortMethod)}`); + const data = await response.json(); + + if (data.error) { + content.innerHTML = `
Error: ${data.error}
`; + return; + } + + const sortSelect = document.getElementById('sortMethod'); + if (sortSelect && data.sort_method) { + sortSelect.value = data.sort_method; + } + + // Update path display + pathDisplay.innerHTML = ` + + + + `; + + // Add event handler for the Go button and Enter key + const pathInput = document.getElementById('pathInput'); + const goPathBtn = document.getElementById('goPath'); + + const goToPath = () => { + const newPath = pathInput.value.trim(); + if (newPath) { + this.loadDirectory(newPath); + } + }; + + goPathBtn.onclick = goToPath; + pathInput.onkeypress = (e) => { + if (e.key === 'Enter') { + goToPath(); + } + }; + + const goUpBtn = document.getElementById('goUp'); + if (data.parent_path !== undefined && data.parent_path !== null) { + // "" is valid → opens the drive list on Windows + goUpBtn.onclick = () => this.loadDirectory(data.parent_path); + goUpBtn.disabled = false; + goUpBtn.style.opacity = '1'; + goUpBtn.style.cursor = 'pointer'; + } else { + goUpBtn.disabled = true; + goUpBtn.style.opacity = '0.4'; + goUpBtn.style.cursor = 'not-allowed'; + } + + // Build file list - LIST VIEW ONLY + let html = '
'; + + // Directories in list view + for (const dir of data.directories) { + const fullPath = data.current_path ? `${data.current_path}${data.current_path.endsWith('/') || data.current_path.endsWith('\\') ? '' : (path.includes('\\') ? '\\' : '/')}${dir}` : dir; + html += ` +
+ 📁 + ${dir} +
+ `; + } + + this.fileList = []; // reset every time the folder changes + + // Files in list view + for (const file of data.files) { + // const fullPath = data.current_path ? `${data.current_path}${data.current_path.endsWith('/') || data.current_path.endsWith('\\') ? '' : (data.current_path.includes('\\') ? '\\' : '/')}${file}` : file; + const fullPath = data.current_path + ? `${data.current_path}${data.current_path.endsWith('/') || data.current_path.endsWith('\\') ? '' : (data.current_path.includes('\\') ? '\\' : '/')}${file}` + : file; + this.fileList.push(fullPath); + html += ` +
+ 🖼️ + ${file} +
+ `; + } + + html += '
'; + content.innerHTML = html; + + // Add click handlers + this.attachEventHandlers(content); + + // If we opened from a pasted path, pre-select that file (once) + if (this.initialFilePath) { + const target = this.initialFilePath.replace(/\s*\[[^\]]+\]\s*$/, '').trim(); + const files = content.querySelectorAll('.browser-item.file'); + for (const item of files) { + const p = item.getAttribute('data-path') || ''; + // loose match: ignore slash direction and case (Windows) + if (p.replace(/\//g, '\\').toLowerCase() === target.replace(/\//g, '\\').toLowerCase()) { + item.click(); // reuses existing select + preview logic + item.scrollIntoView({block: 'nearest'}); + break; + } + } + this.initialFilePath = null; // only on the first open + } + + } catch (error) { + content.innerHTML = `
Error loading directory: ${error.message}
`; + } + } + + attachEventHandlers(content) { + // Click handlers for directories + content.querySelectorAll('.browser-item.directory').forEach(item => { + item.onclick = () => { + const path = item.getAttribute('data-path'); + this.loadDirectory(path); + }; + item.onmouseenter = () => { + item.style.background = '#3a3a3a'; + item.style.border = '1px solid #666'; + }; + item.onmouseleave = () => { + item.style.background = '#333'; + item.style.border = '1px solid transparent'; + }; + }); + + // Click handlers for files + content.querySelectorAll('.browser-item.file').forEach(item => { + let clickTimer; + let clickCount = 0; + + const selectFile = async () => { + // Remove selection from other items + content.querySelectorAll('.browser-item.file').forEach(i => { + i.style.background = '#2a2a2a'; + i.style.border = '1px solid transparent'; + }); + + // Highlight this item + item.style.background = '#2a4a2a'; + item.style.border = '1px solid #3a7a3a'; + + const path = item.getAttribute('data-path'); + this.selectedFile = path; + document.getElementById('selectFile').disabled = false; + + // Load preview + await this.loadPreview(path); + }; + + // Click handler for both single and double click + item.onclick = (e) => { + clickCount++; + + if (clickCount === 1) { + clickTimer = setTimeout(() => { + // Single click behavior + selectFile(); + clickCount = 0; + }, 300); + } else if (clickCount === 2) { + // Double click behavior + clearTimeout(clickTimer); + const path = item.getAttribute('data-path'); + this.selectedFile = path; + const separator = path.includes('\\') ? '\\' : '/'; + lastBrowsedPath = path.substring(0, path.lastIndexOf(separator)); + this.callback(path); + document.body.querySelector('[style*="z-index: 10000"]')?.remove(); + clickCount = 0; + } + }; + + item.onmouseenter = () => { + if (item.style.background !== '#2a4a2a') { + item.style.background = '#3a3a3a'; + item.style.border = '1px solid #666'; + } + }; + item.onmouseleave = () => { + if (item.style.background !== '#2a4a2a') { + item.style.background = '#2a2a2a'; + item.style.border = '1px solid transparent'; + } + }; + }); + } + + + async selectByPath(path) { + const content = document.getElementById('browserContent'); + if (!content) return; + const item = [...content.querySelectorAll('.browser-item.file')] + .find(el => (el.getAttribute('data-path') || '').replace(/\//g, '\\').toLowerCase() + === path.replace(/\//g, '\\').toLowerCase()); + if (!item) return; + item.click(); + item.scrollIntoView({block: 'nearest'}); + } + + async loadPreview(path) { + const previewArea = document.getElementById('previewArea'); + previewArea.innerHTML = '
Loading preview...
'; + + try { + const response = await api.fetchApi(`/noembryo/get_image_preview?path=${encodeURIComponent(path)}`); + const data = await response.json(); + + if (data.error) { + previewArea.innerHTML = `
Preview error: ${data.error}
`; + return; + } + + + const idx = (this.fileList || []).findIndex(p => + p.replace(/\//g, '\\').toLowerCase() === path.replace(/\//g, '\\').toLowerCase() + ); + const hasPrev = idx > 0; + const hasNext = idx >= 0 && idx < (this.fileList.length - 1); + + previewArea.innerHTML = ` +
+ + + +
+
+
${data.width} × ${data.height}
+
+ ${path.split(/[\\/]/).pop()} +
+
+ `; + + document.getElementById('prevImg').onclick = () => { + if (hasPrev) this.selectByPath(this.fileList[idx - 1]); + }; + document.getElementById('nextImg').onclick = () => { + if (hasNext) this.selectByPath(this.fileList[idx + 1]); + }; + + + } catch (error) { + previewArea.innerHTML = `
Error loading preview
`; + } + } +} + +app.registerExtension({ + name: "noEmbryo.LoadImageFromPath", + + async beforeRegisterNodeDef(nodeType, nodeData, app) { + if (nodeData.name === "Load Image (from path) -noEmbryo") { + const onNodeCreated = nodeType.prototype.onNodeCreated; + + nodeType.prototype.onNodeCreated = function () { + const result = onNodeCreated ? onNodeCreated.apply(this, arguments) : undefined; + const node = this; + + // Add browse button + node.addWidget("button", "🔍 Browse...", null, () => { + const pathWidget = node.widgets.find(w => w.name === "image"); + const currentPath = pathWidget ? pathWidget.value : ''; + + const browser = new FileBrowserDialog(currentPath); // ← pass it here + browser.show(async (filePath) => { + const pathWidget = node.widgets.find(w => w.name === "image"); + if (pathWidget) { + pathWidget.value = filePath; + + // Load image using ComfyUI's proper system + try { + const filename = filePath.split(/[\\/]/).pop(); + const imgUrl = `/noembryo/serve_image?path=${encodeURIComponent(filePath)}&filename=${encodeURIComponent(filename)}`; + const img = new Image(); + + // Add cache busting to prevent cached issues + img.src = imgUrl + '&t=' + Date.now(); + + img.onload = () => { + // Ensure node.imgs exists and is properly set + if (!node.imgs) { + node.imgs = []; + } + node.imgs = [img]; + node.imageIndex = 0; + + // Force a more comprehensive refresh + app.graph.setDirtyCanvas(true, true); + + // Also trigger node refresh specifically + if (node.onDrawBackground) { + node.onDrawBackground(); + } + }; + + img.onerror = () => { + console.warn('Failed to load image preview:', filePath); + // Clear any broken images but keep the node functional + node.imgs = null; + node.imageIndex = 0; + app.graph.setDirtyCanvas(true, true); + }; + + } catch (e) { + console.error('Failed to load image:', e); + node.imgs = null; + node.imageIndex = 0; + app.graph.setDirtyCanvas(true, true); + } + } + }); + }); + + return result; + }; + } + } +}); \ No newline at end of file