Skip to content

Commit bbf5fd6

Browse files
authored
Merge pull request #6 from botstar/fix/tu_change-homepage
Added method to boot user into live chat
2 parents ea74ad1 + 6eb984d commit bbf5fd6

File tree

10 files changed

+110
-20
lines changed

10 files changed

+110
-20
lines changed

README.md

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1-
# Chative Widget for React Native
1+
# [Chative.IO](https://chative.io/) Widget for React Native
22

3-
Chative Widget is a React Native component that provides an easy-to-use chat widget for your mobile applications. It allows you to integrate a customizable chat interface with minimal setup.
3+
[Chative.IO](https://chative.io/) Widget is a React Native component that provides an easy-to-use chat widget for your mobile applications. It allows you to integrate a customizable chat interface with minimal setup.
44

55
## Features
66

77
- Customizable chat interface
88
- Easy to show/hide programmatically
99
- Supports custom header components
10+
- Supports filling user information into live chat. (v0.5 or higher)
1011
- Adjustable insets for different device sizes
1112
- TypeScript support
1213

@@ -44,12 +45,24 @@ export default function App() {
4445
// widgetRef.current?.hide();
4546
};
4647

48+
const user = {
49+
user_id: 'UNIQUE_USER_ID',
50+
user: {
51+
email: '[email protected]', // Your user's email address
52+
first_name: 'John',
53+
last_name: 'Doe',
54+
phone: '+1234567890',
55+
custom_field: 'CUSTOMER_FIELD_VALUE' // Replace key and value with your custom field
56+
},
57+
}
58+
4759
return (
4860
<View style={{ flex: 1 }}>
4961
<Button title="Open Chat" onPress={handleOpenChat} />
5062
<ChativeWidget
5163
ref={widgetRef}
5264
channelId="your-channel-id"
65+
user={user} // v0.5 or higher
5366
onClosed={() => console.log('Widget closed')}
5467
onLoaded={() => console.log('Widget loaded')}
5568
onNewMessage={(message) => console.log('New message:', message)}
@@ -64,6 +77,7 @@ export default function App() {
6477
| Prop | Type | Required | Description |
6578
|------|------|----------|-------------|
6679
| channelId | string | Yes | The ID of the chat channel |
80+
| user | ChativeWidgetUser | No | Information about the user, used for booting into live chat.
6781
| headerComponent | ReactElement | No | Custom header component |
6882
| containerStyle | ViewStyle | No | Custom style for the container |
6983
| insetTop | number | No | Top inset (default: 50 for iOS, 20 for Android) |
@@ -98,8 +112,17 @@ You can customize the appearance of the widget by providing a custom header comp
98112
This module includes TypeScript declarations. You can import types like this:
99113
100114
```typescript
101-
import ChativeWidget, { ChativeWidgetRef } from '@chative.io/react-native-widget';
115+
import ChativeWidget, { ChativeWidgetRef, ChativeWidgetUser } from '@chative.io/react-native-widget';
102116
```
117+
### ChativeWidgetUser Interface
118+
| Field | Type | Required | Description |
119+
|---------------|----------|----------|-------------|
120+
| user_id | string | Yes | A unique identifier for the user. This is used to track the user's session in the chat. |
121+
| user.email | string | No | The user's email address. Optional, but recommended for better user identification. |
122+
| user.first_name | string | No | The user's first name. Optional, useful for personalized interactions. |
123+
| user.last_name | string | No | The user's last name. Optional, useful for personalized interactions. |
124+
| user.phone | string | No | The user's phone number. Optional, can be used for follow-up contact. |
125+
| user.[key: string]: any | any | No | Any additional information about the user, represented as key-value pairs. This can be used for custom data. |
103126
104127
## License
105128

examples/App.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,16 @@ export default function App() {
2222
console.log('onNewMessage');
2323
}
2424

25+
const user = {
26+
user_id: 'UNIQUE_USER_ID',
27+
user: {
28+
29+
first_name: 'Chative',
30+
last_name: 'User',
31+
phone: '1234567890',
32+
},
33+
}
34+
2535
return (
2636
<SafeAreaView style={styles.container}>
2737
<View>
@@ -30,6 +40,7 @@ export default function App() {
3040
<ChativeWidget
3141
ref={chativeWidgetRef}
3242
channelId={channelId}
43+
user={user}
3344
onLoaded={onLoaded}
3445
onClosed={handleCloseModal}
3546
onNewMessage={onNewMessage}

examples/app.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212
"backgroundColor": "#ffffff"
1313
},
1414
"ios": {
15-
"supportsTablet": true
15+
"supportsTablet": true,
16+
"bundleIdentifier": "com.example.examples"
1617
},
1718
"android": {
1819
"adaptiveIcon": {

examples/package.json

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,18 @@
77
"android": "expo start --android",
88
"ios": "expo start --ios",
99
"web": "expo start --web",
10-
"livechat": "yarn remove @chative.io/react-native-widget && yarn cache clean && yarn add ../chative.io-react-native-widget-v0.0.1.tgz"
10+
"livechat": "yarn remove @chative.io/react-native-widget || true && yarn cache clean && yarn add ../chative.io-react-native-widget-v0.5.0.tgz"
1111
},
1212
"dependencies": {
13-
"@chative.io/react-native-widget": "../chative.io-react-native-widget-v0.0.1.tgz",
13+
"@chative.io/react-native-widget": "../chative.io-react-native-widget-v0.5.0.tgz",
1414
"@react-native-async-storage/async-storage": "^1.23.1",
15+
"@types/react": "~18.2.79",
1516
"expo": "~51.0.20",
1617
"expo-status-bar": "~1.12.1",
1718
"react": "18.2.0",
1819
"react-native": "0.74.3",
19-
"react-native-webview": "13.8.6"
20+
"react-native-webview": "13.8.6",
21+
"typescript": "~5.3.3"
2022
},
2123
"devDependencies": {
2224
"@babel/core": "^7.20.0"

examples/yarn.lock

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -796,9 +796,9 @@
796796
"@babel/helper-validator-identifier" "^7.24.7"
797797
to-fast-properties "^2.0.0"
798798

799-
"@chative.io/react-native-widget@../chative.io-react-native-widget-v0.0.1.tgz":
800-
version "0.0.1"
801-
resolved "../chative.io-react-native-widget-v0.0.1.tgz#2a83d779d7f53b04c981b12c1f666ce221e6c532"
799+
"@chative.io/react-native-widget@../chative.io-react-native-widget-v0.5.0.tgz":
800+
version "0.5.0"
801+
resolved "../chative.io-react-native-widget-v0.5.0.tgz#b074a980cd915570a5770b8a540949b47b951214"
802802

803803
"@expo/bunyan@^4.0.0":
804804
version "4.0.0"
@@ -1707,6 +1707,19 @@
17071707
dependencies:
17081708
undici-types "~5.26.4"
17091709

1710+
"@types/prop-types@*":
1711+
version "15.7.12"
1712+
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.12.tgz#12bb1e2be27293c1406acb6af1c3f3a1481d98c6"
1713+
integrity sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==
1714+
1715+
"@types/react@~18.2.79":
1716+
version "18.2.79"
1717+
resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.79.tgz#c40efb4f255711f554d47b449f796d1c7756d865"
1718+
integrity sha512-RwGAGXPl9kSXwdNTafkOEuFrTBD5SA2B3iEB96xi8+xu5ddUa/cpvyVCSNn+asgLCTHkb5ZxN8gbuibYJi4s1w==
1719+
dependencies:
1720+
"@types/prop-types" "*"
1721+
csstype "^3.0.2"
1722+
17101723
"@types/stack-utils@^2.0.0":
17111724
version "2.0.3"
17121725
resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.3.tgz#6209321eb2c1712a7e7466422b8cb1fc0d9dd5d8"
@@ -2528,6 +2541,11 @@ crypto-random-string@^2.0.0:
25282541
resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5"
25292542
integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==
25302543

2544+
csstype@^3.0.2:
2545+
version "3.1.3"
2546+
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81"
2547+
integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==
2548+
25312549
dag-map@~1.0.0:
25322550
version "1.0.2"
25332551
resolved "https://registry.yarnpkg.com/dag-map/-/dag-map-1.0.2.tgz#e8379f041000ed561fc515475c1ed2c85eece8d7"
@@ -6247,6 +6265,11 @@ typedarray.prototype.slice@^1.0.3:
62476265
typed-array-buffer "^1.0.2"
62486266
typed-array-byte-offset "^1.0.2"
62496267

6268+
typescript@~5.3.3:
6269+
version "5.3.3"
6270+
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.3.3.tgz#b3ce6ba258e72e6305ba66f5c9b452aaee3ffe37"
6271+
integrity sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==
6272+
62506273
ua-parser-js@^1.0.35:
62516274
version "1.0.38"
62526275
resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-1.0.38.tgz#66bb0c4c0e322fe48edfe6d446df6042e62f25e2"

index.d.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,19 @@ import { ReactElement } from 'react';
44
import { ViewStyle } from 'react-native';
55

66
declare module '@chative.io/react-native-widget' {
7+
export interface ChativeWidgetUser {
8+
user_id: string;
9+
user: {
10+
email?: string;
11+
first_name?: string;
12+
last_name?: string;
13+
phone?: string;
14+
[key: string]: any;
15+
};
16+
}
717
export interface ChativeWidgetProps {
818
channelId: string;
19+
user?: ChativeWidgetUser;
920
headerComponent?: ReactElement;
1021
containerStyle?: ViewStyle;
1122
insetTop?: number;

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@chative.io/react-native-widget",
3-
"version": "0.1.0",
3+
"version": "0.5.0",
44
"description": "React Native SDK for Chative",
55
"main": "index.js",
66
"scripts": {
@@ -70,5 +70,5 @@
7070
"bugs": {
7171
"url": "https://github.com/botstar/chative-react-native-widget/issues"
7272
},
73-
"homepage": "https://github.com/botstar/chative-react-native-widget#readme"
73+
"homepage": "https://chative.io"
7474
}

src/ChativeWidget.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ const propTypes = {
99
channelId: PropTypes.string.isRequired,
1010
headerComponent: PropTypes.element,
1111
containerStyle: PropTypes.object,
12+
user: PropTypes.object || undefined,
1213
insetTop: PropTypes.number,
1314
insetBottom: PropTypes.number,
1415
onClosed: PropTypes.func,
@@ -18,6 +19,7 @@ const propTypes = {
1819

1920
const ChativeWidget = forwardRef(({
2021
channelId,
22+
user,
2123
headerComponent,
2224
containerStyle,
2325
insetTop = Platform.OS === 'ios' ? 50 : 20,
@@ -68,6 +70,7 @@ const ChativeWidget = forwardRef(({
6870
<WebViewComponent
6971
ref={webViewRef}
7072
channelId={channelId}
73+
user={user}
7174
onLoaded={onLoaded}
7275
onNewMessage={onNewMessage}
7376
onClosedWidget={handleClose}
@@ -93,4 +96,4 @@ const styles = StyleSheet.create({
9396

9497
ChativeWidget.propTypes = propTypes;
9598

96-
export default ChativeWidget;
99+
export default React.memo(ChativeWidget);

src/WebView.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,15 @@ import { generateScript, safeParse } from './utils';
77

88
const propTypes = {
99
channelId: PropTypes.string.isRequired,
10+
user: PropTypes.object,
1011
onLoaded: PropTypes.func,
1112
onClosedWidget: PropTypes.func,
1213
onNewMessage: PropTypes.func,
1314
};
1415

15-
const WebViewComponent = forwardRef(({ channelId, onLoaded, onClosedWidget, onNewMessage }, ref) => {
16+
const WebViewComponent = forwardRef(({ channelId, user, onLoaded, onClosedWidget, onNewMessage }, ref) => {
1617
const webViewRef = useRef(null);
17-
18-
const javascript = generateScript();
18+
const javascriptInit = React.useMemo(() => generateScript(user), [user]);
1919

2020
useImperativeHandle(ref, () => ({
2121
injectJavaScript: (script) => {
@@ -31,10 +31,10 @@ const WebViewComponent = forwardRef(({ channelId, onLoaded, onClosedWidget, onNe
3131
ref={webViewRef}
3232
style={styles.webViewContainer}
3333
source={{
34-
uri: `${WIDGET_URL}/${channelId}?mode=livechat`,
34+
uri: `${WIDGET_URL}/${channelId}?mode=livechat&state=${user ? 'off' : 'on'}`,
3535
}}
3636
onLoadEnd={() => {
37-
webViewRef.current?.injectJavaScript(javascript);
37+
webViewRef.current?.injectJavaScript(javascriptInit);
3838
onLoaded && onLoaded();
3939
}}
4040
onMessage={(event) => {

src/utils.js

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
export const generateScript = () => {
1+
export const generateScript = (user = {}) => {
2+
const userString = safeStringify(user);
23
return `
34
window.cti_api = function (action, data) {
45
if (window.ChativeApi) {
@@ -7,7 +8,14 @@ export const generateScript = () => {
78
89
window.ChativeEvents ||= [];
910
window.ChativeEvents.push([action, data]);
11+
};
12+
13+
const user = ${userString};
14+
15+
if (user.user_id) {
16+
window.cti_api('boot', JSON.parse('${userString}'));
1017
}
18+
1119
window.cti_api('openChatWindow');
1220
window.cti_api('addEventListener', { event: 'closed', callback: () => {
1321
window.cti_api('hide');
@@ -22,7 +30,7 @@ export const generateScript = () => {
2230

2331
export const WidgetApi = (event, data) => {
2432
return `
25-
window.cti_api('${event}', ${JSON.stringify(data)});
33+
window.cti_api('${event}', ${data});
2634
`;
2735
};
2836

@@ -33,3 +41,11 @@ export const safeParse = (jsonString) => {
3341
return {};
3442
}
3543
};
44+
45+
export const safeStringify = (data) => {
46+
try {
47+
return JSON.stringify(data);
48+
} catch (e) {
49+
return '{}';
50+
}
51+
}

0 commit comments

Comments
 (0)