rn-erxes-sdk 0.1.25 → 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 +64 -223
- package/docs/native-ios.md +170 -0
- package/ios/RnErxesSdk.m +25 -0
- package/ios/RnErxesSdk.swift +189 -0
- package/lib/commonjs/index.js +3 -4
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/nativeIos.js +50 -0
- package/lib/commonjs/nativeIos.js.map +1 -0
- package/lib/module/index.js +1 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/nativeIos.js +43 -0
- package/lib/module/nativeIos.js.map +1 -0
- package/lib/typescript/index.d.ts +2 -1
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/nativeIos.d.ts +23 -0
- package/lib/typescript/nativeIos.d.ts.map +1 -0
- package/package.json +5 -11
- package/rn-erxes-sdk.podspec +45 -0
- package/src/index.tsx +2 -1
- package/src/nativeIos.ts +74 -0
package/README.md
CHANGED
|
@@ -87,267 +87,113 @@ erxes is composed of 2 main components: **XOS** & **Plugins**
|
|
|
87
87
|
|
|
88
88
|
## Usage
|
|
89
89
|
|
|
90
|
-
<img src="https://raw.githubusercontent.com/erxes/rn-erxes-sdk/
|
|
90
|
+
<img src="https://raw.githubusercontent.com/erxes/rn-erxes-sdk/main/MOBILE-SDK.png" alt="rn-erxes-sdk messenger screenshot" width="350">
|
|
91
91
|
|
|
92
92
|
---
|
|
93
93
|
|
|
94
94
|
# rn-erxes-sdk
|
|
95
95
|
|
|
96
|
-
A React Native
|
|
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
|
-
|
|
99
|
-
|
|
100
|
-
## Installation
|
|
101
|
-
|
|
102
|
-
Install the SDK with Yarn:
|
|
103
|
-
|
|
104
|
-
```bash
|
|
105
|
-
yarn add rn-erxes-sdk
|
|
99
|
+
```tsx
|
|
100
|
+
import { ErxesNativeIOS } from 'rn-erxes-sdk';
|
|
106
101
|
```
|
|
107
102
|
|
|
108
|
-
|
|
103
|
+
## Requirements
|
|
109
104
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
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) |
|
|
113
111
|
|
|
114
|
-
|
|
112
|
+
## Docs
|
|
115
113
|
|
|
116
|
-
|
|
114
|
+
- [Native iOS guide](docs/native-ios.md)
|
|
117
115
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
```bash
|
|
121
|
-
npx expo install @react-native-async-storage/async-storage
|
|
122
|
-
yarn add react-native-get-random-values
|
|
123
|
-
```
|
|
116
|
+
## Installation
|
|
124
117
|
|
|
125
|
-
|
|
118
|
+
### Bare React Native
|
|
126
119
|
|
|
127
120
|
```bash
|
|
128
|
-
|
|
129
|
-
|
|
121
|
+
yarn add rn-erxes-sdk
|
|
122
|
+
cd ios && pod install
|
|
130
123
|
```
|
|
131
124
|
|
|
132
|
-
|
|
133
|
-
- **`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.
|
|
134
|
-
|
|
135
|
-
### Optional
|
|
125
|
+
### Expo
|
|
136
126
|
|
|
137
127
|
```bash
|
|
138
|
-
npx expo install expo-
|
|
128
|
+
npx expo install rn-erxes-sdk expo-build-properties
|
|
139
129
|
```
|
|
140
130
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
## Quick start with Expo
|
|
144
|
-
|
|
145
|
-
```bash
|
|
146
|
-
npx create-expo-app@latest rn-erxes-sdk-test
|
|
147
|
-
cd rn-erxes-sdk-test
|
|
131
|
+
Add to `app.json`:
|
|
148
132
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
133
|
+
```json
|
|
134
|
+
{
|
|
135
|
+
"plugins": [
|
|
136
|
+
["expo-build-properties", { "ios": { "deploymentTarget": "16.0" } }]
|
|
137
|
+
]
|
|
138
|
+
}
|
|
154
139
|
```
|
|
155
140
|
|
|
156
|
-
npm alternative:
|
|
157
|
-
|
|
158
141
|
```bash
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
npx expo start --clear
|
|
142
|
+
npx expo prebuild --platform ios
|
|
143
|
+
cd ios && pod install
|
|
144
|
+
npx expo run:ios
|
|
164
145
|
```
|
|
165
146
|
|
|
166
|
-
|
|
147
|
+
## Usage
|
|
167
148
|
|
|
168
|
-
|
|
169
|
-
app/index.tsx
|
|
170
|
-
```
|
|
149
|
+
Call `configure` once at startup. It connects in the background so the messenger opens instantly.
|
|
171
150
|
|
|
172
|
-
|
|
151
|
+
```tsx
|
|
152
|
+
import { ErxesNativeIOS } from 'rn-erxes-sdk';
|
|
173
153
|
|
|
174
|
-
|
|
175
|
-
|
|
154
|
+
ErxesNativeIOS.configure({
|
|
155
|
+
integrationId: 'YOUR_INTEGRATION_ID',
|
|
156
|
+
subDomain: 'yourcompany.erxes.io',
|
|
157
|
+
});
|
|
176
158
|
```
|
|
177
159
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
The example below separates three concerns:
|
|
181
|
-
|
|
182
|
-
1. authenticated customer-profile data taken from the host app's `currentUser` query,
|
|
183
|
-
2. browser/device/runtime metadata, and
|
|
184
|
-
3. the props passed to `ErxesSDK`.
|
|
160
|
+
Optionally identify the user:
|
|
185
161
|
|
|
186
162
|
```tsx
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
firstName?: string;
|
|
193
|
-
lastName?: string;
|
|
194
|
-
primaryEmail?: string;
|
|
195
|
-
primaryPhone?: string;
|
|
196
|
-
sex?: string | number;
|
|
197
|
-
propertiesData?: Record<string, unknown>;
|
|
198
|
-
};
|
|
199
|
-
|
|
200
|
-
type Props = {
|
|
201
|
-
currentUser?: CurrentUser;
|
|
202
|
-
};
|
|
203
|
-
|
|
204
|
-
export default function App({ currentUser }: Props) {
|
|
205
|
-
const integrationId = 'YOUR_INTEGRATION_ID';
|
|
206
|
-
const subDomain = 'YOUR_SUBDOMAIN.next.erxes.io';
|
|
207
|
-
|
|
208
|
-
const data = {
|
|
209
|
-
firstName: currentUser?.firstName ?? '',
|
|
210
|
-
lastName: currentUser?.lastName ?? '',
|
|
211
|
-
primaryEmail: currentUser?.primaryEmail ?? '',
|
|
212
|
-
sex: currentUser?.sex ?? '',
|
|
213
|
-
Type: 'mobile',
|
|
214
|
-
...currentUser?.propertiesData,
|
|
215
|
-
};
|
|
216
|
-
|
|
217
|
-
const properties = {
|
|
218
|
-
remoteAddress: '',
|
|
219
|
-
region: '',
|
|
220
|
-
countryCode: '',
|
|
221
|
-
city: '',
|
|
222
|
-
country: '',
|
|
223
|
-
url: 'https://YOUR_SUBDOMAIN.nextwidgets.erxes.io/',
|
|
224
|
-
hostname: 'YOUR_SUBDOMAIN.nextwidgets.erxes.io',
|
|
225
|
-
language: 'en-US',
|
|
226
|
-
userAgent: Platform.OS,
|
|
227
|
-
};
|
|
228
|
-
|
|
229
|
-
return (
|
|
230
|
-
<View style={{ flex: 1 }}>
|
|
231
|
-
<ErxesSDK
|
|
232
|
-
integrationId={integrationId}
|
|
233
|
-
subDomain={subDomain}
|
|
234
|
-
onBack={() => console.log('onBack')}
|
|
235
|
-
showWidget={false}
|
|
236
|
-
phone={currentUser?.primaryPhone ?? ''}
|
|
237
|
-
data={data}
|
|
238
|
-
properties={properties}
|
|
239
|
-
/>
|
|
240
|
-
</View>
|
|
241
|
-
);
|
|
242
|
-
}
|
|
163
|
+
ErxesNativeIOS.setUser({
|
|
164
|
+
email: 'user@example.com',
|
|
165
|
+
name: 'Jane Doe',
|
|
166
|
+
customData: { plan: 'pro' },
|
|
167
|
+
});
|
|
243
168
|
```
|
|
244
169
|
|
|
245
|
-
|
|
170
|
+
### Option A — Floating launcher (recommended)
|
|
246
171
|
|
|
247
|
-
|
|
248
|
-
- `data` should normally be mapped from the authenticated user's query result rather than hardcoded.
|
|
249
|
-
- Do not hardcode private customer information in production.
|
|
250
|
-
- Empty property values are acceptable when metadata is unavailable.
|
|
251
|
-
- Do not fake IP addresses or location values.
|
|
252
|
-
- Replace `YOUR_INTEGRATION_ID` and `YOUR_SUBDOMAIN` with the values from your erxes environment.
|
|
253
|
-
- `Platform.OS` is only a lightweight fallback for `userAgent`; it is not a complete browser user-agent string.
|
|
254
|
-
|
|
255
|
-
## Customer data from `currentUser`
|
|
256
|
-
|
|
257
|
-
`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.
|
|
172
|
+
Shows a draggable button over your app. Tapping it opens the messenger automatically.
|
|
258
173
|
|
|
259
174
|
```tsx
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
lastName: currentUser?.lastName ?? '',
|
|
263
|
-
primaryEmail: currentUser?.primaryEmail ?? '',
|
|
264
|
-
sex: currentUser?.sex ?? '',
|
|
265
|
-
Type: 'mobile',
|
|
266
|
-
...currentUser?.propertiesData,
|
|
267
|
-
};
|
|
175
|
+
ErxesNativeIOS.showLauncher();
|
|
176
|
+
// ErxesNativeIOS.hideLauncher(); // to remove it
|
|
268
177
|
```
|
|
269
178
|
|
|
270
|
-
|
|
271
|
-
- Custom fields may be included when relevant (e.g. spread from `propertiesData`).
|
|
272
|
-
- `data` is optional — when omitted, the visitor is connected as a guest.
|
|
273
|
-
- Do not use fake values in production.
|
|
274
|
-
|
|
275
|
-
## Browser and device information
|
|
179
|
+
### Option B — Your own button
|
|
276
180
|
|
|
277
|
-
|
|
181
|
+
If you have a custom trigger in your UI, call `showMessenger()` directly:
|
|
278
182
|
|
|
279
183
|
```tsx
|
|
280
|
-
|
|
281
|
-
remoteAddress: '',
|
|
282
|
-
region: '',
|
|
283
|
-
countryCode: '',
|
|
284
|
-
city: '',
|
|
285
|
-
country: '',
|
|
286
|
-
url: 'https://YOUR_SUBDOMAIN.nextwidgets.erxes.io/',
|
|
287
|
-
hostname: 'YOUR_SUBDOMAIN.nextwidgets.erxes.io',
|
|
288
|
-
language: 'en-US',
|
|
289
|
-
userAgent: 'DEVICE_USER_AGENT',
|
|
290
|
-
};
|
|
184
|
+
<Button title="Support" onPress={() => ErxesNativeIOS.showMessenger()} />
|
|
291
185
|
```
|
|
292
186
|
|
|
293
|
-
|
|
294
|
-
- Do not fake IP addresses or location values.
|
|
295
|
-
- Collect real runtime values where possible.
|
|
296
|
-
|
|
297
|
-
For reference, the mutation the SDK calls internally is:
|
|
298
|
-
|
|
299
|
-
```graphql
|
|
300
|
-
mutation widgetsSaveBrowserInfo(
|
|
301
|
-
$customerId: String
|
|
302
|
-
$visitorId: String
|
|
303
|
-
$browserInfo: JSON!
|
|
304
|
-
) {
|
|
305
|
-
widgetsSaveBrowserInfo(
|
|
306
|
-
customerId: $customerId
|
|
307
|
-
visitorId: $visitorId
|
|
308
|
-
browserInfo: $browserInfo
|
|
309
|
-
) {
|
|
310
|
-
_id
|
|
311
|
-
conversationId
|
|
312
|
-
customerId
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
```
|
|
316
|
-
|
|
317
|
-
The SDK passes the connected `customerId` together with your `properties` object as `browserInfo`. The customer id and visitor id are managed by the SDK:
|
|
318
|
-
|
|
319
|
-
- On first launch the SDK generates a guest **visitor id** (a 24-character hex string) and uses it to connect.
|
|
320
|
-
- After connecting, the resolved **customer id** is cached in `AsyncStorage` and reused on later launches.
|
|
187
|
+
On logout:
|
|
321
188
|
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
Public props of `ErxesSDK` (from the SDK's TypeScript types):
|
|
189
|
+
```tsx
|
|
190
|
+
ErxesNativeIOS.clearUser();
|
|
191
|
+
```
|
|
327
192
|
|
|
328
|
-
|
|
329
|
-
| --- | --- | --- | --- |
|
|
330
|
-
| `integrationId` | `string` | Yes | erxes messenger integration id used to connect. |
|
|
331
|
-
| `subDomain` | `string` | Yes | erxes environment subdomain (e.g. `YOUR_SUBDOMAIN.next.erxes.io`); used to build the GraphQL/WS endpoints and asset URLs. |
|
|
332
|
-
| `showWidget` | `boolean` | Yes | When `true`, renders the floating launcher button; when `false`, renders the messenger inline. |
|
|
333
|
-
| `brandCode` | `string` | No | Brand code; used as a fallback when `integrationId` is not provided. |
|
|
334
|
-
| `email` | `string` | No | When set, the contact is connected as an identified user (`isUser`). |
|
|
335
|
-
| `onBack` | `() => void` | No | Called when the user navigates back from the messenger. |
|
|
336
|
-
| `phone` | `string` | No | Phone number used to identify the customer on connect. |
|
|
337
|
-
| `data` | `object` | No | Customer-profile data forwarded to `widgetsMessengerConnect`. |
|
|
338
|
-
| `properties` | `object` | No | Browser/device metadata sent as `browserInfo` to `widgetsSaveBrowserInfo`. |
|
|
339
|
-
| `backIcon` | `ImageSource` | No | Custom back icon. |
|
|
340
|
-
| `newChatIcon` | `ImageSource` | No | Custom "new chat" icon. |
|
|
341
|
-
| `sendIcon` | `ImageSource` | No | Custom send icon. |
|
|
193
|
+
Full example: [Native iOS guide](docs/native-ios.md).
|
|
342
194
|
|
|
343
195
|
## Troubleshooting
|
|
344
196
|
|
|
345
|
-
### Clear Expo cache
|
|
346
|
-
|
|
347
|
-
```bash
|
|
348
|
-
npx expo start --clear
|
|
349
|
-
```
|
|
350
|
-
|
|
351
197
|
### Confirm the installed version
|
|
352
198
|
|
|
353
199
|
```bash
|
|
@@ -364,30 +210,25 @@ npm ls rn-erxes-sdk
|
|
|
364
210
|
|
|
365
211
|
```bash
|
|
366
212
|
yarn add rn-erxes-sdk@latest
|
|
367
|
-
npx expo start --clear
|
|
368
213
|
```
|
|
369
214
|
|
|
370
215
|
or:
|
|
371
216
|
|
|
372
217
|
```bash
|
|
373
218
|
npm install --save rn-erxes-sdk@latest
|
|
374
|
-
npx expo start --clear
|
|
375
219
|
```
|
|
376
220
|
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
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.
|
|
380
|
-
|
|
381
|
-
### `await is not defined` (BSON Metro crash)
|
|
221
|
+
After upgrading, reinstall pods and rebuild the app:
|
|
382
222
|
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
await is not defined
|
|
387
|
-
node_modules/bson/lib/bson.mjs
|
|
223
|
+
```bash
|
|
224
|
+
cd ios
|
|
225
|
+
pod install
|
|
388
226
|
```
|
|
389
227
|
|
|
390
|
-
|
|
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.
|
|
391
232
|
|
|
392
233
|
## Maintainer workflow
|
|
393
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`.
|
package/ios/RnErxesSdk.m
ADDED
|
@@ -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
|
+
}
|
package/lib/commonjs/index.js
CHANGED
|
@@ -3,12 +3,11 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
Object.defineProperty(exports, "
|
|
6
|
+
Object.defineProperty(exports, "ErxesNativeIOS", {
|
|
7
7
|
enumerable: true,
|
|
8
8
|
get: function () {
|
|
9
|
-
return
|
|
9
|
+
return _nativeIos.ErxesNativeIOS;
|
|
10
10
|
}
|
|
11
11
|
});
|
|
12
|
-
var
|
|
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":["
|
|
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"}
|
package/lib/module/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { ErxesNativeIOS } from './nativeIos';
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/lib/module/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["
|
|
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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
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.
|
|
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 {
|
|
1
|
+
export { ErxesNativeIOS } from './nativeIos';
|
|
2
|
+
export type { NativeIOSConfig, NativeIOSUser } from './nativeIos';
|
package/src/nativeIos.ts
ADDED
|
@@ -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 };
|