From 29ee05021336c12f4e64c8d0a75bdb1f9fad6f23 Mon Sep 17 00:00:00 2001 From: Christian Byrne Date: Sat, 1 Nov 2025 23:28:03 -0700 Subject: [PATCH] [feat] Add centerView option to force center template workflows on load MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Template workflows were not centering on view when loaded because they contained saved view position data (extra.ds) from when they were created. This fix adds a centerView option to loadGraphData that forces centering regardless of saved view state. Changes: - Add centerView option to loadGraphData function - Update view restoration logic to prioritize centering when centerView is true - Pass centerView: true when loading template workflows - Add test to verify centerView option is passed correctly 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .../composables/useTemplateWorkflows.ts | 6 ++++-- src/scripts/app.ts | 12 ++++++----- .../composables/useTemplateWorkflows.test.ts | 21 +++++++++++++++++++ 3 files changed, 32 insertions(+), 7 deletions(-) diff --git a/src/platform/workflow/templates/composables/useTemplateWorkflows.ts b/src/platform/workflow/templates/composables/useTemplateWorkflows.ts index d3bea7fb9..5e4a05726 100644 --- a/src/platform/workflow/templates/composables/useTemplateWorkflows.ts +++ b/src/platform/workflow/templates/composables/useTemplateWorkflows.ts @@ -139,7 +139,8 @@ export function useTemplateWorkflows() { dialogStore.closeDialog() await app.loadGraphData(json, true, true, workflowName, { - openSource: 'template' + openSource: 'template', + centerView: true }) return true @@ -162,7 +163,8 @@ export function useTemplateWorkflows() { dialogStore.closeDialog() await app.loadGraphData(json, true, true, workflowName, { - openSource: 'template' + openSource: 'template', + centerView: true }) return true diff --git a/src/scripts/app.ts b/src/scripts/app.ts index a0479b5b2..a10c4183f 100644 --- a/src/scripts/app.ts +++ b/src/scripts/app.ts @@ -1025,13 +1025,15 @@ export class ComfyApp { showMissingModelsDialog?: boolean checkForRerouteMigration?: boolean openSource?: WorkflowOpenSource + centerView?: boolean } = {} ) { const { showMissingNodesDialog = true, showMissingModelsDialog = true, checkForRerouteMigration = false, - openSource + openSource, + centerView = false } = options useWorkflowService().beforeLoadNewGraph() @@ -1179,16 +1181,16 @@ export class ComfyApp { restore_view && useSettingStore().get('Comfy.EnableWorkflowViewRestore') ) { - if (graphData.extra?.ds) { - this.canvas.ds.offset = graphData.extra.ds.offset - this.canvas.ds.scale = graphData.extra.ds.scale - } else { + if (centerView || !graphData.extra?.ds) { // @note: Set view after the graph has been rendered once. fitView uses // boundingRect on nodes to calculate the view bounds, which only become // available after the first render. requestAnimationFrame(() => { useLitegraphService().fitView() }) + } else { + this.canvas.ds.offset = graphData.extra.ds.offset + this.canvas.ds.scale = graphData.extra.ds.scale } } } catch (error) { diff --git a/tests-ui/tests/composables/useTemplateWorkflows.test.ts b/tests-ui/tests/composables/useTemplateWorkflows.test.ts index 8a78b5a4d..bf166f30f 100644 --- a/tests-ui/tests/composables/useTemplateWorkflows.test.ts +++ b/tests-ui/tests/composables/useTemplateWorkflows.test.ts @@ -278,6 +278,27 @@ describe('useTemplateWorkflows', () => { expect(fetch).toHaveBeenCalledWith('mock-file-url/templates/template1.json') }) + it('should load templates with centerView option enabled', async () => { + const { app } = await import('@/scripts/app') + const { loadWorkflowTemplate } = useTemplateWorkflows() + + // Set the store as loaded + mockWorkflowTemplatesStore.isLoaded = true + + // Load a template from the default category + await loadWorkflowTemplate('template1', 'default') + await flushPromises() + + // Verify that loadGraphData was called with centerView: true + expect(app.loadGraphData).toHaveBeenCalledWith( + { workflow: 'data' }, + true, + true, + 'template1', + { openSource: 'template', centerView: true } + ) + }) + it('should handle errors when loading templates', async () => { const { loadWorkflowTemplate, loadingTemplateId } = useTemplateWorkflows()