Skip to content

Commit

Permalink
Merge pull request #37281 from callstack-internal/audit/implementatio…
Browse files Browse the repository at this point in the history
…n/hasDraft-replacement

[Audit][Implementation] hasDraft replacement
  • Loading branch information
AndrewGable authored Apr 4, 2024
2 parents 3644018 + 564933c commit 9b22258
Show file tree
Hide file tree
Showing 25 changed files with 134 additions and 151 deletions.
10 changes: 7 additions & 3 deletions src/components/LHNOptionsList/LHNOptionsList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import usePrevious from '@hooks/usePrevious';
import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
import useWindowDimensions from '@hooks/useWindowDimensions';
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 @@ -112,7 +113,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 @@ -139,7 +140,7 @@ function LHNOptionsList({
isFocused={!shouldDisableFocusOptions}
onSelectRow={onSelectRow}
preferredLocale={preferredLocale}
comment={itemComment}
hasDraftComment={hasDraftComment}
transactionViolations={transactionViolations}
canUseViolations={canUseViolations}
onLayout={onLayoutItem}
Expand All @@ -163,7 +164,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 @@ -27,7 +27,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 @@ -654,7 +654,6 @@ function createOption(
login: null,
reportID: '',
phoneNumber: null,
hasDraftComment: false,
keyForList: null,
searchText: null,
isDefaultRoom: false,
Expand Down Expand Up @@ -699,7 +698,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 @@ -56,6 +56,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 @@ -391,7 +392,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 @@ -4469,9 +4469,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 @@ -139,7 +140,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 @@ -214,7 +215,6 @@ function getOptionData({
phoneNumber: null,
isUnread: null,
isUnreadWithMention: null,
hasDraftComment: false,
keyForList: null,
searchText: null,
isPinned: false,
Expand Down Expand Up @@ -263,7 +263,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 @@ -160,7 +160,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 @@ -362,7 +361,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 @@ -412,14 +410,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 @@ -881,7 +878,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 @@ -936,14 +932,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

0 comments on commit 9b22258

Please sign in to comment.