Skip to content

Commit

Permalink
feat MessageText FC
Browse files Browse the repository at this point in the history
  • Loading branch information
xcarpentier committed May 12, 2020
1 parent 5c26684 commit 5f36fc4
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 97 deletions.
4 changes: 2 additions & 2 deletions src/Bubble.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {

import QuickReplies from './QuickReplies'

import MessageText from './MessageText'
import { MessageText, MessageTextProps } from './MessageText'
import MessageImage from './MessageImage'
import MessageVideo from './MessageVideo'
import MessageAudio from './MessageAudio'
Expand Down Expand Up @@ -127,7 +127,7 @@ export type RenderMessageTextProps<TMessage extends IMessage> = Omit<
BubbleProps<TMessage>,
'containerStyle' | 'wrapperStyle'
> &
MessageText['props']
MessageTextProps<TMessage>

export interface BubbleProps<TMessage extends IMessage> {
user?: User
Expand Down
6 changes: 2 additions & 4 deletions src/GiftedChat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import Avatar from './Avatar'
import Bubble from './Bubble'
import SystemMessage from './SystemMessage'
import MessageImage from './MessageImage'
import MessageText from './MessageText'
import { MessageText, MessageTextProps } from './MessageText'
import Composer from './Composer'
import { Day, DayProps } from './Day'
import InputToolbar from './InputToolbar'
Expand Down Expand Up @@ -164,9 +164,7 @@ export interface GiftedChatProps<TMessage extends IMessage = IMessage> {
/*Custom message container */
renderMessage?(message: Message<TMessage>['props']): React.ReactNode
/* Custom message text */
renderMessageText?(
messageText: MessageText<TMessage>['props'],
): React.ReactNode
renderMessageText?(messageText: MessageTextProps<TMessage>): React.ReactNode
/* Custom message image */
renderMessageImage?(props: MessageImage<TMessage>['props']): React.ReactNode
/* Custom view inside the bubble */
Expand Down
188 changes: 97 additions & 91 deletions src/MessageText.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,20 @@ import ParsedText from 'react-native-parsed-text'
import Communications from 'react-native-communications'
import { LeftRightStyle, IMessage } from './Models'
import { StylePropType } from './utils'
import { useChatContext } from './GiftedChatContext'

const WWW_URL_PATTERN = /^www\./i

const textStyle = {
fontSize: 16,
lineHeight: 20,
marginTop: 5,
marginBottom: 5,
marginLeft: 10,
marginRight: 10,
}
const { textStyle } = StyleSheet.create({
textStyle: {
fontSize: 16,
lineHeight: 20,
marginTop: 5,
marginBottom: 5,
marginLeft: 10,
marginRight: 10,
},
})

const styles = {
left: StyleSheet.create({
Expand Down Expand Up @@ -66,61 +69,33 @@ export interface MessageTextProps<TMessage extends IMessage> {
parsePatterns?(linkStyle: TextStyle): any
}

export default class MessageText<
TMessage extends IMessage = IMessage
> extends React.Component<MessageTextProps<TMessage>> {
static contextTypes = {
actionSheet: PropTypes.func,
}

static defaultProps = {
position: 'left',
optionTitles: DEFAULT_OPTION_TITLES,
currentMessage: {
text: '',
},
containerStyle: {},
textStyle: {},
linkStyle: {},
customTextStyle: {},
textProps: {},
parsePatterns: () => [],
}

static propTypes = {
position: PropTypes.oneOf(['left', 'right']),
optionTitles: PropTypes.arrayOf(PropTypes.string),
currentMessage: PropTypes.object,
containerStyle: PropTypes.shape({
left: StylePropType,
right: StylePropType,
}),
textStyle: PropTypes.shape({
left: StylePropType,
right: StylePropType,
}),
linkStyle: PropTypes.shape({
left: StylePropType,
right: StylePropType,
}),
parsePatterns: PropTypes.func,
textProps: PropTypes.object,
customTextStyle: StylePropType,
}
export const MessageText = <TMessage extends IMessage = IMessage>({
currentMessage,
optionTitles,
position,
containerStyle,
textStyle,
linkStyle: linkStyleProp,
customTextStyle,
parsePatterns,
textProps,
}: MessageTextProps<TMessage>) => {
const { actionSheet } = useChatContext()

shouldComponentUpdate(nextProps: MessageTextProps<TMessage>) {
return (
!!this.props.currentMessage &&
!!nextProps.currentMessage &&
this.props.currentMessage.text !== nextProps.currentMessage.text
)
}
// TODO: React.memo
// const shouldComponentUpdate = (nextProps: MessageTextProps<TMessage>) => {
// return (
// !!currentMessage &&
// !!nextProps.currentMessage &&
// currentMessage.text !== nextProps.currentMessage.text
// )
// }

onUrlPress = (url: string) => {
const onUrlPress = (url: string) => {
// When someone sends a message that includes a website address beginning with "www." (omitting the scheme),
// react-native-parsed-text recognizes it as a valid url, but Linking fails to open due to the missing scheme.
if (WWW_URL_PATTERN.test(url)) {
this.onUrlPress(`http://${url}`)
onUrlPress(`http://${url}`)
} else {
Linking.canOpenURL(url).then(supported => {
if (!supported) {
Expand All @@ -132,14 +107,13 @@ export default class MessageText<
}
}

onPhonePress = (phone: string) => {
const { optionTitles } = this.props
const onPhonePress = (phone: string) => {
const options =
optionTitles && optionTitles.length > 0
? optionTitles.slice(0, 3)
: DEFAULT_OPTION_TITLES
const cancelButtonIndex = options.length - 1
this.context.actionSheet().showActionSheetWithOptions(
actionSheet().showActionSheetWithOptions(
{
options,
cancelButtonIndex,
Expand All @@ -159,39 +133,71 @@ export default class MessageText<
)
}

onEmailPress = (email: string) =>
const onEmailPress = (email: string) =>
Communications.email([email], null, null, null, null)

render() {
const linkStyle = [
styles[this.props.position].link,
this.props.linkStyle && this.props.linkStyle[this.props.position],
]
return (
<View
const linkStyle = [
styles[position].link,
linkStyleProp && linkStyleProp[position],
]
return (
<View
style={[
styles[position].container,
containerStyle && containerStyle[position],
]}
>
<ParsedText
style={[
styles[this.props.position].container,
this.props.containerStyle &&
this.props.containerStyle[this.props.position],
styles[position].text,
textStyle && textStyle[position],
customTextStyle,
]}
parse={[
...parsePatterns!(linkStyle as TextStyle),
{ type: 'url', style: linkStyle, onPress: onUrlPress },
{ type: 'phone', style: linkStyle, onPress: onPhonePress },
{ type: 'email', style: linkStyle, onPress: onEmailPress },
]}
childrenProps={{ ...textProps }}
>
<ParsedText
style={[
styles[this.props.position].text,
this.props.textStyle && this.props.textStyle[this.props.position],
this.props.customTextStyle,
]}
parse={[
...this.props.parsePatterns!(linkStyle as TextStyle),
{ type: 'url', style: linkStyle, onPress: this.onUrlPress },
{ type: 'phone', style: linkStyle, onPress: this.onPhonePress },
{ type: 'email', style: linkStyle, onPress: this.onEmailPress },
]}
childrenProps={{ ...this.props.textProps }}
>
{this.props.currentMessage!.text}
</ParsedText>
</View>
)
}
{currentMessage!.text}
</ParsedText>
</View>
)
}

MessageText.defaultProps = {
position: 'left',
optionTitles: DEFAULT_OPTION_TITLES,
currentMessage: {
text: '',
},
containerStyle: {},
textStyle: {},
linkStyle: {},
customTextStyle: {},
textProps: {},
parsePatterns: () => [],
}

MessageText.propTypes = {
position: PropTypes.oneOf(['left', 'right']),
optionTitles: PropTypes.arrayOf(PropTypes.string),
currentMessage: PropTypes.object,
containerStyle: PropTypes.shape({
left: StylePropType,
right: StylePropType,
}),
textStyle: PropTypes.shape({
left: StylePropType,
right: StylePropType,
}),
linkStyle: PropTypes.shape({
left: StylePropType,
right: StylePropType,
}),
parsePatterns: PropTypes.func,
textProps: PropTypes.object,
customTextStyle: StylePropType,
}

0 comments on commit 5f36fc4

Please sign in to comment.