"use client"; /** * 下拉刷新 hook(占位实现) * * * * 当前实现:最小可用版本 —— 监听顶部 overscroll 触发 onRefresh。 * 后续可替换为 react-use / react-easy-refresh。 */ import { useEffect, useRef, useState } from "react"; export function usePullToRefresh( onRefresh: () => Promise | void, options: { threshold?: number; disabled?: boolean } = {}, ): { isRefreshing: boolean; pullDistance: number; containerRef: React.RefObject; } { const { threshold = 80, disabled = false } = options; const [isRefreshing, setIsRefreshing] = useState(false); const [pullDistance, setPullDistance] = useState(0); const startY = useRef(null); const containerRef = useRef(null); useEffect(() => { if (disabled || typeof window === "undefined") return; const el = containerRef.current; if (!el) return; const onTouchStart = (e: TouchEvent) => { if (el.scrollTop > 0) return; startY.current = e.touches[0]?.clientY ?? null; }; const onTouchMove = (e: TouchEvent) => { if (startY.current == null) return; const y = e.touches[0]?.clientY ?? startY.current; const delta = y - startY.current; if (delta > 0 && el.scrollTop <= 0) { setPullDistance(Math.min(delta, threshold * 1.5)); } }; const onTouchEnd = async () => { if (startY.current == null) return; if (pullDistance >= threshold && !isRefreshing) { setIsRefreshing(true); try { await onRefresh(); } finally { setIsRefreshing(false); setPullDistance(0); } } else { setPullDistance(0); } startY.current = null; }; el.addEventListener("touchstart", onTouchStart, { passive: true }); el.addEventListener("touchmove", onTouchMove, { passive: true }); el.addEventListener("touchend", onTouchEnd); return () => { el.removeEventListener("touchstart", onTouchStart); el.removeEventListener("touchmove", onTouchMove); el.removeEventListener("touchend", onTouchEnd); }; }, [threshold, disabled, isRefreshing, onRefresh, pullDistance]); return { isRefreshing, pullDistance, containerRef }; }