gallery autoscroll attempt 2

This commit is contained in:
psychedelicious 2023-12-10 00:02:38 +11:00
parent f551c7c013
commit 0d17dc8817
4 changed files with 66 additions and 29 deletions

View File

@ -55,7 +55,7 @@ const GalleryImage = (props: HoverableImageProps) => {
selectionCount !== 1 ||
!virtuosoContext.rootRef.current ||
!virtuosoContext.virtuosoRef.current ||
!virtuosoContext.rangeRef.current ||
!virtuosoContext.virtuosoRangeRef.current ||
!imageContainerRef.current
) {
return;
@ -64,7 +64,7 @@ const GalleryImage = (props: HoverableImageProps) => {
const root = virtuosoContext.rootRef.current;
const virtuoso = virtuosoContext.virtuosoRef.current;
const item = imageContainerRef.current;
const range = virtuosoContext.rangeRef.current;
const range = virtuosoContext.virtuosoRangeRef.current;
const itemRect = item.getBoundingClientRect();
const rootRect = root.getBoundingClientRect();
const itemIsVisible =
@ -88,7 +88,7 @@ const GalleryImage = (props: HoverableImageProps) => {
isSelected,
props.index,
selectionCount,
virtuosoContext.rangeRef,
virtuosoContext.virtuosoRangeRef,
virtuosoContext.rootRef,
virtuosoContext.virtuosoRef,
]);

View File

@ -4,6 +4,7 @@ import { useAppSelector } from 'app/store/storeHooks';
import IAIButton from 'common/components/IAIButton';
import { IAINoContentFallback } from 'common/components/IAIImageFallback';
import { VirtuosoGalleryContext } from 'features/gallery/components/ImageGrid/types';
import { $useNextPrevImageState } from 'features/gallery/hooks/useNextPrevImage';
import { selectListImagesBaseQueryArgs } from 'features/gallery/store/gallerySelectors';
import { IMAGE_LIMIT } from 'features/gallery/store/types';
import {
@ -62,8 +63,7 @@ const GalleryImageGrid = () => {
);
const { currentViewTotal } = useBoardTotal(selectedBoardId);
const queryArgs = useAppSelector(selectListImagesBaseQueryArgs);
const rangeRef = useRef<ListRange | null>(null);
// const lastSingleSelectionImage = useAppSelector(selector);
const virtuosoRangeRef = useRef<ListRange | null>(null);
const virtuosoRef = useRef<VirtuosoGridHandle>(null);
@ -72,11 +72,6 @@ const GalleryImageGrid = () => {
const [listImages] = useLazyListImagesQuery();
// const [visibleRange, setVisibleRange] = useState({
// startIndex: 0,
// endIndex: 0,
// });
const areMoreAvailable = useMemo(() => {
if (!currentData || !currentViewTotal) {
return false;
@ -100,7 +95,7 @@ const GalleryImageGrid = () => {
return {
virtuosoRef,
rootRef,
rangeRef,
virtuosoRangeRef,
};
}, []);
@ -132,20 +127,13 @@ const GalleryImageGrid = () => {
}, [scroller, initialize, osInstance]);
const onRangeChanged = useCallback((range: ListRange) => {
rangeRef.current = range;
virtuosoRangeRef.current = range;
}, []);
// useEffect(() => {
// if (lastSingleSelectionImage && currentData) {
// const index = currentData.ids.indexOf(lastSingleSelectionImage);
// if (index >= visibleRange.startIndex && index <= visibleRange.endIndex) {
// virtuosoRef.current?.scrollToIndex({
// index: index,
// align: 'center',
// });
// }
// }
// }, [visibleRange, lastSingleSelectionImage, currentData]);
useEffect(() => {
$useNextPrevImageState.setKey('virtuosoRef', virtuosoRef);
$useNextPrevImageState.setKey('virtuosoRangeRef', virtuosoRangeRef);
}, []);
if (!currentData) {
return (
@ -197,6 +185,7 @@ const GalleryImageGrid = () => {
ref={virtuosoRef}
rangeChanged={onRangeChanged}
context={virtuosoContext}
overscan={10}
/>
</Box>
<IAIButton

View File

@ -4,5 +4,5 @@ import { ListRange, VirtuosoGridHandle } from 'react-virtuoso';
export type VirtuosoGalleryContext = {
virtuosoRef: RefObject<VirtuosoGridHandle>;
rootRef: RefObject<HTMLDivElement>;
rangeRef: RefObject<ListRange>;
virtuosoRangeRef: RefObject<ListRange>;
};

View File

@ -3,16 +3,28 @@ import { stateSelector } from 'app/store/store';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { imageSelected } from 'features/gallery/store/gallerySlice';
import { clamp, isEqual } from 'lodash-es';
import { useCallback } from 'react';
import { map } from 'nanostores';
import { RefObject, useCallback } from 'react';
import { ListRange, VirtuosoGridHandle } from 'react-virtuoso';
import { boardsApi } from 'services/api/endpoints/boards';
import {
imagesApi,
useLazyListImagesQuery,
} from 'services/api/endpoints/images';
import { selectListImagesBaseQueryArgs } from '../store/gallerySelectors';
import { IMAGE_LIMIT } from '../store/types';
import { ListImagesArgs } from 'services/api/types';
import { imagesAdapter } from 'services/api/util';
import { selectListImagesBaseQueryArgs } from '../store/gallerySelectors';
import { IMAGE_LIMIT } from '../store/types';
export type UseNextPrevImageState = {
virtuosoRef: RefObject<VirtuosoGridHandle> | undefined;
virtuosoRangeRef: RefObject<ListRange> | undefined;
};
export const $useNextPrevImageState = map<UseNextPrevImageState>({
virtuosoRef: undefined,
virtuosoRangeRef: undefined,
});
export const nextPrevImageButtonsSelector = createSelector(
[stateSelector, selectListImagesBaseQueryArgs],
@ -78,6 +90,8 @@ export const nextPrevImageButtonsSelector = createSelector(
isFetching: status === 'pending',
nextImage,
prevImage,
nextImageIndex,
prevImageIndex,
queryArgs,
};
},
@ -93,7 +107,9 @@ export const useNextPrevImage = () => {
const {
nextImage,
nextImageIndex,
prevImage,
prevImageIndex,
areMoreImagesAvailable,
isFetching,
queryArgs,
@ -103,11 +119,43 @@ export const useNextPrevImage = () => {
const handlePrevImage = useCallback(() => {
prevImage && dispatch(imageSelected(prevImage));
}, [dispatch, prevImage]);
const range = $useNextPrevImageState.get().virtuosoRangeRef?.current;
const virtuoso = $useNextPrevImageState.get().virtuosoRef?.current;
if (!range || !virtuoso) {
return;
}
if (
prevImageIndex !== undefined &&
(prevImageIndex < range.startIndex || prevImageIndex > range.endIndex)
) {
virtuoso.scrollToIndex({
index: prevImageIndex,
behavior: 'smooth',
align: 'start',
});
}
}, [dispatch, prevImage, prevImageIndex]);
const handleNextImage = useCallback(() => {
nextImage && dispatch(imageSelected(nextImage));
}, [dispatch, nextImage]);
const range = $useNextPrevImageState.get().virtuosoRangeRef?.current;
const virtuoso = $useNextPrevImageState.get().virtuosoRef?.current;
if (!range || !virtuoso) {
return;
}
if (
nextImageIndex !== undefined &&
(nextImageIndex < range.startIndex || nextImageIndex > range.endIndex)
) {
virtuoso.scrollToIndex({
index: nextImageIndex,
behavior: 'smooth',
align: 'end',
});
}
}, [dispatch, nextImage, nextImageIndex]);
const [listImages] = useLazyListImagesQuery();