mirror of
https://github.com/invoke-ai/InvokeAI.git
synced 2026-02-13 09:34:59 -05:00
106 lines
3.3 KiB
TypeScript
106 lines
3.3 KiB
TypeScript
import { Box, Flex } from '@invoke-ai/ui-library';
|
|
import { useAppSelector } from 'app/store/storeHooks';
|
|
import { CanvasAlertsInvocationProgress } from 'features/controlLayers/components/CanvasAlerts/CanvasAlertsInvocationProgress';
|
|
import { DndImage } from 'features/dnd/DndImage';
|
|
import ImageMetadataViewer from 'features/gallery/components/ImageMetadataViewer/ImageMetadataViewer';
|
|
import NextPrevImageButtons from 'features/gallery/components/NextPrevImageButtons';
|
|
import { selectShouldShowImageDetails } from 'features/ui/store/uiSelectors';
|
|
import type { AnimationProps } from 'framer-motion';
|
|
import { AnimatePresence, motion } from 'framer-motion';
|
|
import { memo, useCallback, useRef, useState } from 'react';
|
|
import type { ImageDTO } from 'services/api/types';
|
|
|
|
import { NoContentForViewer } from './NoContentForViewer';
|
|
|
|
export const CurrentImagePreview = memo(({ imageDTO }: { imageDTO?: ImageDTO }) => {
|
|
const shouldShowImageDetails = useAppSelector(selectShouldShowImageDetails);
|
|
|
|
// Show and hide the next/prev buttons on mouse move
|
|
const [shouldShowNextPrevButtons, setShouldShowNextPrevButtons] = useState<boolean>(false);
|
|
const timeoutId = useRef(0);
|
|
const onMouseOver = useCallback(() => {
|
|
setShouldShowNextPrevButtons(true);
|
|
window.clearTimeout(timeoutId.current);
|
|
}, []);
|
|
const onMouseOut = useCallback(() => {
|
|
timeoutId.current = window.setTimeout(() => {
|
|
setShouldShowNextPrevButtons(false);
|
|
}, 500);
|
|
}, []);
|
|
|
|
return (
|
|
<Flex
|
|
onMouseOver={onMouseOver}
|
|
onMouseOut={onMouseOut}
|
|
width="full"
|
|
height="full"
|
|
alignItems="center"
|
|
justifyContent="center"
|
|
position="relative"
|
|
>
|
|
<ImageContent imageDTO={imageDTO} />
|
|
<Flex
|
|
flexDir="column"
|
|
gap={2}
|
|
position="absolute"
|
|
top={0}
|
|
insetInlineStart={0}
|
|
pointerEvents="none"
|
|
alignItems="flex-start"
|
|
>
|
|
<CanvasAlertsInvocationProgress />
|
|
</Flex>
|
|
{shouldShowImageDetails && imageDTO && (
|
|
<Box position="absolute" opacity={0.8} top={0} width="full" height="full" borderRadius="base">
|
|
<ImageMetadataViewer image={imageDTO} />
|
|
</Box>
|
|
)}
|
|
<AnimatePresence>
|
|
{shouldShowNextPrevButtons && imageDTO && (
|
|
<Box
|
|
as={motion.div}
|
|
key="nextPrevButtons"
|
|
initial={initial}
|
|
animate={animateArrows}
|
|
exit={exit}
|
|
position="absolute"
|
|
top={0}
|
|
right={0}
|
|
bottom={0}
|
|
left={0}
|
|
pointerEvents="none"
|
|
>
|
|
<NextPrevImageButtons />
|
|
</Box>
|
|
)}
|
|
</AnimatePresence>
|
|
</Flex>
|
|
);
|
|
});
|
|
CurrentImagePreview.displayName = 'CurrentImagePreview';
|
|
|
|
const ImageContent = memo(({ imageDTO }: { imageDTO?: ImageDTO }) => {
|
|
if (!imageDTO) {
|
|
return <NoContentForViewer />;
|
|
}
|
|
|
|
return (
|
|
<Flex w="full" h="full" position="absolute" alignItems="center" justifyContent="center">
|
|
<DndImage imageDTO={imageDTO} />
|
|
</Flex>
|
|
);
|
|
});
|
|
ImageContent.displayName = 'ImageContent';
|
|
|
|
const initial: AnimationProps['initial'] = {
|
|
opacity: 0,
|
|
};
|
|
const animateArrows: AnimationProps['animate'] = {
|
|
opacity: 1,
|
|
transition: { duration: 0.07 },
|
|
};
|
|
const exit: AnimationProps['exit'] = {
|
|
opacity: 0,
|
|
transition: { duration: 0.07 },
|
|
};
|