From b9b439da1342cf974a52cd5432269560d0891a70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Musia=C5=82?= Date: Mon, 14 Jul 2025 12:47:21 +0200 Subject: [PATCH 1/8] Migrate ValidateCodeActionModal to ReanimatedModal --- src/components/ValidateCodeActionModal/index.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/components/ValidateCodeActionModal/index.tsx b/src/components/ValidateCodeActionModal/index.tsx index 85a953eb2a10..c0a8e939e00f 100644 --- a/src/components/ValidateCodeActionModal/index.tsx +++ b/src/components/ValidateCodeActionModal/index.tsx @@ -72,6 +72,9 @@ function ValidateCodeActionModal({ useNativeDriver shouldUseModalPaddingStyle={false} animationInTiming={disableAnimation ? 1 : undefined} + shouldUseReanimatedModal + animationIn="slideInRight" + animationOut="slideOutRight" > Date: Mon, 14 Jul 2025 16:44:26 +0200 Subject: [PATCH 2/8] fix wide screen issues --- .../AvatarCropModal/AvatarCropModal.tsx | 1 + src/components/Modal/BaseModal.tsx | 18 +++++- .../ValidateCodeActionModal/index.tsx | 2 - .../utils/generators/ModalStyleUtils.ts | 58 ++++++++++++------- 4 files changed, 54 insertions(+), 25 deletions(-) diff --git a/src/components/AvatarCropModal/AvatarCropModal.tsx b/src/components/AvatarCropModal/AvatarCropModal.tsx index aa2b98cdae6d..0f6cbfff2b7d 100644 --- a/src/components/AvatarCropModal/AvatarCropModal.tsx +++ b/src/components/AvatarCropModal/AvatarCropModal.tsx @@ -352,6 +352,7 @@ function AvatarCropModal({imageUri = '', imageName = '', imageType = '', onClose shouldUseCustomBackdrop shouldHandleNavigationBack enableEdgeToEdgeBottomSafeAreaPadding + shouldUseReanimatedModal > { diff --git a/src/components/ValidateCodeActionModal/index.tsx b/src/components/ValidateCodeActionModal/index.tsx index c0a8e939e00f..a737bbcf1568 100644 --- a/src/components/ValidateCodeActionModal/index.tsx +++ b/src/components/ValidateCodeActionModal/index.tsx @@ -73,8 +73,6 @@ function ValidateCodeActionModal({ shouldUseModalPaddingStyle={false} animationInTiming={disableAnimation ? 1 : undefined} shouldUseReanimatedModal - animationIn="slideInRight" - animationOut="slideOutRight" > GetModalStyles; }; const createModalStyleUtils: StyleUtilGenerator = ({theme, styles}) => ({ - getModalStyles: (type, windowDimensions, popoverAnchorPosition = {}, innerContainerStyle = {}, outerStyle = {}, shouldUseModalPaddingStyle = true): GetModalStyles => { - const {windowWidth, isSmallScreenWidth} = windowDimensions; + getModalStyles: ( + type, + windowDimensions, + popoverAnchorPosition = {}, + innerContainerStyle = {}, + outerStyle = {}, + shouldUseModalPaddingStyle = true, + shouldUseReanimatedModal = false, + ): GetModalStyles => { + const {windowWidth, isSmallScreenWidth, shouldUseNarrowLayout} = windowDimensions; let modalStyle: GetModalStyles['modalStyle'] = { margin: 0, @@ -258,34 +268,40 @@ const createModalStyleUtils: StyleUtilGenerator = ({the modalStyle = { ...modalStyle, ...{ - marginLeft: isSmallScreenWidth ? 0 : windowWidth - variables.sideBarWidth, - width: isSmallScreenWidth ? '100%' : variables.sideBarWidth, + marginLeft: isSmallScreenWidth || (shouldUseReanimatedModal && shouldUseNarrowLayout) ? 0 : windowWidth - variables.sideBarWidth, + width: isSmallScreenWidth || (shouldUseReanimatedModal && shouldUseNarrowLayout) ? '100%' : variables.sideBarWidth, flexDirection: 'row', justifyContent: 'flex-end', }, }; modalContainerStyle = { - width: isSmallScreenWidth ? '100%' : variables.sideBarWidth, + width: isSmallScreenWidth || (shouldUseReanimatedModal && shouldUseNarrowLayout) ? '100%' : variables.sideBarWidth, height: '100%', overflow: 'hidden', }; - animationIn = { - from: { - translateX: isSmallScreenWidth ? windowWidth : variables.sideBarWidth, - }, - to: { - translateX: 0, - }, - }; - animationOut = { - from: { - translateX: 0, - }, - to: { - translateX: isSmallScreenWidth ? windowWidth : variables.sideBarWidth, - }, - }; + if (shouldUseReanimatedModal) { + animationIn = 'slideInRight'; + animationOut = 'slideOutRight'; + } else { + animationIn = { + from: { + translateX: isSmallScreenWidth ? windowWidth : variables.sideBarWidth, + }, + to: { + translateX: 0, + }, + }; + animationOut = { + from: { + translateX: 0, + }, + to: { + translateX: isSmallScreenWidth ? windowWidth : variables.sideBarWidth, + }, + }; + } + hideBackdrop = true; swipeDirection = undefined; shouldAddBottomSafeAreaPadding = true; From edfa2bc652a53f8760b9df145a27f9ae5905168a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Musia=C5=82?= Date: Mon, 14 Jul 2025 16:59:56 +0200 Subject: [PATCH 3/8] fix ts --- src/styles/utils/generators/ModalStyleUtils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/styles/utils/generators/ModalStyleUtils.ts b/src/styles/utils/generators/ModalStyleUtils.ts index e522722aec97..f10bd384dd8b 100644 --- a/src/styles/utils/generators/ModalStyleUtils.ts +++ b/src/styles/utils/generators/ModalStyleUtils.ts @@ -19,7 +19,7 @@ type WindowDimensions = { windowWidth: number; windowHeight: number; isSmallScreenWidth: boolean; - shouldUseNarrowLayout: boolean; + shouldUseNarrowLayout?: boolean; }; type GetModalStyles = { From 8aced10231f419416da7e8bbdd047f13e1551674 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Musia=C5=82?= Date: Mon, 14 Jul 2025 17:23:57 +0200 Subject: [PATCH 4/8] add forgotten stashed changes lol --- src/components/Modal/BaseModal.tsx | 15 +++++++++------ .../Modal/ReanimatedModal/Backdrop/index.web.tsx | 10 ++++++++-- src/hooks/useSidePanel.ts | 7 +++++++ src/styles/utils/generators/ModalStyleUtils.ts | 4 ++-- 4 files changed, 26 insertions(+), 10 deletions(-) diff --git a/src/components/Modal/BaseModal.tsx b/src/components/Modal/BaseModal.tsx index 0832d2692d6e..95dc96b06ad3 100644 --- a/src/components/Modal/BaseModal.tsx +++ b/src/components/Modal/BaseModal.tsx @@ -1,5 +1,7 @@ import React, {forwardRef, useCallback, useContext, useEffect, useMemo, useRef} from 'react'; -import {View} from 'react-native'; +// Animated required for side panel navigation +// eslint-disable-next-line no-restricted-imports +import {Animated, View} from 'react-native'; import type {ModalProps as ReactNativeModalProps} from 'react-native-modal'; import ReactNativeModal from 'react-native-modal'; import type {ValueOf} from 'type-fest'; @@ -106,8 +108,9 @@ function BaseModal( // We need to use isSmallScreenWidth instead of shouldUseNarrowLayout to apply correct modal width // eslint-disable-next-line rulesdir/prefer-shouldUseNarrowLayout-instead-of-isSmallScreenWidth const {isSmallScreenWidth, shouldUseNarrowLayout} = useResponsiveLayout(); - const {sidePanelOffset} = useSidePanel(); - const sidePanelStyle = shouldApplySidePanelOffset && !isSmallScreenWidth ? {paddingRight: sidePanelOffset.current} : undefined; + const {sidePanelOffset, modalTranslateX} = useSidePanel(); + const sidePanelStyle = !shouldUseReanimatedModal && shouldApplySidePanelOffset && !isSmallScreenWidth ? {paddingRight: sidePanelOffset.current} : undefined; + const sidePanelReanimatedStyle = shouldUseReanimatedModal && shouldApplySidePanelOffset && !isSmallScreenWidth ? {transform: [{translateX: modalTranslateX.current}]} : undefined; const keyboardStateContextValue = useKeyboardState(); const insets = useSafeAreaInsets(); @@ -363,12 +366,12 @@ function BaseModal( initialFocus={initialFocus} shouldPreventScroll={shouldPreventScrollOnFocus} > - {children} - + {!keyboardStateContextValue?.isKeyboardActive && } diff --git a/src/components/Modal/ReanimatedModal/Backdrop/index.web.tsx b/src/components/Modal/ReanimatedModal/Backdrop/index.web.tsx index 10f4f54c9263..02b148259aa3 100644 --- a/src/components/Modal/ReanimatedModal/Backdrop/index.web.tsx +++ b/src/components/Modal/ReanimatedModal/Backdrop/index.web.tsx @@ -22,16 +22,22 @@ function Backdrop({ const {translate} = useLocalize(); const Entering = useMemo(() => { + if (!backdropOpacity) { + return; + } const FadeIn = new Keyframe(getModalInAnimation('fadeIn')); return FadeIn.duration(animationInTiming); - }, [animationInTiming]); + }, [animationInTiming, backdropOpacity]); const Exiting = useMemo(() => { + if (!backdropOpacity) { + return; + } const FadeOut = new Keyframe(getModalOutAnimation('fadeOut')); return FadeOut.duration(animationOutTiming); - }, [animationOutTiming]); + }, [animationOutTiming, backdropOpacity]); const backdropStyle = useMemo( () => ({ diff --git a/src/hooks/useSidePanel.ts b/src/hooks/useSidePanel.ts index 2df4b1c5a056..a1aa271dd087 100644 --- a/src/hooks/useSidePanel.ts +++ b/src/hooks/useSidePanel.ts @@ -71,6 +71,7 @@ function useSidePanel() { const shouldApplySidePanelOffset = isExtraLargeScreenWidth && !shouldHideSidePanel; const sidePanelOffset = useRef(new Animated.Value(shouldApplySidePanelOffset ? variables.sideBarWidth : 0)); const sidePanelTranslateX = useRef(new Animated.Value(shouldHideSidePanel ? sidePanelWidth : 0)); + const modalTranslateX = useRef(new Animated.Value(shouldApplySidePanelOffset ? -variables.sideBarWidth : 0)); useEffect(() => { setIsSidePanelTransitionEnded(false); Animated.parallel([ @@ -84,6 +85,11 @@ function useSidePanel() { duration: CONST.ANIMATED_TRANSITION, useNativeDriver: true, }), + Animated.timing(modalTranslateX.current, { + toValue: shouldApplySidePanelOffset ? -variables.sideBarWidth : 0, + duration: CONST.ANIMATED_TRANSITION, + useNativeDriver: true, + }), ]).start(() => setIsSidePanelTransitionEnded(true)); // eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps -- sidePanelWidth dependency caused the help panel content to slide in on window resize @@ -115,6 +121,7 @@ function useSidePanel() { shouldHideToolTip, sidePanelOffset, sidePanelTranslateX, + modalTranslateX, openSidePanel, closeSidePanel, }; diff --git a/src/styles/utils/generators/ModalStyleUtils.ts b/src/styles/utils/generators/ModalStyleUtils.ts index f10bd384dd8b..84edaf4e7711 100644 --- a/src/styles/utils/generators/ModalStyleUtils.ts +++ b/src/styles/utils/generators/ModalStyleUtils.ts @@ -269,13 +269,13 @@ const createModalStyleUtils: StyleUtilGenerator = ({the ...modalStyle, ...{ marginLeft: isSmallScreenWidth || (shouldUseReanimatedModal && shouldUseNarrowLayout) ? 0 : windowWidth - variables.sideBarWidth, - width: isSmallScreenWidth || (shouldUseReanimatedModal && shouldUseNarrowLayout) ? '100%' : variables.sideBarWidth, + width: isSmallScreenWidth ? '100%' : variables.sideBarWidth, flexDirection: 'row', justifyContent: 'flex-end', }, }; modalContainerStyle = { - width: isSmallScreenWidth || (shouldUseReanimatedModal && shouldUseNarrowLayout) ? '100%' : variables.sideBarWidth, + width: isSmallScreenWidth ? '100%' : variables.sideBarWidth, height: '100%', overflow: 'hidden', }; From c5095d47aaf919d38413ed987f38cbf407f7900e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Musia=C5=82?= Date: Mon, 14 Jul 2025 17:31:08 +0200 Subject: [PATCH 5/8] bump to fix tests --- src/components/SidePanel/HelpModal/index.android.tsx | 2 -- src/components/SidePanel/HelpModal/index.ios.tsx | 2 -- 2 files changed, 4 deletions(-) diff --git a/src/components/SidePanel/HelpModal/index.android.tsx b/src/components/SidePanel/HelpModal/index.android.tsx index 2284aeaa2da6..6d59f6e7e5cb 100644 --- a/src/components/SidePanel/HelpModal/index.android.tsx +++ b/src/components/SidePanel/HelpModal/index.android.tsx @@ -27,8 +27,6 @@ function Help({shouldHideSidePanel, closeSidePanel}: HelpProps) { type={CONST.MODAL.MODAL_TYPE.RIGHT_DOCKED} shouldHandleNavigationBack shouldUseReanimatedModal - animationIn="slideInRight" - animationOut="slideOutRight" > diff --git a/src/components/SidePanel/HelpModal/index.ios.tsx b/src/components/SidePanel/HelpModal/index.ios.tsx index 8749e539c4ad..052d50d56d0a 100644 --- a/src/components/SidePanel/HelpModal/index.ios.tsx +++ b/src/components/SidePanel/HelpModal/index.ios.tsx @@ -14,8 +14,6 @@ function Help({shouldHideSidePanel, closeSidePanel}: HelpProps) { propagateSwipe swipeDirection={CONST.SWIPE_DIRECTION.RIGHT} shouldUseReanimatedModal - animationIn="slideInRight" - animationOut="slideOutRight" > From b1015ab32d040df22d48cb7f12151a4ed1d8c685 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Musia=C5=82?= Date: Tue, 22 Jul 2025 10:52:25 +0200 Subject: [PATCH 6/8] clean changes after merge --- src/components/Modal/BaseModal.tsx | 2 +- src/hooks/useSidePanel.ts | 1 + src/styles/utils/generators/ModalStyleUtils.ts | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/components/Modal/BaseModal.tsx b/src/components/Modal/BaseModal.tsx index 756c9e85bace..406fa97c1d9f 100644 --- a/src/components/Modal/BaseModal.tsx +++ b/src/components/Modal/BaseModal.tsx @@ -110,7 +110,7 @@ function BaseModal( // eslint-disable-next-line rulesdir/prefer-shouldUseNarrowLayout-instead-of-isSmallScreenWidth const {isSmallScreenWidth, shouldUseNarrowLayout} = useResponsiveLayout(); const {sidePanelOffset} = useSidePanel(); - const sidePanelStyle = !shouldUseReanimatedModal && !shouldUseReanimatedModal && shouldApplySidePanelOffset && !isSmallScreenWidth ? {paddingRight: sidePanelOffset.current} : undefined; + const sidePanelStyle = !shouldUseReanimatedModal && shouldApplySidePanelOffset && !isSmallScreenWidth ? {paddingRight: sidePanelOffset.current} : undefined; const sidePanelReanimatedStyle = shouldUseReanimatedModal && shouldApplySidePanelOffset && !isSmallScreenWidth ? {transform: [{translateX: Animated.multiply(sidePanelOffset.current, -1)}]} : undefined; const keyboardStateContextValue = useKeyboardState(); diff --git a/src/hooks/useSidePanel.ts b/src/hooks/useSidePanel.ts index 2df4b1c5a056..8e56da3bf89b 100644 --- a/src/hooks/useSidePanel.ts +++ b/src/hooks/useSidePanel.ts @@ -71,6 +71,7 @@ function useSidePanel() { const shouldApplySidePanelOffset = isExtraLargeScreenWidth && !shouldHideSidePanel; const sidePanelOffset = useRef(new Animated.Value(shouldApplySidePanelOffset ? variables.sideBarWidth : 0)); const sidePanelTranslateX = useRef(new Animated.Value(shouldHideSidePanel ? sidePanelWidth : 0)); + useEffect(() => { setIsSidePanelTransitionEnded(false); Animated.parallel([ diff --git a/src/styles/utils/generators/ModalStyleUtils.ts b/src/styles/utils/generators/ModalStyleUtils.ts index 041091bd9f77..8704b8705a8c 100644 --- a/src/styles/utils/generators/ModalStyleUtils.ts +++ b/src/styles/utils/generators/ModalStyleUtils.ts @@ -268,7 +268,7 @@ const createModalStyleUtils: StyleUtilGenerator = ({the modalStyle = { ...modalStyle, ...{ - marginLeft: isSmallScreenWidth || (shouldUseReanimatedModal && shouldUseNarrowLayout) ? 0 : windowWidth - variables.sideBarWidth, + marginLeft: isSmallScreenWidth ? 0 : windowWidth - variables.sideBarWidth, width: isSmallScreenWidth ? '100%' : variables.sideBarWidth, flexDirection: 'row', justifyContent: 'flex-end', From bc4f1748a5ebc154f80e48584b15c6a0f458f688 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Musia=C5=82?= Date: Wed, 23 Jul 2025 13:47:52 +0200 Subject: [PATCH 7/8] remove usused props --- src/components/ValidateCodeActionModal/index.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/components/ValidateCodeActionModal/index.tsx b/src/components/ValidateCodeActionModal/index.tsx index a737bbcf1568..17c54f4bc4b7 100644 --- a/src/components/ValidateCodeActionModal/index.tsx +++ b/src/components/ValidateCodeActionModal/index.tsx @@ -68,8 +68,6 @@ function ValidateCodeActionModal({ onClose={hide} onModalHide={onModalHide ?? hide} onBackdropPress={() => Navigation.dismissModal()} - hideModalContentWhileAnimating - useNativeDriver shouldUseModalPaddingStyle={false} animationInTiming={disableAnimation ? 1 : undefined} shouldUseReanimatedModal From 10e869f52fda8cc367ffc08ea39de037f22e27c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Musia=C5=82?= Date: Fri, 25 Jul 2025 14:31:34 +0200 Subject: [PATCH 8/8] update default timing for narrow pane modals on IOS --- src/CONST/index.ts | 2 ++ src/components/Modal/index.ios.tsx | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/src/CONST/index.ts b/src/CONST/index.ts index 32c9f1a1b616..dba54914d81e 100755 --- a/src/CONST/index.ts +++ b/src/CONST/index.ts @@ -1456,6 +1456,8 @@ const CONST = { ANIMATION_TIMING: { DEFAULT_IN: 300, DEFAULT_OUT: 200, + DEFAULT_RIGHT_DOCKED_IOS_IN: 500, + DEFAULT_RIGHT_DOCKED_IOS_OUT: 400, FAB_IN: 350, FAB_OUT: 200, }, diff --git a/src/components/Modal/index.ios.tsx b/src/components/Modal/index.ios.tsx index c04b1c0ec54a..5430bb6026c8 100644 --- a/src/components/Modal/index.ios.tsx +++ b/src/components/Modal/index.ios.tsx @@ -1,13 +1,21 @@ import React from 'react'; +import useResponsiveLayout from '@hooks/useResponsiveLayout'; +import CONST from '@src/CONST'; import BaseModal from './BaseModal'; import type BaseModalProps from './types'; function Modal({children, ...rest}: BaseModalProps) { + const {isInNarrowPaneModal} = useResponsiveLayout(); + const animationInTiming = rest.animationInTiming ?? (isInNarrowPaneModal ? CONST.MODAL.ANIMATION_TIMING.DEFAULT_RIGHT_DOCKED_IOS_IN : undefined); + const animationOutTiming = rest.animationOutTiming ?? (isInNarrowPaneModal ? CONST.MODAL.ANIMATION_TIMING.DEFAULT_RIGHT_DOCKED_IOS_OUT : undefined); + return ( {children}