[Perf] Pause all CSS animations when in background

This commit is contained in:
Alexander Zinchuk 2025-10-15 19:57:16 +02:00
parent 89e37c280b
commit 980fb6ef41
9 changed files with 46 additions and 22 deletions

View File

@ -6,10 +6,8 @@ import type { GlobalState } from '../global/types';
import type { ThemeKey } from '../types';
import type { UiLoaderPage } from './common/UiLoader';
import {
DARK_THEME_BG_COLOR, INACTIVE_MARKER, LIGHT_THEME_BG_COLOR, PAGE_TITLE,
PAGE_TITLE_TAURI,
} from '../config';
import { DARK_THEME_BG_COLOR, INACTIVE_MARKER, LIGHT_THEME_BG_COLOR, PAGE_TITLE, PAGE_TITLE_TAURI } from '../config';
import { forceMutation } from '../lib/fasterdom/stricterdom.ts';
import { selectTabState, selectTheme } from '../global/selectors';
import { IS_TAURI } from '../util/browser/globalEnvironment';
import { IS_INSTALL_PROMPT_SUPPORTED, PLATFORM_ENV } from '../util/browser/windowEnvironment';
@ -24,6 +22,8 @@ import { updateSizes } from '../util/windowSize';
import useTauriDrag from '../hooks/tauri/useTauriDrag';
import useAppLayout from '../hooks/useAppLayout';
import usePrevious from '../hooks/usePrevious';
import { useSignalEffect } from '../hooks/useSignalEffect.ts';
import { getIsInBackground } from '../hooks/window/useBackgroundMode.ts';
// import Test from './test/TestLocale';
import Auth from './auth/Auth';
@ -226,6 +226,14 @@ const App: FC<StateProps> = ({
);
}, [theme]);
const getIsInBackgroundLocal = getIsInBackground;
useSignalEffect(() => {
// Mutation forced to avoid RAF throttling in background
forceMutation(() => {
document.body.classList.toggle('in-background', getIsInBackgroundLocal());
}, document.body);
}, [getIsInBackgroundLocal]);
return (
<UiLoader page={page} isMobile={isMobile}>
<Transition

View File

@ -15,6 +15,10 @@
html[lang="fa"] & {
animation-name: dot-animation-rtl;
}
body.in-background & {
animation-play-state: paused;
}
}
}
}

View File

@ -78,7 +78,6 @@
transition: transform 500ms ease-in;
&::before {
--x-direction: 0;
--y-direction: var(--background-size);
@ -99,7 +98,6 @@
}
&::after {
--x-direction: calc(-1 * var(--background-size));
--y-direction: calc(-1 * var(--background-size));
@ -143,6 +141,12 @@
}
}
:global(body.in-background) .dots {
&, &::before, &::after {
animation-play-state: paused;
}
}
@keyframes dots-animation {
0% {
background-position: 0 0;

View File

@ -30,11 +30,15 @@
animation: sparkle 5s infinite;
animation-delay: var(--_duration-shift);
}
.noAnimation .symbol {
opacity: 0.5;
animation: none;
.noAnimation & {
opacity: 0.5;
animation: none;
}
:global(body.in-background) & {
animation-play-state: paused;
}
}
@keyframes sparkle {

View File

@ -1,10 +1,8 @@
import { memo, useEffect, useRef } from '../../lib/teact/teact';
import { memo, useRef } from '../../lib/teact/teact';
import buildClassName from '../../util/buildClassName';
import buildStyle from '../../util/buildStyle';
import { getIsInBackground } from '../../hooks/window/useBackgroundMode.ts';
import styles from './Sparkles.module.scss';
type ButtonParameters = {
@ -93,13 +91,6 @@ const Sparkles = ({
}: OwnProps) => {
const ref = useRef<HTMLDivElement>();
const getIsInBackgroundLocal = getIsInBackground;
useEffect(() => {
(Array.from(ref.current!.children) as HTMLDivElement[]).forEach((sparkleEL) => {
sparkleEL.style.animationPlayState = getIsInBackgroundLocal() ? 'paused' : 'running';
});
}, [getIsInBackgroundLocal]);
if (presetSettings.preset === 'button') {
return (
<div

View File

@ -20,6 +20,10 @@
&--animated {
animation: pulse-opacity-light 1.75s linear infinite;
:global(body.in-background) & {
animation-play-state: paused;
}
}
&__content {

View File

@ -93,6 +93,10 @@
animation-duration: 1s;
animation-timing-function: linear;
animation-iteration-count: infinite;
:global(body.in-background) & {
animation-play-state: paused;
}
}
@keyframes spin {

View File

@ -73,4 +73,8 @@
}
}
}
:global(body.in-background) &::before {
animation-play-state: paused;
}
}

View File

@ -1,4 +1,5 @@
import type { FC } from '../../../lib/teact/teact';
import type { FC } from '@teact';
import { memo } from '@teact';
import buildClassName from '../../../util/buildClassName';
import buildStyle from '../../../util/buildStyle';
@ -36,4 +37,4 @@ const Skeleton: FC<OwnProps> = ({
);
};
export default Skeleton;
export default memo(Skeleton);