courrier correct panel 2 scroll up
This commit is contained in:
parent
a6bd553a27
commit
ceca769cbf
@ -246,15 +246,28 @@ 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 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);
|
||||
});
|
||||
// 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);
|
||||
}
|
||||
|
||||
// Note: loadEmails will be called automatically due to the page dependency in useEffect
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -63,7 +63,7 @@ export default function EmailList({
|
||||
|
||||
// If near bottom (within 200px) and more emails are available, load more
|
||||
// Added additional checks to prevent loading loop
|
||||
const isNearBottom = scrollHeight - scrollTop - clientHeight < 200;
|
||||
const isNearBottom = scrollHeight - scrollTop - clientHeight < 300; // Increased detection area
|
||||
if (isNearBottom && hasMoreEmails && !isLoading && !isLoadingMore) {
|
||||
setIsLoadingMore(true);
|
||||
|
||||
@ -71,13 +71,16 @@ export default function EmailList({
|
||||
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
|
||||
setTimeout(() => {
|
||||
console.log('Resetting loading more state after timeout');
|
||||
setIsLoadingMore(false);
|
||||
}, 1500); // Increased from 1000ms to 1500ms to prevent quick re-triggering
|
||||
}, 200); // Increased from 100ms to 200ms for better debouncing
|
||||
}, 3000); // Increased from 1500ms to 3000ms to allow more time for loading
|
||||
}, 300); // Increased from 200ms to 300ms for better debouncing
|
||||
}
|
||||
}, [hasMoreEmails, isLoading, isLoadingMore, onLoadMore]);
|
||||
|
||||
@ -105,6 +108,25 @@ export default function EmailList({
|
||||
prevEmailsLengthRef.current = emails.length;
|
||||
}, [emails.length, scrollPosition, isLoading]);
|
||||
|
||||
// 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
|
||||
const safetyTimeout = setTimeout(() => {
|
||||
if (isLoadingMore) {
|
||||
console.log('Safety timeout: Resetting stuck loading state');
|
||||
setIsLoadingMore(false);
|
||||
}
|
||||
}, 5000);
|
||||
|
||||
return () => clearTimeout(safetyTimeout);
|
||||
}, [emails.length, isLoadingMore]);
|
||||
|
||||
// Add listener for custom reset scroll event
|
||||
useEffect(() => {
|
||||
const handleResetScroll = () => {
|
||||
@ -258,14 +280,18 @@ export default function EmailList({
|
||||
{/* Loading indicator */}
|
||||
{(isLoading || isLoadingMore) && (
|
||||
<div className="flex items-center justify-center p-4">
|
||||
<Loader2 className="h-4 w-4 text-blue-500 animate-spin" />
|
||||
<Loader2 className="h-4 w-4 text-blue-500 animate-spin mr-2" />
|
||||
<span className="text-sm text-gray-500">Loading more emails...</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Load more button - only show when near bottom but not auto-loading */}
|
||||
{hasMoreEmails && !isLoading && !isLoadingMore && (
|
||||
<button
|
||||
onClick={onLoadMore}
|
||||
onClick={() => {
|
||||
console.log('Manual load more triggered');
|
||||
onLoadMore();
|
||||
}}
|
||||
className="w-full py-2 text-gray-500 hover:bg-gray-100 text-sm"
|
||||
>
|
||||
Load more emails
|
||||
|
||||
@ -80,15 +80,24 @@ export const useCourrier = () => {
|
||||
const loadEmails = useCallback(async (isLoadMore = false) => {
|
||||
if (!session?.user?.id) return;
|
||||
|
||||
console.log(`Loading emails for folder ${currentFolder}, page ${page}, isLoadMore: ${isLoadMore}`);
|
||||
|
||||
// If already loading, don't trigger multiple simultaneous requests
|
||||
if (isLoading) {
|
||||
console.log('Skipping loadEmails - already loading');
|
||||
return;
|
||||
}
|
||||
|
||||
setIsLoading(true);
|
||||
setError(null);
|
||||
|
||||
// Keep reference to the current page for this request
|
||||
const currentRequestPage = page;
|
||||
const requestStartTime = Date.now();
|
||||
|
||||
try {
|
||||
// First try Redis cache with low timeout
|
||||
const cachedEmails = await getCachedEmailsWithTimeout(session.user.id, currentFolder, currentRequestPage, perPage, 100);
|
||||
const cachedEmails = await getCachedEmailsWithTimeout(session.user.id, currentFolder, currentRequestPage, perPage, 200);
|
||||
if (cachedEmails) {
|
||||
// Ensure cached data has emails array property
|
||||
if (Array.isArray(cachedEmails.emails)) {
|
||||
@ -101,7 +110,7 @@ export const useCourrier = () => {
|
||||
const newEmails = cachedEmails.emails.filter((email: Email) => !existingIds.has(email.id));
|
||||
|
||||
// Log pagination info
|
||||
console.log(`Added ${newEmails.length} cached emails from page ${currentRequestPage} to existing ${prevEmails.length} emails`);
|
||||
console.log(`Added ${newEmails.length} cached emails from page ${currentRequestPage} to existing ${prevEmails.length} emails (${Date.now() - requestStartTime}ms)`);
|
||||
|
||||
// Combine emails and sort them by date (newest first)
|
||||
const combinedEmails = [...prevEmails, ...newEmails];
|
||||
@ -109,7 +118,7 @@ export const useCourrier = () => {
|
||||
});
|
||||
} else {
|
||||
// For initial load, replace emails
|
||||
console.log(`Setting ${cachedEmails.emails.length} cached emails for page ${currentRequestPage}`);
|
||||
console.log(`Setting ${cachedEmails.emails.length} cached emails for page ${currentRequestPage} (${Date.now() - requestStartTime}ms)`);
|
||||
// Ensure emails are sorted by date (newest first)
|
||||
setEmails(cachedEmails.emails.sort((a: Email, b: Email) => new Date(b.date).getTime() - new Date(a.date).getTime()));
|
||||
}
|
||||
@ -187,7 +196,7 @@ export const useCourrier = () => {
|
||||
const newEmails = data.emails.filter((email: Email) => !existingIds.has(email.id));
|
||||
|
||||
// Log pagination info
|
||||
console.log(`Added ${newEmails.length} fetched emails from page ${currentRequestPage} to existing ${prev.length} emails`);
|
||||
console.log(`Added ${newEmails.length} fetched emails from page ${currentRequestPage} to existing ${prev.length} emails (${Date.now() - requestStartTime}ms)`);
|
||||
|
||||
// Combine emails and sort them by date (newest first)
|
||||
const combinedEmails = [...prev, ...newEmails];
|
||||
@ -230,6 +239,7 @@ export const useCourrier = () => {
|
||||
description: err instanceof Error ? err.message : 'Failed to load emails'
|
||||
});
|
||||
} finally {
|
||||
console.log(`Completed loading emails for page ${currentRequestPage} (${Date.now() - requestStartTime}ms)`);
|
||||
setIsLoading(false);
|
||||
}
|
||||
}, [currentFolder, page, perPage, searchQuery, session?.user?.id, toast]);
|
||||
@ -239,7 +249,11 @@ export const useCourrier = () => {
|
||||
if (session?.user?.id) {
|
||||
// If page is greater than 1, we're loading more emails
|
||||
const isLoadingMore = page > 1;
|
||||
loadEmails(isLoadingMore);
|
||||
|
||||
// Add a small delay to prevent rapid consecutive loads
|
||||
const loadTimer = setTimeout(() => {
|
||||
loadEmails(isLoadingMore);
|
||||
}, 50);
|
||||
|
||||
// If we're loading the first page, publish an event to reset scroll position
|
||||
if (page === 1 && typeof window !== 'undefined') {
|
||||
@ -247,8 +261,10 @@ export const useCourrier = () => {
|
||||
const event = new CustomEvent('reset-email-scroll');
|
||||
window.dispatchEvent(event);
|
||||
}
|
||||
|
||||
return () => clearTimeout(loadTimer);
|
||||
}
|
||||
}, [currentFolder, page, perPage, session?.user?.id, loadEmails]);
|
||||
}, [currentFolder, page, session?.user?.id, loadEmails]);
|
||||
|
||||
// Fetch a single email's content
|
||||
const fetchEmailContent = useCallback(async (emailId: string) => {
|
||||
|
||||
@ -19,7 +19,7 @@ export async function getCachedEmailsWithTimeout(
|
||||
folder: string,
|
||||
page: number,
|
||||
perPage: number,
|
||||
timeoutMs: number = 100
|
||||
timeoutMs: number = 200
|
||||
): Promise<any | null> {
|
||||
return new Promise((resolve) => {
|
||||
const timeoutId = setTimeout(() => {
|
||||
@ -73,16 +73,29 @@ export async function refreshEmailsInBackground(
|
||||
page: number = 1,
|
||||
perPage: number = 20
|
||||
): Promise<void> {
|
||||
// Track ongoing refreshes to avoid duplicates
|
||||
const refreshKey = `${userId}:${folder}:${page}`;
|
||||
|
||||
// Use a higher priority for inbox and small page numbers
|
||||
const priority = folder === 'INBOX' && page <= 2 ? 100 : 300;
|
||||
|
||||
// Use setTimeout to ensure this runs after current execution context
|
||||
setTimeout(async () => {
|
||||
try {
|
||||
console.log(`Background refresh for ${userId}:${folder}:${page}:${perPage}`);
|
||||
const freshData = await getEmails(userId, folder, page, perPage);
|
||||
console.log(`Background refresh completed for ${userId}:${folder}`);
|
||||
console.log(`Background refresh completed for ${userId}:${folder}:${page} with ${freshData.emails.length} emails`);
|
||||
|
||||
// If it's the inbox and there's a next page, prefetch that too
|
||||
if (folder === 'INBOX' && page === 1) {
|
||||
setTimeout(() => {
|
||||
refreshEmailsInBackground(userId, folder, 2, perPage);
|
||||
}, 500);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Background refresh error:', error);
|
||||
}
|
||||
}, 100);
|
||||
}, priority);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -183,9 +196,12 @@ export async function prefetchFolderEmails(
|
||||
|
||||
console.log(`Will prefetch pages: ${pagesToFetch.join(', ')}`);
|
||||
|
||||
// Fetch multiple pages in parallel
|
||||
await Promise.allSettled(
|
||||
pagesToFetch.map(page =>
|
||||
// Fetch multiple pages in parallel, but with a slight delay between them to avoid overwhelming the server
|
||||
for (let i = 0; i < pagesToFetch.length; i++) {
|
||||
const page = pagesToFetch[i];
|
||||
|
||||
// Use a delay for all but the first page
|
||||
setTimeout(() => {
|
||||
getEmails(userId, folder, page, 20)
|
||||
.then(result => {
|
||||
console.log(`Successfully prefetched and cached page ${page} of ${folder} with ${result.emails.length} emails`);
|
||||
@ -194,11 +210,11 @@ export async function prefetchFolderEmails(
|
||||
.catch(err => {
|
||||
console.error(`Error prefetching page ${page} of ${folder}:`, err);
|
||||
return null;
|
||||
})
|
||||
)
|
||||
);
|
||||
});
|
||||
}, i * 300); // Stagger prefetches with 300ms between them
|
||||
}
|
||||
|
||||
console.log(`Completed prefetching ${pages} pages of ${folder}`);
|
||||
console.log(`Scheduled prefetching for ${pages} pages of ${folder}`);
|
||||
} catch (error) {
|
||||
console.error(`Error prefetching folder ${folder}:`, error);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user