diff --git a/app/courrier/page.tsx b/app/courrier/page.tsx index 0d086d1b..e0820d22 100644 --- a/app/courrier/page.tsx +++ b/app/courrier/page.tsx @@ -151,36 +151,9 @@ export default function CourrierPage() { setLoading(true); // First check if Redis is ready before making API calls - // Use a cache mechanism to reduce frequency of Redis status checks - const redisCheckCacheKey = 'neah_redis_status_check'; - const cachedRedisCheck = localStorage.getItem(redisCheckCacheKey); - let redisStatus = { ready: false }; - - if (cachedRedisCheck) { - try { - const { status, timestamp } = JSON.parse(cachedRedisCheck); - // Only use cache if it's less than 2 minutes old - if (Date.now() - timestamp < 2 * 60 * 1000) { - redisStatus = status; - console.log('Using cached Redis status check'); - } - } catch (e) { - // Invalid JSON in cache, ignore and fetch fresh status - } - } - - // Only check Redis status if we don't have a recent cached result - if (!redisStatus.ready) { - redisStatus = await fetch('/api/redis/status') - .then(res => res.json()) - .catch(() => ({ ready: false })); - - // Cache the result - localStorage.setItem(redisCheckCacheKey, JSON.stringify({ - status: redisStatus, - timestamp: Date.now() - })); - } + const redisStatus = await fetch('/api/redis/status') + .then(res => res.json()) + .catch(() => ({ ready: false })); if (!isMounted) return; @@ -273,28 +246,15 @@ export default function CourrierPage() { const nextPage = page + 1; setPage(nextPage); - console.log(`Requesting page ${nextPage} for folder ${currentFolder}`); - - // Immediately trigger a load for this page rather than relying on the useEffect - // This helps ensure we get the data faster - loadEmails(true).catch(error => { - console.error(`Error loading page ${nextPage}:`, error); - }); - // Also prefetch additional pages to make scrolling smoother if (session?.user?.id) { - // Prefetch next page beyond the one we're loading - const pagesToPrefetch = 2; // Prefetch 2 pages ahead - - // Small delay to let the current request start first - setTimeout(() => { - console.log(`Prefetching pages ${nextPage + 1} to ${nextPage + pagesToPrefetch}`); - prefetchFolderEmails(session.user.id, currentFolder, pagesToPrefetch, nextPage + 1) - .catch(err => { - console.error(`Error prefetching additional pages for ${currentFolder}:`, err); - }); - }, 200); + // Prefetch next 2 pages beyond the current next page + prefetchFolderEmails(session.user.id, currentFolder, 2, nextPage + 1).catch(err => { + console.error(`Error prefetching additional pages for ${currentFolder}:`, err); + }); } + + // Note: loadEmails will be called automatically due to the page dependency in useEffect } }; @@ -400,8 +360,7 @@ export default function CourrierPage() { return ( <> - {/* Only render RedisCacheStatus in development mode to avoid unnecessary status checks */} - {process.env.NODE_ENV === 'development' && } + {/* Main layout */}
diff --git a/components/email/EmailList.tsx b/components/email/EmailList.tsx index 26df0b10..94480b2c 100644 --- a/components/email/EmailList.tsx +++ b/components/email/EmailList.tsx @@ -44,20 +44,10 @@ export default function EmailList({ const [scrollPosition, setScrollPosition] = useState(0); const [searchQuery, setSearchQuery] = useState(''); const [isLoadingMore, setIsLoadingMore] = useState(false); - const [lastLoadTime, setLastLoadTime] = useState(0); const scrollRef = useRef(null); const scrollTimeoutRef = useRef(null); - const loadMoreTimeoutRef = useRef(null); const prevEmailsLengthRef = useRef(emails.length); - // Clear any pending timeouts on unmount - useEffect(() => { - return () => { - if (scrollTimeoutRef.current) clearTimeout(scrollTimeoutRef.current); - if (loadMoreTimeoutRef.current) clearTimeout(loadMoreTimeoutRef.current); - }; - }, []); - // Debounced scroll handler for better performance const handleScroll = useCallback((event: React.UIEvent) => { const target = event.target as HTMLDivElement; @@ -71,37 +61,25 @@ export default function EmailList({ clearTimeout(scrollTimeoutRef.current); } - // If near bottom (within 300px) and more emails are available, load more + // If near bottom (within 200px) and more emails are available, load more // Added additional checks to prevent loading loop - const isNearBottom = scrollHeight - scrollTop - clientHeight < 300; - - // Don't trigger load if we're already loading or if the last load was too recent (throttle) - const now = Date.now(); - const timeSinceLastLoad = now - lastLoadTime; - const tooSoonToLoadAgain = timeSinceLastLoad < 2000; // 2 seconds throttle - - if (isNearBottom && hasMoreEmails && !isLoading && !isLoadingMore && !tooSoonToLoadAgain) { + const isNearBottom = scrollHeight - scrollTop - clientHeight < 200; + if (isNearBottom && hasMoreEmails && !isLoading && !isLoadingMore) { setIsLoadingMore(true); - setLastLoadTime(now); // Use timeout to debounce load requests scrollTimeoutRef.current = setTimeout(() => { // Clear the timeout reference before loading scrollTimeoutRef.current = null; - - console.log('Loading more emails from scroll trigger'); onLoadMore(); // Reset loading state after a delay - if (loadMoreTimeoutRef.current) clearTimeout(loadMoreTimeoutRef.current); - loadMoreTimeoutRef.current = setTimeout(() => { - loadMoreTimeoutRef.current = null; - console.log('Resetting loading more state after timeout'); + setTimeout(() => { setIsLoadingMore(false); - }, 2000); // Reduced from 3000ms to 2000ms to avoid long loading states - }, 200); // Reduced from 300ms to 200ms for better responsiveness + }, 1500); // Increased from 1000ms to 1500ms to prevent quick re-triggering + }, 200); // Increased from 100ms to 200ms for better debouncing } - }, [hasMoreEmails, isLoading, isLoadingMore, onLoadMore, lastLoadTime]); + }, [hasMoreEmails, isLoading, isLoadingMore, onLoadMore]); // Restore scroll position when emails are loaded useEffect(() => { @@ -112,13 +90,8 @@ export default function EmailList({ // 4. We're not in the middle of a loading operation if (emails.length > prevEmailsLengthRef.current && scrollRef.current && - scrollPosition > 0) { - // If emails have been loaded, force reset the loading state - if (isLoadingMore) { - console.log('Emails loaded, resetting loading state'); - setIsLoadingMore(false); - } - + scrollPosition > 0 && + !isLoading) { // Use requestAnimationFrame to ensure the DOM has updated requestAnimationFrame(() => { if (scrollRef.current) { @@ -130,26 +103,7 @@ export default function EmailList({ // Always update the reference for next comparison prevEmailsLengthRef.current = emails.length; - }, [emails.length, scrollPosition, isLoadingMore]); - - // Add safety mechanism to reset loading state if we get stuck - useEffect(() => { - // If we have more emails now but still in loading state, reset it - if (emails.length > prevEmailsLengthRef.current && isLoadingMore) { - console.log('Safety reset: Clearing loading state after emails updated'); - setIsLoadingMore(false); - } - - // Add a timeout-based safety mechanism - reduced from 5000ms to 3000ms - const safetyTimeout = setTimeout(() => { - if (isLoadingMore) { - console.log('Safety timeout: Resetting stuck loading state'); - setIsLoadingMore(false); - } - }, 3000); - - return () => clearTimeout(safetyTimeout); - }, [emails.length, isLoadingMore]); + }, [emails.length, scrollPosition, isLoading]); // Add listener for custom reset scroll event useEffect(() => { @@ -303,20 +257,15 @@ export default function EmailList({ {/* Loading indicator */} {(isLoading || isLoadingMore) && ( -
- - Loading more emails... +
+
)} {/* Load more button - only show when near bottom but not auto-loading */} {hasMoreEmails && !isLoading && !isLoadingMore && (