diff --git a/src/global/actions/ui/messages.ts b/src/global/actions/ui/messages.ts index 7ff2dbd77..a809c14a0 100644 --- a/src/global/actions/ui/messages.ts +++ b/src/global/actions/ui/messages.ts @@ -13,6 +13,7 @@ import { SCROLL_MAX_DURATION, SERVICE_NOTIFICATIONS_USER_ID, } from '../../../config'; +import { cancelScrollBlockingAnimation, isAnimatingScroll } from '../../../util/animateScroll'; import { copyHtmlToClipboard } from '../../../util/clipboard'; import { getCurrentTabId } from '../../../util/establishMultitabRole'; import { compact, findLast } from '../../../util/iteratees'; @@ -489,6 +490,10 @@ addActionHandler('focusMessage', (global, actions, payload): ActionReturnType => global = updateFocusDirection(global, direction, tabId); } + if (isAnimatingScroll()) { + cancelScrollBlockingAnimation(); + } + setGlobal(global, { forceOnHeavyAnimation: true }); actions.openThread({ diff --git a/src/lib/teact/heavyAnimation.ts b/src/lib/teact/heavyAnimation.ts index 816376333..d9bb7f437 100644 --- a/src/lib/teact/heavyAnimation.ts +++ b/src/lib/teact/heavyAnimation.ts @@ -5,18 +5,29 @@ import { requestMeasure } from '../fasterdom/fasterdom'; const AUTO_END_TIMEOUT = 1000; let counter = 0; +let counterBlocking = 0; const [getIsAnimating, setIsAnimating] = createSignal(false); +const [getIsBlockingAnimating, setIsBlockingAnimating] = createSignal(false); export const getIsHeavyAnimating = getIsAnimating; +export { getIsBlockingAnimating }; -export function beginHeavyAnimation(duration = AUTO_END_TIMEOUT) { +export function beginHeavyAnimation(duration = AUTO_END_TIMEOUT, isBlocking = false) { counter++; if (counter === 1) { setIsAnimating(true); } + if (isBlocking) { + counterBlocking++; + + if (counterBlocking === 1) { + setIsBlockingAnimating(true); + } + } + const timeout = window.setTimeout(onEnd, duration); let hasEnded = false; @@ -32,6 +43,14 @@ export function beginHeavyAnimation(duration = AUTO_END_TIMEOUT) { if (counter === 0) { setIsAnimating(false); } + + if (isBlocking) { + counterBlocking--; + + if (counterBlocking === 0) { + setIsBlockingAnimating(false); + } + } } return onEnd; diff --git a/src/lib/teact/teact.ts b/src/lib/teact/teact.ts index d2783e8b8..e427270df 100644 --- a/src/lib/teact/teact.ts +++ b/src/lib/teact/teact.ts @@ -8,6 +8,7 @@ import safeExec from '../../util/safeExec'; import { throttleWith } from '../../util/schedulers'; import { createSignal, isSignal, type Signal } from '../../util/signals'; import { requestMeasure, requestMutation } from '../fasterdom/fasterdom'; +import { getIsBlockingAnimating } from './heavyAnimation'; export { getIsHeavyAnimating, beginHeavyAnimation, onFullyIdle } from './heavyAnimation'; @@ -329,6 +330,11 @@ let areImmediateEffectsCaptured = false; */ const runUpdatePassOnRaf = throttleWith(requestMeasure, () => { + if (getIsBlockingAnimating()) { + getIsBlockingAnimating.once(runUpdatePassOnRaf); + return; + } + const runImmediateEffects = captureImmediateEffects(); idsToExcludeFromUpdate = new Set(); diff --git a/src/util/animateScroll.ts b/src/util/animateScroll.ts index 41fd4f4a2..2f2f0c684 100644 --- a/src/util/animateScroll.ts +++ b/src/util/animateScroll.ts @@ -127,7 +127,7 @@ function createMutateFunction( isAnimating = true; const prevOnHeavyAnimationEnd = onHeavyAnimationEnd; - onHeavyAnimationEnd = beginHeavyAnimation(); + onHeavyAnimationEnd = beginHeavyAnimation(undefined, true); prevOnHeavyAnimationEnd?.(); animateSingle(() => { @@ -142,7 +142,7 @@ function createMutateFunction( if (!isAnimating) { currentArgs = undefined; - onHeavyAnimationEnd!(); + onHeavyAnimationEnd?.(); onHeavyAnimationEnd = undefined; } @@ -155,6 +155,11 @@ export function isAnimatingScroll() { return isAnimating; } +export function cancelScrollBlockingAnimation() { + onHeavyAnimationEnd!(); + onHeavyAnimationEnd = undefined; +} + function calculateScrollFrom( container: HTMLElement, scrollTo: number,