File size: 1,861 Bytes
8a37e0a | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | import { Badge, Portal } from '@invoke-ai/ui-library';
import { useStore } from '@nanostores/react';
import { $isLeftPanelOpen } from 'features/ui/store/uiSlice';
import type { RefObject } from 'react';
import { memo, useEffect, useState } from 'react';
import { useGetQueueStatusQuery } from 'services/api/endpoints/queue';
type Props = {
targetRef: RefObject<HTMLDivElement>;
};
export const QueueCountBadge = memo(({ targetRef }: Props) => {
const [badgePos, setBadgePos] = useState<{ x: string; y: string } | null>(null);
const isParametersPanelOpen = useStore($isLeftPanelOpen);
const { queueSize } = useGetQueueStatusQuery(undefined, {
selectFromResult: (res) => ({
queueSize: res.data ? res.data.queue.pending + res.data.queue.in_progress : 0,
}),
});
useEffect(() => {
if (!targetRef.current) {
return;
}
const target = targetRef.current;
const parent = target.parentElement;
if (!parent) {
return;
}
const cb = () => {
if (!$isLeftPanelOpen.get()) {
return;
}
const { x, y } = target.getBoundingClientRect();
setBadgePos({ x: `${x - 7}px`, y: `${y - 5}px` });
};
const resizeObserver = new ResizeObserver(cb);
resizeObserver.observe(parent);
cb();
return () => {
resizeObserver.disconnect();
};
}, [targetRef]);
if (queueSize === 0) {
return null;
}
if (!badgePos) {
return null;
}
if (!isParametersPanelOpen) {
return null;
}
return (
<Portal>
<Badge
pos="absolute"
insetInlineStart={badgePos.x}
insetBlockStart={badgePos.y}
colorScheme="invokeYellow"
zIndex="docked"
shadow="dark-lg"
userSelect="none"
>
{queueSize}
</Badge>
</Portal>
);
});
QueueCountBadge.displayName = 'QueueCountBadge';
|