Skip to content

Commit

Permalink
Merge pull request #39906 from software-mansion-labs/war-in/mention-r…
Browse files Browse the repository at this point in the history
…oom-renderer

[Mentions v2] Parse <mention-report> when displaying reportAction
  • Loading branch information
rlinoz authored Apr 12, 2024
2 parents 617f9e9 + 052e4ce commit 44de443
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ function BaseHTMLEngineProvider({textSelectable = false, children, enableExperim
contentModel: HTMLContentModel.textual,
}),
'mention-user': HTMLElementModel.fromCustomModel({tagName: 'mention-user', contentModel: HTMLContentModel.textual}),
'mention-report': HTMLElementModel.fromCustomModel({tagName: 'mention-report', contentModel: HTMLContentModel.textual}),
'mention-here': HTMLElementModel.fromCustomModel({tagName: 'mention-here', contentModel: HTMLContentModel.textual}),
'next-step': HTMLElementModel.fromCustomModel({
tagName: 'next-step',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
import isEmpty from 'lodash/isEmpty';
import React, {useMemo} from 'react';
import type {TextStyle} from 'react-native';
import {StyleSheet} from 'react-native';
import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
import {withOnyx} from 'react-native-onyx';
import type {CustomRendererProps, TPhrasing, TText} from 'react-native-render-html';
import {ShowContextMenuContext} from '@components/ShowContextMenuContext';
import Text from '@components/Text';
import useCurrentReportID from '@hooks/useCurrentReportID';
import useStyleUtils from '@hooks/useStyleUtils';
import useThemeStyles from '@hooks/useThemeStyles';
import {getReport} from '@libs/ReportUtils';
import * as ReportUtils from '@libs/ReportUtils';
import Navigation from '@navigation/Navigation';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import type {Report} from '@src/types/onyx';
import type {EmptyObject} from '@src/types/utils/EmptyObject';
import {isEmptyObject} from '@src/types/utils/EmptyObject';

type MentionReportOnyxProps = {
/** All reports shared with the user */
reports: OnyxCollection<Report>;
};

type MentionReportRendererProps = MentionReportOnyxProps & CustomRendererProps<TText | TPhrasing>;

const removeLeadingLTRAndHash = (value: string) => value.replace(CONST.UNICODE.LTR, '').replace('#', '');

const getMentionDetails = (htmlAttributeReportID: string, currentReport: OnyxEntry<Report> | EmptyObject, reports: OnyxCollection<Report>, tnode: TText | TPhrasing) => {
let reportID: string | undefined;
let mentionDisplayText: string;

// Get mention details based on reportID from tag attribute
if (!isEmpty(htmlAttributeReportID)) {
const report = getReport(htmlAttributeReportID);

reportID = report?.reportID ?? undefined;
mentionDisplayText = removeLeadingLTRAndHash(report?.reportName ?? report?.displayName ?? htmlAttributeReportID);
// Get mention details from name inside tnode
} else if ('data' in tnode && !isEmptyObject(tnode.data)) {
mentionDisplayText = removeLeadingLTRAndHash(tnode.data);

// eslint-disable-next-line rulesdir/prefer-early-return
Object.values(reports ?? {}).forEach((report) => {
if (report?.policyID === currentReport?.policyID && removeLeadingLTRAndHash(report?.reportName ?? '') === mentionDisplayText) {
reportID = report?.reportID;
}
});
} else {
return null;
}

return {reportID, mentionDisplayText};
};

function MentionReportRenderer({style, tnode, TDefaultRenderer, reports, ...defaultRendererProps}: MentionReportRendererProps) {
const styles = useThemeStyles();
const StyleUtils = useStyleUtils();
const htmlAttributeReportID = tnode.attributes.reportid;

const currentReportID = useCurrentReportID();
const currentReport = getReport(currentReportID?.currentReportID);
const isGroupPolicyReport = useMemo(() => (currentReport && !isEmptyObject(currentReport) ? ReportUtils.isGroupPolicy(currentReport) : false), [currentReport]);

const mentionDetails = getMentionDetails(htmlAttributeReportID, currentReport, reports, tnode);
if (!mentionDetails) {
return null;
}
const {reportID, mentionDisplayText} = mentionDetails;

const navigationRoute = reportID ? ROUTES.REPORT_WITH_ID.getRoute(reportID) : undefined;
const isCurrentRoomMention = reportID === currentReportID?.currentReportID;

const flattenStyle = StyleSheet.flatten(style as TextStyle);
const {color, ...styleWithoutColor} = flattenStyle;

return (
<ShowContextMenuContext.Consumer>
{() => (
<Text
// eslint-disable-next-line react/jsx-props-no-spreading
{...defaultRendererProps}
style={
isGroupPolicyReport
? [styles.link, styleWithoutColor, StyleUtils.getMentionStyle(isCurrentRoomMention), {color: StyleUtils.getMentionTextColor(isCurrentRoomMention)}]
: []
}
suppressHighlighting
onPress={
navigationRoute && isGroupPolicyReport
? (event) => {
event.preventDefault();
Navigation.navigate(navigationRoute);
}
: undefined
}
role={isGroupPolicyReport ? CONST.ROLE.LINK : undefined}
accessibilityLabel={isGroupPolicyReport ? `/${navigationRoute}` : undefined}
>
#{mentionDisplayText}
</Text>
)}
</ShowContextMenuContext.Consumer>
);
}

MentionReportRenderer.displayName = 'MentionReportRenderer';

const chatReportSelector = (report: OnyxEntry<Report>): Report =>
(report && {
reportID: report.reportID,
reportName: report.reportName,
displayName: report.displayName,
policyID: report.policyID,
}) as Report;

export default withOnyx<MentionReportRendererProps, MentionReportOnyxProps>({
reports: {
key: ONYXKEYS.COLLECTION.REPORT,
selector: chatReportSelector,
},
})(MentionReportRenderer);
2 changes: 2 additions & 0 deletions src/components/HTMLEngineProvider/HTMLRenderers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import EditedRenderer from './EditedRenderer';
import EmojiRenderer from './EmojiRenderer';
import ImageRenderer from './ImageRenderer';
import MentionHereRenderer from './MentionHereRenderer';
import MentionReportRenderer from './MentionReportRenderer';
import MentionUserRenderer from './MentionUserRenderer';
import NextStepEmailRenderer from './NextStepEmailRenderer';
import PreRenderer from './PreRenderer';
Expand All @@ -25,6 +26,7 @@ const HTMLEngineProviderComponentList: CustomTagRendererRecord = {
pre: PreRenderer,
/* eslint-disable @typescript-eslint/naming-convention */
'mention-user': MentionUserRenderer,
'mention-report': MentionReportRenderer,
'mention-here': MentionHereRenderer,
emoji: EmojiRenderer,
'next-step-email': NextStepEmailRenderer,
Expand Down

0 comments on commit 44de443

Please sign in to comment.