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

feat: support accountid attribute in user mentions #26877

Merged
merged 7 commits into from
Sep 24, 2023
Merged
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import React from 'react';
import _ from 'underscore';
import {TNodeChildrenRenderer} from 'react-native-render-html';
import {withOnyx} from 'react-native-onyx';
import lodashGet from 'lodash/get';
import Navigation from '../../../libs/Navigation/Navigation';
import ROUTES from '../../../ROUTES';
import Text from '../../Text';
Expand All @@ -10,53 +12,67 @@ import withCurrentUserPersonalDetails from '../../withCurrentUserPersonalDetails
import personalDetailsPropType from '../../../pages/personalDetailsPropType';
import * as StyleUtils from '../../../styles/StyleUtils';
import * as PersonalDetailsUtils from '../../../libs/PersonalDetailsUtils';
import compose from '../../../libs/compose';
import TextLink from '../../TextLink';
import ONYXKEYS from '../../../ONYXKEYS';
import useLocalize from '../../../hooks/useLocalize';
import CONST from '../../../CONST';

const propTypes = {
...htmlRendererPropTypes,

/**
* Current user personal details
*/
/** Current user personal details */
currentUserPersonalDetails: personalDetailsPropType.isRequired,
};

/**
* Navigates to user details screen based on email
* @param {String} email
* @returns {void}
* */
const showUserDetails = (email) => Navigation.navigate(ROUTES.getDetailsRoute(email));
/** Personal details of all users */
personalDetails: personalDetailsPropType.isRequired,
};

function MentionUserRenderer(props) {
const {translate} = useLocalize();
const defaultRendererProps = _.omit(props, ['TDefaultRenderer', 'style']);
const htmlAttribAccountID = lodashGet(props.tnode.attributes, 'accountid');

let accountID;
let displayNameOrLogin;
let navigationRoute;

// We need to remove the LTR unicode and leading @ from data as it is not part of the login
const loginWithoutLeadingAt = props.tnode.data ? props.tnode.data.replace(CONST.UNICODE.LTR, '').slice(1) : '';
if (!_.isEmpty(htmlAttribAccountID)) {
const user = lodashGet(props.personalDetails, htmlAttribAccountID);
accountID = parseInt(htmlAttribAccountID, 10);
displayNameOrLogin = lodashGet(user, 'login', '') || lodashGet(user, 'displayName', '') || translate('common.hidden');
navigationRoute = ROUTES.getProfileRoute(htmlAttribAccountID);
} else if (!_.isEmpty(props.tnode.data)) {
// We need to remove the LTR unicode and leading @ from data as it is not part of the login
displayNameOrLogin = props.tnode.data.replace(CONST.UNICODE.LTR, '').slice(1);

const accountID = _.first(PersonalDetailsUtils.getAccountIDsByLogins([loginWithoutLeadingAt]));
accountID = _.first(PersonalDetailsUtils.getAccountIDsByLogins([displayNameOrLogin]));
navigationRoute = ROUTES.getDetailsRoute(displayNameOrLogin);
} else {
// If neither an account ID or email is provided, don't render anything
return null;
}

const isOurMention = loginWithoutLeadingAt === props.currentUserPersonalDetails.login;
const isOurMention = accountID === props.currentUserPersonalDetails.accountID;

return (
<Text>
<UserDetailsTooltip
accountID={accountID}
fallbackUserDetails={{
displayName: loginWithoutLeadingAt,
displayName: displayNameOrLogin,
}}
>
<TextLink
// eslint-disable-next-line react/jsx-props-no-spreading
{...defaultRendererProps}
href={ROUTES.getDetailsRoute(loginWithoutLeadingAt)}
href={`/${navigationRoute}`}
style={[_.omit(props.style, 'color'), StyleUtils.getMentionStyle(isOurMention), {color: StyleUtils.getMentionTextColor(isOurMention)}]}
onPress={() => showUserDetails(loginWithoutLeadingAt)}
onPress={() => Navigation.navigate(navigationRoute)}
// Add testID so it is NOT selected as an anchor tag by SelectionScraper
testID="span"
>
<TNodeChildrenRenderer tnode={props.tnode} />
{!_.isEmpty(htmlAttribAccountID) ? `@${displayNameOrLogin}` : <TNodeChildrenRenderer tnode={props.tnode} />}
</TextLink>
</UserDetailsTooltip>
</Text>
Expand All @@ -66,4 +82,11 @@ function MentionUserRenderer(props) {
MentionUserRenderer.propTypes = propTypes;
MentionUserRenderer.displayName = 'MentionUserRenderer';

export default withCurrentUserPersonalDetails(MentionUserRenderer);
export default compose(
withCurrentUserPersonalDetails,
withOnyx({
personalDetails: {
key: ONYXKEYS.PERSONAL_DETAILS_LIST,
},
}),
)(MentionUserRenderer);