From ef4723b572367dffe3c1c43317252c173555283f Mon Sep 17 00:00:00 2001 From: space-nuko <24979496+space-nuko@users.noreply.github.com> Date: Sat, 6 May 2023 11:04:06 -0500 Subject: [PATCH] Better bottom bar --- src/lib/components/BlockContainer.svelte | 8 +- src/lib/components/ComfyApp.svelte | 124 +++++---- src/lib/components/ComfyProperties.svelte | 250 ++++++++++-------- src/lib/components/ComfyUIPane.svelte | 2 +- src/lib/components/ComfyUnlockUIButton.svelte | 42 +++ src/lib/components/WidgetContainer.svelte | 7 +- src/lib/stores/layoutState.ts | 37 ++- src/lib/stores/uiState.ts | 6 +- 8 files changed, 298 insertions(+), 178 deletions(-) create mode 100644 src/lib/components/ComfyUnlockUIButton.svelte diff --git a/src/lib/components/BlockContainer.svelte b/src/lib/components/BlockContainer.svelte index 0f910d2..19aafdf 100644 --- a/src/lib/components/BlockContainer.svelte +++ b/src/lib/components/BlockContainer.svelte @@ -41,17 +41,17 @@ {#if container && children} - {@const edit = $uiState.uiEditMode === "widgets" && zIndex > 1} + {@const edit = $uiState.uiUnlocked && $uiState.uiEditMode === "widgets" && zIndex > 1} {#key $attrsChanged}
{#if container.attrs.title !== ""} -
- - - - - - - - - - - - - +
+ + + + + + + + + + + + + + + UI Edit mode + + + + Theme + + +
+
+ +
@@ -276,10 +283,23 @@ } #bottombar { + padding-top: 0.5em; display: flex; - flex-wrap: wrap; + align-items: center; + width: 100%; gap: var(--layout-gap); - margin: 10px; + padding-left: 1em; + padding-right: 1em; + margin-top: auto; + overflow-x: auto; + + > .left { + flex-shrink: 0; + } + + > .right { + margin-left: auto + } } .canvas-wrapper { @@ -350,4 +370,8 @@ label.label > :global(span) { top: 20%; } + + span.left { + right: 0px; + } diff --git a/src/lib/components/ComfyProperties.svelte b/src/lib/components/ComfyProperties.svelte index 2d9c617..251f624 100644 --- a/src/lib/components/ComfyProperties.svelte +++ b/src/lib/components/ComfyProperties.svelte @@ -3,6 +3,7 @@ import { TextBox, Checkbox } from "@gradio/form"; import { LGraphNode } from "@litegraph-ts/core" import layoutState, { type IDragItem, type WidgetLayout, ALL_ATTRIBUTES, type AttributesSpec } from "$lib/stores/layoutState" + import uiState from "$lib/stores/uiState" import { get } from "svelte/store" import type { ComfyWidgetNode } from "$lib/nodes"; import ComfyNumberProperty from "./ComfyNumberProperty.svelte"; @@ -41,74 +42,92 @@ targetType = "" } - function validNodeProperty(spec: AttributesSpec, node: LGraphNode): boolean { + function validNodeProperty(spec: AttributesSpec, node: LGraphNode | null): boolean { + if (node == null) + return false; + + if (spec.canShow && !spec.canShow(node)) + return false; + if (spec.validNodeTypes) { return spec.validNodeTypes.indexOf(node.type) !== -1; } return spec.name in node.properties } - function updateAttribute(entry: AttributesSpec, target: IDragItem, value: any) { - if (target) { - const name = entry.name - console.warn("updateAttribute", name, value) + function validWidgetAttribute(spec: AttributesSpec, widget: IDragItem | null): boolean { + if (widget == null) + return false; + if (spec.canShow) + return spec.canShow(widget); - target.attrs[name] = value - target.attrsChanged.set(!get(target.attrsChanged)) + return spec.name in widget.attrs + } - if (node && "propsChanged" in node) { - const comfyNode = node as ComfyWidgetNode - comfyNode.propsChanged.set(get(comfyNode.propsChanged) + 1) - } + function updateAttribute(entry: AttributesSpec, target: IDragItem | null, value: any) { + if (target == null) + return; + + const name = entry.name + console.warn("updateAttribute", name, value) + + target.attrs[name] = value + target.attrsChanged.set(!get(target.attrsChanged)) + + if (node && "propsChanged" in node) { + const comfyNode = node as ComfyWidgetNode + comfyNode.propsChanged.set(get(comfyNode.propsChanged) + 1) } } function updateProperty(entry: AttributesSpec, value: any) { - if (node) { - const name = entry.name - console.warn("updateProperty", name, value) + if (node == null) + return - node.properties[name] = value; + const name = entry.name + console.warn("updateProperty", name, value) - if ("propsChanged" in node) { - const comfyNode = node as ComfyWidgetNode - comfyNode.propsChanged.set(get(comfyNode.propsChanged) + 1) - } + node.properties[name] = value; + + if ("propsChanged" in node) { + const comfyNode = node as ComfyWidgetNode + comfyNode.propsChanged.set(get(comfyNode.propsChanged) + 1) } } - function getVar(node: LGraphNode, entry: AttributesSpec) { - let value = node[entry.name] - if (entry.serialize) - value = entry.serialize(value) - console.debug("[ComfyProperties] getVar", entry, value, node) + function getVar(node: LGraphNode, spec: AttributesSpec) { + let value = node[spec.name] || spec.defaultValue + if (spec.serialize) + value = spec.serialize(value) + console.debug("[ComfyProperties] getVar", spec, value, node) return value } function updateVar(entry: any, value: any) { - if (node) { - const name = entry.name - console.warn("updateProperty", name, value) + if (node == null) + return; - if (entry.deserialize) - value = entry.deserialize(value) + const name = entry.name + console.warn("updateVar", name, value) - console.debug("[ComfyProperties] updateVar", entry, value, name, node) - node[name] = value; + if (entry.deserialize) + value = entry.deserialize(value) - if ("propsChanged" in node) { - const comfyNode = node as ComfyWidgetNode - comfyNode.propsChanged.set(get(comfyNode.propsChanged) + 1) - } + console.debug("[ComfyProperties] updateVar", entry, value, name, node) + node[name] = value; + + if ("propsChanged" in node) { + const comfyNode = node as ComfyWidgetNode + comfyNode.propsChanged.set(get(comfyNode.propsChanged) + 1) } } function updateWorkflowAttribute(entry: AttributesSpec, value: any) { - const name = entry.name - console.warn("updateWorkflowAttribute", name, value) + const name = entry.name + console.warn("updateWorkflowAttribute", name, value) - $layoutState.attrs[name] = value - $layoutState = $layoutState + $layoutState.attrs[name] = value + $layoutState = $layoutState } @@ -117,9 +136,10 @@
{target?.attrs?.title || node?.title || "Workflow"} - {#if targetType !== ""} - ({targetType}) - {/if} + {#if targetType !== ""} + ({targetType}) + {/if} +
@@ -130,37 +150,37 @@ {category.categoryName} - {#each category.specs as spec(spec.name)} - {#if spec.location === "widget" && target && spec.name in target.attrs} + {#each category.specs as spec(spec.id)} + {#if spec.location === "widget" && validWidgetAttribute(spec, target)}
{#if spec.type === "string"} updateAttribute(spec, target, e.detail)} on:input={(e) => updateAttribute(spec, target, e.detail)} label={spec.name} max_lines={1} /> {:else if spec.type === "boolean"} - updateAttribute(spec, target, e.detail)} - label={spec.name} - /> + updateAttribute(spec, target, e.detail)} + label={spec.name} + /> {:else if spec.type === "number"} - updateAttribute(spec, target, e.detail)} - /> + updateAttribute(spec, target, e.detail)} + /> {:else if spec.type === "enum"} - updateAttribute(spec, target, e.detail)} - /> + updateAttribute(spec, target, e.detail)} + /> {/if}
{:else if node} @@ -168,32 +188,32 @@
{#if spec.type === "string"} updateProperty(spec, e.detail)} on:input={(e) => updateProperty(spec, e.detail)} label={spec.name} max_lines={1} /> {:else if spec.type === "boolean"} - updateProperty(spec, e.detail)} - /> + updateProperty(spec, e.detail)} + /> {:else if spec.type === "number"} - updateProperty(spec, e.detail)} - /> + updateProperty(spec, e.detail)} + /> {:else if spec.type === "enum"} - updateProperty(spec, e.detail)} - /> + updateProperty(spec, e.detail)} + /> {/if}
{:else if spec.location === "nodeVars" && spec.name in node} @@ -207,25 +227,25 @@ max_lines={1} /> {:else if spec.type === "boolean"} - updateVar(spec, e.detail)} - label={spec.name} - /> + updateVar(spec, e.detail)} + label={spec.name} + /> {:else if spec.type === "number"} - updateVar(spec, e.detail)} - /> + updateVar(spec, e.detail)} + /> {:else if spec.type === "enum"} - updateVar(spec, e.detail)} - /> + updateVar(spec, e.detail)} + /> {/if} {/if} @@ -233,32 +253,32 @@
{#if spec.type === "string"} updateWorkflowAttribute(spec, e.detail)} on:input={(e) => updateWorkflowAttribute(spec, e.detail)} label={spec.name} max_lines={1} /> {:else if spec.type === "boolean"} - updateWorkflowAttribute(spec, e.detail)} - label={spec.name} - /> + updateWorkflowAttribute(spec, e.detail)} + label={spec.name} + /> {:else if spec.type === "number"} - updateWorkflowAttribute(spec, e.detail)} - /> + updateWorkflowAttribute(spec, e.detail)} + /> {:else if spec.type === "enum"} - updateWorkflowAttribute(spec, e.detail)} - /> + updateWorkflowAttribute(spec, e.detail)} + /> {/if}
{/if} diff --git a/src/lib/components/ComfyUIPane.svelte b/src/lib/components/ComfyUIPane.svelte index b9a95b1..a6b7415 100644 --- a/src/lib/components/ComfyUIPane.svelte +++ b/src/lib/components/ComfyUIPane.svelte @@ -69,7 +69,7 @@ } async function onRightClick(e) { - if ($uiState.uiEditMode === "disabled") + if (!$uiState.uiUnlocked) return; e.preventDefault(); diff --git a/src/lib/components/ComfyUnlockUIButton.svelte b/src/lib/components/ComfyUnlockUIButton.svelte new file mode 100644 index 0000000..b1a1f83 --- /dev/null +++ b/src/lib/components/ComfyUnlockUIButton.svelte @@ -0,0 +1,42 @@ + + +
+ +
+ + diff --git a/src/lib/components/WidgetContainer.svelte b/src/lib/components/WidgetContainer.svelte index 261e414..8b3478e 100644 --- a/src/lib/components/WidgetContainer.svelte +++ b/src/lib/components/WidgetContainer.svelte @@ -40,7 +40,8 @@ propsChanged = null; } - $: showHandles = $uiState.uiEditMode === "widgets" // TODO + $: showHandles = $uiState.uiUnlocked + && $uiState.uiEditMode === "widgets" // TODO && zIndex > 1 && !$layoutState.isMenuOpen @@ -61,12 +62,12 @@ {/key} {:else if widget && widget.node} - {@const edit = $uiState.uiEditMode === "widgets" && zIndex > 1} + {@const edit = $uiState.uiUnlocked && $uiState.uiEditMode === "widgets" && zIndex > 1} {#key $attrsChanged} {#key $propsChanged}
diff --git a/src/lib/stores/layoutState.ts b/src/lib/stores/layoutState.ts index b6a9433..58660f1 100644 --- a/src/lib/stores/layoutState.ts +++ b/src/lib/stores/layoutState.ts @@ -39,15 +39,18 @@ export type Attributes = { } export type AttributesSpec = { + id?: number, // for svelte keyed each name: string, type: string, location: "widget" | "nodeProps" | "nodeVars" | "workflow" editable: boolean, + defaultValue?: any, values?: string[], hidden?: boolean, validNodeTypes?: string[], + canShow?: (arg: IDragItem | LGraphNode) => boolean, serialize?: (arg: any) => string, deserialize?: (arg: string) => any, } @@ -86,18 +89,22 @@ const ALL_ATTRIBUTES: AttributesSpecList = [ type: "enum", location: "widget", editable: true, - values: ["horizontal", "vertical"] + values: ["horizontal", "vertical"], + defaultValue: "vertical", + canShow: (di: IDragItem) => di.type === "container" }, { name: "flexGrow", type: "number", location: "widget", + defaultValue: 100, editable: true }, { name: "classes", type: "string", location: "widget", + defaultValue: "", editable: true, }, { @@ -105,7 +112,20 @@ const ALL_ATTRIBUTES: AttributesSpecList = [ type: "enum", location: "widget", editable: true, - values: ["block", "hidden"] + values: ["block", "hidden"], + defaultValue: "block", + canShow: (di: IDragItem) => di.type === "container" + }, + + // Container variants + { + name: "variant", + type: "enum", + location: "widget", + editable: true, + values: ["block", "accordion", "tabs"], + defaultValue: "block", + canShow: (di: IDragItem) => di.type === "container" }, ] }, @@ -156,6 +176,7 @@ const ALL_ATTRIBUTES: AttributesSpecList = [ location: "nodeProps", editable: true, validNodeTypes: ["ui/button"], + defaultValue: "bang" }, // Workflow @@ -163,11 +184,21 @@ const ALL_ATTRIBUTES: AttributesSpecList = [ name: "defaultSubgraph", type: "string", location: "workflow", - editable: true + editable: true, + defaultValue: "" } ] } ]; + +let i = 0; +for (const cat of Object.values(ALL_ATTRIBUTES)) { + for (const val of Object.values(cat.specs)) { + val.id = i; + i += 1; + } +} + export { ALL_ATTRIBUTES }; export interface IDragItem { diff --git a/src/lib/stores/uiState.ts b/src/lib/stores/uiState.ts index ba9396c..a7c3cc6 100644 --- a/src/lib/stores/uiState.ts +++ b/src/lib/stores/uiState.ts @@ -2,13 +2,14 @@ import { writable } from 'svelte/store'; import type { Readable, Writable } from 'svelte/store'; import type ComfyApp from "$lib/components/ComfyApp" -export type UIEditMode = "disabled" | "widgets" | "containers" | "layout"; +export type UIEditMode = "widgets" | "containers" | "layout"; export type UIState = { app: ComfyApp, nodesLocked: boolean, graphLocked: boolean, autoAddUI: boolean, + uiUnlocked: boolean, uiEditMode: UIEditMode, } @@ -19,7 +20,8 @@ const store: WritableUIStateStore = writable( graphLocked: false, nodesLocked: false, autoAddUI: true, - uiEditMode: "disabled", + uiUnlocked: false, + uiEditMode: "widgets" }) const uiStateStore: WritableUIStateStore =