rn-erxes-sdk 0.3.4 → 0.4.0
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 +23 -0
- package/ios/RnErxesSdk.swift +20 -1
- package/lib/commonjs/ErxesMessenger.js +91 -17
- package/lib/commonjs/ErxesMessenger.js.map +1 -1
- package/lib/commonjs/nativeIos.js +13 -0
- package/lib/commonjs/nativeIos.js.map +1 -1
- package/lib/module/ErxesMessenger.js +92 -18
- package/lib/module/ErxesMessenger.js.map +1 -1
- package/lib/module/nativeIos.js +13 -0
- package/lib/module/nativeIos.js.map +1 -1
- package/lib/typescript/ErxesMessenger.d.ts +11 -2
- package/lib/typescript/ErxesMessenger.d.ts.map +1 -1
- package/lib/typescript/nativeIos.d.ts +7 -0
- package/lib/typescript/nativeIos.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/ErxesMessenger.tsx +105 -19
- package/src/nativeIos.ts +15 -0
package/README.md
CHANGED
|
@@ -217,6 +217,8 @@ focus so the messenger shows/hides as the user navigates, and add a header actio
|
|
|
217
217
|
jump to another screen.
|
|
218
218
|
|
|
219
219
|
```tsx
|
|
220
|
+
import { ActivityIndicator, View } from 'react-native';
|
|
221
|
+
|
|
220
222
|
const isFocused = useIsFocused();
|
|
221
223
|
|
|
222
224
|
<ErxesMessenger
|
|
@@ -225,6 +227,11 @@ const isFocused = useIsFocused();
|
|
|
225
227
|
endpoint={ENDPOINT}
|
|
226
228
|
displayMode="chat"
|
|
227
229
|
user={CURRENT_USER}
|
|
230
|
+
renderLoading={() => (
|
|
231
|
+
<View style={{ flex: 1, justifyContent: 'center' }}>
|
|
232
|
+
<ActivityIndicator />
|
|
233
|
+
</View>
|
|
234
|
+
)}
|
|
228
235
|
homeActions={[
|
|
229
236
|
{
|
|
230
237
|
id: 'profile',
|
|
@@ -239,6 +246,10 @@ const isFocused = useIsFocused();
|
|
|
239
246
|
/>
|
|
240
247
|
```
|
|
241
248
|
|
|
249
|
+
`renderLoading` shows your own UI until the connection handshake completes
|
|
250
|
+
(`onReady`). Note that chat mode also shows its own loading indicator inside the
|
|
251
|
+
full-screen native view, so `renderLoading` is most useful in classic mode.
|
|
252
|
+
|
|
242
253
|
### Example 3 — Settings → Support screen with a close button
|
|
243
254
|
|
|
244
255
|
Open chat on mount, hide it on unmount, and add an `X` action that closes the
|
|
@@ -283,7 +294,9 @@ messenger and pops the screen.
|
|
|
283
294
|
| `autoHideOnUnmount` | `boolean` | Hide on unmount. Defaults to `true`. |
|
|
284
295
|
| `launcherVisible` | `boolean` | Show/hide the floating launcher after configure. |
|
|
285
296
|
| `homeActions` / `drawerActions` | `ErxesAction[]` | `{ id, title, systemIcon, onPress? }`. Chat mode only. |
|
|
297
|
+
| `renderLoading` | `() => ReactNode` | Rendered while configuring (between `onLoad` and `onReady`/`onError`), e.g. a spinner. Defaults to nothing. |
|
|
286
298
|
| `onLoad` / `onReady` / `onOpen` / `onClose` / `onError` | callbacks | Lifecycle events. |
|
|
299
|
+
| `onLoadingChange` | `(loading: boolean) => void` | Fired when the loading state changes (`true` while configuring). |
|
|
287
300
|
| `onAction` | `(id, helpers) => void` | Fallback for tapped actions with no `onPress`. |
|
|
288
301
|
|
|
289
302
|
Action `onPress` (and `onAction`) receive `ErxesMessengerHelpers`:
|
|
@@ -350,6 +363,16 @@ const sub = ErxesNativeIOS.addActionListener((id) => {
|
|
|
350
363
|
// sub.remove() on cleanup
|
|
351
364
|
```
|
|
352
365
|
|
|
366
|
+
To know when the messenger has finished connecting (e.g. to hide your own
|
|
367
|
+
spinner), listen for the ready event:
|
|
368
|
+
|
|
369
|
+
```tsx
|
|
370
|
+
const readySub = ErxesNativeIOS.addReadyListener(() => {
|
|
371
|
+
// connection handshake complete — messenger is ready
|
|
372
|
+
});
|
|
373
|
+
// readySub.remove() on cleanup
|
|
374
|
+
```
|
|
375
|
+
|
|
353
376
|
Chat mode also supports voice messages — see the [Native iOS guide](docs/native-ios.md) for the required `Info.plist` permissions.
|
|
354
377
|
|
|
355
378
|
On logout:
|
package/ios/RnErxesSdk.swift
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import Combine
|
|
1
2
|
import Foundation
|
|
2
3
|
import MessengerSDK
|
|
3
4
|
import UIKit
|
|
@@ -8,15 +9,21 @@ final class RnErxesSdk: RCTEventEmitter {
|
|
|
8
9
|
/// JS event fired when a chat-mode action (homeActions/drawerActions) is tapped.
|
|
9
10
|
private static let actionEvent = "onErxesAction"
|
|
10
11
|
|
|
12
|
+
/// JS event fired when the connect handshake completes (`MessengerSDK.isReady`).
|
|
13
|
+
private static let readyEvent = "onErxesReady"
|
|
14
|
+
|
|
11
15
|
/// True while JS has at least one listener attached, so we don't emit into the void.
|
|
12
16
|
private var hasListeners = false
|
|
13
17
|
|
|
18
|
+
/// Observes `MessengerSDK.shared.isReady` so we can forward readiness to JS.
|
|
19
|
+
private var readyCancellable: AnyCancellable?
|
|
20
|
+
|
|
14
21
|
override static func requiresMainQueueSetup() -> Bool {
|
|
15
22
|
true
|
|
16
23
|
}
|
|
17
24
|
|
|
18
25
|
override func supportedEvents() -> [String] {
|
|
19
|
-
[Self.actionEvent]
|
|
26
|
+
[Self.actionEvent, Self.readyEvent]
|
|
20
27
|
}
|
|
21
28
|
|
|
22
29
|
override func startObserving() {
|
|
@@ -62,6 +69,18 @@ final class RnErxesSdk: RCTEventEmitter {
|
|
|
62
69
|
self.sendEvent(withName: Self.actionEvent, body: ["id": id])
|
|
63
70
|
}
|
|
64
71
|
|
|
72
|
+
// Forward the connect handshake to JS as `onErxesReady`. `$isReady`
|
|
73
|
+
// emits its current value on subscribe, so a `configure()` after the
|
|
74
|
+
// SDK is already connected still notifies JS. `removeDuplicates`
|
|
75
|
+
// collapses repeated `true`s into a single emission per connection.
|
|
76
|
+
self.readyCancellable = MessengerSDK.shared.$isReady
|
|
77
|
+
.removeDuplicates()
|
|
78
|
+
.filter { $0 }
|
|
79
|
+
.sink { [weak self] _ in
|
|
80
|
+
guard let self, self.hasListeners else { return }
|
|
81
|
+
self.sendEvent(withName: Self.readyEvent, body: nil)
|
|
82
|
+
}
|
|
83
|
+
|
|
65
84
|
MessengerSDK.configure(
|
|
66
85
|
MessengerConfig(
|
|
67
86
|
endpoint: endpoint,
|
|
@@ -63,17 +63,40 @@ function ErxesMessenger(_ref2) {
|
|
|
63
63
|
launcherVisible,
|
|
64
64
|
homeActions = [],
|
|
65
65
|
drawerActions = [],
|
|
66
|
+
renderLoading,
|
|
66
67
|
onLoad,
|
|
67
68
|
onReady,
|
|
68
69
|
onOpen,
|
|
69
70
|
onClose,
|
|
70
71
|
onError,
|
|
71
|
-
onAction
|
|
72
|
+
onAction,
|
|
73
|
+
onLoadingChange
|
|
72
74
|
} = _ref2;
|
|
73
75
|
// Keep the latest actions/callback in refs so the action listener (registered
|
|
74
76
|
// once below) always dispatches against current props without re-subscribing.
|
|
75
77
|
const actionsRef = (0, _react.useRef)([]);
|
|
76
78
|
const onActionRef = (0, _react.useRef)(onAction);
|
|
79
|
+
const onLoadingChangeRef = (0, _react.useRef)(onLoadingChange);
|
|
80
|
+
// Tracks whether we believe the messenger is currently presented, so we never
|
|
81
|
+
// double-present (chat mode auto-presents inside `configure()`) or fire a
|
|
82
|
+
// redundant show/hide. Native gives us no presentation callback, so this is our
|
|
83
|
+
// best-effort intent mirror.
|
|
84
|
+
const shownRef = (0, _react.useRef)(false);
|
|
85
|
+
|
|
86
|
+
// Flips true only after native `configure()` resolves. The controlled-`visible`
|
|
87
|
+
// effect gates on this so it never calls `showMessenger()` before `configure()`
|
|
88
|
+
// (the native SDK asserts on that ordering).
|
|
89
|
+
const [configured, setConfigured] = (0, _react.useState)(false);
|
|
90
|
+
// True while configuring (between `onLoad` and `onReady`/`onError`); drives
|
|
91
|
+
// `renderLoading`.
|
|
92
|
+
const [loading, setLoading] = (0, _react.useState)(false);
|
|
93
|
+
(0, _react.useEffect)(() => {
|
|
94
|
+
onLoadingChangeRef.current = onLoadingChange;
|
|
95
|
+
}, [onLoadingChange]);
|
|
96
|
+
(0, _react.useEffect)(() => {
|
|
97
|
+
var _onLoadingChangeRef$c;
|
|
98
|
+
(_onLoadingChangeRef$c = onLoadingChangeRef.current) === null || _onLoadingChangeRef$c === void 0 ? void 0 : _onLoadingChangeRef$c.call(onLoadingChangeRef, loading);
|
|
99
|
+
}, [loading]);
|
|
77
100
|
(0, _react.useEffect)(() => {
|
|
78
101
|
actionsRef.current = [...homeActions, ...drawerActions];
|
|
79
102
|
onActionRef.current = onAction;
|
|
@@ -82,9 +105,16 @@ function ErxesMessenger(_ref2) {
|
|
|
82
105
|
if (_reactNative.Platform.OS !== 'ios') {
|
|
83
106
|
return;
|
|
84
107
|
}
|
|
108
|
+
setConfigured(false);
|
|
85
109
|
const helpers = {
|
|
86
|
-
show: () =>
|
|
87
|
-
|
|
110
|
+
show: async () => {
|
|
111
|
+
await _nativeIos.ErxesNativeIOS.showMessenger();
|
|
112
|
+
shownRef.current = true;
|
|
113
|
+
},
|
|
114
|
+
hide: async () => {
|
|
115
|
+
await _nativeIos.ErxesNativeIOS.hideMessenger();
|
|
116
|
+
shownRef.current = false;
|
|
117
|
+
},
|
|
88
118
|
showLauncher: () => _nativeIos.ErxesNativeIOS.showLauncher(),
|
|
89
119
|
hideLauncher: () => _nativeIos.ErxesNativeIOS.hideLauncher(),
|
|
90
120
|
setUser: nextUser => _nativeIos.ErxesNativeIOS.setUser(nextUser),
|
|
@@ -99,8 +129,16 @@ function ErxesMessenger(_ref2) {
|
|
|
99
129
|
}
|
|
100
130
|
await ((_onActionRef$current = onActionRef.current) === null || _onActionRef$current === void 0 ? void 0 : _onActionRef$current.call(onActionRef, id, helpers));
|
|
101
131
|
});
|
|
132
|
+
|
|
133
|
+
// Connection complete (native `MessengerSDK.isReady`): the messenger is
|
|
134
|
+
// truly ready, so end the loading state and notify the host.
|
|
135
|
+
const readySub = _nativeIos.ErxesNativeIOS.addReadyListener(() => {
|
|
136
|
+
setLoading(false);
|
|
137
|
+
onReady === null || onReady === void 0 ? void 0 : onReady();
|
|
138
|
+
});
|
|
102
139
|
async function setup() {
|
|
103
140
|
try {
|
|
141
|
+
setLoading(true);
|
|
104
142
|
onLoad === null || onLoad === void 0 ? void 0 : onLoad();
|
|
105
143
|
if (user) {
|
|
106
144
|
await _nativeIos.ErxesNativeIOS.setUser(user);
|
|
@@ -116,25 +154,53 @@ function ErxesMessenger(_ref2) {
|
|
|
116
154
|
homeActions: stripActions(homeActions),
|
|
117
155
|
drawerActions: stripActions(drawerActions)
|
|
118
156
|
});
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
157
|
+
|
|
158
|
+
// `configure()` only kicks off the async connect; `onReady` and the end
|
|
159
|
+
// of `loading` are driven by the ready listener above, not here.
|
|
160
|
+
|
|
161
|
+
// Decide the initial open state. If `visible` is controlled it wins;
|
|
162
|
+
// otherwise fall back to `autoOpen` (defaults to true in chat mode).
|
|
163
|
+
const shouldOpen = visible ?? autoOpen;
|
|
164
|
+
if (displayMode === 'chat') {
|
|
165
|
+
// Chat mode auto-presents itself inside `configure()` — never call
|
|
166
|
+
// `showMessenger()` for the initial open or we'd present a second one.
|
|
167
|
+
if (shouldOpen) {
|
|
168
|
+
shownRef.current = true;
|
|
169
|
+
onOpen === null || onOpen === void 0 ? void 0 : onOpen();
|
|
170
|
+
} else {
|
|
171
|
+
// Caller wants it closed: undo the native auto-present.
|
|
172
|
+
await _nativeIos.ErxesNativeIOS.hideMessenger();
|
|
173
|
+
shownRef.current = false;
|
|
174
|
+
}
|
|
175
|
+
} else {
|
|
176
|
+
// Classic mode: configure does not open anything. Show the launcher
|
|
177
|
+
// and/or present the sheet explicitly.
|
|
178
|
+
if (launcherVisible === true) {
|
|
179
|
+
await _nativeIos.ErxesNativeIOS.showLauncher();
|
|
180
|
+
} else if (launcherVisible === false) {
|
|
181
|
+
await _nativeIos.ErxesNativeIOS.hideLauncher();
|
|
182
|
+
}
|
|
183
|
+
if (shouldOpen) {
|
|
184
|
+
await _nativeIos.ErxesNativeIOS.showMessenger();
|
|
185
|
+
shownRef.current = true;
|
|
186
|
+
onOpen === null || onOpen === void 0 ? void 0 : onOpen();
|
|
187
|
+
}
|
|
128
188
|
}
|
|
189
|
+
setConfigured(true);
|
|
129
190
|
} catch (error) {
|
|
191
|
+
// Setup failed before the connection could complete — end loading here
|
|
192
|
+
// since the ready listener will never fire.
|
|
193
|
+
setLoading(false);
|
|
130
194
|
onError === null || onError === void 0 ? void 0 : onError(error);
|
|
131
195
|
}
|
|
132
196
|
}
|
|
133
197
|
setup();
|
|
134
198
|
return () => {
|
|
135
199
|
sub.remove();
|
|
136
|
-
|
|
200
|
+
readySub.remove();
|
|
201
|
+
if (autoHideOnUnmount && shownRef.current) {
|
|
137
202
|
_nativeIos.ErxesNativeIOS.hideMessenger();
|
|
203
|
+
shownRef.current = false;
|
|
138
204
|
onClose === null || onClose === void 0 ? void 0 : onClose();
|
|
139
205
|
}
|
|
140
206
|
};
|
|
@@ -143,18 +209,26 @@ function ErxesMessenger(_ref2) {
|
|
|
143
209
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
144
210
|
}, [integrationId, endpoint, serverUrl, subDomain, displayMode]);
|
|
145
211
|
(0, _react.useEffect)(() => {
|
|
146
|
-
|
|
212
|
+
// Wait until `configure()` has resolved — otherwise `showMessenger()` would
|
|
213
|
+
// race ahead of it and trip the native configure-before-show assertion. The
|
|
214
|
+
// initial open is handled in `setup()`; this only reacts to later changes.
|
|
215
|
+
if (_reactNative.Platform.OS !== 'ios' || visible === undefined || !configured) {
|
|
147
216
|
return;
|
|
148
217
|
}
|
|
149
|
-
if (visible) {
|
|
218
|
+
if (visible && !shownRef.current) {
|
|
150
219
|
_nativeIos.ErxesNativeIOS.showMessenger();
|
|
220
|
+
shownRef.current = true;
|
|
151
221
|
onOpen === null || onOpen === void 0 ? void 0 : onOpen();
|
|
152
|
-
} else {
|
|
222
|
+
} else if (!visible && shownRef.current) {
|
|
153
223
|
_nativeIos.ErxesNativeIOS.hideMessenger();
|
|
224
|
+
shownRef.current = false;
|
|
154
225
|
onClose === null || onClose === void 0 ? void 0 : onClose();
|
|
155
226
|
}
|
|
156
227
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
157
|
-
}, [visible]);
|
|
228
|
+
}, [visible, configured]);
|
|
229
|
+
if (loading && renderLoading) {
|
|
230
|
+
return renderLoading();
|
|
231
|
+
}
|
|
158
232
|
return null;
|
|
159
233
|
}
|
|
160
234
|
//# sourceMappingURL=ErxesMessenger.js.map
|
|
@@ -1 +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","
|
|
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","renderLoading","onLoad","onReady","onOpen","onClose","onError","onAction","onLoadingChange","actionsRef","useRef","onActionRef","onLoadingChangeRef","shownRef","configured","setConfigured","useState","loading","setLoading","useEffect","current","_onLoadingChangeRef$c","call","Platform","OS","helpers","show","ErxesNativeIOS","showMessenger","hide","hideMessenger","showLauncher","hideLauncher","setUser","nextUser","clearUser","sub","addActionListener","id","_onActionRef$current","action","find","item","readySub","addReadyListener","setup","configure","shouldOpen","error","remove","undefined"],"sourceRoot":"../../src","sources":["ErxesMessenger.tsx"],"mappings":";;;;;;AAAA,IAAAA,MAAA,GAAAC,OAAA;AACA,IAAAC,YAAA,GAAAD,OAAA;AAEA,IAAAE,UAAA,GAAAF,OAAA;AAEA;AACA;AACA;AACA;;AAGA;AACA;AACA;AACA;AACA;;AAUA;AACA;AACA;AACA;AACA;;AA0EA;AACA;AACA;AACA;AACA;AACA,SAASG,YAAYA,CAACC,OAAsB,EAAE;EAC5C,OAAOA,OAAO,CAACC,GAAG,CAACC,IAAA;IAAA,IAAC;MAAEC,OAAO,EAAEC,QAAQ;MAAE,GAAGC;IAAa,CAAC,GAAAH,IAAA;IAAA,OAAKG,YAAY;EAAA,EAAC;AAC9E;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAASC,cAAcA,CAAAC,KAAA,EAuBN;EAAA,IAvBO;IAC7BC,aAAa;IACbC,QAAQ;IACRC,SAAS;IACTC,SAAS;IACTC,WAAW,GAAG,SAAS;IACvBC,IAAI;IACJC,gBAAgB;IAChBC,YAAY;IACZC,OAAO;IACPC,QAAQ,GAAGL,WAAW,KAAK,MAAM;IACjCM,iBAAiB,GAAG,IAAI;IACxBC,eAAe;IACfC,WAAW,GAAG,EAAE;IAChBC,aAAa,GAAG,EAAE;IAClBC,aAAa;IACbC,MAAM;IACNC,OAAO;IACPC,MAAM;IACNC,OAAO;IACPC,OAAO;IACPC,QAAQ;IACRC;EACmB,CAAC,GAAAtB,KAAA;EACpB;EACA;EACA,MAAMuB,UAAU,GAAG,IAAAC,aAAM,EAAgB,EAAE,CAAC;EAC5C,MAAMC,WAAW,GAAG,IAAAD,aAAM,EAACH,QAAQ,CAAC;EACpC,MAAMK,kBAAkB,GAAG,IAAAF,aAAM,EAACF,eAAe,CAAC;EAClD;EACA;EACA;EACA;EACA,MAAMK,QAAQ,GAAG,IAAAH,aAAM,EAAC,KAAK,CAAC;;EAE9B;EACA;EACA;EACA,MAAM,CAACI,UAAU,EAAEC,aAAa,CAAC,GAAG,IAAAC,eAAQ,EAAC,KAAK,CAAC;EACnD;EACA;EACA,MAAM,CAACC,OAAO,EAAEC,UAAU,CAAC,GAAG,IAAAF,eAAQ,EAAC,KAAK,CAAC;EAE7C,IAAAG,gBAAS,EAAC,MAAM;IACdP,kBAAkB,CAACQ,OAAO,GAAGZ,eAAe;EAC9C,CAAC,EAAE,CAACA,eAAe,CAAC,CAAC;EAErB,IAAAW,gBAAS,EAAC,MAAM;IAAA,IAAAE,qBAAA;IACd,CAAAA,qBAAA,GAAAT,kBAAkB,CAACQ,OAAO,cAAAC,qBAAA,uBAA1BA,qBAAA,CAAAC,IAAA,CAAAV,kBAAkB,EAAWK,OAAO,CAAC;EACvC,CAAC,EAAE,CAACA,OAAO,CAAC,CAAC;EAEb,IAAAE,gBAAS,EAAC,MAAM;IACdV,UAAU,CAACW,OAAO,GAAG,CAAC,GAAGrB,WAAW,EAAE,GAAGC,aAAa,CAAC;IACvDW,WAAW,CAACS,OAAO,GAAGb,QAAQ;EAChC,CAAC,EAAE,CAACR,WAAW,EAAEC,aAAa,EAAEO,QAAQ,CAAC,CAAC;EAE1C,IAAAY,gBAAS,EAAC,MAAM;IACd,IAAII,qBAAQ,CAACC,EAAE,KAAK,KAAK,EAAE;MACzB;IACF;IAEAT,aAAa,CAAC,KAAK,CAAC;IAEpB,MAAMU,OAA8B,GAAG;MACrCC,IAAI,EAAE,MAAAA,CAAA,KAAY;QAChB,MAAMC,yBAAc,CAACC,aAAa,CAAC,CAAC;QACpCf,QAAQ,CAACO,OAAO,GAAG,IAAI;MACzB,CAAC;MACDS,IAAI,EAAE,MAAAA,CAAA,KAAY;QAChB,MAAMF,yBAAc,CAACG,aAAa,CAAC,CAAC;QACpCjB,QAAQ,CAACO,OAAO,GAAG,KAAK;MAC1B,CAAC;MACDW,YAAY,EAAEA,CAAA,KAAMJ,yBAAc,CAACI,YAAY,CAAC,CAAC;MACjDC,YAAY,EAAEA,CAAA,KAAML,yBAAc,CAACK,YAAY,CAAC,CAAC;MACjDC,OAAO,EAAGC,QAAQ,IAAKP,yBAAc,CAACM,OAAO,CAACC,QAAQ,CAAC;MACvDC,SAAS,EAAEA,CAAA,KAAMR,yBAAc,CAACQ,SAAS,CAAC;IAC5C,CAAC;IAED,MAAMC,GAAG,GAAGT,yBAAc,CAACU,iBAAiB,CAAC,MAAOC,EAAE,IAAK;MAAA,IAAAC,oBAAA;MACzD,MAAMC,MAAM,GAAG/B,UAAU,CAACW,OAAO,CAACqB,IAAI,CAAEC,IAAI,IAAKA,IAAI,CAACJ,EAAE,KAAKA,EAAE,CAAC;MAEhE,IAAIE,MAAM,aAANA,MAAM,eAANA,MAAM,CAAE1D,OAAO,EAAE;QACnB,MAAM0D,MAAM,CAAC1D,OAAO,CAAC2C,OAAO,CAAC;QAC7B;MACF;MAEA,QAAAc,oBAAA,GAAM5B,WAAW,CAACS,OAAO,cAAAmB,oBAAA,uBAAnBA,oBAAA,CAAAjB,IAAA,CAAAX,WAAW,EAAW2B,EAAE,EAAEb,OAAO,CAAC;IAC1C,CAAC,CAAC;;IAEF;IACA;IACA,MAAMkB,QAAQ,GAAGhB,yBAAc,CAACiB,gBAAgB,CAAC,MAAM;MACrD1B,UAAU,CAAC,KAAK,CAAC;MACjBf,OAAO,aAAPA,OAAO,uBAAPA,OAAO,CAAG,CAAC;IACb,CAAC,CAAC;IAEF,eAAe0C,KAAKA,CAAA,EAAG;MACrB,IAAI;QACF3B,UAAU,CAAC,IAAI,CAAC;QAChBhB,MAAM,aAANA,MAAM,uBAANA,MAAM,CAAG,CAAC;QAEV,IAAIV,IAAI,EAAE;UACR,MAAMmC,yBAAc,CAACM,OAAO,CAACzC,IAAI,CAAC;QACpC;QAEA,MAAMmC,yBAAc,CAACmB,SAAS,CAAC;UAC7B3D,aAAa;UACbC,QAAQ;UACRC,SAAS;UACTC,SAAS;UACTG,gBAAgB;UAChBF,WAAW;UACXG,YAAY;UACZK,WAAW,EAAErB,YAAY,CAACqB,WAAW,CAAC;UACtCC,aAAa,EAAEtB,YAAY,CAACsB,aAAa;QAC3C,CAAC,CAAC;;QAEF;QACA;;QAEA;QACA;QACA,MAAM+C,UAAU,GAAGpD,OAAO,IAAIC,QAAQ;QAEtC,IAAIL,WAAW,KAAK,MAAM,EAAE;UAC1B;UACA;UACA,IAAIwD,UAAU,EAAE;YACdlC,QAAQ,CAACO,OAAO,GAAG,IAAI;YACvBhB,MAAM,aAANA,MAAM,uBAANA,MAAM,CAAG,CAAC;UACZ,CAAC,MAAM;YACL;YACA,MAAMuB,yBAAc,CAACG,aAAa,CAAC,CAAC;YACpCjB,QAAQ,CAACO,OAAO,GAAG,KAAK;UAC1B;QACF,CAAC,MAAM;UACL;UACA;UACA,IAAItB,eAAe,KAAK,IAAI,EAAE;YAC5B,MAAM6B,yBAAc,CAACI,YAAY,CAAC,CAAC;UACrC,CAAC,MAAM,IAAIjC,eAAe,KAAK,KAAK,EAAE;YACpC,MAAM6B,yBAAc,CAACK,YAAY,CAAC,CAAC;UACrC;UAEA,IAAIe,UAAU,EAAE;YACd,MAAMpB,yBAAc,CAACC,aAAa,CAAC,CAAC;YACpCf,QAAQ,CAACO,OAAO,GAAG,IAAI;YACvBhB,MAAM,aAANA,MAAM,uBAANA,MAAM,CAAG,CAAC;UACZ;QACF;QAEAW,aAAa,CAAC,IAAI,CAAC;MACrB,CAAC,CAAC,OAAOiC,KAAK,EAAE;QACd;QACA;QACA9B,UAAU,CAAC,KAAK,CAAC;QACjBZ,OAAO,aAAPA,OAAO,uBAAPA,OAAO,CAAG0C,KAAK,CAAC;MAClB;IACF;IAEAH,KAAK,CAAC,CAAC;IAEP,OAAO,MAAM;MACXT,GAAG,CAACa,MAAM,CAAC,CAAC;MACZN,QAAQ,CAACM,MAAM,CAAC,CAAC;MAEjB,IAAIpD,iBAAiB,IAAIgB,QAAQ,CAACO,OAAO,EAAE;QACzCO,yBAAc,CAACG,aAAa,CAAC,CAAC;QAC9BjB,QAAQ,CAACO,OAAO,GAAG,KAAK;QACxBf,OAAO,aAAPA,OAAO,uBAAPA,OAAO,CAAG,CAAC;MACb;IACF,CAAC;IACD;IACA;IACA;EACF,CAAC,EAAE,CAAClB,aAAa,EAAEC,QAAQ,EAAEC,SAAS,EAAEC,SAAS,EAAEC,WAAW,CAAC,CAAC;EAEhE,IAAA4B,gBAAS,EAAC,MAAM;IACd;IACA;IACA;IACA,IAAII,qBAAQ,CAACC,EAAE,KAAK,KAAK,IAAI7B,OAAO,KAAKuD,SAAS,IAAI,CAACpC,UAAU,EAAE;MACjE;IACF;IAEA,IAAInB,OAAO,IAAI,CAACkB,QAAQ,CAACO,OAAO,EAAE;MAChCO,yBAAc,CAACC,aAAa,CAAC,CAAC;MAC9Bf,QAAQ,CAACO,OAAO,GAAG,IAAI;MACvBhB,MAAM,aAANA,MAAM,uBAANA,MAAM,CAAG,CAAC;IACZ,CAAC,MAAM,IAAI,CAACT,OAAO,IAAIkB,QAAQ,CAACO,OAAO,EAAE;MACvCO,yBAAc,CAACG,aAAa,CAAC,CAAC;MAC9BjB,QAAQ,CAACO,OAAO,GAAG,KAAK;MACxBf,OAAO,aAAPA,OAAO,uBAAPA,OAAO,CAAG,CAAC;IACb;IACA;EACF,CAAC,EAAE,CAACV,OAAO,EAAEmB,UAAU,CAAC,CAAC;EAEzB,IAAIG,OAAO,IAAIhB,aAAa,EAAE;IAC5B,OAAOA,aAAa,CAAC,CAAC;EACxB;EAEA,OAAO,IAAI;AACb"}
|
|
@@ -13,6 +13,9 @@ var _reactNative = require("react-native");
|
|
|
13
13
|
|
|
14
14
|
/** Native event name emitted when a chat-mode action is tapped. */
|
|
15
15
|
const ACTION_EVENT = 'onErxesAction';
|
|
16
|
+
|
|
17
|
+
/** Native event name emitted when the connect handshake completes. */
|
|
18
|
+
const READY_EVENT = 'onErxesReady';
|
|
16
19
|
const LINKING_ERROR = "The rn-erxes-sdk native iOS module is not linked. Run `pod install` in your app's ios directory and rebuild the app.";
|
|
17
20
|
const nativeModule = _reactNative.NativeModules.RnErxesSdk;
|
|
18
21
|
function getNativeModule() {
|
|
@@ -65,6 +68,16 @@ const ErxesNativeIOS = {
|
|
|
65
68
|
addActionListener(handler) {
|
|
66
69
|
const emitter = new _reactNative.NativeEventEmitter(getNativeModule());
|
|
67
70
|
return emitter.addListener(ACTION_EVENT, event => handler(event.id));
|
|
71
|
+
},
|
|
72
|
+
/**
|
|
73
|
+
* Listen for the connect handshake completing — i.e. the messenger is ready
|
|
74
|
+
* (`MessengerSDK.isReady`). Fires once per connection; if already connected
|
|
75
|
+
* when you subscribe via a fresh `configure`, it fires again. Returns a
|
|
76
|
+
* subscription — call `.remove()` to stop listening.
|
|
77
|
+
*/
|
|
78
|
+
addReadyListener(handler) {
|
|
79
|
+
const emitter = new _reactNative.NativeEventEmitter(getNativeModule());
|
|
80
|
+
return emitter.addListener(READY_EVENT, () => handler());
|
|
68
81
|
}
|
|
69
82
|
};
|
|
70
83
|
exports.ErxesNativeIOS = ErxesNativeIOS;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_reactNative","require","ACTION_EVENT","LINKING_ERROR","nativeModule","NativeModules","RnErxesSdk","getNativeModule","Platform","OS","Error","ErxesNativeIOS","configure","options","setUser","customData","Object","fromEntries","entries","filter","_ref","value","undefined","map","_ref2","key","String","clearUser","showMessenger","showLauncher","hideLauncher","hideMessenger","addActionListener","handler","emitter","NativeEventEmitter","addListener","event","id","exports"],"sourceRoot":"../../src","sources":["nativeIos.ts"],"mappings":";;;;;;AAAA,IAAAA,YAAA,GAAAC,OAAA;AAQA;AACA;AACA;AACA;AACA;;AA2CA;AACA,MAAMC,YAAY,GAAG,eAAe;
|
|
1
|
+
{"version":3,"names":["_reactNative","require","ACTION_EVENT","READY_EVENT","LINKING_ERROR","nativeModule","NativeModules","RnErxesSdk","getNativeModule","Platform","OS","Error","ErxesNativeIOS","configure","options","setUser","customData","Object","fromEntries","entries","filter","_ref","value","undefined","map","_ref2","key","String","clearUser","showMessenger","showLauncher","hideLauncher","hideMessenger","addActionListener","handler","emitter","NativeEventEmitter","addListener","event","id","addReadyListener","exports"],"sourceRoot":"../../src","sources":["nativeIos.ts"],"mappings":";;;;;;AAAA,IAAAA,YAAA,GAAAC,OAAA;AAQA;AACA;AACA;AACA;AACA;;AA2CA;AACA,MAAMC,YAAY,GAAG,eAAe;;AAEpC;AACA,MAAMC,WAAW,GAAG,cAAc;AAElC,MAAMC,aAAa,GACjB,sHAAsH;AAExH,MAAMC,YAAY,GAAGC,0BAAa,CAACC,UAAyC;AAE5E,SAASC,eAAeA,CAAA,EAAoB;EAC1C,IAAIC,qBAAQ,CAACC,EAAE,KAAK,KAAK,EAAE;IACzB,MAAM,IAAIC,KAAK,CAAC,kDAAkD,CAAC;EACrE;EAEA,IAAI,CAACN,YAAY,EAAE;IACjB,MAAM,IAAIM,KAAK,CAACP,aAAa,CAAC;EAChC;EAEA,OAAOC,YAAY;AACrB;AAEO,MAAMO,cAAc,GAAG;EAC5BC,SAASA,CAACC,OAAwB,EAAE;IAClC,OAAON,eAAe,CAAC,CAAC,CAACK,SAAS,CAACC,OAAO,CAAC;EAC7C,CAAC;EACDC,OAAOA,CAACD,OAAsB,EAAE;IAC9B,MAAME,UAAU,GAAGC,MAAM,CAACC,WAAW,CACnCD,MAAM,CAACE,OAAO,CAACL,OAAO,CAACE,UAAU,IAAI,CAAC,CAAC,CAAC,CACrCI,MAAM,CAACC,IAAA;MAAA,IAAC,GAAGC,KAAK,CAAC,GAAAD,IAAA;MAAA,OAAKC,KAAK,KAAK,IAAI,IAAIA,KAAK,KAAKC,SAAS;IAAA,EAAC,CAC5DC,GAAG,CAACC,KAAA;MAAA,IAAC,CAACC,GAAG,EAAEJ,KAAK,CAAC,GAAAG,KAAA;MAAA,OAAK,CAACC,GAAG,EAAEC,MAAM,CAACL,KAAK,CAAC,CAAC;IAAA,EAC/C,CAAC;IAED,OAAOd,eAAe,CAAC,CAAC,CAACO,OAAO,CAAC;MAC/B,GAAGD,OAAO;MACVE;IACF,CAAC,CAAC;EACJ,CAAC;EACDY,SAASA,CAAA,EAAG;IACV,OAAOpB,eAAe,CAAC,CAAC,CAACoB,SAAS,CAAC,CAAC;EACtC,CAAC;EACDC,aAAaA,CAAA,EAAG;IACd,OAAOrB,eAAe,CAAC,CAAC,CAACqB,aAAa,CAAC,CAAC;EAC1C,CAAC;EACDC,YAAYA,CAAA,EAAG;IACb,OAAOtB,eAAe,CAAC,CAAC,CAACsB,YAAY,CAAC,CAAC;EACzC,CAAC;EACDC,YAAYA,CAAA,EAAG;IACb,OAAOvB,eAAe,CAAC,CAAC,CAACuB,YAAY,CAAC,CAAC;EACzC,CAAC;EACDC,aAAaA,CAAA,EAAG;IACd,OAAOxB,eAAe,CAAC,CAAC,CAACwB,aAAa,CAAC,CAAC;EAC1C,CAAC;EACD;AACF;AACA;AACA;AACA;AACA;EACEC,iBAAiBA,CAACC,OAA6B,EAAuB;IACpE,MAAMC,OAAO,GAAG,IAAIC,+BAAkB,CACpC5B,eAAe,CAAC,CAClB,CAAC;IACD,OAAO2B,OAAO,CAACE,WAAW,CAACnC,YAAY,EAAGoC,KAAqB,IAC7DJ,OAAO,CAACI,KAAK,CAACC,EAAE,CAClB,CAAC;EACH,CAAC;EACD;AACF;AACA;AACA;AACA;AACA;EACEC,gBAAgBA,CAACN,OAAmB,EAAuB;IACzD,MAAMC,OAAO,GAAG,IAAIC,+BAAkB,CACpC5B,eAAe,CAAC,CAClB,CAAC;IACD,OAAO2B,OAAO,CAACE,WAAW,CAAClC,WAAW,EAAE,MAAM+B,OAAO,CAAC,CAAC,CAAC;EAC1D;AACF,CAAC;AAACO,OAAA,CAAA7B,cAAA,GAAAA,cAAA"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useEffect, useRef } from 'react';
|
|
1
|
+
import { useEffect, useRef, useState } from 'react';
|
|
2
2
|
import { Platform } from 'react-native';
|
|
3
3
|
import { ErxesNativeIOS } from './nativeIos';
|
|
4
4
|
|
|
@@ -58,17 +58,40 @@ export function ErxesMessenger(_ref2) {
|
|
|
58
58
|
launcherVisible,
|
|
59
59
|
homeActions = [],
|
|
60
60
|
drawerActions = [],
|
|
61
|
+
renderLoading,
|
|
61
62
|
onLoad,
|
|
62
63
|
onReady,
|
|
63
64
|
onOpen,
|
|
64
65
|
onClose,
|
|
65
66
|
onError,
|
|
66
|
-
onAction
|
|
67
|
+
onAction,
|
|
68
|
+
onLoadingChange
|
|
67
69
|
} = _ref2;
|
|
68
70
|
// Keep the latest actions/callback in refs so the action listener (registered
|
|
69
71
|
// once below) always dispatches against current props without re-subscribing.
|
|
70
72
|
const actionsRef = useRef([]);
|
|
71
73
|
const onActionRef = useRef(onAction);
|
|
74
|
+
const onLoadingChangeRef = useRef(onLoadingChange);
|
|
75
|
+
// Tracks whether we believe the messenger is currently presented, so we never
|
|
76
|
+
// double-present (chat mode auto-presents inside `configure()`) or fire a
|
|
77
|
+
// redundant show/hide. Native gives us no presentation callback, so this is our
|
|
78
|
+
// best-effort intent mirror.
|
|
79
|
+
const shownRef = useRef(false);
|
|
80
|
+
|
|
81
|
+
// Flips true only after native `configure()` resolves. The controlled-`visible`
|
|
82
|
+
// effect gates on this so it never calls `showMessenger()` before `configure()`
|
|
83
|
+
// (the native SDK asserts on that ordering).
|
|
84
|
+
const [configured, setConfigured] = useState(false);
|
|
85
|
+
// True while configuring (between `onLoad` and `onReady`/`onError`); drives
|
|
86
|
+
// `renderLoading`.
|
|
87
|
+
const [loading, setLoading] = useState(false);
|
|
88
|
+
useEffect(() => {
|
|
89
|
+
onLoadingChangeRef.current = onLoadingChange;
|
|
90
|
+
}, [onLoadingChange]);
|
|
91
|
+
useEffect(() => {
|
|
92
|
+
var _onLoadingChangeRef$c;
|
|
93
|
+
(_onLoadingChangeRef$c = onLoadingChangeRef.current) === null || _onLoadingChangeRef$c === void 0 ? void 0 : _onLoadingChangeRef$c.call(onLoadingChangeRef, loading);
|
|
94
|
+
}, [loading]);
|
|
72
95
|
useEffect(() => {
|
|
73
96
|
actionsRef.current = [...homeActions, ...drawerActions];
|
|
74
97
|
onActionRef.current = onAction;
|
|
@@ -77,9 +100,16 @@ export function ErxesMessenger(_ref2) {
|
|
|
77
100
|
if (Platform.OS !== 'ios') {
|
|
78
101
|
return;
|
|
79
102
|
}
|
|
103
|
+
setConfigured(false);
|
|
80
104
|
const helpers = {
|
|
81
|
-
show: () =>
|
|
82
|
-
|
|
105
|
+
show: async () => {
|
|
106
|
+
await ErxesNativeIOS.showMessenger();
|
|
107
|
+
shownRef.current = true;
|
|
108
|
+
},
|
|
109
|
+
hide: async () => {
|
|
110
|
+
await ErxesNativeIOS.hideMessenger();
|
|
111
|
+
shownRef.current = false;
|
|
112
|
+
},
|
|
83
113
|
showLauncher: () => ErxesNativeIOS.showLauncher(),
|
|
84
114
|
hideLauncher: () => ErxesNativeIOS.hideLauncher(),
|
|
85
115
|
setUser: nextUser => ErxesNativeIOS.setUser(nextUser),
|
|
@@ -94,8 +124,16 @@ export function ErxesMessenger(_ref2) {
|
|
|
94
124
|
}
|
|
95
125
|
await ((_onActionRef$current = onActionRef.current) === null || _onActionRef$current === void 0 ? void 0 : _onActionRef$current.call(onActionRef, id, helpers));
|
|
96
126
|
});
|
|
127
|
+
|
|
128
|
+
// Connection complete (native `MessengerSDK.isReady`): the messenger is
|
|
129
|
+
// truly ready, so end the loading state and notify the host.
|
|
130
|
+
const readySub = ErxesNativeIOS.addReadyListener(() => {
|
|
131
|
+
setLoading(false);
|
|
132
|
+
onReady === null || onReady === void 0 ? void 0 : onReady();
|
|
133
|
+
});
|
|
97
134
|
async function setup() {
|
|
98
135
|
try {
|
|
136
|
+
setLoading(true);
|
|
99
137
|
onLoad === null || onLoad === void 0 ? void 0 : onLoad();
|
|
100
138
|
if (user) {
|
|
101
139
|
await ErxesNativeIOS.setUser(user);
|
|
@@ -111,25 +149,53 @@ export function ErxesMessenger(_ref2) {
|
|
|
111
149
|
homeActions: stripActions(homeActions),
|
|
112
150
|
drawerActions: stripActions(drawerActions)
|
|
113
151
|
});
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
152
|
+
|
|
153
|
+
// `configure()` only kicks off the async connect; `onReady` and the end
|
|
154
|
+
// of `loading` are driven by the ready listener above, not here.
|
|
155
|
+
|
|
156
|
+
// Decide the initial open state. If `visible` is controlled it wins;
|
|
157
|
+
// otherwise fall back to `autoOpen` (defaults to true in chat mode).
|
|
158
|
+
const shouldOpen = visible ?? autoOpen;
|
|
159
|
+
if (displayMode === 'chat') {
|
|
160
|
+
// Chat mode auto-presents itself inside `configure()` — never call
|
|
161
|
+
// `showMessenger()` for the initial open or we'd present a second one.
|
|
162
|
+
if (shouldOpen) {
|
|
163
|
+
shownRef.current = true;
|
|
164
|
+
onOpen === null || onOpen === void 0 ? void 0 : onOpen();
|
|
165
|
+
} else {
|
|
166
|
+
// Caller wants it closed: undo the native auto-present.
|
|
167
|
+
await ErxesNativeIOS.hideMessenger();
|
|
168
|
+
shownRef.current = false;
|
|
169
|
+
}
|
|
170
|
+
} else {
|
|
171
|
+
// Classic mode: configure does not open anything. Show the launcher
|
|
172
|
+
// and/or present the sheet explicitly.
|
|
173
|
+
if (launcherVisible === true) {
|
|
174
|
+
await ErxesNativeIOS.showLauncher();
|
|
175
|
+
} else if (launcherVisible === false) {
|
|
176
|
+
await ErxesNativeIOS.hideLauncher();
|
|
177
|
+
}
|
|
178
|
+
if (shouldOpen) {
|
|
179
|
+
await ErxesNativeIOS.showMessenger();
|
|
180
|
+
shownRef.current = true;
|
|
181
|
+
onOpen === null || onOpen === void 0 ? void 0 : onOpen();
|
|
182
|
+
}
|
|
123
183
|
}
|
|
184
|
+
setConfigured(true);
|
|
124
185
|
} catch (error) {
|
|
186
|
+
// Setup failed before the connection could complete — end loading here
|
|
187
|
+
// since the ready listener will never fire.
|
|
188
|
+
setLoading(false);
|
|
125
189
|
onError === null || onError === void 0 ? void 0 : onError(error);
|
|
126
190
|
}
|
|
127
191
|
}
|
|
128
192
|
setup();
|
|
129
193
|
return () => {
|
|
130
194
|
sub.remove();
|
|
131
|
-
|
|
195
|
+
readySub.remove();
|
|
196
|
+
if (autoHideOnUnmount && shownRef.current) {
|
|
132
197
|
ErxesNativeIOS.hideMessenger();
|
|
198
|
+
shownRef.current = false;
|
|
133
199
|
onClose === null || onClose === void 0 ? void 0 : onClose();
|
|
134
200
|
}
|
|
135
201
|
};
|
|
@@ -138,18 +204,26 @@ export function ErxesMessenger(_ref2) {
|
|
|
138
204
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
139
205
|
}, [integrationId, endpoint, serverUrl, subDomain, displayMode]);
|
|
140
206
|
useEffect(() => {
|
|
141
|
-
|
|
207
|
+
// Wait until `configure()` has resolved — otherwise `showMessenger()` would
|
|
208
|
+
// race ahead of it and trip the native configure-before-show assertion. The
|
|
209
|
+
// initial open is handled in `setup()`; this only reacts to later changes.
|
|
210
|
+
if (Platform.OS !== 'ios' || visible === undefined || !configured) {
|
|
142
211
|
return;
|
|
143
212
|
}
|
|
144
|
-
if (visible) {
|
|
213
|
+
if (visible && !shownRef.current) {
|
|
145
214
|
ErxesNativeIOS.showMessenger();
|
|
215
|
+
shownRef.current = true;
|
|
146
216
|
onOpen === null || onOpen === void 0 ? void 0 : onOpen();
|
|
147
|
-
} else {
|
|
217
|
+
} else if (!visible && shownRef.current) {
|
|
148
218
|
ErxesNativeIOS.hideMessenger();
|
|
219
|
+
shownRef.current = false;
|
|
149
220
|
onClose === null || onClose === void 0 ? void 0 : onClose();
|
|
150
221
|
}
|
|
151
222
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
152
|
-
}, [visible]);
|
|
223
|
+
}, [visible, configured]);
|
|
224
|
+
if (loading && renderLoading) {
|
|
225
|
+
return renderLoading();
|
|
226
|
+
}
|
|
153
227
|
return null;
|
|
154
228
|
}
|
|
155
229
|
//# sourceMappingURL=ErxesMessenger.js.map
|
|
@@ -1 +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","
|
|
1
|
+
{"version":3,"names":["useEffect","useRef","useState","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","renderLoading","onLoad","onReady","onOpen","onClose","onError","onAction","onLoadingChange","actionsRef","onActionRef","onLoadingChangeRef","shownRef","configured","setConfigured","loading","setLoading","current","_onLoadingChangeRef$c","call","OS","helpers","show","showMessenger","hide","hideMessenger","showLauncher","hideLauncher","setUser","nextUser","clearUser","sub","addActionListener","id","_onActionRef$current","action","find","item","readySub","addReadyListener","setup","configure","shouldOpen","error","remove","undefined"],"sourceRoot":"../../src","sources":["ErxesMessenger.tsx"],"mappings":"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"}
|
package/lib/module/nativeIos.js
CHANGED
|
@@ -8,6 +8,9 @@ import { NativeEventEmitter, NativeModules, Platform } from 'react-native';
|
|
|
8
8
|
|
|
9
9
|
/** Native event name emitted when a chat-mode action is tapped. */
|
|
10
10
|
const ACTION_EVENT = 'onErxesAction';
|
|
11
|
+
|
|
12
|
+
/** Native event name emitted when the connect handshake completes. */
|
|
13
|
+
const READY_EVENT = 'onErxesReady';
|
|
11
14
|
const LINKING_ERROR = "The rn-erxes-sdk native iOS module is not linked. Run `pod install` in your app's ios directory and rebuild the app.";
|
|
12
15
|
const nativeModule = NativeModules.RnErxesSdk;
|
|
13
16
|
function getNativeModule() {
|
|
@@ -60,6 +63,16 @@ export const ErxesNativeIOS = {
|
|
|
60
63
|
addActionListener(handler) {
|
|
61
64
|
const emitter = new NativeEventEmitter(getNativeModule());
|
|
62
65
|
return emitter.addListener(ACTION_EVENT, event => handler(event.id));
|
|
66
|
+
},
|
|
67
|
+
/**
|
|
68
|
+
* Listen for the connect handshake completing — i.e. the messenger is ready
|
|
69
|
+
* (`MessengerSDK.isReady`). Fires once per connection; if already connected
|
|
70
|
+
* when you subscribe via a fresh `configure`, it fires again. Returns a
|
|
71
|
+
* subscription — call `.remove()` to stop listening.
|
|
72
|
+
*/
|
|
73
|
+
addReadyListener(handler) {
|
|
74
|
+
const emitter = new NativeEventEmitter(getNativeModule());
|
|
75
|
+
return emitter.addListener(READY_EVENT, () => handler());
|
|
63
76
|
}
|
|
64
77
|
};
|
|
65
78
|
//# sourceMappingURL=nativeIos.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["NativeEventEmitter","NativeModules","Platform","ACTION_EVENT","LINKING_ERROR","nativeModule","RnErxesSdk","getNativeModule","OS","Error","ErxesNativeIOS","configure","options","setUser","customData","Object","fromEntries","entries","filter","_ref","value","undefined","map","_ref2","key","String","clearUser","showMessenger","showLauncher","hideLauncher","hideMessenger","addActionListener","handler","emitter","addListener","event","id"],"sourceRoot":"../../src","sources":["nativeIos.ts"],"mappings":"AAAA,SACEA,kBAAkB,EAClBC,aAAa,EACbC,QAAQ,QAGH,cAAc;;AAErB;AACA;AACA;AACA;AACA;;AA2CA;AACA,MAAMC,YAAY,GAAG,eAAe;
|
|
1
|
+
{"version":3,"names":["NativeEventEmitter","NativeModules","Platform","ACTION_EVENT","READY_EVENT","LINKING_ERROR","nativeModule","RnErxesSdk","getNativeModule","OS","Error","ErxesNativeIOS","configure","options","setUser","customData","Object","fromEntries","entries","filter","_ref","value","undefined","map","_ref2","key","String","clearUser","showMessenger","showLauncher","hideLauncher","hideMessenger","addActionListener","handler","emitter","addListener","event","id","addReadyListener"],"sourceRoot":"../../src","sources":["nativeIos.ts"],"mappings":"AAAA,SACEA,kBAAkB,EAClBC,aAAa,EACbC,QAAQ,QAGH,cAAc;;AAErB;AACA;AACA;AACA;AACA;;AA2CA;AACA,MAAMC,YAAY,GAAG,eAAe;;AAEpC;AACA,MAAMC,WAAW,GAAG,cAAc;AAElC,MAAMC,aAAa,GACjB,sHAAsH;AAExH,MAAMC,YAAY,GAAGL,aAAa,CAACM,UAAyC;AAE5E,SAASC,eAAeA,CAAA,EAAoB;EAC1C,IAAIN,QAAQ,CAACO,EAAE,KAAK,KAAK,EAAE;IACzB,MAAM,IAAIC,KAAK,CAAC,kDAAkD,CAAC;EACrE;EAEA,IAAI,CAACJ,YAAY,EAAE;IACjB,MAAM,IAAII,KAAK,CAACL,aAAa,CAAC;EAChC;EAEA,OAAOC,YAAY;AACrB;AAEA,OAAO,MAAMK,cAAc,GAAG;EAC5BC,SAASA,CAACC,OAAwB,EAAE;IAClC,OAAOL,eAAe,CAAC,CAAC,CAACI,SAAS,CAACC,OAAO,CAAC;EAC7C,CAAC;EACDC,OAAOA,CAACD,OAAsB,EAAE;IAC9B,MAAME,UAAU,GAAGC,MAAM,CAACC,WAAW,CACnCD,MAAM,CAACE,OAAO,CAACL,OAAO,CAACE,UAAU,IAAI,CAAC,CAAC,CAAC,CACrCI,MAAM,CAACC,IAAA;MAAA,IAAC,GAAGC,KAAK,CAAC,GAAAD,IAAA;MAAA,OAAKC,KAAK,KAAK,IAAI,IAAIA,KAAK,KAAKC,SAAS;IAAA,EAAC,CAC5DC,GAAG,CAACC,KAAA;MAAA,IAAC,CAACC,GAAG,EAAEJ,KAAK,CAAC,GAAAG,KAAA;MAAA,OAAK,CAACC,GAAG,EAAEC,MAAM,CAACL,KAAK,CAAC,CAAC;IAAA,EAC/C,CAAC;IAED,OAAOb,eAAe,CAAC,CAAC,CAACM,OAAO,CAAC;MAC/B,GAAGD,OAAO;MACVE;IACF,CAAC,CAAC;EACJ,CAAC;EACDY,SAASA,CAAA,EAAG;IACV,OAAOnB,eAAe,CAAC,CAAC,CAACmB,SAAS,CAAC,CAAC;EACtC,CAAC;EACDC,aAAaA,CAAA,EAAG;IACd,OAAOpB,eAAe,CAAC,CAAC,CAACoB,aAAa,CAAC,CAAC;EAC1C,CAAC;EACDC,YAAYA,CAAA,EAAG;IACb,OAAOrB,eAAe,CAAC,CAAC,CAACqB,YAAY,CAAC,CAAC;EACzC,CAAC;EACDC,YAAYA,CAAA,EAAG;IACb,OAAOtB,eAAe,CAAC,CAAC,CAACsB,YAAY,CAAC,CAAC;EACzC,CAAC;EACDC,aAAaA,CAAA,EAAG;IACd,OAAOvB,eAAe,CAAC,CAAC,CAACuB,aAAa,CAAC,CAAC;EAC1C,CAAC;EACD;AACF;AACA;AACA;AACA;AACA;EACEC,iBAAiBA,CAACC,OAA6B,EAAuB;IACpE,MAAMC,OAAO,GAAG,IAAIlC,kBAAkB,CACpCQ,eAAe,CAAC,CAClB,CAAC;IACD,OAAO0B,OAAO,CAACC,WAAW,CAAChC,YAAY,EAAGiC,KAAqB,IAC7DH,OAAO,CAACG,KAAK,CAACC,EAAE,CAClB,CAAC;EACH,CAAC;EACD;AACF;AACA;AACA;AACA;AACA;EACEC,gBAAgBA,CAACL,OAAmB,EAAuB;IACzD,MAAMC,OAAO,GAAG,IAAIlC,kBAAkB,CACpCQ,eAAe,CAAC,CAClB,CAAC;IACD,OAAO0B,OAAO,CAACC,WAAW,CAAC/B,WAAW,EAAE,MAAM6B,OAAO,CAAC,CAAC,CAAC;EAC1D;AACF,CAAC"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
1
2
|
import { type NativeIOSUser } from './nativeIos';
|
|
2
3
|
/**
|
|
3
4
|
* The identified end user. Same shape the native bridge expects — passing
|
|
@@ -61,10 +62,18 @@ export type ErxesMessengerProps = {
|
|
|
61
62
|
homeActions?: ErxesAction[];
|
|
62
63
|
/** Chat-mode drawer top action rows. Ignored in `'classic'`. */
|
|
63
64
|
drawerActions?: ErxesAction[];
|
|
65
|
+
/**
|
|
66
|
+
* Rendered while the SDK is configuring (between `onLoad` and
|
|
67
|
+
* `onReady`/`onError`), e.g. a spinner shown before the native messenger
|
|
68
|
+
* appears. Returns `null` otherwise. Defaults to rendering nothing.
|
|
69
|
+
*/
|
|
70
|
+
renderLoading?: () => ReactNode;
|
|
64
71
|
/** Fired when setup starts. */
|
|
65
72
|
onLoad?: () => void;
|
|
66
|
-
/** Fired
|
|
73
|
+
/** Fired when the connection handshake completes (the messenger is ready). */
|
|
67
74
|
onReady?: () => void;
|
|
75
|
+
/** Fired when the loading state changes (`true` while configuring). */
|
|
76
|
+
onLoadingChange?: (loading: boolean) => void;
|
|
68
77
|
/** Fired when the messenger is shown. */
|
|
69
78
|
onOpen?: () => void;
|
|
70
79
|
/** Fired when the messenger is hidden. */
|
|
@@ -82,5 +91,5 @@ export type ErxesMessengerProps = {
|
|
|
82
91
|
*
|
|
83
92
|
* For advanced/imperative control, use `ErxesNativeIOS` directly.
|
|
84
93
|
*/
|
|
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):
|
|
94
|
+
export declare function ErxesMessenger({ integrationId, endpoint, serverUrl, subDomain, displayMode, user, cachedCustomerId, primaryColor, visible, autoOpen, autoHideOnUnmount, launcherVisible, homeActions, drawerActions, renderLoading, onLoad, onReady, onOpen, onClose, onError, onAction, onLoadingChange, }: ErxesMessengerProps): ReactNode;
|
|
86
95
|
//# sourceMappingURL=ErxesMessenger.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ErxesMessenger.d.ts","sourceRoot":"","sources":["../../src/ErxesMessenger.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ErxesMessenger.d.ts","sourceRoot":"","sources":["../../src/ErxesMessenger.tsx"],"names":[],"mappings":"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"}
|
|
@@ -48,6 +48,13 @@ export declare const ErxesNativeIOS: {
|
|
|
48
48
|
* to stop listening.
|
|
49
49
|
*/
|
|
50
50
|
addActionListener(handler: (id: string) => void): EmitterSubscription;
|
|
51
|
+
/**
|
|
52
|
+
* Listen for the connect handshake completing — i.e. the messenger is ready
|
|
53
|
+
* (`MessengerSDK.isReady`). Fires once per connection; if already connected
|
|
54
|
+
* when you subscribe via a fresh `configure`, it fires again. Returns a
|
|
55
|
+
* subscription — call `.remove()` to stop listening.
|
|
56
|
+
*/
|
|
57
|
+
addReadyListener(handler: () => void): EmitterSubscription;
|
|
51
58
|
};
|
|
52
59
|
export type { NativeIOSAction, NativeIOSConfig, NativeIOSUser };
|
|
53
60
|
//# sourceMappingURL=nativeIos.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nativeIos.d.ts","sourceRoot":"","sources":["../../src/nativeIos.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,mBAAmB,EAEzB,MAAM,cAAc,CAAC;AAEtB;;;;GAIG;AACH,KAAK,eAAe,GAAG;IACrB,wDAAwD;IACxD,EAAE,EAAE,MAAM,CAAC;IACX,0EAA0E;IAC1E,KAAK,EAAE,MAAM,CAAC;IACd,8CAA8C;IAC9C,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,KAAK,eAAe,GAAG;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,6EAA6E;IAC7E,WAAW,CAAC,EAAE,SAAS,GAAG,MAAM,CAAC;IACjC,8DAA8D;IAC9D,WAAW,CAAC,EAAE,eAAe,EAAE,CAAC;IAChC,gEAAgE;IAChE,aAAa,CAAC,EAAE,eAAe,EAAE,CAAC;IAClC,8DAA8D;IAC9D,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,KAAK,aAAa,GAAG;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;CAC3E,CAAC;
|
|
1
|
+
{"version":3,"file":"nativeIos.d.ts","sourceRoot":"","sources":["../../src/nativeIos.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,mBAAmB,EAEzB,MAAM,cAAc,CAAC;AAEtB;;;;GAIG;AACH,KAAK,eAAe,GAAG;IACrB,wDAAwD;IACxD,EAAE,EAAE,MAAM,CAAC;IACX,0EAA0E;IAC1E,KAAK,EAAE,MAAM,CAAC;IACd,8CAA8C;IAC9C,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,KAAK,eAAe,GAAG;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,6EAA6E;IAC7E,WAAW,CAAC,EAAE,SAAS,GAAG,MAAM,CAAC;IACjC,8DAA8D;IAC9D,WAAW,CAAC,EAAE,eAAe,EAAE,CAAC;IAChC,gEAAgE;IAChE,aAAa,CAAC,EAAE,eAAe,EAAE,CAAC;IAClC,8DAA8D;IAC9D,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,KAAK,aAAa,GAAG;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;CAC3E,CAAC;AAmCF,eAAO,MAAM,cAAc;uBACN,eAAe;qBAGjB,aAAa;;;;;;IA2B9B;;;;;OAKG;oCAC6B,MAAM,KAAK,IAAI,GAAG,mBAAmB;IAQrE;;;;;OAKG;8BACuB,MAAM,IAAI,GAAG,mBAAmB;CAM3D,CAAC;AAEF,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,aAAa,EAAE,CAAC"}
|
package/package.json
CHANGED
package/src/ErxesMessenger.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useEffect, useRef } from 'react';
|
|
1
|
+
import { useEffect, useRef, useState, type ReactNode } from 'react';
|
|
2
2
|
import { Platform } from 'react-native';
|
|
3
3
|
|
|
4
4
|
import { ErxesNativeIOS, type NativeIOSUser } from './nativeIos';
|
|
@@ -75,10 +75,19 @@ export type ErxesMessengerProps = {
|
|
|
75
75
|
/** Chat-mode drawer top action rows. Ignored in `'classic'`. */
|
|
76
76
|
drawerActions?: ErxesAction[];
|
|
77
77
|
|
|
78
|
+
/**
|
|
79
|
+
* Rendered while the SDK is configuring (between `onLoad` and
|
|
80
|
+
* `onReady`/`onError`), e.g. a spinner shown before the native messenger
|
|
81
|
+
* appears. Returns `null` otherwise. Defaults to rendering nothing.
|
|
82
|
+
*/
|
|
83
|
+
renderLoading?: () => ReactNode;
|
|
84
|
+
|
|
78
85
|
/** Fired when setup starts. */
|
|
79
86
|
onLoad?: () => void;
|
|
80
|
-
/** Fired
|
|
87
|
+
/** Fired when the connection handshake completes (the messenger is ready). */
|
|
81
88
|
onReady?: () => void;
|
|
89
|
+
/** Fired when the loading state changes (`true` while configuring). */
|
|
90
|
+
onLoadingChange?: (loading: boolean) => void;
|
|
82
91
|
/** Fired when the messenger is shown. */
|
|
83
92
|
onOpen?: () => void;
|
|
84
93
|
/** Fired when the messenger is hidden. */
|
|
@@ -124,17 +133,41 @@ export function ErxesMessenger({
|
|
|
124
133
|
launcherVisible,
|
|
125
134
|
homeActions = [],
|
|
126
135
|
drawerActions = [],
|
|
136
|
+
renderLoading,
|
|
127
137
|
onLoad,
|
|
128
138
|
onReady,
|
|
129
139
|
onOpen,
|
|
130
140
|
onClose,
|
|
131
141
|
onError,
|
|
132
142
|
onAction,
|
|
143
|
+
onLoadingChange,
|
|
133
144
|
}: ErxesMessengerProps) {
|
|
134
145
|
// Keep the latest actions/callback in refs so the action listener (registered
|
|
135
146
|
// once below) always dispatches against current props without re-subscribing.
|
|
136
147
|
const actionsRef = useRef<ErxesAction[]>([]);
|
|
137
148
|
const onActionRef = useRef(onAction);
|
|
149
|
+
const onLoadingChangeRef = useRef(onLoadingChange);
|
|
150
|
+
// Tracks whether we believe the messenger is currently presented, so we never
|
|
151
|
+
// double-present (chat mode auto-presents inside `configure()`) or fire a
|
|
152
|
+
// redundant show/hide. Native gives us no presentation callback, so this is our
|
|
153
|
+
// best-effort intent mirror.
|
|
154
|
+
const shownRef = useRef(false);
|
|
155
|
+
|
|
156
|
+
// Flips true only after native `configure()` resolves. The controlled-`visible`
|
|
157
|
+
// effect gates on this so it never calls `showMessenger()` before `configure()`
|
|
158
|
+
// (the native SDK asserts on that ordering).
|
|
159
|
+
const [configured, setConfigured] = useState(false);
|
|
160
|
+
// True while configuring (between `onLoad` and `onReady`/`onError`); drives
|
|
161
|
+
// `renderLoading`.
|
|
162
|
+
const [loading, setLoading] = useState(false);
|
|
163
|
+
|
|
164
|
+
useEffect(() => {
|
|
165
|
+
onLoadingChangeRef.current = onLoadingChange;
|
|
166
|
+
}, [onLoadingChange]);
|
|
167
|
+
|
|
168
|
+
useEffect(() => {
|
|
169
|
+
onLoadingChangeRef.current?.(loading);
|
|
170
|
+
}, [loading]);
|
|
138
171
|
|
|
139
172
|
useEffect(() => {
|
|
140
173
|
actionsRef.current = [...homeActions, ...drawerActions];
|
|
@@ -146,9 +179,17 @@ export function ErxesMessenger({
|
|
|
146
179
|
return;
|
|
147
180
|
}
|
|
148
181
|
|
|
182
|
+
setConfigured(false);
|
|
183
|
+
|
|
149
184
|
const helpers: ErxesMessengerHelpers = {
|
|
150
|
-
show: () =>
|
|
151
|
-
|
|
185
|
+
show: async () => {
|
|
186
|
+
await ErxesNativeIOS.showMessenger();
|
|
187
|
+
shownRef.current = true;
|
|
188
|
+
},
|
|
189
|
+
hide: async () => {
|
|
190
|
+
await ErxesNativeIOS.hideMessenger();
|
|
191
|
+
shownRef.current = false;
|
|
192
|
+
},
|
|
152
193
|
showLauncher: () => ErxesNativeIOS.showLauncher(),
|
|
153
194
|
hideLauncher: () => ErxesNativeIOS.hideLauncher(),
|
|
154
195
|
setUser: (nextUser) => ErxesNativeIOS.setUser(nextUser),
|
|
@@ -166,8 +207,16 @@ export function ErxesMessenger({
|
|
|
166
207
|
await onActionRef.current?.(id, helpers);
|
|
167
208
|
});
|
|
168
209
|
|
|
210
|
+
// Connection complete (native `MessengerSDK.isReady`): the messenger is
|
|
211
|
+
// truly ready, so end the loading state and notify the host.
|
|
212
|
+
const readySub = ErxesNativeIOS.addReadyListener(() => {
|
|
213
|
+
setLoading(false);
|
|
214
|
+
onReady?.();
|
|
215
|
+
});
|
|
216
|
+
|
|
169
217
|
async function setup() {
|
|
170
218
|
try {
|
|
219
|
+
setLoading(true);
|
|
171
220
|
onLoad?.();
|
|
172
221
|
|
|
173
222
|
if (user) {
|
|
@@ -186,19 +235,45 @@ export function ErxesMessenger({
|
|
|
186
235
|
drawerActions: stripActions(drawerActions),
|
|
187
236
|
});
|
|
188
237
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
238
|
+
// `configure()` only kicks off the async connect; `onReady` and the end
|
|
239
|
+
// of `loading` are driven by the ready listener above, not here.
|
|
240
|
+
|
|
241
|
+
// Decide the initial open state. If `visible` is controlled it wins;
|
|
242
|
+
// otherwise fall back to `autoOpen` (defaults to true in chat mode).
|
|
243
|
+
const shouldOpen = visible ?? autoOpen;
|
|
244
|
+
|
|
245
|
+
if (displayMode === 'chat') {
|
|
246
|
+
// Chat mode auto-presents itself inside `configure()` — never call
|
|
247
|
+
// `showMessenger()` for the initial open or we'd present a second one.
|
|
248
|
+
if (shouldOpen) {
|
|
249
|
+
shownRef.current = true;
|
|
250
|
+
onOpen?.();
|
|
251
|
+
} else {
|
|
252
|
+
// Caller wants it closed: undo the native auto-present.
|
|
253
|
+
await ErxesNativeIOS.hideMessenger();
|
|
254
|
+
shownRef.current = false;
|
|
255
|
+
}
|
|
256
|
+
} else {
|
|
257
|
+
// Classic mode: configure does not open anything. Show the launcher
|
|
258
|
+
// and/or present the sheet explicitly.
|
|
259
|
+
if (launcherVisible === true) {
|
|
260
|
+
await ErxesNativeIOS.showLauncher();
|
|
261
|
+
} else if (launcherVisible === false) {
|
|
262
|
+
await ErxesNativeIOS.hideLauncher();
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
if (shouldOpen) {
|
|
266
|
+
await ErxesNativeIOS.showMessenger();
|
|
267
|
+
shownRef.current = true;
|
|
268
|
+
onOpen?.();
|
|
269
|
+
}
|
|
194
270
|
}
|
|
195
271
|
|
|
196
|
-
|
|
197
|
-
await ErxesNativeIOS.showLauncher();
|
|
198
|
-
} else if (launcherVisible === false) {
|
|
199
|
-
await ErxesNativeIOS.hideLauncher();
|
|
200
|
-
}
|
|
272
|
+
setConfigured(true);
|
|
201
273
|
} catch (error) {
|
|
274
|
+
// Setup failed before the connection could complete — end loading here
|
|
275
|
+
// since the ready listener will never fire.
|
|
276
|
+
setLoading(false);
|
|
202
277
|
onError?.(error);
|
|
203
278
|
}
|
|
204
279
|
}
|
|
@@ -207,9 +282,11 @@ export function ErxesMessenger({
|
|
|
207
282
|
|
|
208
283
|
return () => {
|
|
209
284
|
sub.remove();
|
|
285
|
+
readySub.remove();
|
|
210
286
|
|
|
211
|
-
if (autoHideOnUnmount) {
|
|
287
|
+
if (autoHideOnUnmount && shownRef.current) {
|
|
212
288
|
ErxesNativeIOS.hideMessenger();
|
|
289
|
+
shownRef.current = false;
|
|
213
290
|
onClose?.();
|
|
214
291
|
}
|
|
215
292
|
};
|
|
@@ -219,19 +296,28 @@ export function ErxesMessenger({
|
|
|
219
296
|
}, [integrationId, endpoint, serverUrl, subDomain, displayMode]);
|
|
220
297
|
|
|
221
298
|
useEffect(() => {
|
|
222
|
-
|
|
299
|
+
// Wait until `configure()` has resolved — otherwise `showMessenger()` would
|
|
300
|
+
// race ahead of it and trip the native configure-before-show assertion. The
|
|
301
|
+
// initial open is handled in `setup()`; this only reacts to later changes.
|
|
302
|
+
if (Platform.OS !== 'ios' || visible === undefined || !configured) {
|
|
223
303
|
return;
|
|
224
304
|
}
|
|
225
305
|
|
|
226
|
-
if (visible) {
|
|
306
|
+
if (visible && !shownRef.current) {
|
|
227
307
|
ErxesNativeIOS.showMessenger();
|
|
308
|
+
shownRef.current = true;
|
|
228
309
|
onOpen?.();
|
|
229
|
-
} else {
|
|
310
|
+
} else if (!visible && shownRef.current) {
|
|
230
311
|
ErxesNativeIOS.hideMessenger();
|
|
312
|
+
shownRef.current = false;
|
|
231
313
|
onClose?.();
|
|
232
314
|
}
|
|
233
315
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
234
|
-
}, [visible]);
|
|
316
|
+
}, [visible, configured]);
|
|
317
|
+
|
|
318
|
+
if (loading && renderLoading) {
|
|
319
|
+
return renderLoading();
|
|
320
|
+
}
|
|
235
321
|
|
|
236
322
|
return null;
|
|
237
323
|
}
|
package/src/nativeIos.ts
CHANGED
|
@@ -56,6 +56,9 @@ type NativeIOSModule = {
|
|
|
56
56
|
/** Native event name emitted when a chat-mode action is tapped. */
|
|
57
57
|
const ACTION_EVENT = 'onErxesAction';
|
|
58
58
|
|
|
59
|
+
/** Native event name emitted when the connect handshake completes. */
|
|
60
|
+
const READY_EVENT = 'onErxesReady';
|
|
61
|
+
|
|
59
62
|
const LINKING_ERROR =
|
|
60
63
|
"The rn-erxes-sdk native iOS module is not linked. Run `pod install` in your app's ios directory and rebuild the app.";
|
|
61
64
|
|
|
@@ -118,6 +121,18 @@ export const ErxesNativeIOS = {
|
|
|
118
121
|
handler(event.id)
|
|
119
122
|
);
|
|
120
123
|
},
|
|
124
|
+
/**
|
|
125
|
+
* Listen for the connect handshake completing — i.e. the messenger is ready
|
|
126
|
+
* (`MessengerSDK.isReady`). Fires once per connection; if already connected
|
|
127
|
+
* when you subscribe via a fresh `configure`, it fires again. Returns a
|
|
128
|
+
* subscription — call `.remove()` to stop listening.
|
|
129
|
+
*/
|
|
130
|
+
addReadyListener(handler: () => void): EmitterSubscription {
|
|
131
|
+
const emitter = new NativeEventEmitter(
|
|
132
|
+
getNativeModule() as unknown as NativeModule
|
|
133
|
+
);
|
|
134
|
+
return emitter.addListener(READY_EVENT, () => handler());
|
|
135
|
+
},
|
|
121
136
|
};
|
|
122
137
|
|
|
123
138
|
export type { NativeIOSAction, NativeIOSConfig, NativeIOSUser };
|