Skip to content
Merged
Show file tree
Hide file tree
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
6,802 changes: 3,173 additions & 3,629 deletions __tests__/__snapshots__/Storyshots.test.js.snap

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion app/containers/MessageBox/ReplyPreview.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ class ReplyPreview extends Component {
<Text style={styles.username}>{message.u.username}</Text>
<Text style={styles.time}>{time}</Text>
</View>
<Markdown msg={message.msg} baseUrl={baseUrl} username={username} getCustomEmoji={getCustomEmoji} numberOfLines={1} useMarkdown={useMarkdown} />
<Markdown msg={message.msg} baseUrl={baseUrl} username={username} getCustomEmoji={getCustomEmoji} numberOfLines={1} useMarkdown={useMarkdown} preview />
</View>
<CustomIcon name='cross' color={COLOR_TEXT_DESCRIPTION} size={20} style={styles.close} onPress={this.close} />
</View>
Expand Down
5 changes: 3 additions & 2 deletions app/containers/markdown/AtMention.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Text } from 'react-native';
import styles from './styles';

const AtMention = React.memo(({
mention, mentions, username, navToRoomInfo
mention, mentions, username, navToRoomInfo, style = []
}) => {
let mentionStyle = styles.mention;
if (mention === 'all' || mention === 'here') {
Expand Down Expand Up @@ -33,7 +33,7 @@ const AtMention = React.memo(({

return (
<Text
style={mentionStyle}
style={[mentionStyle, ...style]}
onPress={handlePress}
>
{`@${ mention }`}
Expand All @@ -45,6 +45,7 @@ AtMention.propTypes = {
mention: PropTypes.string,
username: PropTypes.string,
navToRoomInfo: PropTypes.func,
style: PropTypes.array,
mentions: PropTypes.oneOfType([PropTypes.array, PropTypes.object])
};

Expand Down
19 changes: 15 additions & 4 deletions app/containers/markdown/Emoji.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ import CustomEmoji from '../EmojiPicker/CustomEmoji';
import styles from './styles';

const Emoji = React.memo(({
emojiName, literal, isMessageContainsOnlyEmoji, getCustomEmoji, baseUrl
emojiName, literal, isMessageContainsOnlyEmoji, getCustomEmoji, baseUrl, customEmojis, style = []
}) => {
const emojiUnicode = shortnameToUnicode(literal);
const emoji = getCustomEmoji && getCustomEmoji(emojiName);
if (emoji) {
if (emoji && customEmojis) {
return (
<CustomEmoji
baseUrl={baseUrl}
Expand All @@ -21,15 +21,26 @@ const Emoji = React.memo(({
/>
);
}
return <Text style={isMessageContainsOnlyEmoji ? styles.textBig : styles.text}>{emojiUnicode}</Text>;
return (
<Text
style={[
isMessageContainsOnlyEmoji ? styles.textBig : styles.text,
...style
]}
>
{emojiUnicode}
</Text>
);
});

Emoji.propTypes = {
emojiName: PropTypes.string,
literal: PropTypes.string,
isMessageContainsOnlyEmoji: PropTypes.bool,
getCustomEmoji: PropTypes.func,
baseUrl: PropTypes.string
baseUrl: PropTypes.string,
customEmojis: PropTypes.bool,
style: PropTypes.array
};

export default Emoji;
5 changes: 3 additions & 2 deletions app/containers/markdown/Hashtag.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Text } from 'react-native';
import styles from './styles';

const Hashtag = React.memo(({
hashtag, channels, navToRoomInfo
hashtag, channels, navToRoomInfo, style = []
}) => {
const handlePress = () => {
const index = channels.findIndex(channel => channel.name === hashtag);
Expand All @@ -19,7 +19,7 @@ const Hashtag = React.memo(({
if (channels && channels.length && channels.findIndex(channel => channel.name === hashtag) !== -1) {
return (
<Text
style={styles.mention}
style={[styles.mention, ...style]}
onPress={handlePress}
>
{`#${ hashtag }`}
Expand All @@ -32,6 +32,7 @@ const Hashtag = React.memo(({
Hashtag.propTypes = {
hashtag: PropTypes.string,
navToRoomInfo: PropTypes.func,
style: PropTypes.array,
channels: PropTypes.oneOfType([PropTypes.array, PropTypes.object])
};

Expand Down
13 changes: 10 additions & 3 deletions app/containers/markdown/List.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import PropTypes from 'prop-types';
import React from 'react';

const List = React.memo(({
children, ordered, start, tight
children, ordered, start, tight, numberOfLines = 0
}) => {
let bulletWidth = 15;

Expand All @@ -11,7 +11,13 @@ const List = React.memo(({
bulletWidth = (9 * lastNumber.toString().length) + 7;
}

const _children = React.Children.map(children, (child, index) => React.cloneElement(child, {
let items = React.Children.toArray(children);

if (numberOfLines) {
items = items.slice(0, numberOfLines);
}

const _children = items.map((child, index) => React.cloneElement(child, {
bulletWidth,
ordered,
tight,
Expand All @@ -29,7 +35,8 @@ List.propTypes = {
children: PropTypes.node,
ordered: PropTypes.bool,
start: PropTypes.number,
tight: PropTypes.bool
tight: PropTypes.bool,
numberOfLines: PropTypes.number
};

List.defaultProps = {
Expand Down
97 changes: 63 additions & 34 deletions app/containers/markdown/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { PureComponent } from 'react';
import { View, Text, Image } from 'react-native';
import { Text, Image } from 'react-native';
import { Parser, Node } from 'commonmark';
import Renderer from 'commonmark-react-renderer';
import PropTypes from 'prop-types';
Expand Down Expand Up @@ -53,8 +53,6 @@ const emojiCount = (str) => {
return counter;
};

const encodeEmojis = str => toShort(shortnameToUnicode(str));

export default class Markdown extends PureComponent {
static propTypes = {
msg: PropTypes.string,
Expand All @@ -65,21 +63,24 @@ export default class Markdown extends PureComponent {
isEdited: PropTypes.bool,
numberOfLines: PropTypes.number,
useMarkdown: PropTypes.bool,
customEmojis: PropTypes.bool,
channels: PropTypes.oneOfType([PropTypes.array, PropTypes.object]),
mentions: PropTypes.oneOfType([PropTypes.array, PropTypes.object]),
navToRoomInfo: PropTypes.func
navToRoomInfo: PropTypes.func,
preview: PropTypes.bool,
style: PropTypes.array
};

constructor(props) {
super(props);

this.parser = this.createParser();
this.renderer = this.createRenderer();
this.renderer = this.createRenderer(props.preview);
}

createParser = () => new Parser();

createRenderer = () => new Renderer({
createRenderer = (preview = false) => new Renderer({
renderers: {
text: this.renderText,

Expand Down Expand Up @@ -112,7 +113,7 @@ export default class Markdown extends PureComponent {
table_row: this.renderTableRow,
table_cell: this.renderTableCell,

editedIndicator: this.renderEditedIndicator
editedIndicator: preview ? () => null : this.renderEditedIndicator
},
renderParagraphsInLists: true
});
Expand All @@ -133,12 +134,17 @@ export default class Markdown extends PureComponent {
};

renderText = ({ context, literal }) => {
const { numberOfLines } = this.props;
const { numberOfLines, preview, style = [] } = this.props;
const defaultStyle = [
this.isMessageContainsOnlyEmoji && !preview ? styles.textBig : {},
...context.map(type => styles[type])
];
return (
<Text
style={[
this.isMessageContainsOnlyEmoji ? styles.textBig : styles.text,
...context.map(type => styles[type])
styles.text,
!preview ? defaultStyle : {},
...style
]}
numberOfLines={numberOfLines}
>
Expand All @@ -147,25 +153,30 @@ export default class Markdown extends PureComponent {
);
}

renderCodeInline = ({ literal }) => <Text style={styles.codeInline}>{literal}</Text>;
renderCodeInline = ({ literal }) => {
const { preview } = this.props;
return <Text style={!preview ? styles.codeInline : {}}>{literal}</Text>;
};

renderCodeBlock = ({ literal }) => <Text style={styles.codeBlock}>{literal}</Text>;
renderCodeBlock = ({ literal }) => {
const { preview } = this.props;
return <Text style={!preview ? styles.codeBlock : {}}>{literal}</Text>;
};

renderBreak = () => {
const { tmid } = this.props;
return <Text>{tmid ? ' ' : '\n'}</Text>;
}

renderParagraph = ({ children }) => {
const { numberOfLines, style } = this.props;
if (!children || children.length === 0) {
return null;
}
return (
<View style={styles.block}>
<Text>
{children}
</Text>
</View>
<Text style={style} numberOfLines={numberOfLines}>
{children}
</Text>
);
};

Expand All @@ -176,37 +187,45 @@ export default class Markdown extends PureComponent {
);

renderHashtag = ({ hashtag }) => {
const { channels, navToRoomInfo } = this.props;
const { channels, navToRoomInfo, style } = this.props;
return (
<MarkdownHashtag
hashtag={hashtag}
channels={channels}
navToRoomInfo={navToRoomInfo}
style={style}
/>
);
}

renderAtMention = ({ mentionName }) => {
const { username, mentions, navToRoomInfo } = this.props;
const {
username, mentions, navToRoomInfo, style
} = this.props;
return (
<MarkdownAtMention
mentions={mentions}
mention={mentionName}
username={username}
navToRoomInfo={navToRoomInfo}
style={style}
/>
);
}

renderEmoji = ({ emojiName, literal }) => {
const { getCustomEmoji, baseUrl } = this.props;
const {
getCustomEmoji, baseUrl, customEmojis = true, preview, style
} = this.props;
return (
<MarkdownEmoji
emojiName={emojiName}
literal={literal}
isMessageContainsOnlyEmoji={this.isMessageContainsOnlyEmoji}
isMessageContainsOnlyEmoji={this.isMessageContainsOnlyEmoji && !preview}
getCustomEmoji={getCustomEmoji}
baseUrl={baseUrl}
customEmojis={customEmojis}
style={style}
/>
);
}
Expand All @@ -216,25 +235,30 @@ export default class Markdown extends PureComponent {
renderEditedIndicator = () => <Text style={styles.edited}> ({I18n.t('edited')})</Text>;

renderHeading = ({ children, level }) => {
const { numberOfLines } = this.props;
const textStyle = styles[`heading${ level }Text`];
return (
<Text style={textStyle}>
<Text numberOfLines={numberOfLines} style={textStyle}>
{children}
</Text>
);
};

renderList = ({
children, start, tight, type
}) => (
<MarkdownList
ordered={type !== 'bullet'}
start={start}
tight={tight}
>
{children}
</MarkdownList>
);
}) => {
const { numberOfLines } = this.props;
return (
<MarkdownList
ordered={type !== 'bullet'}
start={start}
tight={tight}
numberOfLines={numberOfLines}
>
{children}
</MarkdownList>
);
};

renderListItem = ({
children, context, ...otherProps
Expand Down Expand Up @@ -269,7 +293,7 @@ export default class Markdown extends PureComponent {

render() {
const {
msg, useMarkdown = true, numberOfLines
msg, useMarkdown = true, numberOfLines, preview = false
} = this.props;

if (!msg) {
Expand All @@ -281,13 +305,18 @@ export default class Markdown extends PureComponent {
// Ex: '[ ](https://open.rocket.chat/group/test?msg=abcdef) Test'
// Return: 'Test'
m = m.replace(/^\[([\s]]*)\]\(([^)]*)\)\s/, '').trim();
m = shortnameToUnicode(m);

if (preview) {
m = m.split('\n').reduce((lines, line) => `${ lines } ${ line }`, '');
}

if (!useMarkdown) {
if (!useMarkdown && !preview) {
return <Text style={styles.text} numberOfLines={numberOfLines}>{m}</Text>;
}

const ast = this.parser.parse(m);
const encodedEmojis = encodeEmojis(m);
const encodedEmojis = toShort(m);
this.isMessageContainsOnlyEmoji = isOnlyEmoji(encodedEmojis) && emojiCount(encodedEmojis) <= 3;

this.editedMessage(ast);
Expand Down
3 changes: 2 additions & 1 deletion app/containers/markdown/styles.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ export default StyleSheet.create({
block: {
alignItems: 'flex-start',
flexDirection: 'row',
flexWrap: 'wrap'
flexWrap: 'wrap',
flex: 1
},
emph: {
fontStyle: 'italic'
Expand Down
1 change: 1 addition & 0 deletions app/containers/message/Content.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const Content = React.memo((props) => {
username={props.user.username}
isEdited={props.isEdited}
numberOfLines={(props.tmid && !props.isThreadRoom) ? 1 : 0}
preview={props.tmid && !props.isThreadRoom}
channels={props.channels}
mentions={props.mentions}
useMarkdown={props.useMarkdown && (!props.tmid || props.isThreadRoom)}
Expand Down
Loading