diff --git a/src/base/common/downloadUtil.ts b/src/base/common/downloadUtil.ts new file mode 100644 index 000000000..307a3e35b --- /dev/null +++ b/src/base/common/downloadUtil.ts @@ -0,0 +1,41 @@ +/** + * Utility functions for downloading files + */ + +// Constants +const DEFAULT_DOWNLOAD_FILENAME = 'download.png' + +/** + * Download a file from a URL by creating a temporary anchor element + * @param url - The URL of the file to download (must be a valid URL string) + * @param filename - Optional filename override (will use URL filename or default if not provided) + * @throws {Error} If the URL is invalid or empty + */ +export const downloadFile = (url: string, filename?: string): void => { + if (!url || typeof url !== 'string' || url.trim().length === 0) { + throw new Error('Invalid URL provided for download') + } + const link = document.createElement('a') + link.href = url + link.download = + filename || extractFilenameFromUrl(url) || DEFAULT_DOWNLOAD_FILENAME + + // Trigger download + document.body.appendChild(link) + link.click() + document.body.removeChild(link) +} + +/** + * Extract filename from a URL's query parameters + * @param url - The URL to extract filename from + * @returns The extracted filename or null if not found + */ +const extractFilenameFromUrl = (url: string): string | null => { + try { + const urlObj = new URL(url, window.location.origin) + return urlObj.searchParams.get('filename') + } catch { + return null + } +} diff --git a/src/composables/graph/useGraphNodeManager.ts b/src/composables/graph/useGraphNodeManager.ts index e91d1f332..e4031fd51 100644 --- a/src/composables/graph/useGraphNodeManager.ts +++ b/src/composables/graph/useGraphNodeManager.ts @@ -53,6 +53,7 @@ export interface VueNodeData { mode: number selected: boolean executing: boolean + subgraphId?: string | null widgets?: SafeWidgetData[] inputs?: unknown[] outputs?: unknown[] @@ -167,6 +168,11 @@ export const useGraphNodeManager = (graph: LGraph): GraphNodeManager => { // Extract safe data from LiteGraph node for Vue consumption const extractVueNodeData = (node: LGraphNode): VueNodeData => { + // Determine subgraph ID - null for root graph, string for subgraphs + const subgraphId = + node.graph && 'id' in node.graph && node.graph !== node.graph.rootGraph + ? String(node.graph.id) + : null // Extract safe widget data const safeWidgets = node.widgets?.map((widget) => { try { @@ -216,6 +222,8 @@ export const useGraphNodeManager = (graph: LGraph): GraphNodeManager => { mode: node.mode || 0, selected: node.selected || false, executing: false, // Will be updated separately based on execution state + subgraphId, + hasErrors: !!node.has_errors, widgets: safeWidgets, inputs: node.inputs ? [...node.inputs] : undefined, diff --git a/src/locales/en/main.json b/src/locales/en/main.json index 0f98ee103..f736ca149 100644 --- a/src/locales/en/main.json +++ b/src/locales/en/main.json @@ -6,6 +6,14 @@ "noWorkflowsFound": "No workflows found.", "comingSoon": "Coming Soon", "download": "Download", + "downloadImage": "Download image", + "editOrMaskImage": "Edit or mask image", + "removeImage": "Remove image", + "viewImageOfTotal": "View image {index} of {total}", + "imagePreview": "Image preview - Use arrow keys to navigate between images", + "errorLoadingImage": "Error loading image", + "failedToDownloadImage": "Failed to download image", + "calculatingDimensions": "Calculating dimensions", "import": "Import", "loadAllFolders": "Load All Folders", "refresh": "Refresh", diff --git a/src/renderer/extensions/vueNodes/components/ImagePreview.vue b/src/renderer/extensions/vueNodes/components/ImagePreview.vue new file mode 100644 index 000000000..120b24657 --- /dev/null +++ b/src/renderer/extensions/vueNodes/components/ImagePreview.vue @@ -0,0 +1,258 @@ + + + diff --git a/src/renderer/extensions/vueNodes/components/LGraphNode.vue b/src/renderer/extensions/vueNodes/components/LGraphNode.vue index aeb0e9a23..2fa74d573 100644 --- a/src/renderer/extensions/vueNodes/components/LGraphNode.vue +++ b/src/renderer/extensions/vueNodes/components/LGraphNode.vue @@ -119,6 +119,7 @@ :node-data="nodeData" :readonly="readonly" :lod-level="lodLevel" + :image-urls="nodeImageUrls" /> @@ -126,7 +127,15 @@ diff --git a/src/renderer/extensions/vueNodes/components/NodeContent.vue b/src/renderer/extensions/vueNodes/components/NodeContent.vue index f99e10917..3df38bdf6 100644 --- a/src/renderer/extensions/vueNodes/components/NodeContent.vue +++ b/src/renderer/extensions/vueNodes/components/NodeContent.vue @@ -5,28 +5,42 @@
- - +