feat(ui): rename gallery boards on double click

This commit is contained in:
psychedelicious 2024-07-10 17:28:49 +10:00 committed by Kent Keirsey
parent 48a57f0da8
commit a7c44b4a98

View File

@ -9,6 +9,7 @@ import {
Text, Text,
Tooltip, Tooltip,
useDisclosure, useDisclosure,
useEditableControls,
} from '@invoke-ai/ui-library'; } from '@invoke-ai/ui-library';
import { skipToken } from '@reduxjs/toolkit/query'; import { skipToken } from '@reduxjs/toolkit/query';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
@ -18,7 +19,8 @@ import { AutoAddBadge } from 'features/gallery/components/Boards/AutoAddBadge';
import BoardContextMenu from 'features/gallery/components/Boards/BoardContextMenu'; import BoardContextMenu from 'features/gallery/components/Boards/BoardContextMenu';
import { BoardTotalsTooltip } from 'features/gallery/components/Boards/BoardsList/BoardTotalsTooltip'; import { BoardTotalsTooltip } from 'features/gallery/components/Boards/BoardsList/BoardTotalsTooltip';
import { autoAddBoardIdChanged, boardIdSelected } from 'features/gallery/store/gallerySlice'; import { autoAddBoardIdChanged, boardIdSelected } from 'features/gallery/store/gallerySlice';
import { memo, useCallback, useMemo, useState } from 'react'; import type { MouseEvent, MouseEventHandler, MutableRefObject } from 'react';
import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { PiArchiveBold, PiImageSquare } from 'react-icons/pi'; import { PiArchiveBold, PiImageSquare } from 'react-icons/pi';
import { useUpdateBoardMutation } from 'services/api/endpoints/boards'; import { useUpdateBoardMutation } from 'services/api/endpoints/boards';
@ -49,15 +51,19 @@ const GalleryBoard = ({ board, isSelected, setBoardToDelete }: GalleryBoardProps
const { t } = useTranslation(); const { t } = useTranslation();
const autoAddBoardId = useAppSelector((s) => s.gallery.autoAddBoardId); const autoAddBoardId = useAppSelector((s) => s.gallery.autoAddBoardId);
const autoAssignBoardOnClick = useAppSelector((s) => s.gallery.autoAssignBoardOnClick); const autoAssignBoardOnClick = useAppSelector((s) => s.gallery.autoAssignBoardOnClick);
const selectedBoardId = useAppSelector((s) => s.gallery.selectedBoardId);
const editingDisclosure = useDisclosure(); const editingDisclosure = useDisclosure();
const [localBoardName, setLocalBoardName] = useState(board.board_name); const [localBoardName, setLocalBoardName] = useState(board.board_name);
const onStartEditingRef = useRef<MouseEventHandler | undefined>(undefined);
const handleSelectBoard = useCallback(() => { const onClick = useCallback(() => {
dispatch(boardIdSelected({ boardId: board.board_id })); if (selectedBoardId !== board.board_id) {
if (autoAssignBoardOnClick) { dispatch(boardIdSelected({ boardId: board.board_id }));
}
if (autoAssignBoardOnClick && autoAddBoardId !== board.board_id) {
dispatch(autoAddBoardIdChanged(board.board_id)); dispatch(autoAddBoardIdChanged(board.board_id));
} }
}, [dispatch, board.board_id, autoAssignBoardOnClick]); }, [selectedBoardId, board.board_id, autoAssignBoardOnClick, autoAddBoardId, dispatch]);
const [updateBoard, { isLoading: isUpdateBoardLoading }] = useUpdateBoardMutation(); const [updateBoard, { isLoading: isUpdateBoardLoading }] = useUpdateBoardMutation();
@ -70,7 +76,7 @@ const GalleryBoard = ({ board, isSelected, setBoardToDelete }: GalleryBoardProps
[board.board_id] [board.board_id]
); );
const handleSubmit = useCallback( const onSubmit = useCallback(
async (newBoardName: string) => { async (newBoardName: string) => {
if (!newBoardName.trim()) { if (!newBoardName.trim()) {
// empty strings are not allowed // empty strings are not allowed
@ -96,10 +102,16 @@ const GalleryBoard = ({ board, isSelected, setBoardToDelete }: GalleryBoardProps
[board.board_id, board.board_name, editingDisclosure, updateBoard] [board.board_id, board.board_name, editingDisclosure, updateBoard]
); );
const handleChange = useCallback((newBoardName: string) => { const onChange = useCallback((newBoardName: string) => {
setLocalBoardName(newBoardName); setLocalBoardName(newBoardName);
}, []); }, []);
const onDoubleClick = useCallback((e: MouseEvent<HTMLDivElement>) => {
if (onStartEditingRef.current) {
onStartEditingRef.current(e);
}
}, []);
return ( return (
<BoardContextMenu board={board} setBoardToDelete={setBoardToDelete}> <BoardContextMenu board={board} setBoardToDelete={setBoardToDelete}>
{(ref) => ( {(ref) => (
@ -110,7 +122,8 @@ const GalleryBoard = ({ board, isSelected, setBoardToDelete }: GalleryBoardProps
<Flex <Flex
position="relative" position="relative"
ref={ref} ref={ref}
onClick={handleSelectBoard} onClick={onClick}
onDoubleClick={onDoubleClick}
w="full" w="full"
alignItems="center" alignItems="center"
borderRadius="base" borderRadius="base"
@ -131,10 +144,12 @@ const GalleryBoard = ({ board, isSelected, setBoardToDelete }: GalleryBoardProps
value={localBoardName} value={localBoardName}
isDisabled={isUpdateBoardLoading} isDisabled={isUpdateBoardLoading}
submitOnBlur={true} submitOnBlur={true}
onChange={handleChange} onChange={onChange}
onSubmit={handleSubmit} onSubmit={onSubmit}
isPreviewFocusable={false}
> >
<EditablePreview <EditablePreview
cursor="pointer"
p={0} p={0}
fontSize="md" fontSize="md"
textOverflow="ellipsis" textOverflow="ellipsis"
@ -145,6 +160,7 @@ const GalleryBoard = ({ board, isSelected, setBoardToDelete }: GalleryBoardProps
fontWeight={isSelected ? 'semibold' : 'normal'} fontWeight={isSelected ? 'semibold' : 'normal'}
/> />
<EditableInput sx={editableInputStyles} /> <EditableInput sx={editableInputStyles} />
<JankEditableHijack onStartEditingRef={onStartEditingRef} />
</Editable> </Editable>
{autoAddBoardId === board.board_id && !editingDisclosure.isOpen && <AutoAddBadge />} {autoAddBoardId === board.board_id && !editingDisclosure.isOpen && <AutoAddBadge />}
{board.archived && !editingDisclosure.isOpen && <Icon as={PiArchiveBold} fill="base.300" />} {board.archived && !editingDisclosure.isOpen && <Icon as={PiArchiveBold} fill="base.300" />}
@ -158,6 +174,16 @@ const GalleryBoard = ({ board, isSelected, setBoardToDelete }: GalleryBoardProps
); );
}; };
const JankEditableHijack = memo((props: { onStartEditingRef: MutableRefObject<MouseEventHandler | undefined> }) => {
const editableControls = useEditableControls();
useEffect(() => {
props.onStartEditingRef.current = editableControls.getEditButtonProps().onClick;
}, [props, editableControls]);
return null;
});
JankEditableHijack.displayName = 'JankEditableHijack';
export default memo(GalleryBoard); export default memo(GalleryBoard);
const CoverImage = ({ board }: { board: BoardDTO }) => { const CoverImage = ({ board }: { board: BoardDTO }) => {