From ca8d7aefbdf900173b733faac4ffeb894bf26a09 Mon Sep 17 00:00:00 2001 From: Josh Corbett Date: Thu, 15 Oct 2026 14:35:01 -0600 Subject: [PATCH] fix(preview): keep in-progress preview off after the user disables it A gallery selection made while the preview was explicitly off recorded a live-follow pause, so the next Invoke turned the preview back on. Selections now pause live-follow only when it is on or already paused. --- .../src/workbench/workbenchState.test.ts | 20 +++++++++++ .../webv2/src/workbench/workbenchState.ts | 36 +++++++++++-------- 2 files changed, 41 insertions(+), 15 deletions(-) diff --git a/invokeai/frontend/webv2/src/workbench/workbenchState.test.ts b/invokeai/frontend/webv2/src/workbench/workbenchState.test.ts index c9db763eea2..49906ed0d8f 100644 --- a/invokeai/frontend/webv2/src/workbench/workbenchState.test.ts +++ b/invokeai/frontend/webv2/src/workbench/workbenchState.test.ts @@ -5237,6 +5237,26 @@ describe('workbenchReducer Phase 5 generation flow', () => { expect(getActiveProject(state).settings.showProgressImagesInViewer).toBe(false); }); + it('keeps an explicit live-follow opt-out through later Gallery selections and submissions', () => { + let state = primeGenerate(); + state = workbenchReducer(state, { destination: 'gallery', type: 'setInvocationDestination' }); + state = workbenchReducer(state, { + settings: { showProgressImagesInViewer: false }, + type: 'setActiveProjectSettings', + }); + state = workbenchReducer(state, { item: createGalleryImageItem('selected.png'), type: 'selectGalleryItem' }); + state = workbenchReducer(state, { + image: createGalleryImageItem('compare.png'), + type: 'setGalleryCompareImage', + }); + + state = submitGenerate(state); + + const project = getActiveProject(state); + expect(project.settings.showProgressImagesInViewer).toBe(false); + expect(getProjectWidgetValues(project, 'gallery').selectedImageName).toBe('image:selected.png'); + }); + it('lifts the selection pause when live-follow is toggled explicitly', () => { let state = createInitialWorkbenchState(); state = workbenchReducer(state, { item: createGalleryImageItem('selected.png'), type: 'selectGalleryItem' }); diff --git a/invokeai/frontend/webv2/src/workbench/workbenchState.ts b/invokeai/frontend/webv2/src/workbench/workbenchState.ts index 4a233f8afb0..8402cd354e9 100644 --- a/invokeai/frontend/webv2/src/workbench/workbenchState.ts +++ b/invokeai/frontend/webv2/src/workbench/workbenchState.ts @@ -3102,29 +3102,35 @@ const reconcileDeletedGalleryBoard = ( return didChangeQueue ? { ...withBoardReferencesCleared, projects } : withBoardReferencesCleared; }; -/** A deliberate selection pauses live-follow; only generations submitted after that selection may take the preview. */ +const getLiveFollowPausedAt = (project: Project): string | null => { + const pausedAt = getWidgetValues(project, 'gallery').liveFollowPausedAt; + + return typeof pausedAt === 'string' ? pausedAt : null; +}; + +/** + * A deliberate selection pauses live-follow; only generations submitted after that selection may take the preview. + * With live-follow explicitly off there is nothing to pause, and a pause recorded then would let the next submission + * turn it back on. + */ const updateGalleryValuesAndPauseLiveFollow = ( state: WorkbenchState, getValues: (values: Record) => Record, projectId = state.activeProjectId ): WorkbenchState => updateProjectById(state, projectId, (project) => - updateProjectWidgetValues( - { - ...project, - settings: { ...project.settings, showProgressImagesInViewer: false }, - }, - 'gallery', - (values) => ({ ...getValues(values), liveFollowPausedAt: now() }) - ) + !project.settings.showProgressImagesInViewer && getLiveFollowPausedAt(project) === null + ? updateProjectWidgetValues(project, 'gallery', getValues) + : updateProjectWidgetValues( + { + ...project, + settings: { ...project.settings, showProgressImagesInViewer: false }, + }, + 'gallery', + (values) => ({ ...getValues(values), liveFollowPausedAt: now() }) + ) ); -const getLiveFollowPausedAt = (project: Project): string | null => { - const pausedAt = getWidgetValues(project, 'gallery').liveFollowPausedAt; - - return typeof pausedAt === 'string' ? pausedAt : null; -}; - /** Submission resumes selection-paused live-follow, but preserves an explicit opt-out. */ const shouldResumeLiveFollowOnSubmit = (project: Project): boolean => !project.settings.showProgressImagesInViewer && getLiveFollowPausedAt(project) !== null;