courrier formatting

This commit is contained in:
alma 2025-04-30 17:12:19 +02:00
parent 2b017a9395
commit b384ad1193
3 changed files with 83 additions and 26 deletions

View File

@ -749,11 +749,39 @@ export default function CourrierPage() {
const distanceToBottom = scrollHeight - scrollTop - clientHeight;
const scrollPercentage = (scrollTop + clientHeight) / scrollHeight;
console.log(`[DEBUG-WRAPPER-SCROLL] Distance to bottom: ${distanceToBottom}px, percentage: ${Math.round(scrollPercentage * 100)}%, hasMoreEmails: ${page < totalPages}, isLoading: ${isLoading}`);
// Store last scroll position to detect direction
const lastScrollTop = target.dataset.lastScrollTop ?
parseInt(target.dataset.lastScrollTop) : 0;
const scrollingDown = scrollTop > lastScrollTop;
// If near bottom and not already loading and has more emails
if (distanceToBottom < 300 && !isLoading && page < totalPages) {
// Update last scroll position
target.dataset.lastScrollTop = scrollTop.toString();
// Prevent frequent log spam with a timestamp check
const now = Date.now();
const lastLog = parseInt(target.dataset.lastLogTime || '0');
if (now - lastLog > 500) { // Log at most every 500ms
console.log(`[DEBUG-WRAPPER-SCROLL] Distance: ${distanceToBottom}px, %: ${Math.round(scrollPercentage * 100)}%, direction: ${scrollingDown ? 'down' : 'up'}, more: ${page < totalPages}, loading: ${isLoading}`);
target.dataset.lastLogTime = now.toString();
}
// Check throttle to prevent multiple rapid triggers
const lastTrigger = parseInt(target.dataset.lastTriggerTime || '0');
const throttleTime = 1000; // 1 second throttle
// Only trigger if:
// 1. Scrolling DOWN (not up)
// 2. Near the bottom
// 3. Not currently loading
// 4. More emails exist
// 5. Not throttled
if (scrollingDown &&
distanceToBottom < 300 &&
!isLoading &&
page < totalPages &&
now - lastTrigger > throttleTime) {
console.log(`[DEBUG-WRAPPER-TRIGGER] Calling handleLoadMore from wrapper`);
target.dataset.lastTriggerTime = now.toString();
handleLoadMore();
}
}}

View File

@ -619,32 +619,25 @@ export const useEmailState = () => {
// DEBUG: Log current state
console.log(`[DEBUG-LOAD_MORE] Current state - page: ${state.page}, totalPages: ${state.totalPages}, isLoading: ${state.isLoading}`);
// CRITICAL: Don't try to load more if we're already at the last page
// This prevents unnecessary API calls when scrolling up and down at the end of the list
if (state.page >= state.totalPages && state.totalPages > 0) {
console.log(`[DEBUG-LOAD_MORE] Already at last page (${state.page}/${state.totalPages}), not loading more`);
return;
}
if (state.isLoading) {
logEmailOp('LOAD_MORE', `Skipping load more request - already loading`);
console.log(`[DEBUG-LOAD_MORE] Skipping because isLoading is true`);
return;
}
if (state.page >= state.totalPages && state.totalPages > 0) {
logEmailOp('LOAD_MORE', `No more emails to load: page ${state.page}/${state.totalPages}`);
console.log(`[DEBUG-LOAD_MORE] At last page - page: ${state.page}, totalPages: ${state.totalPages}`);
// CRITICAL FIX: Re-fetch the last page to force checking for new emails
const { effectiveAccountId } = normalizeFolderAndAccount(state.currentFolder);
setTimeout(() => {
// Re-fetch the last page in a delay to ensure the user can see there are no more emails
logEmailOp('LOAD_MORE', `Re-checking for emails at page ${state.page}`);
console.log(`[DEBUG-LOAD_MORE] Re-checking emails at page ${state.page}`);
loadEmails(true, effectiveAccountId);
}, 2000);
return;
}
// Normal case - load the next page
console.log(`[DEBUG-LOAD_MORE] Incrementing page from ${state.page} to ${state.page + 1}`);
logEmailOp('LOAD_MORE', `Loading more emails: page ${state.page + 1}/${state.totalPages || '?'}`);
dispatch({ type: 'INCREMENT_PAGE' });
// The actual loading will be handled by the useEffect that watches page changes
}, [state.page, state.totalPages, state.isLoading, state.currentFolder, loadEmails, logEmailOp]);
}, [state.page, state.totalPages, state.isLoading, logEmailOp]);
// Effect to load emails when folder changes
useEffect(() => {
@ -665,6 +658,16 @@ export const useEmailState = () => {
// Debug log
console.log(`[DEBUG-PAGE_EFFECT] Page changed to ${state.page}, calling loadEmails`);
// Prevent duplicate effect triggers with ref tracking
const currentEffectPage = state.page;
// CRITICAL: We need to avoid triggering duplicate loads
// Check if we're already loading to prevent duplicate calls
if (state.isLoading) {
console.log(`[DEBUG-PAGE_EFFECT] Skipping loadEmails - already loading`);
return;
}
// Extract account ID for consistency
const { effectiveAccountId } = normalizeFolderAndAccount(state.currentFolder);
@ -673,7 +676,7 @@ export const useEmailState = () => {
// Load more emails with the correct account ID
loadEmails(true, effectiveAccountId);
}
}, [session?.user?.id, state.page, state.currentFolder, loadEmails, logEmailOp]);
}, [session?.user?.id, state.page, state.currentFolder, loadEmails, logEmailOp, state.isLoading]);
// Fetch unread counts from API
const fetchUnreadCounts = useCallback(async () => {

View File

@ -189,17 +189,30 @@ export function emailReducer(state: EmailState, action: EmailAction): EmailState
);
}
// Sort by date, newest first
// CRITICAL FIX: Enhanced sorting function that ensures proper date handling
const sortedEmails = unsortedEmails.sort((a, b) => {
const dateA = new Date(a.date).getTime();
const dateB = new Date(b.date).getTime();
// Convert all dates to timestamps for comparison
let dateA: number, dateB: number;
try {
dateA = a.date instanceof Date ? a.date.getTime() : new Date(a.date).getTime();
} catch (e) {
dateA = 0; // Default to oldest if invalid
}
try {
dateB = b.date instanceof Date ? b.date.getTime() : new Date(b.date).getTime();
} catch (e) {
dateB = 0; // Default to oldest if invalid
}
// Handle invalid dates
if (isNaN(dateA) && isNaN(dateB)) return 0;
if (isNaN(dateA)) return 1; // Put invalid dates at the end
if (isNaN(dateB)) return -1;
return dateB - dateA; // Newest first
// Sort newest first
return dateB - dateA;
});
// For debugging - log a few emails after sorting
@ -256,15 +269,28 @@ export function emailReducer(state: EmailState, action: EmailAction): EmailState
// Combine and sort emails by date (newest first)
const combinedEmails = [...state.emails, ...newEmails].sort(
(a, b) => {
const dateA = new Date(a.date).getTime();
const dateB = new Date(b.date).getTime();
// Convert all dates to timestamps for comparison
let dateA: number, dateB: number;
try {
dateA = a.date instanceof Date ? a.date.getTime() : new Date(a.date).getTime();
} catch (e) {
dateA = 0; // Default to oldest if invalid
}
try {
dateB = b.date instanceof Date ? b.date.getTime() : new Date(b.date).getTime();
} catch (e) {
dateB = 0; // Default to oldest if invalid
}
// Handle invalid dates
if (isNaN(dateA) && isNaN(dateB)) return 0;
if (isNaN(dateA)) return 1; // Put invalid dates at the end
if (isNaN(dateB)) return -1;
return dateB - dateA; // Newest first
// Sort newest first
return dateB - dateA;
}
);