diff --git a/src/components/LHNOptionsList/OptionRowLHN.tsx b/src/components/LHNOptionsList/OptionRowLHN.tsx index b9bc46f56ae5..b665c305f5cf 100644 --- a/src/components/LHNOptionsList/OptionRowLHN.tsx +++ b/src/components/LHNOptionsList/OptionRowLHN.tsx @@ -51,13 +51,22 @@ function OptionRowLHN({reportID, isFocused = false, onSelectRow = () => {}, opti }, []), ); + const isInFocusMode = viewMode === CONST.OPTION_MODE.COMPACT; + const sidebarInnerRowStyle = StyleSheet.flatten( + isInFocusMode + ? [styles.chatLinkRowPressable, styles.flexGrow1, styles.optionItemAvatarNameWrapper, styles.optionRowCompact, styles.justifyContentCenter] + : [styles.chatLinkRowPressable, styles.flexGrow1, styles.optionItemAvatarNameWrapper, styles.optionRow, styles.justifyContentCenter], + ); + if (!optionItem) { - return null; + // rendering null as a render item causes the FlashList to render all + // its children and consume signficant memory. We can avoid this by + // rendering a placeholder view instead. + return ; } const hasBrickError = optionItem.brickRoadIndicator === CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR; const shouldShowGreenDotIndicator = !hasBrickError && ReportUtils.requiresAttentionFromCurrentUser(optionItem, optionItem.parentReportAction); - const isInFocusMode = viewMode === CONST.OPTION_MODE.COMPACT; const textStyle = isFocused ? styles.sidebarLinkActiveText : styles.sidebarLinkText; const textUnreadStyle = optionItem?.isUnread && optionItem.notificationPreference !== CONST.REPORT.NOTIFICATION_PREFERENCE.MUTE ? [textStyle, styles.sidebarLinkTextBold] : [textStyle]; const displayNameStyle = [styles.optionDisplayName, styles.optionDisplayNameCompact, styles.pre, textUnreadStyle, style]; @@ -66,11 +75,6 @@ function OptionRowLHN({reportID, isFocused = false, onSelectRow = () => {}, opti : [textStyle, styles.optionAlternateText, styles.textLabelSupporting, style]; const contentContainerStyles = isInFocusMode ? [styles.flex1, styles.flexRow, styles.overflowHidden, StyleUtils.getCompactContentContainerStyles()] : [styles.flex1]; - const sidebarInnerRowStyle = StyleSheet.flatten( - isInFocusMode - ? [styles.chatLinkRowPressable, styles.flexGrow1, styles.optionItemAvatarNameWrapper, styles.optionRowCompact, styles.justifyContentCenter] - : [styles.chatLinkRowPressable, styles.flexGrow1, styles.optionItemAvatarNameWrapper, styles.optionRow, styles.justifyContentCenter], - ); const hoveredBackgroundColor = !!styles.sidebarLinkHover && 'backgroundColor' in styles.sidebarLinkHover ? styles.sidebarLinkHover.backgroundColor : theme.sidebar; const focusedBackgroundColor = styles.sidebarLinkActive.backgroundColor; diff --git a/src/libs/Navigation/FreezeWrapper.tsx b/src/libs/Navigation/FreezeWrapper.tsx index bb6ab107373b..23513dd87431 100644 --- a/src/libs/Navigation/FreezeWrapper.tsx +++ b/src/libs/Navigation/FreezeWrapper.tsx @@ -2,6 +2,7 @@ import {useIsFocused, useNavigation, useRoute} from '@react-navigation/native'; import React, {useEffect, useRef, useState} from 'react'; import {Freeze} from 'react-freeze'; import type ChildrenProps from '@src/types/utils/ChildrenProps'; +import shouldSetScreenBlurred from './shouldSetScreenBlurred'; type FreezeWrapperProps = ChildrenProps & { /** Prop to disable freeze */ @@ -24,14 +25,8 @@ function FreezeWrapper({keepVisible = false, children}: FreezeWrapperProps) { useEffect(() => { const unsubscribe = navigation.addListener('state', () => { - // if the screen is more than 1 screen away from the current screen, freeze it, - // we don't want to freeze the screen if it's the previous screen because the freeze placeholder - // would be visible at the beginning of the back animation then - if ((navigation.getState()?.index ?? 0) - (screenIndexRef.current ?? 0) > 1) { - setIsScreenBlurred(true); - } else { - setIsScreenBlurred(false); - } + const navigationIndex = (navigation.getState()?.index ?? 0) - (screenIndexRef.current ?? 0); + setIsScreenBlurred(shouldSetScreenBlurred(navigationIndex)); }); return () => unsubscribe(); }, [isFocused, isScreenBlurred, navigation]); diff --git a/src/libs/Navigation/shouldSetScreenBlurred/index.native.tsx b/src/libs/Navigation/shouldSetScreenBlurred/index.native.tsx new file mode 100644 index 000000000000..4043fddb7372 --- /dev/null +++ b/src/libs/Navigation/shouldSetScreenBlurred/index.native.tsx @@ -0,0 +1,12 @@ +/** + * @param navigationIndex + * + * Decides whether to set screen to blurred state. + * + * If the screen is more than 1 screen away from the current screen, freeze it, + * we don't want to freeze the screen if it's the previous screen because the freeze placeholder + * would be visible at the beginning of the back animation then + */ +const shouldSetScreenBlurred = (navigationIndex: number) => navigationIndex > 1; + +export default shouldSetScreenBlurred; diff --git a/src/libs/Navigation/shouldSetScreenBlurred/index.tsx b/src/libs/Navigation/shouldSetScreenBlurred/index.tsx new file mode 100644 index 000000000000..14b45921bdb2 --- /dev/null +++ b/src/libs/Navigation/shouldSetScreenBlurred/index.tsx @@ -0,0 +1,13 @@ +/** + * @param navigationIndex + * + * Decides whether to set screen to blurred state. + * + * Allow freezing the first screen and more in the stack only on + * web and desktop platforms. The reason is that in the case of + * LHN, we have FlashList rendering in the back while we are on + * Settings screen. + */ +const shouldSetScreenBlurred = (navigationIndex: number) => navigationIndex >= 1; + +export default shouldSetScreenBlurred;