* MM-25684 Highlight at-mention followed by a period
* Refactor at_mention to not highlight the period
* Do not add a link for invalid mentions
* Suggested review
Co-authored-by: Miguel Alatzar <migbot@users.noreply.github.com>
Co-authored-by: Miguel Alatzar <migbot@users.noreply.github.com>
(cherry picked from commit 1d0fc0510c)
Co-authored-by: Elias Nahum <nahumhbl@gmail.com>
This commit is contained in:
parent
dccdf1a238
commit
537acefb2d
5 changed files with 100 additions and 35 deletions
|
|
@ -1,8 +1,21 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`AtMention should match snapshot, no highlight 1`] = `
|
||||
<Text>
|
||||
@John.Smith
|
||||
<Text
|
||||
style={Object {}}
|
||||
>
|
||||
<Text
|
||||
style={
|
||||
Array [
|
||||
null,
|
||||
Object {
|
||||
"backgroundColor": "yellow",
|
||||
},
|
||||
]
|
||||
}
|
||||
>
|
||||
@John.Smith
|
||||
</Text>
|
||||
</Text>
|
||||
`;
|
||||
|
||||
|
|
@ -10,9 +23,17 @@ exports[`AtMention should match snapshot, with highlight 1`] = `
|
|||
<Text
|
||||
onLongPress={[Function]}
|
||||
onPress={[Function]}
|
||||
style={Object {}}
|
||||
>
|
||||
<Text
|
||||
style={null}
|
||||
style={
|
||||
Array [
|
||||
null,
|
||||
Object {
|
||||
"backgroundColor": "yellow",
|
||||
},
|
||||
]
|
||||
}
|
||||
>
|
||||
@John.Smith
|
||||
</Text>
|
||||
|
|
@ -24,12 +45,18 @@ exports[`AtMention should match snapshot, without highlight 1`] = `
|
|||
<Text
|
||||
onLongPress={[Function]}
|
||||
onPress={[Function]}
|
||||
style={Object {}}
|
||||
>
|
||||
<Text
|
||||
style={
|
||||
Object {
|
||||
"color": "#ff0000",
|
||||
}
|
||||
Array [
|
||||
Object {
|
||||
"color": "#ff0000",
|
||||
},
|
||||
Object {
|
||||
"backgroundColor": "yellow",
|
||||
},
|
||||
]
|
||||
}
|
||||
>
|
||||
@Victor.Welch
|
||||
|
|
|
|||
|
|
@ -3,17 +3,16 @@
|
|||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {Text} from 'react-native';
|
||||
import {StyleSheet, Text} from 'react-native';
|
||||
import Clipboard from '@react-native-community/clipboard';
|
||||
import {intlShape} from 'react-intl';
|
||||
import MaterialIcon from 'react-native-vector-icons/MaterialIcons';
|
||||
|
||||
import {showModal} from '@actions/navigation';
|
||||
import {displayUsername} from '@mm-redux/utils/user_utils';
|
||||
|
||||
import CustomPropTypes from 'app/constants/custom_prop_types';
|
||||
import CustomPropTypes from '@constants/custom_prop_types';
|
||||
import mattermostManaged from 'app/mattermost_managed';
|
||||
import BottomSheet from 'app/utils/bottom_sheet';
|
||||
import {showModal} from 'app/actions/navigation';
|
||||
import BottomSheet from '@utils/bottom_sheet';
|
||||
|
||||
export default class AtMention extends React.PureComponent {
|
||||
static propTypes = {
|
||||
|
|
@ -142,37 +141,53 @@ export default class AtMention extends React.PureComponent {
|
|||
render() {
|
||||
const {isSearchResult, mentionName, mentionStyle, onPostPress, teammateNameDisplay, textStyle, mentionKeys} = this.props;
|
||||
const {user} = this.state;
|
||||
const {backgroundColor, ...styleText} = StyleSheet.flatten(textStyle);
|
||||
let canPress = false;
|
||||
let highlighted;
|
||||
let mention;
|
||||
let suffix;
|
||||
|
||||
if (!user.username) {
|
||||
if (user?.username) {
|
||||
suffix = this.props.mentionName.substring(user.username.length);
|
||||
highlighted = mentionKeys.some((item) => item.key === user.username);
|
||||
mention = displayUsername(user, teammateNameDisplay);
|
||||
canPress = true;
|
||||
} else {
|
||||
const group = this.getGroupFromMentionName();
|
||||
if (group.allow_reference) {
|
||||
highlighted = mentionKeys.some((item) => item.key === group.name);
|
||||
return (
|
||||
<Text
|
||||
style={textStyle}
|
||||
>
|
||||
<Text style={highlighted ? null : mentionStyle}>
|
||||
{`@${group.name}`}
|
||||
</Text>
|
||||
</Text>
|
||||
);
|
||||
}
|
||||
mention = group.name;
|
||||
suffix = this.props.mentionName.substring(group.name.length);
|
||||
} else {
|
||||
const pattern = new RegExp(/(all|channel|here)\.?/, 'i');
|
||||
const mentionMatch = pattern.exec(mentionName);
|
||||
|
||||
return <Text style={textStyle}>{'@' + mentionName}</Text>;
|
||||
if (mentionMatch) {
|
||||
highlighted = false;
|
||||
mention = mentionMatch.length > 1 ? mentionMatch[1] : mentionMatch[0];
|
||||
suffix = mentionName.replace(mention, '');
|
||||
} else {
|
||||
highlighted = true;
|
||||
mention = mentionName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const suffix = this.props.mentionName.substring(user.username.length);
|
||||
highlighted = mentionKeys.some((item) => item.key === user.username);
|
||||
let onPress;
|
||||
let onLongPress;
|
||||
if (canPress) {
|
||||
onLongPress = this.handleLongPress;
|
||||
onPress = isSearchResult ? onPostPress : this.goToUserProfile;
|
||||
}
|
||||
|
||||
return (
|
||||
<Text
|
||||
style={textStyle}
|
||||
onPress={isSearchResult ? onPostPress : this.goToUserProfile}
|
||||
onLongPress={this.handleLongPress}
|
||||
style={styleText}
|
||||
onPress={onPress}
|
||||
onLongPress={onLongPress}
|
||||
>
|
||||
<Text style={highlighted ? null : mentionStyle}>
|
||||
{'@' + displayUsername(user, teammateNameDisplay)}
|
||||
<Text style={[highlighted ? null : mentionStyle, {backgroundColor}]}>
|
||||
{'@' + mention}
|
||||
</Text>
|
||||
{suffix}
|
||||
</Text>
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ describe('AtMention', () => {
|
|||
teammateNameDisplay: '',
|
||||
mentionName: 'John.Smith',
|
||||
mentionStyle: {color: '#ff0000'},
|
||||
textStyle: {backgroundColor: 'yellow'},
|
||||
theme: {},
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -281,12 +281,10 @@ export function highlightMentions(ast, mentionKeys) {
|
|||
} else if (node.type === 'at_mention') {
|
||||
const matches = mentionKeys.some((mention) => {
|
||||
const mentionName = '@' + node.mentionName;
|
||||
const flags = mention.caseSensitive ? '' : 'i';
|
||||
const pattern = new RegExp(`${escapeRegex(mention.key)}\\.?`, flags);
|
||||
|
||||
if (mention.caseSensitive) {
|
||||
return mention.key === mentionName;
|
||||
}
|
||||
|
||||
return mention.key.toLowerCase() === mentionName.toLowerCase();
|
||||
return pattern.test(mentionName);
|
||||
});
|
||||
|
||||
if (!matches) {
|
||||
|
|
|
|||
|
|
@ -2751,6 +2751,30 @@ describe('Components.Markdown.transform', () => {
|
|||
}],
|
||||
}],
|
||||
},
|
||||
}, {
|
||||
name: 'Mention followed by a period',
|
||||
input: 'This is a mention for @channel.',
|
||||
mentionKeys: [{key: 'channel'}],
|
||||
expected: {
|
||||
type: 'document',
|
||||
children: [{
|
||||
type: 'paragraph',
|
||||
children: [{
|
||||
type: 'text',
|
||||
literal: 'This is a mention for ',
|
||||
}, {
|
||||
type: 'mention_highlight',
|
||||
children: [{
|
||||
type: 'at_mention',
|
||||
_mentionName: 'channel.',
|
||||
children: [{
|
||||
type: 'text',
|
||||
literal: '@channel.',
|
||||
}],
|
||||
}],
|
||||
}],
|
||||
}],
|
||||
},
|
||||
}];
|
||||
|
||||
for (const test of tests) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue