Skip to content

Commit cf1af94

Browse files
Mary Hipppsychedelicious
authored andcommitted
feat(ui): make jump to page a popover
1 parent 2a9fdc6 commit cf1af94

File tree

3 files changed

+114
-53
lines changed

3 files changed

+114
-53
lines changed

invokeai/frontend/web/public/locales/en.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,9 @@
381381
"featuresWillReset": "If you delete this image, those features will immediately be reset.",
382382
"galleryImageSize": "Image Size",
383383
"gallerySettings": "Gallery Settings",
384+
"go": "Go",
384385
"image": "image",
386+
"jump": "Jump",
385387
"loading": "Loading",
386388
"loadMore": "Load More",
387389
"newestFirst": "Newest First",
Lines changed: 35 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
import { Button, CompositeNumberInput, Flex, Icon, IconButton, Spacer } from '@invoke-ai/ui-library';
1+
import { Button, Flex, Icon, IconButton } from '@invoke-ai/ui-library';
22
import { ELLIPSIS, useGalleryPagination } from 'features/gallery/hooks/useGalleryPagination';
33
import { useCallback } from 'react';
44
import { PiCaretLeftBold, PiCaretRightBold, PiDotsThreeBold } from 'react-icons/pi';
55

6+
import { JumpTo } from './JumpTo';
7+
68
export const GalleryPagination = () => {
79
const { goPrev, goNext, isPrevEnabled, isNextEnabled, pageButtons, goToPage, currentPage, total } =
810
useGalleryPagination();
@@ -15,64 +17,44 @@ export const GalleryPagination = () => {
1517
goNext();
1618
}, [goNext]);
1719

18-
const onChangeJumpTo = useCallback(
19-
(v: number) => {
20-
goToPage(v - 1);
21-
},
22-
[goToPage]
23-
);
24-
2520
if (!total) {
2621
return null;
2722
}
2823

2924
return (
30-
<Flex justifyContent="space-between" alignItems="center" w="full">
31-
<Spacer w="auto" />
32-
<Flex flexGrow="1" justifyContent="center">
33-
<Flex gap={1} alignItems="center">
34-
<IconButton
35-
size="xs"
36-
aria-label="prev"
37-
icon={<PiCaretLeftBold />}
38-
onClick={onClickPrev}
39-
isDisabled={!isPrevEnabled}
40-
variant="ghost"
41-
/>
42-
{pageButtons.map((page, i) => {
43-
if (page === ELLIPSIS) {
44-
return <Icon as={PiDotsThreeBold} boxSize="4" key={`ellipsis-${i}`} />;
45-
}
46-
return (
47-
<Button
48-
size="xs"
49-
key={page}
50-
onClick={goToPage.bind(null, page - 1)}
51-
variant={currentPage === page - 1 ? 'solid' : 'outline'}
52-
>
53-
{page}
54-
</Button>
55-
);
56-
})}
57-
<IconButton
58-
size="xs"
59-
aria-label="next"
60-
icon={<PiCaretRightBold />}
61-
onClick={onClickNext}
62-
isDisabled={!isNextEnabled}
63-
variant="ghost"
64-
/>
65-
</Flex>
66-
</Flex>
67-
<CompositeNumberInput
68-
size="xs"
69-
maxW="60px"
70-
value={currentPage + 1}
71-
min={1}
72-
max={total}
73-
step={1}
74-
onChange={onChangeJumpTo}
25+
<Flex justifyContent="center" alignItems="center" w="full" gap={1}>
26+
<IconButton
27+
size="sm"
28+
aria-label="prev"
29+
icon={<PiCaretLeftBold />}
30+
onClick={onClickPrev}
31+
isDisabled={!isPrevEnabled}
32+
variant="ghost"
33+
/>
34+
{pageButtons.map((page, i) => {
35+
if (page === ELLIPSIS) {
36+
return <Icon as={PiDotsThreeBold} boxSize="4" key={`ellipsis-${i}`} />;
37+
}
38+
return (
39+
<Button
40+
size="sm"
41+
key={page}
42+
onClick={goToPage.bind(null, page - 1)}
43+
variant={currentPage === page - 1 ? 'solid' : 'outline'}
44+
>
45+
{page}
46+
</Button>
47+
);
48+
})}
49+
<IconButton
50+
size="sm"
51+
aria-label="next"
52+
icon={<PiCaretRightBold />}
53+
onClick={onClickNext}
54+
isDisabled={!isNextEnabled}
55+
variant="ghost"
7556
/>
57+
<JumpTo />
7658
</Flex>
7759
);
7860
};
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import {
2+
Button,
3+
CompositeNumberInput,
4+
Flex,
5+
FormControl,
6+
Popover,
7+
PopoverArrow,
8+
PopoverBody,
9+
PopoverContent,
10+
PopoverTrigger,
11+
useDisclosure,
12+
} from '@invoke-ai/ui-library';
13+
import { useGalleryPagination } from 'features/gallery/hooks/useGalleryPagination';
14+
import { useCallback, useEffect, useState } from 'react';
15+
import { useHotkeys } from 'react-hotkeys-hook';
16+
import { useTranslation } from 'react-i18next';
17+
18+
export const JumpTo = () => {
19+
const { t } = useTranslation();
20+
const { goToPage, currentPage, pages } = useGalleryPagination();
21+
const [newPage, setNewPage] = useState(currentPage);
22+
const { isOpen, onToggle, onClose } = useDisclosure();
23+
24+
const onChangeJumpTo = useCallback((v: number) => {
25+
setNewPage(v - 1);
26+
}, []);
27+
28+
const onClickGo = useCallback(() => {
29+
goToPage(newPage);
30+
onClose();
31+
}, [newPage, goToPage, onClose]);
32+
33+
useHotkeys(
34+
'enter',
35+
() => {
36+
if (isOpen) {
37+
onClickGo();
38+
}
39+
},
40+
[isOpen, onClickGo]
41+
);
42+
43+
useEffect(() => {
44+
setNewPage(currentPage);
45+
}, [currentPage]);
46+
47+
return (
48+
<Popover isOpen={isOpen} onClose={onClose}>
49+
<PopoverTrigger>
50+
<Button aria-label={t('gallery.jump')} size="xs" onClick={onToggle}>
51+
{t('gallery.jump')}
52+
</Button>
53+
</PopoverTrigger>
54+
<PopoverContent>
55+
<PopoverArrow />
56+
<PopoverBody>
57+
<Flex gap={2}>
58+
<FormControl>
59+
<CompositeNumberInput
60+
size="sm"
61+
maxW="60px"
62+
value={newPage + 1}
63+
min={1}
64+
max={pages}
65+
step={1}
66+
onChange={onChangeJumpTo}
67+
/>
68+
<Button size="sm" onClick={onClickGo}>
69+
{t('gallery.go')}
70+
</Button>
71+
</FormControl>
72+
</Flex>
73+
</PopoverBody>
74+
</PopoverContent>
75+
</Popover>
76+
);
77+
};

0 commit comments

Comments
 (0)