mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-07 08:30:06 +00:00
Cleanup: YAGNI readonly props, private swap on ComfyApp, Canvas resize events simplification, v-memos on individual instances (#5869)
## Summary Assorted cleanup opportunities found while working through the Vue node rendering logic cleanup. ## Review Focus Am I wrong that the readonly logic was never actually executing because it was defined as False in GraphCanvas when making each LGraphNode? Is there an edge case or some other reason that the ResizeObserver wouldn't work as a single signal to resize the canvas? ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-5869-Cleanup-YAGNI-readonly-props-private-swap-on-ComfyApp-Canvas-resize-events-simplificat-27e6d73d3650811ba1dcf29e8d43091e) by [Unito](https://www.unito.io) --------- Co-authored-by: github-actions <github-actions@github.com>
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
import { useResizeObserver } from '@vueuse/core'
|
||||
import _ from 'es-toolkit/compat'
|
||||
import type { ToastMessageOptions } from 'primevue/toast'
|
||||
import { reactive } from 'vue'
|
||||
import { reactive, unref } from 'vue'
|
||||
import { shallowRef } from 'vue'
|
||||
|
||||
import { useCanvasPositionConversion } from '@/composables/element/useCanvasPositionConversion'
|
||||
import { st, t } from '@/i18n'
|
||||
@@ -129,7 +131,7 @@ export class ComfyApp {
|
||||
/**
|
||||
* List of entries to queue
|
||||
*/
|
||||
#queueItems: {
|
||||
private queueItems: {
|
||||
number: number
|
||||
batchCount: number
|
||||
queueNodeIds?: NodeExecutionId[]
|
||||
@@ -137,7 +139,7 @@ export class ComfyApp {
|
||||
/**
|
||||
* If the queue is currently being processed
|
||||
*/
|
||||
#processingQueue: boolean = false
|
||||
private processingQueue: boolean = false
|
||||
|
||||
/**
|
||||
* Content Clipboard
|
||||
@@ -176,12 +178,15 @@ export class ComfyApp {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
canvas: LGraphCanvas
|
||||
dragOverNode: LGraphNode | null = null
|
||||
// @ts-expect-error fixme ts strict error
|
||||
canvasEl: HTMLCanvasElement
|
||||
readonly canvasElRef = shallowRef<HTMLCanvasElement>()
|
||||
get canvasEl() {
|
||||
// TODO: Fix possibly undefined reference
|
||||
return unref(this.canvasElRef)!
|
||||
}
|
||||
|
||||
#configuringGraphLevel: number = 0
|
||||
private configuringGraphLevel: number = 0
|
||||
get configuringGraph() {
|
||||
return this.#configuringGraphLevel > 0
|
||||
return this.configuringGraphLevel > 0
|
||||
}
|
||||
// @ts-expect-error fixme ts strict error
|
||||
ctx: CanvasRenderingContext2D
|
||||
@@ -195,7 +200,7 @@ export class ComfyApp {
|
||||
// Set by Comfy.Clipspace extension
|
||||
openClipspace: () => void = () => {}
|
||||
|
||||
#positionConversion?: {
|
||||
private positionConversion?: {
|
||||
clientPosToCanvasPos: (pos: Vector2) => Vector2
|
||||
canvasPosToClientPos: (pos: Vector2) => Vector2
|
||||
}
|
||||
@@ -517,7 +522,7 @@ export class ComfyApp {
|
||||
/**
|
||||
* Adds a handler allowing drag+drop of files onto the window to load workflows
|
||||
*/
|
||||
#addDropHandler() {
|
||||
private addDropHandler() {
|
||||
// Get prompt from dropped PNG or json
|
||||
document.addEventListener('drop', async (event) => {
|
||||
try {
|
||||
@@ -593,7 +598,7 @@ export class ComfyApp {
|
||||
/**
|
||||
* Handle keypress
|
||||
*/
|
||||
#addProcessKeyHandler() {
|
||||
private addProcessKeyHandler() {
|
||||
const origProcessKey = LGraphCanvas.prototype.processKey
|
||||
LGraphCanvas.prototype.processKey = function (e: KeyboardEvent) {
|
||||
if (!this.graph) return
|
||||
@@ -640,7 +645,7 @@ export class ComfyApp {
|
||||
}
|
||||
}
|
||||
|
||||
#addDrawNodeHandler() {
|
||||
private addDrawNodeHandler() {
|
||||
const origDrawNode = LGraphCanvas.prototype.drawNode
|
||||
LGraphCanvas.prototype.drawNode = function (node) {
|
||||
const editor_alpha = this.editor_alpha
|
||||
@@ -689,7 +694,7 @@ export class ComfyApp {
|
||||
/**
|
||||
* Handles updates from the API socket
|
||||
*/
|
||||
#addApiUpdateHandlers() {
|
||||
private addApiUpdateHandlers() {
|
||||
api.addEventListener('status', ({ detail }) => {
|
||||
this.ui.setStatus(detail)
|
||||
})
|
||||
@@ -763,15 +768,15 @@ export class ComfyApp {
|
||||
}
|
||||
|
||||
/** Flag that the graph is configuring to prevent nodes from running checks while its still loading */
|
||||
#addConfigureHandler() {
|
||||
private addConfigureHandler() {
|
||||
const app = this
|
||||
const configure = LGraph.prototype.configure
|
||||
LGraph.prototype.configure = function (...args) {
|
||||
app.#configuringGraphLevel++
|
||||
app.configuringGraphLevel++
|
||||
try {
|
||||
return configure.apply(this, args)
|
||||
} finally {
|
||||
app.#configuringGraphLevel--
|
||||
app.configuringGraphLevel--
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -808,16 +813,15 @@ export class ComfyApp {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.canvasContainer = document.getElementById('graph-canvas-container')
|
||||
|
||||
this.canvasEl = canvasEl
|
||||
this.resizeCanvas()
|
||||
this.canvasElRef.value = canvasEl
|
||||
|
||||
await useWorkspaceStore().workflow.syncWorkflows()
|
||||
await useSubgraphStore().fetchSubgraphs()
|
||||
await useExtensionService().loadExtensions()
|
||||
|
||||
this.#addProcessKeyHandler()
|
||||
this.#addConfigureHandler()
|
||||
this.#addApiUpdateHandlers()
|
||||
this.addProcessKeyHandler()
|
||||
this.addConfigureHandler()
|
||||
this.addApiUpdateHandlers()
|
||||
|
||||
const graph = new LGraph()
|
||||
|
||||
@@ -883,39 +887,37 @@ export class ComfyApp {
|
||||
this.graph.start()
|
||||
|
||||
// Ensure the canvas fills the window
|
||||
this.resizeCanvas()
|
||||
window.addEventListener('resize', () => this.resizeCanvas())
|
||||
const ro = new ResizeObserver(() => this.resizeCanvas())
|
||||
ro.observe(this.bodyTop)
|
||||
ro.observe(this.bodyLeft)
|
||||
ro.observe(this.bodyRight)
|
||||
ro.observe(this.bodyBottom)
|
||||
useResizeObserver(this.canvasElRef, ([canvasEl]) => {
|
||||
if (canvasEl.target instanceof HTMLCanvasElement) {
|
||||
this.resizeCanvas(canvasEl.target)
|
||||
}
|
||||
})
|
||||
|
||||
await useExtensionService().invokeExtensionsAsync('init')
|
||||
await this.registerNodes()
|
||||
|
||||
this.#addDrawNodeHandler()
|
||||
this.#addDropHandler()
|
||||
this.addDrawNodeHandler()
|
||||
this.addDropHandler()
|
||||
|
||||
await useExtensionService().invokeExtensionsAsync('setup')
|
||||
|
||||
this.#positionConversion = useCanvasPositionConversion(
|
||||
this.positionConversion = useCanvasPositionConversion(
|
||||
this.canvasContainer,
|
||||
this.canvas
|
||||
)
|
||||
}
|
||||
|
||||
resizeCanvas() {
|
||||
private resizeCanvas(canvas: HTMLCanvasElement) {
|
||||
// Limit minimal scale to 1, see https://github.com/comfyanonymous/ComfyUI/pull/845
|
||||
const scale = Math.max(window.devicePixelRatio, 1)
|
||||
|
||||
// Clear fixed width and height while calculating rect so it uses 100% instead
|
||||
this.canvasEl.height = this.canvasEl.width = NaN
|
||||
const { width, height } = this.canvasEl.getBoundingClientRect()
|
||||
this.canvasEl.width = Math.round(width * scale)
|
||||
this.canvasEl.height = Math.round(height * scale)
|
||||
canvas.height = canvas.width = NaN
|
||||
const { width, height } = canvas.getBoundingClientRect()
|
||||
canvas.width = Math.round(width * scale)
|
||||
canvas.height = Math.round(height * scale)
|
||||
// @ts-expect-error fixme ts strict error
|
||||
this.canvasEl.getContext('2d').scale(scale, scale)
|
||||
canvas.getContext('2d').scale(scale, scale)
|
||||
this.canvas?.draw(true, true)
|
||||
}
|
||||
|
||||
@@ -963,7 +965,7 @@ export class ComfyApp {
|
||||
nodeDefStore.updateNodeDefs(nodeDefArray)
|
||||
}
|
||||
|
||||
async #getNodeDefs(): Promise<Record<string, ComfyNodeDefV1>> {
|
||||
async getNodeDefs(): Promise<Record<string, ComfyNodeDefV1>> {
|
||||
const translateNodeDef = (def: ComfyNodeDefV1): ComfyNodeDefV1 => ({
|
||||
...def,
|
||||
display_name: st(
|
||||
@@ -987,7 +989,7 @@ export class ComfyApp {
|
||||
*/
|
||||
async registerNodes() {
|
||||
// Load node definitions from the backend
|
||||
const defs = await this.#getNodeDefs()
|
||||
const defs = await this.getNodeDefs()
|
||||
await this.registerNodesFromDefs(defs)
|
||||
await useExtensionService().invokeExtensionsAsync('registerCustomNodes')
|
||||
if (this.vueAppReady) {
|
||||
@@ -1055,14 +1057,14 @@ export class ComfyApp {
|
||||
localStorage.setItem('litegrapheditor_clipboard', old)
|
||||
}
|
||||
|
||||
#showMissingNodesError(missingNodeTypes: MissingNodeType[]) {
|
||||
private showMissingNodesError(missingNodeTypes: MissingNodeType[]) {
|
||||
if (useSettingStore().get('Comfy.Workflow.ShowMissingNodesWarning')) {
|
||||
useDialogService().showLoadWorkflowWarning({ missingNodeTypes })
|
||||
}
|
||||
}
|
||||
|
||||
// @ts-expect-error fixme ts strict error
|
||||
#showMissingModelsError(missingModels, paths) {
|
||||
private showMissingModelsError(missingModels, paths) {
|
||||
if (useSettingStore().get('Comfy.Workflow.ShowMissingModelsWarning')) {
|
||||
useDialogService().showMissingModelsWarning({
|
||||
missingModels,
|
||||
@@ -1295,11 +1297,11 @@ export class ComfyApp {
|
||||
}
|
||||
|
||||
if (missingNodeTypes.length && showMissingNodesDialog) {
|
||||
this.#showMissingNodesError(missingNodeTypes)
|
||||
this.showMissingNodesError(missingNodeTypes)
|
||||
}
|
||||
if (missingModels.length && showMissingModelsDialog) {
|
||||
const paths = await api.getFolderPaths()
|
||||
this.#showMissingModelsError(missingModels, paths)
|
||||
this.showMissingModelsError(missingModels, paths)
|
||||
}
|
||||
await useExtensionService().invokeExtensionsAsync(
|
||||
'afterConfigureGraph',
|
||||
@@ -1325,14 +1327,14 @@ export class ComfyApp {
|
||||
batchCount: number = 1,
|
||||
queueNodeIds?: NodeExecutionId[]
|
||||
): Promise<boolean> {
|
||||
this.#queueItems.push({ number, batchCount, queueNodeIds })
|
||||
this.queueItems.push({ number, batchCount, queueNodeIds })
|
||||
|
||||
// Only have one action process the items so each one gets a unique seed correctly
|
||||
if (this.#processingQueue) {
|
||||
if (this.processingQueue) {
|
||||
return false
|
||||
}
|
||||
|
||||
this.#processingQueue = true
|
||||
this.processingQueue = true
|
||||
const executionStore = useExecutionStore()
|
||||
executionStore.lastNodeErrors = null
|
||||
|
||||
@@ -1340,8 +1342,8 @@ export class ComfyApp {
|
||||
let comfyOrgApiKey = useApiKeyAuthStore().getApiKey()
|
||||
|
||||
try {
|
||||
while (this.#queueItems.length) {
|
||||
const { number, batchCount, queueNodeIds } = this.#queueItems.pop()!
|
||||
while (this.queueItems.length) {
|
||||
const { number, batchCount, queueNodeIds } = this.queueItems.pop()!
|
||||
|
||||
for (let i = 0; i < batchCount; i++) {
|
||||
// Allow widgets to run callbacks before a prompt has been queued
|
||||
@@ -1406,7 +1408,7 @@ export class ComfyApp {
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
this.#processingQueue = false
|
||||
this.processingQueue = false
|
||||
}
|
||||
api.dispatchCustomEvent('promptQueued', { number, batchCount })
|
||||
return !executionStore.lastNodeErrors
|
||||
@@ -1610,7 +1612,7 @@ export class ComfyApp {
|
||||
(n) => !LiteGraph.registered_node_types[n.class_type]
|
||||
)
|
||||
if (missingNodeTypes.length) {
|
||||
this.#showMissingNodesError(missingNodeTypes.map((t) => t.class_type))
|
||||
this.showMissingNodesError(missingNodeTypes.map((t) => t.class_type))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1729,7 +1731,7 @@ export class ComfyApp {
|
||||
useToastStore().add(requestToastMessage)
|
||||
}
|
||||
|
||||
const defs = await this.#getNodeDefs()
|
||||
const defs = await this.getNodeDefs()
|
||||
for (const nodeId in defs) {
|
||||
this.registerNodeDef(nodeId, defs[nodeId])
|
||||
}
|
||||
@@ -1805,17 +1807,17 @@ export class ComfyApp {
|
||||
}
|
||||
|
||||
clientPosToCanvasPos(pos: Vector2): Vector2 {
|
||||
if (!this.#positionConversion) {
|
||||
if (!this.positionConversion) {
|
||||
throw new Error('clientPosToCanvasPos called before setup')
|
||||
}
|
||||
return this.#positionConversion.clientPosToCanvasPos(pos)
|
||||
return this.positionConversion.clientPosToCanvasPos(pos)
|
||||
}
|
||||
|
||||
canvasPosToClientPos(pos: Vector2): Vector2 {
|
||||
if (!this.#positionConversion) {
|
||||
if (!this.positionConversion) {
|
||||
throw new Error('canvasPosToClientPos called before setup')
|
||||
}
|
||||
return this.#positionConversion.canvasPosToClientPos(pos)
|
||||
return this.positionConversion.canvasPosToClientPos(pos)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user