mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-26 17:54:14 +00:00
Fix extension register tab with API (#229)
* Get rid of extension manager impl * nit * Test register tab
This commit is contained in:
@@ -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')
|
||||
}
|
||||
|
||||
|
||||
@@ -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 = '<div>Custom search tab</div>'
|
||||
}
|
||||
})
|
||||
})
|
||||
await comfyPage.nextFrame()
|
||||
|
||||
const newChildrenCount = await comfyPage.menu.sideToolBar.evaluate(
|
||||
(el) => el.children.length
|
||||
)
|
||||
expect(newChildrenCount).toBe(initialChildrenCount + 1)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -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<boolean>(
|
||||
@@ -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',
|
||||
|
||||
@@ -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<SidebarTabExtension | null>(() => {
|
||||
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(() => {
|
||||
|
||||
@@ -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)
|
||||
])
|
||||
}
|
||||
}
|
||||
@@ -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]
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user