Custom emoji

This commit is contained in:
Diego Mello 2018-02-15 17:56:55 -02:00
parent 2966eed8d9
commit 6bd4cd5f9c
3 changed files with 69 additions and 17 deletions

View File

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import { Text, StyleSheet } from 'react-native'; import { Text, StyleSheet, ViewPropTypes } from 'react-native';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import EasyMarkdown from 'react-native-easy-markdown'; // eslint-disable-line import EasyMarkdown from 'react-native-easy-markdown'; // eslint-disable-line
import SimpleMarkdown from 'simple-markdown'; import SimpleMarkdown from 'simple-markdown';
@ -17,13 +17,15 @@ const BlockCode = ({ node, state }) => (
); );
const mentionStyle = { color: '#13679a' }; const mentionStyle = { color: '#13679a' };
const Markdown = ({ msg, customEmojis }) => { const Markdown = ({
msg, customEmojis, style, markdownStyle, customRules, renderInline
}) => {
if (!msg) { if (!msg) {
return null; return null;
} }
msg = emojify(msg, { output: 'unicode' }); msg = emojify(msg, { output: 'unicode' });
const rules = { const defaultRules = {
username: { username: {
order: -1, order: -1,
match: SimpleMarkdown.inlineRegex(/^@[0-9a-zA-Z-_.]+/), match: SimpleMarkdown.inlineRegex(/^@[0-9a-zA-Z-_.]+/),
@ -121,11 +123,13 @@ const Markdown = ({ msg, customEmojis }) => {
}; };
const codeStyle = StyleSheet.flatten(styles.codeStyle); const codeStyle = StyleSheet.flatten(styles.codeStyle);
style = StyleSheet.flatten(style);
return ( return (
<EasyMarkdown <EasyMarkdown
style={{ marginBottom: 0 }} style={{ marginBottom: 0, ...style }}
rules={rules} markdownStyles={{ code: codeStyle, ...markdownStyle }}
markdownStyles={{ code: codeStyle }} rules={{ ...defaultRules, ...customRules }}
renderInline={renderInline}
>{msg} >{msg}
</EasyMarkdown> </EasyMarkdown>
); );
@ -133,7 +137,11 @@ const Markdown = ({ msg, customEmojis }) => {
Markdown.propTypes = { Markdown.propTypes = {
msg: PropTypes.string.isRequired, msg: PropTypes.string.isRequired,
customEmojis: PropTypes.object customEmojis: PropTypes.object,
style: ViewPropTypes.style,
markdownStyle: PropTypes.object,
customRules: PropTypes.object,
renderInline: PropTypes.bool
}; };
BlockCode.propTypes = { BlockCode.propTypes = {

View File

@ -4,9 +4,12 @@ import PropTypes from 'prop-types';
import { View, Text, StyleSheet } from 'react-native'; import { View, Text, StyleSheet } from 'react-native';
import { emojify } from 'react-emojione'; import { emojify } from 'react-emojione';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import SimpleMarkdown from 'simple-markdown';
import Avatar from '../containers/Avatar'; import Avatar from '../containers/Avatar';
import Touch from '../utils/touch/index'; //eslint-disable-line import Touch from '../utils/touch/index'; //eslint-disable-line
import CustomEmoji from '../containers/EmojiPicker/CustomEmoji';
import Markdown from '../containers/message/Markdown';
const styles = StyleSheet.create({ const styles = StyleSheet.create({
container: { container: {
@ -47,10 +50,7 @@ const styles = StyleSheet.create({
lastMessage: { lastMessage: {
flex: 1, flex: 1,
flexShrink: 1, flexShrink: 1,
fontSize: 16,
color: '#444',
marginRight: 8 marginRight: 8
// margin: 0
}, },
alert: { alert: {
fontWeight: 'bold' fontWeight: 'bold'
@ -72,6 +72,36 @@ const styles = StyleSheet.create({
justifyContent: 'center' justifyContent: 'center'
} }
}); });
const markdownStyle = { block: { marginBottom: 0, flexWrap: 'wrap', flexDirection: 'row' } };
const parseInline = (parse, content, state) => {
const isCurrentlyInline = state.inline || false;
state.inline = true;
const result = parse(content, state);
state.inline = isCurrentlyInline;
return result;
};
const parseCaptureInline = (capture, parse, state) => ({ content: parseInline(parse, capture[1], state) });
const customRules = {
strong: {
order: -4,
match: SimpleMarkdown.inlineRegex(/^\*\*([\s\S]+?)\*\*(?!\*)/),
parse: parseCaptureInline,
react: (node, output, state) => ({
type: 'strong',
key: state.key,
props: {
children: output(node.content, state)
}
})
},
text: {
order: -3,
match: SimpleMarkdown.inlineRegex(/^[\s\S]+?(?=[^0-9A-Za-z\s\u00c0-\uffff]|\n\n| {2,}\n|\w+:\S|$)/),
parse: capture => ({ content: capture[0] }),
react: node => node.content
}
}
const renderNumber = (unread, userMentions) => { const renderNumber = (unread, userMentions) => {
if (!unread || unread <= 0) { if (!unread || unread <= 0) {
@ -94,7 +124,8 @@ const renderNumber = (unread, userMentions) => {
}; };
@connect(state => ({ @connect(state => ({
StoreLastMessage: state.settings.Store_Last_Message StoreLastMessage: state.settings.Store_Last_Message,
customEmojis: state.customEmojis
})) }))
export default class RoomItem extends React.PureComponent { export default class RoomItem extends React.PureComponent {
static propTypes = { static propTypes = {
@ -108,7 +139,8 @@ export default class RoomItem extends React.PureComponent {
unread: PropTypes.number, unread: PropTypes.number,
userMentions: PropTypes.number, userMentions: PropTypes.number,
baseUrl: PropTypes.string, baseUrl: PropTypes.string,
onPress: PropTypes.func onPress: PropTypes.func,
customEmojis: PropTypes.object
} }
get icon() { get icon() {
@ -118,14 +150,18 @@ export default class RoomItem extends React.PureComponent {
get lastMessage() { get lastMessage() {
const { const {
lastMessage lastMessage, alert
} = this.props; } = this.props;
if (!this.props.StoreLastMessage) { if (!this.props.StoreLastMessage) {
return ''; return '';
} }
return lastMessage ? `${ lastMessage.u.username }: ${ emojify(lastMessage.msg, { output: 'unicode' }) }` : 'No Message'; let msg = lastMessage ? `${ lastMessage.u.username }: ${ emojify(lastMessage.msg, { output: 'unicode' }) }` : 'No Message';
if (alert) {
msg = `**${ msg }**`;
}
return msg;
} }
formatDate = date => moment(date).calendar(null, { formatDate = date => moment(date).calendar(null, {
@ -137,7 +173,7 @@ export default class RoomItem extends React.PureComponent {
render() { render() {
const { const {
favorite, alert, unread, userMentions, name, _updatedAt favorite, unread, userMentions, name, _updatedAt, customEmojis, baseUrl
} = this.props; } = this.props;
const date = this.formatDate(_updatedAt); const date = this.formatDate(_updatedAt);
@ -165,7 +201,15 @@ export default class RoomItem extends React.PureComponent {
{_updatedAt ? <Text style={styles.update} ellipsizeMode='tail' numberOfLines={1}>{ date }</Text> : null} {_updatedAt ? <Text style={styles.update} ellipsizeMode='tail' numberOfLines={1}>{ date }</Text> : null}
</View> </View>
<View style={styles.row}> <View style={styles.row}>
<Text style={[styles.lastMessage, alert && styles.alert]} ellipsizeMode='tail' numberOfLines={1}>{this.lastMessage}</Text> <Markdown
msg={this.lastMessage}
customEmojis={customEmojis}
baseUrl={baseUrl}
style={styles.lastMessage}
markdownStyle={markdownStyle}
customRules={customRules}
renderInline
/>
{renderNumber(unread, userMentions)} {renderNumber(unread, userMentions)}
</View> </View>
</View> </View>

2
package-lock.json generated
View File

@ -12505,7 +12505,7 @@
} }
}, },
"react-native-easy-markdown": { "react-native-easy-markdown": {
"version": "git+https://github.com/diegolmello/react-native-easy-markdown.git#ed1afe45f870524f6c23a4ca1df97770f0979c74", "version": "git+https://github.com/diegolmello/react-native-easy-markdown.git#600a79faf4fdac2c21cfebeb01f96b997674dabe",
"requires": { "requires": {
"simple-markdown": "0.1.2" "simple-markdown": "0.1.2"
}, },