feat(ui): remove shouldShowDeleteButton

- remove this state entirely
- use `state.hotkeys.shift` directly to hide and show the icon on gallery
- also formatting
This commit is contained in:
psychedelicious 2023-08-16 11:50:57 +10:00
parent 5b1099193d
commit 0f8606914e
8 changed files with 51 additions and 70 deletions

View File

@ -1,4 +1,11 @@
import { ChakraProps, Flex, Icon, Image, useColorMode } from '@chakra-ui/react'; import {
ChakraProps,
Flex,
FlexProps,
Icon,
Image,
useColorMode,
} from '@chakra-ui/react';
import { import {
IAILoadingImageFallback, IAILoadingImageFallback,
IAINoContentFallback, IAINoContentFallback,
@ -25,7 +32,7 @@ import {
TypesafeDroppableData, TypesafeDroppableData,
} from 'features/dnd/types'; } from 'features/dnd/types';
type IAIDndImageProps = { type IAIDndImageProps = FlexProps & {
imageDTO: ImageDTO | undefined; imageDTO: ImageDTO | undefined;
onError?: (event: SyntheticEvent<HTMLImageElement>) => void; onError?: (event: SyntheticEvent<HTMLImageElement>) => void;
onLoad?: (event: SyntheticEvent<HTMLImageElement>) => void; onLoad?: (event: SyntheticEvent<HTMLImageElement>) => void;
@ -47,8 +54,6 @@ type IAIDndImageProps = {
useThumbailFallback?: boolean; useThumbailFallback?: boolean;
withHoverOverlay?: boolean; withHoverOverlay?: boolean;
children?: JSX.Element; children?: JSX.Element;
onMouseOver?: () => void;
onMouseOut?: () => void;
}; };
const IAIDndImage = (props: IAIDndImageProps) => { const IAIDndImage = (props: IAIDndImageProps) => {
@ -79,14 +84,20 @@ const IAIDndImage = (props: IAIDndImageProps) => {
const { colorMode } = useColorMode(); const { colorMode } = useColorMode();
const [isHovered, setIsHovered] = useState(false); const [isHovered, setIsHovered] = useState(false);
const handleMouseOver = useCallback(() => { const handleMouseOver = useCallback(
if (onMouseOver) onMouseOver(); (e: MouseEvent<HTMLDivElement>) => {
setIsHovered(true); if (onMouseOver) onMouseOver(e);
}, [onMouseOver]); setIsHovered(true);
const handleMouseOut = useCallback(() => { },
if (onMouseOut) onMouseOut(); [onMouseOver]
setIsHovered(false); );
}, [onMouseOut]); const handleMouseOut = useCallback(
(e: MouseEvent<HTMLDivElement>) => {
if (onMouseOut) onMouseOut(e);
setIsHovered(false);
},
[onMouseOut]
);
const { getUploadButtonProps, getUploadInputProps } = useImageUploadButton({ const { getUploadButtonProps, getUploadInputProps } = useImageUploadButton({
postUploadAction, postUploadAction,

View File

@ -1,6 +1,6 @@
import { JSXElementConstructor, ReactElement, memo, MouseEvent } from 'react';
import IAIIconButton from './IAIIconButton';
import { SystemStyleObject, useColorModeValue } from '@chakra-ui/react'; import { SystemStyleObject, useColorModeValue } from '@chakra-ui/react';
import { JSXElementConstructor, MouseEvent, ReactElement, memo } from 'react';
import IAIIconButton from './IAIIconButton';
type Props = { type Props = {
onClick: (event: MouseEvent<HTMLButtonElement>) => void; onClick: (event: MouseEvent<HTMLButtonElement>) => void;

View File

@ -1,10 +1,4 @@
import { import { Box, Flex, Spinner, SystemStyleObject } from '@chakra-ui/react';
Box,
Flex,
Spinner,
SystemStyleObject,
useColorModeValue,
} from '@chakra-ui/react';
import { createSelector } from '@reduxjs/toolkit'; import { createSelector } from '@reduxjs/toolkit';
import { skipToken } from '@reduxjs/toolkit/dist/query'; import { skipToken } from '@reduxjs/toolkit/dist/query';
import { import {
@ -16,14 +10,14 @@ import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions'; import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
import IAIDndImage from 'common/components/IAIDndImage'; import IAIDndImage from 'common/components/IAIDndImage';
import { memo, useCallback, useMemo, useState } from 'react'; import { memo, useCallback, useMemo, useState } from 'react';
import { FaUndo } from 'react-icons/fa';
import { useGetImageDTOQuery } from 'services/api/endpoints/images'; import { useGetImageDTOQuery } from 'services/api/endpoints/images';
import { PostUploadAction } from 'services/api/types'; import { PostUploadAction } from 'services/api/types';
import IAIDndImageIcon from '../../../common/components/IAIDndImageIcon';
import { import {
ControlNetConfig, ControlNetConfig,
controlNetImageChanged, controlNetImageChanged,
} from '../store/controlNetSlice'; } from '../store/controlNetSlice';
import { FaUndo } from 'react-icons/fa';
import IAIDndImageIcon from '../../../common/components/IAIDndImageIcon';
type Props = { type Props = {
controlNet: ControlNetConfig; controlNet: ControlNetConfig;
@ -101,11 +95,6 @@ const ControlNetImagePreview = (props: Props) => {
[controlNetId] [controlNetId]
); );
const resetIconShadow = useColorModeValue(
`drop-shadow(0px 0px 0.1rem var(--invokeai-colors-base-600))`,
`drop-shadow(0px 0px 0.1rem var(--invokeai-colors-base-800))`
);
const shouldShowProcessedImage = const shouldShowProcessedImage =
controlImage && controlImage &&
processedControlImage && processedControlImage &&

View File

@ -27,9 +27,7 @@ const GalleryImage = (props: HoverableImageProps) => {
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
const { imageName } = props; const { imageName } = props;
const { currentData: imageDTO } = useGetImageDTOQuery(imageName); const { currentData: imageDTO } = useGetImageDTOQuery(imageName);
const shouldShowDeleteButton = useAppSelector( const shift = useAppSelector((state) => state.hotkeys.shift);
(state) => state.gallery.shouldShowDeleteButton
);
const { handleClick, isSelected, selection, selectionCount } = const { handleClick, isSelected, selection, selectionCount } =
useMultiselect(imageDTO); useMultiselect(imageDTO);
@ -81,6 +79,14 @@ const GalleryImage = (props: HoverableImageProps) => {
const [isHovered, setIsHovered] = useState(false); const [isHovered, setIsHovered] = useState(false);
const handleMouseOver = useCallback(() => {
setIsHovered(true);
}, []);
const handleMouseOut = useCallback(() => {
setIsHovered(false);
}, []);
const starIcon = useMemo(() => { const starIcon = useMemo(() => {
if (imageDTO?.starred) return <MdStar size="20" />; if (imageDTO?.starred) return <MdStar size="20" />;
if (!imageDTO?.starred && isHovered) return <MdStarBorder size="20" />; if (!imageDTO?.starred && isHovered) return <MdStarBorder size="20" />;
@ -112,8 +118,8 @@ const GalleryImage = (props: HoverableImageProps) => {
isUploadDisabled={true} isUploadDisabled={true}
thumbnail={true} thumbnail={true}
withHoverOverlay withHoverOverlay
onMouseOver={() => setIsHovered(true)} onMouseOver={handleMouseOver}
onMouseOut={() => setIsHovered(false)} onMouseOut={handleMouseOut}
> >
<> <>
<IAIDndImageIcon <IAIDndImageIcon
@ -122,13 +128,13 @@ const GalleryImage = (props: HoverableImageProps) => {
tooltip={imageDTO.starred ? 'Unstar' : 'Star'} tooltip={imageDTO.starred ? 'Unstar' : 'Star'}
/> />
{isHovered && shouldShowDeleteButton && ( {isHovered && shift && (
<IAIDndImageIcon <IAIDndImageIcon
onClick={handleDelete} onClick={handleDelete}
icon={<FaTrash />} icon={<FaTrash />}
tooltip={'Delete'} tooltip="Delete"
styleOverrides={{ styleOverrides={{
bottom: 1, bottom: 2,
top: 'auto', top: 'auto',
}} }}
/> />

View File

@ -1,5 +1,5 @@
import { Box, Flex } from '@chakra-ui/react'; import { Box, Flex } from '@chakra-ui/react';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { useAppSelector } from 'app/store/storeHooks';
import IAIButton from 'common/components/IAIButton'; import IAIButton from 'common/components/IAIButton';
import { IAINoContentFallback } from 'common/components/IAIImageFallback'; import { IAINoContentFallback } from 'common/components/IAIImageFallback';
import { selectListImagesBaseQueryArgs } from 'features/gallery/store/gallerySelectors'; import { selectListImagesBaseQueryArgs } from 'features/gallery/store/gallerySelectors';
@ -20,8 +20,6 @@ import { useBoardTotal } from 'services/api/hooks/useBoardTotal';
import GalleryImage from './GalleryImage'; import GalleryImage from './GalleryImage';
import ImageGridItemContainer from './ImageGridItemContainer'; import ImageGridItemContainer from './ImageGridItemContainer';
import ImageGridListContainer from './ImageGridListContainer'; import ImageGridListContainer from './ImageGridListContainer';
import { useHotkeys } from 'react-hotkeys-hook';
import { shouldShowDeleteButtonChanged } from '../../store/gallerySlice';
const overlayScrollbarsConfig: UseOverlayScrollbarsParams = { const overlayScrollbarsConfig: UseOverlayScrollbarsParams = {
defer: true, defer: true,
@ -38,7 +36,6 @@ const overlayScrollbarsConfig: UseOverlayScrollbarsParams = {
const GalleryImageGrid = () => { const GalleryImageGrid = () => {
const { t } = useTranslation(); const { t } = useTranslation();
const dispatch = useAppDispatch();
const rootRef = useRef<HTMLDivElement>(null); const rootRef = useRef<HTMLDivElement>(null);
const [scroller, setScroller] = useState<HTMLElement | null>(null); const [scroller, setScroller] = useState<HTMLElement | null>(null);
const [initialize, osInstance] = useOverlayScrollbars( const [initialize, osInstance] = useOverlayScrollbars(
@ -88,23 +85,6 @@ const GalleryImageGrid = () => {
return () => osInstance()?.destroy(); return () => osInstance()?.destroy();
}, [scroller, initialize, osInstance]); }, [scroller, initialize, osInstance]);
useHotkeys(
'shift',
() => {
dispatch(shouldShowDeleteButtonChanged(true));
},
[shouldShowDeleteButtonChanged]
);
useHotkeys(
'shift',
() => {
dispatch(shouldShowDeleteButtonChanged(false));
},
{ keyup: true },
[shouldShowDeleteButtonChanged]
);
if (!currentData) { if (!currentData) {
return ( return (
<Flex <Flex

View File

@ -13,7 +13,6 @@ export const initialGalleryState: GalleryState = {
galleryImageMinimumWidth: 96, galleryImageMinimumWidth: 96,
selectedBoardId: 'none', selectedBoardId: 'none',
galleryView: 'images', galleryView: 'images',
shouldShowDeleteButton: false,
boardSearchText: '', boardSearchText: '',
}; };
@ -50,9 +49,6 @@ export const gallerySlice = createSlice({
galleryViewChanged: (state, action: PayloadAction<GalleryView>) => { galleryViewChanged: (state, action: PayloadAction<GalleryView>) => {
state.galleryView = action.payload; state.galleryView = action.payload;
}, },
shouldShowDeleteButtonChanged: (state, action: PayloadAction<boolean>) => {
state.shouldShowDeleteButton = action.payload;
},
boardSearchTextChanged: (state, action: PayloadAction<string>) => { boardSearchTextChanged: (state, action: PayloadAction<string>) => {
state.boardSearchText = action.payload; state.boardSearchText = action.payload;
}, },
@ -93,7 +89,6 @@ export const {
autoAddBoardIdChanged, autoAddBoardIdChanged,
galleryViewChanged, galleryViewChanged,
selectionChanged, selectionChanged,
shouldShowDeleteButtonChanged,
boardSearchTextChanged, boardSearchTextChanged,
} = gallerySlice.actions; } = gallerySlice.actions;

View File

@ -21,6 +21,5 @@ export type GalleryState = {
galleryImageMinimumWidth: number; galleryImageMinimumWidth: number;
selectedBoardId: BoardId; selectedBoardId: BoardId;
galleryView: GalleryView; galleryView: GalleryView;
shouldShowDeleteButton: boolean;
boardSearchText: string; boardSearchText: string;
}; };

View File

@ -26,26 +26,27 @@ export const getIsImageInDateRange = (
for (let index = 0; index < totalCachedImageDtos.length; index++) { for (let index = 0; index < totalCachedImageDtos.length; index++) {
const image = totalCachedImageDtos[index]; const image = totalCachedImageDtos[index];
if (image?.starred) cachedStarredImages.push(image) if (image?.starred) cachedStarredImages.push(image);
if (!image?.starred) cachedUnstarredImages.push(image) if (!image?.starred) cachedUnstarredImages.push(image);
} }
if (imageDTO.starred) { if (imageDTO.starred) {
const lastStarredImage = cachedStarredImages[cachedStarredImages.length - 1]; const lastStarredImage =
cachedStarredImages[cachedStarredImages.length - 1];
// if starring or already starred, want to look in list of starred images // if starring or already starred, want to look in list of starred images
if (!lastStarredImage) return true; // no starred images showing, so always show this one if (!lastStarredImage) return true; // no starred images showing, so always show this one
const createdDate = new Date(imageDTO.created_at); const createdDate = new Date(imageDTO.created_at);
const oldestDate = new Date(lastStarredImage.created_at); const oldestDate = new Date(lastStarredImage.created_at);
return createdDate >= oldestDate; return createdDate >= oldestDate;
} else { } else {
const lastUnstarredImage = cachedUnstarredImages[cachedUnstarredImages.length - 1]; const lastUnstarredImage =
cachedUnstarredImages[cachedUnstarredImages.length - 1];
// if unstarring or already unstarred, want to look in list of unstarred images // if unstarring or already unstarred, want to look in list of unstarred images
if (!lastUnstarredImage) return false; // no unstarred images showing, so don't show this one if (!lastUnstarredImage) return false; // no unstarred images showing, so don't show this one
const createdDate = new Date(imageDTO.created_at); const createdDate = new Date(imageDTO.created_at);
const oldestDate = new Date(lastUnstarredImage.created_at); const oldestDate = new Date(lastUnstarredImage.created_at);
return createdDate >= oldestDate; return createdDate >= oldestDate;
} }
}; };
export const getCategories = (imageDTO: ImageDTO) => { export const getCategories = (imageDTO: ImageDTO) => {
@ -67,7 +68,7 @@ export const imagesAdapter = createEntityAdapter<ImageDTO>({
if (!a.starred && b.starred) { if (!a.starred && b.starred) {
return 1; return 1;
} }
return dateComparator(b.created_at, a.created_at) return dateComparator(b.created_at, a.created_at);
}, },
}); });