diff --git a/packages/webgal/src/UI/Backlog/Backlog.tsx b/packages/webgal/src/UI/Backlog/Backlog.tsx index a4e0d4ec0..50717a6f3 100644 --- a/packages/webgal/src/UI/Backlog/Backlog.tsx +++ b/packages/webgal/src/UI/Backlog/Backlog.tsx @@ -23,30 +23,53 @@ export const Backlog = () => { const [indexHide, setIndexHide] = useState(false); const [isDisableScroll, setIsDisableScroll] = useState(false); const [limit, setLimit] = useState(20); - useEffect(() => { - if (!isBacklogOpen) { + const backlogContentRef = useRef(null); + const userRequestedMoreRef = useRef(false); + const isLoadingMoreRef = useRef(false); + const wheelGestureTimeoutRef = useRef>(); + const tryLoadMore = () => { + const backlogContent = backlogContentRef.current; + const backlogLength = WebGAL.backlogManager.getBacklog().length; + if ( + !isBacklogOpen || + !backlogContent || + !userRequestedMoreRef.current || + isLoadingMoreRef.current || + limit >= backlogLength + ) { + return; + } + const observeTarget = backlogContent.querySelector(`#backlog_item_${limit - 5}`); + if (!observeTarget) { return; } - let options = { - root: null, - rootMargin: '0px', - threshold: [1.0], - }; + const contentRect = backlogContent.getBoundingClientRect(); + const targetRect = observeTarget.getBoundingClientRect(); + const isTargetVisible = targetRect.top >= contentRect.top && targetRect.bottom <= contentRect.bottom; + if (!isTargetVisible) { + return; + } + userRequestedMoreRef.current = false; + isLoadingMoreRef.current = true; + setLimit((currentLimit) => Math.min(currentLimit + 20, backlogLength)); + }; - let observer = new IntersectionObserver((entries) => { - if ((entries?.[0]?.intersectionRatio ?? 0) <= 0) return; - setLimit(limit + 20); - }, options); + useEffect(() => { + isLoadingMoreRef.current = false; + }, [limit]); - const observeTarget = document.querySelector(`#backlog_item_${limit - 5}`); - if (observeTarget) { - observer.observe(observeTarget); + const handleWheel = () => { + if (!wheelGestureTimeoutRef.current) { + userRequestedMoreRef.current = true; } - - return () => { - observer.disconnect(); - }; - }, [limit, isBacklogOpen]); + if (wheelGestureTimeoutRef.current) { + clearTimeout(wheelGestureTimeoutRef.current); + } + wheelGestureTimeoutRef.current = setTimeout(() => { + wheelGestureTimeoutRef.current = undefined; + }, 200); + requestAnimationFrame(tryLoadMore); + }; useEffect(() => { if (!isBacklogOpen) { @@ -241,7 +264,18 @@ export const Backlog = () => { {GUIStore.showBacklog && ( -
+
{ + userRequestedMoreRef.current = true; + }} + onTouchMove={() => { + requestAnimationFrame(tryLoadMore); + }} + className={`${styles.backlog_content} ${isDisableScroll ? styles.Backlog_main_DisableScroll : ''}`} + > {backlogList}
)}