rn-erxes-sdk 0.1.26 → 0.2.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
@@ -93,275 +93,107 @@ erxes is composed of 2 main components: **XOS** & **Plugins**
93
93
 
94
94
  # rn-erxes-sdk
95
95
 
96
- A React Native SDK for embedding the [erxes](https://erxes.io/) messenger experience inside a mobile application. It renders the erxes messenger UI, connects the visitor/customer to your erxes messenger integration, and handles conversations, unread counts, and message subscriptions for you.
96
+ A React Native bridge for the native SwiftUI erxes messenger
97
+ ([`erxes/erxes-ios-sdk`](https://github.com/erxes/erxes-ios-sdk) `0.30.0`).
97
98
 
98
- It works in Expo (managed) and bare React Native apps.
99
-
100
- ## Installation
101
-
102
- Install the SDK with Yarn:
103
-
104
- ```bash
105
- yarn add rn-erxes-sdk
106
- ```
107
-
108
- or npm:
109
-
110
- ```bash
111
- npm install --save rn-erxes-sdk
112
- ```
113
-
114
- ```bash
115
- npm i rn-erxes-sdk
99
+ ```tsx
100
+ import { ErxesNativeIOS } from 'rn-erxes-sdk';
116
101
  ```
117
102
 
118
- These commands install the latest version published to **npm** (currently `0.1.26`). To install or upgrade to a specific version, pin it explicitly:
103
+ ## Requirements
119
104
 
120
- ```bash
121
- yarn add rn-erxes-sdk@0.1.26
122
- ```
105
+ | | |
106
+ |---|---|
107
+ | iOS | 16.0+ |
108
+ | Swift | 5.9+ |
109
+ | React Native | 0.81+ |
110
+ | Expo SDK | 53+ (development build or prebuild — Expo Go not supported) |
123
111
 
124
- ```bash
125
- npm i rn-erxes-sdk@0.1.26
126
- ```
112
+ ## Docs
127
113
 
128
- Pushing code to GitHub does **not** automatically update the npm package — a new version must be published explicitly (see [Maintainer workflow](#maintainer-workflow)).
114
+ - [Native iOS guide](docs/native-ios.md)
129
115
 
130
- ## Required peer dependencies
116
+ ## Installation
131
117
 
132
- The SDK relies on the following native packages, which must be installed in the host app:
118
+ ### Bare React Native
133
119
 
134
120
  ```bash
135
- npx expo install @react-native-async-storage/async-storage
136
- yarn add react-native-get-random-values
121
+ yarn add rn-erxes-sdk
122
+ cd ios && pod install
137
123
  ```
138
124
 
139
- npm equivalent:
125
+ ### Expo
140
126
 
141
127
  ```bash
142
- npx expo install @react-native-async-storage/async-storage
143
- npm install --save react-native-get-random-values
128
+ npx expo install rn-erxes-sdk expo-build-properties
144
129
  ```
145
130
 
146
- - **`@react-native-async-storage/async-storage`** — required. Used to cache the customer id and conversation id between launches.
147
- - **`react-native-get-random-values`** — required. The SDK imports it internally to polyfill `crypto.getRandomValues`, which is used to generate a guest visitor id. It must be present in the host app's dependency tree.
131
+ Add to `app.json`:
148
132
 
149
- ### Optional
150
-
151
- ```bash
152
- npx expo install expo-image-picker
133
+ ```json
134
+ {
135
+ "plugins": [
136
+ ["expo-build-properties", { "ios": { "deploymentTarget": "16.0" } }]
137
+ ]
138
+ }
153
139
  ```
154
140
 
155
- - **`expo-image-picker`** — optional. If installed, the messenger lets users attach images from their library. The SDK loads it lazily, so the attachment button is simply hidden when it is not installed. (Bare React Native apps may use `react-native-image-picker` instead — it is detected the same way.)
156
-
157
- ## Quick start with Expo
158
-
159
141
  ```bash
160
- npx create-expo-app@latest rn-erxes-sdk-test
161
- cd rn-erxes-sdk-test
162
-
163
- yarn add rn-erxes-sdk
164
- npx expo install @react-native-async-storage/async-storage
165
- yarn add react-native-get-random-values
166
-
167
- npx expo start --clear
142
+ npx expo prebuild --platform ios
143
+ cd ios && pod install
144
+ npx expo run:ios
168
145
  ```
169
146
 
170
- npm alternative:
147
+ ## Usage
171
148
 
172
- ```bash
173
- npm install --save rn-erxes-sdk
174
- npx expo install @react-native-async-storage/async-storage
175
- npm install --save react-native-get-random-values
149
+ Call `configure` once at startup. It connects in the background so the messenger opens instantly.
176
150
 
177
- npx expo start --clear
178
- ```
179
-
180
- Render `<ErxesSDK />` from your app entry. In a classic Expo (`blank-typescript`) project that is `App.tsx`. In an Expo Router project the usage commonly lives in:
151
+ ```tsx
152
+ import { ErxesNativeIOS } from 'rn-erxes-sdk';
181
153
 
182
- ```text
183
- app/index.tsx
154
+ ErxesNativeIOS.configure({
155
+ integrationId: 'YOUR_INTEGRATION_ID',
156
+ subDomain: 'yourcompany.erxes.io',
157
+ });
184
158
  ```
185
159
 
186
- or:
160
+ Optionally identify the user:
187
161
 
188
- ```text
189
- src/app/index.tsx
162
+ ```tsx
163
+ ErxesNativeIOS.setUser({
164
+ email: 'user@example.com',
165
+ name: 'Jane Doe',
166
+ customData: { plan: 'pro' },
167
+ });
190
168
  ```
191
169
 
192
- ## Usage with Expo
193
-
194
- The example below separates three concerns:
170
+ ### Option A — Floating launcher (recommended)
195
171
 
196
- 1. authenticated customer-profile data taken from the host app's `currentUser` query,
197
- 2. browser/device/runtime metadata, and
198
- 3. the props passed to `ErxesSDK`.
172
+ Shows a draggable button over your app. Tapping it opens the messenger automatically.
199
173
 
200
174
  ```tsx
201
- import * as React from 'react';
202
- import { Platform, View } from 'react-native';
203
- import { ErxesSDK } from 'rn-erxes-sdk';
204
-
205
- type CurrentUser = {
206
- firstName?: string;
207
- lastName?: string;
208
- primaryEmail?: string;
209
- primaryPhone?: string;
210
- sex?: string | number;
211
- propertiesData?: Record<string, unknown>;
212
- };
213
-
214
- type Props = {
215
- currentUser?: CurrentUser;
216
- };
217
-
218
- export default function App({ currentUser }: Props) {
219
- const integrationId = 'YOUR_INTEGRATION_ID';
220
- const subDomain = 'YOUR_SUBDOMAIN.next.erxes.io';
221
-
222
- const data = {
223
- firstName: currentUser?.firstName ?? '',
224
- lastName: currentUser?.lastName ?? '',
225
- primaryEmail: currentUser?.primaryEmail ?? '',
226
- sex: currentUser?.sex ?? '',
227
- Type: 'mobile',
228
- ...currentUser?.propertiesData,
229
- };
230
-
231
- const properties = {
232
- remoteAddress: '',
233
- region: '',
234
- countryCode: '',
235
- city: '',
236
- country: '',
237
- url: 'https://YOUR_SUBDOMAIN.nextwidgets.erxes.io/',
238
- hostname: 'YOUR_SUBDOMAIN.nextwidgets.erxes.io',
239
- language: 'en-US',
240
- userAgent: Platform.OS,
241
- };
242
-
243
- return (
244
- <View style={{ flex: 1 }}>
245
- <ErxesSDK
246
- integrationId={integrationId}
247
- subDomain={subDomain}
248
- onBack={() => console.log('onBack')}
249
- showWidget={false}
250
- phone={currentUser?.primaryPhone ?? ''}
251
- data={data}
252
- properties={properties}
253
- />
254
- </View>
255
- );
256
- }
175
+ ErxesNativeIOS.showLauncher();
176
+ // ErxesNativeIOS.hideLauncher(); // to remove it
257
177
  ```
258
178
 
259
- Notes:
260
-
261
- - The exact `currentUser` query depends on your host application — the SDK does not provide it.
262
- - `data` should normally be mapped from the authenticated user's query result rather than hardcoded.
263
- - Do not hardcode private customer information in production.
264
- - Empty property values are acceptable when metadata is unavailable.
265
- - Do not fake IP addresses or location values.
266
- - Replace `YOUR_INTEGRATION_ID` and `YOUR_SUBDOMAIN` with the values from your erxes environment.
267
- - `Platform.OS` is only a lightweight fallback for `userAgent`; it is not a complete browser user-agent string.
179
+ ### Option B — Your own button
268
180
 
269
- ## Customer data from `currentUser`
270
-
271
- `data` is customer-profile information. It is forwarded to the erxes `widgetsMessengerConnect` mutation (as the `data` JSON argument) when the SDK connects, and is used to create or identify the customer.
181
+ If you have a custom trigger in your UI, call `showMessenger()` directly:
272
182
 
273
183
  ```tsx
274
- const data = {
275
- firstName: currentUser?.firstName ?? '',
276
- lastName: currentUser?.lastName ?? '',
277
- primaryEmail: currentUser?.primaryEmail ?? '',
278
- sex: currentUser?.sex ?? '',
279
- Type: 'mobile',
280
- ...currentUser?.propertiesData,
281
- };
184
+ <Button title="Support" onPress={() => ErxesNativeIOS.showMessenger()} />
282
185
  ```
283
186
 
284
- - This normally comes from the host application's authenticated-user query.
285
- - Custom fields may be included when relevant (e.g. spread from `propertiesData`).
286
- - `data` is optional — when omitted, the visitor is connected as a guest.
287
- - Do not use fake values in production.
288
-
289
- ## Browser and device information
290
-
291
- `properties` describes the browser, device, and runtime environment. When the SDK has an identified customer, it sends these values to the erxes `widgetsSaveBrowserInfo` mutation internally — **you do not call it yourself**, you only pass the `properties` prop.
187
+ On logout:
292
188
 
293
189
  ```tsx
294
- const properties = {
295
- remoteAddress: '',
296
- region: '',
297
- countryCode: '',
298
- city: '',
299
- country: '',
300
- url: 'https://YOUR_SUBDOMAIN.nextwidgets.erxes.io/',
301
- hostname: 'YOUR_SUBDOMAIN.nextwidgets.erxes.io',
302
- language: 'en-US',
303
- userAgent: 'DEVICE_USER_AGENT',
304
- };
305
- ```
306
-
307
- - Empty strings are acceptable when a value is unavailable.
308
- - Do not fake IP addresses or location values.
309
- - Collect real runtime values where possible.
310
-
311
- For reference, the mutation the SDK calls internally is:
312
-
313
- ```graphql
314
- mutation widgetsSaveBrowserInfo(
315
- $customerId: String
316
- $visitorId: String
317
- $browserInfo: JSON!
318
- ) {
319
- widgetsSaveBrowserInfo(
320
- customerId: $customerId
321
- visitorId: $visitorId
322
- browserInfo: $browserInfo
323
- ) {
324
- _id
325
- conversationId
326
- customerId
327
- }
328
- }
190
+ ErxesNativeIOS.clearUser();
329
191
  ```
330
192
 
331
- The SDK passes the connected `customerId` together with your `properties` object as `browserInfo`. The customer id and visitor id are managed by the SDK:
332
-
333
- - On first launch the SDK generates a guest **visitor id** (a 24-character hex string) and uses it to connect.
334
- - After connecting, the resolved **customer id** is cached in `AsyncStorage` and reused on later launches.
335
-
336
- You only pass the relevant props (`data`, `properties`, `phone`); you should not duplicate this connect / save-browser-info flow yourself.
337
-
338
- ## Props
339
-
340
- Public props of `ErxesSDK` (from the SDK's TypeScript types):
341
-
342
- | Prop | Type | Required | Description |
343
- | --- | --- | --- | --- |
344
- | `integrationId` | `string` | Yes | erxes messenger integration id used to connect. |
345
- | `subDomain` | `string` | Yes | erxes environment subdomain (e.g. `YOUR_SUBDOMAIN.next.erxes.io`); used to build the GraphQL/WS endpoints and asset URLs. |
346
- | `showWidget` | `boolean` | Yes | When `true`, renders the floating launcher button; when `false`, renders the messenger inline. |
347
- | `brandCode` | `string` | No | Brand code; used as a fallback when `integrationId` is not provided. |
348
- | `email` | `string` | No | When set, the contact is connected as an identified user (`isUser`). |
349
- | `onBack` | `() => void` | No | Called when the user navigates back from the messenger. |
350
- | `phone` | `string` | No | Phone number used to identify the customer on connect. |
351
- | `data` | `object` | No | Customer-profile data forwarded to `widgetsMessengerConnect`. |
352
- | `properties` | `object` | No | Browser/device metadata sent as `browserInfo` to `widgetsSaveBrowserInfo`. |
353
- | `backIcon` | `ImageSource` | No | Custom back icon. |
354
- | `newChatIcon` | `ImageSource` | No | Custom "new chat" icon. |
355
- | `sendIcon` | `ImageSource` | No | Custom send icon. |
193
+ Full example: [Native iOS guide](docs/native-ios.md).
356
194
 
357
195
  ## Troubleshooting
358
196
 
359
- ### Clear Expo cache
360
-
361
- ```bash
362
- npx expo start --clear
363
- ```
364
-
365
197
  ### Confirm the installed version
366
198
 
367
199
  ```bash
@@ -378,30 +210,25 @@ npm ls rn-erxes-sdk
378
210
 
379
211
  ```bash
380
212
  yarn add rn-erxes-sdk@latest
381
- npx expo start --clear
382
213
  ```
383
214
 
384
215
  or:
385
216
 
386
217
  ```bash
387
218
  npm install --save rn-erxes-sdk@latest
388
- npx expo start --clear
389
219
  ```
390
220
 
391
- ### Native dependencies
392
-
393
- The required peer dependencies (`@react-native-async-storage/async-storage`, `react-native-get-random-values`) must be installed in the **host app**. The SDK does not bundle them.
394
-
395
- ### `await is not defined` (BSON Metro crash)
221
+ After upgrading, reinstall pods and rebuild the app:
396
222
 
397
- Older SDK releases depended on `bson`, which could cause Metro/Hermes to crash at startup with:
398
-
399
- ```text
400
- await is not defined
401
- node_modules/bson/lib/bson.mjs
223
+ ```bash
224
+ cd ios
225
+ pod install
402
226
  ```
403
227
 
404
- This happened because Expo resolves packages through their ESM `exports` map and picked `bson/lib/bson.mjs`, which uses a top-level `await`. **Upgrade to the latest `rn-erxes-sdk` release** — it no longer depends on `bson`. A custom Metro config change is not required.
228
+ ### Expo Go
229
+
230
+ This package uses native Swift code and does not run in Expo Go. Use an Expo
231
+ development build or a bare React Native app.
405
232
 
406
233
  ## Maintainer workflow
407
234
 
@@ -0,0 +1,170 @@
1
+ # Native iOS Guide
2
+
3
+ `ErxesNativeIOS` bridges the native SwiftUI erxes messenger
4
+ ([`erxes/erxes-ios-sdk`](https://github.com/erxes/erxes-ios-sdk) `0.30.0`)
5
+ into your React Native app.
6
+
7
+ ## Requirements
8
+
9
+ | | |
10
+ |---|---|
11
+ | iOS | 16.0+ |
12
+ | Swift | 5.9+ |
13
+ | React Native | 0.81+ |
14
+ | Expo SDK | 53+ (development build or prebuild only — Expo Go not supported) |
15
+
16
+ ---
17
+
18
+ ## Installation
19
+
20
+ ### Bare React Native
21
+
22
+ ```bash
23
+ yarn add rn-erxes-sdk
24
+ cd ios && pod install
25
+ ```
26
+
27
+ ### Expo
28
+
29
+ Expo Go cannot load custom native modules. You need a development build or prebuild.
30
+
31
+ ```bash
32
+ npx expo install rn-erxes-sdk expo-build-properties
33
+ ```
34
+
35
+ Set the minimum iOS deployment target in `app.json`:
36
+
37
+ ```json
38
+ {
39
+ "plugins": [
40
+ ["expo-build-properties", { "ios": { "deploymentTarget": "16.0" } }]
41
+ ]
42
+ }
43
+ ```
44
+
45
+ Prebuild and install pods:
46
+
47
+ ```bash
48
+ npx expo prebuild --platform ios
49
+ cd ios && pod install
50
+ npx expo run:ios
51
+ ```
52
+
53
+ ---
54
+
55
+ ## Setup
56
+
57
+ Call `configure` once at app startup (e.g. inside `useEffect` in your root component). This starts the connection handshake in the background so the messenger is ready instantly when the user opens it.
58
+
59
+ ```tsx
60
+ import { ErxesNativeIOS } from 'rn-erxes-sdk';
61
+
62
+ ErxesNativeIOS.configure({
63
+ integrationId: 'YOUR_INTEGRATION_ID',
64
+ subDomain: 'yourcompany.erxes.io',
65
+ });
66
+ ```
67
+
68
+ You can pass `endpoint` instead of `subDomain`:
69
+
70
+ ```tsx
71
+ ErxesNativeIOS.configure({
72
+ integrationId: 'YOUR_INTEGRATION_ID',
73
+ endpoint: 'https://yourcompany.erxes.io',
74
+ });
75
+ ```
76
+
77
+ Optionally identify the logged-in user:
78
+
79
+ ```tsx
80
+ ErxesNativeIOS.setUser({
81
+ email: 'user@example.com',
82
+ phone: '+15551234567',
83
+ name: 'Jane Doe',
84
+ customData: { plan: 'pro' }, // any key-value pairs
85
+ });
86
+ ```
87
+
88
+ ---
89
+
90
+ ## Showing the messenger
91
+
92
+ There are two ways to let users open the messenger. Pick one.
93
+
94
+ ### Option A — Floating launcher button (recommended)
95
+
96
+ Call `showLauncher()` after `configure()`. A draggable floating button appears on screen automatically once the SDK connects. The user taps it to open the messenger. No extra code needed.
97
+
98
+ ```tsx
99
+ ErxesNativeIOS.configure({ integrationId, subDomain });
100
+ ErxesNativeIOS.showLauncher();
101
+ ```
102
+
103
+ To remove the launcher (e.g. on certain screens or after logout):
104
+
105
+ ```tsx
106
+ ErxesNativeIOS.hideLauncher();
107
+ ```
108
+
109
+ ### Option B — Your own button
110
+
111
+ If you have a custom button, tab, or trigger in your own UI, call `showMessenger()` directly. Skip `showLauncher()`.
112
+
113
+ ```tsx
114
+ ErxesNativeIOS.configure({ integrationId, subDomain });
115
+
116
+ // somewhere in your UI:
117
+ <Button title="Support" onPress={() => ErxesNativeIOS.showMessenger()} />
118
+ ```
119
+
120
+ ---
121
+
122
+ ## Logout
123
+
124
+ Clear the user when they log out of your app:
125
+
126
+ ```tsx
127
+ ErxesNativeIOS.clearUser();
128
+ ```
129
+
130
+ ---
131
+
132
+ ## Full example
133
+
134
+ ```tsx
135
+ import React, { useEffect } from 'react';
136
+ import { View, Button } from 'react-native';
137
+ import { ErxesNativeIOS } from 'rn-erxes-sdk';
138
+
139
+ export default function App() {
140
+ useEffect(() => {
141
+ ErxesNativeIOS.configure({
142
+ integrationId: 'YOUR_INTEGRATION_ID',
143
+ subDomain: 'yourcompany.erxes.io',
144
+ primaryColor: '#3f78d9',
145
+ });
146
+
147
+ ErxesNativeIOS.setUser({
148
+ email: 'user@example.com',
149
+ name: 'Jane Doe',
150
+ });
151
+
152
+ // Show floating launcher — remove this if you use your own button instead
153
+ ErxesNativeIOS.showLauncher();
154
+ }, []);
155
+
156
+ return <View style={{ flex: 1 }} />;
157
+ }
158
+ ```
159
+
160
+ ---
161
+
162
+ ## Troubleshooting
163
+
164
+ **Native module not found** — run `pod install` and rebuild:
165
+ ```bash
166
+ cd ios && pod install
167
+ npx react-native run-ios # or: npx expo run:ios
168
+ ```
169
+
170
+ **Expo Go** — not supported. Build a development client with `npx expo run:ios`.
@@ -0,0 +1,25 @@
1
+ #import <React/RCTBridgeModule.h>
2
+
3
+ @interface RCT_EXTERN_MODULE(RnErxesSdk, NSObject)
4
+
5
+ RCT_EXTERN_METHOD(configure:(NSDictionary *)options
6
+ resolver:(RCTPromiseResolveBlock)resolve
7
+ rejecter:(RCTPromiseRejectBlock)reject)
8
+
9
+ RCT_EXTERN_METHOD(setUser:(NSDictionary *)options
10
+ resolver:(RCTPromiseResolveBlock)resolve
11
+ rejecter:(RCTPromiseRejectBlock)reject)
12
+
13
+ RCT_EXTERN_METHOD(clearUser:(RCTPromiseResolveBlock)resolve
14
+ rejecter:(RCTPromiseRejectBlock)reject)
15
+
16
+ RCT_EXTERN_METHOD(showMessenger:(RCTPromiseResolveBlock)resolve
17
+ rejecter:(RCTPromiseRejectBlock)reject)
18
+
19
+ RCT_EXTERN_METHOD(showLauncher:(RCTPromiseResolveBlock)resolve
20
+ rejecter:(RCTPromiseRejectBlock)reject)
21
+
22
+ RCT_EXTERN_METHOD(hideLauncher:(RCTPromiseResolveBlock)resolve
23
+ rejecter:(RCTPromiseRejectBlock)reject)
24
+
25
+ @end
@@ -0,0 +1,189 @@
1
+ import Foundation
2
+ import MessengerSDK
3
+ import UIKit
4
+ import React
5
+
6
+ @objc(RnErxesSdk)
7
+ final class RnErxesSdk: NSObject {
8
+ @objc
9
+ static func requiresMainQueueSetup() -> Bool {
10
+ true
11
+ }
12
+
13
+ @objc(configure:resolver:rejecter:)
14
+ func configure(
15
+ _ options: NSDictionary,
16
+ resolver resolve: @escaping RCTPromiseResolveBlock,
17
+ rejecter reject: @escaping RCTPromiseRejectBlock
18
+ ) {
19
+ Task { @MainActor in
20
+ guard let integrationId = options["integrationId"] as? String, !integrationId.isEmpty else {
21
+ reject("missing_integration_id", "integrationId is required", nil)
22
+ return
23
+ }
24
+
25
+ guard let endpoint = Self.endpoint(from: options) else {
26
+ reject("missing_endpoint", "endpoint, serverUrl, or subDomain is required", nil)
27
+ return
28
+ }
29
+
30
+ let cachedCustomerId = Self.string(options["cachedCustomerId"])
31
+
32
+ MessengerSDK.configure(
33
+ MessengerConfig(
34
+ endpoint: endpoint,
35
+ integrationId: integrationId,
36
+ cachedCustomerId: cachedCustomerId
37
+ )
38
+ )
39
+
40
+ resolve(nil)
41
+ }
42
+ }
43
+
44
+ @objc(setUser:resolver:rejecter:)
45
+ func setUser(
46
+ _ options: NSDictionary,
47
+ resolver resolve: @escaping RCTPromiseResolveBlock,
48
+ rejecter reject: @escaping RCTPromiseRejectBlock
49
+ ) {
50
+ Task { @MainActor in
51
+ let email = Self.string(options["email"])
52
+ let phone = Self.string(options["phone"])
53
+ let name = Self.string(options["name"])
54
+ let customData = Self.stringDictionary(options["customData"])
55
+
56
+ MessengerSDK.setUser(
57
+ MessengerUser(
58
+ email: email,
59
+ phone: phone,
60
+ name: name,
61
+ customData: customData
62
+ )
63
+ )
64
+
65
+ resolve(nil)
66
+ }
67
+ }
68
+
69
+ @objc(clearUser:rejecter:)
70
+ func clearUser(
71
+ _ resolve: @escaping RCTPromiseResolveBlock,
72
+ rejecter reject: @escaping RCTPromiseRejectBlock
73
+ ) {
74
+ Task { @MainActor in
75
+ MessengerSDK.clearUser()
76
+ resolve(nil)
77
+ }
78
+ }
79
+
80
+ @objc(showMessenger:rejecter:)
81
+ func showMessenger(
82
+ _ resolve: @escaping RCTPromiseResolveBlock,
83
+ rejecter reject: @escaping RCTPromiseRejectBlock
84
+ ) {
85
+ Task { @MainActor in
86
+ guard let presenter = Self.topViewController() else {
87
+ reject("missing_presenter", "Unable to find a view controller to present from", nil)
88
+ return
89
+ }
90
+
91
+ MessengerSDK.showMessenger(from: presenter)
92
+ resolve(nil)
93
+ }
94
+ }
95
+
96
+ @objc(showLauncher:rejecter:)
97
+ func showLauncher(
98
+ _ resolve: @escaping RCTPromiseResolveBlock,
99
+ rejecter reject: @escaping RCTPromiseRejectBlock
100
+ ) {
101
+ Task { @MainActor in
102
+ MessengerSDK.showLauncher()
103
+ resolve(nil)
104
+ }
105
+ }
106
+
107
+ @objc(hideLauncher:rejecter:)
108
+ func hideLauncher(
109
+ _ resolve: @escaping RCTPromiseResolveBlock,
110
+ rejecter reject: @escaping RCTPromiseRejectBlock
111
+ ) {
112
+ Task { @MainActor in
113
+ MessengerSDK.hideLauncher()
114
+ resolve(nil)
115
+ }
116
+ }
117
+
118
+ private static func endpoint(from options: NSDictionary) -> String? {
119
+ if let endpoint = string(options["endpoint"]) ?? string(options["serverUrl"]) {
120
+ return endpoint
121
+ }
122
+
123
+ guard let subDomain = string(options["subDomain"]) else {
124
+ return nil
125
+ }
126
+
127
+ if subDomain.hasPrefix("http://") || subDomain.hasPrefix("https://") {
128
+ return subDomain
129
+ }
130
+
131
+ return "https://\(subDomain)"
132
+ }
133
+
134
+ private static func string(_ value: Any?) -> String? {
135
+ guard let value else { return nil }
136
+
137
+ if let value = value as? String {
138
+ return value.isEmpty ? nil : value
139
+ }
140
+
141
+ if let value = value as? NSNumber {
142
+ return value.stringValue
143
+ }
144
+
145
+ return nil
146
+ }
147
+
148
+ private static func stringDictionary(_ value: Any?) -> [String: String] {
149
+ guard let dictionary = value as? [String: Any] else {
150
+ return [:]
151
+ }
152
+
153
+ return dictionary.reduce(into: [String: String]()) { result, item in
154
+ if let stringValue = string(item.value) {
155
+ result[item.key] = stringValue
156
+ }
157
+ }
158
+ }
159
+
160
+ @MainActor
161
+ private static func topViewController() -> UIViewController? {
162
+ topViewController(from: keyWindow()?.rootViewController)
163
+ }
164
+
165
+ @MainActor
166
+ private static func topViewController(from root: UIViewController?) -> UIViewController? {
167
+ if let navigation = root as? UINavigationController {
168
+ return topViewController(from: navigation.visibleViewController)
169
+ }
170
+
171
+ if let tab = root as? UITabBarController {
172
+ return topViewController(from: tab.selectedViewController)
173
+ }
174
+
175
+ if let presented = root?.presentedViewController {
176
+ return topViewController(from: presented)
177
+ }
178
+
179
+ return root
180
+ }
181
+
182
+ @MainActor
183
+ private static func keyWindow() -> UIWindow? {
184
+ UIApplication.shared.connectedScenes
185
+ .compactMap { $0 as? UIWindowScene }
186
+ .flatMap(\.windows)
187
+ .first { $0.isKeyWindow }
188
+ }
189
+ }
@@ -3,12 +3,11 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- Object.defineProperty(exports, "ErxesSDK", {
6
+ Object.defineProperty(exports, "ErxesNativeIOS", {
7
7
  enumerable: true,
8
8
  get: function () {
9
- return _App.default;
9
+ return _nativeIos.ErxesNativeIOS;
10
10
  }
11
11
  });
12
- var _App = _interopRequireDefault(require("./App"));
13
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
12
+ var _nativeIos = require("./nativeIos");
14
13
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["_App","_interopRequireDefault","require","obj","__esModule","default"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;;;;;;;;;;AAAA,IAAAA,IAAA,GAAAC,sBAAA,CAAAC,OAAA;AAA4C,SAAAD,uBAAAE,GAAA,WAAAA,GAAA,IAAAA,GAAA,CAAAC,UAAA,GAAAD,GAAA,KAAAE,OAAA,EAAAF,GAAA"}
1
+ {"version":3,"names":["_nativeIos","require"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;;;;;;;;;;AAAA,IAAAA,UAAA,GAAAC,OAAA"}
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.ErxesNativeIOS = void 0;
7
+ var _reactNative = require("react-native");
8
+ 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.";
9
+ const nativeModule = _reactNative.NativeModules.RnErxesSdk;
10
+ function getNativeModule() {
11
+ if (_reactNative.Platform.OS !== 'ios') {
12
+ throw new Error('Erxes native messenger is only available on iOS.');
13
+ }
14
+ if (!nativeModule) {
15
+ throw new Error(LINKING_ERROR);
16
+ }
17
+ return nativeModule;
18
+ }
19
+ const ErxesNativeIOS = {
20
+ configure(options) {
21
+ return getNativeModule().configure(options);
22
+ },
23
+ setUser(options) {
24
+ const customData = Object.fromEntries(Object.entries(options.customData ?? {}).filter(_ref => {
25
+ let [, value] = _ref;
26
+ return value !== null && value !== undefined;
27
+ }).map(_ref2 => {
28
+ let [key, value] = _ref2;
29
+ return [key, String(value)];
30
+ }));
31
+ return getNativeModule().setUser({
32
+ ...options,
33
+ customData
34
+ });
35
+ },
36
+ clearUser() {
37
+ return getNativeModule().clearUser();
38
+ },
39
+ showMessenger() {
40
+ return getNativeModule().showMessenger();
41
+ },
42
+ showLauncher() {
43
+ return getNativeModule().showLauncher();
44
+ },
45
+ hideLauncher() {
46
+ return getNativeModule().hideLauncher();
47
+ }
48
+ };
49
+ exports.ErxesNativeIOS = ErxesNativeIOS;
50
+ //# sourceMappingURL=nativeIos.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["_reactNative","require","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","exports"],"sourceRoot":"../../src","sources":["nativeIos.ts"],"mappings":";;;;;;AAAA,IAAAA,YAAA,GAAAC,OAAA;AA0BA,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;AACF,CAAC;AAACC,OAAA,CAAApB,cAAA,GAAAA,cAAA"}
@@ -1,2 +1,2 @@
1
- export { default as ErxesSDK } from './App';
1
+ export { ErxesNativeIOS } from './nativeIos';
2
2
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["default","ErxesSDK"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":"AAAA,SAASA,OAAO,IAAIC,QAAQ,QAAQ,OAAO"}
1
+ {"version":3,"names":["ErxesNativeIOS"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":"AAAA,SAASA,cAAc,QAAQ,aAAa"}
@@ -0,0 +1,43 @@
1
+ import { NativeModules, Platform } from 'react-native';
2
+ 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.";
3
+ const nativeModule = NativeModules.RnErxesSdk;
4
+ function getNativeModule() {
5
+ if (Platform.OS !== 'ios') {
6
+ throw new Error('Erxes native messenger is only available on iOS.');
7
+ }
8
+ if (!nativeModule) {
9
+ throw new Error(LINKING_ERROR);
10
+ }
11
+ return nativeModule;
12
+ }
13
+ export const ErxesNativeIOS = {
14
+ configure(options) {
15
+ return getNativeModule().configure(options);
16
+ },
17
+ setUser(options) {
18
+ const customData = Object.fromEntries(Object.entries(options.customData ?? {}).filter(_ref => {
19
+ let [, value] = _ref;
20
+ return value !== null && value !== undefined;
21
+ }).map(_ref2 => {
22
+ let [key, value] = _ref2;
23
+ return [key, String(value)];
24
+ }));
25
+ return getNativeModule().setUser({
26
+ ...options,
27
+ customData
28
+ });
29
+ },
30
+ clearUser() {
31
+ return getNativeModule().clearUser();
32
+ },
33
+ showMessenger() {
34
+ return getNativeModule().showMessenger();
35
+ },
36
+ showLauncher() {
37
+ return getNativeModule().showLauncher();
38
+ },
39
+ hideLauncher() {
40
+ return getNativeModule().hideLauncher();
41
+ }
42
+ };
43
+ //# sourceMappingURL=nativeIos.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["NativeModules","Platform","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"],"sourceRoot":"../../src","sources":["nativeIos.ts"],"mappings":"AAAA,SAASA,aAAa,EAAEC,QAAQ,QAAQ,cAAc;AA0BtD,MAAMC,aAAa,GACjB,sHAAsH;AAExH,MAAMC,YAAY,GAAGH,aAAa,CAACI,UAAyC;AAE5E,SAASC,eAAeA,CAAA,EAAoB;EAC1C,IAAIJ,QAAQ,CAACK,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;AACF,CAAC"}
@@ -1,2 +1,3 @@
1
- export { default as ErxesSDK } from './App';
1
+ export { ErxesNativeIOS } from './nativeIos';
2
+ export type { NativeIOSConfig, NativeIOSUser } from './nativeIos';
2
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,OAAO,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,YAAY,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,23 @@
1
+ type NativeIOSConfig = {
2
+ integrationId: string;
3
+ endpoint?: string;
4
+ serverUrl?: string;
5
+ subDomain?: string;
6
+ cachedCustomerId?: string;
7
+ };
8
+ type NativeIOSUser = {
9
+ email?: string;
10
+ phone?: string;
11
+ name?: string;
12
+ customData?: Record<string, string | number | boolean | null | undefined>;
13
+ };
14
+ export declare const ErxesNativeIOS: {
15
+ configure(options: NativeIOSConfig): Promise<void>;
16
+ setUser(options: NativeIOSUser): Promise<void>;
17
+ clearUser(): Promise<void>;
18
+ showMessenger(): Promise<void>;
19
+ showLauncher(): Promise<void>;
20
+ hideLauncher(): Promise<void>;
21
+ };
22
+ export type { NativeIOSConfig, NativeIOSUser };
23
+ //# sourceMappingURL=nativeIos.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nativeIos.d.ts","sourceRoot":"","sources":["../../src/nativeIos.ts"],"names":[],"mappings":"AAEA,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;CAC3B,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;AA4BF,eAAO,MAAM,cAAc;uBACN,eAAe;qBAGjB,aAAa;;;;;CAwB/B,CAAC;AAEF,YAAY,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.1.26",
3
+ "version": "0.2.0",
4
4
  "description": "react-native erxes sdk",
5
5
  "main": "lib/commonjs/index",
6
6
  "module": "lib/module/index",
@@ -10,8 +10,10 @@
10
10
  "files": [
11
11
  "src",
12
12
  "lib",
13
+ "docs",
13
14
  "android",
14
- "ios",
15
+ "ios/RnErxesSdk.m",
16
+ "ios/RnErxesSdk.swift",
15
17
  "cpp",
16
18
  "*.podspec",
17
19
  "!lib/typescript/example",
@@ -81,16 +83,8 @@
81
83
  "typescript": "^4.5.2"
82
84
  },
83
85
  "peerDependencies": {
84
- "@react-native-async-storage/async-storage": ">=2.2.0",
85
86
  "react": "*",
86
- "react-native": "*",
87
- "react-native-get-random-values": ">=1.11.0",
88
- "expo-image-picker": "*"
89
- },
90
- "peerDependenciesMeta": {
91
- "expo-image-picker": {
92
- "optional": true
93
- }
87
+ "react-native": "*"
94
88
  },
95
89
  "engines": {
96
90
  "node": ">=20.19.0"
@@ -0,0 +1,45 @@
1
+ require 'json'
2
+
3
+ package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
4
+
5
+ begin
6
+ react_native_pods = Pod::Executable.execute_command(
7
+ 'node',
8
+ [
9
+ '-p',
10
+ 'require.resolve("react-native/scripts/react_native_pods.rb", {paths: [process.argv[1]]})',
11
+ __dir__
12
+ ]
13
+ ).strip
14
+ require react_native_pods
15
+ rescue StandardError
16
+ # React Native Podfiles normally load react_native_pods.rb before evaluating
17
+ # package podspecs. This fallback keeps podspec parsing useful in isolation.
18
+ end
19
+
20
+ Pod::Spec.new do |s|
21
+ s.name = 'rn-erxes-sdk'
22
+ s.version = package['version']
23
+ s.summary = package['description']
24
+ s.description = package['description']
25
+ s.homepage = package['homepage']
26
+ s.license = package['license']
27
+ s.author = package['author']
28
+ s.platforms = { :ios => '16.0' }
29
+ s.source = { :git => 'https://github.com/erxes/rn-erxes-sdk.git', :tag => "v#{s.version}" }
30
+ s.source_files = 'ios/RnErxesSdk.{m,swift}'
31
+ s.swift_version = '5.9'
32
+
33
+ s.dependency 'React-Core'
34
+
35
+ if defined?(spm_dependency)
36
+ spm_dependency(
37
+ s,
38
+ url: 'https://github.com/Munkhorgilb/ios-sdk.git',
39
+ requirement: { :kind => 'exactVersion', :version => '0.30.0' },
40
+ products: ['MessengerSDK']
41
+ )
42
+ else
43
+ raise 'rn-erxes-sdk requires React Native 0.81+ CocoaPods SPM support to install MessengerSDK 0.0.1'
44
+ end
45
+ end
package/src/index.tsx CHANGED
@@ -1 +1,2 @@
1
- export { default as ErxesSDK } from './App';
1
+ export { ErxesNativeIOS } from './nativeIos';
2
+ export type { NativeIOSConfig, NativeIOSUser } from './nativeIos';
@@ -0,0 +1,74 @@
1
+ import { NativeModules, Platform } from 'react-native';
2
+
3
+ type NativeIOSConfig = {
4
+ integrationId: string;
5
+ endpoint?: string;
6
+ serverUrl?: string;
7
+ subDomain?: string;
8
+ cachedCustomerId?: string;
9
+ };
10
+
11
+ type NativeIOSUser = {
12
+ email?: string;
13
+ phone?: string;
14
+ name?: string;
15
+ customData?: Record<string, string | number | boolean | null | undefined>;
16
+ };
17
+
18
+ type NativeIOSModule = {
19
+ configure(options: NativeIOSConfig): Promise<void>;
20
+ setUser(options: NativeIOSUser): Promise<void>;
21
+ clearUser(): Promise<void>;
22
+ showMessenger(): Promise<void>;
23
+ showLauncher(): Promise<void>;
24
+ hideLauncher(): Promise<void>;
25
+ };
26
+
27
+ const LINKING_ERROR =
28
+ "The rn-erxes-sdk native iOS module is not linked. Run `pod install` in your app's ios directory and rebuild the app.";
29
+
30
+ const nativeModule = NativeModules.RnErxesSdk as NativeIOSModule | undefined;
31
+
32
+ function getNativeModule(): NativeIOSModule {
33
+ if (Platform.OS !== 'ios') {
34
+ throw new Error('Erxes native messenger is only available on iOS.');
35
+ }
36
+
37
+ if (!nativeModule) {
38
+ throw new Error(LINKING_ERROR);
39
+ }
40
+
41
+ return nativeModule;
42
+ }
43
+
44
+ export const ErxesNativeIOS = {
45
+ configure(options: NativeIOSConfig) {
46
+ return getNativeModule().configure(options);
47
+ },
48
+ setUser(options: NativeIOSUser) {
49
+ const customData = Object.fromEntries(
50
+ Object.entries(options.customData ?? {})
51
+ .filter(([, value]) => value !== null && value !== undefined)
52
+ .map(([key, value]) => [key, String(value)])
53
+ );
54
+
55
+ return getNativeModule().setUser({
56
+ ...options,
57
+ customData,
58
+ });
59
+ },
60
+ clearUser() {
61
+ return getNativeModule().clearUser();
62
+ },
63
+ showMessenger() {
64
+ return getNativeModule().showMessenger();
65
+ },
66
+ showLauncher() {
67
+ return getNativeModule().showLauncher();
68
+ },
69
+ hideLauncher() {
70
+ return getNativeModule().hideLauncher();
71
+ },
72
+ };
73
+
74
+ export type { NativeIOSConfig, NativeIOSUser };