From 3eb6e3abd9fb1ea6ead2326db4708cfdaeaacf4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A9=AC=E5=AD=90=E5=A4=9C?= Date: Thu, 5 Mar 2026 11:46:50 +0800 Subject: [PATCH 1/2] fix: prevent infinite timezone update loop for delegate sessions --- src/hooks/useAutoUpdateTimezone.ts | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/hooks/useAutoUpdateTimezone.ts b/src/hooks/useAutoUpdateTimezone.ts index 4005ac3c369b0..501adac37432c 100644 --- a/src/hooks/useAutoUpdateTimezone.ts +++ b/src/hooks/useAutoUpdateTimezone.ts @@ -1,16 +1,37 @@ import {useEffect} from 'react'; import {updateAutomaticTimezone} from '@userActions/PersonalDetails'; +import {isActingAsDelegateSelector} from '@selectors/Account'; import type {SelectedTimezone} from '@src/types/onyx/PersonalDetails'; import useCurrentUserPersonalDetails from './useCurrentUserPersonalDetails'; +const THROTTLE_INTERVAL_MS = 60 * 60 * 1000; // 1 hour + +let lastUpdateTimestamp = 0; + const useAutoUpdateTimezone = () => { const currentUserPersonalDetails = useCurrentUserPersonalDetails(); const timezone = currentUserPersonalDetails?.timezone ?? {}; + const account = currentUserPersonalDetails?.account; + const isDelegate = isActingAsDelegateSelector(account); + useEffect(() => { + // Skip auto-timezone updates for copilot/delegate sessions + if (isDelegate) { + return; + } + + const currentTime = Date.now(); + + // Throttle timezone updates to once per hour + if (currentTime - lastUpdateTimestamp < THROTTLE_INTERVAL_MS) { + return; + } + const currentTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone as SelectedTimezone; const hasValidCurrentTimezone = typeof currentTimezone === 'string' && currentTimezone.trim().length > 0; if (hasValidCurrentTimezone && timezone?.automatic && timezone?.selected !== currentTimezone) { + lastUpdateTimestamp = currentTime; updateAutomaticTimezone( { automatic: true, @@ -20,7 +41,7 @@ const useAutoUpdateTimezone = () => { ); } // eslint-disable-next-line react-hooks/exhaustive-deps - }, [timezone?.automatic, timezone?.selected]); + }, [timezone?.automatic, timezone?.selected, isDelegate]); }; export default useAutoUpdateTimezone; From ab286a7aa17c068288b6551f6b9c8b6f6a8a8b85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A9=AC=E5=AD=90=E5=A4=9C?= Date: Thu, 5 Mar 2026 15:58:06 +0800 Subject: [PATCH 2/2] fix: correct delegate check and per-account throttle - Use useOnyx to get Account data from ONYXKEYS.ACCOUNT (contains delegatedAccess) - Use useRef to store per-account timestamps instead of global variable - Each account now has its own throttle timer --- src/hooks/useAutoUpdateTimezone.ts | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/src/hooks/useAutoUpdateTimezone.ts b/src/hooks/useAutoUpdateTimezone.ts index 501adac37432c..7b24eb2dbf6df 100644 --- a/src/hooks/useAutoUpdateTimezone.ts +++ b/src/hooks/useAutoUpdateTimezone.ts @@ -1,18 +1,24 @@ -import {useEffect} from 'react'; +import {useEffect, useRef} from 'react'; import {updateAutomaticTimezone} from '@userActions/PersonalDetails'; import {isActingAsDelegateSelector} from '@selectors/Account'; import type {SelectedTimezone} from '@src/types/onyx/PersonalDetails'; import useCurrentUserPersonalDetails from './useCurrentUserPersonalDetails'; +import useOnyx from './useOnyx'; +import ONYXKEYS from '@src/ONYXKEYS'; const THROTTLE_INTERVAL_MS = 60 * 60 * 1000; // 1 hour -let lastUpdateTimestamp = 0; - const useAutoUpdateTimezone = () => { const currentUserPersonalDetails = useCurrentUserPersonalDetails(); const timezone = currentUserPersonalDetails?.timezone ?? {}; - const account = currentUserPersonalDetails?.account; + const accountID = currentUserPersonalDetails?.accountID; + + // Use useOnyx to get the Account data (contains delegatedAccess) + const [account] = useOnyx(ONYXKEYS.ACCOUNT); const isDelegate = isActingAsDelegateSelector(account); + + // Use useRef to store per-account timestamps + const lastUpdateTimestamps = useRef>({}); useEffect(() => { // Skip auto-timezone updates for copilot/delegate sessions @@ -21,8 +27,11 @@ const useAutoUpdateTimezone = () => { } const currentTime = Date.now(); + + // Get the last update timestamp for this specific account + const lastUpdateTimestamp = lastUpdateTimestamps.current[accountID] ?? 0; - // Throttle timezone updates to once per hour + // Throttle timezone updates to once per hour (per account) if (currentTime - lastUpdateTimestamp < THROTTLE_INTERVAL_MS) { return; } @@ -31,17 +40,18 @@ const useAutoUpdateTimezone = () => { const hasValidCurrentTimezone = typeof currentTimezone === 'string' && currentTimezone.trim().length > 0; if (hasValidCurrentTimezone && timezone?.automatic && timezone?.selected !== currentTimezone) { - lastUpdateTimestamp = currentTime; + // Update the timestamp for this specific account + lastUpdateTimestamps.current[accountID] = currentTime; updateAutomaticTimezone( { automatic: true, selected: currentTimezone, }, - currentUserPersonalDetails.accountID, + accountID, ); } // eslint-disable-next-line react-hooks/exhaustive-deps - }, [timezone?.automatic, timezone?.selected, isDelegate]); + }, [timezone?.automatic, timezone?.selected, isDelegate, accountID]); }; export default useAutoUpdateTimezone;