diff --git a/hooks/use-email-state.ts b/hooks/use-email-state.ts index 84b3ea65..be4e415d 100644 --- a/hooks/use-email-state.ts +++ b/hooks/use-email-state.ts @@ -63,11 +63,17 @@ export const useEmailState = () => { // Load emails from the server const loadEmails = useCallback(async (page: number, perPage: number, isLoadMore: boolean = false) => { + // CRITICAL FIX: Do important validation before setting loading state if (!session?.user?.id) return; // CRITICAL FIX: Always log the isLoadMore parameter console.log(`[DEBUG-LOAD_EMAILS] Called with isLoadMore=${isLoadMore}, page=${page}, currentEmails=${state.emails.length}`); + // Set the current folder and account being loaded to detect changes + const startFolder = state.currentFolder; + const startAccount = state.selectedAccount ? state.selectedAccount.id : 'default'; + + // CRITICAL FIX: Force loading state to true dispatch({ type: 'SET_LOADING', payload: true }); try { @@ -271,6 +277,15 @@ export const useEmailState = () => { title: "Error", description: err instanceof Error ? err.message : 'Failed to load emails' }); + } finally { + // CRITICAL FIX: Only clear loading state if the folder/account hasn't changed + if (startFolder === state.currentFolder && + (startAccount === (state.selectedAccount?.id || 'default'))) { + // Safe to clear loading state + dispatch({ type: 'SET_LOADING', payload: false }); + } else { + console.log(`[DEBUG-LOAD_EMAILS] Folder/account changed during load, not clearing loading state`); + } } }, [session?.user?.id, state.currentFolder, state.selectedAccount, state.page, state.perPage, state.emails.length, toast, logEmailOp]); @@ -279,22 +294,38 @@ export const useEmailState = () => { logEmailOp('CHANGE_FOLDER', `Changing to folder ${folder} with account ${accountId || 'default'}`); try { - // This will handle all the state updates in a single atomic operation + // CRITICAL FIX: Reset pagination state immediately + lastPageLoadedRef.current = 0; + + // Reset page to 1 directly to prevent any issues with page effects + // This will be atomic with the CHANGE_FOLDER action + dispatch({ type: 'SET_PAGE', payload: 1 }); + + // Clear existing emails - don't show old emails during load + dispatch({ type: 'SET_EMAILS', payload: [] }); + + // Set loading state explicitly - this is critical + dispatch({ type: 'SET_LOADING', payload: true }); + + // This will handle folder setting in a single atomic operation dispatch({ type: 'CHANGE_FOLDER', payload: { folder, accountId: accountId || 'default' } }); - // After dispatch, the state will be updated with consistent values - // We'll load emails in the useEffect that watches for folder changes + // CRITICAL: The email loading will be triggered by the folder effect + // We don't need to call loadEmails directly here } catch (error) { logEmailOp('ERROR', `Failed to change folder: ${error instanceof Error ? error.message : String(error)}`); dispatch({ type: 'SET_ERROR', payload: error instanceof Error ? error.message : 'Failed to change folder' }); + + // Always ensure loading state is cleared on error + dispatch({ type: 'SET_LOADING', payload: false }); } - }, [logEmailOp]); + }, [logEmailOp, dispatch]); // Select account const selectAccount = useCallback((account: Account) => { @@ -735,7 +766,33 @@ export const useEmailState = () => { console.log(`[DEBUG-PAGE_EFFECT] Page changed to ${state.page}`); - // CRITICAL FIX: Don't run this effect at all if we're already loading + // CRITICAL FIX: Add a special case for page 1 loads - we should never skip loading the first page + // This ensures that after a folder change, page 1 always loads even if loading state is true + if (state.page === 1) { + const currentFolder = state.currentFolder; + const lastLoadedFolder = prevFolderRef.current; + + // Check if this is a fresh folder load (folder changed or first time loading) + if (currentFolder !== lastLoadedFolder || lastPageLoadedRef.current === 0) { + // Force loading page 1 for new folders, regardless of loading state + console.log(`[DEBUG-PAGE_EFFECT] Force loading page 1 for folder: ${currentFolder}`); + + // Set the loading state explicitly (might already be true) + dispatch({ type: 'SET_LOADING', payload: true }); + + // Update refs to track the current state + prevFolderRef.current = currentFolder; + lastPageLoadedRef.current = 1; + + // Call loadEmails to load the first page - never skip this! + loadEmails(1, state.perPage, false); + return; + } + } + + // For pages > 1 or already loaded folders, follow normal rules + + // Skip if already loading if (state.isLoading) { console.log(`[DEBUG-PAGE_EFFECT] Skipping effect execution entirely - already loading`); return; @@ -759,12 +816,12 @@ export const useEmailState = () => { // Update our reference to prevent duplicate loads lastPageLoadedRef.current = state.page; - // CRITICAL FIX: Always use isLoadMore=true when page > 1 + // Always use isLoadMore=true when page > 1 console.log(`[DEBUG-PAGE_EFFECT] Calling loadEmails with isLoadMore=true for page ${state.page}`); loadEmails(state.page, state.perPage, true); // Do NOT include state.emails.length here to prevent infinite loops - }, [session?.user?.id, state.page, state.currentFolder, state.isLoading, state.perPage, loadEmails, logEmailOp]); + }, [session?.user?.id, state.page, state.currentFolder, state.isLoading, state.perPage, loadEmails, logEmailOp, dispatch]); // Fetch unread counts from API const fetchUnreadCounts = useCallback(async () => {