Skip to content

Commit

Permalink
Update imports for quick replies
Browse files Browse the repository at this point in the history
  • Loading branch information
danielmejiadev authored and xcarpentier committed Jun 26, 2020
1 parent cdee34b commit c814443
Show file tree
Hide file tree
Showing 2 changed files with 119 additions and 138 deletions.
4 changes: 2 additions & 2 deletions src/GiftedChat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import MessageContainer from './MessageContainer'
import { Send, SendProps } from './Send'
import { GiftedChatContext } from './GiftedChatContext'
import { Time, TimeProps } from './Time'
import { QuickRepliesProps } from './QuickReplies'
import GiftedAvatar from './GiftedAvatar'

import {
Expand All @@ -48,7 +49,6 @@ import {
DATE_FORMAT,
} from './Constant'
import { IMessage, User, Reply, LeftRightStyle } from './Models'
import QuickReplies from './QuickReplies'

dayjs.extend(localizedFormat)

Expand Down Expand Up @@ -196,7 +196,7 @@ export interface GiftedChatProps<TMessage extends IMessage = IMessage> {
/* Custom parse patterns for react-native-parsed-text used to linking message content (like URLs and phone numbers) */
parsePatterns?(linkStyle: TextStyle): any
onQuickReply?(replies: Reply[]): void
renderQuickReplies?(quickReplies: QuickReplies['props']): React.ReactNode
renderQuickReplies?(quickReplies: QuickRepliesProps): React.ReactNode
renderQuickReplySend?(): React.ReactNode
/* Scroll to bottom custom component */
scrollToBottomComponent?(): React.ReactNode
Expand Down
253 changes: 117 additions & 136 deletions src/QuickReplies.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import PropTypes from 'prop-types'
import React, { Component } from 'react'
import React, { useState, useMemo } from 'react'
import {
Text,
StyleSheet,
Expand All @@ -11,6 +11,7 @@ import {
import { IMessage, Reply } from './Models'
import Color from './Color'
import { warning, StylePropType } from './utils'
import { useCallbackOne } from 'use-memo-one'

const styles = StyleSheet.create({
container: {
Expand Down Expand Up @@ -52,164 +53,144 @@ export interface QuickRepliesProps {
renderQuickReplySend?(): React.ReactNode
}

export interface QuickRepliesState {
replies: Reply[]
}

const sameReply = (currentReply: Reply) => (reply: Reply) =>
currentReply.value === reply.value

const diffReply = (currentReply: Reply) => (reply: Reply) =>
currentReply.value !== reply.value

export default class QuickReplies extends Component<
QuickRepliesProps,
QuickRepliesState
> {
static defaultProps = {
currentMessage: {
quickReplies: [],
},
onQuickReply: () => {},
color: Color.peterRiver,
sendText: 'Send',
keepReplies: false,
renderQuickReplySend: undefined,
quickReplyStyle: undefined,
}

static propTypes = {
currentMessage: PropTypes.object.isRequired,
onQuickReply: PropTypes.func,
color: PropTypes.string,
sendText: PropTypes.string,
keepReplies: PropTypes.bool,
renderQuickReplySend: PropTypes.func,
quickReplyStyle: StylePropType,
}

state = {
replies: [],
}

handlePress = (reply: Reply) => () => {
const { currentMessage } = this.props
const { replies } = this.state
if (currentMessage) {
const { type } = currentMessage.quickReplies!
switch (type) {
case 'radio': {
this.handleSend([reply])()
return
}

case 'checkbox': {
if (replies.find(sameReply(reply))) {
this.setState({
replies: this.state.replies.filter(diffReply(reply)),
})
} else {
this.setState({ replies: [...this.state.replies, reply] })
}
return
}

default: {
warning(`onQuickReply unknown type: ${type}`)
return
}
}
}
}

handleSend = (replies: Reply[]) => () => {
const { currentMessage } = this.props
if (this.props.onQuickReply) {
this.props.onQuickReply(
replies.map((reply: Reply) => ({
...reply,
messageId: currentMessage!._id,
})),
)
}
}

shouldComponentDisplay = () => {
const { currentMessage, nextMessage } = this.props
export function QuickReplies(props: QuickRepliesProps) {
const {
currentMessage,
nextMessage,
color,
quickReplyStyle,
onQuickReply,
sendText,
renderQuickReplySend,
} = props
const { type } = currentMessage!.quickReplies!
const [replies, setReplies] = useState<Reply[]>([])

const shouldComponentDisplay = useMemo(() => {
const hasReplies = !!currentMessage && !!currentMessage!.quickReplies
const hasNext = !!nextMessage && !!nextMessage!._id
const keepIt = currentMessage!.quickReplies!.keepIt

if (hasReplies && !hasNext) {
return true
}

if (hasReplies && hasNext && keepIt) {
return true
}

return false
}, [currentMessage, nextMessage])

if (!shouldComponentDisplay) {
return null
}

renderQuickReplySend = () => {
const { replies } = this.state
const { sendText, renderQuickReplySend: customSend } = this.props

return (
<TouchableOpacity
style={[styles.quickReply, styles.sendLink]}
onPress={this.handleSend(replies)}
>
{customSend ? (
customSend()
) : (
<Text style={styles.sendLinkText}>{sendText}</Text>
)}
</TouchableOpacity>
const handlePress = useCallbackOne(
(reply: Reply) => () => {
if (currentMessage) {
const { type } = currentMessage.quickReplies!
switch (type) {
case 'radio': {
handleSend([reply])()
return
}
case 'checkbox': {
if (replies.find(sameReply(reply))) {
setReplies(replies.filter(diffReply(reply)))
} else {
setReplies([...replies, reply])
}
return
}
default: {
warning(`onQuickReply unknown type: ${type}`)
return
}
}
}
},
[replies, currentMessage],
)

const handleSend = (repliesData: Reply[]) => () => {
onQuickReply?.(
repliesData.map((reply: Reply) => ({
...reply,
messageId: currentMessage!._id,
})),
)
}

render() {
const { currentMessage, color, quickReplyStyle } = this.props
const { replies } = this.state

if (!this.shouldComponentDisplay()) {
return null
}

const { type } = currentMessage!.quickReplies!

return (
<View style={styles.container}>
{currentMessage!.quickReplies!.values.map(
(reply: Reply, index: number) => {
const selected =
type === 'checkbox' && replies.find(sameReply(reply))
return (
<TouchableOpacity
onPress={this.handlePress(reply)}
return (
<View style={styles.container}>
{currentMessage!.quickReplies!.values.map(
(reply: Reply, index: number) => {
const selected = type === 'checkbox' && replies.find(sameReply(reply))

return (
<TouchableOpacity
onPress={handlePress(reply)}
style={[
styles.quickReply,
quickReplyStyle,
{ borderColor: color },
selected && { backgroundColor: color },
]}
key={`${reply.value}-${index}`}
>
<Text
numberOfLines={10}
ellipsizeMode={'tail'}
style={[
styles.quickReply,
quickReplyStyle,
{ borderColor: color },
selected && { backgroundColor: color },
styles.quickReplyText,
{ color: selected ? Color.white : color },
]}
key={`${reply.value}-${index}`}
>
<Text
numberOfLines={10}
ellipsizeMode={'tail'}
style={[
styles.quickReplyText,
{ color: selected ? Color.white : color },
]}
>
{reply.title}
</Text>
</TouchableOpacity>
)
},
)}
{replies.length > 0 && this.renderQuickReplySend()}
</View>
)
}
{reply.title}
</Text>
</TouchableOpacity>
)
},
)}
{replies.length > 0 && (
<TouchableOpacity
style={[styles.quickReply, styles.sendLink]}
onPress={handleSend(replies)}
>
{renderQuickReplySend?.() || (
<Text style={styles.sendLinkText}>{sendText}</Text>
)}
</TouchableOpacity>
)}
</View>
)
}

QuickReplies.defaultProps = {
currentMessage: {
quickReplies: [],
},
onQuickReply: () => {},
color: Color.peterRiver,
sendText: 'Send',
keepReplies: false,
renderQuickReplySend: undefined,
quickReplyStyle: undefined,
}

QuickReplies.propTypes = {
currentMessage: PropTypes.object.isRequired,
onQuickReply: PropTypes.func,
color: PropTypes.string,
sendText: PropTypes.string,
keepReplies: PropTypes.bool,
renderQuickReplySend: PropTypes.func,
quickReplyStyle: StylePropType,
}

0 comments on commit c814443

Please sign in to comment.