Skip to content

Persist selected board and auto-select most recent image across browser sessions#92

Merged
lstein merged 2 commits intolstein/feature/remember-boardfrom
copilot/enhance-state-restoration
Feb 27, 2026
Merged

Persist selected board and auto-select most recent image across browser sessions#92
lstein merged 2 commits intolstein/feature/remember-boardfrom
copilot/enhance-state-restoration

Conversation

Copy link

Copilot AI commented Feb 26, 2026

Summary

The gallery's selected board (selectedBoardId) was excluded from redux-remember persistence, causing it to reset to "none" (uncategorized) on every page load. Removing it from persistDenylist restores the board on reload.

Additionally, at load time the most recent image in the restored board is automatically selected and displayed in the viewer. This is done by the appStarted listener, which awaits the first getImageNames response and selects payload.image_names[0] (the most recent image, ordered DESC by default) whenever no image is currently selected. Since selection is still in persistDenylist (always resets to [] on load), this reliably fires on every startup.

Bug fix in appStarted listener: The original effect was synchronous — it called take(...).then(...) and returned immediately. RTK listener middleware aborts the listener's internalTaskController as soon as a synchronous effect returns, causing raceWithSignal inside take to reject before any network response arrives, so the .then() callback never fired. The fix makes the effect async and uses await take(imagesApi.endpoints.getImageNames.matchFulfilled, 5000), keeping the controller alive until the query resolves or times out.

Graceful fallback is already handled: the existing addArchivedOrDeletedBoardListener validates the restored selectedBoardId against the listAllBoards response on app init and resets to 'none' if the board has been deleted, archived, or is otherwise unavailable.

- persistDenylist: ['selection', 'selectedBoardId', 'galleryView', 'imageToCompare'],
+ persistDenylist: ['selection', 'galleryView', 'imageToCompare'],
- effect: (action, { unsubscribe, cancelActiveListeners, take, getState, dispatch }) => {
+ effect: async (action, { unsubscribe, cancelActiveListeners, take, getState, dispatch }) => {
    cancelActiveListeners();
    unsubscribe();
-   take(imagesApi.endpoints.getImageNames.matchFulfilled).then((firstImageLoad) => { ... });
+   const firstImageLoad = await take(imagesApi.endpoints.getImageNames.matchFulfilled, 5000);
+   // ... select image from payload

Related Issues / Discussions

QA Instructions

  1. Select any non-default board in the gallery.
  2. Reload the page.
  3. Confirm the same board is still selected.
  4. Confirm the most recent image in that board is selected and displayed in the viewer.
  5. Delete the selected board, then reload — confirm it falls back to uncategorized.
  6. Archive the selected board with "show archived" off, then reload — confirm fallback to uncategorized.

Merge Plan

Checklist

  • The PR has a short but descriptive title, suitable for a changelog
  • Tests added / updated (if applicable)
  • ❗Changes to a redux slice have a corresponding migration
  • Documentation added / updated (if applicable)
  • Updated What's New copy (if doing a release after this PR)
Original prompt

This section details on the original issue you should resolve

<issue_title>[enhancement]: Client state restores last selected board</issue_title>
<issue_description>### Is there an existing issue for this?

  • I have searched the existing issues

Contact Details

No response

What should this feature add?

Much of the InvokeAI client state is saved, including the prompt, generation settings, and state of the various panels. When the user reopens a browser session, this state is largely restored. The exception is the current image board and the particular image that was last in view. The requested feature is to save and restore the current board and image.

Alternatives

No response

Additional Content

No response</issue_description>

Comments on the Issue (you are @copilot in this section)


🔒 GitHub Advanced Security automatically protects Copilot coding agent pull requests. You can protect all pull requests by enabling Advanced Security for your repositories. Learn more about Advanced Security.

Copilot AI changed the title [WIP] Add feature to restore last selected board and image Persist selected board across browser sessions Feb 26, 2026
@lstein lstein marked this pull request as ready for review February 26, 2026 05:07
@lstein lstein self-requested a review as a code owner February 26, 2026 05:07
Copy link
Owner

@lstein lstein left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The previously-selected image board is correctly restored. Thank you.

At load time, would it be possible to select the most recent image in the current image board so that it displays in the viewer? This would greatly improve the UX.

Copy link
Author

Copilot AI commented Feb 27, 2026

The previously-selected image board is correctly restored. Thank you.

At load time, would it be possible to select the most recent image in the current image board so that it displays in the viewer...

Yes — this is already handled by the existing appStarted listener in combination with my change. Here's what happens at load time:

  1. selectedBoardId is restored from server storage (my change, commit 8bd4b27)
  2. The gallery queries getImageNames for the restored board
  3. The appStarted listener (appStarted.ts) waits for the first getImageNames.matchFulfilled response — since selection is still reset to [] on every load, selectLastSelectedItem returns null, so it always dispatches imageSelected(payload.image_names[0])
  4. payload.image_names[0] is the most recent image in the restored board (images are ordered DESC by default, starred-first)

No additional code changes are needed — the appStarted listener was already designed to select the first image on load, and with the board ID now persisted, it naturally targets the restored board.

Copilot AI changed the title Persist selected board across browser sessions Persist selected board and auto-select most recent image across browser sessions Feb 27, 2026
@lstein
Copy link
Owner

lstein commented Feb 27, 2026

@copilot In practice the automatic selection of the most recent image is not working. The correct gallery is being selected, but the Viewer window always says "No Image Selected." Could you recheck the code and your reasoning?

Copy link
Author

Copilot AI commented Feb 27, 2026

@copilot In practice the automatic selection of the most recent image is not working. The correct gallery is being selected, but the Viewer window always says "No Image Selected." C...

Found and fixed the root cause (commit b0216e5).

The appStarted listener effect was synchronous. It called take(...).then(...) and immediately returned. RTK's notifyListener then ran its finally block, which calls abortControllerWithReason(internalTaskController, listenerCompleted) — aborting the controller before any network response could arrive. This caused raceWithSignal inside take to reject, so the .then() callback never fired and imageSelected was never dispatched.

The fix makes the effect async and uses await take(imagesApi.endpoints.getImageNames.matchFulfilled, 5000). This keeps the internalTaskController alive until the getImageNames query resolves (with a 5 s safety timeout), at which point the most recent image in the restored board is dispatched as the selected image. The patchmatch status check is moved before the await so it still fires immediately.

Copy link
Owner

@lstein lstein left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Works as advertised.

Copilot AI and others added 2 commits February 26, 2026 19:41
Co-authored-by: lstein <111189+lstein@users.noreply.github.com>
… works on startup

Co-authored-by: lstein <111189+lstein@users.noreply.github.com>
@lstein lstein force-pushed the copilot/enhance-state-restoration branch from b0216e5 to f2e25a8 Compare February 27, 2026 00:41
@lstein lstein merged commit 374effb into lstein/feature/remember-board Feb 27, 2026
13 checks passed
@lstein lstein deleted the copilot/enhance-state-restoration branch February 27, 2026 00:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants