diff --git a/browser_tests/ComfyPage.ts b/browser_tests/ComfyPage.ts index 943abdf8e..c4cb513fd 100644 --- a/browser_tests/ComfyPage.ts +++ b/browser_tests/ComfyPage.ts @@ -212,6 +212,16 @@ class WorkflowsSidebarTab extends SidebarTab { } } +class Topbar { + constructor(public readonly page: Page) {} + + async getTabNames(): Promise { + return await this.page + .locator('.workflow-tabs .workflow-label') + .allInnerTexts() + } +} + class ComfyMenu { public readonly sideToolbar: Locator public readonly themeToggleButton: Locator @@ -248,6 +258,10 @@ class ComfyMenu { return new WorkflowsSidebarTab(this.page) } + get topbar() { + return new Topbar(this.page) + } + async toggleTheme() { await this.themeToggleButton.click() await this.page.evaluate(() => { diff --git a/browser_tests/menu.spec.ts b/browser_tests/menu.spec.ts index e1f48422d..6020d8aef 100644 --- a/browser_tests/menu.spec.ts +++ b/browser_tests/menu.spec.ts @@ -381,6 +381,11 @@ test.describe('Menu', () => { test.describe('Workflows sidebar', () => { test.beforeEach(async ({ comfyPage }) => { + await comfyPage.setSetting( + 'Comfy.Workflow.WorkflowTabsPosition', + 'Sidebar' + ) + // Open the sidebar const tab = comfyPage.menu.workflowsTab await tab.open() @@ -434,6 +439,21 @@ test.describe('Menu', () => { }) }) + test.describe('Workflows topbar tabs', () => { + test.beforeEach(async ({ comfyPage }) => { + await comfyPage.setSetting( + 'Comfy.Workflow.WorkflowTabsPosition', + 'Topbar' + ) + }) + + test('Can show opened workflows', async ({ comfyPage }) => { + expect(await comfyPage.menu.topbar.getTabNames()).toEqual([ + 'Unsaved Workflow' + ]) + }) + }) + test('Can change canvas zoom speed setting', async ({ comfyPage }) => { const [defaultSpeed, maxSpeed] = [1.1, 2.5] expect(await comfyPage.getSetting('Comfy.Graph.ZoomSpeed')).toBe( diff --git a/src/components/sidebar/tabs/WorkflowsSidebarTab.vue b/src/components/sidebar/tabs/WorkflowsSidebarTab.vue index aa411735c..efffee1a2 100644 --- a/src/components/sidebar/tabs/WorkflowsSidebarTab.vue +++ b/src/components/sidebar/tabs/WorkflowsSidebarTab.vue @@ -38,7 +38,10 @@ :placeholder="$t('searchWorkflows') + '...'" />
-
+
+ settingStore.get('Comfy.Workflow.WorkflowTabsPosition') +) const searchQuery = ref('') const isSearching = computed(() => searchQuery.value.length > 0) diff --git a/src/components/topbar/TopMenubar.vue b/src/components/topbar/TopMenubar.vue index a3206e3ec..5ec206922 100644 --- a/src/components/topbar/TopMenubar.vue +++ b/src/components/topbar/TopMenubar.vue @@ -9,17 +9,24 @@ rootList: 'gap-0' }" /> + +
+ + diff --git a/src/stores/coreSettings.ts b/src/stores/coreSettings.ts index 4f27c0aca..da0fa30d9 100644 --- a/src/stores/coreSettings.ts +++ b/src/stores/coreSettings.ts @@ -380,5 +380,12 @@ export const CORE_SETTINGS: SettingParams[] = [ experimental: true, type: 'combo', options: ['Disabled', 'Floating'] + }, + { + id: 'Comfy.Workflow.WorkflowTabsPosition', + name: 'Opened workflows position', + type: 'combo', + options: ['Sidebar', 'Topbar'], + defaultValue: 'Sidebar' } ] diff --git a/src/types/apiTypes.ts b/src/types/apiTypes.ts index aa064c42a..0cc3eaf64 100644 --- a/src/types/apiTypes.ts +++ b/src/types/apiTypes.ts @@ -500,6 +500,7 @@ const zSettings = z.record(z.any()).and( 'Comfy.Queue.ImageFit': z.enum(['contain', 'cover']), 'Comfy.Workflow.ModelDownload.AllowedSources': z.array(z.string()), 'Comfy.Workflow.ModelDownload.AllowedSuffixes': z.array(z.string()), + 'Comfy.Workflow.WorkflowTabsPosition': z.enum(['Sidebar', 'Topbar']), 'Comfy.Node.DoubleClickTitleToEdit': z.boolean(), 'Comfy.Window.UnloadConfirmation': z.boolean(), 'Comfy.NodeBadge.NodeSourceBadgeMode': zNodeBadgeMode, diff --git a/src/views/GraphView.vue b/src/views/GraphView.vue index e6a22b0de..4ce9f48d2 100644 --- a/src/views/GraphView.vue +++ b/src/views/GraphView.vue @@ -135,6 +135,11 @@ const init = () => { id: 'workflows', icon: 'pi pi-folder-open', iconBadge: () => { + if ( + settingStore.get('Comfy.Workflow.WorkflowTabsPosition') !== 'Sidebar' + ) { + return null + } const value = useWorkflowStore().openWorkflows.length.toString() return value === '0' ? null : value },