Skip to content
Permalink
Browse files

Bot message implementation (#1211)

  • Loading branch information...
xcarpentier committed May 21, 2019
1 parent e578df2 commit af7758a935f5fa298befc33261c23155d74afc38
Showing with 3,182 additions and 16,536 deletions.
  1. +8 βˆ’1 .npmignore
  2. +0 βˆ’3 .watchmanconfig
  3. +37 βˆ’16 {example-expo β†’ }/App.js
  4. +92 βˆ’15 README.md
  5. +22 βˆ’0 app.json
  6. +1 βˆ’4 babel.config.js
  7. +21 βˆ’14 example-expo/AccessoryBar.js
  8. +42 βˆ’26 example-expo/CustomActions.js
  9. +32 βˆ’22 example-expo/CustomView.js
  10. +5 βˆ’5 example-expo/NavBar.js
  11. +0 βˆ’36 example-expo/app.json
  12. BIN example-expo/assets/icon.png
  13. BIN example-expo/assets/splash.png
  14. +114 βˆ’60 example-expo/data/messages.js
  15. +0 βˆ’3 example-expo/e2e/config.json
  16. +0 βˆ’52 example-expo/e2e/e2e.spec.js
  17. +0 βˆ’12 example-expo/e2e/init.js
  18. +0 βˆ’22 example-expo/e2e/init.sh
  19. +16 βˆ’16 example-expo/mediaUtils.js
  20. +0 βˆ’21 example-expo/package.json
  21. +0 βˆ’16 example-expo/setPRVersion.js
  22. +0 βˆ’7,924 example-expo/yarn.lock
  23. +0 βˆ’3 example/.babelrc
  24. +0 βˆ’6 example/.buckconfig
  25. +0 βˆ’45 example/.flowconfig
  26. +0 βˆ’1 example/.gitattributes
  27. +0 βˆ’53 example/.gitignore
  28. +0 βˆ’1 example/.watchmanconfig
  29. +0 βˆ’238 example/App.js
  30. +0 βˆ’205 example/CustomActions.js
  31. +0 βˆ’68 example/CustomView.js
  32. +0 βˆ’23 example/README.md
  33. +0 βˆ’65 example/android/app/BUCK
  34. +0 βˆ’147 example/android/app/build.gradle
  35. +0 βˆ’70 example/android/app/proguard-rules.pro
  36. +0 βˆ’33 example/android/app/src/main/AndroidManifest.xml
  37. +0 βˆ’15 example/android/app/src/main/java/com/giftedchat/MainActivity.java
  38. +0 βˆ’42 example/android/app/src/main/java/com/giftedchat/MainApplication.java
  39. BIN example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
  40. BIN example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
  41. BIN example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
  42. BIN example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
  43. +0 βˆ’3 example/android/app/src/main/res/values/strings.xml
  44. +0 βˆ’8 example/android/app/src/main/res/values/styles.xml
  45. +0 βˆ’24 example/android/build.gradle
  46. +0 βˆ’20 example/android/gradle.properties
  47. BIN example/android/gradle/wrapper/gradle-wrapper.jar
  48. +0 βˆ’5 example/android/gradle/wrapper/gradle-wrapper.properties
  49. +0 βˆ’164 example/android/gradlew
  50. +0 βˆ’90 example/android/gradlew.bat
  51. +0 βˆ’8 example/android/keystores/BUCK
  52. +0 βˆ’4 example/android/keystores/debug.keystore.properties
  53. +0 βˆ’6 example/android/settings.gradle
  54. +0 βˆ’4 example/app.json
  55. +0 βˆ’32 example/data/messages.js
  56. +0 βˆ’27 example/data/old_messages.js
  57. +0 βˆ’7 example/index.android.js
  58. +0 βˆ’7 example/index.ios.js
  59. +0 βˆ’54 example/ios/GiftedChat-tvOS/Info.plist
  60. +0 βˆ’24 example/ios/GiftedChat-tvOSTests/Info.plist
  61. +0 βˆ’1,420 example/ios/GiftedChat.xcodeproj/project.pbxproj
  62. +0 βˆ’129 example/ios/GiftedChat.xcodeproj/xcshareddata/xcschemes/GiftedChat-tvOS.xcscheme
  63. +0 βˆ’129 example/ios/GiftedChat.xcodeproj/xcshareddata/xcschemes/GiftedChat.xcscheme
  64. +0 βˆ’16 example/ios/GiftedChat/AppDelegate.h
  65. +0 βˆ’37 example/ios/GiftedChat/AppDelegate.m
  66. +0 βˆ’42 example/ios/GiftedChat/Base.lproj/LaunchScreen.xib
  67. +0 βˆ’38 example/ios/GiftedChat/Images.xcassets/AppIcon.appiconset/Contents.json
  68. +0 βˆ’60 example/ios/GiftedChat/Info.plist
  69. +0 βˆ’18 example/ios/GiftedChat/main.m
  70. +0 βˆ’70 example/ios/GiftedChatTests/GiftedChatTests.m
  71. +0 βˆ’24 example/ios/GiftedChatTests/Info.plist
  72. +0 βˆ’25 example/package.json
  73. +0 βˆ’3,652 example/yarn.lock
  74. +5 βˆ’0 metro.config.js
  75. +15 βˆ’9 package.json
  76. +22 βˆ’1 src/Bubble.tsx
  77. +4 βˆ’1 src/GiftedChat.tsx
  78. +7 βˆ’4 src/Message.tsx
  79. +1 βˆ’0 src/MessageContainer.tsx
  80. +177 βˆ’0 src/QuickReplies.tsx
  81. +0 βˆ’37 src/__tests__/__snapshots__/Message.test.tsx.snap
  82. +13 βˆ’0 src/types.ts
  83. +2,548 βˆ’1,054 yarn.lock
@@ -10,4 +10,11 @@ README.md
ISSUE_TEMPLATE.md
circle.yml
codecov.yml
media/
media/
App.js
app.json
babel.config.js
src/
.expo
tsconfig.json
tslint.json

This file was deleted.

@@ -1,27 +1,22 @@
import { AppLoading, Asset, Linking } from 'expo'
import React, { Component } from 'react'
import { StyleSheet, View } from 'react-native'
import { Bubble, GiftedChat, SystemMessage } from 'react-native-gifted-chat'
import Sentry from 'sentry-expo'
import { StyleSheet, View, Text } from 'react-native'
import { Bubble, GiftedChat, SystemMessage } from './src/'

import AccessoryBar from './AccessoryBar'
import CustomActions from './CustomActions'
import CustomView from './CustomView'
import NavBar from './NavBar'
import messagesData from './data/messages'
import earlierMessages from './data/earlierMessages'

Sentry.config(
'https://2a164b1e89424a5aafc186da811308cb@sentry.io/276804',
).install()
import AccessoryBar from './example-expo/AccessoryBar'
import CustomActions from './example-expo/CustomActions'
import CustomView from './example-expo/CustomView'
import NavBar from './example-expo/NavBar'
import messagesData from './example-expo/data/messages'
import earlierMessages from './example-expo/data/earlierMessages'

const styles = StyleSheet.create({
container: { flex: 1 },
})

const filterBotMessages = message =>
!message.system && message.user && message.user._id && message.user._id === 2
const findStep = step => (_, index) => index === step - 1
const findStep = step => message => message._id === step

const user = {
_id: 1,
@@ -45,7 +40,7 @@ export default class App extends Component {

_isMounted = false

async componentWillMount() {
componentDidMount() {
this._isMounted = true
// init with only system messages
this.setState({
@@ -97,7 +92,7 @@ export default class App extends Component {
botSend = (step = 0) => {
const newMessage = messagesData
.reverse()
.filter(filterBotMessages)
// .filter(filterBotMessages)
.find(findStep(step))
if (newMessage) {
this.setState(previousState => ({
@@ -188,6 +183,31 @@ export default class App extends Component {
return null
}

onQuickReply = replies => {
const createdAt = new Date()
if (replies.length === 1) {
this.onSend([
{
createdAt,
_id: Math.round(Math.random() * 1000000),
text: replies[0].title,
user,
},
])
} else if (replies.length > 1) {
this.onSend([
{
createdAt,
_id: Math.round(Math.random() * 1000000),
text: replies.map(reply => reply.title).join(', '),
user,
},
])
} else {
console.warn('replies param is not set correctly')
}
}

render() {
if (!this.state.appIsReady) {
return <AppLoading />
@@ -208,6 +228,7 @@ export default class App extends Component {
isLoadingEarlier={this.state.isLoadingEarlier}
parsePatterns={this.parsePatterns}
user={user}
onQuickReply={this.onQuickReply}
keyboardShouldPersistTaps='never'
renderAccessory={this.renderAccessory}
renderActions={this.renderCustomActions}
107 README.md
@@ -80,6 +80,7 @@
- InputToolbar avoiding keyboard
- Redux support
- System message
- Quick Reply messages
## Dependency
@@ -102,35 +103,35 @@
## Example
```jsx
import React from "react";
import { GiftedChat } from "react-native-gifted-chat";
import React from 'react'
import { GiftedChat } from 'react-native-gifted-chat'
class Example extends React.Component {
state = {
messages: []
};
messages: [],
}
componentWillMount() {
this.setState({
messages: [
{
_id: 1,
text: "Hello developer",
text: 'Hello developer',
createdAt: new Date(),
user: {
_id: 2,
name: "React Native",
avatar: "https://placeimg.com/140/140/any"
}
}
]
});
name: 'React Native',
avatar: 'https://placeimg.com/140/140/any',
},
},
],
})
}
onSend(messages = []) {
this.setState(previousState => ({
messages: GiftedChat.append(previousState.messages, messages)
}));
messages: GiftedChat.append(previousState.messages, messages),
}))
}
render() {
@@ -139,10 +140,10 @@ class Example extends React.Component {
messages={this.state.messages}
onSend={messages => this.onSend(messages)}
user={{
_id: 1
_id: 1,
}}
/>
);
)
}
}
```
@@ -188,6 +189,80 @@ e.g. System Message
}
```
### e.g. Chat Message with Quick Reply options
See PR [#1211](https://github.com/FaridSafi/react-native-gifted-chat/pull/1211)
```ts
interface Reply {
title: string
value: string
messageId?: any
}
interface QuickReplies {
type: 'radio' | 'checkbox'
values: Reply[]
keepIt?: boolean
}
```
```js
{
_id: 1,
text: 'This is a quick reply. Do you love Gifted Chat? (radio) KEEP IT',
createdAt: new Date(),
quickReplies: {
type: 'radio', // or 'checkbox',
keepIt: true,
values: [
{
title: 'πŸ˜‹ Yes',
value: 'yes',
},
{
title: 'πŸ“· Yes, let me show you with a picture!',
value: 'yes_picture',
},
{
title: '😞 Nope. What?',
value: 'no',
},
],
},
user: {
_id: 2,
name: 'React Native',
},
},
{
_id: 2,
text: 'This is a quick reply. Do you love Gifted Chat? (checkbox)',
createdAt: new Date(),
quickReplies: {
type: 'checkbox', // or 'radio',
values: [
{
title: 'Yes',
value: 'yes',
},
{
title: 'Yes, let me show you with a picture!',
value: 'yes_picture',
},
{
title: 'Nope. What?',
value: 'no',
},
],
},
user: {
_id: 2,
name: 'React Native',
},
}
```
## Props
- **`messages`** _(Array)_ - Messages to display
@@ -259,6 +334,8 @@ e.g. System Message
* **`scrollToBottomComponent`** _(Function)_ - Custom Scroll To Bottom Component container
* **`scrollToBottomOffset`** _(Integer)_ - Custom Height Offset upon which to begin showing Scroll To Bottom Component (Default is 200)
* **`alignTop`** _(Boolean)_ Controls whether or not the message bubbles appear at the top of the chat (Default is false - bubbles align to bottom)
* **`onQuickReply`** _(Function)_ - Callback when sending a quick reply (to backend server)
* **`renderQuickReply`** _(Function)_ - Custom quick reply view

## Imperative methods

@@ -0,0 +1,22 @@
{
"expo": {
"name": "gifted-chat-example",
"description": "Gifted Chat Expo Example",
"slug": "example-expo",
"privacy": "public",
"sdkVersion": "32.0.0",
"platforms": ["ios", "android"],
"version": "0.5.0",
"orientation": "portrait",
"icon": "https://d1wp6m56sqw74a.cloudfront.net/~assets/c9aa1be8a6a6fe81e20c3ac4106a2ebc",
"splash": {
"image": "https://d1wp6m56sqw74a.cloudfront.net/~assets/c9aa1be8a6a6fe81e20c3ac4106a2ebc"
},
"ios": {
"supportsTablet": true
},
"androidStatusBar": {
"backgroundColor": "#000000"
}
}
}
@@ -1,9 +1,6 @@
module.exports = function(api) {
api.cache(true)
return {
presets: [
'module:metro-react-native-babel-preset',
'@babel/preset-typescript',
],
presets: ['babel-preset-expo', '@babel/preset-typescript'],
}
}
@@ -1,29 +1,36 @@
import { MaterialIcons } from '@expo/vector-icons';
import React from 'react';
import { StyleSheet, TouchableOpacity, View } from 'react-native';
import { MaterialIcons } from '@expo/vector-icons'
import React from 'react'
import { StyleSheet, TouchableOpacity, View } from 'react-native'

import { getLocationAsync, pickImageAsync, takePictureAsync } from './mediaUtils';
import {
getLocationAsync,
pickImageAsync,
takePictureAsync,
} from './mediaUtils'

export default class AccessoryBar extends React.Component {

render() {
const { onSend } = this.props;
const { onSend } = this.props
return (
<View style={styles.container}>
<Button onPress={() => pickImageAsync(onSend)} name="photo" />
<Button onPress={() => takePictureAsync(onSend)} name="camera" />
<Button onPress={() => getLocationAsync(onSend)} name="my-location" />
<Button onPress={() => pickImageAsync(onSend)} name='photo' />
<Button onPress={() => takePictureAsync(onSend)} name='camera' />
<Button onPress={() => getLocationAsync(onSend)} name='my-location' />
</View>
);
)
}

}

const Button = ({ onPress, size = 30, color = 'rgba(0,0,0,0.5)', ...props }) => (
const Button = ({
onPress,
size = 30,
color = 'rgba(0,0,0,0.5)',
...props
}) => (
<TouchableOpacity onPress={onPress}>
<MaterialIcons size={size} color={color} {...props} />
</TouchableOpacity>
);
)

const styles = StyleSheet.create({
container: {
@@ -36,4 +43,4 @@ const styles = StyleSheet.create({
borderTopWidth: StyleSheet.hairlineWidth,
borderTopColor: 'rgba(0,0,0,0.3)',
},
});
})

0 comments on commit af7758a

Please sign in to comment.
You can’t perform that action at this time.