mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-04-29 02:32:18 +00:00
Backward compatibility with extension injections on legacy menu bar (#970)
* Compatible to legacy top menu extensions * Rework css * nit
This commit is contained in:
@@ -1,16 +1,23 @@
|
|||||||
<template>
|
<template>
|
||||||
<teleport to=".comfyui-body-top">
|
<teleport to=".comfyui-body-top">
|
||||||
<div class="top-menubar comfyui-menu" v-if="betaMenuEnabled">
|
<div
|
||||||
|
class="top-menubar comfyui-menu flex items-center"
|
||||||
|
v-show="betaMenuEnabled"
|
||||||
|
>
|
||||||
<h1 class="comfyui-logo mx-2">ComfyUI</h1>
|
<h1 class="comfyui-logo mx-2">ComfyUI</h1>
|
||||||
<Menubar
|
<Menubar
|
||||||
:model="items"
|
:model="items"
|
||||||
class="border-none p-0 bg-transparent"
|
class="border-none p-0 bg-transparent"
|
||||||
:pt="{
|
:pt="{
|
||||||
rootList: 'gap-0'
|
rootList: 'gap-0 flex-nowrap'
|
||||||
}"
|
}"
|
||||||
/>
|
/>
|
||||||
<Divider layout="vertical" class="mx-2" />
|
<Divider layout="vertical" class="mx-2" />
|
||||||
<WorkflowTabs v-if="workflowTabsPosition === 'Topbar'" />
|
<WorkflowTabs
|
||||||
|
v-if="workflowTabsPosition === 'Topbar'"
|
||||||
|
class="flex-grow"
|
||||||
|
/>
|
||||||
|
<div class="comfyui-menu-right" ref="menuRight"></div>
|
||||||
</div>
|
</div>
|
||||||
</teleport>
|
</teleport>
|
||||||
</template>
|
</template>
|
||||||
@@ -20,8 +27,9 @@ import Menubar from 'primevue/menubar'
|
|||||||
import Divider from 'primevue/divider'
|
import Divider from 'primevue/divider'
|
||||||
import WorkflowTabs from '@/components/topbar/WorkflowTabs.vue'
|
import WorkflowTabs from '@/components/topbar/WorkflowTabs.vue'
|
||||||
import { useCoreMenuItemStore } from '@/stores/coreMenuItemStore'
|
import { useCoreMenuItemStore } from '@/stores/coreMenuItemStore'
|
||||||
import { computed } from 'vue'
|
import { computed, onMounted, ref } from 'vue'
|
||||||
import { useSettingStore } from '@/stores/settingStore'
|
import { useSettingStore } from '@/stores/settingStore'
|
||||||
|
import { app } from '@/scripts/app'
|
||||||
|
|
||||||
const settingStore = useSettingStore()
|
const settingStore = useSettingStore()
|
||||||
const workflowTabsPosition = computed(() =>
|
const workflowTabsPosition = computed(() =>
|
||||||
@@ -32,6 +40,14 @@ const betaMenuEnabled = computed(
|
|||||||
)
|
)
|
||||||
const coreMenuItemsStore = useCoreMenuItemStore()
|
const coreMenuItemsStore = useCoreMenuItemStore()
|
||||||
const items = coreMenuItemsStore.menuItems
|
const items = coreMenuItemsStore.menuItems
|
||||||
|
|
||||||
|
const menuRight = ref<HTMLDivElement | null>(null)
|
||||||
|
// Menu-right holds legacy topbar elements attached by custom scripts
|
||||||
|
onMounted(() => {
|
||||||
|
if (menuRight.value) {
|
||||||
|
menuRight.value.appendChild(app.menu.element)
|
||||||
|
}
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
@@ -41,13 +57,10 @@ const items = coreMenuItemsStore.menuItems
|
|||||||
color: var(--fg-color);
|
color: var(--fg-color);
|
||||||
font-family: Arial, Helvetica, sans-serif;
|
font-family: Arial, Helvetica, sans-serif;
|
||||||
font-size: 0.8em;
|
font-size: 0.8em;
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
z-index: 1000;
|
z-index: 1000;
|
||||||
order: 0;
|
order: 0;
|
||||||
grid-column: 1/-1;
|
grid-column: 1/-1;
|
||||||
overflow: auto;
|
|
||||||
max-height: 90vh;
|
max-height: 90vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,32 +1,31 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="workflow-tabs">
|
<SelectButton
|
||||||
<SelectButton
|
class="workflow-tabs bg-transparent flex flex-wrap"
|
||||||
class="select-button-group bg-transparent"
|
:class="props.class"
|
||||||
:modelValue="selectedWorkflow"
|
:modelValue="selectedWorkflow"
|
||||||
@update:modelValue="onWorkflowChange"
|
@update:modelValue="onWorkflowChange"
|
||||||
:options="options"
|
:options="options"
|
||||||
optionLabel="label"
|
optionLabel="label"
|
||||||
dataKey="value"
|
dataKey="value"
|
||||||
>
|
>
|
||||||
<template #option="{ option }">
|
<template #option="{ option }">
|
||||||
<span
|
<span
|
||||||
class="workflow-label text-sm max-w-[150px] truncate inline-block"
|
class="workflow-label text-sm max-w-[150px] truncate inline-block"
|
||||||
>{{ option.label }}</span
|
>{{ option.label }}</span
|
||||||
>
|
>
|
||||||
<div class="relative">
|
<div class="relative">
|
||||||
<span class="status-indicator" v-if="option.unsaved">•</span>
|
<span class="status-indicator" v-if="option.unsaved">•</span>
|
||||||
<Button
|
<Button
|
||||||
class="close-button p-0 w-auto"
|
class="close-button p-0 w-auto"
|
||||||
icon="pi pi-times"
|
icon="pi pi-times"
|
||||||
text
|
text
|
||||||
severity="secondary"
|
severity="secondary"
|
||||||
size="small"
|
size="small"
|
||||||
@click.stop="onCloseWorkflow(option)"
|
@click.stop="onCloseWorkflow(option)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</SelectButton>
|
</SelectButton>
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
@@ -37,6 +36,10 @@ import SelectButton from 'primevue/selectbutton'
|
|||||||
import Button from 'primevue/button'
|
import Button from 'primevue/button'
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
class?: string
|
||||||
|
}>()
|
||||||
|
|
||||||
const workflowStore = useWorkflowStore()
|
const workflowStore = useWorkflowStore()
|
||||||
interface WorkflowOption {
|
interface WorkflowOption {
|
||||||
label: string
|
label: string
|
||||||
@@ -79,26 +82,9 @@ const onCloseWorkflow = (option: WorkflowOption) => {
|
|||||||
const workflow = optionToWorkflow(option)
|
const workflow = optionToWorkflow(option)
|
||||||
app.workflowManager.closeWorkflow(workflow)
|
app.workflowManager.closeWorkflow(workflow)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add this new function to check if a workflow is unsaved
|
|
||||||
const isWorkflowUnsaved = (option: WorkflowOption): boolean => {
|
|
||||||
const workflow = optionToWorkflow(option)
|
|
||||||
return workflow.unsaved
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.select-button-group {
|
|
||||||
/* TODO: Make this dynamic. Take rest of space after all tool buttons */
|
|
||||||
max-width: 70vw;
|
|
||||||
overflow-x: auto;
|
|
||||||
overflow-y: hidden;
|
|
||||||
|
|
||||||
/* Scrollbar styling */
|
|
||||||
scrollbar-width: thin;
|
|
||||||
scrollbar-color: rgba(155, 155, 155, 0.5) transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(.p-togglebutton::before) {
|
:deep(.p-togglebutton::before) {
|
||||||
@apply hidden;
|
@apply hidden;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,140 +1,37 @@
|
|||||||
import type { ComfyApp } from '@/scripts/app'
|
import type { ComfyApp } from '@/scripts/app'
|
||||||
import { api } from '../../api'
|
|
||||||
import { $el } from '../../ui'
|
import { $el } from '../../ui'
|
||||||
import { downloadBlob } from '../../utils'
|
import { downloadBlob } from '../../utils'
|
||||||
import { ComfyButton } from '../components/button'
|
|
||||||
import { ComfyButtonGroup } from '../components/buttonGroup'
|
import { ComfyButtonGroup } from '../components/buttonGroup'
|
||||||
import { ComfySplitButton } from '../components/splitButton'
|
|
||||||
import { ComfyQueueButton } from './queueButton'
|
|
||||||
import { getInterruptButton } from './interruptButton'
|
|
||||||
import './menu.css'
|
import './menu.css'
|
||||||
|
|
||||||
const collapseOnMobile = (t) => {
|
// Import ComfyButton to make sure it's shimmed and exported by vite
|
||||||
;(t.element ?? t).classList.add('comfyui-menu-mobile-collapse')
|
import { ComfyButton } from '../components/button'
|
||||||
return t
|
import { ComfySplitButton } from '../components/splitButton'
|
||||||
}
|
import { ComfyPopup } from '../components/popup'
|
||||||
const showOnMobile = (t) => {
|
console.debug(
|
||||||
;(t.element ?? t).classList.add('lt-lg-show')
|
`Keep following definitions ${ComfyButton} ${ComfySplitButton} ${ComfyPopup}`
|
||||||
return t
|
)
|
||||||
}
|
|
||||||
|
|
||||||
export class ComfyAppMenu {
|
export class ComfyAppMenu {
|
||||||
app: ComfyApp
|
app: ComfyApp
|
||||||
logo: HTMLElement
|
|
||||||
saveButton: ComfySplitButton
|
|
||||||
actionsGroup: ComfyButtonGroup
|
actionsGroup: ComfyButtonGroup
|
||||||
settingsGroup: ComfyButtonGroup
|
settingsGroup: ComfyButtonGroup
|
||||||
viewGroup: ComfyButtonGroup
|
viewGroup: ComfyButtonGroup
|
||||||
mobileMenuButton: ComfyButton
|
|
||||||
queueButton: ComfyQueueButton
|
|
||||||
element: HTMLElement
|
element: HTMLElement
|
||||||
|
|
||||||
constructor(app: ComfyApp) {
|
constructor(app: ComfyApp) {
|
||||||
this.app = app
|
this.app = app
|
||||||
const getSaveButton = (t?: string) =>
|
|
||||||
new ComfyButton({
|
|
||||||
icon: 'content-save',
|
|
||||||
tooltip: 'Save the current workflow',
|
|
||||||
action: () => app.workflowManager.activeWorkflow.save(),
|
|
||||||
content: t
|
|
||||||
})
|
|
||||||
|
|
||||||
this.logo = $el('h1.comfyui-logo.nlg-hide', { title: 'ComfyUI' }, 'ComfyUI')
|
// Keep the group as there are custom scripts attaching extra
|
||||||
this.saveButton = new ComfySplitButton(
|
|
||||||
{
|
|
||||||
primary: getSaveButton(),
|
|
||||||
mode: 'hover',
|
|
||||||
position: 'absolute'
|
|
||||||
},
|
|
||||||
getSaveButton('Save'),
|
|
||||||
new ComfyButton({
|
|
||||||
icon: 'content-save-edit',
|
|
||||||
content: 'Save As',
|
|
||||||
tooltip: 'Save the current graph as a new workflow',
|
|
||||||
action: () => app.workflowManager.activeWorkflow.save(true)
|
|
||||||
}),
|
|
||||||
new ComfyButton({
|
|
||||||
icon: 'download',
|
|
||||||
content: 'Export',
|
|
||||||
tooltip: 'Export the current workflow as JSON',
|
|
||||||
action: () => this.exportWorkflow('workflow', 'workflow')
|
|
||||||
}),
|
|
||||||
new ComfyButton({
|
|
||||||
icon: 'api',
|
|
||||||
content: 'Export (API Format)',
|
|
||||||
tooltip:
|
|
||||||
'Export the current workflow as JSON for use with the ComfyUI API',
|
|
||||||
action: () => this.exportWorkflow('workflow_api', 'output'),
|
|
||||||
visibilitySetting: { id: 'Comfy.DevMode', showValue: true },
|
|
||||||
app
|
|
||||||
})
|
|
||||||
)
|
|
||||||
|
|
||||||
const actionButtons = [
|
|
||||||
new ComfyButton({
|
|
||||||
icon: 'refresh',
|
|
||||||
content: 'Refresh',
|
|
||||||
tooltip: 'Refresh widgets in nodes to find new models or files',
|
|
||||||
action: () => app.refreshComboInNodes()
|
|
||||||
}),
|
|
||||||
new ComfyButton({
|
|
||||||
icon: 'clipboard-edit-outline',
|
|
||||||
content: 'Clipspace',
|
|
||||||
tooltip: 'Open Clipspace window',
|
|
||||||
action: () => app['openClipspace']()
|
|
||||||
}),
|
|
||||||
new ComfyButton({
|
|
||||||
icon: 'fit-to-page-outline',
|
|
||||||
content: 'Reset View',
|
|
||||||
tooltip: 'Reset the canvas view',
|
|
||||||
action: () => app.resetView()
|
|
||||||
}),
|
|
||||||
new ComfyButton({
|
|
||||||
icon: 'cancel',
|
|
||||||
content: 'Clear',
|
|
||||||
tooltip: 'Clears current workflow',
|
|
||||||
action: () => {
|
|
||||||
if (
|
|
||||||
!app.ui.settings.getSettingValue('Comfy.ConfirmClear', true) ||
|
|
||||||
confirm('Clear workflow?')
|
|
||||||
) {
|
|
||||||
app.clean()
|
|
||||||
app.graph.clear()
|
|
||||||
api.dispatchEvent(new CustomEvent('graphCleared'))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
]
|
|
||||||
this.actionsGroup = new ComfyButtonGroup(...actionButtons)
|
|
||||||
|
|
||||||
// Keep the settings group as there are custom scripts attaching extra
|
|
||||||
// elements to it.
|
// elements to it.
|
||||||
|
this.actionsGroup = new ComfyButtonGroup()
|
||||||
this.settingsGroup = new ComfyButtonGroup()
|
this.settingsGroup = new ComfyButtonGroup()
|
||||||
const interruptButton = getInterruptButton('nlg-hide').element
|
this.viewGroup = new ComfyButtonGroup()
|
||||||
this.viewGroup = new ComfyButtonGroup(interruptButton)
|
|
||||||
this.mobileMenuButton = new ComfyButton({
|
|
||||||
icon: 'menu',
|
|
||||||
action: (_, btn) => {
|
|
||||||
btn.icon = this.element.classList.toggle('expanded')
|
|
||||||
? 'menu-open'
|
|
||||||
: 'menu'
|
|
||||||
window.dispatchEvent(new Event('resize'))
|
|
||||||
},
|
|
||||||
classList: 'comfyui-button comfyui-menu-button'
|
|
||||||
})
|
|
||||||
this.queueButton = new ComfyQueueButton(app)
|
|
||||||
|
|
||||||
this.element = $el('nav.comfyui-menu.lg', { style: { display: 'none' } }, [
|
this.element = $el('div.flex.gap-2.mx-2', [
|
||||||
this.logo,
|
this.actionsGroup.element,
|
||||||
this.saveButton.element,
|
this.settingsGroup.element,
|
||||||
collapseOnMobile(this.actionsGroup).element,
|
this.viewGroup.element
|
||||||
$el('section.comfyui-menu-push'),
|
|
||||||
collapseOnMobile(this.settingsGroup).element,
|
|
||||||
collapseOnMobile(this.viewGroup).element,
|
|
||||||
|
|
||||||
getInterruptButton('lt-lg-show').element,
|
|
||||||
this.queueButton.element,
|
|
||||||
showOnMobile(this.mobileMenuButton).element
|
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,32 +0,0 @@
|
|||||||
import { StatusWsMessageStatus } from '@/types/apiTypes'
|
|
||||||
import { api } from '../../api'
|
|
||||||
import { ComfyButton } from '../components/button'
|
|
||||||
import { useToastStore } from '@/stores/toastStore'
|
|
||||||
|
|
||||||
export function getInterruptButton(visibility: string) {
|
|
||||||
const btn = new ComfyButton({
|
|
||||||
icon: 'close',
|
|
||||||
tooltip: 'Cancel current generation',
|
|
||||||
enabled: false,
|
|
||||||
action: async () => {
|
|
||||||
await api.interrupt()
|
|
||||||
useToastStore().add({
|
|
||||||
severity: 'info',
|
|
||||||
summary: 'Interrupted',
|
|
||||||
detail: 'Execution has been interrupted',
|
|
||||||
life: 1000
|
|
||||||
})
|
|
||||||
},
|
|
||||||
classList: ['comfyui-button', 'comfyui-interrupt-button', visibility]
|
|
||||||
})
|
|
||||||
|
|
||||||
api.addEventListener(
|
|
||||||
'status',
|
|
||||||
({ detail }: CustomEvent<StatusWsMessageStatus>) => {
|
|
||||||
const sz = detail?.exec_info?.queue_remaining
|
|
||||||
btn.enabled = sz > 0
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
return btn
|
|
||||||
}
|
|
||||||
@@ -122,9 +122,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Menu */
|
/* Menu */
|
||||||
.comfyui-menu>* {
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
.comfyui-menu .mdi::before {
|
.comfyui-menu .mdi::before {
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,103 +0,0 @@
|
|||||||
import { ComfyButton } from '../components/button'
|
|
||||||
import { $el } from '../../ui'
|
|
||||||
import { api } from '../../api'
|
|
||||||
import { ComfySplitButton } from '../components/splitButton'
|
|
||||||
import { ComfyQueueOptions } from './queueOptions'
|
|
||||||
import { prop } from '../../utils'
|
|
||||||
import type { ComfyApp } from '@/scripts/app'
|
|
||||||
import { StatusWsMessageStatus } from '@/types/apiTypes'
|
|
||||||
|
|
||||||
export class ComfyQueueButton {
|
|
||||||
element = $el('div.comfyui-queue-button')
|
|
||||||
#internalQueueSize = 0
|
|
||||||
|
|
||||||
queuePrompt = async (e?: MouseEvent) => {
|
|
||||||
this.#internalQueueSize += this.queueOptions.batchCount
|
|
||||||
// Hold shift to queue front, event is undefined when auto-queue is enabled
|
|
||||||
await this.app.queuePrompt(
|
|
||||||
e?.shiftKey ? -1 : 0,
|
|
||||||
this.queueOptions.batchCount
|
|
||||||
)
|
|
||||||
}
|
|
||||||
queueOptions: ComfyQueueOptions
|
|
||||||
app: ComfyApp
|
|
||||||
autoQueueMode: string
|
|
||||||
graphHasChanged: boolean
|
|
||||||
|
|
||||||
constructor(app: ComfyApp) {
|
|
||||||
this.app = app
|
|
||||||
|
|
||||||
const queue = new ComfyButton({
|
|
||||||
content: $el('div', [
|
|
||||||
$el('span', {
|
|
||||||
textContent: 'Queue'
|
|
||||||
})
|
|
||||||
]),
|
|
||||||
icon: 'play',
|
|
||||||
classList: 'comfyui-button',
|
|
||||||
action: this.queuePrompt
|
|
||||||
})
|
|
||||||
|
|
||||||
this.queueOptions = new ComfyQueueOptions(app)
|
|
||||||
|
|
||||||
const btn = new ComfySplitButton(
|
|
||||||
{
|
|
||||||
primary: queue,
|
|
||||||
mode: 'click',
|
|
||||||
position: 'absolute',
|
|
||||||
horizontal: 'right'
|
|
||||||
},
|
|
||||||
this.queueOptions.element
|
|
||||||
)
|
|
||||||
btn.element.classList.add('primary')
|
|
||||||
this.element.append(btn.element)
|
|
||||||
|
|
||||||
this.autoQueueMode = prop(this, 'autoQueueMode', '', () => {
|
|
||||||
switch (this.autoQueueMode) {
|
|
||||||
case 'instant':
|
|
||||||
queue.icon = 'infinity'
|
|
||||||
break
|
|
||||||
case 'change':
|
|
||||||
queue.icon = 'auto-mode'
|
|
||||||
break
|
|
||||||
default:
|
|
||||||
queue.icon = 'play'
|
|
||||||
break
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
this.queueOptions.addEventListener(
|
|
||||||
'autoQueueMode',
|
|
||||||
(e) => (this.autoQueueMode = e['detail'])
|
|
||||||
)
|
|
||||||
|
|
||||||
api.addEventListener('graphChanged', () => {
|
|
||||||
if (this.autoQueueMode === 'change') {
|
|
||||||
if (this.#internalQueueSize) {
|
|
||||||
this.graphHasChanged = true
|
|
||||||
} else {
|
|
||||||
this.graphHasChanged = false
|
|
||||||
this.queuePrompt()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
api.addEventListener(
|
|
||||||
'status',
|
|
||||||
({ detail }: CustomEvent<StatusWsMessageStatus>) => {
|
|
||||||
this.#internalQueueSize = detail?.exec_info?.queue_remaining
|
|
||||||
if (this.#internalQueueSize != null) {
|
|
||||||
if (!this.#internalQueueSize && !app.lastExecutionError) {
|
|
||||||
if (
|
|
||||||
this.autoQueueMode === 'instant' ||
|
|
||||||
(this.autoQueueMode === 'change' && this.graphHasChanged)
|
|
||||||
) {
|
|
||||||
this.graphHasChanged = false
|
|
||||||
this.queuePrompt()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,82 +0,0 @@
|
|||||||
import type { ComfyApp } from '@/scripts/app'
|
|
||||||
import { $el } from '../../ui'
|
|
||||||
import { prop } from '../../utils'
|
|
||||||
|
|
||||||
export class ComfyQueueOptions extends EventTarget {
|
|
||||||
element = $el('div.comfyui-queue-options')
|
|
||||||
app: ComfyApp
|
|
||||||
batchCountInput: HTMLInputElement
|
|
||||||
batchCount: number
|
|
||||||
batchCountRange: HTMLInputElement
|
|
||||||
autoQueueMode: string
|
|
||||||
autoQueueEl: HTMLElement
|
|
||||||
|
|
||||||
constructor(app: ComfyApp) {
|
|
||||||
super()
|
|
||||||
this.app = app
|
|
||||||
|
|
||||||
this.batchCountInput = $el('input', {
|
|
||||||
className: 'comfyui-queue-batch-value',
|
|
||||||
type: 'number',
|
|
||||||
min: '1',
|
|
||||||
value: '1',
|
|
||||||
oninput: () => (this.batchCount = +this.batchCountInput.value)
|
|
||||||
})
|
|
||||||
|
|
||||||
this.batchCountRange = $el('input', {
|
|
||||||
type: 'range',
|
|
||||||
min: '1',
|
|
||||||
max: '100',
|
|
||||||
value: '1',
|
|
||||||
oninput: () => (this.batchCount = +this.batchCountRange.value)
|
|
||||||
})
|
|
||||||
|
|
||||||
this.element.append(
|
|
||||||
$el('div.comfyui-queue-batch', [
|
|
||||||
$el(
|
|
||||||
'label',
|
|
||||||
{
|
|
||||||
textContent: 'Batch count: '
|
|
||||||
},
|
|
||||||
this.batchCountInput
|
|
||||||
),
|
|
||||||
this.batchCountRange
|
|
||||||
])
|
|
||||||
)
|
|
||||||
|
|
||||||
const createOption = (text, value, checked = false) =>
|
|
||||||
$el(
|
|
||||||
'label',
|
|
||||||
{ textContent: text },
|
|
||||||
$el('input', {
|
|
||||||
type: 'radio',
|
|
||||||
name: 'AutoQueueMode',
|
|
||||||
checked,
|
|
||||||
value,
|
|
||||||
oninput: (e) => (this.autoQueueMode = e.target['value'])
|
|
||||||
})
|
|
||||||
)
|
|
||||||
|
|
||||||
this.autoQueueEl = $el('div.comfyui-queue-mode', [
|
|
||||||
$el('span', 'Auto Queue:'),
|
|
||||||
createOption('Disabled', '', true),
|
|
||||||
createOption('Instant', 'instant'),
|
|
||||||
createOption('On Change', 'change')
|
|
||||||
])
|
|
||||||
|
|
||||||
this.element.append(this.autoQueueEl)
|
|
||||||
|
|
||||||
this.batchCount = prop(this, 'batchCount', 1, () => {
|
|
||||||
this.batchCountInput.value = this.batchCount + ''
|
|
||||||
this.batchCountRange.value = this.batchCount + ''
|
|
||||||
})
|
|
||||||
|
|
||||||
this.autoQueueMode = prop(this, 'autoQueueMode', 'Disabled', () => {
|
|
||||||
this.dispatchEvent(
|
|
||||||
new CustomEvent('autoQueueMode', {
|
|
||||||
detail: this.autoQueueMode
|
|
||||||
})
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,10 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
|
<!-- Top menu bar needs to load before the GraphCanvas as it needs to host
|
||||||
|
the menu buttons added by legacy extension scripts.-->
|
||||||
|
<TopMenubar />
|
||||||
<GraphCanvas />
|
<GraphCanvas />
|
||||||
<GlobalToast />
|
<GlobalToast />
|
||||||
<UnloadWindowConfirmDialog />
|
<UnloadWindowConfirmDialog />
|
||||||
<BrowserTabTitle />
|
<BrowserTabTitle />
|
||||||
<AppMenu />
|
<AppMenu />
|
||||||
<TopMenubar />
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
|||||||
Reference in New Issue
Block a user