Skip to content

Commit 52b3055

Browse files
committed
fix: display emoji in private messages
1 parent 3b77008 commit 52b3055

File tree

2 files changed

+163
-0
lines changed

2 files changed

+163
-0
lines changed
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
// This component is <MessageText /> from react-native-gifted-chat 0.3.0,
2+
// just use `parseContentWithEmoji` to parse emoji in message text.
3+
4+
import PropTypes from 'prop-types';
5+
import React from 'react';
6+
import {
7+
Linking,
8+
StyleSheet,
9+
Text,
10+
View,
11+
ViewPropTypes,
12+
} from 'react-native';
13+
import { parseContentWithEmoji } from '../../utils/contentParser';
14+
15+
import ParsedText from 'react-native-parsed-text';
16+
import Communications from 'react-native-communications';
17+
18+
const WWW_URL_PATTERN = /^www\./i;
19+
20+
export default class MessageText extends React.Component {
21+
constructor(props) {
22+
super(props);
23+
this.onUrlPress = this.onUrlPress.bind(this);
24+
this.onPhonePress = this.onPhonePress.bind(this);
25+
this.onEmailPress = this.onEmailPress.bind(this);
26+
}
27+
28+
onUrlPress(url) {
29+
// When someone sends a message that includes a website address beginning with "www." (omitting the scheme),
30+
// react-native-parsed-text recognizes it as a valid url, but Linking fails to open due to the missing scheme.
31+
if (WWW_URL_PATTERN.test(url)) {
32+
this.onUrlPress(`http://${url}`);
33+
} else {
34+
Linking.canOpenURL(url).then((supported) => {
35+
if (!supported) {
36+
console.error('No handler for URL:', url);
37+
} else {
38+
Linking.openURL(url);
39+
}
40+
});
41+
}
42+
}
43+
44+
onPhonePress(phone) {
45+
const options = [
46+
'Call',
47+
'Text',
48+
'Cancel',
49+
];
50+
const cancelButtonIndex = options.length - 1;
51+
this.context.actionSheet().showActionSheetWithOptions({
52+
options,
53+
cancelButtonIndex,
54+
},
55+
(buttonIndex) => {
56+
switch (buttonIndex) {
57+
case 0:
58+
Communications.phonecall(phone, true);
59+
break;
60+
case 1:
61+
Communications.text(phone);
62+
break;
63+
}
64+
});
65+
}
66+
67+
onEmailPress(email) {
68+
Communications.email([email], null, null, null, null);
69+
}
70+
71+
render() {
72+
const linkStyle = StyleSheet.flatten([styles[this.props.position].link, this.props.linkStyle[this.props.position]]);
73+
return (
74+
<View style={[styles[this.props.position].container, this.props.containerStyle[this.props.position]]}>
75+
<ParsedText
76+
style={[styles[this.props.position].text, this.props.textStyle[this.props.position], this.props.customTextStyle]}
77+
parse={[
78+
...this.props.parsePatterns(linkStyle),
79+
{type: 'url', style: linkStyle, onPress: this.onUrlPress},
80+
{type: 'phone', style: linkStyle, onPress: this.onPhonePress},
81+
{type: 'email', style: linkStyle, onPress: this.onEmailPress},
82+
]}
83+
childrenProps={{...this.props.textProps}}
84+
>
85+
{parseContentWithEmoji(this.props.currentMessage.text)}
86+
</ParsedText>
87+
</View>
88+
);
89+
}
90+
}
91+
92+
const textStyle = {
93+
fontSize: 16,
94+
lineHeight: 20,
95+
marginTop: 5,
96+
marginBottom: 5,
97+
marginLeft: 10,
98+
marginRight: 10,
99+
};
100+
101+
const styles = {
102+
left: StyleSheet.create({
103+
container: {
104+
},
105+
text: {
106+
color: 'black',
107+
...textStyle,
108+
},
109+
link: {
110+
color: 'black',
111+
textDecorationLine: 'underline',
112+
},
113+
}),
114+
right: StyleSheet.create({
115+
container: {
116+
},
117+
text: {
118+
color: 'white',
119+
...textStyle,
120+
},
121+
link: {
122+
color: 'white',
123+
textDecorationLine: 'underline',
124+
},
125+
}),
126+
};
127+
128+
MessageText.contextTypes = {
129+
actionSheet: PropTypes.func,
130+
};
131+
132+
MessageText.defaultProps = {
133+
position: 'left',
134+
currentMessage: {
135+
text: '',
136+
},
137+
containerStyle: {},
138+
textStyle: {},
139+
linkStyle: {},
140+
parsePatterns: () => [],
141+
};
142+
143+
MessageText.propTypes = {
144+
position: PropTypes.oneOf(['left', 'right']),
145+
currentMessage: PropTypes.object,
146+
containerStyle: PropTypes.shape({
147+
left: ViewPropTypes.style,
148+
right: ViewPropTypes.style,
149+
}),
150+
textStyle: PropTypes.shape({
151+
left: Text.propTypes.style,
152+
right: Text.propTypes.style,
153+
}),
154+
linkStyle: PropTypes.shape({
155+
left: Text.propTypes.style,
156+
right: Text.propTypes.style,
157+
}),
158+
parsePatterns: PropTypes.func,
159+
textProps: PropTypes.object,
160+
customTextStyle: Text.propTypes.style,
161+
};

src/containers/PmList.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import LoadingSpinner from '../components/LoadingSpinner';
1111
import { GiftedChat } from 'react-native-gifted-chat';
1212
import GiftedChatSendButton from '../components/3rd_party/GiftedChatSendButton';
1313
import GiftedChatLoadEarlierButton from '../components/3rd_party/GiftedChatLoadEarlierButton';
14+
import GiftedChatMessageText from '../components/3rd_party/GiftedChatMessageText';
1415
import {
1516
submit,
1617
resetPublish
@@ -192,6 +193,7 @@ class PmList extends Component {
192193
})}
193194
renderSend={props => <GiftedChatSendButton {...props} />}
194195
renderLoadEarlier={props => <GiftedChatLoadEarlierButton {...props} />}
196+
renderMessageText={props => <GiftedChatMessageText {...props} />}
195197
renderTicks={message => {
196198
if (!message.isNew) { return; }
197199

0 commit comments

Comments
 (0)