Skip to content

Commit

Permalink
feat(ui): handle edge cases when archiving/deleting boards
Browse files Browse the repository at this point in the history
If the currently selected or auto-add board is archived or deleted, we should reset them. There are some edge cases taht weren't handled in the previous implementation.

All handling of this logic is moved to the (renamed) listener.
  • Loading branch information
psychedelicious committed Jun 27, 2024
1 parent 037b17e commit 822017b
Show file tree
Hide file tree
Showing 7 changed files with 52 additions and 65 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ import { addUpscaleRequestedListener } from 'app/store/middleware/listenerMiddle
import { addWorkflowLoadRequestedListener } from 'app/store/middleware/listenerMiddleware/listeners/workflowLoadRequested';
import type { AppDispatch, RootState } from 'app/store/store';

import { addCheckAutoAddBoardVisibleListener } from './listeners/checkAutoAddBoardVisible';
import { addArchivedOrDeletedBoardListener } from './listeners/addArchivedOrDeletedBoardListener';

export const listenerMiddleware = createListenerMiddleware();

Expand Down Expand Up @@ -118,7 +118,7 @@ addControlNetAutoProcessListener(startAppListening);
addImageAddedToBoardFulfilledListener(startAppListening);
addImageRemovedFromBoardFulfilledListener(startAppListening);
addBoardIdSelectedListener(startAppListening);
addCheckAutoAddBoardVisibleListener(startAppListening);
addArchivedOrDeletedBoardListener(startAppListening);

// Node schemas
addGetOpenAPISchemaListener(startAppListening);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { isAnyOf } from '@reduxjs/toolkit';
import type { AppStartListening } from 'app/store/middleware/listenerMiddleware';
import { selectListBoardsQueryArgs } from 'features/gallery/store/gallerySelectors';
import {
autoAddBoardIdChanged,
boardIdSelected,
galleryViewChanged,
shouldShowArchivedBoardsChanged,
} from 'features/gallery/store/gallerySlice';
import { boardsApi } from 'services/api/endpoints/boards';
import { imagesApi } from 'services/api/endpoints/images';

export const addArchivedOrDeletedBoardListener = (startAppListening: AppStartListening) => {
startAppListening({
matcher: isAnyOf(
// Updating a board may change its archived status
boardsApi.endpoints.updateBoard.matchFulfilled,
// If the selected/auto-add board was deleted from a different session, we'll only know during the list request,
boardsApi.endpoints.listAllBoards.matchFulfilled,
// If a board is deleted, we'll need to reset the auto-add board
imagesApi.endpoints.deleteBoard.matchFulfilled,
imagesApi.endpoints.deleteBoardAndImages.matchFulfilled,
// When we change the visibility of archived boards, we may need to reset the auto-add board
shouldShowArchivedBoardsChanged
),
effect: async (action, { dispatch, getState }) => {
/**
* The auto-add board shouldn't be set to an archived board or deleted board. When we archive a board, delete
* a board, or change a the archived board visibility flag, we may need to reset the auto-add board.
*/

const state = getState();
const queryArgs = selectListBoardsQueryArgs(state);
const queryResult = boardsApi.endpoints.listAllBoards.select(queryArgs)(state);
const autoAddBoardId = state.gallery.autoAddBoardId;

if (!queryResult.data) {
return;
}

if (!queryResult.data.find((board) => board.board_id === autoAddBoardId)) {
dispatch(autoAddBoardIdChanged('none'));
dispatch(boardIdSelected({ boardId: 'none' }));
dispatch(galleryViewChanged('images'));
}
},
});
};

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import type { ContextMenuProps } from '@invoke-ai/ui-library';
import { ContextMenu, MenuGroup, MenuItem, MenuList } from '@invoke-ai/ui-library';
import { createSelector } from '@reduxjs/toolkit';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { checkAutoAddBoardVisible } from 'features/gallery/store/actions';
import { autoAddBoardIdChanged, selectGallerySlice } from 'features/gallery/store/gallerySlice';
import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus';
import { toast } from 'features/toast/toast';
Expand Down Expand Up @@ -53,14 +52,13 @@ const BoardContextMenu = ({ board, setBoardToDelete, children }: Props) => {
board_id: board.board_id,
changes: { archived: true },
}).unwrap();
dispatch(checkAutoAddBoardVisible());
} catch (error) {
toast({
status: 'error',
title: 'Unable to archive board',
});
}
}, [board.board_id, updateBoard, dispatch]);
}, [board.board_id, updateBoard]);

const handleUnarchive = useCallback(() => {
updateBoard({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import {
Switch,
} from '@invoke-ai/ui-library';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { checkAutoAddBoardVisible } from 'features/gallery/store/actions';
import {
alwaysShowImageSizeBadgeChanged,
autoAssignBoardOnClickChanged,
Expand Down Expand Up @@ -69,7 +68,6 @@ const GallerySettingsPopover = () => {
const handleChangeShouldShowArchivedBoardsChanged = useCallback(
(e: ChangeEvent<HTMLInputElement>) => {
dispatch(shouldShowArchivedBoardsChanged(e.target.checked));
dispatch(checkAutoAddBoardVisible());
},
[dispatch]
);
Expand Down
2 changes: 0 additions & 2 deletions invokeai/frontend/web/src/features/gallery/store/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,3 @@ export const sentImageToCanvas = createAction('gallery/sentImageToCanvas');
export const sentImageToImg2Img = createAction('gallery/sentImageToImg2Img');

export const imageDownloaded = createAction('gallery/imageDownloaded');

export const checkAutoAddBoardVisible = createAction('gallery/checkAutoAddBoardVisible');
32 changes: 1 addition & 31 deletions invokeai/frontend/web/src/features/gallery/store/gallerySlice.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import type { PayloadAction } from '@reduxjs/toolkit';
import { createSlice, isAnyOf } from '@reduxjs/toolkit';
import { createSlice } from '@reduxjs/toolkit';
import type { PersistConfig, RootState } from 'app/store/store';
import { uniqBy } from 'lodash-es';
import { boardsApi } from 'services/api/endpoints/boards';
import { imagesApi } from 'services/api/endpoints/images';
import type { ImageDTO } from 'services/api/types';

import type { BoardId, ComparisonMode, GalleryState, GalleryView } from './types';
Expand Down Expand Up @@ -115,29 +113,6 @@ export const gallerySlice = createSlice({
state.shouldShowArchivedBoards = action.payload;
},
},
extraReducers: (builder) => {
builder.addMatcher(isAnyBoardDeleted, (state, action) => {
const deletedBoardId = action.meta.arg.originalArgs;
if (deletedBoardId === state.selectedBoardId) {
state.selectedBoardId = 'none';
state.galleryView = 'images';
}
if (deletedBoardId === state.autoAddBoardId) {
state.autoAddBoardId = 'none';
}
});
builder.addMatcher(boardsApi.endpoints.listAllBoards.matchFulfilled, (state, action) => {
const boards = action.payload;

if (!state.autoAddBoardId) {
return;
}

if (!boards.map((b) => b.board_id).includes(state.autoAddBoardId)) {
state.autoAddBoardId = 'none';
}
});
},
});

export const {
Expand All @@ -162,11 +137,6 @@ export const {
shouldShowArchivedBoardsChanged,
} = gallerySlice.actions;

const isAnyBoardDeleted = isAnyOf(
imagesApi.endpoints.deleteBoard.matchFulfilled,
imagesApi.endpoints.deleteBoardAndImages.matchFulfilled
);

export const selectGallerySlice = (state: RootState) => state.gallery;

/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
Expand Down

0 comments on commit 822017b

Please sign in to comment.