|
|
@@ -1,4 +1,4 @@
|
|
|
-import React, { useState, useEffect, useRef } from 'react';
|
|
|
+import React, { useState, useEffect, useRef, useCallback } from 'react';
|
|
|
import {
|
|
|
Drawer,
|
|
|
Button,
|
|
|
@@ -45,10 +45,18 @@ const VideoSelectModal: React.FC<VideoSelectModalProps> = ({ planType, visible,
|
|
|
const [videoListAll, setVideoListAll] = useState<VideoItem[]>([]);
|
|
|
const [selectedVideoIds, setSelectedVideoIds] = useState<Set<number>>(new Set(initialSelectedIds));
|
|
|
const [playingVideo, setPlayingVideo] = useState<VideoItem | null>(null);
|
|
|
- const sentinelRef = useRef<HTMLDivElement>(null);
|
|
|
+ const observerRef = useRef<IntersectionObserver | null>(null);
|
|
|
const loadingMoreRef = useRef(false);
|
|
|
+ const hasMoreRef = useRef(true);
|
|
|
+ const loadingRef = useRef(false);
|
|
|
+ const currentPageRef = useRef(1);
|
|
|
+ const getVideoListRef = useRef<(pageNum: number, append: boolean) => Promise<void>>();
|
|
|
const MAX_SELECTION = 3;
|
|
|
|
|
|
+ useEffect(() => { hasMoreRef.current = hasMore; }, [hasMore]);
|
|
|
+ useEffect(() => { loadingRef.current = loading; }, [loading]);
|
|
|
+ useEffect(() => { currentPageRef.current = currentPage; }, [currentPage]);
|
|
|
+
|
|
|
const getVideoListType = (planType: GzhPlanType) => {
|
|
|
if (planType === GzhPlanType.自动回复) {
|
|
|
return VideoSearchPlanType.自动回复;
|
|
|
@@ -99,6 +107,8 @@ const VideoSelectModal: React.FC<VideoSelectModalProps> = ({ planType, visible,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ getVideoListRef.current = getVideoList;
|
|
|
+
|
|
|
useEffect(() => {
|
|
|
if (visible) {
|
|
|
setVideoList(selectedVideos);
|
|
|
@@ -114,18 +124,17 @@ const VideoSelectModal: React.FC<VideoSelectModalProps> = ({ planType, visible,
|
|
|
}
|
|
|
}, [visible, initialSelectedIds]);
|
|
|
|
|
|
- useEffect(() => {
|
|
|
- if (!visible) return;
|
|
|
- const sentinel = sentinelRef.current;
|
|
|
- if (!sentinel) return;
|
|
|
- const observer = new IntersectionObserver((entries) => {
|
|
|
- if (entries[0].isIntersecting && hasMore && !loadingMoreRef.current && !loading) {
|
|
|
- getVideoList(currentPage + 1, true);
|
|
|
+ const sentinelRef = useCallback((node: HTMLDivElement | null) => {
|
|
|
+ observerRef.current?.disconnect();
|
|
|
+ observerRef.current = null;
|
|
|
+ if (!node) return;
|
|
|
+ observerRef.current = new IntersectionObserver((entries) => {
|
|
|
+ if (entries[0].isIntersecting && hasMoreRef.current && !loadingMoreRef.current && !loadingRef.current) {
|
|
|
+ getVideoListRef.current?.(currentPageRef.current + 1, true);
|
|
|
}
|
|
|
- }, { threshold: 0.1 });
|
|
|
- observer.observe(sentinel);
|
|
|
- return () => observer.disconnect();
|
|
|
- }, [visible, hasMore, loading, currentPage]);
|
|
|
+ }, { rootMargin: '200px' });
|
|
|
+ observerRef.current.observe(node);
|
|
|
+ }, []);
|
|
|
|
|
|
const handleSearch = () => {
|
|
|
setHasMore(true);
|
|
|
@@ -170,7 +179,6 @@ const VideoSelectModal: React.FC<VideoSelectModalProps> = ({ planType, visible,
|
|
|
onClose={onClose}
|
|
|
width={900}
|
|
|
placement="right"
|
|
|
- loading={loading}
|
|
|
styles={{ footer: { textAlign: 'right', padding: '10px 24px' } }}
|
|
|
footer={
|
|
|
<div className="flex justify-between items-center">
|
|
|
@@ -252,7 +260,7 @@ const VideoSelectModal: React.FC<VideoSelectModalProps> = ({ planType, visible,
|
|
|
})}
|
|
|
</div>
|
|
|
<div ref={sentinelRef} className="text-center py-4 text-gray-400 text-xs">
|
|
|
- {loadingMore ? '加载中...' : !hasMore && videoList.length > 0 ? '— 没有更多了 —' : ''}
|
|
|
+ {loading ? '加载中...' : loadingMore ? '加载中...' : !hasMore && videoList.length > 0 ? '— 没有更多了 —' : ''}
|
|
|
</div>
|
|
|
</Drawer>
|
|
|
|