Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions src/hooks/useOriginalReportID.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import {useMemo} from 'react';
import {getAllNonDeletedTransactions} from '@libs/MoneyRequestReportUtils';
import {getOneTransactionThreadReportID} from '@libs/ReportActionsUtils';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import type {OnyxInputOrEntry, ReportAction} from '@src/types/onyx';
import useNetwork from './useNetwork';
import useOnyx from './useOnyx';
import useTransactionsAndViolationsForReport from './useTransactionsAndViolationsForReport';

function useOriginalReportID(reportID: string | undefined, reportAction: OnyxInputOrEntry<ReportAction>): string | undefined {
const [reportActions] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`, {canBeMissing: true});
const [report] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`, {canBeMissing: true});
const [chatReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${report?.chatReportID}`, {canBeMissing: true});
const {isOffline} = useNetwork();
const {transactions: allReportTransactions} = useTransactionsAndViolationsForReport(reportID);

const visibleTransactionsIDs = useMemo(
() =>
getAllNonDeletedTransactions(allReportTransactions, Object.values(reportActions ?? {}))
.filter((transaction) => isOffline || transaction.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE)
.map((transaction) => transaction.transactionID),
[allReportTransactions, reportActions, isOffline],
);
if (!reportID) {
return undefined;
}
const currentReportAction = reportAction?.reportActionID ? reportActions?.[reportAction.reportActionID] : undefined;

if (Object.keys(currentReportAction ?? {}).length === 0) {
const isThreadReportParentAction = reportAction?.childReportID?.toString() === reportID;
if (isThreadReportParentAction) {
return report?.parentReportID;
}
const transactionThreadReportID = getOneTransactionThreadReportID(report, chatReport, reportActions ?? ([] as ReportAction[]), isOffline, visibleTransactionsIDs);
return transactionThreadReportID ?? reportID;
}
return reportID;
}

export default useOriginalReportID;
46 changes: 24 additions & 22 deletions src/libs/actions/Report.ts
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@
let currentUserAccountID = -1;
let currentUserEmail: string | undefined;

Onyx.connect({

Check warning on line 278 in src/libs/actions/Report.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.SESSION,
callback: (value) => {
// When signed out, val is undefined
Expand All @@ -288,13 +288,13 @@
},
});

Onyx.connect({

Check warning on line 291 in src/libs/actions/Report.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.CONCIERGE_REPORT_ID,
callback: (value) => (conciergeReportID = value),
});

let preferredSkinTone: number = CONST.EMOJI_DEFAULT_SKIN_TONE;
Onyx.connect({

Check warning on line 297 in src/libs/actions/Report.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.PREFERRED_EMOJI_SKIN_TONE,
callback: (value) => {
preferredSkinTone = EmojiUtils.getPreferredSkinToneIndex(value);
Expand All @@ -304,7 +304,7 @@
// map of reportID to all reportActions for that report
const allReportActions: OnyxCollection<ReportActions> = {};

Onyx.connect({

Check warning on line 307 in src/libs/actions/Report.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.REPORT_ACTIONS,
callback: (actions, key) => {
if (!key || !actions) {
Expand All @@ -316,14 +316,14 @@
});

let allTransactionViolations: OnyxCollection<TransactionViolations> = {};
Onyx.connect({

Check warning on line 319 in src/libs/actions/Report.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS,
waitForCollectionCallback: true,
callback: (value) => (allTransactionViolations = value),
});

let allReports: OnyxCollection<Report>;
Onyx.connect({

Check warning on line 326 in src/libs/actions/Report.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.REPORT,
waitForCollectionCallback: true,
callback: (value) => {
Expand All @@ -333,7 +333,7 @@

let isNetworkOffline = false;
let networkStatus: NetworkStatus;
Onyx.connect({

Check warning on line 336 in src/libs/actions/Report.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.NETWORK,
callback: (value) => {
isNetworkOffline = value?.isOffline ?? false;
Expand All @@ -342,7 +342,7 @@
});

let allPersonalDetails: OnyxEntry<PersonalDetailsList> = {};
Onyx.connect({

Check warning on line 345 in src/libs/actions/Report.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.PERSONAL_DETAILS_LIST,
callback: (value) => {
allPersonalDetails = value ?? {};
Expand All @@ -350,7 +350,7 @@
});

let account: OnyxEntry<Account> = {};
Onyx.connect({

Check warning on line 353 in src/libs/actions/Report.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.ACCOUNT,
callback: (value) => {
account = value ?? {};
Expand All @@ -358,7 +358,7 @@
});

const draftNoteMap: OnyxCollection<string> = {};
Onyx.connect({

Check warning on line 361 in src/libs/actions/Report.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.PRIVATE_NOTES_DRAFT,
callback: (value, key) => {
if (!key) {
Expand Down Expand Up @@ -663,8 +663,11 @@
* - Adding one comment
* - Adding one attachment
* - Add both a comment and attachment simultaneously
*
* @param reportID - The report ID where the comment should be added
* @param notifyReportID - The report ID we should notify for new actions. This is usually the same as reportID, except when adding a comment to an expense report with a single transaction thread, in which case we want to notify the parent expense report.
*/
function addActions(reportID: string, text = '', file?: FileObject) {
function addActions(reportID: string, notifyReportID: string, text = '', file?: FileObject) {
let reportCommentText = '';
let reportCommentAction: OptimisticAddCommentReportAction | undefined;
let attachmentAction: OptimisticAddCommentReportAction | undefined;
Expand Down Expand Up @@ -830,23 +833,23 @@
successData,
failureData,
});
notifyNewAction(reportID, lastAction?.actorAccountID, lastAction);
notifyNewAction(notifyReportID, lastAction?.actorAccountID, lastAction);
}

/** Add an attachment and optional comment. */
function addAttachment(reportID: string, file: FileObject, text = '', shouldPlaySound?: boolean) {
function addAttachment(reportID: string, notifyReportID: string, file: FileObject, text = '', shouldPlaySound?: boolean) {
if (shouldPlaySound) {
playSound(SOUNDS.DONE);
}
addActions(reportID, text, file);
addActions(reportID, notifyReportID, text, file);
}

/** Add a single comment to a report */
function addComment(reportID: string, text: string, shouldPlaySound?: boolean) {
function addComment(reportID: string, notifyReportID: string, text: string, shouldPlaySound?: boolean) {
if (shouldPlaySound) {
playSound(SOUNDS.DONE);
}
addActions(reportID, text);
addActions(reportID, notifyReportID, text);
}

function reportActionsExist(reportID: string): boolean {
Expand Down Expand Up @@ -2058,11 +2061,10 @@

/** Saves a new message for a comment. Marks the comment as edited, which will be reflected in the UI. */
function editReportComment(reportID: string | undefined, originalReportAction: OnyxEntry<ReportAction>, textForNewComment: string, videoAttributeCache?: Record<string, string>) {
const originalReportID = getOriginalReportID(reportID, originalReportAction);
if (!originalReportID || !originalReportAction) {
if (!reportID || !originalReportAction) {
return;
}
const report = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${originalReportID}`];
const report = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`];
const canUserPerformWriteAction = canUserPerformWriteActionReportUtils(report);

// Do not autolink if someone explicitly tries to remove a link from message.
Expand All @@ -2089,7 +2091,7 @@

// Delete the comment if it's empty
if (!htmlForNewComment) {
deleteReportComment(originalReportID, originalReportAction);
deleteReportComment(reportID, originalReportAction);
return;
}

Expand Down Expand Up @@ -2120,28 +2122,28 @@
const optimisticData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${originalReportID}`,
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`,
value: optimisticReportActions,
},
];

const lastVisibleAction = ReportActionsUtils.getLastVisibleAction(originalReportID, canUserPerformWriteAction, optimisticReportActions as ReportActions);
const lastVisibleAction = ReportActionsUtils.getLastVisibleAction(reportID, canUserPerformWriteAction, optimisticReportActions as ReportActions);
if (reportActionID === lastVisibleAction?.reportActionID) {
const lastMessageText = formatReportLastMessageText(reportComment);
const optimisticReport = {
lastMessageText,
};
optimisticData.push({
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT}${originalReportID}`,
key: `${ONYXKEYS.COLLECTION.REPORT}${reportID}`,
value: optimisticReport,
});
}

const failureData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${originalReportID}`,
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`,
value: {
[reportActionID]: {
...originalReportAction,
Expand All @@ -2154,7 +2156,7 @@
const successData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${originalReportID}`,
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`,
value: {
[reportActionID]: {
pendingAction: null,
Expand All @@ -2164,7 +2166,7 @@
];

const parameters: UpdateCommentParams = {
reportID: originalReportID,
reportID,
reportComment: htmlForNewComment,
reportActionID,
};
Expand Down Expand Up @@ -5931,19 +5933,19 @@

/**
* Resolves Concierge category options by adding a comment and updating the report action
* @param reportID - The report ID where the comment should be added
* @param actionReportID - The report ID where the report action should be updated (may be different for threads)
* @param reportID - The report ID where the comment should be added and the report action should be updated
* @param notifyReportID - The report ID we should notify for new actions. This is usually the same as reportID, except when adding a comment to an expense report with a single transaction thread, in which case we want to notify the parent expense report.
* @param reportActionID - The specific report action ID to update
* @param selectedCategory - The category selected by the user
*/
function resolveConciergeCategoryOptions(reportID: string | undefined, actionReportID: string | undefined, reportActionID: string | undefined, selectedCategory: string) {
if (!reportID || !actionReportID || !reportActionID) {
function resolveConciergeCategoryOptions(reportID: string | undefined, notifyReportID: string | undefined, reportActionID: string | undefined, selectedCategory: string) {
if (!reportID || !reportActionID) {
return;
}

addComment(reportID, selectedCategory);
addComment(reportID, notifyReportID ?? reportID, selectedCategory);

Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${actionReportID}`, {
Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`, {
[reportActionID]: {
originalMessage: {
selectedCategory,
Expand Down
4 changes: 2 additions & 2 deletions src/pages/Share/ShareDetailsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ function ShareDetailsPage({
}

if (isTextShared) {
addComment(report.reportID, message);
addComment(report.reportID, report.reportID, message);
const routeToNavigate = ROUTES.REPORT_WITH_ID.getRoute(reportOrAccountID);
Navigation.navigate(routeToNavigate, {forceReplace: true});
return;
Expand All @@ -119,7 +119,7 @@ function ShareDetailsPage({
);
}
if (report.reportID) {
addAttachment(report.reportID, file, message);
addAttachment(report.reportID, report.reportID, file, message);
}

const routeToNavigate = ROUTES.REPORT_WITH_ID.getRoute(reportOrAccountID);
Expand Down
4 changes: 4 additions & 0 deletions src/pages/home/ReportScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import {
isCreatedAction,
isDeletedParentAction,
isMoneyRequestAction,
isSentMoneyReportAction,
isWhisperAction,
shouldReportActionBeVisible,
} from '@libs/ReportActionsUtils';
Expand Down Expand Up @@ -316,6 +317,7 @@ function ReportScreen({route, navigation}: ReportScreenProps) {
canBeMissing: true,
});
const combinedReportActions = getCombinedReportActions(reportActions, transactionThreadReportID ?? null, Object.values(transactionThreadReportActions));
const isSentMoneyReport = useMemo(() => reportActions.some((action) => isSentMoneyReportAction(action)), [reportActions]);
const lastReportAction = [...combinedReportActions, parentReportAction].find((action) => canEditReportAction(action) && !isMoneyRequestAction(action));
// wrapping in useMemo to stabilize children re-rendering
const policy = policies?.[`${ONYXKEYS.COLLECTION.POLICY}${report?.policyID}`];
Expand Down Expand Up @@ -888,6 +890,8 @@ function ReportScreen({route, navigation}: ReportScreenProps) {
isComposerFullSize={!!isComposerFullSize}
lastReportAction={lastReportAction}
reportTransactions={reportTransactions}
// If the report is from the 'Send Money' flow, we add the comment to the `iou` report because for these we don't combine reportActions even if there is a single transaction (they always have a single transaction)
transactionThreadReportID={isSentMoneyReport ? undefined : transactionThreadReportID}
/>
) : null}
</View>
Expand Down
Loading
Loading