From ee6eed1c1c3a38424779217bcb8f6f7c68c77f94 Mon Sep 17 00:00:00 2001 From: Chenlei Hu Date: Fri, 26 Jul 2024 10:29:20 -0400 Subject: [PATCH] Fix extension register tab with API (#229) * Get rid of extension manager impl * nit * Test register tab --- browser_tests/ComfyPage.ts | 2 ++ browser_tests/menu.spec.ts | 25 +++++++++++++++ src/App.vue | 5 ++- src/components/sidebar/SideToolBar.vue | 11 +++---- src/scripts/extensionManager.ts | 43 -------------------------- src/stores/workspaceStateStore.ts | 31 +++++++++++-------- 6 files changed, 52 insertions(+), 65 deletions(-) delete mode 100644 src/scripts/extensionManager.ts diff --git a/browser_tests/ComfyPage.ts b/browser_tests/ComfyPage.ts index 673319003..593aef8e5 100644 --- a/browser_tests/ComfyPage.ts +++ b/browser_tests/ComfyPage.ts @@ -38,9 +38,11 @@ class ComfyNodeSearchBox { } class ComfyMenu { + public readonly sideToolBar: Locator public readonly themeToggleButton: Locator constructor(public readonly page: Page) { + this.sideToolBar = page.locator('.side-tool-bar-container') this.themeToggleButton = page.locator('.comfy-vue-theme-toggle') } diff --git a/browser_tests/menu.spec.ts b/browser_tests/menu.spec.ts index 1c74a8e98..369cc27c4 100644 --- a/browser_tests/menu.spec.ts +++ b/browser_tests/menu.spec.ts @@ -42,4 +42,29 @@ test.describe('Menu', () => { expect(await comfyPage.menu.getThemeId()).toBe('dark') }) + + test('Can register sidebar tab', async ({ comfyPage }) => { + const initialChildrenCount = await comfyPage.menu.sideToolBar.evaluate( + (el) => el.children.length + ) + + await comfyPage.page.evaluate(async () => { + window['app'].extensionManager.registerSidebarTab({ + id: 'search', + icon: 'pi pi-search', + title: 'search', + tooltip: 'search', + type: 'custom', + render: (el) => { + el.innerHTML = '
Custom search tab
' + } + }) + }) + await comfyPage.nextFrame() + + const newChildrenCount = await comfyPage.menu.sideToolBar.evaluate( + (el) => el.children.length + ) + expect(newChildrenCount).toBe(initialChildrenCount + 1) + }) }) diff --git a/src/App.vue b/src/App.vue index 3ede732a2..691dbdfc1 100644 --- a/src/App.vue +++ b/src/App.vue @@ -21,8 +21,8 @@ import QueueSideBarTab from '@/components/sidebar/tabs/QueueSideBarTab.vue' import ProgressSpinner from 'primevue/progressspinner' import { app } from './scripts/app' import { useSettingStore } from './stores/settingStore' -import { ExtensionManagerImpl } from './scripts/extensionManager' import { useI18n } from 'vue-i18n' +import { useWorkspaceStore } from './stores/workspaceStateStore' const isLoading = ref(true) const nodeSearchEnabled = computed( @@ -52,8 +52,7 @@ const { t } = useI18n() const init = () => { useSettingStore().addSettings(app.ui.settings) app.vueAppReady = true - // lazy init as extension manager needs to access pinia store. - app.extensionManager = new ExtensionManagerImpl() + app.extensionManager = useWorkspaceStore() app.extensionManager.registerSidebarTab({ id: 'queue', icon: 'pi pi-history', diff --git a/src/components/sidebar/SideToolBar.vue b/src/components/sidebar/SideToolBar.vue index a338d8491..caaebda82 100644 --- a/src/components/sidebar/SideToolBar.vue +++ b/src/components/sidebar/SideToolBar.vue @@ -39,25 +39,24 @@ import SideBarIcon from './SideBarIcon.vue' import SideBarThemeToggleIcon from './SideBarThemeToggleIcon.vue' import SideBarSettingsToggleIcon from './SideBarSettingsToggleIcon.vue' import { computed, onBeforeUnmount } from 'vue' -import { app } from '@/scripts/app' import { useWorkspaceStore } from '@/stores/workspaceStateStore' import { CustomSidebarTabExtension, SidebarTabExtension } from '@/types/extensionTypes' -const workspaceStateStore = useWorkspaceStore() -const tabs = computed(() => app.extensionManager.getSidebarTabs()) +const workspaceStore = useWorkspaceStore() +const tabs = computed(() => workspaceStore.getSidebarTabs()) const selectedTab = computed(() => { - const tabId = workspaceStateStore.activeSidebarTab + const tabId = workspaceStore.activeSidebarTab return tabs.value.find((tab) => tab.id === tabId) || null }) const mountCustomTab = (tab: CustomSidebarTabExtension, el: HTMLElement) => { tab.render(el) } const onTabClick = (item: SidebarTabExtension) => { - workspaceStateStore.updateActiveSidebarTab( - workspaceStateStore.activeSidebarTab === item.id ? null : item.id + workspaceStore.updateActiveSidebarTab( + workspaceStore.activeSidebarTab === item.id ? null : item.id ) } onBeforeUnmount(() => { diff --git a/src/scripts/extensionManager.ts b/src/scripts/extensionManager.ts deleted file mode 100644 index d64e3ca2b..000000000 --- a/src/scripts/extensionManager.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { useWorkspaceStore } from '@/stores/workspaceStateStore' -import { ExtensionManager, SidebarTabExtension } from '@/types/extensionTypes' - -export class ExtensionManagerImpl implements ExtensionManager { - private sidebarTabs: SidebarTabExtension[] = [] - private workspaceStore = useWorkspaceStore() - - registerSidebarTab(tab: SidebarTabExtension) { - this.sidebarTabs.push(tab) - this.updateSidebarOrder() - } - - unregisterSidebarTab(id: string) { - const index = this.sidebarTabs.findIndex((tab) => tab.id === id) - if (index !== -1) { - const tab = this.sidebarTabs[index] - if (tab.type === 'custom' && tab.destroy) { - tab.destroy() - } - this.sidebarTabs.splice(index, 1) - this.updateSidebarOrder() - } - } - - getSidebarTabs() { - return this.sidebarTabs.sort((a, b) => { - const orderA = this.workspaceStore.sidebarTabsOrder.indexOf(a.id) - const orderB = this.workspaceStore.sidebarTabsOrder.indexOf(b.id) - return orderA - orderB - }) - } - - private updateSidebarOrder() { - const currentOrder = this.workspaceStore.sidebarTabsOrder - const newTabs = this.sidebarTabs.filter( - (tab) => !currentOrder.includes(tab.id) - ) - this.workspaceStore.updateSidebarOrder([ - ...currentOrder, - ...newTabs.map((tab) => tab.id) - ]) - } -} diff --git a/src/stores/workspaceStateStore.ts b/src/stores/workspaceStateStore.ts index 8ff2a6af5..b8f75928b 100644 --- a/src/stores/workspaceStateStore.ts +++ b/src/stores/workspaceStateStore.ts @@ -1,32 +1,37 @@ +import { SidebarTabExtension } from '@/types/extensionTypes' import { defineStore } from 'pinia' interface WorkspaceState { activeSidebarTab: string | null - sidebarTabsOrder: string[] // Array of tab IDs in order + sidebarTabs: SidebarTabExtension[] } export const useWorkspaceStore = defineStore('workspace', { state: (): WorkspaceState => ({ activeSidebarTab: null, - sidebarTabsOrder: [] + sidebarTabs: [] }), actions: { updateActiveSidebarTab(tabId: string) { this.activeSidebarTab = tabId }, - updateSidebarOrder(newOrder: string[]) { - this.sidebarTabsOrder = newOrder + registerSidebarTab(tab: SidebarTabExtension) { + this.sidebarTabs = [...this.sidebarTabs, tab] }, - serialize() { - return JSON.stringify({ - activeSidebarTab: this.activeSidebarTab, - sidebarTabsOrder: this.sidebarTabsOrder - }) + unregisterSidebarTab(id: string) { + const index = this.sidebarTabs.findIndex((tab) => tab.id === id) + if (index !== -1) { + const tab = this.sidebarTabs[index] + if (tab.type === 'custom' && tab.destroy) { + tab.destroy() + } + const newSidebarTabs = [...this.sidebarTabs] + newSidebarTabs.splice(index, 1) + this.sidebarTabs = newSidebarTabs + } }, - deserialize(state: string) { - const parsedState = JSON.parse(state) - this.sidebarTabsOrder = parsedState.sidebarTabsOrder - this.activeSidebarTab = parsedState.activeSidebarTab + getSidebarTabs() { + return [...this.sidebarTabs] } } })