courrier formatting
This commit is contained in:
parent
2b017a9395
commit
b384ad1193
@ -749,11 +749,39 @@ export default function CourrierPage() {
|
|||||||
const distanceToBottom = scrollHeight - scrollTop - clientHeight;
|
const distanceToBottom = scrollHeight - scrollTop - clientHeight;
|
||||||
const scrollPercentage = (scrollTop + clientHeight) / scrollHeight;
|
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
|
// Update last scroll position
|
||||||
if (distanceToBottom < 300 && !isLoading && page < totalPages) {
|
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`);
|
console.log(`[DEBUG-WRAPPER-TRIGGER] Calling handleLoadMore from wrapper`);
|
||||||
|
target.dataset.lastTriggerTime = now.toString();
|
||||||
handleLoadMore();
|
handleLoadMore();
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
|||||||
@ -619,32 +619,25 @@ export const useEmailState = () => {
|
|||||||
// DEBUG: Log current state
|
// DEBUG: Log current state
|
||||||
console.log(`[DEBUG-LOAD_MORE] Current state - page: ${state.page}, totalPages: ${state.totalPages}, isLoading: ${state.isLoading}`);
|
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) {
|
if (state.isLoading) {
|
||||||
logEmailOp('LOAD_MORE', `Skipping load more request - already loading`);
|
logEmailOp('LOAD_MORE', `Skipping load more request - already loading`);
|
||||||
console.log(`[DEBUG-LOAD_MORE] Skipping because isLoading is true`);
|
console.log(`[DEBUG-LOAD_MORE] Skipping because isLoading is true`);
|
||||||
return;
|
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
|
// Normal case - load the next page
|
||||||
console.log(`[DEBUG-LOAD_MORE] Incrementing page from ${state.page} to ${state.page + 1}`);
|
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 || '?'}`);
|
logEmailOp('LOAD_MORE', `Loading more emails: page ${state.page + 1}/${state.totalPages || '?'}`);
|
||||||
dispatch({ type: 'INCREMENT_PAGE' });
|
dispatch({ type: 'INCREMENT_PAGE' });
|
||||||
// The actual loading will be handled by the useEffect that watches page changes
|
// 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
|
// Effect to load emails when folder changes
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -665,6 +658,16 @@ export const useEmailState = () => {
|
|||||||
// Debug log
|
// Debug log
|
||||||
console.log(`[DEBUG-PAGE_EFFECT] Page changed to ${state.page}, calling loadEmails`);
|
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
|
// Extract account ID for consistency
|
||||||
const { effectiveAccountId } = normalizeFolderAndAccount(state.currentFolder);
|
const { effectiveAccountId } = normalizeFolderAndAccount(state.currentFolder);
|
||||||
|
|
||||||
@ -673,7 +676,7 @@ export const useEmailState = () => {
|
|||||||
// Load more emails with the correct account ID
|
// Load more emails with the correct account ID
|
||||||
loadEmails(true, effectiveAccountId);
|
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
|
// Fetch unread counts from API
|
||||||
const fetchUnreadCounts = useCallback(async () => {
|
const fetchUnreadCounts = useCallback(async () => {
|
||||||
|
|||||||
@ -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 sortedEmails = unsortedEmails.sort((a, b) => {
|
||||||
const dateA = new Date(a.date).getTime();
|
// Convert all dates to timestamps for comparison
|
||||||
const dateB = new Date(b.date).getTime();
|
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
|
// Handle invalid dates
|
||||||
if (isNaN(dateA) && isNaN(dateB)) return 0;
|
if (isNaN(dateA) && isNaN(dateB)) return 0;
|
||||||
if (isNaN(dateA)) return 1; // Put invalid dates at the end
|
if (isNaN(dateA)) return 1; // Put invalid dates at the end
|
||||||
if (isNaN(dateB)) return -1;
|
if (isNaN(dateB)) return -1;
|
||||||
|
|
||||||
return dateB - dateA; // Newest first
|
// Sort newest first
|
||||||
|
return dateB - dateA;
|
||||||
});
|
});
|
||||||
|
|
||||||
// For debugging - log a few emails after sorting
|
// 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)
|
// Combine and sort emails by date (newest first)
|
||||||
const combinedEmails = [...state.emails, ...newEmails].sort(
|
const combinedEmails = [...state.emails, ...newEmails].sort(
|
||||||
(a, b) => {
|
(a, b) => {
|
||||||
const dateA = new Date(a.date).getTime();
|
// Convert all dates to timestamps for comparison
|
||||||
const dateB = new Date(b.date).getTime();
|
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
|
// Handle invalid dates
|
||||||
if (isNaN(dateA) && isNaN(dateB)) return 0;
|
if (isNaN(dateA) && isNaN(dateB)) return 0;
|
||||||
if (isNaN(dateA)) return 1; // Put invalid dates at the end
|
if (isNaN(dateA)) return 1; // Put invalid dates at the end
|
||||||
if (isNaN(dateB)) return -1;
|
if (isNaN(dateB)) return -1;
|
||||||
|
|
||||||
return dateB - dateA; // Newest first
|
// Sort newest first
|
||||||
|
return dateB - dateA;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user