From 7c4486ed29913944939c26846114cf91aab7800b Mon Sep 17 00:00:00 2001 From: Christian Byrne Date: Fri, 20 Feb 2026 00:37:38 -0800 Subject: [PATCH] feat: automatically fit view when loading templates (#8749) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Description When loading a template workflow, always call `fitView()` to ensure the template is properly framed within the viewport. This provides a better initial viewing experience for users. ## Problem Previously, templates with embedded viewport positions (`extra.ds`) would load at arbitrary positions, sometimes showing a blank canvas. Users had to navigate significantly to find the workflow content. ## Solution Added a single condition in `loadGraphData()` to check if `openSource === 'template'` and force `fitView()` when true, bypassing the saved viewport position. This change only affects template loading - normal workflow loading behavior remains unchanged. ## Changes - `src/scripts/app.ts`: Added condition to always call `fitView()` when loading templates ## Testing - Load various templates from the template selector - Verify the workflow is fully visible and centered on load - Verify normal workflow loading still respects saved positions ## Related - Fixes COM-14156 - Related to COM-10087 (Center view on workflow when loading templates - Done) ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-8749-feat-automatically-fit-view-when-loading-templates-3016d73d36508167a63de2ae407de7b8) by [Unito](https://www.unito.io) --- browser_tests/tests/templateFitView.spec.ts | 56 +++++++++++++++++++++ src/scripts/app.ts | 5 +- 2 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 browser_tests/tests/templateFitView.spec.ts diff --git a/browser_tests/tests/templateFitView.spec.ts b/browser_tests/tests/templateFitView.spec.ts new file mode 100644 index 0000000000..933c032285 --- /dev/null +++ b/browser_tests/tests/templateFitView.spec.ts @@ -0,0 +1,56 @@ +import { expect } from '@playwright/test' + +import type { ComfyWorkflowJSON } from '@/platform/workflow/validation/schemas/workflowSchema' + +import { comfyPageFixture as test } from '../fixtures/ComfyPage' + +/** + * Tests that templates are automatically fitted to view when loaded. + * + * When openSource === 'template', fitView() is called to ensure + * templates with saved off-screen viewport positions (extra.ds) + * are always displayed correctly. + */ +test.describe('Template Fit View', { tag: ['@canvas', '@workflow'] }, () => { + test('should automatically fit view when loading a template with off-screen saved position', async ({ + comfyPage + }) => { + await comfyPage.settings.setSetting('Comfy.EnableWorkflowViewRestore', true) + + // Serialize the current default graph, inject an extreme off-screen + // viewport position, then reload it as a template. Without the fix, + // the saved offset [-5000, -5000] would be restored and nodes would + // be invisible. + const viewportState = await comfyPage.page.evaluate(async () => { + const app = window.app! + const workflow = app.graph.serialize() + + workflow.extra = { + ...workflow.extra, + ds: { scale: 1, offset: [-5000, -5000] } + } + + await app.loadGraphData(workflow as ComfyWorkflowJSON, true, true, null, { + openSource: 'template' + }) + + return { + offsetX: app.canvas.ds.offset[0], + offsetY: app.canvas.ds.offset[1], + nodeCount: app.graph._nodes.length + } + }) + + expect(viewportState.nodeCount).toBeGreaterThan(0) + + // fitView() should have overridden the saved [-5000, -5000] offset + expect( + viewportState.offsetX, + 'Viewport X offset should not be the saved off-screen value' + ).not.toBe(-5000) + expect( + viewportState.offsetY, + 'Viewport Y offset should not be the saved off-screen value' + ).not.toBe(-5000) + }) +}) diff --git a/src/scripts/app.ts b/src/scripts/app.ts index febf53ca39..6973114dfd 100644 --- a/src/scripts/app.ts +++ b/src/scripts/app.ts @@ -1250,7 +1250,10 @@ export class ComfyApp { restore_view && useSettingStore().get('Comfy.EnableWorkflowViewRestore') ) { - if (graphData.extra?.ds) { + // Always fit view for templates to ensure they're visible on load + if (openSource === 'template') { + useLitegraphService().fitView() + } else if (graphData.extra?.ds) { this.canvas.ds.offset = graphData.extra.ds.offset this.canvas.ds.scale = graphData.extra.ds.scale