From e9399fa7cd3cdce92eb4aa3cb4947eef1ac9cf53 Mon Sep 17 00:00:00 2001 From: Stelios Sotiriadis Date: Wed, 20 May 2026 23:38:47 +0100 Subject: [PATCH] Make GenAsset manager button independent --- .github/workflows/publish_action.yml | 3 ++ README.md | 2 +- js/genasset_manager.js | 56 ++++++++++++++++++++++++++-- pyproject.toml | 2 +- 4 files changed, 58 insertions(+), 5 deletions(-) diff --git a/.github/workflows/publish_action.yml b/.github/workflows/publish_action.yml index 6c92128..3bcc0cc 100644 --- a/.github/workflows/publish_action.yml +++ b/.github/workflows/publish_action.yml @@ -2,6 +2,9 @@ name: Publish to Comfy registry on: workflow_dispatch: + push: + tags: + - "v*" jobs: publish-node: diff --git a/README.md b/README.md index 755e13c..01a31d0 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ ComfyUI nodes for saving, loading, and versioning image generations in **GenAsse GenAsset keeps the output image together with the recipe (prompt, model, seed, sampler/scheduler, workflow JSON, metadata), so teams and agents can reproduce and reuse results reliably. -Current package version: **v1.0.17**. +Current package version: **v1.0.18**. ## Start Free diff --git a/js/genasset_manager.js b/js/genasset_manager.js index 2a25cd6..3a98b43 100644 --- a/js/genasset_manager.js +++ b/js/genasset_manager.js @@ -1783,6 +1783,55 @@ function managerButtonCandidates() { }); } +function buttonCandidatesMatching(pattern) { + return [...document.querySelectorAll("button")].filter((button) => { + const label = [button.getAttribute("aria-label"), button.getAttribute("title"), button.textContent] + .filter(Boolean) + .join(" ") + .trim(); + return pattern.test(label) && isVisibleElement(button); + }); +} + +function stableToolbarContainers() { + const selectors = [ + ".comfyui-menu", + ".comfyui-menu-right", + ".comfyui-menu-actions", + ".comfyui-queue-button", + ".comfyui-button-group", + ".comfyui-body-top", + ".comfyui-topbar", + ".comfyui-top-bar", + ".topbar", + ".p-toolbar", + ]; + const containers = []; + for (const selector of selectors) { + for (const element of document.querySelectorAll(selector)) { + if (element instanceof HTMLElement && isVisibleElement(element)) containers.push(element); + } + } + return containers; +} + +function toolbarAnchorCandidate() { + const managerButton = managerButtonCandidates()[0]; + if (managerButton?.parentElement) { + return { container: managerButton.parentElement, before: managerButton, mode: "manager" }; + } + + const runButton = buttonCandidatesMatching(/\brun\b/i)[0]; + if (runButton?.parentElement) { + return { container: runButton.parentElement, before: runButton, mode: "run" }; + } + + const container = stableToolbarContainers()[0]; + if (container) return { container, before: null, mode: "container" }; + + return null; +} + function createToolbarButton() { const button = document.createElement("button"); button.className = "genasset-toolbar-button"; @@ -1978,10 +2027,11 @@ function installToolbarButton() { const existingButtons = [...document.querySelectorAll(".genasset-toolbar-button")]; if (existingButtons.some(isVisibleElement)) return true; for (const existing of existingButtons) existing.remove(); - const managerButton = managerButtonCandidates()[0]; - if (!managerButton || !managerButton.parentElement) return false; + const anchor = toolbarAnchorCandidate(); + if (!anchor?.container) return false; const button = createToolbarButton(); - managerButton.parentElement.insertBefore(button, managerButton); + if (anchor.mode !== "manager") button.dataset.genassetAnchor = anchor.mode; + anchor.container.insertBefore(button, anchor.before || null); return true; } diff --git a/pyproject.toml b/pyproject.toml index 9d04076..83b5b0b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "genasset" -version = "1.0.17" +version = "1.0.18" description = "ComfyUI nodes for saving, loading, and versioning GenAsset generations." license = { file = "LICENSE" } requires-python = ">=3.10"