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 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:
@@ -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: () => _nativeIos.ErxesNativeIOS.showMessenger(),
87
- hide: () => _nativeIos.ErxesNativeIOS.hideMessenger(),
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
- 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();
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
- if (autoHideOnUnmount) {
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
- if (_reactNative.Platform.OS !== 'ios' || visible === undefined) {
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","call","setup","configure","error","remove","undefined"],"sourceRoot":"../../src","sources":["ErxesMessenger.tsx"],"mappings":"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"}
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":"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"}
@@ -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;AAEpC,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,CAAClC,YAAY,EAAGmC,KAAqB,IAC7DJ,OAAO,CAACI,KAAK,CAACC,EAAE,CAClB,CAAC;EACH;AACF,CAAC;AAACC,OAAA,CAAA5B,cAAA,GAAAA,cAAA"}
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: () => ErxesNativeIOS.showMessenger(),
82
- hide: () => ErxesNativeIOS.hideMessenger(),
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
- 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();
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
- if (autoHideOnUnmount) {
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
- if (Platform.OS !== 'ios' || visible === undefined) {
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","call","setup","configure","error","remove","undefined"],"sourceRoot":"../../src","sources":["ErxesMessenger.tsx"],"mappings":"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"}
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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"}
@@ -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;AAEpC,MAAMC,aAAa,GACjB,sHAAsH;AAExH,MAAMC,YAAY,GAAGJ,aAAa,CAACK,UAAyC;AAE5E,SAASC,eAAeA,CAAA,EAAoB;EAC1C,IAAIL,QAAQ,CAACM,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,IAAIjC,kBAAkB,CACpCO,eAAe,CAAC,CAClB,CAAC;IACD,OAAO0B,OAAO,CAACC,WAAW,CAAC/B,YAAY,EAAGgC,KAAqB,IAC7DH,OAAO,CAACG,KAAK,CAACC,EAAE,CAClB,CAAC;EACH;AACF,CAAC"}
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 after native `configure` succeeds. */
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): null;
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":"AAGA,OAAO,EAAkB,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjE;;;GAGG;AACH,MAAM,MAAM,SAAS,GAAG,aAAa,CAAC;AAEtC;;;;GAIG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAClC,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,YAAY,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAClC,YAAY,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAClC,OAAO,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5C,SAAS,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAChC,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB,oEAAoE;IACpE,EAAE,EAAE,MAAM,CAAC;IACX,0EAA0E;IAC1E,KAAK,EAAE,MAAM,CAAC;IACd,iDAAiD;IACjD,UAAU,EAAE,MAAM,CAAC;IACnB,0FAA0F;IAC1F,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,qBAAqB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACpE,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,gDAAgD;IAChD,aAAa,EAAE,MAAM,CAAC;IAEtB,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4BAA4B;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2DAA2D;IAC3D,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,6EAA6E;IAC7E,WAAW,CAAC,EAAE,SAAS,GAAG,MAAM,CAAC;IAEjC,2CAA2C;IAC3C,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,6CAA6C;IAC7C,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B,8DAA8D;IAC9D,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,mEAAmE;IACnE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,2EAA2E;IAC3E,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,0EAA0E;IAC1E,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,6EAA6E;IAC7E,eAAe,CAAC,EAAE,OAAO,CAAC;IAE1B,8DAA8D;IAC9D,WAAW,CAAC,EAAE,WAAW,EAAE,CAAC;IAC5B,gEAAgE;IAChE,aAAa,CAAC,EAAE,WAAW,EAAE,CAAC;IAE9B,+BAA+B;IAC/B,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,+CAA+C;IAC/C,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,yCAAyC;IACzC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,0CAA0C;IAC1C,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,wCAAwC;IACxC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IACnC,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,CACT,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,qBAAqB,KAC3B,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3B,CAAC;AAWF;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,EAC7B,aAAa,EACb,QAAQ,EACR,SAAS,EACT,SAAS,EACT,WAAuB,EACvB,IAAI,EACJ,gBAAgB,EAChB,YAAY,EACZ,OAAO,EACP,QAAiC,EACjC,iBAAwB,EACxB,eAAe,EACf,WAAgB,EAChB,aAAkB,EAClB,MAAM,EACN,OAAO,EACP,MAAM,EACN,OAAO,EACP,OAAO,EACP,QAAQ,GACT,EAAE,mBAAmB,QAwGrB"}
1
+ {"version":3,"file":"ErxesMessenger.d.ts","sourceRoot":"","sources":["../../src/ErxesMessenger.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA+B,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAGpE,OAAO,EAAkB,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjE;;;GAGG;AACH,MAAM,MAAM,SAAS,GAAG,aAAa,CAAC;AAEtC;;;;GAIG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAClC,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,YAAY,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAClC,YAAY,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAClC,OAAO,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5C,SAAS,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAChC,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB,oEAAoE;IACpE,EAAE,EAAE,MAAM,CAAC;IACX,0EAA0E;IAC1E,KAAK,EAAE,MAAM,CAAC;IACd,iDAAiD;IACjD,UAAU,EAAE,MAAM,CAAC;IACnB,0FAA0F;IAC1F,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,qBAAqB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACpE,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,gDAAgD;IAChD,aAAa,EAAE,MAAM,CAAC;IAEtB,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4BAA4B;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2DAA2D;IAC3D,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,6EAA6E;IAC7E,WAAW,CAAC,EAAE,SAAS,GAAG,MAAM,CAAC;IAEjC,2CAA2C;IAC3C,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,6CAA6C;IAC7C,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B,8DAA8D;IAC9D,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,mEAAmE;IACnE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,2EAA2E;IAC3E,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,0EAA0E;IAC1E,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,6EAA6E;IAC7E,eAAe,CAAC,EAAE,OAAO,CAAC;IAE1B,8DAA8D;IAC9D,WAAW,CAAC,EAAE,WAAW,EAAE,CAAC;IAC5B,gEAAgE;IAChE,aAAa,CAAC,EAAE,WAAW,EAAE,CAAC;IAE9B;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,SAAS,CAAC;IAEhC,+BAA+B;IAC/B,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,8EAA8E;IAC9E,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,uEAAuE;IACvE,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IAC7C,yCAAyC;IACzC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,0CAA0C;IAC1C,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,wCAAwC;IACxC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IACnC,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,CACT,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,qBAAqB,KAC3B,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3B,CAAC;AAWF;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,EAC7B,aAAa,EACb,QAAQ,EACR,SAAS,EACT,SAAS,EACT,WAAuB,EACvB,IAAI,EACJ,gBAAgB,EAChB,YAAY,EACZ,OAAO,EACP,QAAiC,EACjC,iBAAwB,EACxB,eAAe,EACf,WAAgB,EAChB,aAAkB,EAClB,aAAa,EACb,MAAM,EACN,OAAO,EACP,MAAM,EACN,OAAO,EACP,OAAO,EACP,QAAQ,EACR,eAAe,GAChB,EAAE,mBAAmB,aAmLrB"}
@@ -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;AAgCF,eAAO,MAAM,cAAc;uBACN,eAAe;qBAGjB,aAAa;;;;;;IA2B9B;;;;;OAKG;oCAC6B,MAAM,KAAK,IAAI,GAAG,mBAAmB;CAQtE,CAAC;AAEF,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,aAAa,EAAE,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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rn-erxes-sdk",
3
- "version": "0.3.4",
3
+ "version": "0.4.0",
4
4
  "description": "react-native erxes sdk",
5
5
  "main": "lib/commonjs/index",
6
6
  "module": "lib/module/index",
@@ -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 after native `configure` succeeds. */
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: () => ErxesNativeIOS.showMessenger(),
151
- hide: () => ErxesNativeIOS.hideMessenger(),
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
- onReady?.();
190
-
191
- if (autoOpen) {
192
- await ErxesNativeIOS.showMessenger();
193
- onOpen?.();
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
- if (launcherVisible === true) {
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
- if (Platform.OS !== 'ios' || visible === undefined) {
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 };