Skip to content
2 changes: 1 addition & 1 deletion src/libs/ReportUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1938,7 +1938,7 @@ function getTransactionReportName(reportAction: OnyxEntry<ReportAction>): string
* @param [reportAction] This can be either a report preview action or the IOU action
*/
function getReportPreviewMessage(
report: OnyxEntry<Report>,
report: OnyxEntry<Report> | EmptyObject,
reportAction: OnyxEntry<ReportAction> | EmptyObject = {},
shouldConsiderReceiptBeingScanned = false,
isPreviewMessageForParentChatReport = false,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,88 +1,83 @@
import lodashGet from 'lodash/get';
import PropTypes from 'prop-types';
import React from 'react';
import {Text, View} from 'react-native';
import _ from 'underscore';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
import React, {ReactElement} from 'react';
import {StyleProp, Text, View, ViewStyle} from 'react-native';
import useLocalize from '@hooks/useLocalize';
import useThemeStyles from '@hooks/useThemeStyles';
import * as ReportActionsUtils from '@libs/ReportActionsUtils';
import * as ReportUtils from '@libs/ReportUtils';
import CONST from '@src/CONST';
import type {ReportAction} from '@src/types/onyx';
import type {OriginalMessageAddComment} from '@src/types/onyx/OriginalMessage';
import TextCommentFragment from './comment/TextCommentFragment';
import ReportActionItemFragment from './ReportActionItemFragment';
import reportActionPropTypes from './reportActionPropTypes';

const propTypes = {
type ReportActionItemMessageProps = {
/** The report action */
action: PropTypes.shape(reportActionPropTypes).isRequired,
action: ReportAction;

/** Should the comment have the appearance of being grouped with the previous comment? */
displayAsGroup: PropTypes.bool.isRequired,
displayAsGroup: boolean;

/** Additional styles to add after local styles. */
style: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.object), PropTypes.object]),
style?: StyleProp<ViewStyle>;

/** Whether or not the message is hidden by moderation */
isHidden: PropTypes.bool,
isHidden?: boolean;

/** The ID of the report */
reportID: PropTypes.string.isRequired,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This got removed accidentally.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@parasharrajat it's still there

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops. Got confused with Default props.


/** localization props */
...withLocalizePropTypes,
};

const defaultProps = {
style: [],
isHidden: false,
reportID: string;
};

function ReportActionItemMessage(props) {
function ReportActionItemMessage({action, displayAsGroup, reportID, style, isHidden = false}: ReportActionItemMessageProps) {
const styles = useThemeStyles();
const fragments = _.compact(props.action.previousMessage || props.action.message);
const isIOUReport = ReportActionsUtils.isMoneyRequestAction(props.action);
if (ReportActionsUtils.isMemberChangeAction(props.action)) {
const fragment = ReportActionsUtils.getMemberChangeMessageFragment(props.action);
const {translate} = useLocalize();

const fragments = (action.previousMessage ?? action.message ?? []).filter((item) => !!item);
const isIOUReport = ReportActionsUtils.isMoneyRequestAction(action);

if (ReportActionsUtils.isMemberChangeAction(action)) {
const fragment = ReportActionsUtils.getMemberChangeMessageFragment(action);

return (
<TextCommentFragment
fragment={fragment}
displayAsGroup={props.displayAsGroup}
style={props.style}
displayAsGroup={displayAsGroup}
style={style}
source=""
styleAsDeleted={false}
/>
);
}

let iouMessage;
let iouMessage: string | undefined;
if (isIOUReport) {
const iouReportID = lodashGet(props.action, 'originalMessage.IOUReportID');
const originalMessage = action.actionName === CONST.REPORT.ACTIONS.TYPE.IOU ? action.originalMessage : null;
const iouReportID = originalMessage?.IOUReportID;
if (iouReportID) {
iouMessage = ReportUtils.getReportPreviewMessage(ReportUtils.getReport(iouReportID), props.action);
iouMessage = ReportUtils.getReportPreviewMessage(ReportUtils.getReport(iouReportID), action);
}
}

const isApprovedOrSubmittedReportAction = _.contains([CONST.REPORT.ACTIONS.TYPE.APPROVED, CONST.REPORT.ACTIONS.TYPE.SUBMITTED], props.action.actionName);
const isApprovedOrSubmittedReportAction = [CONST.REPORT.ACTIONS.TYPE.APPROVED, CONST.REPORT.ACTIONS.TYPE.SUBMITTED].some((type) => type === action.actionName);

/**
* Get the ReportActionItemFragments
* @param {Boolean} shouldWrapInText determines whether the fragments are wrapped in a Text component
* @returns {Object} report action item fragments
* @param shouldWrapInText determines whether the fragments are wrapped in a Text component
* @returns report action item fragments
*/
const renderReportActionItemFragments = (shouldWrapInText) => {
const reportActionItemFragments = _.map(fragments, (fragment, index) => (
const renderReportActionItemFragments = (shouldWrapInText: boolean): ReactElement | ReactElement[] => {
const reportActionItemFragments = fragments.map((fragment, index) => (
<ReportActionItemFragment
key={`actionFragment-${props.action.reportActionID}-${index}`}
/* eslint-disable-next-line react/no-array-index-key */
key={`actionFragment-${action.reportActionID}-${index}`}
fragment={fragment}
iouMessage={iouMessage}
isThreadParentMessage={ReportActionsUtils.isThreadParentMessage(props.action, props.reportID)}
attachmentInfo={props.action.attachmentInfo}
pendingAction={props.action.pendingAction}
source={lodashGet(props.action, 'originalMessage.source')}
accountID={props.action.actorAccountID}
style={props.style}
displayAsGroup={props.displayAsGroup}
isThreadParentMessage={ReportActionsUtils.isThreadParentMessage(action, reportID)}
attachmentInfo={action.attachmentInfo}
pendingAction={action.pendingAction}
source={(action.originalMessage as OriginalMessageAddComment['originalMessage'])?.source}
accountID={action.actorAccountID}
style={style}
displayAsGroup={displayAsGroup}
isApprovedOrSubmittedReportAction={isApprovedOrSubmittedReportAction}
// Since system messages from Old Dot begin with the person who performed the action,
// the first fragment will contain the person's display name and their email. We'll use this
Expand All @@ -99,18 +94,16 @@ function ReportActionItemMessage(props) {
};

return (
<View style={[styles.chatItemMessage, ...props.style]}>
{!props.isHidden ? (
<View style={[styles.chatItemMessage, style]}>
{!isHidden ? (
renderReportActionItemFragments(isApprovedOrSubmittedReportAction)
) : (
<Text style={[styles.textLabelSupporting, styles.lh20]}>{props.translate('moderation.flaggedContent')}</Text>
<Text style={[styles.textLabelSupporting, styles.lh20]}>{translate('moderation.flaggedContent')}</Text>
)}
</View>
);
}

ReportActionItemMessage.propTypes = propTypes;
ReportActionItemMessage.defaultProps = defaultProps;
ReportActionItemMessage.displayName = 'ReportActionItemMessage';

export default withLocalize(ReportActionItemMessage);
export default ReportActionItemMessage;
16 changes: 15 additions & 1 deletion src/types/onyx/OriginalMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ type OriginalMessageApproved = {
actionName: typeof CONST.REPORT.ACTIONS.TYPE.APPROVED;
originalMessage: unknown;
};
type OriginalMessageSource = 'Chronos' | 'email' | 'ios' | 'android' | 'web' | '';

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Curious, where did you get this list?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These values were taken from this file


type IOUDetails = {
amount: number;
Expand Down Expand Up @@ -95,6 +96,7 @@ type OriginalMessageAddComment = {
actionName: typeof CONST.REPORT.ACTIONS.TYPE.ADDCOMMENT;
originalMessage: {
html: string;
source?: OriginalMessageSource;
lastModified?: string;
taskReportID?: string;
edits?: string[];
Expand Down Expand Up @@ -252,4 +254,16 @@ type OriginalMessage =
| OriginalMessageMoved;

export default OriginalMessage;
export type {ChronosOOOEvent, Decision, Reaction, ActionName, IOUMessage, Closed, OriginalMessageActionName, ChangeLog, OriginalMessageIOU, OriginalMessageCreated};
export type {
ChronosOOOEvent,
Decision,
Reaction,
ActionName,
IOUMessage,
Closed,
OriginalMessageActionName,
ChangeLog,
OriginalMessageIOU,
OriginalMessageCreated,
OriginalMessageAddComment,
};
4 changes: 3 additions & 1 deletion src/types/utils/EmptyObject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ import Falsy from './Falsy';

type EmptyObject = Record<string, never>;

type EmptyValue = EmptyObject | null | undefined;

// eslint-disable-next-line rulesdir/no-negated-variables
function isNotEmptyObject<T extends Record<string, unknown> | Falsy>(arg: T | EmptyObject): arg is NonNullable<T> {
return Object.keys(arg ?? {}).length > 0;
}

function isEmptyObject<T>(obj: T): boolean {
function isEmptyObject<T>(obj: T | EmptyValue): obj is EmptyValue {
return Object.keys(obj ?? {}).length === 0;
}

Expand Down