diff --git a/README.md b/README.md index 81031d77c..cf161ab5e 100644 --- a/README.md +++ b/README.md @@ -137,6 +137,37 @@ https://github.com/user-attachments/assets/c142c43f-2fe9-4030-8196-b3bfd4c6977d ### Node developers API + +
+ v1.3.1: Extension API to register custom topbar menu items + + Extensions can call the following API to register custom topbar menu items. + +```js + app.extensionManager.menu.registerTopbarCommands(["ext", "ext2"], [{id:"foo", label: "foo", function: () => alert(1)}]) +``` + +![image](https://github.com/user-attachments/assets/ae7b082f-7ce9-4549-a446-4563567102fe) +
+ +
+ v1.2.27: Extension API to add toast messagei + + Extensions can call the following API to add toast messages. + +```js + app.extensionManager.toast.add({ + severity: 'info', + summary: 'Loaded!', + detail: 'Extension loaded!', + life: 3000 + }) +``` +Documentation of all supported options can be found here: + +![image](https://github.com/user-attachments/assets/de02cd7e-cd81-43d1-a0b0-bccef92ff487) +
+
v1.2.4: Extension API to register custom sidebar tab @@ -162,24 +193,6 @@ We will support custom icons later. ![image](https://github.com/user-attachments/assets/7bff028a-bf91-4cab-bf97-55c243b3f5e0)
-
- v1.2.27: Extension API to add toast message - - Extensions can call the following API to add toast messages. - -```js - app.extensionManager.toast.add({ - severity: 'info', - summary: 'Loaded!', - detail: 'Extension loaded!', - life: 3000 - }) -``` -Documentation of all supported options can be found here: - -![image](https://github.com/user-attachments/assets/de02cd7e-cd81-43d1-a0b0-bccef92ff487) -
- ## Road Map ### What has been done diff --git a/browser_tests/ComfyPage.ts b/browser_tests/ComfyPage.ts index 72f51aab6..93ce93550 100644 --- a/browser_tests/ComfyPage.ts +++ b/browser_tests/ComfyPage.ts @@ -229,6 +229,32 @@ class Topbar { .locator('.workflow-tabs .workflow-label') .allInnerTexts() } + + async triggerTopbarCommand(path: string[]) { + if (path.length < 2) { + throw new Error('Path is too short') + } + + const tabName = path[0] + const topLevelMenu = this.page.locator( + `.top-menubar .p-menubar-item:has-text("${tabName}")` + ) + await topLevelMenu.waitFor({ state: 'visible' }) + await topLevelMenu.click() + + for (let i = 1; i < path.length; i++) { + const commandName = path[i] + const menuItem = this.page.locator( + `.top-menubar .p-menubar-submenu .p-menubar-item:has-text("${commandName}")` + ) + await menuItem.waitFor({ state: 'visible' }) + await menuItem.hover() + + if (i === path.length - 1) { + await menuItem.click() + } + } + } } class ComfyMenu { diff --git a/browser_tests/extensionAPI.spec.ts b/browser_tests/extensionAPI.spec.ts new file mode 100644 index 000000000..8002bda53 --- /dev/null +++ b/browser_tests/extensionAPI.spec.ts @@ -0,0 +1,32 @@ +import { expect } from '@playwright/test' +import { comfyPageFixture as test } from './ComfyPage' + +test.describe('Topbar commands', () => { + test.beforeEach(async ({ comfyPage }) => { + await comfyPage.setSetting('Comfy.UseNewMenu', 'Floating') + }) + + test.afterEach(async ({ comfyPage }) => { + await comfyPage.setSetting('Comfy.UseNewMenu', 'Disabled') + }) + + test('Should allow registering topbar commands', async ({ comfyPage }) => { + await comfyPage.page.evaluate(() => { + window['app'].extensionManager.menu.registerTopbarCommands( + ['ext'], + [ + { + id: 'foo', + label: 'foo', + function: () => { + window['foo'] = true + } + } + ] + ) + }) + + await comfyPage.menu.topbar.triggerTopbarCommand(['ext', 'foo']) + expect(await comfyPage.page.evaluate(() => window['foo'])).toBe(true) + }) +}) diff --git a/src/components/appMenu/AppMenu.vue b/src/components/appMenu/AppMenu.vue index 035c617ea..8f78ec693 100644 --- a/src/components/appMenu/AppMenu.vue +++ b/src/components/appMenu/AppMenu.vue @@ -29,7 +29,7 @@ icon="pi pi-times" :severity="executingPrompt ? 'danger' : 'secondary'" :disabled="!executingPrompt" - @click="() => commandStore.getCommand('Comfy.Interrupt')()" + @click="() => commandStore.getCommandFunction('Comfy.Interrupt')()" >