Compare commits

...

3 Commits

Author SHA1 Message Date
bymyself
b198aaaca2 centralize render condition in TopMenuBar 2025-03-06 17:33:16 -07:00
bymyself
7003a9e98b refactor 2025-03-06 02:26:14 -07:00
bymyself
35fb6378d1 add webview store 2025-03-06 02:12:36 -07:00
7 changed files with 168 additions and 18 deletions

View File

@@ -3,7 +3,12 @@
<!-- If load immediately, the top-level splitter stateKey won't be correctly
synced with the stateStorage (localStorage). -->
<LiteGraphCanvasSplitterOverlay
v-if="comfyAppReady && betaMenuEnabled && !workspaceStore.focusMode"
v-if="
comfyAppReady &&
betaMenuEnabled &&
!workspaceStore.focusMode &&
!webviewStore.hasActiveWebview
"
>
<template #side-bar-panel>
<SideToolbar />
@@ -69,6 +74,7 @@ import { useCommandStore } from '@/stores/commandStore'
import { useCanvasStore } from '@/stores/graphStore'
import { useNodeDefStore } from '@/stores/nodeDefStore'
import { useSettingStore } from '@/stores/settingStore'
import { useWebviewStore } from '@/stores/webviewStore'
import { useColorPaletteStore } from '@/stores/workspace/colorPaletteStore'
import { useWorkspaceStore } from '@/stores/workspaceStore'
@@ -78,6 +84,7 @@ const settingStore = useSettingStore()
const nodeDefStore = useNodeDefStore()
const workspaceStore = useWorkspaceStore()
const canvasStore = useCanvasStore()
const webviewStore = useWebviewStore()
const betaMenuEnabled = computed(
() => settingStore.get('Comfy.UseNewMenu') !== 'Disabled'
)

View File

@@ -1,5 +1,6 @@
<template>
<ButtonGroup
v-if="!webviewStore.hasActiveWebview"
class="p-buttongroup-vertical absolute bottom-[10px] right-[10px] z-[1000]"
>
<Button
@@ -69,11 +70,13 @@ import { useI18n } from 'vue-i18n'
import { useCommandStore } from '@/stores/commandStore'
import { useCanvasStore } from '@/stores/graphStore'
import { useSettingStore } from '@/stores/settingStore'
import { useWebviewStore } from '@/stores/webviewStore'
const { t } = useI18n()
const commandStore = useCommandStore()
const canvasStore = useCanvasStore()
const settingStore = useSettingStore()
const webviewStore = useWebviewStore()
const linkHidden = computed(
() => settingStore.get('Comfy.LinkRenderMode') === LiteGraph.HIDDEN_LINK

View File

@@ -10,23 +10,25 @@
<div class="flex-grow min-w-0 app-drag h-full">
<WorkflowTabs v-if="workflowTabsPosition === 'Topbar'" />
</div>
<div class="comfyui-menu-right flex-shrink-0" ref="menuRight"></div>
<Actionbar />
<BottomPanelToggleButton class="flex-shrink-0" />
<Button
class="flex-shrink-0"
icon="pi pi-bars"
severity="secondary"
text
v-tooltip="{ value: $t('menu.hideMenu'), showDelay: 300 }"
:aria-label="$t('menu.hideMenu')"
@click="workspaceState.focusMode = true"
@contextmenu="showNativeSystemMenu"
/>
<div
v-show="menuSetting !== 'Bottom'"
class="window-actions-spacer flex-shrink-0"
/>
<template v-if="!webviewStore.hasActiveWebview">
<div class="comfyui-menu-right flex-shrink-0" ref="menuRight"></div>
<Actionbar />
<BottomPanelToggleButton class="flex-shrink-0" />
<Button
class="flex-shrink-0"
icon="pi pi-bars"
severity="secondary"
text
v-tooltip="{ value: $t('menu.hideMenu'), showDelay: 300 }"
:aria-label="$t('menu.hideMenu')"
@click="workspaceState.focusMode = true"
@contextmenu="showNativeSystemMenu"
/>
<div
v-show="menuSetting !== 'Bottom'"
class="window-actions-spacer flex-shrink-0"
/>
</template>
</div>
<!-- Virtual top menu for native window (drag handle) -->
@@ -47,6 +49,7 @@ import CommandMenubar from '@/components/topbar/CommandMenubar.vue'
import WorkflowTabs from '@/components/topbar/WorkflowTabs.vue'
import { app } from '@/scripts/app'
import { useSettingStore } from '@/stores/settingStore'
import { useWebviewStore } from '@/stores/webviewStore'
import { useWorkspaceStore } from '@/stores/workspaceStore'
import {
electronAPI,
@@ -57,6 +60,7 @@ import {
const workspaceState = useWorkspaceStore()
const settingStore = useSettingStore()
const webviewStore = useWebviewStore()
const workflowTabsPosition = computed(() =>
settingStore.get('Comfy.Workflow.WorkflowTabsPosition')
)

View File

@@ -19,6 +19,7 @@
>
<template #option="{ option }">
<WorkflowTab
@click="() => webviewStore.hideActiveWebview()"
@contextmenu="showContextMenu($event, option)"
@click.middle="onCloseWorkflow(option)"
:workflow-option="option"
@@ -50,6 +51,7 @@ import { useI18n } from 'vue-i18n'
import WorkflowTab from '@/components/topbar/WorkflowTab.vue'
import { useWorkflowService } from '@/services/workflowService'
import { useCommandStore } from '@/stores/commandStore'
import { useWebviewStore } from '@/stores/webviewStore'
import { ComfyWorkflow, useWorkflowBookmarkStore } from '@/stores/workflowStore'
import { useWorkflowStore } from '@/stores/workflowStore'
import { useWorkspaceStore } from '@/stores/workspaceStore'
@@ -68,6 +70,7 @@ const workspaceStore = useWorkspaceStore()
const workflowStore = useWorkflowStore()
const workflowService = useWorkflowService()
const workflowBookmarkStore = useWorkflowBookmarkStore()
const webviewStore = useWebviewStore()
const rightClickedTab = ref<WorkflowOption>(null)
const menu = ref()

View File

@@ -0,0 +1,29 @@
<template>
<div class="w-full h-full relative pointer-events-auto">
<KeepAlive>
<component
v-if="
webviewStore.hasActiveWebview && webviewStore.activeWebview.keepAlive
"
:is="webviewStore.activeWebview.component"
:key="webviewStore.activeWebviewId"
v-bind="webviewStore.activeWebview.props || {}"
/>
</KeepAlive>
<component
v-if="
webviewStore.hasActiveWebview && !webviewStore.activeWebview.keepAlive
"
:is="webviewStore.activeWebview.component"
:key="webviewStore.activeWebviewId"
v-bind="webviewStore.activeWebview.props || {}"
/>
</div>
</template>
<script setup lang="ts">
import { useWebviewStore } from '@/stores/webviewStore'
const webviewStore = useWebviewStore()
</script>

View File

@@ -0,0 +1,96 @@
import { merge } from 'lodash'
import { defineStore } from 'pinia'
import { Component, computed, markRaw, ref, shallowRef } from 'vue'
export interface Webview {
id: string
component: Component
props?: Record<string, any>
keepAlive?: boolean
}
/**
* Store used to manage webview canvases
*/
export const useWebviewStore = defineStore('webview', () => {
const registeredWebviews = shallowRef<Record<string, Webview>>({})
const activeWebviewId = ref<string | null>(null)
const activeWebview = computed(() =>
activeWebviewId.value
? registeredWebviews.value[activeWebviewId.value]
: null
)
const hasActiveWebview = computed(() => activeWebviewId.value !== null)
/**
* Register a new webview
* @param webview The webview to register
*/
const registerWebview = (webview: Webview) => {
registeredWebviews.value[webview.id] = {
...webview,
component: markRaw(webview.component)
}
}
/**
* Unregister a webview
* @param id The ID of the webview to unregister
*/
const unregisterWebview = (id: string) => {
const webview = registeredWebviews.value[id]
if (!webview) return
if (activeWebviewId.value === id) {
activeWebviewId.value = null
}
delete registeredWebviews.value[id]
}
/**
* Show a webview and make it active
* @param id The ID of the webview to show
* @param props Optional props to pass to the webview component
*/
const showWebview = (id: string, props?: Record<string, any>) => {
const webview = registeredWebviews.value[id]
if (!webview) return
if (props) {
webview.props = merge(webview.props, props)
}
activeWebviewId.value = id
}
/**
* Hide a webview by ID
* @param id The ID of the webview to hide
*/
const hideWebview = (id: string) => {
if (activeWebviewId.value === id) {
activeWebviewId.value = null
}
}
/**
* Hide the active webview
*/
const hideActiveWebview = () => {
activeWebviewId.value = null
}
return {
activeWebviewId,
activeWebview,
hasActiveWebview,
registerWebview,
unregisterWebview,
showWebview,
hideWebview,
hideActiveWebview
}
})

View File

@@ -10,6 +10,12 @@
<div class="comfyui-body-right" id="comfyui-body-right" />
<div class="graph-canvas-container" id="graph-canvas-container">
<GraphCanvas @ready="onGraphReady" />
<div
class="absolute inset-0 isolation z-50 pointer-events-none bg-[var(--p-dialog-background)]"
:class="{ hidden: !webviewStore.hasActiveWebview }"
>
<WebviewContainer />
</div>
</div>
</div>
@@ -52,6 +58,7 @@ import {
} from '@/stores/queueStore'
import { useServerConfigStore } from '@/stores/serverConfigStore'
import { useSettingStore } from '@/stores/settingStore'
import { useWebviewStore } from '@/stores/webviewStore'
import { useBottomPanelStore } from '@/stores/workspace/bottomPanelStore'
import { useColorPaletteStore } from '@/stores/workspace/colorPaletteStore'
import { useSidebarTabStore } from '@/stores/workspace/sidebarTabStore'
@@ -66,6 +73,7 @@ const settingStore = useSettingStore()
const executionStore = useExecutionStore()
const colorPaletteStore = useColorPaletteStore()
const queueStore = useQueueStore()
const webviewStore = useWebviewStore()
watch(
() => colorPaletteStore.completedActivePalette,