courrier multi account restore compose

This commit is contained in:
alma 2025-04-30 14:40:01 +02:00
parent 6939ad5e35
commit eb557d16dd

View File

@ -614,141 +614,6 @@ export const useEmailState = () => {
}
}, [session?.user?.id, state.page, state.currentFolder, loadEmails, logEmailOp]);
// Calculate and update unread counts from emails
const updateUnreadCounts = useCallback(() => {
// This function will count unread emails in each folder and update the unreadCountMap
if (state.emails.length === 0) return;
// Create a temporary count map
const tempUnreadMap: Record<string, Record<string, number>> = {};
// Initialize with existing accounts and folders to avoid losing counts
// when switching folders
state.accounts.forEach(account => {
tempUnreadMap[account.id] = { ...state.unreadCountMap[account.id] || {} };
// Initialize each folder with 0 if it doesn't exist
account.folders.forEach(folder => {
// Extract base folder name if it has a prefix
const baseFolderName = folder.includes(':') ? folder.split(':')[1] : folder;
const prefixedFolder = folder.includes(':') ? folder : `${account.id}:${baseFolderName}`;
// Initialize both prefixed and unprefixed versions
if (tempUnreadMap[account.id][baseFolderName] === undefined) {
tempUnreadMap[account.id][baseFolderName] = 0;
}
if (tempUnreadMap[account.id][prefixedFolder] === undefined) {
tempUnreadMap[account.id][prefixedFolder] = 0;
}
});
});
// Count unread emails from current folder
state.emails.forEach(email => {
// Check if email is unread
const isUnread = email.flags && !email.flags.seen;
// Only count if it's unread
if (isUnread && email.accountId) {
// Get folder information
let folder = email.folder;
let accountId = email.accountId;
// Make sure the account exists in our map
if (!tempUnreadMap[accountId]) {
tempUnreadMap[accountId] = {};
}
// Extract folder name if it has a prefix
let baseFolderName = folder;
if (folder.includes(':')) {
const parts = folder.split(':');
// Don't override accountId from the folder prefix
baseFolderName = parts[1];
}
// Ensure we have entries for both formats
if (!tempUnreadMap[accountId][baseFolderName]) {
tempUnreadMap[accountId][baseFolderName] = 0;
}
if (!tempUnreadMap[accountId][folder]) {
tempUnreadMap[accountId][folder] = 0;
}
// Increment both formats to ensure they're both available
tempUnreadMap[accountId][baseFolderName]++;
tempUnreadMap[accountId][folder]++;
}
});
// Store the current update for comparison
if (!(window as any).__lastUnreadUpdate) {
(window as any).__lastUnreadUpdate = {
timestamp: 0,
map: {}
};
}
// Check if the unread counts have actually changed before updating state
let hasChanged = false;
// Compare with current unread count map
Object.entries(tempUnreadMap).forEach(([accountId, folderCounts]) => {
Object.entries(folderCounts).forEach(([folder, count]) => {
if (state.unreadCountMap[accountId]?.[folder] !== count) {
hasChanged = true;
}
});
});
// Check if we've updated recently
const now = Date.now();
const lastUpdate = (window as any).__lastUnreadUpdate;
const timeSinceLastUpdate = now - lastUpdate.timestamp;
// If changes found and not updated too recently, update state
if (hasChanged && timeSinceLastUpdate > 500) {
// Log only on actual change
logEmailOp('UNREAD_COUNTS', 'Updated unread counts:', tempUnreadMap);
// Create a single dispatch to update all counts at once
dispatch({
type: 'SET_UNREAD_COUNTS',
payload: tempUnreadMap
});
// Update timestamp of last update
lastUpdate.timestamp = now;
lastUpdate.map = tempUnreadMap;
}
}, [state.emails, state.accounts, state.unreadCountMap, dispatch, logEmailOp]);
// Call updateUnreadCounts when relevant state changes
useEffect(() => {
if (!state.emails || state.emails.length === 0) return;
// Debounce unread count updates to prevent rapid multiple updates
let updateTimeoutId: ReturnType<typeof setTimeout>;
const debounceMs = 500; // 500ms debounce
// Function to call after debounce period
const debouncedUpdate = () => {
updateTimeoutId = setTimeout(() => {
updateUnreadCounts();
}, debounceMs);
};
// Clear any existing timeout and start a new one
debouncedUpdate();
// Cleanup timeout on unmount or state change
return () => {
clearTimeout(updateTimeoutId);
};
// Deliberately exclude unreadCountMap to prevent infinite loops
}, [state.emails, updateUnreadCounts]);
// Fetch unread counts from API
const fetchUnreadCounts = useCallback(async () => {
// Don't fetch if user is not logged in
@ -827,7 +692,59 @@ export const useEmailState = () => {
dispatch({ type: 'SET_LOADING_UNREAD_COUNTS', payload: false });
}
}, [dispatch, session?.user, state.isLoadingUnreadCounts, logEmailOp]);
// Calculate and update unread counts
const updateUnreadCounts = useCallback(() => {
// Skip if no emails or accounts
if (state.emails.length === 0 || state.accounts.length === 0) return;
// To avoid running this too frequently, check the timestamp of last update
if (!(window as any).__lastUnreadUpdate) {
(window as any).__lastUnreadUpdate = { timestamp: 0 };
}
const now = Date.now();
const lastUpdate = (window as any).__lastUnreadUpdate;
const MIN_UPDATE_INTERVAL = 2000; // 2 seconds minimum between updates
if (now - lastUpdate.timestamp < MIN_UPDATE_INTERVAL) {
return; // Skip if updated too recently
}
// Rather than calculating locally, let's fetch from the API
// This ensures we get accurate server-side counts
fetchUnreadCounts();
// Update timestamp of last update
lastUpdate.timestamp = now;
}, [state.emails.length, state.accounts.length, fetchUnreadCounts]);
// Call updateUnreadCounts when relevant state changes
useEffect(() => {
if (!state.emails || state.emails.length === 0) return;
// Debounce unread count updates to prevent rapid multiple updates
let updateTimeoutId: ReturnType<typeof setTimeout>;
const debounceMs = 2000; // Increase debounce to 2 seconds
// Function to call after debounce period
const debouncedUpdate = () => {
updateTimeoutId = setTimeout(() => {
updateUnreadCounts();
}, debounceMs);
};
// Clear any existing timeout and start a new one
debouncedUpdate();
// Cleanup timeout on unmount or state change
return () => {
clearTimeout(updateTimeoutId);
};
// Deliberately exclude unreadCountMap to prevent infinite loops
}, [state.emails, updateUnreadCounts]);
// Tracking when an email is viewed to optimize unread count refreshes
const lastViewedEmailRef = useRef<number | null>(null);
const fetchFailuresRef = useRef<number>(0);