mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-08 09:00:05 +00:00
Migrate tooltip tracking to a pinia store
While I was concerned that doing this would remove the capability to suppress tooltips on the active node, clearing the hoveredItem when it used for documentation functions without even producing a temporary tooltip. A future commit will likely be made so that disabling tooltips for nodes doesn't also prevent the hovered item from being tracked in the store.
This commit is contained in:
@@ -10,15 +10,16 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { nextTick, ref } from 'vue'
|
||||
import { nextTick, ref, watch } from 'vue'
|
||||
import { LiteGraph } from '@comfyorg/litegraph'
|
||||
import { app as comfyApp } from '@/scripts/app'
|
||||
import { useNodeDefStore } from '@/stores/nodeDefStore'
|
||||
import { useHoveredItemStore } from '@/stores/graphStore'
|
||||
import { useEventListener } from '@vueuse/core'
|
||||
import { selectDocItem } from '@/components/sidebar/tabs/DocumentationSidebarTab.vue'
|
||||
|
||||
let idleTimeout: number
|
||||
const nodeDefStore = useNodeDefStore()
|
||||
const hoveredItemStore = useHoveredItemStore()
|
||||
const tooltipRef = ref<HTMLDivElement>()
|
||||
const tooltipText = ref('')
|
||||
const left = ref<string>()
|
||||
@@ -54,6 +55,7 @@ const getHoveredWidget = () => {
|
||||
}
|
||||
|
||||
const hideTooltip = () => (tooltipText.value = null)
|
||||
const clearHovered = () => (hoveredItemStore.value = null)
|
||||
|
||||
const showTooltip = async (tooltip: string | null | undefined) => {
|
||||
if (!tooltip) return
|
||||
@@ -73,6 +75,30 @@ const showTooltip = async (tooltip: string | null | undefined) => {
|
||||
top.value = comfyApp.canvas.mouse[1] + rect.height + 'px'
|
||||
}
|
||||
}
|
||||
watch(hoveredItemStore, (hoveredItem) => {
|
||||
if (!hoveredItem.value) {
|
||||
return hideTooltip()
|
||||
}
|
||||
const item = hoveredItem.value
|
||||
const nodeDef = nodeDefStore.nodeDefsByName[item.node.type]
|
||||
if (item.type == 'Title') {
|
||||
let description = nodeDef.description
|
||||
if (Array.isArray(description)) {
|
||||
description = description[0]
|
||||
}
|
||||
return showTooltip(description)
|
||||
} else if (item.type == 'Input') {
|
||||
showTooltip(nodeDef.input.getInput(item.inputName)?.tooltip)
|
||||
} else if (item.type == 'Output') {
|
||||
showTooltip(nodeDef?.output?.all?.[item.outputSlot]?.tooltip)
|
||||
} else if (item.type == 'Widget') {
|
||||
showTooltip(
|
||||
item.widget.tooltip ?? nodeDef.input.getInput(item.widget.name)?.tooltip
|
||||
)
|
||||
} else {
|
||||
hideTooltip()
|
||||
}
|
||||
})
|
||||
|
||||
const onIdle = () => {
|
||||
const { canvas } = comfyApp
|
||||
@@ -86,12 +112,7 @@ const onIdle = () => {
|
||||
ctor.title_mode !== LiteGraph.NO_TITLE &&
|
||||
canvas.graph_mouse[1] < node.pos[1] // If we are over a node, but not within the node then we are on its title
|
||||
) {
|
||||
if (selectDocItem(node, 'DESCRIPTION')) {
|
||||
return
|
||||
} else if (Array.isArray(nodeDef.description)) {
|
||||
return showTooltip(nodeDef.description[0])
|
||||
}
|
||||
return showTooltip(nodeDef.description)
|
||||
hoveredItemStore.value = { node, type: 'Title' }
|
||||
}
|
||||
|
||||
if (node.flags?.collapsed) return
|
||||
@@ -104,9 +125,7 @@ const onIdle = () => {
|
||||
)
|
||||
if (inputSlot !== -1) {
|
||||
const inputName = node.inputs[inputSlot].name
|
||||
if (!selectDocItem(node, inputName)) {
|
||||
return showTooltip(nodeDef.input.getInput(inputName)?.tooltip)
|
||||
}
|
||||
hoveredItemStore.value = { node, type: 'Input', inputName }
|
||||
}
|
||||
|
||||
const outputSlot = canvas.isOverNodeOutput(
|
||||
@@ -116,25 +135,18 @@ const onIdle = () => {
|
||||
[0, 0]
|
||||
)
|
||||
if (outputSlot !== -1) {
|
||||
const outputDef = nodeDef.output.all?.[outputSlot]
|
||||
if (!selectDocItem(node, outputDef?.name)) {
|
||||
return showTooltip(outputDef?.tooltip)
|
||||
}
|
||||
hoveredItemStore.value = { node, type: 'Output', outputSlot }
|
||||
}
|
||||
|
||||
const widget = getHoveredWidget()
|
||||
// Dont show for DOM widgets, these use native browser tooltips as we dont get proper mouse events on these
|
||||
if (widget && !widget.element) {
|
||||
if (!selectDocItem(node, widget.name, widget.value)) {
|
||||
return showTooltip(
|
||||
widget.tooltip ?? nodeDef.input.getInput(widget.name)?.tooltip
|
||||
)
|
||||
}
|
||||
hoveredItemStore.value = { node, type: 'Widget', widget }
|
||||
}
|
||||
}
|
||||
|
||||
const onMouseMove = (e: MouseEvent) => {
|
||||
hideTooltip()
|
||||
clearHovered()
|
||||
clearTimeout(idleTimeout)
|
||||
|
||||
if ((e.target as Node).nodeName !== 'CANVAS') return
|
||||
@@ -142,7 +154,7 @@ const onMouseMove = (e: MouseEvent) => {
|
||||
}
|
||||
|
||||
useEventListener(window, 'mousemove', onMouseMove)
|
||||
useEventListener(window, 'click', hideTooltip)
|
||||
useEventListener(window, 'click', clearHovered)
|
||||
</script>
|
||||
|
||||
<style lang="css" scoped>
|
||||
|
||||
@@ -26,11 +26,17 @@
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
<script setup lang="ts">
|
||||
import { ref, watch } from 'vue'
|
||||
import { app } from '@/scripts/app'
|
||||
import { useCanvasStore } from '@/stores/graphStore'
|
||||
var docElement = ref(null)
|
||||
import { useHoveredItemStore } from '@/stores/graphStore'
|
||||
import { useNodeDefStore } from '@/stores/nodeDefStore'
|
||||
const nodeDefStore = useNodeDefStore()
|
||||
const hoveredItemStore = useHoveredItemStore()
|
||||
const canvasStore = useCanvasStore()
|
||||
|
||||
const docElement = ref(null)
|
||||
|
||||
let def
|
||||
const rawDoc = ref(null)
|
||||
@@ -39,13 +45,6 @@ const title = ref(null)
|
||||
const inputs = ref([])
|
||||
const outputs = ref([])
|
||||
|
||||
export function selectDocItem(node, name, value) {
|
||||
if (node != app?.canvas?.current_node || name == 'DESCRIPTION') {
|
||||
return false
|
||||
}
|
||||
selectHelp(name, value)
|
||||
return true
|
||||
}
|
||||
function setCollapse(el, doCollapse) {
|
||||
if (doCollapse) {
|
||||
el.children[0].children[0].innerHTML = '+'
|
||||
@@ -83,7 +82,7 @@ function collapseOnClick() {
|
||||
setCollapse(this.parentElement, doCollapse)
|
||||
}
|
||||
function selectHelp(name: string, value?: string) {
|
||||
if (!docElement.value) {
|
||||
if (!docElement.value || !name) {
|
||||
return null
|
||||
}
|
||||
if (def[2]?.select) {
|
||||
@@ -170,22 +169,31 @@ function updateNode(node?) {
|
||||
function hasAnyDoc() {
|
||||
return def?.description || inputs.value.length || outputs.value.length
|
||||
}
|
||||
export default {
|
||||
setup() {
|
||||
const canvasStore = useCanvasStore()
|
||||
watch(() => canvasStore?.canvas?.current_node, updateNode)
|
||||
updateNode()
|
||||
return {
|
||||
hasAnyDoc,
|
||||
inputs,
|
||||
outputs,
|
||||
docElement,
|
||||
title,
|
||||
rawDoc,
|
||||
description
|
||||
}
|
||||
watch(hoveredItemStore, (hoveredItem) => {
|
||||
if (!hoveredItem.value) {
|
||||
return
|
||||
}
|
||||
}
|
||||
const item = hoveredItem.value
|
||||
if (item.node.id != app?.canvas?.current_node.id) {
|
||||
return
|
||||
}
|
||||
const nodeDef = nodeDefStore.nodeDefsByName[item.node.type]
|
||||
if (item.type == 'DESCRIPTION') {
|
||||
return
|
||||
} else if (item.type == 'Input') {
|
||||
selectHelp(item.inputName)
|
||||
hoveredItem.value = null
|
||||
} else if (item.type == 'Output') {
|
||||
selectHelp(nodeDef?.output?.all?.[item.outputSlot]?.name)
|
||||
hoveredItem.value = null
|
||||
} else if (item.type == 'Widget') {
|
||||
selectHelp(item.widget.name, item.widget.value)
|
||||
hoveredItem.value = null
|
||||
}
|
||||
})
|
||||
|
||||
watch(() => canvasStore?.canvas?.current_node, updateNode)
|
||||
updateNode()
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { LGraphNode, LGraphGroup, LGraphCanvas } from '@comfyorg/litegraph'
|
||||
import type { ComfyNodeItem } from '@/types/comfy'
|
||||
import { defineStore } from 'pinia'
|
||||
import { shallowRef } from 'vue'
|
||||
|
||||
@@ -10,6 +11,14 @@ export const useTitleEditorStore = defineStore('titleEditor', () => {
|
||||
}
|
||||
})
|
||||
|
||||
export const useHoveredItemStore = defineStore('hoveredItem', () => {
|
||||
const hoveredItem = shallowRef<ComfyNodeItem | null>(null)
|
||||
|
||||
return {
|
||||
hoveredItem
|
||||
}
|
||||
})
|
||||
|
||||
export const useCanvasStore = defineStore('canvas', () => {
|
||||
/**
|
||||
* The LGraphCanvas instance.
|
||||
|
||||
6
src/types/comfy.d.ts
vendored
6
src/types/comfy.d.ts
vendored
@@ -114,6 +114,12 @@ export interface ComfyExtension {
|
||||
[key: string]: any
|
||||
}
|
||||
|
||||
export type ComfyNodeItem =
|
||||
| { node: ComfyObjectInfo; type: 'Title' }
|
||||
| { node: ComfyObjectInfo; type: 'Output'; outputSlot: number }
|
||||
| { node: ComfyObjectInfo; type: 'Input'; inputName: string }
|
||||
| { node: comfyObjectInfo; type: 'Widget'; widget: IWidget }
|
||||
|
||||
export type ComfyObjectInfo = {
|
||||
name: string
|
||||
display_name?: string
|
||||
|
||||
Reference in New Issue
Block a user