Skip to content

Commit baa61f5

Browse files
authored
Merge pull request #87714 from truph01/fix/66416-part-3
Remove Onyx.connect() for the key: ONYXKEYS.COLLECTION.REPORT in src/libs/ReportUtils.ts (part 3)
2 parents 474ade3 + 3296e50 commit baa61f5

24 files changed

Lines changed: 163 additions & 65 deletions

src/components/Attachments/AttachmentView/index.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
2020
import useLocalize from '@hooks/useLocalize';
2121
import useNetwork from '@hooks/useNetwork';
2222
import useOnyx from '@hooks/useOnyx';
23+
import useReportOrReportDraft from '@hooks/useReportOrReportDraft';
2324
import useSafeAreaPaddings from '@hooks/useSafeAreaPaddings';
2425
import useStyleUtils from '@hooks/useStyleUtils';
2526
import useTheme from '@hooks/useTheme';
@@ -144,6 +145,7 @@ function AttachmentView({
144145
const encryptedAuthToken = session?.encryptedAuthToken ?? '';
145146
const {translate} = useLocalize();
146147
const {updateCurrentURLAndReportID} = usePlaybackActionsContext();
148+
const report = useReportOrReportDraft(reportID);
147149

148150
const actions = useAttachmentCarouselPagerActions();
149151
const {onAttachmentError, onTap} = actions ?? {};
@@ -163,8 +165,8 @@ function AttachmentView({
163165
return;
164166
}
165167
const videoSource = isVideo && typeof source === 'string' ? source : undefined;
166-
updateCurrentURLAndReportID(videoSource, reportID);
167-
}, [file, isFocused, isInFocusedModal, isUsedInAttachmentModal, isVideo, reportID, source, updateCurrentURLAndReportID]);
168+
updateCurrentURLAndReportID(videoSource, report, reportID);
169+
}, [file, isFocused, isInFocusedModal, isUsedInAttachmentModal, isVideo, reportID, source, updateCurrentURLAndReportID, report]);
168170

169171
const [imageError, setImageError] = useState(false);
170172

src/components/Search/SearchAutocompleteList.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -432,7 +432,7 @@ function SearchAutocompleteList({
432432
}
433433

434434
const nextStyledRecentReports = recentReportsOptions.map((option) => {
435-
const report = getReportOrDraftReport(option.reportID);
435+
const report = getReportOrDraftReport(option.reportID, undefined, undefined, undefined, reports?.[`${ONYXKEYS.COLLECTION.REPORT}${option.reportID}`]);
436436
const reportAction = getReportAction(report?.parentReportID, report?.parentReportActionID);
437437
const shouldParserToHTML = !!reportAction && reportAction.actionName !== CONST.REPORT.ACTIONS.TYPE.ADD_COMMENT;
438438
const shouldParseAlternateText = report?.lastActionType !== CONST.REPORT.ACTIONS.TYPE.ADD_COMMENT;
@@ -510,6 +510,7 @@ function SearchAutocompleteList({
510510
translate,
511511
isLoadingOptions,
512512
isRecentSearchesDataLoaded,
513+
reports,
513514
]);
514515

515516
const sectionItemText = sections?.at(1)?.data?.[0]?.text ?? '';

src/components/Search/SearchList/ListItem/TransactionGroupListExpanded.tsx

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
import React from 'react';
1+
import React, {useMemo} from 'react';
22
import {View} from 'react-native';
3+
import type {OnyxCollection} from 'react-native-onyx';
34
import ActivityIndicator from '@components/ActivityIndicator';
45
import Button from '@components/Button';
56
import OfflineWithFeedback from '@components/OfflineWithFeedback';
@@ -31,6 +32,7 @@ import CONST from '@src/CONST';
3132
import ONYXKEYS from '@src/ONYXKEYS';
3233
import ROUTES from '@src/ROUTES';
3334
import {columnsSelector} from '@src/selectors/AdvancedSearchFiltersForm';
35+
import type * as OnyxTypes from '@src/types/onyx';
3436
import type {TransactionGroupListExpandedProps, TransactionListItemType} from './types';
3537

3638
function TransactionGroupListExpanded<TItem extends ListItem>({
@@ -73,6 +75,31 @@ function TransactionGroupListExpanded<TItem extends ListItem>({
7375

7476
const visibleTransactions = isExpenseReportType ? transactions.slice(0, transactionsVisibleLimit) : transactions;
7577

78+
const neededReportIDs = useMemo(() => {
79+
const ids = new Set<string>();
80+
for (const transaction of visibleTransactions) {
81+
if (transaction.reportID) {
82+
ids.add(`${ONYXKEYS.COLLECTION.REPORT}${transaction.reportID}`);
83+
}
84+
if (transaction.reportAction?.childReportID) {
85+
ids.add(`${ONYXKEYS.COLLECTION.REPORT}${transaction.reportAction.childReportID}`);
86+
}
87+
}
88+
return ids;
89+
}, [visibleTransactions]);
90+
91+
const [allReports] = useOnyx(ONYXKEYS.COLLECTION.REPORT, {
92+
selector: (reports) => {
93+
const result: OnyxCollection<OnyxTypes.Report> = {};
94+
for (const key of Object.keys(reports ?? {})) {
95+
if (neededReportIDs.has(key)) {
96+
result[key] = reports?.[key];
97+
}
98+
}
99+
return result;
100+
},
101+
});
102+
76103
const isLastTransaction = (index: number) => {
77104
return index === visibleTransactions.length - 1;
78105
};
@@ -106,8 +133,14 @@ function TransactionGroupListExpanded<TItem extends ListItem>({
106133
const selectRow = onSelectRow as (item: TItem, transactionPreviewData?: TransactionPreviewData) => void;
107134
const getTransactionPreviewData = (transactionItem: TransactionListItemType): TransactionPreviewData => {
108135
const parentReportAction = getReportAction(transactionItem?.reportID, transactionItem?.reportAction?.reportActionID);
109-
const parentReport = getReportOrDraftReport(transactionItem?.reportID);
110-
const transactionThreadReport = getReportOrDraftReport(transactionItem?.reportAction?.childReportID);
136+
const parentReport = getReportOrDraftReport(transactionItem?.reportID, undefined, undefined, undefined, allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${transactionItem?.reportID}`]);
137+
const transactionThreadReport = getReportOrDraftReport(
138+
transactionItem?.reportAction?.childReportID,
139+
undefined,
140+
undefined,
141+
undefined,
142+
allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${transactionItem?.reportAction?.childReportID}`],
143+
);
111144
const transaction = allTransactions?.[`${ONYXKEYS.COLLECTION.TRANSACTION}${getNonEmptyStringOnyxID(transactionItem?.transactionID)}`];
112145

113146
return {

src/components/Search/SearchRouter/SearchRouter.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import useKeyboardShortcut from '@hooks/useKeyboardShortcut';
2222
import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
2323
import useLocalize from '@hooks/useLocalize';
2424
import useOnyx from '@hooks/useOnyx';
25+
import useReportOrReportDraft from '@hooks/useReportOrReportDraft';
2526
import useResponsiveLayout from '@hooks/useResponsiveLayout';
2627
import useRootNavigationState from '@hooks/useRootNavigationState';
2728
import useThemeStyles from '@hooks/useThemeStyles';
@@ -31,7 +32,7 @@ import type {SearchOption} from '@libs/OptionsListUtils';
3132
import {createOptionFromReport} from '@libs/OptionsListUtils';
3233
import Parser from '@libs/Parser';
3334
import {getReportAction} from '@libs/ReportActionsUtils';
34-
import {getReportOrDraftReport, isHiddenForCurrentUser} from '@libs/ReportUtils';
35+
import {isHiddenForCurrentUser} from '@libs/ReportUtils';
3536
import type {OptionData} from '@libs/ReportUtils';
3637
import {getAutocompleteQueryWithComma, getTrimmedUserSearchQueryPreservingComma} from '@libs/SearchAutocompleteUtils';
3738
import {getQueryWithUpdatedValues, sanitizeSearchValue} from '@libs/SearchQueryUtils';
@@ -86,7 +87,7 @@ function SearchRouter({onRouterClose, shouldHideInputCaret, isSearchRouterDispla
8687

8788
const {contextualReportID, isSearchRouterScreen} = useRootNavigationState(getContextualReportData);
8889

89-
const [contextualReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${contextualReportID}`);
90+
const contextualReport = useReportOrReportDraft(contextualReportID);
9091
const [contextualReportNVP] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${contextualReportID}`, {
9192
selector: privateIsArchivedSelector,
9293
});
@@ -123,7 +124,7 @@ function SearchRouter({onRouterClose, shouldHideInputCaret, isSearchRouterDispla
123124
return undefined;
124125
}
125126
let reportForContextualSearch = recentReports.find((option) => option.reportID === contextualReportID);
126-
const reportForContextualSearchReport = getReportOrDraftReport(reportForContextualSearch?.reportID);
127+
const reportForContextualSearchReport = reportForContextualSearch ? contextualReport : undefined;
127128
const reportAction = getReportAction(reportForContextualSearchReport?.parentReportID, reportForContextualSearchReport?.parentReportActionID);
128129
const shouldParserToHTML = reportAction?.actionName !== CONST.REPORT.ACTIONS.TYPE.ADD_COMMENT;
129130
if (!reportForContextualSearch) {

src/components/VideoPlayer/BaseVideoPlayer.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {useVideoPopoverMenuActions} from '@components/VideoPlayerContexts/VideoP
1919
import {useVolumeActions, useVolumeState} from '@components/VideoPlayerContexts/VolumeContext';
2020
import VideoPopoverMenu from '@components/VideoPopoverMenu';
2121
import useNetwork from '@hooks/useNetwork';
22+
import useReportOrReportDraft from '@hooks/useReportOrReportDraft';
2223
import useThemeStyles from '@hooks/useThemeStyles';
2324
import addEncryptedAuthTokenToURL from '@libs/addEncryptedAuthTokenToURL';
2425
import {isSafari} from '@libs/Browser';
@@ -57,6 +58,7 @@ function BaseVideoPlayer({
5758
const {pauseVideo, playVideo, replayVideo, shareVideoPlayerElements, updateCurrentURLAndReportID, setCurrentlyPlayingURL, updatePlayerStatus, requestDonorReRegistration} =
5859
usePlaybackActionsContext();
5960
const {isFullScreenRef} = useFullScreenState();
61+
const report = useReportOrReportDraft(reportID);
6062

6163
const isOffline = useNetwork().isOffline;
6264
const [isVideoOffline, setIsVideoOffline] = useState(false);
@@ -172,7 +174,7 @@ function BaseVideoPlayer({
172174

173175
const togglePlayCurrentVideo = useCallback(() => {
174176
if (!isCurrentlyURLSet) {
175-
updateCurrentURLAndReportID(url, reportID);
177+
updateCurrentURLAndReportID(url, report, reportID);
176178
return;
177179
}
178180

@@ -194,7 +196,7 @@ function BaseVideoPlayer({
194196

195197
allowSharedAutoPlayRef.current = true;
196198
playVideo();
197-
}, [isCurrentlyURLSet, isLoading, isEnded, currentTime, duration, playVideo, updateCurrentURLAndReportID, url, reportID, pauseVideo, replayVideo]);
199+
}, [isCurrentlyURLSet, isLoading, isEnded, currentTime, duration, playVideo, updateCurrentURLAndReportID, url, report, reportID, pauseVideo, replayVideo]);
198200

199201
const hideControl = useCallback(() => {
200202
if (isEnded || isSeeking) {
@@ -498,8 +500,8 @@ function BaseVideoPlayer({
498500
if (!shouldPlay) {
499501
return;
500502
}
501-
updateCurrentURLAndReportID(url, reportID);
502-
}, [reportID, shouldPlay, updateCurrentURLAndReportID, url]);
503+
updateCurrentURLAndReportID(url, report, reportID);
504+
}, [report, reportID, shouldPlay, updateCurrentURLAndReportID, url]);
503505

504506
// ensure that video loads after page refresh on iOS Safari
505507
useEffect(() => {

src/components/VideoPlayer/VideoPlayerControls/index.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {convertSecondsToTime} from '@components/VideoPlayer/utils';
1111
import {usePlaybackActionsContext} from '@components/VideoPlayerContexts/PlaybackContext';
1212
import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
1313
import useLocalize from '@hooks/useLocalize';
14+
import useReportOrReportDraft from '@hooks/useReportOrReportDraft';
1415
import useThemeStyles from '@hooks/useThemeStyles';
1516
import CONST from '@src/CONST';
1617
import ProgressBar from './ProgressBar';
@@ -78,6 +79,7 @@ function VideoPlayerControls({
7879
const styles = useThemeStyles();
7980
const {translate} = useLocalize();
8081
const {updateCurrentURLAndReportID} = usePlaybackActionsContext();
82+
const report = useReportOrReportDraft(reportID);
8183
const [shouldShowTime, setShouldShowTime] = useState(false);
8284
const iconSpacing = small ? styles.mr3 : styles.mr4;
8385

@@ -86,9 +88,9 @@ function VideoPlayerControls({
8688
};
8789

8890
const enterFullScreenMode = useCallback(() => {
89-
updateCurrentURLAndReportID(url, reportID);
91+
updateCurrentURLAndReportID(url, report, reportID);
9092
videoViewRef.current?.enterFullscreen();
91-
}, [reportID, updateCurrentURLAndReportID, url, videoViewRef]);
93+
}, [report, reportID, updateCurrentURLAndReportID, url, videoViewRef]);
9294

9395
const seekPosition = useCallback(
9496
(newPosition: number) => {

src/components/VideoPlayerContexts/PlaybackContext/index.tsx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type {VideoPlayer, VideoPlayerStatus, VideoView} from 'expo-video';
22
import React, {useCallback, useContext, useEffect, useRef, useState} from 'react';
33
import type {View} from 'react-native';
4-
import {getReportOrDraftReport, isChatThread} from '@libs/ReportUtils';
4+
import {isChatThread} from '@libs/ReportUtils';
55
import Navigation from '@navigation/Navigation';
66
import type ChildrenProps from '@src/types/utils/ChildrenProps';
77
import type {ProtectedCurrentRouteReportID} from './playbackContextReportIDUtils';
@@ -21,7 +21,6 @@ function PlaybackContextProvider({children}: ChildrenProps) {
2121
const [shareVersion, setShareVersion] = useState(0);
2222
const mountedVideoPlayersRef = useRef<string[]>([]);
2323
const playerStatus = useRef<VideoPlayerStatus>('loading');
24-
2524
const resetContextProperties = () => {
2625
setSharedElement(null);
2726
setOriginalParent(null);
@@ -33,7 +32,7 @@ function PlaybackContextProvider({children}: ChildrenProps) {
3332
const video = usePlaybackContextVideoRefs(resetContextProperties);
3433

3534
const updateCurrentURLAndReportID: PlaybackActionsContextValues['updateCurrentURLAndReportID'] = useCallback(
36-
(url, reportID) => {
35+
(url, report, reportID) => {
3736
if (!reportID) {
3837
return;
3938
}
@@ -50,7 +49,6 @@ function PlaybackContextProvider({children}: ChildrenProps) {
5049
return;
5150
}
5251

53-
const report = getReportOrDraftReport(reportID);
5452
const isReportAChatThread = isChatThread(report);
5553
let reportIDtoSet;
5654
if (isReportAChatThread) {

src/components/VideoPlayerContexts/PlaybackContext/types.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import type {VideoPlayer, VideoPlayerStatus, VideoView} from 'expo-video';
22
import type {RefObject} from 'react';
33
import type {View} from 'react-native';
4+
import type {OnyxEntry} from 'react-native-onyx';
5+
import type {Report} from '@src/types/onyx';
46

57
/**
68
* Callback type for reporting the current playback status.
@@ -83,11 +85,14 @@ type PlaybackStateContextValues = {
8385
*/
8486
type PlaybackActionsContextValues = {
8587
/**
86-
* Updates the currently tracked video URL and associated report ID.
88+
* Updates the currently tracked video URL and associated report.
89+
* `report` and `reportID` are separate params because `report` comes from Onyx and may be undefined or lack a
90+
* `reportID` field, while `reportID` is always available from route params or component props.
8791
* @param url The new video URL.
88-
* @param reportID The new report ID.
92+
* @param report The Onyx report object (may be undefined).
93+
* @param reportID The report ID from route params or props.
8994
*/
90-
updateCurrentURLAndReportID: (url: string | undefined, reportID: string | undefined) => void;
95+
updateCurrentURLAndReportID: (url: string | undefined, report: OnyxEntry<Report>, reportID: string | undefined) => void;
9196

9297
/**
9398
* Updates shared video player elements across different parts of the UI.

src/components/VideoPlayerPreview/index.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {usePlaybackActionsContext, usePlaybackStateContext} from '@components/Vi
1010
import useCheckIfRouteHasRemainedUnchanged from '@hooks/useCheckIfRouteHasRemainedUnchanged';
1111
import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
1212
import useLocalize from '@hooks/useLocalize';
13+
import useReportOrReportDraft from '@hooks/useReportOrReportDraft';
1314
import useResponsiveLayout from '@hooks/useResponsiveLayout';
1415
import useThemeStyles from '@hooks/useThemeStyles';
1516
import useThumbnailDimensions from '@hooks/useThumbnailDimensions';
@@ -54,6 +55,7 @@ function VideoPlayerPreview({videoUrl, thumbnailUrl, reportID, fileName, videoDi
5455
const {translate} = useLocalize();
5556
const {currentlyPlayingURL, currentRouteReportID} = usePlaybackStateContext();
5657
const {updateCurrentURLAndReportID} = usePlaybackActionsContext();
58+
const report = useReportOrReportDraft(reportID);
5759

5860
/* This needs to be isSmallScreenWidth because we want to be able to play video in chat (not in attachment modal) when preview is inside an RHP */
5961
// eslint-disable-next-line rulesdir/prefer-shouldUseNarrowLayout-instead-of-isSmallScreenWidth
@@ -103,7 +105,7 @@ function VideoPlayerPreview({videoUrl, thumbnailUrl, reportID, fileName, videoDi
103105
};
104106

105107
const handleOnPress = () => {
106-
updateCurrentURLAndReportID(videoUrl, reportID);
108+
updateCurrentURLAndReportID(videoUrl, report, reportID);
107109
if (isSmallScreenWidth) {
108110
onShowModalPress();
109111
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID';
2+
import ONYXKEYS from '@src/ONYXKEYS';
3+
import useOnyx from './useOnyx';
4+
5+
/**
6+
* Subscribes to a single report by ID, falling back to the report draft if the
7+
* non-draft entry doesn't exist. This replaces the common pattern of calling
8+
* `getReportOrDraftReport(reportID, undefined, undefined, undefined, report)`
9+
* while avoiding a full `COLLECTION.REPORT` subscription.
10+
*/
11+
function useReportOrReportDraft(reportID: string | undefined) {
12+
const onyxID = getNonEmptyStringOnyxID(reportID);
13+
const [report] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${onyxID}`);
14+
const [reportDraft] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_DRAFT}${onyxID}`);
15+
return report ?? reportDraft;
16+
}
17+
18+
export default useReportOrReportDraft;

0 commit comments

Comments
 (0)