Files
InvokeAI/invokeai/frontend/web/src/features/system/components/StatusIndicator.tsx
psychedelicious 72cb8b83fe feat(ui): upgrade redux and RTK
There are a few breaking changes, which I've addressed.

The vast majority of changes are related to new handling of `reselect`'s `createSelector` options.

For better or worse, we memoize just about all our selectors using lodash `isEqual` for `resultEqualityCheck`. The upgrade requires we explicitly set the `memoize` option to `lruMemoize` to continue using lodash here.

Doing that required changing our `defaultSelectorOptions`.

Instead of changing that and finding dozens of instances where we weren't using that and instead were defining selector options manually, I've created a pre-configured selector: `createMemoizedSelector`.

This is now used everywhere instead of `createSelector`.
2023-12-09 16:09:26 +11:00

106 lines
2.7 KiB
TypeScript

import { Flex, Icon, Text } from '@chakra-ui/react';
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
import { stateSelector } from 'app/store/store';
import { useAppSelector } from 'app/store/storeHooks';
import { STATUS_TRANSLATION_KEYS } from 'features/system/store/types';
import { AnimatePresence, motion } from 'framer-motion';
import { ResourceKey } from 'i18next';
import { memo, useMemo, useRef } from 'react';
import { useTranslation } from 'react-i18next';
import { FaCircle } from 'react-icons/fa';
import { useHoverDirty } from 'react-use';
import { useGetQueueStatusQuery } from 'services/api/endpoints/queue';
const statusIndicatorSelector = createMemoizedSelector(
stateSelector,
({ system }) => {
const { isConnected, status } = system;
return {
isConnected,
statusTranslationKey: STATUS_TRANSLATION_KEYS[status],
};
}
);
const DARK_COLOR_MAP = {
ok: 'green.400',
working: 'yellow.400',
error: 'red.400',
};
const LIGHT_COLOR_MAP = {
ok: 'green.600',
working: 'yellow.500',
error: 'red.500',
};
const StatusIndicator = () => {
const { isConnected, statusTranslationKey } = useAppSelector(
statusIndicatorSelector
);
const { t } = useTranslation();
const ref = useRef(null);
const { data: queueStatus } = useGetQueueStatusQuery();
const statusColor = useMemo(() => {
if (!isConnected) {
return 'error';
}
if (queueStatus?.queue.in_progress) {
return 'working';
}
return 'ok';
}, [queueStatus?.queue.in_progress, isConnected]);
const isHovered = useHoverDirty(ref);
return (
<Flex ref={ref} h="full" px={2} alignItems="center" gap={5}>
<AnimatePresence>
{isHovered && (
<motion.div
key="statusText"
initial={{
opacity: 0,
}}
animate={{
opacity: 1,
transition: { duration: 0.15 },
}}
exit={{
opacity: 0,
transition: { delay: 0.8 },
}}
>
<Text
sx={{
fontSize: 'sm',
fontWeight: '600',
pb: '1px',
userSelect: 'none',
color: LIGHT_COLOR_MAP[statusColor],
_dark: { color: DARK_COLOR_MAP[statusColor] },
}}
>
{t(statusTranslationKey as ResourceKey)}
</Text>
</motion.div>
)}
</AnimatePresence>
<Icon
as={FaCircle}
sx={{
boxSize: '0.5rem',
color: LIGHT_COLOR_MAP[statusColor],
_dark: { color: DARK_COLOR_MAP[statusColor] },
}}
/>
</Flex>
);
};
export default memo(StatusIndicator);