Skip to content
3 changes: 0 additions & 3 deletions src/components/ActionSheetAwareScrollView/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,18 @@
// On all other platforms, the action sheet is implemented using the Animated.ScrollView
import React from 'react';
import Reanimated from 'react-native-reanimated';
import useThemeStyles from '@hooks/useThemeStyles';
import {Actions, ActionSheetAwareScrollViewProvider, useActionSheetAwareScrollViewActions, useActionSheetAwareScrollViewState} from './ActionSheetAwareScrollViewContext';
import type {ActionSheetAwareScrollViewProps, RenderActionSheetAwareScrollViewComponent} from './types';
import useActionSheetAwareScrollViewRef from './useActionSheetAwareScrollViewRef';

function ActionSheetAwareScrollView({children, ref, ...restProps}: ActionSheetAwareScrollViewProps) {
const {onRef} = useActionSheetAwareScrollViewRef(ref);
const styles = useThemeStyles();

return (
<Reanimated.ScrollView
// eslint-disable-next-line react/jsx-props-no-spreading
{...restProps}
ref={onRef}
contentContainerStyle={[restProps.contentContainerStyle, restProps.horizontal ? styles.flexRowReverse : styles.flexColumnReverse, styles.justifyContentEnd]}
>
{children}
</Reanimated.ScrollView>
Expand Down
9 changes: 9 additions & 0 deletions src/components/FlatList/InvertedFlatList/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import React from 'react';
import FlatList from '@components/FlatList/FlatList';
import useFlatListScrollKey from '@components/FlatList/hooks/useFlatListScrollKey';
import useThemeStyles from '@hooks/useThemeStyles';
import getPlatform from '@libs/getPlatform';
import CONST from '@src/CONST';
import CellRendererComponent from './CellRendererComponent';
import shouldRemoveClippedSubviews from './shouldRemoveClippedSubviews';
import type {InvertedFlatListProps} from './types';
Expand Down Expand Up @@ -38,6 +41,11 @@ function InvertedFlatList<T>({
renderItem,
ref,
});
const styles = useThemeStyles();
const platform = getPlatform();
const isWeb = platform === CONST.PLATFORM.WEB;

const contentContainerDirectionStyle = [restProps.horizontal ? styles.flexRowReverse : styles.flexColumnReverse];

return (
<FlatList<T>
Expand All @@ -52,6 +60,7 @@ function InvertedFlatList<T>({
onStartReached={handleStartReached}
CellRendererComponent={CellRendererComponent}
removeClippedSubviews={shouldRemoveClippedSubviews}
contentContainerStyle={[restProps.contentContainerStyle, isWeb ? contentContainerDirectionStyle : undefined]}
/>
);
}
Expand Down
7 changes: 5 additions & 2 deletions src/pages/inbox/report/PureReportActionItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import mapValues from 'lodash/mapValues';
import React, {memo, use, useCallback, useContext, useEffect, useMemo, useRef, useState} from 'react';
import type {GestureResponderEvent, TextInput} from 'react-native';
import {InteractionManager, Keyboard, Platform, View} from 'react-native';
import {InteractionManager, Keyboard, View} from 'react-native';
import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
import type {ValueOf} from 'type-fest';
import type {Emoji} from '@assets/emojis/types';
Expand Down Expand Up @@ -67,6 +67,7 @@
import {getLatestErrorMessageField, isReceiptError} from '@libs/ErrorUtils';
import focusComposerWithDelay from '@libs/focusComposerWithDelay';
import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID';
import getPlatform from '@libs/getPlatform';
import {isReportMessageAttachment} from '@libs/isReportMessageAttachment';
import Navigation from '@libs/Navigation/Navigation';
import {getBankAccountLastFourDigits} from '@libs/PaymentUtils';
Expand Down Expand Up @@ -546,6 +547,8 @@
const {transitionActionSheetState} = ActionSheetAwareScrollView.useActionSheetAwareScrollViewActions();
const {translate, formatPhoneNumber, localeCompare, formatTravelDate, getLocalDateFromDatetime, datetimeToCalendarTime} = useLocalize();
const {showConfirmModal} = useConfirmModal();
const platform = getPlatform();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❌ CONSISTENCY-1 (docs)

The PR introduces getPlatform() and isWeb inside PureReportActionItem to determine the accessibilityRole. This is a platform-specific check within a heavily rendered component. While the original code already had Platform.OS !== CONST.PLATFORM.WEB, replacing it with getPlatform() (a function call on every render) is strictly worse than the static constant Platform.OS for a component rendered per report action.

If keeping the platform check inline, prefer the original Platform.OS which is a static constant with zero per-render cost:

accessibilityRole={Platform.OS !== CONST.PLATFORM.WEB ? CONST.ROLE.BUTTON : undefined}

Alternatively, extract the platform-specific accessibilityRole logic into a platform-specific file or constant.


Please rate this suggestion with 👍 or 👎 to help us improve! Reactions are used to monitor reviewer efficiency.

const isWeb = platform === CONST.PLATFORM.WEB;
const personalDetail = useCurrentUserPersonalDetails();
const {shouldUseNarrowLayout} = useResponsiveLayout();
const reportID = report?.reportID ?? action?.reportID;
Expand Down Expand Up @@ -623,7 +626,7 @@
clearError(transactionID);
}
clearAllRelatedReportActionErrors(reportID, action, originalReportID);
}, [action, isSendingMoney, reportID, clearAllRelatedReportActionErrors, report, chatReport, clearError]);

Check warning on line 629 in src/pages/inbox/report/PureReportActionItem.tsx

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

React Hook useCallback has a missing dependency: 'originalReportID'. Either include it or remove the dependency array

const showDismissReceiptErrorModal = useCallback(async () => {
const result = await showConfirmModal({
Expand Down Expand Up @@ -2056,7 +2059,7 @@
withoutFocusOnSecondaryInteraction
accessibilityLabel={accessibilityLabel}
accessibilityHint={translate('accessibilityHints.chatMessage')}
accessibilityRole={Platform.OS !== CONST.PLATFORM.WEB ? CONST.ROLE.BUTTON : undefined}
accessibilityRole={!isWeb ? CONST.ROLE.BUTTON : undefined}
sentryLabel={CONST.SENTRY_LABEL.REPORT.PURE_REPORT_ACTION_ITEM}
>
<Hoverable
Expand Down
9 changes: 8 additions & 1 deletion src/pages/inbox/report/ReportActionsList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import {isSafari} from '@libs/Browser';
import type {ReasoningEntry} from '@libs/ConciergeReasoningStore';
import DateUtils from '@libs/DateUtils';
import FS from '@libs/Fullstory';
import getPlatform from '@libs/getPlatform';
import durationHighlightItem from '@libs/Navigation/helpers/getDurationHighlightItem';
import isReportTopmostSplitNavigator from '@libs/Navigation/helpers/isReportTopmostSplitNavigator';
import isSearchTopmostFullScreenRoute from '@libs/Navigation/helpers/isSearchTopmostFullScreenRoute';
Expand Down Expand Up @@ -815,6 +816,12 @@ function ReportActionsList({
const hideComposer = !canUserPerformWriteAction(report, isReportArchived);
const shouldShowReportRecipientLocalTime = canShowReportRecipientLocalTime(personalDetailsList, report, currentUserAccountID) && !isComposerFullSize;
const canShowHeader = isOffline || hasHeaderRendered.current;
const platform = getPlatform();
const isWeb = platform === CONST.PLATFORM.WEB;

// Web: reversed via `unshift`, `justifyContentEnd` only needed for normal chat (pushes content down), not when `shouldFocusToTopOnMount`.
// Native: flipped via scaleY(-1), `justifyContentEnd` always needed since "end" aligns to visual top.
const chatContentContainerStyle = [styles.chatContentScrollView, (isWeb ? !shouldFocusToTopOnMount : shouldFocusToTopOnMount) ? styles.justifyContentEnd : undefined];

const onLayoutInner = useCallback(
(event: LayoutChangeEvent) => {
Expand Down Expand Up @@ -918,7 +925,7 @@ function ReportActionsList({
data={sortedVisibleReportActions}
renderItem={renderItem}
renderScrollComponent={renderActionSheetAwareScrollView}
contentContainerStyle={[styles.chatContentScrollView, shouldFocusToTopOnMount ? styles.justifyContentEnd : undefined]}
contentContainerStyle={chatContentContainerStyle}
shouldHideContent={shouldScrollToEndAfterLayout}
shouldDisableVisibleContentPosition={shouldScrollToEndAfterLayout}
showsVerticalScrollIndicator={!shouldScrollToEndAfterLayout}
Expand Down
Loading