[Perf] Fix global updates with interval when in background (#2707)
This commit is contained in:
parent
2cde76ea94
commit
e480499a80
@ -50,7 +50,7 @@ const App: FC<StateProps> = ({
|
|||||||
hasWebAuthTokenFailed,
|
hasWebAuthTokenFailed,
|
||||||
isInactiveAuth,
|
isInactiveAuth,
|
||||||
}) => {
|
}) => {
|
||||||
const { disconnect, updatePageTitle } = getActions();
|
const { disconnect } = getActions();
|
||||||
|
|
||||||
const [isInactive, markInactive, unmarkInactive] = useFlag(false);
|
const [isInactive, markInactive, unmarkInactive] = useFlag(false);
|
||||||
const { isMobile } = useAppLayout();
|
const { isMobile } = useAppLayout();
|
||||||
@ -157,7 +157,7 @@ const App: FC<StateProps> = ({
|
|||||||
|
|
||||||
markInactive();
|
markInactive();
|
||||||
});
|
});
|
||||||
}, [activeKey, disconnect, markInactive, updatePageTitle]);
|
}, [activeKey, disconnect, markInactive]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isInactiveAuth) {
|
if (isInactiveAuth) {
|
||||||
@ -166,7 +166,7 @@ const App: FC<StateProps> = ({
|
|||||||
} else {
|
} else {
|
||||||
unmarkInactive();
|
unmarkInactive();
|
||||||
}
|
}
|
||||||
}, [isInactiveAuth, markInactive, unmarkInactive, updatePageTitle]);
|
}, [isInactiveAuth, markInactive, unmarkInactive]);
|
||||||
|
|
||||||
const prevActiveKey = usePrevious(activeKey);
|
const prevActiveKey = usePrevious(activeKey);
|
||||||
|
|
||||||
|
|||||||
@ -1,11 +1,10 @@
|
|||||||
import { addCallback } from '../../../lib/teact/teactn';
|
|
||||||
import {
|
import {
|
||||||
addActionHandler, getActions, getGlobal, setGlobal,
|
addActionHandler, getGlobal, setGlobal,
|
||||||
} from '../../index';
|
} from '../../index';
|
||||||
|
|
||||||
import type { ApiError, ApiNotification } from '../../../api/types';
|
import type { ApiError, ApiNotification } from '../../../api/types';
|
||||||
import { MAIN_THREAD_ID } from '../../../api/types';
|
import { MAIN_THREAD_ID } from '../../../api/types';
|
||||||
import type { ActionReturnType, GlobalState } from '../../types';
|
import type { ActionReturnType } from '../../types';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
APP_VERSION, DEBUG, GLOBAL_STATE_CACHE_CUSTOM_EMOJI_LIMIT, INACTIVE_MARKER, PAGE_TITLE,
|
APP_VERSION, DEBUG, GLOBAL_STATE_CACHE_CUSTOM_EMOJI_LIMIT, INACTIVE_MARKER, PAGE_TITLE,
|
||||||
@ -19,7 +18,7 @@ import { compact, unique } from '../../../util/iteratees';
|
|||||||
import { getAllMultitabTokens, getCurrentTabId, reestablishMasterToSelf } from '../../../util/establishMultitabRole';
|
import { getAllMultitabTokens, getCurrentTabId, reestablishMasterToSelf } from '../../../util/establishMultitabRole';
|
||||||
import { getAllNotificationsCount } from '../../../util/folderManager';
|
import { getAllNotificationsCount } from '../../../util/folderManager';
|
||||||
import updateIcon from '../../../util/updateIcon';
|
import updateIcon from '../../../util/updateIcon';
|
||||||
import setPageTitle from '../../../util/updatePageTitle';
|
import { setPageTitle, setPageTitleInstant } from '../../../util/updatePageTitle';
|
||||||
import { updateTabState } from '../../reducers/tabs';
|
import { updateTabState } from '../../reducers/tabs';
|
||||||
import { getIsMobile, getIsTablet } from '../../../hooks/useAppLayout';
|
import { getIsMobile, getIsTablet } from '../../../hooks/useAppLayout';
|
||||||
import * as langProvider from '../../../util/langProvider';
|
import * as langProvider from '../../../util/langProvider';
|
||||||
@ -606,47 +605,34 @@ addActionHandler('afterHangUp', (global): ActionReturnType => {
|
|||||||
|
|
||||||
let notificationInterval: NodeJS.Timeout | undefined;
|
let notificationInterval: NodeJS.Timeout | undefined;
|
||||||
|
|
||||||
const NOTIFICATION_INTERVAL = 1000;
|
const NOTIFICATION_INTERVAL = 500;
|
||||||
|
|
||||||
addActionHandler('onTabFocusChange', (global, actions, payload): ActionReturnType => {
|
addActionHandler('onTabFocusChange', (global, actions, payload): ActionReturnType => {
|
||||||
const { isBlurred } = payload;
|
const { isBlurred, tabId = getCurrentTabId() } = payload;
|
||||||
const token = getCurrentTabId();
|
|
||||||
|
|
||||||
if (!isBlurred) {
|
if (!isBlurred) {
|
||||||
actions.updateIsOnline(true);
|
actions.updateIsOnline(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
const blurredTabTokens = unique(isBlurred
|
const blurredTabTokens = unique(isBlurred
|
||||||
? [...global.blurredTabTokens, token]
|
? [...global.blurredTabTokens, tabId]
|
||||||
: global.blurredTabTokens.filter((t) => t !== token));
|
: global.blurredTabTokens.filter((t) => t !== tabId));
|
||||||
|
|
||||||
if (blurredTabTokens.length === getAllMultitabTokens().length) {
|
if (blurredTabTokens.length === getAllMultitabTokens().length) {
|
||||||
actions.updateIsOnline(false);
|
actions.updateIsOnline(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
const isNewlyBlurred = isBlurred && blurredTabTokens.length === 1;
|
if (isBlurred) {
|
||||||
|
|
||||||
if (isNewlyBlurred) {
|
|
||||||
if (notificationInterval) clearInterval(notificationInterval);
|
if (notificationInterval) clearInterval(notificationInterval);
|
||||||
|
|
||||||
notificationInterval = setInterval(() => {
|
notificationInterval = setInterval(() => {
|
||||||
global = getGlobal();
|
actions.updatePageTitle({
|
||||||
global = {
|
tabId,
|
||||||
...global,
|
});
|
||||||
notificationIndex: (global.notificationIndex || 0) + 1,
|
|
||||||
allNotificationsCount: getAllNotificationsCount(),
|
|
||||||
};
|
|
||||||
setGlobal(global);
|
|
||||||
}, NOTIFICATION_INTERVAL);
|
}, NOTIFICATION_INTERVAL);
|
||||||
}
|
} else {
|
||||||
|
|
||||||
if (!blurredTabTokens.length && notificationInterval) {
|
|
||||||
clearInterval(notificationInterval);
|
clearInterval(notificationInterval);
|
||||||
notificationInterval = undefined;
|
notificationInterval = undefined;
|
||||||
global = {
|
|
||||||
...global,
|
|
||||||
notificationIndex: undefined,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -657,20 +643,30 @@ addActionHandler('onTabFocusChange', (global, actions, payload): ActionReturnTyp
|
|||||||
});
|
});
|
||||||
|
|
||||||
addActionHandler('updatePageTitle', (global, actions, payload): ActionReturnType => {
|
addActionHandler('updatePageTitle', (global, actions, payload): ActionReturnType => {
|
||||||
const { isInactive, notificationCount, tabId = getCurrentTabId() } = payload || {};
|
const { tabId = getCurrentTabId() } = payload || {};
|
||||||
const { canDisplayChatInTitle } = global.settings.byKey;
|
const { canDisplayChatInTitle } = global.settings.byKey;
|
||||||
const currentUserId = global.currentUserId;
|
const currentUserId = global.currentUserId;
|
||||||
|
|
||||||
if (isInactive) {
|
if (document.title.includes(INACTIVE_MARKER)) {
|
||||||
setPageTitle(`${PAGE_TITLE} ${INACTIVE_MARKER}`);
|
updateIcon(false);
|
||||||
|
setPageTitleInstant(`${PAGE_TITLE} ${INACTIVE_MARKER}`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (notificationCount) {
|
if (global.initialUnreadNotifications && Math.round(Date.now() / 1000) % 2 === 0) {
|
||||||
setPageTitle(`${notificationCount} notification${notificationCount > 1 ? 's' : ''}`);
|
const notificationCount = getAllNotificationsCount();
|
||||||
return;
|
|
||||||
|
const newUnread = notificationCount - global.initialUnreadNotifications;
|
||||||
|
|
||||||
|
if (newUnread > 0) {
|
||||||
|
setPageTitleInstant(`${newUnread} notification${newUnread > 1 ? 's' : ''}`);
|
||||||
|
updateIcon(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateIcon(false);
|
||||||
|
|
||||||
const messageList = selectCurrentMessageList(global, tabId);
|
const messageList = selectCurrentMessageList(global, tabId);
|
||||||
if (messageList && canDisplayChatInTitle) {
|
if (messageList && canDisplayChatInTitle) {
|
||||||
const { chatId, threadId } = messageList;
|
const { chatId, threadId } = messageList;
|
||||||
@ -687,34 +683,5 @@ addActionHandler('updatePageTitle', (global, actions, payload): ActionReturnType
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setPageTitle(PAGE_TITLE);
|
setPageTitleInstant(PAGE_TITLE);
|
||||||
});
|
|
||||||
|
|
||||||
addCallback((global: GlobalState) => {
|
|
||||||
if (global.notificationIndex === undefined || global.allNotificationsCount === undefined) return;
|
|
||||||
// eslint-disable-next-line eslint-multitab-tt/no-getactions-in-actions
|
|
||||||
const { updatePageTitle } = getActions();
|
|
||||||
|
|
||||||
const index = global.notificationIndex;
|
|
||||||
const allNotificationsCount = global.allNotificationsCount;
|
|
||||||
|
|
||||||
if (document.title.includes(INACTIVE_MARKER) || !global.initialUnreadNotifications) {
|
|
||||||
updateIcon(false);
|
|
||||||
updatePageTitle();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (index % 2 === 0) {
|
|
||||||
const newUnread = allNotificationsCount - global.initialUnreadNotifications;
|
|
||||||
if (newUnread > 0) {
|
|
||||||
updatePageTitle({
|
|
||||||
notificationCount: newUnread,
|
|
||||||
});
|
|
||||||
updateIcon(true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
updatePageTitle();
|
|
||||||
updateIcon(false);
|
|
||||||
});
|
});
|
||||||
|
|||||||
@ -560,8 +560,6 @@ export type GlobalState = {
|
|||||||
leftColumnWidth?: number;
|
leftColumnWidth?: number;
|
||||||
lastIsChatInfoShown?: boolean;
|
lastIsChatInfoShown?: boolean;
|
||||||
initialUnreadNotifications?: number;
|
initialUnreadNotifications?: number;
|
||||||
notificationIndex?: number;
|
|
||||||
allNotificationsCount?: number;
|
|
||||||
|
|
||||||
audioPlayer: {
|
audioPlayer: {
|
||||||
lastPlaybackRate: number;
|
lastPlaybackRate: number;
|
||||||
@ -1533,7 +1531,7 @@ export interface ActionPayloads {
|
|||||||
};
|
};
|
||||||
onTabFocusChange: {
|
onTabFocusChange: {
|
||||||
isBlurred: boolean;
|
isBlurred: boolean;
|
||||||
};
|
} & WithTabId;
|
||||||
onSomeTabSwitchedMultitabRole: undefined;
|
onSomeTabSwitchedMultitabRole: undefined;
|
||||||
afterHangUp: undefined;
|
afterHangUp: undefined;
|
||||||
requestMasterAndCallAction: CallbackAction & WithTabId;
|
requestMasterAndCallAction: CallbackAction & WithTabId;
|
||||||
@ -2169,10 +2167,7 @@ export interface ActionPayloads {
|
|||||||
} & WithTabId;
|
} & WithTabId;
|
||||||
dismissNotification: { localId: string } & WithTabId;
|
dismissNotification: { localId: string } & WithTabId;
|
||||||
|
|
||||||
updatePageTitle: {
|
updatePageTitle: WithTabId | undefined;
|
||||||
isInactive?: boolean;
|
|
||||||
notificationCount?: number;
|
|
||||||
} & WithTabId | undefined;
|
|
||||||
|
|
||||||
// Calls
|
// Calls
|
||||||
joinGroupCall: {
|
joinGroupCall: {
|
||||||
|
|||||||
@ -4,11 +4,11 @@ const UPDATE_DEBOUNCE_MS = 200;
|
|||||||
|
|
||||||
// For some reason setting `document.title` to the same value
|
// For some reason setting `document.title` to the same value
|
||||||
// causes increment of Chrome Dev Tools > Performance Monitor > DOM Nodes counter
|
// causes increment of Chrome Dev Tools > Performance Monitor > DOM Nodes counter
|
||||||
function updatePageTitle(nextTitle: string) {
|
export function setPageTitleInstant(nextTitle: string) {
|
||||||
if (document.title !== nextTitle) {
|
if (document.title !== nextTitle) {
|
||||||
document.title = nextTitle;
|
document.title = nextTitle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Synchronous page title update has conflicts with History API in Chrome
|
// Synchronous page title update has conflicts with History API in Chrome
|
||||||
export default debounce(updatePageTitle, UPDATE_DEBOUNCE_MS, false);
|
export const setPageTitle = debounce(setPageTitleInstant, UPDATE_DEBOUNCE_MS, false);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user