"use client"; import { useEffect } from "react"; import type { Dispatch, MutableRefObject, SetStateAction } from "react"; import { isEditableTarget } from "@/features/entries/components/entries-panel.utils"; type UseInfiniteVisibleCountParams = { enabled: boolean; hasMore: boolean; totalCount: number; pageSize: number; sentinelRef: MutableRefObject; setVisibleCount: Dispatch>; }; export default function useInfiniteVisibleCount({ enabled, hasMore, totalCount, pageSize, sentinelRef, setVisibleCount }: UseInfiniteVisibleCountParams) { useEffect(() => { if (!enabled || !hasMore) return; let touchY: number | null = null; let lastLoadAt = 0; let lastScrollY = window.scrollY; function shouldLoadMore() { const sentinel = sentinelRef.current; if (!sentinel) return false; const rect = sentinel.getBoundingClientRect(); return rect.top <= window.innerHeight + 48; } function tryLoadMore() { if (!shouldLoadMore()) return; const now = Date.now(); if (now - lastLoadAt < 150) return; lastLoadAt = now; setVisibleCount(prev => { if (prev >= totalCount) return prev; return Math.min(prev + pageSize, totalCount); }); } function onWheel(event: WheelEvent) { if (event.deltaY <= 0) return; tryLoadMore(); } function onScroll() { const nextY = window.scrollY; if (nextY <= lastScrollY) { lastScrollY = nextY; return; } lastScrollY = nextY; tryLoadMore(); } function onKeyDown(event: KeyboardEvent) { if (isEditableTarget(event.target)) return; if (event.key === "ArrowDown" || event.key === "PageDown" || event.key === "End" || (event.key === " " && !event.shiftKey)) { tryLoadMore(); } } function onTouchStart(event: TouchEvent) { touchY = event.touches[0]?.clientY ?? null; } function onTouchMove(event: TouchEvent) { const nextY = event.touches[0]?.clientY; if (touchY == null || nextY == null) return; const delta = touchY - nextY; touchY = nextY; if (delta > 10) tryLoadMore(); } window.addEventListener("wheel", onWheel, { passive: true }); window.addEventListener("scroll", onScroll, { passive: true }); window.addEventListener("keydown", onKeyDown); window.addEventListener("touchstart", onTouchStart, { passive: true }); window.addEventListener("touchmove", onTouchMove, { passive: true }); return () => { window.removeEventListener("wheel", onWheel); window.removeEventListener("scroll", onScroll); window.removeEventListener("keydown", onKeyDown); window.removeEventListener("touchstart", onTouchStart); window.removeEventListener("touchmove", onTouchMove); }; }, [enabled, hasMore, pageSize, sentinelRef, setVisibleCount, totalCount]); }