mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-04-29 02:32:18 +00:00
This reverts commit 94db2e90da.
This commit is contained in:
165
src/App.vue
165
src/App.vue
@@ -4,22 +4,183 @@
|
|||||||
v-if="isLoading"
|
v-if="isLoading"
|
||||||
class="absolute inset-0 flex justify-center items-center h-screen"
|
class="absolute inset-0 flex justify-center items-center h-screen"
|
||||||
/>
|
/>
|
||||||
<GlobalDialog />
|
|
||||||
<BlockUI full-screen :blocked="isLoading" />
|
<BlockUI full-screen :blocked="isLoading" />
|
||||||
|
<GlobalDialog />
|
||||||
|
<GlobalToast />
|
||||||
|
<UnloadWindowConfirmDialog />
|
||||||
|
<BrowserTabTitle />
|
||||||
|
<AppMenu />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import {
|
||||||
|
computed,
|
||||||
|
markRaw,
|
||||||
|
onMounted,
|
||||||
|
onUnmounted,
|
||||||
|
watch,
|
||||||
|
watchEffect
|
||||||
|
} from 'vue'
|
||||||
import config from '@/config'
|
import config from '@/config'
|
||||||
import { computed, onMounted, onBeforeUnmount } from 'vue'
|
import { app } from '@/scripts/app'
|
||||||
|
import { useSettingStore } from '@/stores/settingStore'
|
||||||
|
import { useI18n } from 'vue-i18n'
|
||||||
import { useWorkspaceStore } from '@/stores/workspaceStateStore'
|
import { useWorkspaceStore } from '@/stores/workspaceStateStore'
|
||||||
|
import { api } from '@/scripts/api'
|
||||||
|
import { StatusWsMessageStatus } from '@/types/apiTypes'
|
||||||
|
import { useQueuePendingTaskCountStore } from '@/stores/queueStore'
|
||||||
|
import type { ToastMessageOptions } from 'primevue/toast'
|
||||||
|
import { useToast } from 'primevue/usetoast'
|
||||||
|
import { i18n } from '@/i18n'
|
||||||
|
import { useExecutionStore } from '@/stores/executionStore'
|
||||||
|
import { useWorkflowBookmarkStore, useWorkflowStore } from '@/stores/workflowStore'
|
||||||
import BlockUI from 'primevue/blockui'
|
import BlockUI from 'primevue/blockui'
|
||||||
import ProgressSpinner from 'primevue/progressspinner'
|
import ProgressSpinner from 'primevue/progressspinner'
|
||||||
|
import QueueSidebarTab from '@/components/sidebar/tabs/QueueSidebarTab.vue'
|
||||||
|
import NodeLibrarySidebarTab from '@/components/sidebar/tabs/NodeLibrarySidebarTab.vue'
|
||||||
import GlobalDialog from '@/components/dialog/GlobalDialog.vue'
|
import GlobalDialog from '@/components/dialog/GlobalDialog.vue'
|
||||||
|
import GlobalToast from '@/components/toast/GlobalToast.vue'
|
||||||
|
import UnloadWindowConfirmDialog from '@/components/dialog/UnloadWindowConfirmDialog.vue'
|
||||||
|
import BrowserTabTitle from '@/components/BrowserTabTitle.vue'
|
||||||
|
import AppMenu from '@/components/appMenu/AppMenu.vue'
|
||||||
|
import WorkflowsSidebarTab from './components/sidebar/tabs/WorkflowsSidebarTab.vue'
|
||||||
|
import { setupAutoQueueHandler } from './services/autoQueueService'
|
||||||
|
|
||||||
const isLoading = computed<boolean>(() => useWorkspaceStore().spinner)
|
const isLoading = computed<boolean>(() => useWorkspaceStore().spinner)
|
||||||
|
|
||||||
|
const { t } = useI18n()
|
||||||
|
const toast = useToast()
|
||||||
|
const settingStore = useSettingStore()
|
||||||
|
const queuePendingTaskCountStore = useQueuePendingTaskCountStore()
|
||||||
|
const executionStore = useExecutionStore()
|
||||||
|
const workflowStore = useWorkflowStore()
|
||||||
|
const workflowBookmarkStore = useWorkflowBookmarkStore()
|
||||||
|
|
||||||
|
const theme = computed<string>(() => settingStore.get('Comfy.ColorPalette'))
|
||||||
|
|
||||||
|
watch(
|
||||||
|
theme,
|
||||||
|
(newTheme) => {
|
||||||
|
const DARK_THEME_CLASS = 'dark-theme'
|
||||||
|
const isDarkTheme = newTheme !== 'light'
|
||||||
|
if (isDarkTheme) {
|
||||||
|
document.body.classList.add(DARK_THEME_CLASS)
|
||||||
|
} else {
|
||||||
|
document.body.classList.remove(DARK_THEME_CLASS)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
)
|
||||||
|
|
||||||
|
setupAutoQueueHandler()
|
||||||
|
|
||||||
|
watchEffect(() => {
|
||||||
|
const fontSize = settingStore.get('Comfy.TextareaWidget.FontSize')
|
||||||
|
document.documentElement.style.setProperty(
|
||||||
|
'--comfy-textarea-font-size',
|
||||||
|
`${fontSize}px`
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
watchEffect(() => {
|
||||||
|
const padding = settingStore.get('Comfy.TreeExplorer.ItemPadding')
|
||||||
|
document.documentElement.style.setProperty(
|
||||||
|
'--comfy-tree-explorer-item-padding',
|
||||||
|
`${padding}px`
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
watchEffect(() => {
|
||||||
|
const locale = settingStore.get('Comfy.Locale')
|
||||||
|
if (locale) {
|
||||||
|
i18n.global.locale.value = locale as 'en' | 'zh'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const init = () => {
|
||||||
|
settingStore.addSettings(app.ui.settings)
|
||||||
|
app.extensionManager = useWorkspaceStore()
|
||||||
|
app.extensionManager.registerSidebarTab({
|
||||||
|
id: 'queue',
|
||||||
|
icon: 'pi pi-history',
|
||||||
|
iconBadge: () => {
|
||||||
|
const value = useQueuePendingTaskCountStore().count.toString()
|
||||||
|
return value === '0' ? null : value
|
||||||
|
},
|
||||||
|
title: t('sideToolbar.queue'),
|
||||||
|
tooltip: t('sideToolbar.queue'),
|
||||||
|
component: markRaw(QueueSidebarTab),
|
||||||
|
type: 'vue'
|
||||||
|
})
|
||||||
|
app.extensionManager.registerSidebarTab({
|
||||||
|
id: 'node-library',
|
||||||
|
icon: 'pi pi-book',
|
||||||
|
title: t('sideToolbar.nodeLibrary'),
|
||||||
|
tooltip: t('sideToolbar.nodeLibrary'),
|
||||||
|
component: markRaw(NodeLibrarySidebarTab),
|
||||||
|
type: 'vue'
|
||||||
|
})
|
||||||
|
app.extensionManager.registerSidebarTab({
|
||||||
|
id: 'workflows',
|
||||||
|
icon: 'pi pi-folder-open',
|
||||||
|
iconBadge: () => {
|
||||||
|
const value = useWorkflowStore().openWorkflows.length.toString()
|
||||||
|
return value === '0' ? null : value
|
||||||
|
},
|
||||||
|
title: t('sideToolbar.workflows'),
|
||||||
|
tooltip: t('sideToolbar.workflows'),
|
||||||
|
component: markRaw(WorkflowsSidebarTab),
|
||||||
|
type: 'vue'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const onStatus = (e: CustomEvent<StatusWsMessageStatus>) => {
|
||||||
|
queuePendingTaskCountStore.update(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
const reconnectingMessage: ToastMessageOptions = {
|
||||||
|
severity: 'error',
|
||||||
|
summary: t('reconnecting')
|
||||||
|
}
|
||||||
|
|
||||||
|
const onReconnecting = () => {
|
||||||
|
toast.remove(reconnectingMessage)
|
||||||
|
toast.add(reconnectingMessage)
|
||||||
|
}
|
||||||
|
|
||||||
|
const onReconnected = () => {
|
||||||
|
toast.remove(reconnectingMessage)
|
||||||
|
toast.add({
|
||||||
|
severity: 'success',
|
||||||
|
summary: t('reconnected'),
|
||||||
|
life: 2000
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
app.workflowManager.executionStore = executionStore
|
||||||
|
app.workflowManager.workflowStore = workflowStore
|
||||||
|
app.workflowManager.workflowBookmarkStore = workflowBookmarkStore
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
window['__COMFYUI_FRONTEND_VERSION__'] = config.app_version
|
window['__COMFYUI_FRONTEND_VERSION__'] = config.app_version
|
||||||
console.log('ComfyUI Front-end version:', config.app_version)
|
console.log('ComfyUI Front-end version:', config.app_version)
|
||||||
|
|
||||||
|
api.addEventListener('status', onStatus)
|
||||||
|
api.addEventListener('reconnecting', onReconnecting)
|
||||||
|
api.addEventListener('reconnected', onReconnected)
|
||||||
|
executionStore.bindExecutionEvents()
|
||||||
|
|
||||||
|
try {
|
||||||
|
init()
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Failed to init ComfyUI frontend', e)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
api.removeEventListener('status', onStatus)
|
||||||
|
api.removeEventListener('reconnecting', onReconnecting)
|
||||||
|
api.removeEventListener('reconnected', onReconnected)
|
||||||
|
executionStore.unbindExecutionEvents()
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,20 +1,16 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<!--
|
<!-- This component does not render anything visible. It is used to confirm
|
||||||
UnloadWindowConfirmDialog: This component does not render
|
the user wants to close the window, and if they do, it will call the
|
||||||
anything visible. It is used to confirm the user wants to
|
beforeunload event. -->
|
||||||
close the window, and if they do, it will call the
|
|
||||||
beforeunload event.
|
|
||||||
-->
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useSettingStore } from '@/stores/settingStore'
|
import { useSettingStore } from '@/stores/settingStore'
|
||||||
import { onMounted, onBeforeUnmount } from 'vue'
|
import { onMounted, onUnmounted } from 'vue'
|
||||||
|
|
||||||
const settingStore = useSettingStore()
|
const settingStore = useSettingStore()
|
||||||
|
|
||||||
const handleBeforeUnload = (event: BeforeUnloadEvent) => {
|
const handleBeforeUnload = (event: BeforeUnloadEvent) => {
|
||||||
if (settingStore.get('Comfy.Window.UnloadConfirmation')) {
|
if (settingStore.get('Comfy.Window.UnloadConfirmation')) {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
@@ -27,7 +23,7 @@ onMounted(() => {
|
|||||||
window.addEventListener('beforeunload', handleBeforeUnload)
|
window.addEventListener('beforeunload', handleBeforeUnload)
|
||||||
})
|
})
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
onUnmounted(() => {
|
||||||
window.removeEventListener('beforeunload', handleBeforeUnload)
|
window.removeEventListener('beforeunload', handleBeforeUnload)
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,156 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<GraphCanvas />
|
<GraphCanvas />
|
||||||
<GlobalToast />
|
|
||||||
<UnloadWindowConfirmDialog />
|
|
||||||
<BrowserTabTitle />
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import GraphCanvas from '@/components/graph/GraphCanvas.vue'
|
import GraphCanvas from '@/components/graph/GraphCanvas.vue'
|
||||||
|
|
||||||
import {
|
|
||||||
computed,
|
|
||||||
markRaw,
|
|
||||||
onMounted,
|
|
||||||
onBeforeUnmount,
|
|
||||||
watch,
|
|
||||||
watchEffect
|
|
||||||
} from 'vue'
|
|
||||||
import { app } from '@/scripts/app'
|
|
||||||
import { useSettingStore } from '@/stores/settingStore'
|
|
||||||
import { useI18n } from 'vue-i18n'
|
|
||||||
import { useWorkspaceStore } from '@/stores/workspaceStateStore'
|
|
||||||
import { api } from '@/scripts/api'
|
|
||||||
import { StatusWsMessageStatus } from '@/types/apiTypes'
|
|
||||||
import { useQueuePendingTaskCountStore } from '@/stores/queueStore'
|
|
||||||
import type { ToastMessageOptions } from 'primevue/toast'
|
|
||||||
import { useToast } from 'primevue/usetoast'
|
|
||||||
import { i18n } from '@/i18n'
|
|
||||||
import { useExecutionStore } from '@/stores/executionStore'
|
|
||||||
import { useWorkflowStore } from '@/stores/workflowStore'
|
|
||||||
import QueueSidebarTab from '@/components/sidebar/tabs/QueueSidebarTab.vue'
|
|
||||||
import NodeLibrarySidebarTab from '@/components/sidebar/tabs/NodeLibrarySidebarTab.vue'
|
|
||||||
import GlobalToast from '@/components/toast/GlobalToast.vue'
|
|
||||||
import UnloadWindowConfirmDialog from '@/components/dialog/UnloadWindowConfirmDialog.vue'
|
|
||||||
import BrowserTabTitle from '@/components/BrowserTabTitle.vue'
|
|
||||||
|
|
||||||
const { t } = useI18n()
|
|
||||||
const toast = useToast()
|
|
||||||
const settingStore = useSettingStore()
|
|
||||||
const executionStore = useExecutionStore()
|
|
||||||
|
|
||||||
const theme = computed<string>(() => settingStore.get('Comfy.ColorPalette'))
|
|
||||||
|
|
||||||
watch(
|
|
||||||
theme,
|
|
||||||
(newTheme) => {
|
|
||||||
const DARK_THEME_CLASS = 'dark-theme'
|
|
||||||
const isDarkTheme = newTheme !== 'light'
|
|
||||||
if (isDarkTheme) {
|
|
||||||
document.body.classList.add(DARK_THEME_CLASS)
|
|
||||||
} else {
|
|
||||||
document.body.classList.remove(DARK_THEME_CLASS)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{ immediate: true }
|
|
||||||
)
|
|
||||||
|
|
||||||
watchEffect(() => {
|
|
||||||
const fontSize = settingStore.get('Comfy.TextareaWidget.FontSize')
|
|
||||||
document.documentElement.style.setProperty(
|
|
||||||
'--comfy-textarea-font-size',
|
|
||||||
`${fontSize}px`
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
watchEffect(() => {
|
|
||||||
const padding = settingStore.get('Comfy.TreeExplorer.ItemPadding')
|
|
||||||
document.documentElement.style.setProperty(
|
|
||||||
'--comfy-tree-explorer-item-padding',
|
|
||||||
`${padding}px`
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
watchEffect(() => {
|
|
||||||
const locale = settingStore.get('Comfy.Locale')
|
|
||||||
if (locale) {
|
|
||||||
i18n.global.locale.value = locale as 'en' | 'zh'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const init = () => {
|
|
||||||
settingStore.addSettings(app.ui.settings)
|
|
||||||
app.extensionManager = useWorkspaceStore()
|
|
||||||
app.extensionManager.registerSidebarTab({
|
|
||||||
id: 'queue',
|
|
||||||
icon: 'pi pi-history',
|
|
||||||
iconBadge: () => {
|
|
||||||
const value = useQueuePendingTaskCountStore().count.toString()
|
|
||||||
return value === '0' ? null : value
|
|
||||||
},
|
|
||||||
title: t('sideToolbar.queue'),
|
|
||||||
tooltip: t('sideToolbar.queue'),
|
|
||||||
component: markRaw(QueueSidebarTab),
|
|
||||||
type: 'vue'
|
|
||||||
})
|
|
||||||
app.extensionManager.registerSidebarTab({
|
|
||||||
id: 'node-library',
|
|
||||||
icon: 'pi pi-book',
|
|
||||||
title: t('sideToolbar.nodeLibrary'),
|
|
||||||
tooltip: t('sideToolbar.nodeLibrary'),
|
|
||||||
component: markRaw(NodeLibrarySidebarTab),
|
|
||||||
type: 'vue'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const queuePendingTaskCountStore = useQueuePendingTaskCountStore()
|
|
||||||
const onStatus = (e: CustomEvent<StatusWsMessageStatus>) => {
|
|
||||||
queuePendingTaskCountStore.update(e)
|
|
||||||
}
|
|
||||||
|
|
||||||
const reconnectingMessage: ToastMessageOptions = {
|
|
||||||
severity: 'error',
|
|
||||||
summary: t('reconnecting')
|
|
||||||
}
|
|
||||||
|
|
||||||
const onReconnecting = () => {
|
|
||||||
toast.remove(reconnectingMessage)
|
|
||||||
toast.add(reconnectingMessage)
|
|
||||||
}
|
|
||||||
|
|
||||||
const onReconnected = () => {
|
|
||||||
toast.remove(reconnectingMessage)
|
|
||||||
toast.add({
|
|
||||||
severity: 'success',
|
|
||||||
summary: t('reconnected'),
|
|
||||||
life: 2000
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const workflowStore = useWorkflowStore()
|
|
||||||
app.workflowManager.executionStore = executionStore
|
|
||||||
watchEffect(() => {
|
|
||||||
app.menu.workflows.buttonProgress.style.width = `${executionStore.executionProgress}%`
|
|
||||||
})
|
|
||||||
app.workflowManager.workflowStore = workflowStore
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
api.addEventListener('status', onStatus)
|
|
||||||
api.addEventListener('reconnecting', onReconnecting)
|
|
||||||
api.addEventListener('reconnected', onReconnected)
|
|
||||||
executionStore.bindExecutionEvents()
|
|
||||||
|
|
||||||
try {
|
|
||||||
init()
|
|
||||||
} catch (e) {
|
|
||||||
console.error('Failed to init ComfyUI frontend', e)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
|
||||||
api.removeEventListener('status', onStatus)
|
|
||||||
api.removeEventListener('reconnecting', onReconnecting)
|
|
||||||
api.removeEventListener('reconnected', onReconnected)
|
|
||||||
executionStore.unbindExecutionEvents()
|
|
||||||
})
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Reference in New Issue
Block a user