diff --git a/ts/state/ducks/conversations.ts b/ts/state/ducks/conversations.ts index 4d739491b5..e6a967a27d 100644 --- a/ts/state/ducks/conversations.ts +++ b/ts/state/ducks/conversations.ts @@ -483,6 +483,7 @@ export type ConversationsStateType = Readonly<{ targetedMessageSource: TargetedMessageSource | undefined; targetedConversationPanels: { isAnimating: boolean; + wasAnimated: boolean; direction: 'push' | 'pop' | undefined; stack: ReadonlyArray; watermark: number; @@ -4156,6 +4157,7 @@ export function getEmptyState(): ConversationsStateType { showArchived: false, targetedConversationPanels: { isAnimating: false, + wasAnimated: false, direction: undefined, stack: [], watermark: -1, @@ -4710,6 +4712,7 @@ export function reducer( selectedConversationId, targetedConversationPanels: { isAnimating: false, + wasAnimated: false, direction: undefined, stack: [], watermark: -1, @@ -5651,6 +5654,7 @@ export function reducer( const targetedConversationPanels = { isAnimating: false, + wasAnimated: false, direction: 'push' as const, stack, watermark, @@ -5691,6 +5695,7 @@ export function reducer( const targetedConversationPanels = { isAnimating: false, + wasAnimated: false, direction: 'pop' as const, stack: state.targetedConversationPanels.stack, watermark, @@ -5726,6 +5731,7 @@ export function reducer( targetedConversationPanels: { ...state.targetedConversationPanels, isAnimating: false, + wasAnimated: true, }, }; } diff --git a/ts/state/selectors/conversations.ts b/ts/state/selectors/conversations.ts index b04bc04e44..69babb997e 100644 --- a/ts/state/selectors/conversations.ts +++ b/ts/state/selectors/conversations.ts @@ -1201,6 +1201,13 @@ export const getIsPanelAnimating = createSelector( } ); +export const getWasPanelAnimated = createSelector( + getConversations, + (conversations): boolean => { + return conversations.targetedConversationPanels.wasAnimated; + } +); + export const getConversationTitle = createSelector( getIntl, getActivePanel, diff --git a/ts/state/smart/ConversationPanel.tsx b/ts/state/smart/ConversationPanel.tsx index c456a0c756..229c68f03c 100644 --- a/ts/state/smart/ConversationPanel.tsx +++ b/ts/state/smart/ConversationPanel.tsx @@ -2,7 +2,14 @@ // SPDX-License-Identifier: AGPL-3.0-only import type { MutableRefObject } from 'react'; -import React, { forwardRef, useEffect, useMemo, useRef, useState } from 'react'; +import React, { + forwardRef, + useCallback, + useEffect, + useMemo, + useRef, + useState, +} from 'react'; import { useSelector } from 'react-redux'; import type { PanelRenderType } from '../../types/Panels'; import * as log from '../../logging/log'; @@ -23,6 +30,7 @@ import { getIntl } from '../selectors/user'; import { getIsPanelAnimating, getPanelInformation, + getWasPanelAnimated, } from '../selectors/conversations'; import { focusableSelectors } from '../../util/focusableSelectors'; import { missingCaseError } from '../../util/missingCaseError'; @@ -92,37 +100,48 @@ export function ConversationPanel({ const panelInformation = useSelector(getPanelInformation); const { panelAnimationDone, panelAnimationStarted } = useConversationsActions(); - const [shouldRenderPoppedPanel, setShouldRenderPoppedPanel] = useState(true); + const animateRef = useRef(null); const overlayRef = useRef(null); const prefersReducedMotion = useReducedMotion(); - useEffect(() => { - setShouldRenderPoppedPanel(true); - }, [panelInformation?.prevPanel]); - const i18n = useSelector(getIntl); const isRTL = i18n.getLocaleDirection() === 'rtl'; const isAnimating = useSelector(getIsPanelAnimating); + const wasAnimated = useSelector(getWasPanelAnimated); + + const [lastPanelDoneAnimating, setLastPanelDoneAnimating] = + useState(null); + + const wasAnimatedRef = useRef(wasAnimated); + useEffect(() => { + wasAnimatedRef.current = wasAnimated; + }, [wasAnimated]); useEffect(() => { - if (prefersReducedMotion) { + setLastPanelDoneAnimating(null); + }, [panelInformation?.prevPanel]); + + const onAnimationDone = useCallback( + (panel: PanelRenderType | null) => { + setLastPanelDoneAnimating(panel); panelAnimationDone(); - setShouldRenderPoppedPanel(false); + }, + [panelAnimationDone] + ); + + useEffect(() => { + if (prefersReducedMotion || wasAnimatedRef.current) { + onAnimationDone(panelInformation?.prevPanel ?? null); return; } if (panelInformation?.direction === 'pop') { - if (!shouldRenderPoppedPanel) { - return; - } - return doAnimate({ isRTL, onAnimationDone: () => { - panelAnimationDone(); - setShouldRenderPoppedPanel(false); + onAnimationDone(panelInformation?.prevPanel ?? null); }, onAnimationStarted: panelAnimationStarted, overlay: { @@ -143,13 +162,11 @@ export function ConversationPanel({ } if (panelInformation?.direction === 'push') { - if (!panelInformation?.currPanel) { - return; - } - return doAnimate({ isRTL, - onAnimationDone: panelAnimationDone, + onAnimationDone: () => { + onAnimationDone(panelInformation?.prevPanel ?? null); + }, onAnimationStarted: panelAnimationStarted, overlay: { ref: overlayRef, @@ -171,13 +188,12 @@ export function ConversationPanel({ return undefined; }, [ isRTL, - panelAnimationDone, + onAnimationDone, panelAnimationStarted, panelInformation?.currPanel, panelInformation?.direction, panelInformation?.prevPanel, prefersReducedMotion, - shouldRenderPoppedPanel, ]); if (!panelInformation) { @@ -200,10 +216,10 @@ export function ConversationPanel({ panel={activePanel} /> )} - {shouldRenderPoppedPanel && ( + {lastPanelDoneAnimating !== prevPanel && (
)} - {shouldRenderPoppedPanel && prevPanel && ( + {prevPanel && lastPanelDoneAnimating !== prevPanel && ( (null);", "reasonCategory": "usageTrusted", - "updated": "2023-08-09T21:48:42.602Z", - "reasonDetail": "" + "updated": "2023-08-09T21:48:42.602Z" }, { "rule": "React-useRef", @@ -2427,16 +2426,14 @@ "path": "ts/components/Modal.tsx", "line": " const bodyRef = useRef(null);", "reasonCategory": "usageTrusted", - "updated": "2023-07-25T21:55:26.191Z", - "reasonDetail": "" + "updated": "2023-07-25T21:55:26.191Z" }, { "rule": "React-useRef", "path": "ts/components/Modal.tsx", "line": " const bodyInnerRef = useRef(null);", "reasonCategory": "usageTrusted", - "updated": "2023-07-25T21:55:26.191Z", - "reasonDetail": "" + "updated": "2023-07-25T21:55:26.191Z" }, { "rule": "React-useRef", @@ -2529,24 +2526,21 @@ "path": "ts/components/StoryViewer.tsx", "line": " const progressBarRef = useRef(null);", "reasonCategory": "usageTrusted", - "updated": "2022-10-13T15:18:21.267Z", - "reasonDetail": "" + "updated": "2022-10-13T15:18:21.267Z" }, { "rule": "React-useRef", "path": "ts/components/StoryViewer.tsx", "line": " const animationRef = useRef(null);", "reasonCategory": "usageTrusted", - "updated": "2022-10-13T15:18:21.267Z", - "reasonDetail": "" + "updated": "2022-10-13T15:18:21.267Z" }, { "rule": "React-useRef", "path": "ts/components/StoryViewer.tsx", "line": " const onFinishRef = useRef<(() => void) | null>(null);", "reasonCategory": "usageTrusted", - "updated": "2022-10-13T15:18:21.267Z", - "reasonDetail": "" + "updated": "2022-10-13T15:18:21.267Z" }, { "rule": "React-useRef", @@ -2595,8 +2589,7 @@ "path": "ts/components/TextAttachment.tsx", "line": " const ref = useRef(null);", "reasonCategory": "usageTrusted", - "updated": "2023-07-25T21:55:26.191Z", - "reasonDetail": "" + "updated": "2023-07-25T21:55:26.191Z" }, { "rule": "React-useRef", @@ -2617,8 +2610,7 @@ "path": "ts/components/Tooltip.tsx", "line": " const timeoutRef = useRef();", "reasonCategory": "usageTrusted", - "updated": "2023-08-10T00:23:35.320Z", - "reasonDetail": "" + "updated": "2023-08-10T00:23:35.320Z" }, { "rule": "React-createRef", @@ -2832,56 +2824,49 @@ "path": "ts/hooks/useSizeObserver.tsx", "line": " const sizeRef = useRef(null);", "reasonCategory": "usageTrusted", - "updated": "2023-07-25T21:55:26.191Z", - "reasonDetail": "" + "updated": "2023-07-25T21:55:26.191Z" }, { "rule": "React-useRef", "path": "ts/hooks/useSizeObserver.tsx", "line": " const onSizeChangeRef = useRef(onSizeChange);", "reasonCategory": "usageTrusted", - "updated": "2023-07-25T21:55:26.191Z", - "reasonDetail": "" + "updated": "2023-07-25T21:55:26.191Z" }, { "rule": "React-useRef", "path": "ts/hooks/useSizeObserver.tsx", "line": " const ref = useRef();", "reasonCategory": "usageTrusted", - "updated": "2023-07-25T21:55:26.191Z", - "reasonDetail": "" + "updated": "2023-07-25T21:55:26.191Z" }, { "rule": "React-useRef", "path": "ts/hooks/useSizeObserver.tsx", "line": " * const scrollerRef = useRef()", "reasonCategory": "usageTrusted", - "updated": "2023-07-25T21:55:26.191Z", - "reasonDetail": "" + "updated": "2023-07-25T21:55:26.191Z" }, { "rule": "React-useRef", "path": "ts/hooks/useSizeObserver.tsx", "line": " * const scrollerInnerRef = useRef()", "reasonCategory": "usageTrusted", - "updated": "2023-07-25T21:55:26.191Z", - "reasonDetail": "" + "updated": "2023-07-25T21:55:26.191Z" }, { "rule": "React-useRef", "path": "ts/hooks/useSizeObserver.tsx", "line": " const scrollRef = useRef(null);", "reasonCategory": "usageTrusted", - "updated": "2023-07-25T21:55:26.191Z", - "reasonDetail": "" + "updated": "2023-07-25T21:55:26.191Z" }, { "rule": "React-useRef", "path": "ts/hooks/useSizeObserver.tsx", "line": " const onScrollChangeRef = useRef(onScrollChange);", "reasonCategory": "usageTrusted", - "updated": "2023-07-25T21:55:26.191Z", - "reasonDetail": "" + "updated": "2023-07-25T21:55:26.191Z" }, { "rule": "React-useRef", @@ -2936,6 +2921,13 @@ "reasonCategory": "usageTrusted", "updated": "2023-07-13T23:34:39.367Z" }, + { + "rule": "React-useRef", + "path": "ts/state/smart/ConversationPanel.tsx", + "line": " const wasAnimatedRef = useRef(wasAnimated);", + "reasonCategory": "usageTrusted", + "updated": "2023-08-20T22:14:52.008Z" + }, { "rule": "React-useRef", "path": "ts/state/smart/InstallScreen.tsx",