Media Viewer: Fix closing animation (#5515)

This commit is contained in:
zubiden 2025-01-21 18:22:13 +01:00 committed by Alexander Zinchuk
parent ea2c3111eb
commit 5a00d56a69
9 changed files with 22 additions and 23 deletions

View File

@ -5,8 +5,9 @@ import { ANIMATION_END_DELAY, MESSAGE_CONTENT_SELECTOR } from '../../../config';
import { requestMutation } from '../../../lib/fasterdom/fasterdom';
import { getMessageHtmlId } from '../../../global/helpers';
import { applyStyles } from '../../../util/animation';
import { isElementInViewport } from '../../../util/isElementInViewport';
import stopEvent from '../../../util/stopEvent';
import getOffsetToContainer from '../../../util/visibility/getOffsetToContainer';
import { isElementInViewport } from '../../../util/visibility/isElementInViewport';
import { IS_TOUCH_ENV } from '../../../util/windowEnvironment';
import windowSize from '../../../util/windowSize';
import {
@ -128,11 +129,13 @@ export function animateClosing(
let fromScaleY = fromHeight / toHeight;
const shouldFadeOut = (
[MediaViewerOrigin.Inline, MediaViewerOrigin.ScheduledInline].includes(origin)
&& !isMessageImageFullyVisible(container, toImage)
) || (
[MediaViewerOrigin.Album, MediaViewerOrigin.ScheduledAlbum].includes(origin)
&& !isMessageImageFullyVisible(container, toImage)
[
MediaViewerOrigin.Inline,
MediaViewerOrigin.ScheduledInline,
MediaViewerOrigin.Album,
MediaViewerOrigin.ScheduledAlbum,
].includes(origin)
&& !isMessageImageFullyVisible(toImage)
);
if ([
@ -266,15 +269,13 @@ function uncover(realWidth: number, realHeight: number, top: number, left: numbe
};
}
function isMessageImageFullyVisible(container: HTMLElement, imageEl: HTMLElement) {
function isMessageImageFullyVisible(imageEl: HTMLElement) {
const messageListElement = document.querySelector<HTMLDivElement>('.Transition_slide-active > .MessageList')!;
let imgOffsetTop = container.offsetTop + imageEl.closest<HTMLDivElement>('.content-inner, .WebPage')!.offsetTop;
if (container.id.includes('album-media-')) {
imgOffsetTop += container.parentElement!.offsetTop + container.closest<HTMLDivElement>('.Message')!.offsetTop;
}
return imgOffsetTop > messageListElement.scrollTop
&& imgOffsetTop + imageEl.offsetHeight < messageListElement.scrollTop + messageListElement.offsetHeight;
const { top } = getOffsetToContainer(imageEl, messageListElement);
return top > messageListElement.scrollTop
&& top + imageEl.offsetHeight < messageListElement.scrollTop + messageListElement.offsetHeight;
}
function getTopOffset(hasFooter: boolean) {

View File

@ -56,7 +56,7 @@ import { orderBy } from '../../util/iteratees';
import { isLocalMessageId } from '../../util/keys/messageKey';
import resetScroll from '../../util/resetScroll';
import { debounce, onTickEnd } from '../../util/schedulers';
import { getOffsetToContainer } from '../../util/scroll';
import getOffsetToContainer from '../../util/visibility/getOffsetToContainer';
import { groupMessages } from './helpers/groupMessages';
import { preventMessageInputBlur } from './helpers/preventMessageInputBlur';

View File

@ -6,7 +6,7 @@ import type { ApiSticker } from '../../../api/types';
import animateHorizontalScroll from '../../../util/animateHorizontalScroll';
import buildClassName from '../../../util/buildClassName';
import findInViewport from '../../../util/findInViewport';
import isFullyVisible from '../../../util/isFullyVisible';
import isFullyVisible from '../../../util/visibility/isFullyVisible';
import useEffectWithPrevDeps from '../../../hooks/useEffectWithPrevDeps';
import useHorizontalScroll from '../../../hooks/useHorizontalScroll';

View File

@ -111,9 +111,9 @@ import {
selectUser,
} from '../../../global/selectors';
import buildClassName from '../../../util/buildClassName';
import { isElementInViewport } from '../../../util/isElementInViewport';
import { getMessageKey } from '../../../util/keys/messageKey';
import stopEvent from '../../../util/stopEvent';
import { isElementInViewport } from '../../../util/visibility/isElementInViewport';
import { IS_ANDROID, IS_ELECTRON, IS_TRANSLATION_SUPPORTED } from '../../../util/windowEnvironment';
import { calculateDimensionsForMessageMedia, getStickerDimensions, REM } from '../../common/helpers/mediaDimensions';
import { getPeerColorClass } from '../../common/helpers/peerColor';

View File

@ -12,8 +12,8 @@ import {
} from '../config';
import { requestMeasure, requestMutation } from '../lib/fasterdom/fasterdom';
import { selectCanAnimateInterface } from '../global/selectors';
import getOffsetToContainer from './visibility/getOffsetToContainer';
import { animateSingle, cancelSingleAnimation } from './animation';
import { getOffsetToContainer } from './scroll';
import { IS_ANDROID } from './windowEnvironment';
export type AnimateScrollArgs = {

View File

@ -1,6 +1,6 @@
import isFullyVisible from './visibility/isFullyVisible';
import animateScroll from './animateScroll';
import findInViewport from './findInViewport';
import isFullyVisible from './isFullyVisible';
const VIEWPORT_MARGIN = 8;
const SCROLL_MARGIN = 10;

View File

@ -1,4 +1,4 @@
export function getOffsetToContainer(element: HTMLElement, container: HTMLElement) {
export default function getOffsetToContainer(element: HTMLElement, container: HTMLElement) {
let offsetTop = 0;
let offsetLeft = 0;

View File

@ -1,4 +1,4 @@
import windowSize from './windowSize';
import windowSize from '../windowSize';
export function isElementInViewport(el: HTMLElement) {
if (el.style.display === 'none') {

View File

@ -1,9 +1,7 @@
function isFullyVisible(container: HTMLElement, element: HTMLElement, isHorizontal = false) {
export default function isFullyVisible(container: HTMLElement, element: HTMLElement, isHorizontal = false) {
const viewportY1 = container[isHorizontal ? 'scrollLeft' : 'scrollTop'];
const viewportY2 = viewportY1 + container[isHorizontal ? 'offsetWidth' : 'offsetHeight'];
const y1 = element[isHorizontal ? 'offsetLeft' : 'offsetTop'];
const y2 = y1 + element[isHorizontal ? 'offsetWidth' : 'offsetHeight'];
return y1 > viewportY1 && y2 < viewportY2;
}
export default isFullyVisible;