Skip to content

Commit f2e25a8

Browse files
Copilotlstein
andcommitted
fix(frontend): make appStarted listener async so image auto-selection works on startup
Co-authored-by: lstein <111189+lstein@users.noreply.github.com>
1 parent c24ee27 commit f2e25a8

1 file changed

Lines changed: 20 additions & 17 deletions

File tree

  • invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners

invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/appStarted.ts

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,27 +12,12 @@ export const appStarted = createAction('app/appStarted');
1212
export const addAppStartedListener = (startAppListening: AppStartListening) => {
1313
startAppListening({
1414
actionCreator: appStarted,
15-
effect: (action, { unsubscribe, cancelActiveListeners, take, getState, dispatch }) => {
15+
effect: async (action, { unsubscribe, cancelActiveListeners, take, getState, dispatch }) => {
1616
// this should only run once
1717
cancelActiveListeners();
1818
unsubscribe();
1919

20-
// ensure an image is selected when we load the first board
21-
take(imagesApi.endpoints.getImageNames.matchFulfilled).then((firstImageLoad) => {
22-
if (firstImageLoad === null) {
23-
// timeout or cancelled
24-
return;
25-
}
26-
const [{ payload }] = firstImageLoad;
27-
const selectedImage = selectLastSelectedItem(getState());
28-
if (selectedImage) {
29-
return;
30-
}
31-
if (payload.image_names[0]) {
32-
dispatch(imageSelected(payload.image_names[0]));
33-
}
34-
});
35-
20+
// Fire patchmatch check without blocking the image-selection logic below
3621
dispatch(appInfoApi.endpoints.getPatchmatchStatus.initiate())
3722
.unwrap()
3823
.then((isPatchmatchAvailable) => {
@@ -43,6 +28,24 @@ export const addAppStartedListener = (startAppListening: AppStartListening) => {
4328
}
4429
})
4530
.catch(noop);
31+
32+
// ensure an image is selected when we load the first board.
33+
// The effect must be async and await take() so that RTK keeps the listener's AbortController
34+
// alive until the query resolves; a synchronous effect causes the controller to be aborted
35+
// immediately after the effect returns, before any network response arrives.
36+
const firstImageLoad = await take(imagesApi.endpoints.getImageNames.matchFulfilled, 5000);
37+
if (firstImageLoad === null) {
38+
// timeout or cancelled
39+
return;
40+
}
41+
const [{ payload }] = firstImageLoad;
42+
const selectedImage = selectLastSelectedItem(getState());
43+
if (selectedImage) {
44+
return;
45+
}
46+
if (payload.image_names[0]) {
47+
dispatch(imageSelected(payload.image_names[0]));
48+
}
4649
},
4750
});
4851
};

0 commit comments

Comments
 (0)