From 4e61568ca38afb671fcb23d07293bc7fc91691ac Mon Sep 17 00:00:00 2001 From: x0x0b <42596409+x0x0b@users.noreply.github.com> Date: Wed, 29 Oct 2025 20:46:42 +0900 Subject: [PATCH] Enhance prompt history refresh --- prompt_history_gallery/hooks.py | 18 +++++++++++++- prompt_history_gallery/storage.py | 2 +- web/history_sidebar.js | 40 +++++++++++++++++++++++++++---- 3 files changed, 54 insertions(+), 6 deletions(-) diff --git a/prompt_history_gallery/hooks.py b/prompt_history_gallery/hooks.py index d8fcc6e..658f13e 100644 --- a/prompt_history_gallery/hooks.py +++ b/prompt_history_gallery/hooks.py @@ -77,6 +77,7 @@ def _handle_prompt_completion( prompt_id: Optional[str], history_result: Any, prompt_payload: Any, + server: Optional[Any], ) -> None: storage = get_prompt_history_storage() @@ -96,6 +97,15 @@ def _handle_prompt_completion( storage.touch_entries(entry_ids) + if server is not None: + try: + server.send_sync( + "PromptHistoryGallery.updated", + {"entry_ids": list(entry_ids)}, + ) + except Exception: # pragma: no cover + LOGGER.exception("Failed to notify clients about history update") + def _wrap_task_done() -> None: original = execution.PromptQueue.task_done @@ -104,6 +114,7 @@ def _wrap_task_done() -> None: def wrapper(self, item_id, history_result, status): # type: ignore[override] prompt_id: Optional[str] = None prompt_payload: Any = None + server = getattr(self, "server", None) try: with self.mutex: # type: ignore[attr-defined] prompt = self.currently_running.get(item_id) # type: ignore[attr-defined] @@ -118,7 +129,12 @@ def _wrap_task_done() -> None: return original(self, item_id, history_result, status) finally: try: - _handle_prompt_completion(prompt_id, history_result, prompt_payload) + _handle_prompt_completion( + prompt_id, + history_result, + prompt_payload, + server, + ) except Exception: # pragma: no cover - defensive logging. LOGGER.exception("Failed to store generated files for prompt %s", prompt_id) diff --git a/prompt_history_gallery/storage.py b/prompt_history_gallery/storage.py index 63382ac..8319e81 100644 --- a/prompt_history_gallery/storage.py +++ b/prompt_history_gallery/storage.py @@ -285,7 +285,7 @@ class PromptHistoryStorage: for item in normalized: cursor.execute( """ - INSERT INTO prompt_history_output + INSERT OR IGNORE INTO prompt_history_output (entry_id, filename, subfolder, type) VALUES (:entry_id, :filename, :subfolder, :type) diff --git a/web/history_sidebar.js b/web/history_sidebar.js index bac2a23..59fa338 100644 --- a/web/history_sidebar.js +++ b/web/history_sidebar.js @@ -79,8 +79,15 @@ function toDateLabel(value) { } } -function createHistoryComponent(api, toastStore, vueHelpers) { - const { defineComponent, ref, computed, onMounted, h } = vueHelpers; +function createHistoryComponent(api, toastStore, vueHelpers, eventBus) { + const { + defineComponent, + ref, + computed, + onMounted, + onBeforeUnmount, + h, + } = vueHelpers; return defineComponent({ name: "PromptHistorySidebar", @@ -198,7 +205,25 @@ function createHistoryComponent(api, toastStore, vueHelpers) { window.open(url, "_blank", "noopener,noreferrer"); }; - onMounted(fetchEntries); + const updateEventName = "PromptHistoryGallery.updated"; + const handleHistoryUpdate = () => { + fetchEntries(); + }; + + onMounted(() => { + fetchEntries(); + if (api?.addEventListener) { + api.addEventListener(updateEventName, handleHistoryUpdate); + } + eventBus?.on?.(updateEventName, handleHistoryUpdate); + }); + + onBeforeUnmount(() => { + if (api?.removeEventListener) { + api.removeEventListener(updateEventName, handleHistoryUpdate); + } + eventBus?.off?.(updateEventName, handleHistoryUpdate); + }); return { entries, @@ -471,16 +496,23 @@ async function registerHistoryTab() { const comfyApp = window.comfyAPI?.app?.app ?? null; const api = comfyApp?.api ?? window.comfyAPI?.api?.api ?? null; + const eventBus = comfyApp?.eventBus ?? null; const vueHelpers = { defineComponent: vue.defineComponent, ref: vue.ref, computed: vue.computed, onMounted: vue.onMounted, + onBeforeUnmount: vue.onBeforeUnmount, h: vue.h, }; - const component = createHistoryComponent(api, toastStore, vueHelpers); + const component = createHistoryComponent( + api, + toastStore, + vueHelpers, + eventBus + ); workspaceStore.registerSidebarTab({ id: TAB_ID,