Add new parser components
This commit is contained in:
parent
559f804073
commit
ff9b0fec9c
|
@ -0,0 +1,18 @@
|
||||||
|
/* eslint-disable react/no-array-index-key */
|
||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
import Emoji from './Emoji';
|
||||||
|
|
||||||
|
|
||||||
|
const BigEmoji = ({ value }) => (
|
||||||
|
<>
|
||||||
|
{value.map((block, index) => <Emoji key={index} value={block.value.value} isBigEmoji />)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
|
||||||
|
BigEmoji.propTypes = {
|
||||||
|
value: PropTypes.object
|
||||||
|
};
|
||||||
|
|
||||||
|
export default BigEmoji;
|
|
@ -0,0 +1,36 @@
|
||||||
|
/* eslint-disable react/no-array-index-key */
|
||||||
|
import React from 'react';
|
||||||
|
import { StyleSheet, Text } from 'react-native';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import Plain from './Plain';
|
||||||
|
import Strike from './Strike';
|
||||||
|
import Italic from './Italic';
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
text: {
|
||||||
|
fontWeight: 'bold'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const Bold = ({ value }) => (
|
||||||
|
<Text style={styles.text}>
|
||||||
|
{value.map((block, index) => {
|
||||||
|
switch (block.type) {
|
||||||
|
case 'PLAIN_TEXT':
|
||||||
|
return <Plain key={index} value={block.value} />;
|
||||||
|
case 'STRIKE':
|
||||||
|
return <Strike key={index} value={block.value} />;
|
||||||
|
case 'ITALIC':
|
||||||
|
return <Italic key={index} value={block.value} />;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
})}
|
||||||
|
</Text>
|
||||||
|
);
|
||||||
|
|
||||||
|
Bold.propTypes = {
|
||||||
|
value: PropTypes.string
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Bold;
|
|
@ -1,5 +1,6 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { PropTypes, Text } from 'react-native';
|
import { Text } from 'react-native';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
import { themes } from '../../../constants/colors';
|
import { themes } from '../../../constants/colors';
|
||||||
import { useTheme } from '../../../theme';
|
import { useTheme } from '../../../theme';
|
||||||
|
|
||||||
|
@ -11,7 +12,7 @@ const Code = ({
|
||||||
<Text
|
<Text
|
||||||
style={[
|
style={[
|
||||||
{
|
{
|
||||||
...(type === 'CODE_INLINE' ? styles.codeInline : styles.codeBlock),
|
...(type === 'INLINE_CODE' ? styles.codeInline : styles.codeBlock),
|
||||||
color: themes[theme].bodyText,
|
color: themes[theme].bodyText,
|
||||||
backgroundColor: themes[theme].bannerBackground,
|
backgroundColor: themes[theme].bannerBackground,
|
||||||
borderColor: themes[theme].bannerBackground
|
borderColor: themes[theme].bannerBackground
|
|
@ -0,0 +1,32 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { Text } from 'react-native';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
import shortnameToUnicode from '../../../utils/shortnameToUnicode';
|
||||||
|
import { themes } from '../../../constants/colors';
|
||||||
|
import { useTheme } from '../../../theme';
|
||||||
|
import styles from '../styles';
|
||||||
|
|
||||||
|
const Emoji = ({ emojiHandle, style, isBigEmoji }) => {
|
||||||
|
const { theme } = useTheme();
|
||||||
|
const emojiUnicode = shortnameToUnicode(emojiHandle);
|
||||||
|
return (
|
||||||
|
<Text
|
||||||
|
style={[
|
||||||
|
{ color: themes[theme].bodyText },
|
||||||
|
isBigEmoji ? styles.textBig : styles.text,
|
||||||
|
style
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
{emojiUnicode}
|
||||||
|
</Text>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
Emoji.propTypes = {
|
||||||
|
emojiHandle: PropTypes.string,
|
||||||
|
style: PropTypes.object,
|
||||||
|
isBigEmoji: PropTypes.bool
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Emoji;
|
|
@ -0,0 +1,35 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { Text } from 'react-native';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { themes } from '../../../constants/colors';
|
||||||
|
import styles from '../styles';
|
||||||
|
import { useTheme } from '../../../theme';
|
||||||
|
|
||||||
|
const Heading = ({ value, level }) => {
|
||||||
|
const { theme } = useTheme();
|
||||||
|
const textStyle = styles[`heading${ level }`];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{value.map((block) => {
|
||||||
|
switch (block.type) {
|
||||||
|
case 'PLAIN_TEXT':
|
||||||
|
return (
|
||||||
|
<Text style={[textStyle, { color: themes[theme].bodyText }]}>
|
||||||
|
{block.value}
|
||||||
|
</Text>
|
||||||
|
);
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
})}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
Heading.propTypes = {
|
||||||
|
value: PropTypes.string,
|
||||||
|
level: PropTypes.number
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Heading;
|
|
@ -0,0 +1,48 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { Text } from 'react-native';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
import Link from './Link';
|
||||||
|
import Plain from './Plain';
|
||||||
|
import Code from './Code';
|
||||||
|
import Bold from './Bold';
|
||||||
|
import Strike from './Strike';
|
||||||
|
import Italic from './Italic';
|
||||||
|
import Emoji from './Emoji';
|
||||||
|
|
||||||
|
const Inline = ({ value }) => (
|
||||||
|
<Text>
|
||||||
|
{value.map((block) => {
|
||||||
|
switch (block.type) {
|
||||||
|
case 'PLAIN_TEXT':
|
||||||
|
return <Plain value={block.value} />;
|
||||||
|
case 'BOLD':
|
||||||
|
return <Bold value={block.value} />;
|
||||||
|
case 'STRIKE':
|
||||||
|
return <Strike value={block.value} />;
|
||||||
|
case 'ITALIC':
|
||||||
|
return <Italic value={block.value} />;
|
||||||
|
case 'LINK':
|
||||||
|
// eslint-disable-next-line jsx-a11y/anchor-is-valid
|
||||||
|
return <Link value={block.value} />;
|
||||||
|
// case 'MENTION_USER':
|
||||||
|
// return <Mention value={block.value} mentions={mentions} />;
|
||||||
|
case 'EMOJI':
|
||||||
|
return <Emoji emojiHandle={`:${ block.value.value }:`} />;
|
||||||
|
// case 'MENTION_CHANNEL':
|
||||||
|
// // case 'COLOR':
|
||||||
|
// return <Plain value={block.value} />;
|
||||||
|
case 'INLINE_CODE':
|
||||||
|
return <Code value={block.value} />;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
})}
|
||||||
|
</Text>
|
||||||
|
);
|
||||||
|
|
||||||
|
Inline.propTypes = {
|
||||||
|
value: PropTypes.object
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Inline;
|
|
@ -0,0 +1,37 @@
|
||||||
|
/* eslint-disable react/no-array-index-key */
|
||||||
|
import React from 'react';
|
||||||
|
import { StyleSheet, Text } from 'react-native';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
import Plain from './Plain';
|
||||||
|
import Strike from './Strike';
|
||||||
|
import Bold from './Bold';
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
text: {
|
||||||
|
fontStyle: 'italic'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const Italic = ({ value }) => (
|
||||||
|
<Text style={styles.text}>
|
||||||
|
{value.map((block, index) => {
|
||||||
|
switch (block.type) {
|
||||||
|
case 'PLAIN_TEXT':
|
||||||
|
return <Plain key={index} value={block.value} />;
|
||||||
|
case 'STRIKE':
|
||||||
|
return <Strike key={index} value={block.value} />;
|
||||||
|
case 'BOLD':
|
||||||
|
return <Bold key={index} value={block.value} />;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
})}
|
||||||
|
</Text>
|
||||||
|
);
|
||||||
|
|
||||||
|
Italic.propTypes = {
|
||||||
|
value: PropTypes.string
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Italic;
|
|
@ -0,0 +1,63 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { Text, Clipboard } from 'react-native';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
import Strike from './Strike';
|
||||||
|
import Italic from './Italic';
|
||||||
|
import Bold from './Bold';
|
||||||
|
import styles from '../styles';
|
||||||
|
import I18n from '../../../i18n';
|
||||||
|
import { LISTENER } from '../../Toast';
|
||||||
|
import { useTheme } from '../../../theme';
|
||||||
|
import openLink from '../../../utils/openLink';
|
||||||
|
import EventEmitter from '../../../utils/events';
|
||||||
|
import { themes } from '../../../constants/colors';
|
||||||
|
|
||||||
|
const Link = ({ value }) => {
|
||||||
|
const { theme } = useTheme();
|
||||||
|
const { src, label } = value;
|
||||||
|
const handlePress = () => {
|
||||||
|
if (!src.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
openLink(src.value, theme);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onLongPress = () => {
|
||||||
|
Clipboard.setString(src.value);
|
||||||
|
EventEmitter.emit(LISTENER, { message: I18n.t('Copied_to_clipboard') });
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Text
|
||||||
|
onPress={handlePress}
|
||||||
|
onLongPress={onLongPress}
|
||||||
|
o
|
||||||
|
style={{ ...styles.link, color: themes[theme].actionTintColor }}
|
||||||
|
>
|
||||||
|
{((block) => {
|
||||||
|
switch (block.type) {
|
||||||
|
case 'PLAIN_TEXT':
|
||||||
|
return block.value;
|
||||||
|
case 'STRIKE':
|
||||||
|
return <Strike value={block.value} />;
|
||||||
|
case 'ITALIC':
|
||||||
|
return <Italic value={block.value} />;
|
||||||
|
case 'BOLD':
|
||||||
|
return <Bold value={block.value} />;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
})(label)}
|
||||||
|
</Text>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
Link.propTypes = {
|
||||||
|
value: {
|
||||||
|
src: PropTypes.string,
|
||||||
|
label: PropTypes.string
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Link;
|
|
@ -0,0 +1,13 @@
|
||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
import Inline from './Inline';
|
||||||
|
|
||||||
|
const Paragraph = ({ value, mentions }) => <Inline value={value} mentions={mentions} />;
|
||||||
|
|
||||||
|
Paragraph.propTypes = {
|
||||||
|
value: PropTypes.string,
|
||||||
|
mentions: PropTypes.string
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Paragraph;
|
|
@ -0,0 +1,15 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { Text } from 'react-native';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
const Plain = ({ value }) => (
|
||||||
|
<Text accessibilityLabel={value}>
|
||||||
|
{value}
|
||||||
|
</Text>
|
||||||
|
);
|
||||||
|
|
||||||
|
Plain.propTypes = {
|
||||||
|
value: PropTypes.string
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Plain;
|
|
@ -0,0 +1,26 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { View } from 'react-native';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { themes } from '../../../constants/colors';
|
||||||
|
import { useTheme } from '../../../theme';
|
||||||
|
import styles from '../styles';
|
||||||
|
|
||||||
|
const Quote = ({ value }) => {
|
||||||
|
const theme = useTheme();
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<View style={styles.container}>
|
||||||
|
<View style={[styles.quote, { backgroundColor: themes[theme].borderColor }]} />
|
||||||
|
<View style={styles.childContainer}>
|
||||||
|
{value}
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
Quote.propTypes = {
|
||||||
|
value: PropTypes.string
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Quote;
|
|
@ -0,0 +1,37 @@
|
||||||
|
/* eslint-disable react/no-array-index-key */
|
||||||
|
import React from 'react';
|
||||||
|
import { StyleSheet, Text } from 'react-native';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
import Plain from './Plain';
|
||||||
|
import Bold from './Bold';
|
||||||
|
import Italic from './Italic';
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
text: {
|
||||||
|
textDecorationLine: 'line-through'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const Strike = ({ value }) => (
|
||||||
|
<Text style={styles.text}>
|
||||||
|
{value.map((block, index) => {
|
||||||
|
switch (block.type) {
|
||||||
|
case 'PLAIN_TEXT':
|
||||||
|
return <Plain key={index} value={block.value} />;
|
||||||
|
case 'BOLD':
|
||||||
|
return <Bold key={index} value={block.value} />;
|
||||||
|
case 'ITALIC':
|
||||||
|
return <Italic key={index} value={block.value} />;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
})}
|
||||||
|
</Text>
|
||||||
|
);
|
||||||
|
|
||||||
|
Strike.propTypes = {
|
||||||
|
value: PropTypes.string
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Strike;
|
|
@ -0,0 +1,56 @@
|
||||||
|
/* eslint-disable react/no-array-index-key */
|
||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
import List from './List';
|
||||||
|
import Quote from './Quote';
|
||||||
|
import Paragraph from './Paragraph';
|
||||||
|
import Heading from './Heading';
|
||||||
|
import Code from './Code';
|
||||||
|
import Link from './Link';
|
||||||
|
import BigEmoji from './BigEmoji';
|
||||||
|
import { useTheme } from '../../../theme';
|
||||||
|
|
||||||
|
const isBigEmoji = tokens => tokens.length === 1 && tokens[0].type === 'BIG_EMOJI';
|
||||||
|
|
||||||
|
const Body = ({ tokens, mentions }) => {
|
||||||
|
const { theme } = useTheme();
|
||||||
|
if (isBigEmoji(tokens)) {
|
||||||
|
return <BigEmoji value={tokens[0].value} theme={theme} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{tokens.map((block, index) => {
|
||||||
|
switch (block.type) {
|
||||||
|
case 'UNORDERED_LIST':
|
||||||
|
return <List type={block.type} value={block.value} key={index} />;
|
||||||
|
case 'ORDERED_LIST':
|
||||||
|
return <List type={block.type} value={block.value} key={index} />;
|
||||||
|
case 'TASK':
|
||||||
|
return <List type={block.type} value={block.value} key={index} />;
|
||||||
|
case 'QUOTE':
|
||||||
|
return <Quote key={index} value={block.value} />;
|
||||||
|
case 'PARAGRAPH':
|
||||||
|
return <Paragraph key={index} value={block.value} mentions={mentions} />;
|
||||||
|
case 'CODE':
|
||||||
|
return <Code key={index} value={block.value} />;
|
||||||
|
case 'LINK':
|
||||||
|
// eslint-disable-next-line jsx-a11y/anchor-is-valid
|
||||||
|
return <Link key={index} value={block.value} />;
|
||||||
|
case 'HEADING':
|
||||||
|
return <Heading key={index} value={block.value} level={block.level} />;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
})}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
Body.propTypes = {
|
||||||
|
tokens: PropTypes.array,
|
||||||
|
mentions: PropTypes.array
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Body;
|
|
@ -1,16 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import { PropTypes } from 'react-native';
|
|
||||||
|
|
||||||
import MarkdownEmoji from '../Emoji';
|
|
||||||
|
|
||||||
const BigEmoji = ({ value }) => (
|
|
||||||
<>
|
|
||||||
<MarkdownEmoji literal={value} />
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
|
|
||||||
BigEmoji.propTypes = {
|
|
||||||
value: PropTypes.string
|
|
||||||
};
|
|
||||||
|
|
||||||
export default BigEmoji;
|
|
|
@ -1,53 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import { Text, PropTypes } from 'react-native';
|
|
||||||
import MarkdownLink from '../Link';
|
|
||||||
import MarkdownList from '../List';
|
|
||||||
// import MarkdownListItem from '../ListItem';
|
|
||||||
// import MarkdownAtMention from '../AtMention';
|
|
||||||
// import MarkdownHashtag from '../Hashtag';
|
|
||||||
import MarkdownBlockQuote from '../BlockQuote';
|
|
||||||
// import MarkdownTable from '../Table';
|
|
||||||
// import MarkdownTableRow from '../TableRow';
|
|
||||||
// import MarkdownTableCell from '../TableCell';
|
|
||||||
import styles from '../styles';
|
|
||||||
import { withTheme } from '../../../theme';
|
|
||||||
import { themes } from '../../../constants/colors';
|
|
||||||
|
|
||||||
|
|
||||||
const Body = ({
|
|
||||||
md, style, numberOfLines, theme
|
|
||||||
}) => (
|
|
||||||
<>
|
|
||||||
{md.map((block, index) => {
|
|
||||||
switch (block.type) {
|
|
||||||
case 'UNORDERED_LIST':
|
|
||||||
return <MarkdownList ordered={false} />;
|
|
||||||
case 'ORDERED_LIST':
|
|
||||||
return <MarkdownList ordered />;
|
|
||||||
case 'QUOTE':
|
|
||||||
return <MarkdownBlockQuote />;
|
|
||||||
case 'PARAGRAPH':
|
|
||||||
return (
|
|
||||||
<Text style={[styles.text, style, { color: themes[theme].bodyText }]} numberOfLines={numberOfLines} index={index}>
|
|
||||||
{block.value?.value}
|
|
||||||
</Text>
|
|
||||||
);
|
|
||||||
case 'CODE':
|
|
||||||
return <MarkdownLink />;
|
|
||||||
case 'LINK':
|
|
||||||
return <MarkdownLink />;
|
|
||||||
default:
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
})}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
|
|
||||||
Body.propTypes = {
|
|
||||||
md: PropTypes.array,
|
|
||||||
theme: PropTypes.string,
|
|
||||||
style: PropTypes.object,
|
|
||||||
numberOfLines: PropTypes.number
|
|
||||||
};
|
|
||||||
|
|
||||||
export default withTheme(Body);
|
|
|
@ -4,6 +4,7 @@ import { Parser, Node } from 'commonmark';
|
||||||
import Renderer from 'commonmark-react-renderer';
|
import Renderer from 'commonmark-react-renderer';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import removeMarkdown from 'remove-markdown';
|
import removeMarkdown from 'remove-markdown';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
import shortnameToUnicode from '../../utils/shortnameToUnicode';
|
import shortnameToUnicode from '../../utils/shortnameToUnicode';
|
||||||
import I18n from '../../i18n';
|
import I18n from '../../i18n';
|
||||||
|
@ -23,6 +24,8 @@ import mergeTextNodes from './mergeTextNodes';
|
||||||
|
|
||||||
import styles from './styles';
|
import styles from './styles';
|
||||||
import { isValidURL } from '../../utils/url';
|
import { isValidURL } from '../../utils/url';
|
||||||
|
import { getUserSelector } from '../../selectors/login';
|
||||||
|
import MessageBody from './MessageBody';
|
||||||
|
|
||||||
// Support <http://link|Text>
|
// Support <http://link|Text>
|
||||||
const formatText = text => text.replace(
|
const formatText = text => text.replace(
|
||||||
|
@ -69,6 +72,7 @@ class Markdown extends PureComponent {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
msg: PropTypes.string,
|
msg: PropTypes.string,
|
||||||
md: PropTypes.string,
|
md: PropTypes.string,
|
||||||
|
user: PropTypes.object,
|
||||||
getCustomEmoji: PropTypes.func,
|
getCustomEmoji: PropTypes.func,
|
||||||
baseUrl: PropTypes.string,
|
baseUrl: PropTypes.string,
|
||||||
username: PropTypes.string,
|
username: PropTypes.string,
|
||||||
|
@ -372,13 +376,17 @@ class Markdown extends PureComponent {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
msg, numberOfLines, preview = false, theme, style = [], testID
|
msg, md, numberOfLines, preview = false, theme, style = [], testID, user, mentions
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
if (!msg) {
|
if (!msg) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (user.enableMessageParserEarlyAdoption && md) {
|
||||||
|
return <MessageBody tokens={md} theme={theme} style={style} mentions={mentions} />;
|
||||||
|
}
|
||||||
|
|
||||||
let m = formatText(msg);
|
let m = formatText(msg);
|
||||||
|
|
||||||
// Ex: '[ ](https://open.rocket.chat/group/test?msg=abcdef) Test'
|
// Ex: '[ ](https://open.rocket.chat/group/test?msg=abcdef) Test'
|
||||||
|
@ -406,4 +414,8 @@ class Markdown extends PureComponent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Markdown;
|
const mapStateToProps = state => ({
|
||||||
|
user: getUserSelector(state)
|
||||||
|
});
|
||||||
|
|
||||||
|
export default connect(mapStateToProps)(Markdown);
|
||||||
|
|
|
@ -19,11 +19,11 @@ const changeMessageStatus = async(id, tmid, status, message) => {
|
||||||
if (message) {
|
if (message) {
|
||||||
m.mentions = message.mentions;
|
m.mentions = message.mentions;
|
||||||
m.channels = message.channels;
|
m.channels = message.channels;
|
||||||
}
|
|
||||||
|
|
||||||
if (message.md) {
|
if (message.md) {
|
||||||
m.md = message.md;
|
m.md = message.md;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -35,6 +35,10 @@ const changeMessageStatus = async(id, tmid, status, message) => {
|
||||||
if (message) {
|
if (message) {
|
||||||
tm.mentions = message.mentions;
|
tm.mentions = message.mentions;
|
||||||
tm.channels = message.channels;
|
tm.channels = message.channels;
|
||||||
|
|
||||||
|
if (message.md) {
|
||||||
|
tm.md = message.md;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
|
@ -54,7 +54,6 @@ const LastMessage = React.memo(({
|
||||||
msg={formatMsg({
|
msg={formatMsg({
|
||||||
lastMessage, type, showLastMessage, username, useRealName
|
lastMessage, type, showLastMessage, username, useRealName
|
||||||
})}
|
})}
|
||||||
md={lastMessage?.md}
|
|
||||||
style={[styles.markdownText, { color: alert ? themes[theme].bodyText : themes[theme].auxiliaryText }]}
|
style={[styles.markdownText, { color: alert ? themes[theme].bodyText : themes[theme].auxiliaryText }]}
|
||||||
customEmojis={false}
|
customEmojis={false}
|
||||||
useRealName={useRealName}
|
useRealName={useRealName}
|
||||||
|
|
Loading…
Reference in New Issue