[refactor] Move thumbnail functionality to renderer/core domain (#5586)

Move thumbnail functionality from src/renderer/thumbnail/ to src/renderer/core/thumbnail/
to align with domain-driven design architecture. Thumbnail generation is core rendering
infrastructure and belongs alongside other core renderer utilities.

Changes:
- Move useWorkflowThumbnail.ts and graphThumbnailRenderer.ts to renderer/core/thumbnail/
- Update all import paths in consuming files
- Fix relative imports within moved files

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Christian Byrne
2025-09-15 02:58:35 -07:00
committed by GitHub
parent ca312fd1ea
commit e3bb29ceb8
6 changed files with 9 additions and 8 deletions

View File

@@ -0,0 +1,64 @@
import type { LGraph } from '@/lib/litegraph/src/litegraph'
import { useWorkflowStore } from '@/platform/workflow/management/stores/workflowStore'
import { useCanvasStore } from '@/renderer/core/canvas/canvasStore'
import {
calculateMinimapScale,
calculateNodeBounds
} from '@/renderer/core/spatial/boundsCalculator'
import { renderMinimapToCanvas } from '../../extensions/minimap/minimapCanvasRenderer'
/**
* Create a thumbnail of the current canvas's active graph.
* Used by workflow thumbnail generation.
*/
export function createGraphThumbnail(): string | null {
const canvasStore = useCanvasStore()
const workflowStore = useWorkflowStore()
const graph = workflowStore.activeSubgraph || canvasStore.canvas?.graph
if (!graph || !graph._nodes || graph._nodes.length === 0) {
return null
}
const width = 250
const height = 200
// Calculate bounds using spatial calculator
const bounds = calculateNodeBounds(graph._nodes)
if (!bounds) {
return null
}
const scale = calculateMinimapScale(bounds, width, height)
// Create detached canvas
const canvas = document.createElement('canvas')
canvas.width = width
canvas.height = height
// Render the minimap
renderMinimapToCanvas(canvas, graph as LGraph, {
bounds,
scale,
settings: {
nodeColors: true,
showLinks: false,
showGroups: true,
renderBypass: false,
renderError: false
},
width,
height
})
const dataUrl = canvas.toDataURL()
// Explicit cleanup (optional but good practice)
const ctx = canvas.getContext('2d')
if (ctx) {
ctx.clearRect(0, 0, width, height)
}
return dataUrl
}

View File

@@ -0,0 +1,90 @@
import { ref } from 'vue'
import { ComfyWorkflow } from '@/platform/workflow/management/stores/workflowStore'
import { createGraphThumbnail } from './graphThumbnailRenderer'
// Store thumbnails for each workflow
const workflowThumbnails = ref<Map<string, string>>(new Map())
export const useWorkflowThumbnail = () => {
/**
* Capture a thumbnail of the canvas
*/
const createMinimapPreview = (): Promise<string | null> => {
try {
const thumbnailDataUrl = createGraphThumbnail()
return Promise.resolve(thumbnailDataUrl)
} catch (error) {
console.error('Failed to capture canvas thumbnail:', error)
return Promise.resolve(null)
}
}
/**
* Store a thumbnail for a workflow
*/
const storeThumbnail = async (workflow: ComfyWorkflow) => {
const thumbnail = await createMinimapPreview()
if (thumbnail) {
// Clean up existing thumbnail if it exists
const existingThumbnail = workflowThumbnails.value.get(workflow.key)
if (existingThumbnail) {
URL.revokeObjectURL(existingThumbnail)
}
workflowThumbnails.value.set(workflow.key, thumbnail)
}
}
/**
* Get a thumbnail for a workflow
*/
const getThumbnail = (workflowKey: string): string | undefined => {
return workflowThumbnails.value.get(workflowKey)
}
/**
* Clear a thumbnail for a workflow
*/
const clearThumbnail = (workflowKey: string) => {
const thumbnail = workflowThumbnails.value.get(workflowKey)
if (thumbnail) {
URL.revokeObjectURL(thumbnail)
}
workflowThumbnails.value.delete(workflowKey)
}
/**
* Clear all thumbnails
*/
const clearAllThumbnails = () => {
for (const thumbnail of workflowThumbnails.value.values()) {
URL.revokeObjectURL(thumbnail)
}
workflowThumbnails.value.clear()
}
/**
* Move a thumbnail from one workflow key to another (useful for workflow renaming)
*/
const moveWorkflowThumbnail = (oldKey: string, newKey: string) => {
// Don't do anything if moving to the same key
if (oldKey === newKey) return
const thumbnail = workflowThumbnails.value.get(oldKey)
if (thumbnail) {
workflowThumbnails.value.set(newKey, thumbnail)
workflowThumbnails.value.delete(oldKey)
}
}
return {
createMinimapPreview,
storeThumbnail,
getThumbnail,
clearThumbnail,
clearAllThumbnails,
moveWorkflowThumbnail,
workflowThumbnails
}
}