Files
ComfyUI_frontend/src/components/graph/TitleEditor.vue
AustinMroz 565305175c Initial 1.28 backports (#5986)
Includes
- Subgraph widget promotion fixes (#5911)
- fix "what's changed" release toast attention level logic (#5959)
- Fix: Missing Node Title Editor bug (#5963)
- OpenAIVideoSora2 Frontend pricing (#5958)
- hotfix: quick test updates for sora2 pricing badge. (#5966)

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5986-Initial-1-28-backports-2866d73d365081448ff2c4827bdbb9e5)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Christian Byrne <cbyrne@comfy.org>
Co-authored-by: Alexander Brown <drjkl@comfy.org>
Co-authored-by: Marwan Ahmed <155799754+marawan206@users.noreply.github.com>
2025-10-08 15:03:16 -07:00

152 lines
4.1 KiB
Vue

<template>
<div
v-if="showInput"
class="group-title-editor node-title-editor"
:style="inputStyle"
>
<EditableText
:is-editing="showInput"
:model-value="editedTitle"
@edit="onEdit"
/>
</div>
</template>
<script setup lang="ts">
import { useEventListener } from '@vueuse/core'
import { type CSSProperties, computed, ref, watch } from 'vue'
import EditableText from '@/components/common/EditableText.vue'
import { useAbsolutePosition } from '@/composables/element/useAbsolutePosition'
import {
LGraphGroup,
LGraphNode,
LiteGraph
} from '@/lib/litegraph/src/litegraph'
import type { LiteGraphCanvasEvent } from '@/lib/litegraph/src/litegraph'
import { useSettingStore } from '@/platform/settings/settingStore'
import {
useCanvasStore,
useTitleEditorStore
} from '@/renderer/core/canvas/canvasStore'
import { app } from '@/scripts/app'
const settingStore = useSettingStore()
const showInput = ref(false)
const editedTitle = ref('')
const { style: inputPositionStyle, updatePosition } = useAbsolutePosition()
const inputFontStyle = ref<CSSProperties>({})
const inputStyle = computed<CSSProperties>(() => ({
...inputPositionStyle.value,
...inputFontStyle.value
}))
const titleEditorStore = useTitleEditorStore()
const canvasStore = useCanvasStore()
const previousCanvasDraggable = ref(true)
const onEdit = (newValue: string) => {
if (titleEditorStore.titleEditorTarget && newValue?.trim()) {
const trimmedTitle = newValue.trim()
titleEditorStore.titleEditorTarget.title = trimmedTitle
// If this is a subgraph node, sync the runtime subgraph name for breadcrumb reactivity
const target = titleEditorStore.titleEditorTarget
if (target instanceof LGraphNode && target.isSubgraphNode?.()) {
target.subgraph.name = trimmedTitle
}
app.graph.setDirtyCanvas(true, true)
}
showInput.value = false
titleEditorStore.titleEditorTarget = null
canvasStore.canvas!.allow_dragcanvas = previousCanvasDraggable.value
}
watch(
() => titleEditorStore.titleEditorTarget,
(target) => {
if (target === null) {
return
}
editedTitle.value = target.title
showInput.value = true
const canvas = canvasStore.canvas!
previousCanvasDraggable.value = canvas.allow_dragcanvas
canvas.allow_dragcanvas = false
const scale = canvas.ds.scale
if (target instanceof LGraphGroup) {
const group = target
updatePosition({
pos: group.pos,
size: [group.size[0], group.titleHeight]
})
inputFontStyle.value = { fontSize: `${group.font_size * scale}px` }
} else if (target instanceof LGraphNode) {
const node = target
const [x, y] = node.getBounding()
updatePosition({
pos: [x, y],
size: [node.width, LiteGraph.NODE_TITLE_HEIGHT]
})
inputFontStyle.value = { fontSize: `${12 * scale}px` }
}
}
)
const canvasEventHandler = (event: LiteGraphCanvasEvent) => {
if (event.detail.subType === 'group-double-click') {
if (!settingStore.get('Comfy.Group.DoubleClickTitleToEdit')) {
return
}
const group: LGraphGroup = event.detail.group
const [_, y] = group.pos
const e = event.detail.originalEvent
const relativeY = e.canvasY - y
// Only allow editing if the click is on the title bar
if (relativeY <= group.titleHeight) {
titleEditorStore.titleEditorTarget = group
}
} else if (event.detail.subType === 'node-double-click') {
if (!settingStore.get('Comfy.Node.DoubleClickTitleToEdit')) {
return
}
const node: LGraphNode = event.detail.node
const [_, y] = node.pos
const e = event.detail.originalEvent
const relativeY = e.canvasY - y
// Only allow editing if the click is on the title bar
if (relativeY <= 0) {
titleEditorStore.titleEditorTarget = node
}
}
}
useEventListener(document, 'litegraph:canvas', canvasEventHandler)
</script>
<style scoped>
.group-title-editor.node-title-editor {
z-index: 9999;
padding: 0.25rem;
}
:deep(.editable-text) {
width: 100%;
height: 100%;
}
:deep(.editable-text input) {
width: 100%;
height: 100%;
/* Override the default font size */
font-size: inherit;
}
</style>