rn-erxes-sdk 0.3.3 → 0.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +117 -2
- package/docs/native-ios.md +5 -0
- package/lib/commonjs/ErxesMessenger.js +160 -0
- package/lib/commonjs/ErxesMessenger.js.map +1 -0
- package/lib/commonjs/index.js +7 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/module/ErxesMessenger.js +155 -0
- package/lib/module/ErxesMessenger.js.map +1 -0
- package/lib/module/index.js +1 -0
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/ErxesMessenger.d.ts +86 -0
- package/lib/typescript/ErxesMessenger.d.ts.map +1 -0
- package/lib/typescript/index.d.ts +2 -0
- package/lib/typescript/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/ErxesMessenger.tsx +237 -0
- package/src/index.tsx +8 -0
package/README.md
CHANGED
|
@@ -127,9 +127,15 @@ Supports the classic widget and the full-screen **chat mode** (with voice
|
|
|
127
127
|
messages and header/drawer actions).
|
|
128
128
|
|
|
129
129
|
```tsx
|
|
130
|
-
import {
|
|
130
|
+
import { ErxesMessenger } from 'rn-erxes-sdk';
|
|
131
131
|
```
|
|
132
132
|
|
|
133
|
+
Two APIs are exported:
|
|
134
|
+
|
|
135
|
+
- **`<ErxesMessenger />`** — a declarative React component that handles configure,
|
|
136
|
+
user identity, action taps, and the show/hide lifecycle. Recommended for most apps.
|
|
137
|
+
- **`ErxesNativeIOS`** — the low-level native bridge for advanced/imperative control.
|
|
138
|
+
|
|
133
139
|
## Requirements
|
|
134
140
|
|
|
135
141
|
| | |
|
|
@@ -174,7 +180,116 @@ cd ios && pod install
|
|
|
174
180
|
npx expo run:ios
|
|
175
181
|
```
|
|
176
182
|
|
|
177
|
-
## Usage
|
|
183
|
+
## Usage — `<ErxesMessenger />` (recommended)
|
|
184
|
+
|
|
185
|
+
Render the component where the messenger should be active. It configures the SDK on
|
|
186
|
+
mount, dispatches action taps to your `onPress` handlers, and hides the messenger on
|
|
187
|
+
unmount. It renders nothing — the messenger UI is presented natively over your app.
|
|
188
|
+
|
|
189
|
+
```tsx
|
|
190
|
+
import { ErxesMessenger } from 'rn-erxes-sdk';
|
|
191
|
+
|
|
192
|
+
<ErxesMessenger
|
|
193
|
+
integrationId="YOUR_INTEGRATION_ID"
|
|
194
|
+
subDomain="yourcompany.erxes.io"
|
|
195
|
+
user={{ name: 'Jane Doe', email: 'user@example.com' }}
|
|
196
|
+
/>
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
### Example 1 — Classic floating launcher
|
|
200
|
+
|
|
201
|
+
Shows a draggable button over your app. Tapping it opens the messenger.
|
|
202
|
+
|
|
203
|
+
```tsx
|
|
204
|
+
<ErxesMessenger
|
|
205
|
+
integrationId={INTEGRATION_ID}
|
|
206
|
+
endpoint={ENDPOINT}
|
|
207
|
+
displayMode="classic"
|
|
208
|
+
launcherVisible
|
|
209
|
+
user={CURRENT_USER}
|
|
210
|
+
/>
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### Example 2 — Home screen full-screen chat
|
|
214
|
+
|
|
215
|
+
Chat mode opens full-screen and auto-opens when connected. Bind `visible` to screen
|
|
216
|
+
focus so the messenger shows/hides as the user navigates, and add a header action to
|
|
217
|
+
jump to another screen.
|
|
218
|
+
|
|
219
|
+
```tsx
|
|
220
|
+
const isFocused = useIsFocused();
|
|
221
|
+
|
|
222
|
+
<ErxesMessenger
|
|
223
|
+
visible={isFocused}
|
|
224
|
+
integrationId={INTEGRATION_ID}
|
|
225
|
+
endpoint={ENDPOINT}
|
|
226
|
+
displayMode="chat"
|
|
227
|
+
user={CURRENT_USER}
|
|
228
|
+
homeActions={[
|
|
229
|
+
{
|
|
230
|
+
id: 'profile',
|
|
231
|
+
title: 'Profile',
|
|
232
|
+
systemIcon: 'person.crop.circle',
|
|
233
|
+
onPress: async ({ hide }) => {
|
|
234
|
+
await hide();
|
|
235
|
+
navigation.navigate('Profile', { user: CURRENT_USER });
|
|
236
|
+
},
|
|
237
|
+
},
|
|
238
|
+
]}
|
|
239
|
+
/>
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### Example 3 — Settings → Support screen with a close button
|
|
243
|
+
|
|
244
|
+
Open chat on mount, hide it on unmount, and add an `X` action that closes the
|
|
245
|
+
messenger and pops the screen.
|
|
246
|
+
|
|
247
|
+
```tsx
|
|
248
|
+
<ErxesMessenger
|
|
249
|
+
integrationId={INTEGRATION_ID}
|
|
250
|
+
endpoint={ENDPOINT}
|
|
251
|
+
displayMode="chat"
|
|
252
|
+
autoOpen
|
|
253
|
+
autoHideOnUnmount
|
|
254
|
+
user={CURRENT_USER}
|
|
255
|
+
homeActions={[
|
|
256
|
+
{
|
|
257
|
+
id: 'close',
|
|
258
|
+
title: 'Close',
|
|
259
|
+
systemIcon: 'xmark',
|
|
260
|
+
onPress: async ({ hide }) => {
|
|
261
|
+
await hide();
|
|
262
|
+
navigation.goBack();
|
|
263
|
+
},
|
|
264
|
+
},
|
|
265
|
+
]}
|
|
266
|
+
onReady={() => console.log('erxes messenger ready')}
|
|
267
|
+
onError={(error) => console.log('erxes messenger error', error)}
|
|
268
|
+
/>
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
### Props
|
|
272
|
+
|
|
273
|
+
| Prop | Type | Notes |
|
|
274
|
+
|---|---|---|
|
|
275
|
+
| `integrationId` | `string` | Required. |
|
|
276
|
+
| `endpoint` / `serverUrl` / `subDomain` | `string` | Provide one. `subDomain` accepts `'company.erxes.io'`. |
|
|
277
|
+
| `displayMode` | `'classic' \| 'chat'` | Defaults to `'classic'`. |
|
|
278
|
+
| `user` | `ErxesUser` | `{ name?, email?, phone?, customData? }`. |
|
|
279
|
+
| `cachedCustomerId` | `string` | Reuse a cached customer. |
|
|
280
|
+
| `primaryColor` | `string` | Hex accent, e.g. `'#3f78d9'`. |
|
|
281
|
+
| `visible` | `boolean` | Controlled show/hide on change. |
|
|
282
|
+
| `autoOpen` | `boolean` | Open after configure. Defaults to `true` in chat mode. |
|
|
283
|
+
| `autoHideOnUnmount` | `boolean` | Hide on unmount. Defaults to `true`. |
|
|
284
|
+
| `launcherVisible` | `boolean` | Show/hide the floating launcher after configure. |
|
|
285
|
+
| `homeActions` / `drawerActions` | `ErxesAction[]` | `{ id, title, systemIcon, onPress? }`. Chat mode only. |
|
|
286
|
+
| `onLoad` / `onReady` / `onOpen` / `onClose` / `onError` | callbacks | Lifecycle events. |
|
|
287
|
+
| `onAction` | `(id, helpers) => void` | Fallback for tapped actions with no `onPress`. |
|
|
288
|
+
|
|
289
|
+
Action `onPress` (and `onAction`) receive `ErxesMessengerHelpers`:
|
|
290
|
+
`show`, `hide`, `showLauncher`, `hideLauncher`, `setUser`, `clearUser`.
|
|
291
|
+
|
|
292
|
+
## Advanced — `ErxesNativeIOS` (low-level)
|
|
178
293
|
|
|
179
294
|
Call `configure` once at startup. It connects in the background so the messenger opens instantly.
|
|
180
295
|
|
package/docs/native-ios.md
CHANGED
|
@@ -4,6 +4,11 @@
|
|
|
4
4
|
([`erxes/erxes-ios-sdk`](https://github.com/erxes/erxes-ios-sdk) `0.30.7`)
|
|
5
5
|
into your React Native app.
|
|
6
6
|
|
|
7
|
+
> **Most apps should use the `<ErxesMessenger />` component instead** — it wraps
|
|
8
|
+
> this bridge and manages configure, user identity, action taps, and the show/hide
|
|
9
|
+
> lifecycle declaratively. See the [README](../README.md#usage--erxesmessenger-recommended).
|
|
10
|
+
> This guide documents the low-level `ErxesNativeIOS` API for advanced/imperative use.
|
|
11
|
+
|
|
7
12
|
## Requirements
|
|
8
13
|
|
|
9
14
|
| | |
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.ErxesMessenger = ErxesMessenger;
|
|
7
|
+
var _react = require("react");
|
|
8
|
+
var _reactNative = require("react-native");
|
|
9
|
+
var _nativeIos = require("./nativeIos");
|
|
10
|
+
/**
|
|
11
|
+
* The identified end user. Same shape the native bridge expects — passing
|
|
12
|
+
* `undefined` leaves the visitor anonymous until you call `setUser` later.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Helpers handed to action `onPress` callbacks (and `onAction`) so you can drive
|
|
17
|
+
* the messenger imperatively from inside a tap handler — show/hide it, toggle the
|
|
18
|
+
* launcher, or swap the user.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* A chat-mode action rendered in the header (`homeActions`) or drawer
|
|
23
|
+
* (`drawerActions`). Only `id`/`title`/`systemIcon` cross the native bridge; the
|
|
24
|
+
* `onPress` callback stays in JS and runs when the matching action is tapped.
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Drop `onPress` so only the data-only fields the native bridge understands
|
|
29
|
+
* (`id`/`title`/`systemIcon`) cross over. React Native cannot send JS functions
|
|
30
|
+
* to native, so `onPress` is dispatched on the JS side via the action listener.
|
|
31
|
+
*/
|
|
32
|
+
function stripActions(actions) {
|
|
33
|
+
return actions.map(_ref => {
|
|
34
|
+
let {
|
|
35
|
+
onPress: _onPress,
|
|
36
|
+
...nativeAction
|
|
37
|
+
} = _ref;
|
|
38
|
+
return nativeAction;
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Declarative wrapper around {@link ErxesNativeIOS}. Configures the native erxes
|
|
44
|
+
* messenger, wires up action taps, and manages the show/hide lifecycle so app
|
|
45
|
+
* code stays a single component. Renders nothing — the messenger UI is presented
|
|
46
|
+
* natively over your app.
|
|
47
|
+
*
|
|
48
|
+
* For advanced/imperative control, use `ErxesNativeIOS` directly.
|
|
49
|
+
*/
|
|
50
|
+
function ErxesMessenger(_ref2) {
|
|
51
|
+
let {
|
|
52
|
+
integrationId,
|
|
53
|
+
endpoint,
|
|
54
|
+
serverUrl,
|
|
55
|
+
subDomain,
|
|
56
|
+
displayMode = 'classic',
|
|
57
|
+
user,
|
|
58
|
+
cachedCustomerId,
|
|
59
|
+
primaryColor,
|
|
60
|
+
visible,
|
|
61
|
+
autoOpen = displayMode === 'chat',
|
|
62
|
+
autoHideOnUnmount = true,
|
|
63
|
+
launcherVisible,
|
|
64
|
+
homeActions = [],
|
|
65
|
+
drawerActions = [],
|
|
66
|
+
onLoad,
|
|
67
|
+
onReady,
|
|
68
|
+
onOpen,
|
|
69
|
+
onClose,
|
|
70
|
+
onError,
|
|
71
|
+
onAction
|
|
72
|
+
} = _ref2;
|
|
73
|
+
// Keep the latest actions/callback in refs so the action listener (registered
|
|
74
|
+
// once below) always dispatches against current props without re-subscribing.
|
|
75
|
+
const actionsRef = (0, _react.useRef)([]);
|
|
76
|
+
const onActionRef = (0, _react.useRef)(onAction);
|
|
77
|
+
(0, _react.useEffect)(() => {
|
|
78
|
+
actionsRef.current = [...homeActions, ...drawerActions];
|
|
79
|
+
onActionRef.current = onAction;
|
|
80
|
+
}, [homeActions, drawerActions, onAction]);
|
|
81
|
+
(0, _react.useEffect)(() => {
|
|
82
|
+
if (_reactNative.Platform.OS !== 'ios') {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
const helpers = {
|
|
86
|
+
show: () => _nativeIos.ErxesNativeIOS.showMessenger(),
|
|
87
|
+
hide: () => _nativeIos.ErxesNativeIOS.hideMessenger(),
|
|
88
|
+
showLauncher: () => _nativeIos.ErxesNativeIOS.showLauncher(),
|
|
89
|
+
hideLauncher: () => _nativeIos.ErxesNativeIOS.hideLauncher(),
|
|
90
|
+
setUser: nextUser => _nativeIos.ErxesNativeIOS.setUser(nextUser),
|
|
91
|
+
clearUser: () => _nativeIos.ErxesNativeIOS.clearUser()
|
|
92
|
+
};
|
|
93
|
+
const sub = _nativeIos.ErxesNativeIOS.addActionListener(async id => {
|
|
94
|
+
var _onActionRef$current;
|
|
95
|
+
const action = actionsRef.current.find(item => item.id === id);
|
|
96
|
+
if (action !== null && action !== void 0 && action.onPress) {
|
|
97
|
+
await action.onPress(helpers);
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
await ((_onActionRef$current = onActionRef.current) === null || _onActionRef$current === void 0 ? void 0 : _onActionRef$current.call(onActionRef, id, helpers));
|
|
101
|
+
});
|
|
102
|
+
async function setup() {
|
|
103
|
+
try {
|
|
104
|
+
onLoad === null || onLoad === void 0 ? void 0 : onLoad();
|
|
105
|
+
if (user) {
|
|
106
|
+
await _nativeIos.ErxesNativeIOS.setUser(user);
|
|
107
|
+
}
|
|
108
|
+
await _nativeIos.ErxesNativeIOS.configure({
|
|
109
|
+
integrationId,
|
|
110
|
+
endpoint,
|
|
111
|
+
serverUrl,
|
|
112
|
+
subDomain,
|
|
113
|
+
cachedCustomerId,
|
|
114
|
+
displayMode,
|
|
115
|
+
primaryColor,
|
|
116
|
+
homeActions: stripActions(homeActions),
|
|
117
|
+
drawerActions: stripActions(drawerActions)
|
|
118
|
+
});
|
|
119
|
+
onReady === null || onReady === void 0 ? void 0 : onReady();
|
|
120
|
+
if (autoOpen) {
|
|
121
|
+
await _nativeIos.ErxesNativeIOS.showMessenger();
|
|
122
|
+
onOpen === null || onOpen === void 0 ? void 0 : onOpen();
|
|
123
|
+
}
|
|
124
|
+
if (launcherVisible === true) {
|
|
125
|
+
await _nativeIos.ErxesNativeIOS.showLauncher();
|
|
126
|
+
} else if (launcherVisible === false) {
|
|
127
|
+
await _nativeIos.ErxesNativeIOS.hideLauncher();
|
|
128
|
+
}
|
|
129
|
+
} catch (error) {
|
|
130
|
+
onError === null || onError === void 0 ? void 0 : onError(error);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
setup();
|
|
134
|
+
return () => {
|
|
135
|
+
sub.remove();
|
|
136
|
+
if (autoHideOnUnmount) {
|
|
137
|
+
_nativeIos.ErxesNativeIOS.hideMessenger();
|
|
138
|
+
onClose === null || onClose === void 0 ? void 0 : onClose();
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
// Re-run setup only when the native config identity changes; callbacks and
|
|
142
|
+
// actions are read through refs so they don't need to be deps here.
|
|
143
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
144
|
+
}, [integrationId, endpoint, serverUrl, subDomain, displayMode]);
|
|
145
|
+
(0, _react.useEffect)(() => {
|
|
146
|
+
if (_reactNative.Platform.OS !== 'ios' || visible === undefined) {
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
if (visible) {
|
|
150
|
+
_nativeIos.ErxesNativeIOS.showMessenger();
|
|
151
|
+
onOpen === null || onOpen === void 0 ? void 0 : onOpen();
|
|
152
|
+
} else {
|
|
153
|
+
_nativeIos.ErxesNativeIOS.hideMessenger();
|
|
154
|
+
onClose === null || onClose === void 0 ? void 0 : onClose();
|
|
155
|
+
}
|
|
156
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
157
|
+
}, [visible]);
|
|
158
|
+
return null;
|
|
159
|
+
}
|
|
160
|
+
//# sourceMappingURL=ErxesMessenger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["_react","require","_reactNative","_nativeIos","stripActions","actions","map","_ref","onPress","_onPress","nativeAction","ErxesMessenger","_ref2","integrationId","endpoint","serverUrl","subDomain","displayMode","user","cachedCustomerId","primaryColor","visible","autoOpen","autoHideOnUnmount","launcherVisible","homeActions","drawerActions","onLoad","onReady","onOpen","onClose","onError","onAction","actionsRef","useRef","onActionRef","useEffect","current","Platform","OS","helpers","show","ErxesNativeIOS","showMessenger","hide","hideMessenger","showLauncher","hideLauncher","setUser","nextUser","clearUser","sub","addActionListener","id","_onActionRef$current","action","find","item","call","setup","configure","error","remove","undefined"],"sourceRoot":"../../src","sources":["ErxesMessenger.tsx"],"mappings":"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"}
|
package/lib/commonjs/index.js
CHANGED
|
@@ -3,6 +3,12 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
+
Object.defineProperty(exports, "ErxesMessenger", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: function () {
|
|
9
|
+
return _ErxesMessenger.ErxesMessenger;
|
|
10
|
+
}
|
|
11
|
+
});
|
|
6
12
|
Object.defineProperty(exports, "ErxesNativeIOS", {
|
|
7
13
|
enumerable: true,
|
|
8
14
|
get: function () {
|
|
@@ -10,4 +16,5 @@ Object.defineProperty(exports, "ErxesNativeIOS", {
|
|
|
10
16
|
}
|
|
11
17
|
});
|
|
12
18
|
var _nativeIos = require("./nativeIos");
|
|
19
|
+
var _ErxesMessenger = require("./ErxesMessenger");
|
|
13
20
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_nativeIos","require"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":"
|
|
1
|
+
{"version":3,"names":["_nativeIos","require","_ErxesMessenger"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;;;;;;;;;;;;;;;;AAAA,IAAAA,UAAA,GAAAC,OAAA;AAOA,IAAAC,eAAA,GAAAD,OAAA"}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { useEffect, useRef } from 'react';
|
|
2
|
+
import { Platform } from 'react-native';
|
|
3
|
+
import { ErxesNativeIOS } from './nativeIos';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The identified end user. Same shape the native bridge expects — passing
|
|
7
|
+
* `undefined` leaves the visitor anonymous until you call `setUser` later.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Helpers handed to action `onPress` callbacks (and `onAction`) so you can drive
|
|
12
|
+
* the messenger imperatively from inside a tap handler — show/hide it, toggle the
|
|
13
|
+
* launcher, or swap the user.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* A chat-mode action rendered in the header (`homeActions`) or drawer
|
|
18
|
+
* (`drawerActions`). Only `id`/`title`/`systemIcon` cross the native bridge; the
|
|
19
|
+
* `onPress` callback stays in JS and runs when the matching action is tapped.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Drop `onPress` so only the data-only fields the native bridge understands
|
|
24
|
+
* (`id`/`title`/`systemIcon`) cross over. React Native cannot send JS functions
|
|
25
|
+
* to native, so `onPress` is dispatched on the JS side via the action listener.
|
|
26
|
+
*/
|
|
27
|
+
function stripActions(actions) {
|
|
28
|
+
return actions.map(_ref => {
|
|
29
|
+
let {
|
|
30
|
+
onPress: _onPress,
|
|
31
|
+
...nativeAction
|
|
32
|
+
} = _ref;
|
|
33
|
+
return nativeAction;
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Declarative wrapper around {@link ErxesNativeIOS}. Configures the native erxes
|
|
39
|
+
* messenger, wires up action taps, and manages the show/hide lifecycle so app
|
|
40
|
+
* code stays a single component. Renders nothing — the messenger UI is presented
|
|
41
|
+
* natively over your app.
|
|
42
|
+
*
|
|
43
|
+
* For advanced/imperative control, use `ErxesNativeIOS` directly.
|
|
44
|
+
*/
|
|
45
|
+
export function ErxesMessenger(_ref2) {
|
|
46
|
+
let {
|
|
47
|
+
integrationId,
|
|
48
|
+
endpoint,
|
|
49
|
+
serverUrl,
|
|
50
|
+
subDomain,
|
|
51
|
+
displayMode = 'classic',
|
|
52
|
+
user,
|
|
53
|
+
cachedCustomerId,
|
|
54
|
+
primaryColor,
|
|
55
|
+
visible,
|
|
56
|
+
autoOpen = displayMode === 'chat',
|
|
57
|
+
autoHideOnUnmount = true,
|
|
58
|
+
launcherVisible,
|
|
59
|
+
homeActions = [],
|
|
60
|
+
drawerActions = [],
|
|
61
|
+
onLoad,
|
|
62
|
+
onReady,
|
|
63
|
+
onOpen,
|
|
64
|
+
onClose,
|
|
65
|
+
onError,
|
|
66
|
+
onAction
|
|
67
|
+
} = _ref2;
|
|
68
|
+
// Keep the latest actions/callback in refs so the action listener (registered
|
|
69
|
+
// once below) always dispatches against current props without re-subscribing.
|
|
70
|
+
const actionsRef = useRef([]);
|
|
71
|
+
const onActionRef = useRef(onAction);
|
|
72
|
+
useEffect(() => {
|
|
73
|
+
actionsRef.current = [...homeActions, ...drawerActions];
|
|
74
|
+
onActionRef.current = onAction;
|
|
75
|
+
}, [homeActions, drawerActions, onAction]);
|
|
76
|
+
useEffect(() => {
|
|
77
|
+
if (Platform.OS !== 'ios') {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
const helpers = {
|
|
81
|
+
show: () => ErxesNativeIOS.showMessenger(),
|
|
82
|
+
hide: () => ErxesNativeIOS.hideMessenger(),
|
|
83
|
+
showLauncher: () => ErxesNativeIOS.showLauncher(),
|
|
84
|
+
hideLauncher: () => ErxesNativeIOS.hideLauncher(),
|
|
85
|
+
setUser: nextUser => ErxesNativeIOS.setUser(nextUser),
|
|
86
|
+
clearUser: () => ErxesNativeIOS.clearUser()
|
|
87
|
+
};
|
|
88
|
+
const sub = ErxesNativeIOS.addActionListener(async id => {
|
|
89
|
+
var _onActionRef$current;
|
|
90
|
+
const action = actionsRef.current.find(item => item.id === id);
|
|
91
|
+
if (action !== null && action !== void 0 && action.onPress) {
|
|
92
|
+
await action.onPress(helpers);
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
await ((_onActionRef$current = onActionRef.current) === null || _onActionRef$current === void 0 ? void 0 : _onActionRef$current.call(onActionRef, id, helpers));
|
|
96
|
+
});
|
|
97
|
+
async function setup() {
|
|
98
|
+
try {
|
|
99
|
+
onLoad === null || onLoad === void 0 ? void 0 : onLoad();
|
|
100
|
+
if (user) {
|
|
101
|
+
await ErxesNativeIOS.setUser(user);
|
|
102
|
+
}
|
|
103
|
+
await ErxesNativeIOS.configure({
|
|
104
|
+
integrationId,
|
|
105
|
+
endpoint,
|
|
106
|
+
serverUrl,
|
|
107
|
+
subDomain,
|
|
108
|
+
cachedCustomerId,
|
|
109
|
+
displayMode,
|
|
110
|
+
primaryColor,
|
|
111
|
+
homeActions: stripActions(homeActions),
|
|
112
|
+
drawerActions: stripActions(drawerActions)
|
|
113
|
+
});
|
|
114
|
+
onReady === null || onReady === void 0 ? void 0 : onReady();
|
|
115
|
+
if (autoOpen) {
|
|
116
|
+
await ErxesNativeIOS.showMessenger();
|
|
117
|
+
onOpen === null || onOpen === void 0 ? void 0 : onOpen();
|
|
118
|
+
}
|
|
119
|
+
if (launcherVisible === true) {
|
|
120
|
+
await ErxesNativeIOS.showLauncher();
|
|
121
|
+
} else if (launcherVisible === false) {
|
|
122
|
+
await ErxesNativeIOS.hideLauncher();
|
|
123
|
+
}
|
|
124
|
+
} catch (error) {
|
|
125
|
+
onError === null || onError === void 0 ? void 0 : onError(error);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
setup();
|
|
129
|
+
return () => {
|
|
130
|
+
sub.remove();
|
|
131
|
+
if (autoHideOnUnmount) {
|
|
132
|
+
ErxesNativeIOS.hideMessenger();
|
|
133
|
+
onClose === null || onClose === void 0 ? void 0 : onClose();
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
// Re-run setup only when the native config identity changes; callbacks and
|
|
137
|
+
// actions are read through refs so they don't need to be deps here.
|
|
138
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
139
|
+
}, [integrationId, endpoint, serverUrl, subDomain, displayMode]);
|
|
140
|
+
useEffect(() => {
|
|
141
|
+
if (Platform.OS !== 'ios' || visible === undefined) {
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
if (visible) {
|
|
145
|
+
ErxesNativeIOS.showMessenger();
|
|
146
|
+
onOpen === null || onOpen === void 0 ? void 0 : onOpen();
|
|
147
|
+
} else {
|
|
148
|
+
ErxesNativeIOS.hideMessenger();
|
|
149
|
+
onClose === null || onClose === void 0 ? void 0 : onClose();
|
|
150
|
+
}
|
|
151
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
152
|
+
}, [visible]);
|
|
153
|
+
return null;
|
|
154
|
+
}
|
|
155
|
+
//# sourceMappingURL=ErxesMessenger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["useEffect","useRef","Platform","ErxesNativeIOS","stripActions","actions","map","_ref","onPress","_onPress","nativeAction","ErxesMessenger","_ref2","integrationId","endpoint","serverUrl","subDomain","displayMode","user","cachedCustomerId","primaryColor","visible","autoOpen","autoHideOnUnmount","launcherVisible","homeActions","drawerActions","onLoad","onReady","onOpen","onClose","onError","onAction","actionsRef","onActionRef","current","OS","helpers","show","showMessenger","hide","hideMessenger","showLauncher","hideLauncher","setUser","nextUser","clearUser","sub","addActionListener","id","_onActionRef$current","action","find","item","call","setup","configure","error","remove","undefined"],"sourceRoot":"../../src","sources":["ErxesMessenger.tsx"],"mappings":"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"}
|
package/lib/module/index.js
CHANGED
package/lib/module/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["ErxesNativeIOS"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":"AAAA,SAASA,cAAc,QAAQ,aAAa"}
|
|
1
|
+
{"version":3,"names":["ErxesNativeIOS","ErxesMessenger"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":"AAAA,SAASA,cAAc,QAAQ,aAAa;AAO5C,SAASC,cAAc,QAAQ,kBAAkB"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { type NativeIOSUser } from './nativeIos';
|
|
2
|
+
/**
|
|
3
|
+
* The identified end user. Same shape the native bridge expects — passing
|
|
4
|
+
* `undefined` leaves the visitor anonymous until you call `setUser` later.
|
|
5
|
+
*/
|
|
6
|
+
export type ErxesUser = NativeIOSUser;
|
|
7
|
+
/**
|
|
8
|
+
* Helpers handed to action `onPress` callbacks (and `onAction`) so you can drive
|
|
9
|
+
* the messenger imperatively from inside a tap handler — show/hide it, toggle the
|
|
10
|
+
* launcher, or swap the user.
|
|
11
|
+
*/
|
|
12
|
+
export type ErxesMessengerHelpers = {
|
|
13
|
+
show: () => Promise<void>;
|
|
14
|
+
hide: () => Promise<void>;
|
|
15
|
+
showLauncher: () => Promise<void>;
|
|
16
|
+
hideLauncher: () => Promise<void>;
|
|
17
|
+
setUser: (user: ErxesUser) => Promise<void>;
|
|
18
|
+
clearUser: () => Promise<void>;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* A chat-mode action rendered in the header (`homeActions`) or drawer
|
|
22
|
+
* (`drawerActions`). Only `id`/`title`/`systemIcon` cross the native bridge; the
|
|
23
|
+
* `onPress` callback stays in JS and runs when the matching action is tapped.
|
|
24
|
+
*/
|
|
25
|
+
export type ErxesAction = {
|
|
26
|
+
/** Identifier echoed back from native when the action is tapped. */
|
|
27
|
+
id: string;
|
|
28
|
+
/** Display title (drawer rows / accessibility label for header icons). */
|
|
29
|
+
title: string;
|
|
30
|
+
/** SF Symbol name, e.g. "person.crop.circle". */
|
|
31
|
+
systemIcon: string;
|
|
32
|
+
/** Runs when this action is tapped. Receives imperative {@link ErxesMessengerHelpers}. */
|
|
33
|
+
onPress?: (helpers: ErxesMessengerHelpers) => void | Promise<void>;
|
|
34
|
+
};
|
|
35
|
+
export type ErxesMessengerProps = {
|
|
36
|
+
/** erxes messenger integration id. Required. */
|
|
37
|
+
integrationId: string;
|
|
38
|
+
/** Full endpoint URL. Provide one of `endpoint`/`serverUrl`/`subDomain`. */
|
|
39
|
+
endpoint?: string;
|
|
40
|
+
/** Alias for `endpoint`. */
|
|
41
|
+
serverUrl?: string;
|
|
42
|
+
/** Sub-domain shorthand, e.g. `'yourcompany.erxes.io'`. */
|
|
43
|
+
subDomain?: string;
|
|
44
|
+
/** UI shell to present. Defaults to `'classic'` (the sheet-based widget). */
|
|
45
|
+
displayMode?: 'classic' | 'chat';
|
|
46
|
+
/** Identify the user before connecting. */
|
|
47
|
+
user?: ErxesUser;
|
|
48
|
+
/** Reuse a previously cached customer id. */
|
|
49
|
+
cachedCustomerId?: string;
|
|
50
|
+
/** Primary accent color as a hex string, e.g. `'#3f78d9'`. */
|
|
51
|
+
primaryColor?: string;
|
|
52
|
+
/** Controlled visibility. When set, drives show/hide on change. */
|
|
53
|
+
visible?: boolean;
|
|
54
|
+
/** Open the messenger once configured. Defaults to `true` in chat mode. */
|
|
55
|
+
autoOpen?: boolean;
|
|
56
|
+
/** Hide the messenger when the component unmounts. Defaults to `true`. */
|
|
57
|
+
autoHideOnUnmount?: boolean;
|
|
58
|
+
/** Show (`true`) or hide (`false`) the floating launcher after configure. */
|
|
59
|
+
launcherVisible?: boolean;
|
|
60
|
+
/** Chat-mode header-right actions. Ignored in `'classic'`. */
|
|
61
|
+
homeActions?: ErxesAction[];
|
|
62
|
+
/** Chat-mode drawer top action rows. Ignored in `'classic'`. */
|
|
63
|
+
drawerActions?: ErxesAction[];
|
|
64
|
+
/** Fired when setup starts. */
|
|
65
|
+
onLoad?: () => void;
|
|
66
|
+
/** Fired after native `configure` succeeds. */
|
|
67
|
+
onReady?: () => void;
|
|
68
|
+
/** Fired when the messenger is shown. */
|
|
69
|
+
onOpen?: () => void;
|
|
70
|
+
/** Fired when the messenger is hidden. */
|
|
71
|
+
onClose?: () => void;
|
|
72
|
+
/** Fired when setup/open/hide fails. */
|
|
73
|
+
onError?: (error: unknown) => void;
|
|
74
|
+
/** Fallback for tapped actions that have no `onPress`. */
|
|
75
|
+
onAction?: (id: string, helpers: ErxesMessengerHelpers) => void | Promise<void>;
|
|
76
|
+
};
|
|
77
|
+
/**
|
|
78
|
+
* Declarative wrapper around {@link ErxesNativeIOS}. Configures the native erxes
|
|
79
|
+
* messenger, wires up action taps, and manages the show/hide lifecycle so app
|
|
80
|
+
* code stays a single component. Renders nothing — the messenger UI is presented
|
|
81
|
+
* natively over your app.
|
|
82
|
+
*
|
|
83
|
+
* For advanced/imperative control, use `ErxesNativeIOS` directly.
|
|
84
|
+
*/
|
|
85
|
+
export declare function ErxesMessenger({ integrationId, endpoint, serverUrl, subDomain, displayMode, user, cachedCustomerId, primaryColor, visible, autoOpen, autoHideOnUnmount, launcherVisible, homeActions, drawerActions, onLoad, onReady, onOpen, onClose, onError, onAction, }: ErxesMessengerProps): null;
|
|
86
|
+
//# sourceMappingURL=ErxesMessenger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ErxesMessenger.d.ts","sourceRoot":"","sources":["../../src/ErxesMessenger.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
export { ErxesNativeIOS } from './nativeIos';
|
|
2
2
|
export type { NativeIOSAction, NativeIOSConfig, NativeIOSUser, } from './nativeIos';
|
|
3
|
+
export { ErxesMessenger } from './ErxesMessenger';
|
|
4
|
+
export type { ErxesUser, ErxesAction, ErxesMessengerHelpers, ErxesMessengerProps, } from './ErxesMessenger';
|
|
3
5
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,YAAY,EACV,eAAe,EACf,eAAe,EACf,aAAa,GACd,MAAM,aAAa,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,YAAY,EACV,eAAe,EACf,eAAe,EACf,aAAa,GACd,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,YAAY,EACV,SAAS,EACT,WAAW,EACX,qBAAqB,EACrB,mBAAmB,GACpB,MAAM,kBAAkB,CAAC"}
|
package/package.json
CHANGED
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
import { useEffect, useRef } from 'react';
|
|
2
|
+
import { Platform } from 'react-native';
|
|
3
|
+
|
|
4
|
+
import { ErxesNativeIOS, type NativeIOSUser } from './nativeIos';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* The identified end user. Same shape the native bridge expects — passing
|
|
8
|
+
* `undefined` leaves the visitor anonymous until you call `setUser` later.
|
|
9
|
+
*/
|
|
10
|
+
export type ErxesUser = NativeIOSUser;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Helpers handed to action `onPress` callbacks (and `onAction`) so you can drive
|
|
14
|
+
* the messenger imperatively from inside a tap handler — show/hide it, toggle the
|
|
15
|
+
* launcher, or swap the user.
|
|
16
|
+
*/
|
|
17
|
+
export type ErxesMessengerHelpers = {
|
|
18
|
+
show: () => Promise<void>;
|
|
19
|
+
hide: () => Promise<void>;
|
|
20
|
+
showLauncher: () => Promise<void>;
|
|
21
|
+
hideLauncher: () => Promise<void>;
|
|
22
|
+
setUser: (user: ErxesUser) => Promise<void>;
|
|
23
|
+
clearUser: () => Promise<void>;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* A chat-mode action rendered in the header (`homeActions`) or drawer
|
|
28
|
+
* (`drawerActions`). Only `id`/`title`/`systemIcon` cross the native bridge; the
|
|
29
|
+
* `onPress` callback stays in JS and runs when the matching action is tapped.
|
|
30
|
+
*/
|
|
31
|
+
export type ErxesAction = {
|
|
32
|
+
/** Identifier echoed back from native when the action is tapped. */
|
|
33
|
+
id: string;
|
|
34
|
+
/** Display title (drawer rows / accessibility label for header icons). */
|
|
35
|
+
title: string;
|
|
36
|
+
/** SF Symbol name, e.g. "person.crop.circle". */
|
|
37
|
+
systemIcon: string;
|
|
38
|
+
/** Runs when this action is tapped. Receives imperative {@link ErxesMessengerHelpers}. */
|
|
39
|
+
onPress?: (helpers: ErxesMessengerHelpers) => void | Promise<void>;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export type ErxesMessengerProps = {
|
|
43
|
+
/** erxes messenger integration id. Required. */
|
|
44
|
+
integrationId: string;
|
|
45
|
+
|
|
46
|
+
/** Full endpoint URL. Provide one of `endpoint`/`serverUrl`/`subDomain`. */
|
|
47
|
+
endpoint?: string;
|
|
48
|
+
/** Alias for `endpoint`. */
|
|
49
|
+
serverUrl?: string;
|
|
50
|
+
/** Sub-domain shorthand, e.g. `'yourcompany.erxes.io'`. */
|
|
51
|
+
subDomain?: string;
|
|
52
|
+
|
|
53
|
+
/** UI shell to present. Defaults to `'classic'` (the sheet-based widget). */
|
|
54
|
+
displayMode?: 'classic' | 'chat';
|
|
55
|
+
|
|
56
|
+
/** Identify the user before connecting. */
|
|
57
|
+
user?: ErxesUser;
|
|
58
|
+
/** Reuse a previously cached customer id. */
|
|
59
|
+
cachedCustomerId?: string;
|
|
60
|
+
|
|
61
|
+
/** Primary accent color as a hex string, e.g. `'#3f78d9'`. */
|
|
62
|
+
primaryColor?: string;
|
|
63
|
+
|
|
64
|
+
/** Controlled visibility. When set, drives show/hide on change. */
|
|
65
|
+
visible?: boolean;
|
|
66
|
+
/** Open the messenger once configured. Defaults to `true` in chat mode. */
|
|
67
|
+
autoOpen?: boolean;
|
|
68
|
+
/** Hide the messenger when the component unmounts. Defaults to `true`. */
|
|
69
|
+
autoHideOnUnmount?: boolean;
|
|
70
|
+
/** Show (`true`) or hide (`false`) the floating launcher after configure. */
|
|
71
|
+
launcherVisible?: boolean;
|
|
72
|
+
|
|
73
|
+
/** Chat-mode header-right actions. Ignored in `'classic'`. */
|
|
74
|
+
homeActions?: ErxesAction[];
|
|
75
|
+
/** Chat-mode drawer top action rows. Ignored in `'classic'`. */
|
|
76
|
+
drawerActions?: ErxesAction[];
|
|
77
|
+
|
|
78
|
+
/** Fired when setup starts. */
|
|
79
|
+
onLoad?: () => void;
|
|
80
|
+
/** Fired after native `configure` succeeds. */
|
|
81
|
+
onReady?: () => void;
|
|
82
|
+
/** Fired when the messenger is shown. */
|
|
83
|
+
onOpen?: () => void;
|
|
84
|
+
/** Fired when the messenger is hidden. */
|
|
85
|
+
onClose?: () => void;
|
|
86
|
+
/** Fired when setup/open/hide fails. */
|
|
87
|
+
onError?: (error: unknown) => void;
|
|
88
|
+
/** Fallback for tapped actions that have no `onPress`. */
|
|
89
|
+
onAction?: (
|
|
90
|
+
id: string,
|
|
91
|
+
helpers: ErxesMessengerHelpers
|
|
92
|
+
) => void | Promise<void>;
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Drop `onPress` so only the data-only fields the native bridge understands
|
|
97
|
+
* (`id`/`title`/`systemIcon`) cross over. React Native cannot send JS functions
|
|
98
|
+
* to native, so `onPress` is dispatched on the JS side via the action listener.
|
|
99
|
+
*/
|
|
100
|
+
function stripActions(actions: ErxesAction[]) {
|
|
101
|
+
return actions.map(({ onPress: _onPress, ...nativeAction }) => nativeAction);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Declarative wrapper around {@link ErxesNativeIOS}. Configures the native erxes
|
|
106
|
+
* messenger, wires up action taps, and manages the show/hide lifecycle so app
|
|
107
|
+
* code stays a single component. Renders nothing — the messenger UI is presented
|
|
108
|
+
* natively over your app.
|
|
109
|
+
*
|
|
110
|
+
* For advanced/imperative control, use `ErxesNativeIOS` directly.
|
|
111
|
+
*/
|
|
112
|
+
export function ErxesMessenger({
|
|
113
|
+
integrationId,
|
|
114
|
+
endpoint,
|
|
115
|
+
serverUrl,
|
|
116
|
+
subDomain,
|
|
117
|
+
displayMode = 'classic',
|
|
118
|
+
user,
|
|
119
|
+
cachedCustomerId,
|
|
120
|
+
primaryColor,
|
|
121
|
+
visible,
|
|
122
|
+
autoOpen = displayMode === 'chat',
|
|
123
|
+
autoHideOnUnmount = true,
|
|
124
|
+
launcherVisible,
|
|
125
|
+
homeActions = [],
|
|
126
|
+
drawerActions = [],
|
|
127
|
+
onLoad,
|
|
128
|
+
onReady,
|
|
129
|
+
onOpen,
|
|
130
|
+
onClose,
|
|
131
|
+
onError,
|
|
132
|
+
onAction,
|
|
133
|
+
}: ErxesMessengerProps) {
|
|
134
|
+
// Keep the latest actions/callback in refs so the action listener (registered
|
|
135
|
+
// once below) always dispatches against current props without re-subscribing.
|
|
136
|
+
const actionsRef = useRef<ErxesAction[]>([]);
|
|
137
|
+
const onActionRef = useRef(onAction);
|
|
138
|
+
|
|
139
|
+
useEffect(() => {
|
|
140
|
+
actionsRef.current = [...homeActions, ...drawerActions];
|
|
141
|
+
onActionRef.current = onAction;
|
|
142
|
+
}, [homeActions, drawerActions, onAction]);
|
|
143
|
+
|
|
144
|
+
useEffect(() => {
|
|
145
|
+
if (Platform.OS !== 'ios') {
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
const helpers: ErxesMessengerHelpers = {
|
|
150
|
+
show: () => ErxesNativeIOS.showMessenger(),
|
|
151
|
+
hide: () => ErxesNativeIOS.hideMessenger(),
|
|
152
|
+
showLauncher: () => ErxesNativeIOS.showLauncher(),
|
|
153
|
+
hideLauncher: () => ErxesNativeIOS.hideLauncher(),
|
|
154
|
+
setUser: (nextUser) => ErxesNativeIOS.setUser(nextUser),
|
|
155
|
+
clearUser: () => ErxesNativeIOS.clearUser(),
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
const sub = ErxesNativeIOS.addActionListener(async (id) => {
|
|
159
|
+
const action = actionsRef.current.find((item) => item.id === id);
|
|
160
|
+
|
|
161
|
+
if (action?.onPress) {
|
|
162
|
+
await action.onPress(helpers);
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
await onActionRef.current?.(id, helpers);
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
async function setup() {
|
|
170
|
+
try {
|
|
171
|
+
onLoad?.();
|
|
172
|
+
|
|
173
|
+
if (user) {
|
|
174
|
+
await ErxesNativeIOS.setUser(user);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
await ErxesNativeIOS.configure({
|
|
178
|
+
integrationId,
|
|
179
|
+
endpoint,
|
|
180
|
+
serverUrl,
|
|
181
|
+
subDomain,
|
|
182
|
+
cachedCustomerId,
|
|
183
|
+
displayMode,
|
|
184
|
+
primaryColor,
|
|
185
|
+
homeActions: stripActions(homeActions),
|
|
186
|
+
drawerActions: stripActions(drawerActions),
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
onReady?.();
|
|
190
|
+
|
|
191
|
+
if (autoOpen) {
|
|
192
|
+
await ErxesNativeIOS.showMessenger();
|
|
193
|
+
onOpen?.();
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
if (launcherVisible === true) {
|
|
197
|
+
await ErxesNativeIOS.showLauncher();
|
|
198
|
+
} else if (launcherVisible === false) {
|
|
199
|
+
await ErxesNativeIOS.hideLauncher();
|
|
200
|
+
}
|
|
201
|
+
} catch (error) {
|
|
202
|
+
onError?.(error);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
setup();
|
|
207
|
+
|
|
208
|
+
return () => {
|
|
209
|
+
sub.remove();
|
|
210
|
+
|
|
211
|
+
if (autoHideOnUnmount) {
|
|
212
|
+
ErxesNativeIOS.hideMessenger();
|
|
213
|
+
onClose?.();
|
|
214
|
+
}
|
|
215
|
+
};
|
|
216
|
+
// Re-run setup only when the native config identity changes; callbacks and
|
|
217
|
+
// actions are read through refs so they don't need to be deps here.
|
|
218
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
219
|
+
}, [integrationId, endpoint, serverUrl, subDomain, displayMode]);
|
|
220
|
+
|
|
221
|
+
useEffect(() => {
|
|
222
|
+
if (Platform.OS !== 'ios' || visible === undefined) {
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
if (visible) {
|
|
227
|
+
ErxesNativeIOS.showMessenger();
|
|
228
|
+
onOpen?.();
|
|
229
|
+
} else {
|
|
230
|
+
ErxesNativeIOS.hideMessenger();
|
|
231
|
+
onClose?.();
|
|
232
|
+
}
|
|
233
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
234
|
+
}, [visible]);
|
|
235
|
+
|
|
236
|
+
return null;
|
|
237
|
+
}
|
package/src/index.tsx
CHANGED