Skip to content

Commit af66079

Browse files
authored
Merge pull request Expensify#67599 from Expensify/chuckdries/sync-drafts-2
Sync drafts between devices 2
2 parents 4ba9019 + 56929e8 commit af66079

34 files changed

Lines changed: 259 additions & 204 deletions

src/ONYXKEYS.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -565,6 +565,9 @@ const ONYXKEYS = {
565565
NVP_LAST_ECASH_ANDROID_LOGIN: 'nvp_lastECashAndroidLogin',
566566
NVP_LAST_ANDROID_LOGIN: 'nvp_lastAndroidLogin',
567567

568+
/** Draft report comments */
569+
NVP_DRAFT_REPORT_COMMENTS: 'nvp_draftReportComments',
570+
568571
/** Collection Keys */
569572
COLLECTION: {
570573
DOWNLOAD: 'download_',
@@ -598,7 +601,8 @@ const ONYXKEYS = {
598601
REPORT_ACTIONS_DRAFTS: 'reportActionsDrafts_',
599602
REPORT_ACTIONS_PAGES: 'reportActionsPages_',
600603
REPORT_ACTIONS_REACTIONS: 'reportActionsReactions_',
601-
REPORT_DRAFT_COMMENT: 'reportDraftComment_',
604+
/** @deprecated */
605+
REPORT_DRAFT_COMMENT: 'reportDraftComment_', // eslint-disable-line deprecation/deprecation
602606
REPORT_IS_COMPOSER_FULL_SIZE: 'reportIsComposerFullSize_',
603607
REPORT_USER_IS_TYPING: 'reportUserIsTyping_',
604608
REPORT_USER_IS_LEAVING_ROOM: 'reportUserIsLeavingRoom_',
@@ -1001,6 +1005,7 @@ type OnyxCollectionValuesMapping = {
10011005
[ONYXKEYS.COLLECTION.REPORT_ACTIONS_DRAFTS]: OnyxTypes.ReportActionsDrafts;
10021006
[ONYXKEYS.COLLECTION.REPORT_ACTIONS_PAGES]: OnyxTypes.Pages;
10031007
[ONYXKEYS.COLLECTION.REPORT_ACTIONS_REACTIONS]: OnyxTypes.ReportActionReactions;
1008+
// eslint-disable-next-line deprecation/deprecation
10041009
[ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT]: string;
10051010
[ONYXKEYS.COLLECTION.REPORT_IS_COMPOSER_FULL_SIZE]: boolean;
10061011
[ONYXKEYS.COLLECTION.REPORT_USER_IS_TYPING]: OnyxTypes.ReportUserIsTyping;
@@ -1226,6 +1231,7 @@ type OnyxValuesMapping = {
12261231
[ONYXKEYS.ONBOARDING_USER_REPORTED_INTEGRATION]: OnboardingAccounting;
12271232
[ONYXKEYS.HYBRID_APP]: OnyxTypes.HybridApp;
12281233
[ONYXKEYS.NVP_CSV_EXPORT_LAYOUTS]: Record<string, OnyxTypes.ExportTemplate>;
1234+
[ONYXKEYS.NVP_DRAFT_REPORT_COMMENTS]: OnyxTypes.DraftReportComments;
12291235
};
12301236

12311237
type OnyxDerivedValuesMapping = {

src/components/LHNOptionsList/LHNOptionsList.tsx

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ import useRootNavigationState from '@hooks/useRootNavigationState';
1919
import useScrollEventEmitter from '@hooks/useScrollEventEmitter';
2020
import useTheme from '@hooks/useTheme';
2121
import useThemeStyles from '@hooks/useThemeStyles';
22-
import {isValidDraftComment} from '@libs/DraftCommentUtils';
2322
import getPlatform from '@libs/getPlatform';
2423
import Log from '@libs/Log';
2524
import {getIOUReportIDOfLastAction, getLastMessageTextForReport} from '@libs/OptionsListUtils';
@@ -53,7 +52,7 @@ function LHNOptionsList({style, contentContainerStyles, data, onSelectRow, optio
5352
const [policy] = useOnyx(ONYXKEYS.COLLECTION.POLICY, {canBeMissing: false});
5453
const [personalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST, {canBeMissing: true});
5554
const [transactions] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION, {canBeMissing: false});
56-
const [draftComments] = useOnyx(ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT, {canBeMissing: false});
55+
const [draftComments] = useOnyx(ONYXKEYS.NVP_DRAFT_REPORT_COMMENTS, {canBeMissing: true});
5756
const [transactionViolations] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS, {canBeMissing: false});
5857
const [dismissedProductTraining, dismissedProductTrainingMetadata] = useOnyx(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING, {canBeMissing: true});
5958
const [activePolicyID] = useOnyx(ONYXKEYS.NVP_ACTIVE_POLICY_ID, {canBeMissing: true});
@@ -189,7 +188,7 @@ function LHNOptionsList({style, contentContainerStyles, data, onSelectRow, optio
189188
? (getOriginalMessage(itemParentReportAction)?.IOUTransactionID ?? CONST.DEFAULT_NUMBER_ID)
190189
: CONST.DEFAULT_NUMBER_ID;
191190
const itemTransaction = transactions?.[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`];
192-
const hasDraftComment = isValidDraftComment(draftComments?.[`${ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT}${reportID}`]);
191+
const hasDraftComment = !!draftComments?.[reportID];
193192

194193
const isReportArchived = !!itemReportNameValuePairs?.private_isArchived;
195194
const canUserPerformWrite = canUserPerformWriteAction(item, isReportArchived);
@@ -288,7 +287,6 @@ function LHNOptionsList({style, contentContainerStyles, data, onSelectRow, optio
288287
policy,
289288
personalDetails,
290289
data.length,
291-
draftComments,
292290
optionMode,
293291
preferredLocale,
294292
transactions,
@@ -305,7 +303,6 @@ function LHNOptionsList({style, contentContainerStyles, data, onSelectRow, optio
305303
policy,
306304
personalDetails,
307305
data.length,
308-
draftComments,
309306
optionMode,
310307
preferredLocale,
311308
transactions,

src/hooks/useDiffPrevious.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import union from 'lodash/union';
2+
import {useMemo} from 'react';
3+
import usePrevious from './usePrevious';
4+
5+
/** This hook provides a list of which keys changed in an object vs the previous render
6+
* akin to `sourceValue` for collections. Generally, using this hook at all is an anti-pattern.
7+
* Avoid it at all costs */
8+
export default function useDiffPrevious<T extends Record<string, unknown>>(value: T): string[] {
9+
const previous = usePrevious(value);
10+
const diff = useMemo(() => {
11+
const allKeys = union(Object.keys(value), Object.keys(previous));
12+
return allKeys.filter((key) => value[key] !== previous[key]);
13+
}, [value, previous]);
14+
15+
return diff;
16+
}

src/hooks/usePriorityChange.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import usePrevious from './usePrevious';
77

88
function usePriorityMode() {
99
const [priorityMode] = useOnyx(ONYXKEYS.NVP_PRIORITY_MODE, {canBeMissing: true});
10-
const [allReportsWithDraftComments] = useOnyx(ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT, {canBeMissing: true});
10+
const [allReportsWithDraftComments] = useOnyx(ONYXKEYS.NVP_DRAFT_REPORT_COMMENTS, {canBeMissing: true});
1111
const prevPriorityMode = usePrevious(priorityMode);
1212

1313
useEffect(() => {

src/hooks/useSidebarOrderedReports.tsx

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@ import SidebarUtils from '@libs/SidebarUtils';
77
import CONST from '@src/CONST';
88
import ONYXKEYS from '@src/ONYXKEYS';
99
import type * as OnyxTypes from '@src/types/onyx';
10+
import {getEmptyObject} from '@src/types/utils/EmptyObject';
1011
import mapOnyxCollectionItems from '@src/utils/mapOnyxCollectionItems';
1112
import useCurrentReportID from './useCurrentReportID';
1213
import useCurrentUserPersonalDetails from './useCurrentUserPersonalDetails';
14+
import useDiffPrevious from './useDiffPrevious';
1315
import useLocalize from './useLocalize';
1416
import useOnyx from './useOnyx';
1517
import usePrevious from './usePrevious';
@@ -65,7 +67,8 @@ function SidebarOrderedReportsContextProvider({
6567
const [transactions, {sourceValue: transactionsUpdates}] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION, {canBeMissing: true});
6668
const [transactionViolations, {sourceValue: transactionViolationsUpdates}] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS, {canBeMissing: true});
6769
const [reportNameValuePairs, {sourceValue: reportNameValuePairsUpdates}] = useOnyx(ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS, {canBeMissing: true});
68-
const [, {sourceValue: reportsDraftsUpdates}] = useOnyx(ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT, {canBeMissing: true});
70+
const [drafts = getEmptyObject<OnyxTypes.DraftReportComments>()] = useOnyx(ONYXKEYS.NVP_DRAFT_REPORT_COMMENTS, {canBeMissing: true});
71+
const reportsDraftsUpdates = useDiffPrevious(drafts);
6972
const [betas] = useOnyx(ONYXKEYS.BETAS, {canBeMissing: true});
7073
const [reportAttributes] = useOnyx(ONYXKEYS.DERIVED.REPORT_ATTRIBUTES, {selector: (value) => value?.reports, canBeMissing: true});
7174
const [currentReportsToDisplay, setCurrentReportsToDisplay] = useState<ReportsToDisplayInLHN>({});
@@ -98,8 +101,8 @@ function SidebarOrderedReportsContextProvider({
98101
reportsToUpdate = Object.keys(transactionViolationsUpdates ?? {})
99102
.map((key) => key.replace(ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS, ONYXKEYS.COLLECTION.TRANSACTION))
100103
.map((key) => `${ONYXKEYS.COLLECTION.REPORT}${transactions?.[key]?.reportID}`);
101-
} else if (reportsDraftsUpdates) {
102-
reportsToUpdate = Object.keys(reportsDraftsUpdates).map((key) => key.replace(ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT, ONYXKEYS.COLLECTION.REPORT));
104+
} else if (reportsDraftsUpdates.length > 0) {
105+
reportsToUpdate = reportsDraftsUpdates.map((key) => `${ONYXKEYS.COLLECTION.REPORT}${key}`);
103106
} else if (policiesUpdates) {
104107
const updatedPolicies = Object.keys(policiesUpdates).map((key) => key.replace(ONYXKEYS.COLLECTION.POLICY, ''));
105108
reportsToUpdate = Object.entries(chatReports ?? {})
@@ -150,10 +153,10 @@ function SidebarOrderedReportsContextProvider({
150153
derivedCurrentReportID,
151154
priorityMode === CONST.PRIORITY_MODE.GSD,
152155
betas,
153-
policies,
154156
transactionViolations,
155157
reportNameValuePairs,
156158
reportAttributes,
159+
drafts,
157160
);
158161
} else {
159162
reportsToDisplay = SidebarUtils.getReportsToDisplayInLHN(
@@ -165,19 +168,20 @@ function SidebarOrderedReportsContextProvider({
165168
transactionViolations,
166169
reportNameValuePairs,
167170
reportAttributes,
171+
drafts,
168172
);
169173
}
170174
return reportsToDisplay;
171175
// Rule disabled intentionally — triggering a re-render on currentReportsToDisplay would cause an infinite loop
172176
// eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps
173-
}, [getUpdatedReports, chatReports, derivedCurrentReportID, priorityMode, betas, policies, transactionViolations, reportNameValuePairs, reportAttributes]);
177+
}, [getUpdatedReports, chatReports, derivedCurrentReportID, priorityMode, betas, policies, transactionViolations, reportNameValuePairs, reportAttributes, reportsDraftsUpdates]);
174178

175179
useEffect(() => {
176180
setCurrentReportsToDisplay(reportsToDisplayInLHN);
177181
}, [reportsToDisplayInLHN]);
178182

179183
const getOrderedReportIDs = useCallback(
180-
() => SidebarUtils.sortReportsToDisplayInLHN(reportsToDisplayInLHN, priorityMode, localeCompare, reportNameValuePairs, reportAttributes),
184+
() => SidebarUtils.sortReportsToDisplayInLHN(reportsToDisplayInLHN, priorityMode, localeCompare, reportNameValuePairs, reportAttributes, drafts),
181185
// Rule disabled intentionally - reports should be sorted only when the reportsToDisplayInLHN changes
182186
// eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps
183187
[reportsToDisplayInLHN, localeCompare],
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
type SaveReportDraftCommentParams = {
2+
reportID: string;
3+
reportComment: string;
4+
};
5+
6+
export default SaveReportDraftCommentParams;

src/libs/API/parameters/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -419,3 +419,4 @@ export type {default as ReopenReportParams} from './ReopenReportParams';
419419
export type {default as OpenUnreportedExpensesPageParams} from './OpenUnreportedExpensesPageParams';
420420
export type {default as VerifyTestDriveRecipientParams} from './VerifyTestDriveRecipientParams';
421421
export type {default as ExportSearchWithTemplateParams} from './ExportSearchWithTemplateParams';
422+
export type {default as SaveReportDraftCommentParams} from './SaveReportDraftCommentParams';

src/libs/API/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import type UpdateBeneficialOwnersForBankAccountParams from './parameters/Update
1111
type ApiRequestType = ValueOf<typeof CONST.API_REQUEST_TYPE>;
1212

1313
const WRITE_COMMANDS = {
14+
SAVE_REPORT_DRAFT_COMMENT: 'SaveReportDraftComment',
1415
CLEAN_POLICY_TAGS: 'ClearPolicyTags',
1516
IMPORT_MULTI_LEVEL_TAGS: 'ImportMultiLevelTags',
1617
SET_WORKSPACE_AUTO_REPORTING_FREQUENCY: 'SetWorkspaceAutoReportingFrequency',
@@ -861,6 +862,7 @@ type WriteCommandParameters = {
861862
[WRITE_COMMANDS.FINISH_CORPAY_BANK_ACCOUNT_ONBOARDING]: Parameters.FinishCorpayBankAccountOnboardingParams;
862863
[WRITE_COMMANDS.DELETE_VACATION_DELEGATE]: null;
863864
[WRITE_COMMANDS.REOPEN_REPORT]: Parameters.ReopenReportParams;
865+
[WRITE_COMMANDS.SAVE_REPORT_DRAFT_COMMENT]: Parameters.SaveReportDraftCommentParams;
864866

865867
[WRITE_COMMANDS.DELETE_MONEY_REQUEST_ON_SEARCH]: Parameters.DeleteMoneyRequestOnSearchParams;
866868
[WRITE_COMMANDS.HOLD_MONEY_REQUEST_ON_SEARCH]: Parameters.HoldMoneyRequestOnSearchParams;

src/libs/DraftCommentUtils.ts

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
1+
import type {OnyxEntry} from 'react-native-onyx';
22
import Onyx from 'react-native-onyx';
33
import ONYXKEYS from '@src/ONYXKEYS';
4+
import type {DraftReportComments} from '@src/types/onyx';
45

5-
let draftCommentCollection: OnyxCollection<string> = {};
6+
let draftComments: OnyxEntry<DraftReportComments> = {};
67
Onyx.connect({
7-
key: ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT,
8+
key: ONYXKEYS.NVP_DRAFT_REPORT_COMMENTS,
89
callback: (nextVal) => {
9-
draftCommentCollection = nextVal;
10+
draftComments = nextVal;
1011
},
11-
waitForCollectionCallback: true,
1212
});
1313

1414
/**
@@ -17,22 +17,15 @@ Onyx.connect({
1717
* A valid use-case of this function is outside React components, like in utility functions.
1818
*/
1919
function getDraftComment(reportID: string): OnyxEntry<string> | null | undefined {
20-
return draftCommentCollection?.[ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT + reportID];
21-
}
22-
23-
/**
24-
* Returns true if the report has a valid draft comment.
25-
* A valid draft comment is a non-empty string.
26-
*/
27-
function isValidDraftComment(comment?: string | null): boolean {
28-
return !!comment;
20+
return draftComments?.[reportID];
2921
}
3022

3123
/**
3224
* Returns true if the report has a valid draft comment.
25+
* NOTE: please prefer useOnyx when possible
3326
*/
3427
function hasValidDraftComment(reportID: string): boolean {
35-
return isValidDraftComment(getDraftComment(reportID));
28+
return !!getDraftComment(reportID);
3629
}
3730

3831
/**
@@ -44,4 +37,4 @@ function prepareDraftComment(comment: string | null) {
4437
return comment || null;
4538
}
4639

47-
export {getDraftComment, isValidDraftComment, hasValidDraftComment, prepareDraftComment};
40+
export {getDraftComment, hasValidDraftComment, prepareDraftComment};

src/libs/SidebarUtils.ts

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,17 @@ import type {LocaleContextProps} from '@components/LocaleContextProvider';
66
import type {PartialPolicyForSidebar, ReportsToDisplayInLHN} from '@hooks/useSidebarOrderedReports';
77
import CONST from '@src/CONST';
88
import ONYXKEYS from '@src/ONYXKEYS';
9-
import type {Card, PersonalDetails, PersonalDetailsList, ReportActions, ReportAttributesDerivedValue, ReportNameValuePairs, Transaction, TransactionViolation} from '@src/types/onyx';
9+
import type {
10+
Card,
11+
DraftReportComments,
12+
PersonalDetails,
13+
PersonalDetailsList,
14+
ReportActions,
15+
ReportAttributesDerivedValue,
16+
ReportNameValuePairs,
17+
Transaction,
18+
TransactionViolation,
19+
} from '@src/types/onyx';
1020
import type Beta from '@src/types/onyx/Beta';
1121
import type {ReportAttributes} from '@src/types/onyx/DerivedValues';
1222
import type {Errors} from '@src/types/onyx/OnyxCommon';
@@ -15,7 +25,6 @@ import type PriorityMode from '@src/types/onyx/PriorityMode';
1525
import type Report from '@src/types/onyx/Report';
1626
import type ReportAction from '@src/types/onyx/ReportAction';
1727
import {extractCollectionItemID} from './CollectionUtils';
18-
import {hasValidDraftComment} from './DraftCommentUtils';
1928
import {translateLocal} from './Localize';
2029
import {getLastActorDisplayName, getLastMessageTextForReport, getPersonalDetailsForAccountIDs, shouldShowLastActorDisplayName} from './OptionsListUtils';
2130
import Parser from './Parser';
@@ -207,6 +216,7 @@ function shouldDisplayReportInLHN(
207216
transactionViolations: OnyxCollection<TransactionViolation[]>,
208217
isReportArchived?: boolean,
209218
reportAttributes?: ReportAttributesDerivedValue['reports'],
219+
draftReportComments?: DraftReportComments,
210220
) {
211221
if (!report) {
212222
return {shouldDisplay: false};
@@ -237,7 +247,12 @@ function shouldDisplayReportInLHN(
237247
// Check if report should override hidden status
238248
const isSystemChat = isSystemChatUtil(report);
239249
const shouldOverrideHidden =
240-
hasValidDraftComment(report.reportID) || hasErrorsOtherThanFailedReceipt || isFocused || isSystemChat || !!report.isPinned || reportAttributes?.[report?.reportID]?.requiresAttention;
250+
!!draftReportComments?.[report.reportID] ||
251+
hasErrorsOtherThanFailedReceipt ||
252+
isFocused ||
253+
isSystemChat ||
254+
!!report.isPinned ||
255+
reportAttributes?.[report?.reportID]?.requiresAttention;
241256

242257
if (isHidden && !shouldOverrideHidden) {
243258
return {shouldDisplay: false};
@@ -268,6 +283,7 @@ function getReportsToDisplayInLHN(
268283
transactionViolations: OnyxCollection<TransactionViolation[]>,
269284
reportNameValuePairs?: OnyxCollection<ReportNameValuePairs>,
270285
reportAttributes?: ReportAttributesDerivedValue['reports'],
286+
draftReportComments?: DraftReportComments,
271287
) {
272288
const isInFocusMode = priorityMode === CONST.PRIORITY_MODE.GSD;
273289
const allReportsDictValues = reports ?? {};
@@ -287,6 +303,7 @@ function getReportsToDisplayInLHN(
287303
transactionViolations,
288304
isArchivedReport(reportNameValuePairs?.[`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${report.reportID}`]),
289305
reportAttributes,
306+
draftReportComments,
290307
);
291308

292309
if (shouldDisplay) {
@@ -304,10 +321,10 @@ function updateReportsToDisplayInLHN(
304321
currentReportId: string | undefined,
305322
isInFocusMode: boolean,
306323
betas: OnyxEntry<Beta[]>,
307-
policies: OnyxCollection<PartialPolicyForSidebar>,
308324
transactionViolations: OnyxCollection<TransactionViolation[]>,
309325
reportNameValuePairs?: OnyxCollection<ReportNameValuePairs>,
310326
reportAttributes?: ReportAttributesDerivedValue['reports'],
327+
draftReportComments?: DraftReportComments,
311328
) {
312329
const displayedReportsCopy = {...displayedReports};
313330
updatedReportsKeys.forEach((reportID) => {
@@ -325,6 +342,7 @@ function updateReportsToDisplayInLHN(
325342
transactionViolations,
326343
isArchivedReport(reportNameValuePairs?.[`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${report.reportID}`]),
327344
reportAttributes,
345+
draftReportComments,
328346
);
329347

330348
if (shouldDisplay) {
@@ -343,6 +361,7 @@ function categorizeReportsForLHN(
343361
reportsToDisplay: ReportsToDisplayInLHN,
344362
reportNameValuePairs?: OnyxCollection<ReportNameValuePairs>,
345363
reportAttributes?: ReportAttributesDerivedValue['reports'],
364+
draftReportComments?: DraftReportComments,
346365
) {
347366
const pinnedAndGBRReports: MiniReport[] = [];
348367
const errorReports: MiniReport[] = [];
@@ -355,7 +374,7 @@ function categorizeReportsForLHN(
355374
const reportID = report.reportID;
356375
const isPinned = !!report.isPinned;
357376
const hasErrors = !!report.hasErrorsOtherThanFailedReceipt;
358-
const hasDraft = reportID ? hasValidDraftComment(reportID) : false;
377+
const hasDraft = reportID ? !!draftReportComments?.[reportID] : false;
359378
const reportNameValuePairsKey = `${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${reportID}`;
360379
const rNVPs = reportNameValuePairs?.[reportNameValuePairsKey];
361380

@@ -469,6 +488,7 @@ function sortReportsToDisplayInLHN(
469488
localeCompare: LocaleContextProps['localeCompare'],
470489
reportNameValuePairs?: OnyxCollection<ReportNameValuePairs>,
471490
reportAttributes?: ReportAttributesDerivedValue['reports'],
491+
draftReportComments?: DraftReportComments,
472492
): string[] {
473493
Performance.markStart(CONST.TIMING.GET_ORDERED_REPORT_IDS);
474494

@@ -486,7 +506,7 @@ function sortReportsToDisplayInLHN(
486506
// - Sorted by reportDisplayName in GSD (focus) view mode
487507

488508
// Step 1: Categorize reports
489-
const categories = categorizeReportsForLHN(reportsToDisplay, reportNameValuePairs, reportAttributes);
509+
const categories = categorizeReportsForLHN(reportsToDisplay, reportNameValuePairs, reportAttributes, draftReportComments);
490510

491511
// Step 2: Sort each category
492512
const sortedCategories = sortCategorizedReports(categories, isInDefaultMode, localeCompare);

0 commit comments

Comments
 (0)