From 54979701d06dfe9deeef5710c277cf8bd05a7c9c Mon Sep 17 00:00:00 2001 From: Johnpaul Chiwetelu <49923152+Myestery@users.noreply.github.com> Date: Sat, 8 Nov 2025 12:36:04 +0100 Subject: [PATCH] Cloud feedback Extension (#6626) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This pull request introduces a new extensible system for adding custom action bar buttons to the top menu, and demonstrates its use by adding a cloud feedback button. The changes include defining a new `ActionBarButton` type, updating the extension system to support action bar buttons, creating a Pinia store to aggregate buttons from extensions, and updating the UI to render these buttons in the top menu. The cloud feedback button is now conditionally loaded for cloud environments. **Extensible Action Bar Button System** * Defined a new `ActionBarButton` interface in `comfy.ts` for describing buttons (icon, label, tooltip, class, click handler) and added an `actionBarButtons` property to the `ComfyExtension` interface to allow extensions to contribute buttons. [[1]](diffhunk://#diff-c29886a1b0c982c6fff3545af0ca Screenshot 2025-11-07 at 01 07 36 8ec269876c2cf3948f867d08c14032c04d66R60-R82) [[2]](diffhunk://#diff-c29886a1b0c982c6fff3545af0ca8ec269876c2cf3948f867d08c14032c04d66R128-R131) * Created a Pinia store (`actionBarButtonStore.ts`) that collects all action bar buttons from registered extensions for use in the UI. **UI Integration** * Added a new `ActionBarButtons.vue` component that renders all action bar buttons using the store, and integrated it into the top menu section (`TopMenuSection.vue`). [[1]](diffhunk://#diff-d6820f57cde865083d515ac0c23e1ad09e6fbc6792d742ae948a1d3b772be473R1-R28) [[2]](diffhunk://#diff-45dffe390927ed2d5ba2426a139c52adae28ce15f81821c88e7991944562074cR10) [[3]](diffhunk://#diff-45dffe390927ed2d5ba2426a139c52adae28ce15f81821c88e7991944562074cR28) **Cloud Feedback Button Extension** * Implemented a new extension (`cloudFeedbackTopbarButton.ts`) that registers a "Feedback" button opening the Zendesk feedback page, and ensured it loads only in cloud environments. [[1]](diffhunk://#diff-b84a6a0dfaca19fd77b3fae6999a40c3ab8d04ed22636fcdecc65b385a8e9a98R1-R24) [[2]](diffhunk://#diff-236993d9e4213efe96d267c75c3292d32b93aa4dd6c3318d26a397e0ae56bc87R32) ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-6626-Cloud-feedback-Extension-2a46d73d36508170bd07f582ccfabb3c) by [Unito](https://www.unito.io) --- src/components/TopMenuSection.vue | 2 ++ src/components/topbar/ActionBarButtons.vue | 29 ++++++++++++++++++ .../core/cloudFeedbackTopbarButton.ts | 23 ++++++++++++++ src/extensions/core/index.ts | 1 + src/locales/en/main.json | 4 ++- src/stores/actionBarButtonStore.ts | 18 +++++++++++ src/types/comfy.ts | 30 +++++++++++++++++++ 7 files changed, 106 insertions(+), 1 deletion(-) create mode 100644 src/components/topbar/ActionBarButtons.vue create mode 100644 src/extensions/core/cloudFeedbackTopbarButton.ts create mode 100644 src/stores/actionBarButtonStore.ts diff --git a/src/components/TopMenuSection.vue b/src/components/TopMenuSection.vue index 438bfaa95..d170305a4 100644 --- a/src/components/TopMenuSection.vue +++ b/src/components/TopMenuSection.vue @@ -7,6 +7,7 @@
+
+
+ +
+ + + diff --git a/src/extensions/core/cloudFeedbackTopbarButton.ts b/src/extensions/core/cloudFeedbackTopbarButton.ts new file mode 100644 index 000000000..144506d7e --- /dev/null +++ b/src/extensions/core/cloudFeedbackTopbarButton.ts @@ -0,0 +1,23 @@ +import { t } from '@/i18n' +import { useExtensionService } from '@/services/extensionService' +import type { ActionBarButton } from '@/types/comfy' + +// Zendesk feedback URL - update this with the actual URL +const ZENDESK_FEEDBACK_URL = + 'https://support.comfy.org/hc/en-us/requests/new?ticket_form_id=43066738713236' + +const buttons: ActionBarButton[] = [ + { + icon: 'icon-[lucide--message-circle-question-mark]', + label: t('actionbar.feedback'), + tooltip: t('actionbar.feedbackTooltip'), + onClick: () => { + window.open(ZENDESK_FEEDBACK_URL, '_blank', 'noopener,noreferrer') + } + } +] + +useExtensionService().registerExtension({ + name: 'Comfy.Cloud.FeedbackButton', + actionBarButtons: buttons +}) diff --git a/src/extensions/core/index.ts b/src/extensions/core/index.ts index a11a61abb..95802ff4e 100644 --- a/src/extensions/core/index.ts +++ b/src/extensions/core/index.ts @@ -29,6 +29,7 @@ if (isCloud) { await import('./cloudRemoteConfig') await import('./cloudBadges') await import('./cloudSessionCookie') + await import('./cloudFeedbackTopbarButton') if (window.__CONFIG__?.subscription_required) { await import('./cloudSubscription') diff --git a/src/locales/en/main.json b/src/locales/en/main.json index 15b310742..5ef78eace 100644 --- a/src/locales/en/main.json +++ b/src/locales/en/main.json @@ -2282,7 +2282,9 @@ } }, "actionbar": { - "dockToTop": "Dock to top" + "dockToTop": "Dock to top", + "feedback": "Feedback", + "feedbackTooltip": "Feedback" }, "desktopDialogs": { "": { diff --git a/src/stores/actionBarButtonStore.ts b/src/stores/actionBarButtonStore.ts new file mode 100644 index 000000000..cb2730e13 --- /dev/null +++ b/src/stores/actionBarButtonStore.ts @@ -0,0 +1,18 @@ +import { defineStore } from 'pinia' +import { computed } from 'vue' + +import type { ActionBarButton } from '@/types/comfy' + +import { useExtensionStore } from './extensionStore' + +export const useActionBarButtonStore = defineStore('actionBarButton', () => { + const extensionStore = useExtensionStore() + + const buttons = computed(() => + extensionStore.extensions.flatMap((e) => e.actionBarButtons ?? []) + ) + + return { + buttons + } +}) diff --git a/src/types/comfy.ts b/src/types/comfy.ts index db0760bbd..436e504ef 100644 --- a/src/types/comfy.ts +++ b/src/types/comfy.ts @@ -57,6 +57,32 @@ export interface TopbarBadge { tooltip?: string } +/* + * Action bar button definition: add buttons to the action bar + */ +export interface ActionBarButton { + /** + * Icon class to display (e.g., "icon-[lucide--message-circle-question-mark]") + */ + icon: string + /** + * Optional label text to display next to the icon + */ + label?: string + /** + * Optional tooltip text to show on hover + */ + tooltip?: string + /** + * Optional CSS classes to apply to the button + */ + class?: string + /** + * Click handler for the button + */ + onClick: () => void +} + export type MissingNodeType = | string // Primarily used by group nodes. @@ -102,6 +128,10 @@ export interface ComfyExtension { * Badges to add to the top bar */ topbarBadges?: TopbarBadge[] + /** + * Buttons to add to the action bar + */ + actionBarButtons?: ActionBarButton[] /** * Allows any initialisation, e.g. loading resources. Called after the canvas is created but before nodes are added * @param app The ComfyUI app instance