Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Audit][Implementation] hasDraft replacement #37281

Merged
Show file tree
Hide file tree
Changes from 28 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
00c81de
remove hasDraft from Report model
kacper-mikolajczak Feb 27, 2024
d177314
remove reportWithoutHasDraftSelector
kacper-mikolajczak Feb 27, 2024
eeec9ba
use draft comment to calculate hasDraftComment
kacper-mikolajczak Feb 27, 2024
7b8a757
fix shouldREportBeInOptionList
kacper-mikolajczak Feb 28, 2024
9df353b
trim the comment for hasDraftComment calculations
kacper-mikolajczak Feb 28, 2024
8876c08
create draft message store
kacper-mikolajczak Mar 4, 2024
cdef526
split gORIDs into smaller functions
kacper-mikolajczak Mar 4, 2024
2f0555f
fixing complexity
kacper-mikolajczak Mar 5, 2024
74c658a
Revert "fixing complexity"
kacper-mikolajczak Mar 8, 2024
024a50c
Revert "split gORIDs into smaller functions"
kacper-mikolajczak Mar 8, 2024
3330608
invalidate reports order on drafts change
kacper-mikolajczak Mar 8, 2024
bb2da17
remove hasDraft from tests
kacper-mikolajczak Mar 8, 2024
b166c50
fix draftComment computation
kacper-mikolajczak Mar 21, 2024
3fddd59
change name
kacper-mikolajczak Mar 21, 2024
c1214ab
remain ordering of default Option object
kacper-mikolajczak Mar 21, 2024
1b245b4
make saveReportComment delete drafts for empty comments
kacper-mikolajczak Mar 22, 2024
059ea4a
cleanup
kacper-mikolajczak Mar 22, 2024
e599e5b
do not save drafts with spaces only
kacper-mikolajczak Mar 22, 2024
7e2c3c5
prepare draft comment util
kacper-mikolajczak Mar 22, 2024
a3cd97d
waitForCollectionCallback in DraftCommentUtils
kacper-mikolajczak Mar 22, 2024
da1d823
rename draftCommentMap to draftCommentCollection
kacper-mikolajczak Mar 22, 2024
7adfbc9
merge & fix to main
kacper-mikolajczak Mar 22, 2024
67a8736
fix tests
kacper-mikolajczak Mar 22, 2024
eff88de
add draftComments to FlashList extraData
kacper-mikolajczak Mar 22, 2024
4b56f6f
fix minor things
kacper-mikolajczak Mar 22, 2024
c9d75e2
merge main
kacper-mikolajczak Mar 25, 2024
7b2c6bc
merge main
kacper-mikolajczak Mar 27, 2024
fa7415c
fix tests
kacper-mikolajczak Mar 28, 2024
1575de7
merge main
kacper-mikolajczak Apr 2, 2024
b52bb0b
fix list reordering
kacper-mikolajczak Apr 4, 2024
564933c
Merge branch 'main' into audit/implementation/hasDraft-replacement
kacper-mikolajczak Apr 4, 2024
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
10 changes: 7 additions & 3 deletions src/components/LHNOptionsList/LHNOptionsList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {ScrollOffsetContext} from '@components/ScrollOffsetContextProvider';
import usePermissions from '@hooks/usePermissions';
import usePrevious from '@hooks/usePrevious';
import useThemeStyles from '@hooks/useThemeStyles';
import * as DraftCommentUtils from '@libs/DraftCommentUtils';
import * as ReportActionsUtils from '@libs/ReportActionsUtils';
import variables from '@styles/variables';
import CONST from '@src/CONST';
Expand Down Expand Up @@ -66,7 +67,7 @@ function LHNOptionsList({
const itemPolicy = policy?.[`${ONYXKEYS.COLLECTION.POLICY}${itemFullReport?.policyID}`] ?? null;
const transactionID = itemParentReportAction?.actionName === CONST.REPORT.ACTIONS.TYPE.IOU ? itemParentReportAction.originalMessage.IOUTransactionID ?? '' : '';
const itemTransaction = transactions?.[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`] ?? null;
const itemComment = draftComments?.[`${ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT}${reportID}`] ?? '';
const hasDraftComment = DraftCommentUtils.isValidDraftComment(draftComments?.[`${ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT}${reportID}`]);
const sortedReportActions = ReportActionsUtils.getSortedReportActionsForDisplay(itemReportActions);
const lastReportAction = sortedReportActions[0];

Expand All @@ -93,7 +94,7 @@ function LHNOptionsList({
isFocused={!shouldDisableFocusOptions}
onSelectRow={onSelectRow}
preferredLocale={preferredLocale}
comment={itemComment}
hasDraftComment={hasDraftComment}
transactionViolations={transactionViolations}
canUseViolations={canUseViolations}
onLayout={onLayoutItem}
Expand All @@ -117,7 +118,10 @@ function LHNOptionsList({
],
);

const extraData = useMemo(() => [reportActions, reports, policy, personalDetails, data.length], [reportActions, reports, policy, personalDetails, data.length]);
const extraData = useMemo(
() => [reportActions, reports, policy, personalDetails, data.length, draftComments],
[reportActions, reports, policy, personalDetails, data.length, draftComments],
);

const previousOptionMode = usePrevious(optionMode);

Expand Down
4 changes: 2 additions & 2 deletions src/components/LHNOptionsList/OptionRowLHN.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import CONST from '@src/CONST';
import {isEmptyObject} from '@src/types/utils/EmptyObject';
import type {OptionRowLHNProps} from './types';

function OptionRowLHN({reportID, isFocused = false, onSelectRow = () => {}, optionItem, viewMode = 'default', style, onLayout = () => {}}: OptionRowLHNProps) {
function OptionRowLHN({reportID, isFocused = false, onSelectRow = () => {}, optionItem, viewMode = 'default', style, onLayout = () => {}, hasDraftComment}: OptionRowLHNProps) {
const theme = useTheme();
const styles = useThemeStyles();
const popoverAnchor = useRef<View>(null);
Expand Down Expand Up @@ -248,7 +248,7 @@ function OptionRowLHN({reportID, isFocused = false, onSelectRow = () => {}, opti
/>
</View>
)}
{optionItem.hasDraftComment && optionItem.isAllowedToComment && (
{hasDraftComment && optionItem.isAllowedToComment && (
<View
style={styles.ml2}
accessibilityLabel={translate('sidebarScreen.draftedMessage')}
Expand Down
12 changes: 1 addition & 11 deletions src/components/LHNOptionsList/OptionRowLHNData.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import {deepEqual} from 'fast-equals';
import React, {useEffect, useMemo, useRef} from 'react';
import React, {useMemo, useRef} from 'react';
import useCurrentReportID from '@hooks/useCurrentReportID';
import * as ReportUtils from '@libs/ReportUtils';
import SidebarUtils from '@libs/SidebarUtils';
import * as Report from '@userActions/Report';
import CONST from '@src/CONST';
import type {OptionData} from '@src/libs/ReportUtils';
import OptionRowLHN from './OptionRowLHN';
Expand All @@ -21,7 +20,6 @@ function OptionRowLHNData({
reportActions,
personalDetails = {},
preferredLocale = CONST.LOCALES.DEFAULT,
comment,
policy,
receiptTransactions,
parentReportAction,
Expand Down Expand Up @@ -74,14 +72,6 @@ function OptionRowLHNData({
receiptTransactions,
]);

useEffect(() => {
if (!optionItem || !!optionItem.hasDraftComment || !comment || comment.length <= 0 || isFocused) {
return;
}
Report.setReportWithDraft(reportID, true);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

return (
<OptionRowLHN
// eslint-disable-next-line react/jsx-props-no-spreading
Expand Down
7 changes: 5 additions & 2 deletions src/components/LHNOptionsList/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,8 @@ type OptionRowLHNDataProps = {
/** The transaction linked to the report's last action */
lastReportActionTransaction?: OnyxEntry<Transaction | EmptyObject>;

/** Comment added to report */
comment: string;
/** Whether a report contains a draft */
hasDraftComment: boolean;

/** The receipt transaction from the parent report action */
receiptTransactions: OnyxCollection<Transaction>;
Expand Down Expand Up @@ -133,6 +133,9 @@ type OptionRowLHNProps = {
/** The item that should be rendered */
optionItem?: OptionData;

/** Whether a report contains a draft */
hasDraftComment: boolean;

onLayout?: (event: LayoutChangeEvent) => void;
};

Expand Down
3 changes: 0 additions & 3 deletions src/components/optionPropTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,6 @@ export default PropTypes.shape({
// reportID (only present when there is a matching report)
reportID: PropTypes.string,

// Whether the report has a draft comment or not
hasDraftComment: PropTypes.bool,

// Key used internally by React
keyForList: PropTypes.string,

Expand Down
25 changes: 0 additions & 25 deletions src/libs/ComposerUtils/getDraftComment.ts

This file was deleted.

47 changes: 47 additions & 0 deletions src/libs/DraftCommentUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
import Onyx from 'react-native-onyx';
import ONYXKEYS from '@src/ONYXKEYS';

let draftCommentCollection: OnyxCollection<string> = {};
Onyx.connect({
key: ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT,
callback: (nextVal) => {
draftCommentCollection = nextVal;
},
waitForCollectionCallback: true,
});

/**
* Returns a draft comment from the onyx collection for given reportID.
* Note: You should use the HOCs/hooks to get onyx data, instead of using this directly.
* A valid use-case of this function is outside React components, like in utility functions.
*/
function getDraftComment(reportID: string): OnyxEntry<string> | null | undefined {
return draftCommentCollection?.[ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT + reportID];
}

/**
* Returns true if the report has a valid draft comment.
* A valid draft comment is a non-empty string.
*/
function isValidDraftComment(comment?: string | null): boolean {
return !!comment?.trim();
}

/**
* Returns true if the report has a valid draft comment.
*/
function hasValidDraftComment(reportID: string): boolean {
return isValidDraftComment(getDraftComment(reportID));
}

/**
* Prepares a draft comment by trimming it and returning null if it's empty.
*/
function prepareDraftComment(comment: string | null) {
// logical OR is used to convert empty string to null
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
return comment?.trim() || null;
}

export {getDraftComment, isValidDraftComment, hasValidDraftComment, prepareDraftComment};
14 changes: 0 additions & 14 deletions src/libs/OnyxSelectors/reportWithoutHasDraftSelector.ts

This file was deleted.

2 changes: 0 additions & 2 deletions src/libs/OptionsListUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -618,7 +618,6 @@ function createOption(
login: null,
reportID: '',
phoneNumber: null,
hasDraftComment: false,
keyForList: null,
searchText: null,
isDefaultRoom: false,
Expand Down Expand Up @@ -664,7 +663,6 @@ function createOption(
result.ownerAccountID = report.ownerAccountID;
result.reportID = report.reportID;
result.isUnread = ReportUtils.isUnread(report);
result.hasDraftComment = report.hasDraft;
result.isPinned = report.isPinned;
result.iouReportID = report.iouReportID;
result.keyForList = String(report.reportID);
Expand Down
7 changes: 5 additions & 2 deletions src/libs/ReportUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ import * as store from './actions/ReimbursementAccount/store';
import * as CollectionUtils from './CollectionUtils';
import * as CurrencyUtils from './CurrencyUtils';
import DateUtils from './DateUtils';
import {hasValidDraftComment} from './DraftCommentUtils';
import originalGetReportPolicyID from './getReportPolicyID';
import isReportMessageAttachment from './isReportMessageAttachment';
import localeCompare from './LocaleCompare';
Expand Down Expand Up @@ -380,7 +381,6 @@ type OptionData = {
phoneNumber?: string | null;
isUnread?: boolean | null;
isUnreadWithMention?: boolean | null;
hasDraftComment?: boolean | null;
keyForList?: string | null;
searchText?: string | null;
isIOUReportOwner?: boolean | null;
Expand Down Expand Up @@ -4369,9 +4369,12 @@ function shouldReportBeInOptionList({
return true;
}

// Retrieve the draft comment for the report and convert it to a boolean
const hasDraftComment = hasValidDraftComment(report.reportID);

// Include reports that are relevant to the user in any view mode. Criteria include having a draft or having a GBR showing.
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
if (report.hasDraft || requiresAttentionFromCurrentUser(report)) {
if (hasDraftComment || requiresAttentionFromCurrentUser(report)) {
return true;
}
const lastVisibleMessage = ReportActionsUtils.getLastVisibleMessage(report.reportID);
Expand Down
5 changes: 2 additions & 3 deletions src/libs/SidebarUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import type {ReportActions} from '@src/types/onyx/ReportAction';
import type ReportAction from '@src/types/onyx/ReportAction';
import type DeepValueOf from '@src/types/utils/DeepValueOf';
import * as CollectionUtils from './CollectionUtils';
import {hasValidDraftComment} from './DraftCommentUtils';
import localeCompare from './LocaleCompare';
import * as LocalePhoneNumber from './LocalePhoneNumber';
import * as Localize from './Localize';
Expand Down Expand Up @@ -147,7 +148,7 @@ function getOrderedReportIDs(
const reportAction = ReportActionsUtils.getReportAction(report.parentReportID ?? '', report.parentReportActionID ?? '');
if (isPinned || ReportUtils.requiresAttentionFromCurrentUser(report, reportAction)) {
pinnedAndGBRReports.push(report);
} else if (report.hasDraft) {
} else if (hasValidDraftComment(report.reportID)) {
draftReports.push(report);
} else if (ReportUtils.isArchivedRoom(report)) {
archivedReports.push(report);
Expand Down Expand Up @@ -222,7 +223,6 @@ function getOptionData({
phoneNumber: null,
isUnread: null,
isUnreadWithMention: null,
hasDraftComment: false,
keyForList: null,
searchText: null,
isPinned: false,
Expand Down Expand Up @@ -271,7 +271,6 @@ function getOptionData({
// setting it Unread so we add additional condition here to avoid empty chat LHN from being bold.
result.isUnread = ReportUtils.isUnread(report) && !!report.lastActorAccountID;
result.isUnreadWithMention = ReportUtils.isUnreadWithMention(report);
result.hasDraftComment = report.hasDraft;
result.isPinned = report.isPinned;
result.iouReportID = report.iouReportID;
result.keyForList = String(report.reportID);
Expand Down
9 changes: 2 additions & 7 deletions src/libs/actions/Policy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,6 @@ Onyx.connect({
return;
}
const {reportID} = policyReport;
cleanUpMergeQueries[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`] = {hasDraft: false};
cleanUpSetQueries[`${ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT}${reportID}`] = null;
cleanUpSetQueries[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS_DRAFTS}${reportID}`] = null;
});
Expand Down Expand Up @@ -351,7 +350,6 @@ function deleteWorkspace(policyID: string, policyName: string) {
value: {
stateNum: CONST.REPORT.STATE_NUM.APPROVED,
statusNum: CONST.REPORT.STATUS_NUM.CLOSED,
hasDraft: false,
oldPolicyName: allPolicies?.[`${ONYXKEYS.COLLECTION.POLICY}${policyID}`]?.name ?? '',
policyName: '',
},
Expand Down Expand Up @@ -401,14 +399,13 @@ function deleteWorkspace(policyID: string, policyName: string) {
];

reportsToArchive.forEach((report) => {
const {reportID, stateNum, statusNum, hasDraft, oldPolicyName} = report ?? {};
const {reportID, stateNum, statusNum, oldPolicyName} = report ?? {};
failureData.push({
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT}${reportID}`,
value: {
stateNum,
statusNum,
hasDraft,
oldPolicyName,
policyName: report?.policyName,
},
Expand Down Expand Up @@ -878,7 +875,6 @@ function removeMembers(accountIDs: number[], policyID: string) {
statusNum: CONST.REPORT.STATUS_NUM.CLOSED,
stateNum: CONST.REPORT.STATE_NUM.APPROVED,
oldPolicyName: policy.name,
hasDraft: false,
pendingChatMembers,
},
});
Expand Down Expand Up @@ -933,14 +929,13 @@ function removeMembers(accountIDs: number[], policyID: string) {

const filteredWorkspaceChats = workspaceChats.filter((report): report is Report => report !== null);

filteredWorkspaceChats.forEach(({reportID, stateNum, statusNum, hasDraft, oldPolicyName = null}) => {
filteredWorkspaceChats.forEach(({reportID, stateNum, statusNum, oldPolicyName = null}) => {
failureData.push({
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT}${reportID}`,
value: {
stateNum,
statusNum,
hasDraft,
oldPolicyName,
},
});
Expand Down
Loading
Loading