diff --git a/invokeai/app/api/routers/boards.py b/invokeai/app/api/routers/boards.py
index 77d6956033..926c0f7fd2 100644
--- a/invokeai/app/api/routers/boards.py
+++ b/invokeai/app/api/routers/boards.py
@@ -31,6 +31,7 @@ class DeleteBoardResult(BaseModel):
)
async def create_board(
board_name: str = Query(description="The name of the board to create"),
+ is_private: bool = Query(default=False, description="Whether the board is private"),
) -> BoardDTO:
"""Creates a board"""
try:
diff --git a/invokeai/app/services/board_records/board_records_common.py b/invokeai/app/services/board_records/board_records_common.py
index d763480a9f..0dda8a8b6b 100644
--- a/invokeai/app/services/board_records/board_records_common.py
+++ b/invokeai/app/services/board_records/board_records_common.py
@@ -24,6 +24,8 @@ class BoardRecord(BaseModelExcludeNull):
"""The name of the cover image of the board."""
archived: bool = Field(description="Whether or not the board is archived.")
"""Whether or not the board is archived."""
+ is_private: Optional[bool] = Field(default=None, description="Whether the board is private.")
+ """Whether the board is private."""
def deserialize_board_record(board_dict: dict) -> BoardRecord:
@@ -38,6 +40,7 @@ def deserialize_board_record(board_dict: dict) -> BoardRecord:
updated_at = board_dict.get("updated_at", get_iso_timestamp())
deleted_at = board_dict.get("deleted_at", get_iso_timestamp())
archived = board_dict.get("archived", False)
+ is_private = board_dict.get("is_private", False)
return BoardRecord(
board_id=board_id,
@@ -47,6 +50,7 @@ def deserialize_board_record(board_dict: dict) -> BoardRecord:
updated_at=updated_at,
deleted_at=deleted_at,
archived=archived,
+ is_private=is_private,
)
diff --git a/invokeai/frontend/web/public/locales/en.json b/invokeai/frontend/web/public/locales/en.json
index dc09ac313f..4b102d6cf3 100644
--- a/invokeai/frontend/web/public/locales/en.json
+++ b/invokeai/frontend/web/public/locales/en.json
@@ -17,9 +17,12 @@
},
"boards": {
"addBoard": "Add Board",
+ "addPrivateBoard": "Add Private Board",
+ "addSharedBoard": "Add Shared Board",
"archiveBoard": "Archive Board",
"archived": "Archived",
"autoAddBoard": "Auto-Add Board",
+ "boards": "Boards",
"selectedForAutoAdd": "Selected for Auto-Add",
"bottomMessage": "Deleting this board and its images will reset any features currently using them.",
"cancel": "Cancel",
@@ -36,8 +39,10 @@
"movingImagesToBoard_other": "Moving {{count}} images to board:",
"myBoard": "My Board",
"noMatching": "No matching Boards",
+ "private": "Private",
"searchBoard": "Search Boards...",
"selectBoard": "Select a Board",
+ "shared": "Shared",
"topMessage": "This board contains images used in the following features:",
"unarchiveBoard": "Unarchive Board",
"uncategorized": "Uncategorized",
diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/addArchivedOrDeletedBoardListener.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/addArchivedOrDeletedBoardListener.ts
index 0915929245..c569a6e36d 100644
--- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/addArchivedOrDeletedBoardListener.ts
+++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/addArchivedOrDeletedBoardListener.ts
@@ -15,8 +15,6 @@ export const addArchivedOrDeletedBoardListener = (startAppListening: AppStartLis
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,
diff --git a/invokeai/frontend/web/src/app/types/invokeai.ts b/invokeai/frontend/web/src/app/types/invokeai.ts
index 21636ada49..6d7416d95d 100644
--- a/invokeai/frontend/web/src/app/types/invokeai.ts
+++ b/invokeai/frontend/web/src/app/types/invokeai.ts
@@ -65,6 +65,7 @@ export type AppConfig = {
*/
shouldUpdateImagesOnConnect: boolean;
shouldFetchMetadataFromApi: boolean;
+ allowPrivateBoards: boolean;
disabledTabs: InvokeTabName[];
disabledFeatures: AppFeature[];
disabledSDFeatures: SDFeature[];
diff --git a/invokeai/frontend/web/src/common/components/IAIDropOverlay.tsx b/invokeai/frontend/web/src/common/components/IAIDropOverlay.tsx
index cd3e0cbee1..51e5583bc6 100644
--- a/invokeai/frontend/web/src/common/components/IAIDropOverlay.tsx
+++ b/invokeai/frontend/web/src/common/components/IAIDropOverlay.tsx
@@ -52,8 +52,8 @@ const IAIDropOverlay = (props: Props) => {
bottom={0.5}
opacity={1}
borderWidth={2}
- borderColor={isOver ? 'base.50' : 'base.300'}
- borderRadius="lg"
+ borderColor={isOver ? 'base.300' : 'base.500'}
+ borderRadius="base"
borderStyle="dashed"
transitionProperty="common"
transitionDuration="0.1s"
diff --git a/invokeai/frontend/web/src/features/gallery/components/Boards/AutoAddBadge.tsx b/invokeai/frontend/web/src/features/gallery/components/Boards/AutoAddBadge.tsx
new file mode 100644
index 0000000000..a8b1f9f4fb
--- /dev/null
+++ b/invokeai/frontend/web/src/features/gallery/components/Boards/AutoAddBadge.tsx
@@ -0,0 +1,14 @@
+import { Badge } from '@invoke-ai/ui-library';
+import { memo } from 'react';
+import { useTranslation } from 'react-i18next';
+
+export const AutoAddBadge = memo(() => {
+ const { t } = useTranslation();
+ return (
+
+ {t('common.auto')}
+
+ );
+});
+
+AutoAddBadge.displayName = 'AutoAddBadge';
diff --git a/invokeai/frontend/web/src/features/gallery/components/Boards/AutoAddIcon.tsx b/invokeai/frontend/web/src/features/gallery/components/Boards/AutoAddIcon.tsx
deleted file mode 100644
index 9dd6a59c49..0000000000
--- a/invokeai/frontend/web/src/features/gallery/components/Boards/AutoAddIcon.tsx
+++ /dev/null
@@ -1,16 +0,0 @@
-import { Badge, Flex } from '@invoke-ai/ui-library';
-import { memo } from 'react';
-import { useTranslation } from 'react-i18next';
-
-const AutoAddIcon = () => {
- const { t } = useTranslation();
- return (
-
-
- {t('common.auto')}
-
-
- );
-};
-
-export default memo(AutoAddIcon);
diff --git a/invokeai/frontend/web/src/features/gallery/components/Boards/BoardsList/AddBoardButton.tsx b/invokeai/frontend/web/src/features/gallery/components/Boards/BoardsList/AddBoardButton.tsx
index 5cd4d001f4..c6ddb85daa 100644
--- a/invokeai/frontend/web/src/features/gallery/components/Boards/BoardsList/AddBoardButton.tsx
+++ b/invokeai/frontend/web/src/features/gallery/components/Boards/BoardsList/AddBoardButton.tsx
@@ -1,26 +1,48 @@
import { IconButton } from '@invoke-ai/ui-library';
-import { memo, useCallback } from 'react';
+import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
+import { boardIdSelected } from 'features/gallery/store/gallerySlice';
+import { memo, useCallback, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import { PiPlusBold } from 'react-icons/pi';
import { useCreateBoardMutation } from 'services/api/endpoints/boards';
-const AddBoardButton = () => {
+type Props = {
+ isPrivateBoard: boolean;
+};
+
+const AddBoardButton = ({ isPrivateBoard }: Props) => {
const { t } = useTranslation();
+ const dispatch = useAppDispatch();
+ const allowPrivateBoards = useAppSelector((s) => s.config.allowPrivateBoards);
const [createBoard, { isLoading }] = useCreateBoardMutation();
- const DEFAULT_BOARD_NAME = t('boards.myBoard');
- const handleCreateBoard = useCallback(() => {
- createBoard(DEFAULT_BOARD_NAME);
- }, [createBoard, DEFAULT_BOARD_NAME]);
+ const label = useMemo(() => {
+ if (!allowPrivateBoards) {
+ return t('boards.addBoard');
+ }
+ if (isPrivateBoard) {
+ return t('boards.addPrivateBoard');
+ }
+ return t('boards.addSharedBoard');
+ }, [allowPrivateBoards, isPrivateBoard, t]);
+ const handleCreateBoard = useCallback(async () => {
+ try {
+ const board = await createBoard({ board_name: t('boards.myBoard'), is_private: isPrivateBoard }).unwrap();
+ dispatch(boardIdSelected({ boardId: board.board_id }));
+ } catch {
+ //no-op
+ }
+ }, [t, createBoard, isPrivateBoard, dispatch]);
return (
}
isLoading={isLoading}
- tooltip={t('boards.addBoard')}
- aria-label={t('boards.addBoard')}
+ tooltip={label}
+ aria-label={label}
onClick={handleCreateBoard}
- size="sm"
+ size="md"
data-testid="add-board-button"
+ variant="ghost"
/>
);
};
diff --git a/invokeai/frontend/web/src/features/gallery/components/Boards/BoardsList/BoardsList.tsx b/invokeai/frontend/web/src/features/gallery/components/Boards/BoardsList/BoardsList.tsx
index e47edd21fc..6f37dbcdb5 100644
--- a/invokeai/frontend/web/src/features/gallery/components/Boards/BoardsList/BoardsList.tsx
+++ b/invokeai/frontend/web/src/features/gallery/components/Boards/BoardsList/BoardsList.tsx
@@ -1,11 +1,15 @@
-import { Collapse, Flex, Grid, GridItem } from '@invoke-ai/ui-library';
+import { Collapse, Flex, Icon, Text, useDisclosure } from '@invoke-ai/ui-library';
+import { EMPTY_ARRAY } from 'app/store/constants';
import { useAppSelector } from 'app/store/storeHooks';
import { overlayScrollbarsParams } from 'common/components/OverlayScrollbars/constants';
import DeleteBoardModal from 'features/gallery/components/Boards/DeleteBoardModal';
+import GallerySettingsPopover from 'features/gallery/components/GallerySettingsPopover/GallerySettingsPopover';
import { selectListBoardsQueryArgs } from 'features/gallery/store/gallerySelectors';
import { OverlayScrollbarsComponent } from 'overlayscrollbars-react';
import type { CSSProperties } from 'react';
-import { memo, useState } from 'react';
+import { memo, useMemo, useState } from 'react';
+import { useTranslation } from 'react-i18next';
+import { PiCaretUpBold } from 'react-icons/pi';
import { useListAllBoardsQuery } from 'services/api/endpoints/boards';
import type { BoardDTO } from 'services/api/types';
@@ -19,56 +23,112 @@ const overlayScrollbarsStyles: CSSProperties = {
width: '100%',
};
-type Props = {
- isOpen: boolean;
-};
-
-const BoardsList = (props: Props) => {
- const { isOpen } = props;
+const BoardsList = () => {
const selectedBoardId = useAppSelector((s) => s.gallery.selectedBoardId);
const boardSearchText = useAppSelector((s) => s.gallery.boardSearchText);
+ const allowPrivateBoards = useAppSelector((s) => s.config.allowPrivateBoards);
const queryArgs = useAppSelector(selectListBoardsQueryArgs);
const { data: boards } = useListAllBoardsQuery(queryArgs);
- const filteredBoards = boardSearchText
- ? boards?.filter((board) => board.board_name.toLowerCase().includes(boardSearchText.toLowerCase()))
- : boards;
const [boardToDelete, setBoardToDelete] = useState();
+ const privateBoardsDisclosure = useDisclosure({ defaultIsOpen: false });
+ const sharedBoardsDisclosure = useDisclosure({ defaultIsOpen: false });
+ const { t } = useTranslation();
+
+ const { filteredPrivateBoards, filteredSharedBoards } = useMemo(() => {
+ const filteredBoards = boardSearchText
+ ? boards?.filter((board) => board.board_name.toLowerCase().includes(boardSearchText.toLowerCase()))
+ : boards;
+ const filteredPrivateBoards = filteredBoards?.filter((board) => board.is_private) ?? EMPTY_ARRAY;
+ const filteredSharedBoards = filteredBoards?.filter((board) => !board.is_private) ?? EMPTY_ARRAY;
+ return { filteredPrivateBoards, filteredSharedBoards };
+ }, [boardSearchText, boards]);
return (
<>
-
-
-
-
-
-
-
-
-
-
-
- {filteredBoards &&
- filteredBoards.map((board, index) => (
-
+
+
+
+
+
+ {allowPrivateBoards && (
+ <>
+
+
+
+
+ {t('boards.private')}
+
+
+
+
+
+
+
+ {allowPrivateBoards && }
+ {filteredPrivateBoards.map((board) => (
-
- ))}
-
-
+ ))}
+
+
+
+ >
+ )}
+
+
+
+
+ {allowPrivateBoards ? t('boards.shared') : t('boards.boards')}
+
+
+
-
+
+
+
+ {!allowPrivateBoards && }
+ {filteredSharedBoards.map((board) => (
+
+ ))}
+
+
+
+
>
);
};
-
export default memo(BoardsList);
diff --git a/invokeai/frontend/web/src/features/gallery/components/Boards/BoardsList/GalleryBoard.tsx b/invokeai/frontend/web/src/features/gallery/components/Boards/BoardsList/GalleryBoard.tsx
index ad40fdbf6a..32ed84558c 100644
--- a/invokeai/frontend/web/src/features/gallery/components/Boards/BoardsList/GalleryBoard.tsx
+++ b/invokeai/frontend/web/src/features/gallery/components/Boards/BoardsList/GalleryBoard.tsx
@@ -1,36 +1,41 @@
import type { SystemStyleObject } from '@invoke-ai/ui-library';
-import { Box, Editable, EditableInput, EditablePreview, Flex, Icon, Image, Text, Tooltip } from '@invoke-ai/ui-library';
-import { createSelector } from '@reduxjs/toolkit';
+import {
+ Editable,
+ EditableInput,
+ EditablePreview,
+ Flex,
+ Icon,
+ Image,
+ Text,
+ Tooltip,
+ useDisclosure,
+} from '@invoke-ai/ui-library';
import { skipToken } from '@reduxjs/toolkit/query';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import IAIDroppable from 'common/components/IAIDroppable';
-import SelectionOverlay from 'common/components/SelectionOverlay';
import type { AddToBoardDropData } from 'features/dnd/types';
-import AutoAddIcon from 'features/gallery/components/Boards/AutoAddIcon';
+import { AutoAddBadge } from 'features/gallery/components/Boards/AutoAddBadge';
import BoardContextMenu from 'features/gallery/components/Boards/BoardContextMenu';
import { BoardTotalsTooltip } from 'features/gallery/components/Boards/BoardsList/BoardTotalsTooltip';
-import { autoAddBoardIdChanged, boardIdSelected, selectGallerySlice } from 'features/gallery/store/gallerySlice';
+import { autoAddBoardIdChanged, boardIdSelected } from 'features/gallery/store/gallerySlice';
import { memo, useCallback, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
-import { PiArchiveBold, PiImagesSquare } from 'react-icons/pi';
+import { PiArchiveBold, PiImageSquare } from 'react-icons/pi';
import { useUpdateBoardMutation } from 'services/api/endpoints/boards';
import { useGetImageDTOQuery } from 'services/api/endpoints/images';
import type { BoardDTO } from 'services/api/types';
const editableInputStyles: SystemStyleObject = {
p: 0,
+ fontSize: 'md',
+ w: '100%',
_focusVisible: {
p: 0,
- textAlign: 'center',
},
};
-const ArchivedIcon = () => {
- return (
-
-
-
- );
+const _hover: SystemStyleObject = {
+ bg: 'base.800',
};
interface GalleryBoardProps {
@@ -42,71 +47,53 @@ interface GalleryBoardProps {
const GalleryBoard = ({ board, isSelected, setBoardToDelete }: GalleryBoardProps) => {
const dispatch = useAppDispatch();
const { t } = useTranslation();
+ const autoAddBoardId = useAppSelector((s) => s.gallery.autoAddBoardId);
const autoAssignBoardOnClick = useAppSelector((s) => s.gallery.autoAssignBoardOnClick);
- const selectIsSelectedForAutoAdd = useMemo(
- () => createSelector(selectGallerySlice, (gallery) => board.board_id === gallery.autoAddBoardId),
- [board.board_id]
- );
-
- const isSelectedForAutoAdd = useAppSelector(selectIsSelectedForAutoAdd);
- const [isHovered, setIsHovered] = useState(false);
- const handleMouseOver = useCallback(() => {
- setIsHovered(true);
- }, []);
- const handleMouseOut = useCallback(() => {
- setIsHovered(false);
- }, []);
-
- const { currentData: coverImage } = useGetImageDTOQuery(board.cover_image_name ?? skipToken);
-
- const { board_name, board_id } = board;
- const [localBoardName, setLocalBoardName] = useState(board_name);
+ const editingDisclosure = useDisclosure();
+ const [localBoardName, setLocalBoardName] = useState(board.board_name);
const handleSelectBoard = useCallback(() => {
- dispatch(boardIdSelected({ boardId: board_id }));
+ dispatch(boardIdSelected({ boardId: board.board_id }));
if (autoAssignBoardOnClick) {
- dispatch(autoAddBoardIdChanged(board_id));
+ dispatch(autoAddBoardIdChanged(board.board_id));
}
- }, [board_id, autoAssignBoardOnClick, dispatch]);
+ }, [dispatch, board.board_id, autoAssignBoardOnClick]);
const [updateBoard, { isLoading: isUpdateBoardLoading }] = useUpdateBoardMutation();
const droppableData: AddToBoardDropData = useMemo(
() => ({
- id: board_id,
+ id: board.board_id,
actionType: 'ADD_TO_BOARD',
- context: { boardId: board_id },
+ context: { boardId: board.board_id },
}),
- [board_id]
+ [board.board_id]
);
const handleSubmit = useCallback(
async (newBoardName: string) => {
- // empty strings are not allowed
if (!newBoardName.trim()) {
- setLocalBoardName(board_name);
- return;
- }
+ // empty strings are not allowed
+ setLocalBoardName(board.board_name);
+ } else if (newBoardName === board.board_name) {
+ // don't updated the board name if it hasn't changed
+ } else {
+ try {
+ const { board_name } = await updateBoard({
+ board_id: board.board_id,
+ changes: { board_name: newBoardName },
+ }).unwrap();
- // don't updated the board name if it hasn't changed
- if (newBoardName === board_name) {
- return;
- }
-
- try {
- const { board_name } = await updateBoard({
- board_id,
- changes: { board_name: newBoardName },
- }).unwrap();
-
- // update local state
- setLocalBoardName(board_name);
- } catch {
- // revert on error
- setLocalBoardName(board_name);
+ // update local state
+ setLocalBoardName(board_name);
+ } catch {
+ // revert on error
+ setLocalBoardName(board.board_name);
+ }
}
+ editingDisclosure.onClose();
},
- [board_id, board_name, updateBoard]
+ [board.board_id, board.board_name, editingDisclosure, updateBoard]
);
const handleChange = useCallback((newBoardName: string) => {
@@ -114,98 +101,91 @@ const GalleryBoard = ({ board, isSelected, setBoardToDelete }: GalleryBoardProps
}, []);
return (
-
-
-
- {(ref) => (
- }
- openDelay={1000}
+
+ {(ref) => (
+ }
+ openDelay={1000}
+ >
+
+
+
-
- {board.archived && }
- {coverImage?.thumbnail_url ? (
-
- ) : (
-
-
-
- )}
- {isSelectedForAutoAdd && }
-
-
-
-
-
-
-
+
+
+
+ {autoAddBoardId === board.board_id && !editingDisclosure.isOpen && }
+ {board.archived && !editingDisclosure.isOpen && (
+
+ )}
+ {!editingDisclosure.isOpen && {board.image_count}}
- {t('unifiedCanvas.move')}} />
-
-
- )}
-
-
-
+ {t('unifiedCanvas.move')}} />
+
+
+ )}
+
);
};
export default memo(GalleryBoard);
+
+const CoverImage = ({ board }: { board: BoardDTO }) => {
+ const { currentData: coverImage } = useGetImageDTOQuery(board.cover_image_name ?? skipToken);
+
+ if (coverImage) {
+ return (
+
+ );
+ }
+
+ return (
+
+
+
+ );
+};
diff --git a/invokeai/frontend/web/src/features/gallery/components/Boards/BoardsList/NoBoardBoard.tsx b/invokeai/frontend/web/src/features/gallery/components/Boards/BoardsList/NoBoardBoard.tsx
index 2e823ea25b..fb47bf5810 100644
--- a/invokeai/frontend/web/src/features/gallery/components/Boards/BoardsList/NoBoardBoard.tsx
+++ b/invokeai/frontend/web/src/features/gallery/components/Boards/BoardsList/NoBoardBoard.tsx
@@ -1,23 +1,32 @@
-import { Box, Flex, Image, Text, Tooltip } from '@invoke-ai/ui-library';
+import type { SystemStyleObject } from '@invoke-ai/ui-library';
+import { Flex, Icon, Text, Tooltip } from '@invoke-ai/ui-library';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import IAIDroppable from 'common/components/IAIDroppable';
-import SelectionOverlay from 'common/components/SelectionOverlay';
import type { RemoveFromBoardDropData } from 'features/dnd/types';
-import AutoAddIcon from 'features/gallery/components/Boards/AutoAddIcon';
+import { AutoAddBadge } from 'features/gallery/components/Boards/AutoAddBadge';
import { BoardTotalsTooltip } from 'features/gallery/components/Boards/BoardsList/BoardTotalsTooltip';
import NoBoardBoardContextMenu from 'features/gallery/components/Boards/NoBoardBoardContextMenu';
import { autoAddBoardIdChanged, boardIdSelected } from 'features/gallery/store/gallerySlice';
-import InvokeLogoSVG from 'public/assets/images/invoke-symbol-wht-lrg.svg';
-import { memo, useCallback, useMemo, useState } from 'react';
+import { memo, useCallback, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
+import { useGetBoardImagesTotalQuery } from 'services/api/endpoints/boards';
import { useBoardName } from 'services/api/hooks/useBoardName';
interface Props {
isSelected: boolean;
}
+const _hover: SystemStyleObject = {
+ bg: 'base.800',
+};
+
const NoBoardBoard = memo(({ isSelected }: Props) => {
const dispatch = useAppDispatch();
+ const { imagesTotal } = useGetBoardImagesTotalQuery('none', {
+ selectFromResult: ({ data }) => {
+ return { imagesTotal: data?.total ?? 0 };
+ },
+ });
const autoAddBoardId = useAppSelector((s) => s.gallery.autoAddBoardId);
const autoAssignBoardOnClick = useAppSelector((s) => s.gallery.autoAssignBoardOnClick);
const boardName = useBoardName('none');
@@ -27,15 +36,6 @@ const NoBoardBoard = memo(({ isSelected }: Props) => {
dispatch(autoAddBoardIdChanged('none'));
}
}, [dispatch, autoAssignBoardOnClick]);
- const [isHovered, setIsHovered] = useState(false);
-
- const handleMouseOver = useCallback(() => {
- setIsHovered(true);
- }, []);
-
- const handleMouseOut = useCallback(() => {
- setIsHovered(false);
- }, []);
const droppableData: RemoveFromBoardDropData = useMemo(
() => ({
@@ -46,74 +46,49 @@ const NoBoardBoard = memo(({ isSelected }: Props) => {
);
const { t } = useTranslation();
return (
-
-
-
- {(ref) => (
- } openDelay={1000}>
-
-
-
-
- {autoAddBoardId === 'none' && }
-
- {boardName}
-
-
- {t('unifiedCanvas.move')}} />
-
-
- )}
-
-
-
+
+ {(ref) => (
+ } openDelay={1000}>
+
+
+ {/* iconified from public/assets/images/invoke-symbol-wht-lrg.svg */}
+
+
+
+
+
+
+ {boardName}
+
+ {autoAddBoardId === 'none' && }
+ {imagesTotal}
+ {t('unifiedCanvas.move')}} />
+
+
+ )}
+
);
});
diff --git a/invokeai/frontend/web/src/features/gallery/components/GalleryBoardName.tsx b/invokeai/frontend/web/src/features/gallery/components/GalleryBoardName.tsx
index 55aec17ab2..233aa8a8c1 100644
--- a/invokeai/frontend/web/src/features/gallery/components/GalleryBoardName.tsx
+++ b/invokeai/frontend/web/src/features/gallery/components/GalleryBoardName.tsx
@@ -1,48 +1,17 @@
-import { Button, Flex, Icon, Spacer } from '@invoke-ai/ui-library';
+import { Flex, Text } from '@invoke-ai/ui-library';
import { useAppSelector } from 'app/store/storeHooks';
-import { memo, useMemo } from 'react';
-import { PiCaretUpBold } from 'react-icons/pi';
+import { memo } from 'react';
import { useBoardName } from 'services/api/hooks/useBoardName';
-type Props = {
- isOpen: boolean;
- onToggle: () => void;
-};
-
-const GalleryBoardName = (props: Props) => {
- const { isOpen, onToggle } = props;
+const GalleryBoardName = () => {
const selectedBoardId = useAppSelector((s) => s.gallery.selectedBoardId);
const boardName = useBoardName(selectedBoardId);
- const formattedBoardName = useMemo(() => {
- if (boardName.length > 20) {
- return `${boardName.substring(0, 20)}...`;
- }
- return boardName;
- }, [boardName]);
-
return (
-
-
- {formattedBoardName}
-
-
+
+
+ {boardName}
+
);
};
diff --git a/invokeai/frontend/web/src/features/gallery/components/ImageGalleryContent.tsx b/invokeai/frontend/web/src/features/gallery/components/ImageGalleryContent.tsx
index b0b147b510..665d96a006 100644
--- a/invokeai/frontend/web/src/features/gallery/components/ImageGalleryContent.tsx
+++ b/invokeai/frontend/web/src/features/gallery/components/ImageGalleryContent.tsx
@@ -1,4 +1,4 @@
-import { Box, Button, ButtonGroup, Flex, Tab, TabList, Tabs, useDisclosure } from '@invoke-ai/ui-library';
+import { Button, ButtonGroup, Flex, Tab, TabList, Tabs } from '@invoke-ai/ui-library';
import { useStore } from '@nanostores/react';
import { $galleryHeader } from 'app/store/nanostores/galleryHeader';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
@@ -10,7 +10,6 @@ import { RiServerLine } from 'react-icons/ri';
import BoardsList from './Boards/BoardsList/BoardsList';
import GalleryBoardName from './GalleryBoardName';
-import GallerySettingsPopover from './GallerySettingsPopover/GallerySettingsPopover';
import GalleryImageGrid from './ImageGrid/GalleryImageGrid';
import { GalleryPagination } from './ImageGrid/GalleryPagination';
import { GallerySearch } from './ImageGrid/GallerySearch';
@@ -20,7 +19,6 @@ const ImageGalleryContent = () => {
const galleryView = useAppSelector((s) => s.gallery.galleryView);
const dispatch = useAppDispatch();
const galleryHeader = useStore($galleryHeader);
- const { isOpen: isBoardListOpen, onToggle: onToggleBoardList } = useDisclosure({ defaultIsOpen: true });
const handleClickImages = useCallback(() => {
dispatch(galleryViewChanged('images'));
@@ -42,15 +40,8 @@ const ImageGalleryContent = () => {
gap={2}
>
{galleryHeader}
-
-
-
-
-
-
-
-
-
+
+
diff --git a/invokeai/frontend/web/src/features/system/store/configSlice.ts b/invokeai/frontend/web/src/features/system/store/configSlice.ts
index 7d26dbd34c..8901365556 100644
--- a/invokeai/frontend/web/src/features/system/store/configSlice.ts
+++ b/invokeai/frontend/web/src/features/system/store/configSlice.ts
@@ -18,6 +18,7 @@ const initialConfigState: AppConfig = {
isLocal: true,
shouldUpdateImagesOnConnect: false,
shouldFetchMetadataFromApi: false,
+ allowPrivateBoards: false,
disabledTabs: [],
disabledFeatures: ['lightbox', 'faceRestore', 'batches'],
disabledSDFeatures: ['variation', 'symmetry', 'hires', 'perlinNoise', 'noiseThreshold'],
diff --git a/invokeai/frontend/web/src/services/api/endpoints/boards.ts b/invokeai/frontend/web/src/services/api/endpoints/boards.ts
index 177aa0e340..55ebeab318 100644
--- a/invokeai/frontend/web/src/services/api/endpoints/boards.ts
+++ b/invokeai/frontend/web/src/services/api/endpoints/boards.ts
@@ -1,5 +1,11 @@
import { ASSETS_CATEGORIES, IMAGE_CATEGORIES } from 'features/gallery/store/types';
-import type { BoardDTO, ListBoardsArgs, OffsetPaginatedResults_ImageDTO_, UpdateBoardArg } from 'services/api/types';
+import type {
+ BoardDTO,
+ CreateBoardArg,
+ ListBoardsArgs,
+ OffsetPaginatedResults_ImageDTO_,
+ UpdateBoardArg,
+} from 'services/api/types';
import { getListImagesUrl } from 'services/api/util';
import type { ApiTagDescription } from '..';
@@ -87,11 +93,11 @@ export const boardsApi = api.injectEndpoints({
* Boards Mutations
*/
- createBoard: build.mutation({
- query: (board_name) => ({
+ createBoard: build.mutation({
+ query: ({ board_name, is_private }) => ({
url: buildBoardsUrl(),
method: 'POST',
- params: { board_name },
+ params: { board_name, is_private },
}),
invalidatesTags: [{ type: 'Board', id: LIST_TAG }],
}),
diff --git a/invokeai/frontend/web/src/services/api/schema.ts b/invokeai/frontend/web/src/services/api/schema.ts
index f64fba6e77..7780ccbdc8 100644
--- a/invokeai/frontend/web/src/services/api/schema.ts
+++ b/invokeai/frontend/web/src/services/api/schema.ts
@@ -1058,6 +1058,11 @@ export type components = {
* @description Whether or not the board is archived.
*/
archived: boolean;
+ /**
+ * Is Private
+ * @description Whether the board is private.
+ */
+ is_private?: boolean | null;
/**
* Image Count
* @description The number of images in the board.
@@ -6561,6 +6566,12 @@ export type components = {
* @default false
*/
tiled?: boolean;
+ /**
+ * Tile Size
+ * @description The tile size for VAE tiling in pixels (image space). If set to 0, the default tile size for the
+ * @default 0
+ */
+ tile_size?: number;
/**
* Fp32
* @description Whether or not to use full float32 precision
@@ -7293,145 +7304,145 @@ export type components = {
project_id: string | null;
};
InvocationOutputMap: {
- save_image: components["schemas"]["ImageOutput"];
- integer_math: components["schemas"]["IntegerOutput"];
- segment_anything_processor: components["schemas"]["ImageOutput"];
- sdxl_refiner_compel_prompt: components["schemas"]["ConditioningOutput"];
- zoe_depth_image_processor: components["schemas"]["ImageOutput"];
- collect: components["schemas"]["CollectInvocationOutput"];
- range: components["schemas"]["IntegerCollectionOutput"];
- unsharp_mask: components["schemas"]["ImageOutput"];
- string_replace: components["schemas"]["StringOutput"];
- face_identifier: components["schemas"]["ImageOutput"];
- heuristic_resize: components["schemas"]["ImageOutput"];
- range_of_size: components["schemas"]["IntegerCollectionOutput"];
- latents_collection: components["schemas"]["LatentsCollectionOutput"];
- color_map_image_processor: components["schemas"]["ImageOutput"];
- img_ilerp: components["schemas"]["ImageOutput"];
- infill_patchmatch: components["schemas"]["ImageOutput"];
- face_off: components["schemas"]["FaceOffOutput"];
- string_collection: components["schemas"]["StringCollectionOutput"];
- sdxl_model_loader: components["schemas"]["SDXLModelLoaderOutput"];
- sdxl_lora_loader: components["schemas"]["SDXLLoRALoaderOutput"];
- string_join: components["schemas"]["StringOutput"];
- lblend: components["schemas"]["LatentsOutput"];
- conditioning_collection: components["schemas"]["ConditioningCollectionOutput"];
- string_split_neg: components["schemas"]["StringPosNegOutput"];
- img_watermark: components["schemas"]["ImageOutput"];
- infill_lama: components["schemas"]["ImageOutput"];
- div: components["schemas"]["IntegerOutput"];
- show_image: components["schemas"]["ImageOutput"];
- tile_to_properties: components["schemas"]["TileToPropertiesOutput"];
- sub: components["schemas"]["IntegerOutput"];
- normalbae_image_processor: components["schemas"]["ImageOutput"];
- invert_tensor_mask: components["schemas"]["MaskOutput"];
- create_gradient_mask: components["schemas"]["GradientMaskOutput"];
- string_split: components["schemas"]["String2Output"];
- step_param_easing: components["schemas"]["FloatCollectionOutput"];
- metadata: components["schemas"]["MetadataOutput"];
- img_pad_crop: components["schemas"]["ImageOutput"];
- integer: components["schemas"]["IntegerOutput"];
- img_mul: components["schemas"]["ImageOutput"];
- calculate_image_tiles: components["schemas"]["CalculateImageTilesOutput"];
- color: components["schemas"]["ColorOutput"];
- infill_rgba: components["schemas"]["ImageOutput"];
- t2i_adapter: components["schemas"]["T2IAdapterOutput"];
- denoise_latents: components["schemas"]["LatentsOutput"];
- img_lerp: components["schemas"]["ImageOutput"];
- img_channel_offset: components["schemas"]["ImageOutput"];
- img_crop: components["schemas"]["ImageOutput"];
- alpha_mask_to_tensor: components["schemas"]["MaskOutput"];
- color_correct: components["schemas"]["ImageOutput"];
- calculate_image_tiles_min_overlap: components["schemas"]["CalculateImageTilesOutput"];
- img_hue_adjust: components["schemas"]["ImageOutput"];
- lresize: components["schemas"]["LatentsOutput"];
- img_blur: components["schemas"]["ImageOutput"];
- compel: components["schemas"]["ConditioningOutput"];
- sdxl_lora_collection_loader: components["schemas"]["SDXLLoRALoaderOutput"];
- float_to_int: components["schemas"]["IntegerOutput"];
- boolean: components["schemas"]["BooleanOutput"];
- string_join_three: components["schemas"]["StringOutput"];
- add: components["schemas"]["IntegerOutput"];
- merge_tiles_to_image: components["schemas"]["ImageOutput"];
- core_metadata: components["schemas"]["MetadataOutput"];
- lscale: components["schemas"]["LatentsOutput"];
- mlsd_image_processor: components["schemas"]["ImageOutput"];
- image_collection: components["schemas"]["ImageCollectionOutput"];
- crop_latents: components["schemas"]["LatentsOutput"];
- image_mask_to_tensor: components["schemas"]["MaskOutput"];
- lora_collection_loader: components["schemas"]["LoRALoaderOutput"];
- ip_adapter: components["schemas"]["IPAdapterOutput"];
- pidi_image_processor: components["schemas"]["ImageOutput"];
- rand_int: components["schemas"]["IntegerOutput"];
- img_conv: components["schemas"]["ImageOutput"];
- scheduler: components["schemas"]["SchedulerOutput"];
- img_paste: components["schemas"]["ImageOutput"];
- noise: components["schemas"]["NoiseOutput"];
- img_scale: components["schemas"]["ImageOutput"];
- i2l: components["schemas"]["LatentsOutput"];
- main_model_loader: components["schemas"]["ModelLoaderOutput"];
- blank_image: components["schemas"]["ImageOutput"];
- mask_edge: components["schemas"]["ImageOutput"];
- seamless: components["schemas"]["SeamlessModeOutput"];
- esrgan: components["schemas"]["ImageOutput"];
- canvas_paste_back: components["schemas"]["ImageOutput"];
- mul: components["schemas"]["IntegerOutput"];
- dynamic_prompt: components["schemas"]["StringCollectionOutput"];
- controlnet: components["schemas"]["ControlOutput"];
- l2i: components["schemas"]["ImageOutput"];
- ideal_size: components["schemas"]["IdealSizeOutput"];
- latents: components["schemas"]["LatentsOutput"];
- midas_depth_image_processor: components["schemas"]["ImageOutput"];
- tomask: components["schemas"]["ImageOutput"];
- float_math: components["schemas"]["FloatOutput"];
- round_float: components["schemas"]["FloatOutput"];
- cv_inpaint: components["schemas"]["ImageOutput"];
- create_denoise_mask: components["schemas"]["DenoiseMaskOutput"];
- model_identifier: components["schemas"]["ModelIdentifierOutput"];
- pair_tile_image: components["schemas"]["PairTileImageOutput"];
- lineart_image_processor: components["schemas"]["ImageOutput"];
- img_nsfw: components["schemas"]["ImageOutput"];
- infill_cv2: components["schemas"]["ImageOutput"];
- clip_skip: components["schemas"]["CLIPSkipInvocationOutput"];
- dw_openpose_image_processor: components["schemas"]["ImageOutput"];
- img_resize: components["schemas"]["ImageOutput"];
- iterate: components["schemas"]["IterateInvocationOutput"];
rectangle_mask: components["schemas"]["MaskOutput"];
- canny_image_processor: components["schemas"]["ImageOutput"];
- calculate_image_tiles_even_split: components["schemas"]["CalculateImageTilesOutput"];
+ hed_image_processor: components["schemas"]["ImageOutput"];
+ compel: components["schemas"]["ConditioningOutput"];
+ img_resize: components["schemas"]["ImageOutput"];
+ ideal_size: components["schemas"]["IdealSizeOutput"];
+ rand_int: components["schemas"]["IntegerOutput"];
+ clip_skip: components["schemas"]["CLIPSkipInvocationOutput"];
+ string_collection: components["schemas"]["StringCollectionOutput"];
+ create_gradient_mask: components["schemas"]["GradientMaskOutput"];
+ round_float: components["schemas"]["FloatOutput"];
+ scheduler: components["schemas"]["SchedulerOutput"];
+ main_model_loader: components["schemas"]["ModelLoaderOutput"];
+ string_split: components["schemas"]["String2Output"];
mask_from_id: components["schemas"]["ImageOutput"];
- metadata_item: components["schemas"]["MetadataItemOutput"];
- infill_tile: components["schemas"]["ImageOutput"];
- tiled_multi_diffusion_denoise_latents: components["schemas"]["LatentsOutput"];
- img_channel_multiply: components["schemas"]["ImageOutput"];
+ collect: components["schemas"]["CollectInvocationOutput"];
+ heuristic_resize: components["schemas"]["ImageOutput"];
+ tomask: components["schemas"]["ImageOutput"];
boolean_collection: components["schemas"]["BooleanCollectionOutput"];
- lora_loader: components["schemas"]["LoRALoaderOutput"];
- float_collection: components["schemas"]["FloatCollectionOutput"];
- string: components["schemas"]["StringOutput"];
- freeu: components["schemas"]["UNetOutput"];
- lineart_anime_image_processor: components["schemas"]["ImageOutput"];
- depth_anything_image_processor: components["schemas"]["ImageOutput"];
- image: components["schemas"]["ImageOutput"];
+ core_metadata: components["schemas"]["MetadataOutput"];
+ canny_image_processor: components["schemas"]["ImageOutput"];
+ string_replace: components["schemas"]["StringOutput"];
face_mask_detection: components["schemas"]["FaceMaskOutput"];
+ integer: components["schemas"]["IntegerOutput"];
+ img_watermark: components["schemas"]["ImageOutput"];
+ img_crop: components["schemas"]["ImageOutput"];
+ t2i_adapter: components["schemas"]["T2IAdapterOutput"];
+ create_denoise_mask: components["schemas"]["DenoiseMaskOutput"];
rand_float: components["schemas"]["FloatOutput"];
- float: components["schemas"]["FloatOutput"];
- random_range: components["schemas"]["IntegerCollectionOutput"];
- integer_collection: components["schemas"]["IntegerCollectionOutput"];
- sdxl_refiner_model_loader: components["schemas"]["SDXLRefinerModelLoaderOutput"];
- mask_combine: components["schemas"]["ImageOutput"];
- tile_image_processor: components["schemas"]["ImageOutput"];
+ zoe_depth_image_processor: components["schemas"]["ImageOutput"];
+ face_off: components["schemas"]["FaceOffOutput"];
+ tile_to_properties: components["schemas"]["TileToPropertiesOutput"];
+ color_map_image_processor: components["schemas"]["ImageOutput"];
+ lineart_anime_image_processor: components["schemas"]["ImageOutput"];
+ face_identifier: components["schemas"]["ImageOutput"];
+ float_math: components["schemas"]["FloatOutput"];
+ mediapipe_face_processor: components["schemas"]["ImageOutput"];
+ img_channel_multiply: components["schemas"]["ImageOutput"];
+ metadata_item: components["schemas"]["MetadataItemOutput"];
+ img_ilerp: components["schemas"]["ImageOutput"];
+ conditioning: components["schemas"]["ConditioningOutput"];
+ pidi_image_processor: components["schemas"]["ImageOutput"];
+ seamless: components["schemas"]["SeamlessModeOutput"];
+ latents: components["schemas"]["LatentsOutput"];
img_chan: components["schemas"]["ImageOutput"];
- vae_loader: components["schemas"]["VAEOutput"];
+ model_identifier: components["schemas"]["ModelIdentifierOutput"];
+ noise: components["schemas"]["NoiseOutput"];
+ string_join: components["schemas"]["StringOutput"];
+ blank_image: components["schemas"]["ImageOutput"];
+ calculate_image_tiles: components["schemas"]["CalculateImageTilesOutput"];
+ invert_tensor_mask: components["schemas"]["MaskOutput"];
+ save_image: components["schemas"]["ImageOutput"];
+ unsharp_mask: components["schemas"]["ImageOutput"];
+ image_mask_to_tensor: components["schemas"]["MaskOutput"];
+ step_param_easing: components["schemas"]["FloatCollectionOutput"];
+ merge_tiles_to_image: components["schemas"]["ImageOutput"];
+ integer_collection: components["schemas"]["IntegerCollectionOutput"];
+ calculate_image_tiles_even_split: components["schemas"]["CalculateImageTilesOutput"];
+ integer_math: components["schemas"]["IntegerOutput"];
+ range: components["schemas"]["IntegerCollectionOutput"];
prompt_from_file: components["schemas"]["StringCollectionOutput"];
+ segment_anything_processor: components["schemas"]["ImageOutput"];
+ freeu: components["schemas"]["UNetOutput"];
+ sub: components["schemas"]["IntegerOutput"];
+ lresize: components["schemas"]["LatentsOutput"];
+ float: components["schemas"]["FloatOutput"];
+ float_collection: components["schemas"]["FloatCollectionOutput"];
+ dynamic_prompt: components["schemas"]["StringCollectionOutput"];
+ infill_lama: components["schemas"]["ImageOutput"];
+ l2i: components["schemas"]["ImageOutput"];
+ img_lerp: components["schemas"]["ImageOutput"];
+ ip_adapter: components["schemas"]["IPAdapterOutput"];
+ lora_collection_loader: components["schemas"]["LoRALoaderOutput"];
+ color: components["schemas"]["ColorOutput"];
+ tiled_multi_diffusion_denoise_latents: components["schemas"]["LatentsOutput"];
+ cv_inpaint: components["schemas"]["ImageOutput"];
+ lscale: components["schemas"]["LatentsOutput"];
+ string: components["schemas"]["StringOutput"];
+ sdxl_refiner_compel_prompt: components["schemas"]["ConditioningOutput"];
+ string_join_three: components["schemas"]["StringOutput"];
+ midas_depth_image_processor: components["schemas"]["ImageOutput"];
+ esrgan: components["schemas"]["ImageOutput"];
+ sdxl_refiner_model_loader: components["schemas"]["SDXLRefinerModelLoaderOutput"];
+ mul: components["schemas"]["IntegerOutput"];
+ normalbae_image_processor: components["schemas"]["ImageOutput"];
+ infill_rgba: components["schemas"]["ImageOutput"];
+ sdxl_model_loader: components["schemas"]["SDXLModelLoaderOutput"];
+ vae_loader: components["schemas"]["VAEOutput"];
+ float_to_int: components["schemas"]["IntegerOutput"];
+ lora_selector: components["schemas"]["LoRASelectorOutput"];
+ crop_latents: components["schemas"]["LatentsOutput"];
+ img_mul: components["schemas"]["ImageOutput"];
float_range: components["schemas"]["FloatCollectionOutput"];
merge_metadata: components["schemas"]["MetadataOutput"];
- sdxl_compel_prompt: components["schemas"]["ConditioningOutput"];
- hed_image_processor: components["schemas"]["ImageOutput"];
- lora_selector: components["schemas"]["LoRASelectorOutput"];
- conditioning: components["schemas"]["ConditioningOutput"];
+ img_blur: components["schemas"]["ImageOutput"];
+ boolean: components["schemas"]["BooleanOutput"];
+ tile_image_processor: components["schemas"]["ImageOutput"];
+ mlsd_image_processor: components["schemas"]["ImageOutput"];
+ infill_patchmatch: components["schemas"]["ImageOutput"];
+ img_pad_crop: components["schemas"]["ImageOutput"];
leres_image_processor: components["schemas"]["ImageOutput"];
- mediapipe_face_processor: components["schemas"]["ImageOutput"];
+ sdxl_lora_loader: components["schemas"]["SDXLLoRALoaderOutput"];
+ dw_openpose_image_processor: components["schemas"]["ImageOutput"];
+ img_scale: components["schemas"]["ImageOutput"];
+ pair_tile_image: components["schemas"]["PairTileImageOutput"];
+ lblend: components["schemas"]["LatentsOutput"];
+ range_of_size: components["schemas"]["IntegerCollectionOutput"];
+ image_collection: components["schemas"]["ImageCollectionOutput"];
+ calculate_image_tiles_min_overlap: components["schemas"]["CalculateImageTilesOutput"];
+ img_channel_offset: components["schemas"]["ImageOutput"];
+ alpha_mask_to_tensor: components["schemas"]["MaskOutput"];
+ infill_cv2: components["schemas"]["ImageOutput"];
+ mask_combine: components["schemas"]["ImageOutput"];
+ string_split_neg: components["schemas"]["StringPosNegOutput"];
+ sdxl_lora_collection_loader: components["schemas"]["SDXLLoRALoaderOutput"];
+ lineart_image_processor: components["schemas"]["ImageOutput"];
+ img_nsfw: components["schemas"]["ImageOutput"];
+ image: components["schemas"]["ImageOutput"];
content_shuffle_image_processor: components["schemas"]["ImageOutput"];
+ canvas_paste_back: components["schemas"]["ImageOutput"];
+ iterate: components["schemas"]["IterateInvocationOutput"];
+ div: components["schemas"]["IntegerOutput"];
+ latents_collection: components["schemas"]["LatentsCollectionOutput"];
+ img_conv: components["schemas"]["ImageOutput"];
+ mask_edge: components["schemas"]["ImageOutput"];
+ conditioning_collection: components["schemas"]["ConditioningCollectionOutput"];
+ img_hue_adjust: components["schemas"]["ImageOutput"];
+ depth_anything_image_processor: components["schemas"]["ImageOutput"];
+ lora_loader: components["schemas"]["LoRALoaderOutput"];
+ sdxl_compel_prompt: components["schemas"]["ConditioningOutput"];
+ add: components["schemas"]["IntegerOutput"];
+ controlnet: components["schemas"]["ControlOutput"];
+ color_correct: components["schemas"]["ImageOutput"];
+ random_range: components["schemas"]["IntegerCollectionOutput"];
+ denoise_latents: components["schemas"]["LatentsOutput"];
+ metadata: components["schemas"]["MetadataOutput"];
+ i2l: components["schemas"]["LatentsOutput"];
+ show_image: components["schemas"]["ImageOutput"];
+ img_paste: components["schemas"]["ImageOutput"];
+ infill_tile: components["schemas"]["ImageOutput"];
};
/**
* InvocationStartedEvent
@@ -7769,6 +7780,12 @@ export type components = {
* @default false
*/
tiled?: boolean;
+ /**
+ * Tile Size
+ * @description The tile size for VAE tiling in pixels (image space). If set to 0, the default tile size for the
+ * @default 0
+ */
+ tile_size?: number;
/**
* Fp32
* @description Whether or not to use full float32 precision
@@ -15014,6 +15031,8 @@ export type operations = {
query: {
/** @description The name of the board to create */
board_name: string;
+ /** @description Whether the board is private */
+ is_private?: boolean;
};
};
responses: {
diff --git a/invokeai/frontend/web/src/services/api/types.ts b/invokeai/frontend/web/src/services/api/types.ts
index 162bdf6abc..5beb5cbbf5 100644
--- a/invokeai/frontend/web/src/services/api/types.ts
+++ b/invokeai/frontend/web/src/services/api/types.ts
@@ -11,6 +11,8 @@ export type ListBoardsArgs = NonNullable