From b35d9b1773112e00106df8882196800d4ebd8dab Mon Sep 17 00:00:00 2001 From: bartlomiej obudzinski Date: Thu, 7 May 2026 14:59:11 +0200 Subject: [PATCH 1/3] refactor: extract OptionRow.Status leaf --- .../OptionRowLHN/OptionRow/Status.tsx | 47 +++++++++++++++++++ .../OptionRowLHN/OptionRowLHNCore.tsx | 28 +++-------- 2 files changed, 53 insertions(+), 22 deletions(-) create mode 100644 src/components/LHNOptionsList/OptionRowLHN/OptionRow/Status.tsx diff --git a/src/components/LHNOptionsList/OptionRowLHN/OptionRow/Status.tsx b/src/components/LHNOptionsList/OptionRowLHN/OptionRow/Status.tsx new file mode 100644 index 000000000000..0aff345fd898 --- /dev/null +++ b/src/components/LHNOptionsList/OptionRowLHN/OptionRow/Status.tsx @@ -0,0 +1,47 @@ +import React from 'react'; +import Text from '@components/Text'; +import Tooltip from '@components/Tooltip'; +import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; +import useLocalize from '@hooks/useLocalize'; +import useThemeStyles from '@hooks/useThemeStyles'; +import DateUtils from '@libs/DateUtils'; +import type {OptionData} from '@libs/ReportUtils'; +import {isOneOnOneChat} from '@libs/ReportUtils'; +import CONST from '@src/CONST'; +import type {Report} from '@src/types/onyx'; +import {isEmptyObject} from '@src/types/utils/EmptyObject'; + +type StatusProps = { + optionItem: OptionData; + report?: Report; +}; + +function Status({optionItem, report}: StatusProps) { + const styles = useThemeStyles(); + const {translate} = useLocalize(); + const currentUserPersonalDetails = useCurrentUserPersonalDetails(); + + const emojiCode = optionItem.status?.emojiCode ?? ''; + if (!emojiCode || !isOneOnOneChat(!isEmptyObject(report) ? report : undefined)) { + return null; + } + + const statusText = optionItem.status?.text ?? ''; + const statusClearAfterDate = optionItem.status?.clearAfter ?? ''; + const currentSelectedTimezone = currentUserPersonalDetails?.timezone?.selected ?? CONST.DEFAULT_TIME_ZONE.selected; + const formattedDate = DateUtils.getStatusUntilDate(translate, statusClearAfterDate, optionItem?.timezone?.selected ?? CONST.DEFAULT_TIME_ZONE.selected, currentSelectedTimezone); + const statusContent = formattedDate ? `${statusText ? `${statusText} ` : ''}(${formattedDate})` : statusText; + + return ( + + {emojiCode} + + ); +} + +Status.displayName = 'OptionRow.Status'; + +export default Status; diff --git a/src/components/LHNOptionsList/OptionRowLHN/OptionRowLHNCore.tsx b/src/components/LHNOptionsList/OptionRowLHN/OptionRowLHNCore.tsx index 879ef0a54ec9..bf70079fd898 100644 --- a/src/components/LHNOptionsList/OptionRowLHN/OptionRowLHNCore.tsx +++ b/src/components/LHNOptionsList/OptionRowLHN/OptionRowLHNCore.tsx @@ -6,10 +6,8 @@ import Icon from '@components/Icon'; import {useLHNTooltipContext} from '@components/LHNOptionsList/LHNTooltipContext'; import type {OptionRowLHNProps} from '@components/LHNOptionsList/types'; import Text from '@components/Text'; -import Tooltip from '@components/Tooltip'; import getContextMenuAccessibilityHint from '@components/utils/getContextMenuAccessibilityHint'; import getContextMenuAccessibilityProps from '@components/utils/getContextMenuAccessibilityProps'; -import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; import useEnvironment from '@hooks/useEnvironment'; import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset'; import useLocalize from '@hooks/useLocalize'; @@ -17,15 +15,14 @@ import useOnyx from '@hooks/useOnyx'; import useStyleUtils from '@hooks/useStyleUtils'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; -import DateUtils from '@libs/DateUtils'; import FS from '@libs/Fullstory'; import {shouldUseBoldText} from '@libs/OptionsListUtils'; -import {isChatUsedForOnboarding as isChatUsedForOnboardingReportUtils, isGroupChat, isOneOnOneChat, isSystemChat} from '@libs/ReportUtils'; +import {isChatUsedForOnboarding as isChatUsedForOnboardingReportUtils, isGroupChat, isSystemChat} from '@libs/ReportUtils'; import FreeTrial from '@pages/settings/Subscription/FreeTrial'; import variables from '@styles/variables'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; -import {isEmptyObject} from '@src/types/utils/EmptyObject'; +import Status from './OptionRow/Status'; import OptionRowAlternateText from './OptionRowAlternateText'; import OptionRowAvatar from './OptionRowAvatar'; import OptionRowErrorBadge from './OptionRowErrorBadge'; @@ -57,7 +54,6 @@ function OptionRowLHN({ const isChatUsedForOnboarding = isChatUsedForOnboardingReportUtils(report, onboarding, conciergeReportID, onboardingPurpose); const {translate} = useLocalize(); - const currentUserPersonalDetails = useCurrentUserPersonalDetails(); const isInFocusMode = viewMode === CONST.OPTION_MODE.COMPACT; const sidebarInnerRowStyle = StyleSheet.flatten( isInFocusMode @@ -83,14 +79,6 @@ function OptionRowLHN({ const hoveredBackgroundColor = !!styles.sidebarLinkHover && 'backgroundColor' in styles.sidebarLinkHover ? styles.sidebarLinkHover.backgroundColor : theme.sidebar; const focusedBackgroundColor = styles.sidebarLinkActive.backgroundColor; - const emojiCode = optionItem.status?.emojiCode ?? ''; - const statusText = optionItem.status?.text ?? ''; - const statusClearAfterDate = optionItem.status?.clearAfter ?? ''; - const currentSelectedTimezone = currentUserPersonalDetails?.timezone?.selected ?? CONST.DEFAULT_TIME_ZONE.selected; - const formattedDate = DateUtils.getStatusUntilDate(translate, statusClearAfterDate, optionItem?.timezone?.selected ?? CONST.DEFAULT_TIME_ZONE.selected, currentSelectedTimezone); - const statusContent = formattedDate ? `${statusText ? `${statusText} ` : ''}(${formattedDate})` : statusText; - const isStatusVisible = !!emojiCode && isOneOnOneChat(!isEmptyObject(report) ? report : undefined); - const subscriptAvatarBorderColor = isOptionFocused ? focusedBackgroundColor : theme.sidebar; // This is used to ensure that we display the text exactly as the user entered it when displaying LHN title, instead of parsing their text to HTML. @@ -168,14 +156,10 @@ function OptionRowLHN({ testID={testID} /> {isChatUsedForOnboarding && } - {isStatusVisible && ( - - {emojiCode} - - )} + Date: Tue, 12 May 2026 09:05:19 +0200 Subject: [PATCH 2/3] chore: remove unused Text import --- src/components/LHNOptionsList/OptionRowLHN/OptionRowLHNCore.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/LHNOptionsList/OptionRowLHN/OptionRowLHNCore.tsx b/src/components/LHNOptionsList/OptionRowLHN/OptionRowLHNCore.tsx index beb9c0a1fc8b..64653675d5a6 100644 --- a/src/components/LHNOptionsList/OptionRowLHN/OptionRowLHNCore.tsx +++ b/src/components/LHNOptionsList/OptionRowLHN/OptionRowLHNCore.tsx @@ -4,7 +4,6 @@ import {StyleSheet, View} from 'react-native'; import Icon from '@components/Icon'; import {useLHNTooltipContext} from '@components/LHNOptionsList/LHNTooltipContext'; import type {OptionRowLHNProps} from '@components/LHNOptionsList/types'; -import Text from '@components/Text'; import getContextMenuAccessibilityHint from '@components/utils/getContextMenuAccessibilityHint'; import getContextMenuAccessibilityProps from '@components/utils/getContextMenuAccessibilityProps'; import useEnvironment from '@hooks/useEnvironment'; From 9a38623aa7d749aa03a1fd8052c65eb2789beb4f Mon Sep 17 00:00:00 2001 From: bartlomiej obudzinski Date: Tue, 12 May 2026 10:15:23 +0200 Subject: [PATCH 3/3] docs: add JSDoc to StatusProps --- src/components/LHNOptionsList/OptionRowLHN/OptionRow/Status.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/LHNOptionsList/OptionRowLHN/OptionRow/Status.tsx b/src/components/LHNOptionsList/OptionRowLHN/OptionRow/Status.tsx index 326253a97987..09bfb20b7b04 100644 --- a/src/components/LHNOptionsList/OptionRowLHN/OptionRow/Status.tsx +++ b/src/components/LHNOptionsList/OptionRowLHN/OptionRow/Status.tsx @@ -9,6 +9,7 @@ import type {OptionData} from '@libs/ReportUtils'; import CONST from '@src/CONST'; type StatusProps = { + /** The option data for the report row. Status is only shown for 1:1 chats whose participant has set a status emoji. */ optionItem: OptionData; };