@robylon/react-native-sdk 2.1.0 → 2.1.3-staging.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/.claude/settings.local.json +25 -0
- package/README.md +332 -5
- package/android/src/main/AndroidManifest.xml +3 -0
- package/android/src/main/java/com/robylonreactnativesdk/RobylonDownloadModule.java +83 -0
- package/android/src/main/java/com/robylonreactnativesdk/RobylonReactNativeSdkPackage.java +24 -0
- package/lib/commonjs/Chatbotsdk.js +3 -3
- package/lib/commonjs/Chatbotsdk.js.map +1 -1
- package/lib/commonjs/config.js +1 -1
- package/lib/commonjs/config.js.map +1 -1
- package/lib/commonjs/constants.js +1 -1
- package/lib/commonjs/constants.js.map +1 -1
- package/lib/commonjs/hooks/useChatbotEvents.js +1 -1
- package/lib/commonjs/hooks/useChatbotEvents.js.map +1 -1
- package/lib/commonjs/utils/session.js +2 -0
- package/lib/commonjs/utils/session.js.map +1 -0
- package/lib/commonjs/versions/version.staging.js +1 -1
- package/lib/commonjs/versions/version.staging.js.map +1 -1
- package/lib/module/Chatbotsdk.js +3 -3
- package/lib/module/Chatbotsdk.js.map +1 -1
- package/lib/module/config.js +1 -1
- package/lib/module/config.js.map +1 -1
- package/lib/module/constants.js +1 -1
- package/lib/module/constants.js.map +1 -1
- package/lib/module/hooks/useChatbotEvents.js +1 -1
- package/lib/module/hooks/useChatbotEvents.js.map +1 -1
- package/lib/module/utils/session.js +2 -0
- package/lib/module/utils/session.js.map +1 -0
- package/lib/module/versions/version.staging.js +1 -1
- package/lib/module/versions/version.staging.js.map +1 -1
- package/lib/typescript/Chatbotsdk.d.ts +4 -0
- package/lib/typescript/Chatbotsdk.d.ts.map +1 -1
- package/lib/typescript/hooks/useChatbotEvents.d.ts.map +1 -1
- package/lib/typescript/utils/session.d.ts +21 -0
- package/lib/typescript/utils/session.d.ts.map +1 -0
- package/lib/typescript/versions/version.staging.d.ts +1 -1
- package/lib/typescript/versions/version.staging.d.ts.map +1 -1
- package/package.json +2 -2
- package/robylon-react-native-sdk-2.1.1-staging.3.tgz +0 -0
- package/scripts/setup-git-hooks.js +22 -10
- package/src/Chatbotsdk.tsx +1039 -0
- package/src/FloatingButton/launchers/ImageLauncher.tsx +75 -0
- package/src/FloatingButton/launchers/TextLauncher.tsx +84 -0
- package/src/FloatingButton/launchers/TextualImageLauncher.tsx +133 -0
- package/src/FloatingButton.tsx +97 -0
- package/src/LoadingIndicator.tsx +11 -0
- package/src/Toast.tsx +65 -0
- package/src/components/DebugButton.tsx +46 -0
- package/src/components/ErrorBoundary.tsx +38 -0
- package/src/config.ts +4 -0
- package/src/constants/errorConstants.ts +21 -0
- package/src/constants/fontStyles.ts +3 -0
- package/src/constants.ts +5 -0
- package/src/global.d.ts +11 -0
- package/src/hooks/useChatbotEvents.ts +117 -0
- package/src/index.tsx +10 -0
- package/src/openChatbot.ts +11 -0
- package/src/openChatbot.tsx +0 -0
- package/src/services/ErrorTrackingService.ts +217 -0
- package/src/types/events.ts +28 -0
- package/src/types/react-native-flipper-performance-plugin.d.ts +3 -0
- package/src/types/react-native-globals.d.ts +10 -0
- package/src/utils/animations.ts +120 -0
- package/src/utils/colorUtils.ts +35 -0
- package/src/utils/cookieUtils.ts +7 -0
- package/src/utils/debugConfig.ts +56 -0
- package/src/utils/debugMenu.ts +14 -0
- package/src/utils/errorHandler.ts +58 -0
- package/src/utils/fileDownload.ts +198 -0
- package/src/utils/logger.ts +14 -0
- package/src/utils/session.ts +26 -0
- package/src/utils/systemInfo.ts +110 -0
- package/src/utils/webViewStorage.ts +62 -0
- package/src/version.ts +2 -0
- package/src/versions/version.dev.ts +2 -0
- package/src/versions/version.production.ts +2 -0
- package/src/versions/version.staging.ts +2 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"permissions": {
|
|
3
|
+
"allow": [
|
|
4
|
+
"Bash(npx tsc *)",
|
|
5
|
+
"Bash(echo \"EXIT:$?\")",
|
|
6
|
+
"Bash(node -e \"const p=require\\('./package.json'\\);console.log\\(JSON.stringify\\(p.scripts,null,2\\)\\);console.log\\('---devDeps---'\\);console.log\\(Object.keys\\(p.devDependencies||{}\\).join\\('\\\\n'\\)\\)\")",
|
|
7
|
+
"Bash(node -e \"const p=require\\('./package.json'\\);console.log\\('name:',p.name\\);console.log\\('version:',p.version\\);console.log\\('main:',p.main\\);console.log\\('module:',p.module\\);console.log\\('types:',p.types\\);console.log\\('files:',JSON.stringify\\(p.files\\)\\);console.log\\('rnbob:',JSON.stringify\\(p['react-native-builder-bob'],null,2\\)\\)\")",
|
|
8
|
+
"Bash(curl -s -o /dev/null -w \"root: %{http_code}\\\\n\" --max-time 4 http://localhost:3000/)",
|
|
9
|
+
"Bash(curl -s -o /dev/null -w \"chatbot-plugin: %{http_code}\\\\n\" --max-time 4 http://localhost:3000/chatbot-plugin)",
|
|
10
|
+
"Bash(npm run *)",
|
|
11
|
+
"Bash(npm pack *)",
|
|
12
|
+
"Bash(tar -tzf robylon-react-native-sdk-2.1.1-staging.3.tgz)",
|
|
13
|
+
"Bash(node -e \"const p=require\\('./package.json'\\); console.log\\('prepare:',p.scripts.prepare\\)\")",
|
|
14
|
+
"Bash(grep -n \"^#\\\\{1,4\\\\} \" README.md)",
|
|
15
|
+
"Bash(node -e ' *)",
|
|
16
|
+
"Bash(grep -n \"^#\\\\{1,4\\\\} \" usage/ecommerce-order-session-example.md)",
|
|
17
|
+
"Bash(python3 -)",
|
|
18
|
+
"Bash(echo \"TSC_EXIT:$?\")",
|
|
19
|
+
"Bash(git rm *)",
|
|
20
|
+
"Bash(git check-ignore *)",
|
|
21
|
+
"Bash(node -e \"console.log\\('postinstall:', require\\('./package.json'\\).scripts.postinstall\\)\")",
|
|
22
|
+
"Bash(node scripts/setup-git-hooks.js)"
|
|
23
|
+
]
|
|
24
|
+
}
|
|
25
|
+
}
|
package/README.md
CHANGED
|
@@ -1,5 +1,38 @@
|
|
|
1
1
|
# Robylon React Native SDK Documentation
|
|
2
2
|
|
|
3
|
+
## Table of Contents
|
|
4
|
+
|
|
5
|
+
- [Installation](#installation)
|
|
6
|
+
- [Available Exports](#available-exports)
|
|
7
|
+
- [Prerequisites](#prerequisites)
|
|
8
|
+
- [Basic Implementation](#basic-implementation)
|
|
9
|
+
- [Import and Basic Usage](#import-and-basic-usage)
|
|
10
|
+
- [Props Reference](#props-reference)
|
|
11
|
+
- [Required Props](#required-props)
|
|
12
|
+
- [Optional Props](#optional-props)
|
|
13
|
+
- [User Profile Properties](#user-profile-properties)
|
|
14
|
+
- [External Trigger API](#external-trigger-api)
|
|
15
|
+
- [Ref-based Imperative API](#ref-based-imperative-api)
|
|
16
|
+
- [Ref Methods](#ref-methods)
|
|
17
|
+
- [Callback Props](#callback-props)
|
|
18
|
+
- [Session Management](#session-management)
|
|
19
|
+
- [Reading the session id](#reading-the-session-id)
|
|
20
|
+
- [Resuming a conversation](#resuming-a-conversation)
|
|
21
|
+
- [`session_context`](#session_context)
|
|
22
|
+
- [Privacy](#privacy)
|
|
23
|
+
- [Recipes](#recipes)
|
|
24
|
+
- [One chat session per e-commerce order](#one-chat-session-per-e-commerce-order)
|
|
25
|
+
- [Advanced Usage Examples](#advanced-usage-examples)
|
|
26
|
+
- [Custom UI Integration](#custom-ui-integration)
|
|
27
|
+
- [Safety Features](#safety-features)
|
|
28
|
+
- [Use Cases](#use-cases)
|
|
29
|
+
- [Automatically Collected Information](#automatically-collected-information)
|
|
30
|
+
- [Event Handling](#event-handling)
|
|
31
|
+
- [Available Events](#available-events)
|
|
32
|
+
- [Anonymous Users](#anonymous-users)
|
|
33
|
+
- [Best Practices](#best-practices)
|
|
34
|
+
- [Support](#support)
|
|
35
|
+
|
|
3
36
|
## Installation
|
|
4
37
|
|
|
5
38
|
Install the package using npm or yarn:
|
|
@@ -79,6 +112,9 @@ export default App;
|
|
|
79
112
|
| `user_id` | string \| null \| number | Unique identifier for the user. If not provided, an anonymous ID will be generated |
|
|
80
113
|
| `user_token` | string | Authentication token for the user |
|
|
81
114
|
| `user_profile` | { email?: string; name?: string; mobile?: string; is_test_user?: boolean; [key:string \| number]: any } | User profile information |
|
|
115
|
+
| `session_id` | string | Session to resume. Read when the chat initializes — see [Session Management](#session-management) |
|
|
116
|
+
| `session_context` | Record<string, any> | Opaque value echoed back as the second argument to `onSession`. Never read by the SDK |
|
|
117
|
+
| `onSession` | (session_id: string, session_context?: Record<string, any>) => void | Called whenever the active session id changes |
|
|
82
118
|
| `onEvent` | ChatbotEventHandler | Callback for chatbot events |
|
|
83
119
|
| `onOpen` | () => void | Callback when chatbot opens |
|
|
84
120
|
| `onClose` | () => void | Callback when chatbot closes |
|
|
@@ -147,14 +183,305 @@ const App = () => {
|
|
|
147
183
|
| `close()` | Programmatically close the chatbot |
|
|
148
184
|
| `toggle()` | Toggle chatbot visibility |
|
|
149
185
|
| `isReady()` | Check if chatbot is ready for external triggers |
|
|
186
|
+
| `getSessionId()` | Current session id, or `undefined` if no session has started yet |
|
|
150
187
|
|
|
151
188
|
### Callback Props
|
|
152
189
|
|
|
153
|
-
| Prop
|
|
154
|
-
|
|
|
155
|
-
| `onOpen`
|
|
156
|
-
| `onClose`
|
|
157
|
-
| `onReady`
|
|
190
|
+
| Prop | Type | Description |
|
|
191
|
+
| ----------- | ------------------------------------------------------------------- | ---------------------------------------------- |
|
|
192
|
+
| `onOpen` | () => void | Called when chatbot opens |
|
|
193
|
+
| `onClose` | () => void | Called when chatbot closes |
|
|
194
|
+
| `onReady` | () => void | Called when chatbot is fully initialized |
|
|
195
|
+
| `onSession` | (session_id: string, session_context?: Record<string, any>) => void | Called when the active session id changes |
|
|
196
|
+
|
|
197
|
+
## Session Management
|
|
198
|
+
|
|
199
|
+
Each conversation has a session id. The SDK hands it to you as it changes, and
|
|
200
|
+
accepts one back so a returning user can continue an earlier conversation.
|
|
201
|
+
|
|
202
|
+
### Reading the session id
|
|
203
|
+
|
|
204
|
+
`onSession` fires whenever the active session id changes — when a conversation
|
|
205
|
+
starts, when one is resumed, and if the id rotates mid-conversation. It does not
|
|
206
|
+
fire again for an unchanged id, so it is safe to trigger side effects from it.
|
|
207
|
+
|
|
208
|
+
```typescript
|
|
209
|
+
<Chatbot
|
|
210
|
+
api_key="YOUR_API_KEY"
|
|
211
|
+
user_id={user.id}
|
|
212
|
+
onSession={(sessionId) => AsyncStorage.setItem("robylon_session", sessionId)}
|
|
213
|
+
/>
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
The id is also available on demand through the ref:
|
|
217
|
+
|
|
218
|
+
```typescript
|
|
219
|
+
const sessionId = chatbotRef.current?.getSessionId();
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### Resuming a conversation
|
|
223
|
+
|
|
224
|
+
Store the id from `onSession` and pass it back as `session_id` on a later mount:
|
|
225
|
+
|
|
226
|
+
```typescript
|
|
227
|
+
const App = () => {
|
|
228
|
+
const [sessionId, setSessionId] = useState<string>();
|
|
229
|
+
const [loaded, setLoaded] = useState(false);
|
|
230
|
+
|
|
231
|
+
useEffect(() => {
|
|
232
|
+
AsyncStorage.getItem("robylon_session").then((stored) => {
|
|
233
|
+
setSessionId(stored ?? undefined);
|
|
234
|
+
setLoaded(true);
|
|
235
|
+
});
|
|
236
|
+
}, []);
|
|
237
|
+
|
|
238
|
+
// Wait for the stored id before mounting, since session_id is read at init
|
|
239
|
+
if (!loaded) return null;
|
|
240
|
+
|
|
241
|
+
return (
|
|
242
|
+
<Chatbot
|
|
243
|
+
api_key="YOUR_API_KEY"
|
|
244
|
+
user_id={user.id}
|
|
245
|
+
session_id={sessionId}
|
|
246
|
+
onSession={(id) => {
|
|
247
|
+
setSessionId(id);
|
|
248
|
+
AsyncStorage.setItem("robylon_session", id);
|
|
249
|
+
}}
|
|
250
|
+
/>
|
|
251
|
+
);
|
|
252
|
+
};
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
Things worth knowing:
|
|
256
|
+
|
|
257
|
+
- **`session_id` is read at initialization**, not continuously. Changing it while
|
|
258
|
+
the chat is open has no effect until the chat is next initialized. Mount the
|
|
259
|
+
component only once the stored id is available.
|
|
260
|
+
- **If the session cannot be resumed** — expired, closed, or belonging to a
|
|
261
|
+
different user — a new conversation starts and `onSession` fires with that new
|
|
262
|
+
id. Compare it against what you passed in to detect this.
|
|
263
|
+
- **Omitting `session_id` does not guarantee a new conversation.** The chatbot
|
|
264
|
+
may resume from its own stored state.
|
|
265
|
+
- **The session does not survive unmounting on its own.** Navigating away tears
|
|
266
|
+
down the chatbot; storing the id and passing it back is what restores the
|
|
267
|
+
conversation.
|
|
268
|
+
- **Changing `user_id` invalidates any stored session id.** Stop passing a
|
|
269
|
+
session id that belongs to a different user.
|
|
270
|
+
|
|
271
|
+
### `session_context`
|
|
272
|
+
|
|
273
|
+
If your `onSession` handler is defined outside the component and cannot see the
|
|
274
|
+
surrounding state, `session_context` carries that state across for you. The SDK
|
|
275
|
+
never reads it — it is passed back verbatim as the second argument.
|
|
276
|
+
|
|
277
|
+
```typescript
|
|
278
|
+
// analytics.ts — has no view of which screen mounted the chatbot
|
|
279
|
+
export const onRobylonSession = (sessionId: string, ctx?: Record<string, any>) => {
|
|
280
|
+
Analytics.track("chat_session", { sessionId, ...ctx });
|
|
281
|
+
};
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
```typescript
|
|
285
|
+
<Chatbot
|
|
286
|
+
api_key="YOUR_API_KEY"
|
|
287
|
+
session_context={{ screen: "OrderDetail", orderId: order.id }}
|
|
288
|
+
onSession={onRobylonSession}
|
|
289
|
+
/>
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
This is optional. An inline handler can simply close over the values it needs.
|
|
293
|
+
When `session_context` is omitted the second argument is an empty object, never
|
|
294
|
+
`undefined`.
|
|
295
|
+
|
|
296
|
+
### Privacy
|
|
297
|
+
|
|
298
|
+
The session id is delivered only through `onSession` and `getSessionId()`. It is
|
|
299
|
+
never included in `onEvent` payloads and is not sent to Robylon's event logging.
|
|
300
|
+
Integrations that do not use either API never observe it.
|
|
301
|
+
|
|
302
|
+
## Recipes
|
|
303
|
+
|
|
304
|
+
Complete integration patterns built from the APIs above.
|
|
305
|
+
|
|
306
|
+
### One chat session per e-commerce order
|
|
307
|
+
|
|
308
|
+
A list of orders, each with its own **"Need help with this order?"** button,
|
|
309
|
+
where every order keeps its own conversation. Tapping the same order a week
|
|
310
|
+
later resumes that order's chat instead of starting over.
|
|
311
|
+
|
|
312
|
+
```
|
|
313
|
+
Tap "Need help with this order?" on order BK-908213
|
|
314
|
+
→ SDK initializes for that order, resuming its stored session if there is one
|
|
315
|
+
→ chat opens full screen
|
|
316
|
+
→ onSession fires with the session id + the order it belongs to
|
|
317
|
+
→ app stores BK-908213 -> sess_abc123
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
The data model is one line — **order id → session id**. The SDK never stores
|
|
321
|
+
this for you and never interprets it; persistence and expiry are yours.
|
|
322
|
+
|
|
323
|
+
#### Storage helper
|
|
324
|
+
|
|
325
|
+
Registered outside React, the way a real storage layer is. It has no view of
|
|
326
|
+
component state, so it learns which order a session belongs to from
|
|
327
|
+
`session_context`.
|
|
328
|
+
|
|
329
|
+
```ts
|
|
330
|
+
// sessionStore.ts
|
|
331
|
+
import AsyncStorage from "@react-native-async-storage/async-storage";
|
|
332
|
+
|
|
333
|
+
const STORAGE_KEY = "robylon.sessionByOrder";
|
|
334
|
+
let sessionByOrder: Record<string, string> = {};
|
|
335
|
+
|
|
336
|
+
/** Call once during app start, before rendering the orders list. */
|
|
337
|
+
export async function loadSessions(): Promise<void> {
|
|
338
|
+
const raw = await AsyncStorage.getItem(STORAGE_KEY);
|
|
339
|
+
sessionByOrder = raw ? JSON.parse(raw) : {};
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
export function getSessionForOrder(orderId: string): string | undefined {
|
|
343
|
+
return sessionByOrder[orderId];
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/** Pass straight to <Chatbot onSession={...}>. */
|
|
347
|
+
export function persistSession(
|
|
348
|
+
sessionId: string,
|
|
349
|
+
ctx?: Record<string, any>,
|
|
350
|
+
): void {
|
|
351
|
+
const orderId = ctx?.order_id;
|
|
352
|
+
if (!orderId) return;
|
|
353
|
+
|
|
354
|
+
sessionByOrder[orderId] = sessionId;
|
|
355
|
+
AsyncStorage.setItem(STORAGE_KEY, JSON.stringify(sessionByOrder)).catch(() => {
|
|
356
|
+
// A failed write only costs the customer a resume, never the chat.
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
/** Call when the signed-in user changes. Sessions belong to a user. */
|
|
361
|
+
export async function clearSessions(): Promise<void> {
|
|
362
|
+
sessionByOrder = {};
|
|
363
|
+
await AsyncStorage.removeItem(STORAGE_KEY);
|
|
364
|
+
}
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
#### The screen
|
|
368
|
+
|
|
369
|
+
```tsx
|
|
370
|
+
export default function OrdersScreen({ orders, userId }) {
|
|
371
|
+
const chatbotRef = useRef<ChatbotRef>(null);
|
|
372
|
+
const [activeOrderId, setActiveOrderId] = useState<string | undefined>();
|
|
373
|
+
const [readyOrderId, setReadyOrderId] = useState<string | undefined>();
|
|
374
|
+
const pendingOpenRef = useRef<string | undefined>(undefined);
|
|
375
|
+
|
|
376
|
+
const activeOrder = useMemo(
|
|
377
|
+
() => orders.find((o) => o.id === activeOrderId),
|
|
378
|
+
[orders, activeOrderId],
|
|
379
|
+
);
|
|
380
|
+
|
|
381
|
+
const openHelpForOrder = useCallback(
|
|
382
|
+
(order) => {
|
|
383
|
+
if (activeOrderId === order.id) {
|
|
384
|
+
chatbotRef.current?.open(); // already initialized — just show it
|
|
385
|
+
return;
|
|
386
|
+
}
|
|
387
|
+
// A different order: remount so its stored session_id is read at init
|
|
388
|
+
pendingOpenRef.current = order.id;
|
|
389
|
+
setActiveOrderId(order.id);
|
|
390
|
+
},
|
|
391
|
+
[activeOrderId],
|
|
392
|
+
);
|
|
393
|
+
|
|
394
|
+
// Open from an effect, not from inside onReady — see below
|
|
395
|
+
useEffect(() => {
|
|
396
|
+
if (readyOrderId && pendingOpenRef.current === readyOrderId) {
|
|
397
|
+
pendingOpenRef.current = undefined;
|
|
398
|
+
chatbotRef.current?.open();
|
|
399
|
+
}
|
|
400
|
+
}, [readyOrderId]);
|
|
401
|
+
|
|
402
|
+
return (
|
|
403
|
+
<View style={{ flex: 1 }}>
|
|
404
|
+
<FlatList
|
|
405
|
+
data={orders}
|
|
406
|
+
keyExtractor={(order) => order.id}
|
|
407
|
+
renderItem={({ item }) => (
|
|
408
|
+
<TouchableOpacity onPress={() => openHelpForOrder(item)}>
|
|
409
|
+
<Text>Need help with this order?</Text>
|
|
410
|
+
</TouchableOpacity>
|
|
411
|
+
)}
|
|
412
|
+
/>
|
|
413
|
+
|
|
414
|
+
{/* The chat needs a full-screen box of its own */}
|
|
415
|
+
<View style={StyleSheet.absoluteFill} pointerEvents="box-none">
|
|
416
|
+
{activeOrder ? (
|
|
417
|
+
<Chatbot
|
|
418
|
+
key={activeOrder.id}
|
|
419
|
+
ref={chatbotRef}
|
|
420
|
+
api_key={API_KEY}
|
|
421
|
+
user_id={userId}
|
|
422
|
+
show_floating_button={false}
|
|
423
|
+
session_id={getSessionForOrder(activeOrder.id)}
|
|
424
|
+
session_context={{
|
|
425
|
+
order_id: activeOrder.id,
|
|
426
|
+
order_status: activeOrder.status,
|
|
427
|
+
}}
|
|
428
|
+
onSession={persistSession}
|
|
429
|
+
onReady={() => setReadyOrderId(activeOrder.id)}
|
|
430
|
+
/>
|
|
431
|
+
) : null}
|
|
432
|
+
</View>
|
|
433
|
+
</View>
|
|
434
|
+
);
|
|
435
|
+
}
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
#### Four things that look removable but aren't
|
|
439
|
+
|
|
440
|
+
**`key={activeOrder.id}` is what makes resume work.** `session_id` is read once,
|
|
441
|
+
at initialization. Changing it while the chat is mounted does nothing.
|
|
442
|
+
Remounting through a changing `key` forces a fresh initialization that picks up
|
|
443
|
+
the new order's stored session. Without it, every order after the first reuses
|
|
444
|
+
the first order's conversation.
|
|
445
|
+
|
|
446
|
+
**Open from an effect, not from inside `onReady`.** Calling
|
|
447
|
+
`chatbotRef.current?.open()` directly inside `onReady` does nothing. `onReady`
|
|
448
|
+
fires in the same pass that the SDK marks itself initialized, and `open()` is
|
|
449
|
+
gated on that flag through a ref handle that is only rebuilt on the following
|
|
450
|
+
render — so the handle in hand is still the un-initialized one. The symptom if
|
|
451
|
+
you skip this: the first tap appears to do nothing, and the second tap works.
|
|
452
|
+
|
|
453
|
+
**The `absoluteFill` wrapper.** The SDK draws its chat window inside whatever
|
|
454
|
+
box the host gives the component, not against the screen. Rendered as an
|
|
455
|
+
ordinary child of a flex column it can collapse to zero height — the chat
|
|
456
|
+
"opens" and the conversation genuinely starts, but nothing is visible.
|
|
457
|
+
`pointerEvents="box-none"` on the wrapper keeps the order list tappable while
|
|
458
|
+
the chat is closed.
|
|
459
|
+
|
|
460
|
+
> Requires SDK 2.2.0 or newer. Earlier versions left the SDK's own root view
|
|
461
|
+
> hit-testable while closed, so it swallowed taps meant for your UI and
|
|
462
|
+
> `box-none` on your wrapper was not enough to prevent it. If you are pinned to
|
|
463
|
+
> an older version, gate the wrapper with
|
|
464
|
+
> `pointerEvents={isChatOpen ? "auto" : "none"}` driven by `onOpen` / `onClose`.
|
|
465
|
+
|
|
466
|
+
**`session_context` rather than a closure.** `persistSession` lives outside the
|
|
467
|
+
component, so it cannot see which order is active. If your handler is defined
|
|
468
|
+
inline and already closes over the order, you do not need `session_context` at
|
|
469
|
+
all — `onSession={(sessionId) => save(order.id, sessionId)}` carries it.
|
|
470
|
+
|
|
471
|
+
#### Checklist
|
|
472
|
+
|
|
473
|
+
- [ ] `loadSessions()` awaited during app start, before the orders list renders
|
|
474
|
+
- [ ] `key` on `<Chatbot>` changes with the order
|
|
475
|
+
- [ ] `show_floating_button={false}` if the order buttons are the only entry point
|
|
476
|
+
- [ ] `<Chatbot>` wrapped in a full-screen container
|
|
477
|
+
- [ ] Verified: open a chat, close it, then tap another order's button — the
|
|
478
|
+
screen must still respond
|
|
479
|
+
- [ ] `open()` called from an effect after ready, not inside `onReady`
|
|
480
|
+
- [ ] `session_context` carries the order id, and `onSession` reads it
|
|
481
|
+
- [ ] Stored sessions cleared when the signed-in user changes
|
|
482
|
+
|
|
483
|
+
The full worked example, including styles and the complete behaviour matrix, is
|
|
484
|
+
in [`usage/ecommerce-order-session-example.md`](usage/ecommerce-order-session-example.md).
|
|
158
485
|
|
|
159
486
|
## Advanced Usage Examples
|
|
160
487
|
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
package com.robylonreactnativesdk;
|
|
2
|
+
|
|
3
|
+
import android.app.DownloadManager;
|
|
4
|
+
import android.content.Context;
|
|
5
|
+
import android.net.Uri;
|
|
6
|
+
import android.os.Environment;
|
|
7
|
+
import android.webkit.MimeTypeMap;
|
|
8
|
+
|
|
9
|
+
import androidx.annotation.NonNull;
|
|
10
|
+
|
|
11
|
+
import com.facebook.react.bridge.Promise;
|
|
12
|
+
import com.facebook.react.bridge.ReactApplicationContext;
|
|
13
|
+
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
|
14
|
+
import com.facebook.react.bridge.ReactMethod;
|
|
15
|
+
|
|
16
|
+
public class RobylonDownloadModule extends ReactContextBaseJavaModule {
|
|
17
|
+
private final ReactApplicationContext reactContext;
|
|
18
|
+
|
|
19
|
+
public RobylonDownloadModule(ReactApplicationContext reactContext) {
|
|
20
|
+
super(reactContext);
|
|
21
|
+
this.reactContext = reactContext;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
@NonNull
|
|
25
|
+
@Override
|
|
26
|
+
public String getName() {
|
|
27
|
+
return "RobylonDownloadModule";
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
@ReactMethod
|
|
31
|
+
public void downloadFile(String url, String filename, Promise promise) {
|
|
32
|
+
try {
|
|
33
|
+
if (url == null || url.trim().isEmpty()) {
|
|
34
|
+
promise.reject("INVALID_URL", "Download URL is missing");
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
String safeName = getSafeFileName(filename, url);
|
|
39
|
+
DownloadManager manager = (DownloadManager) reactContext.getSystemService(Context.DOWNLOAD_SERVICE);
|
|
40
|
+
if (manager == null) {
|
|
41
|
+
promise.reject("DOWNLOAD_SERVICE_UNAVAILABLE", "Download service unavailable");
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
|
|
46
|
+
request.setTitle(safeName);
|
|
47
|
+
request.setDescription("Downloading transcript");
|
|
48
|
+
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
|
|
49
|
+
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, safeName);
|
|
50
|
+
request.setMimeType(getMimeTypeFromName(safeName));
|
|
51
|
+
request.setAllowedOverMetered(true);
|
|
52
|
+
request.setAllowedOverRoaming(true);
|
|
53
|
+
|
|
54
|
+
long downloadId = manager.enqueue(request);
|
|
55
|
+
promise.resolve(String.valueOf(downloadId));
|
|
56
|
+
} catch (Exception error) {
|
|
57
|
+
promise.reject("DOWNLOAD_FAILED", error);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
private String getSafeFileName(String filename, String url) {
|
|
62
|
+
if (filename != null && !filename.trim().isEmpty()) {
|
|
63
|
+
return filename.trim().replaceAll("[\\\\/:*?\"<>|]", "_");
|
|
64
|
+
}
|
|
65
|
+
String fromUrl = Uri.parse(url).getLastPathSegment();
|
|
66
|
+
if (fromUrl == null || fromUrl.trim().isEmpty()) {
|
|
67
|
+
return "chat-transcript-" + System.currentTimeMillis() + ".txt";
|
|
68
|
+
}
|
|
69
|
+
return fromUrl.trim().replaceAll("[\\\\/:*?\"<>|]", "_");
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
private String getMimeTypeFromName(String filename) {
|
|
73
|
+
String extension = MimeTypeMap.getFileExtensionFromUrl(filename);
|
|
74
|
+
if (extension == null || extension.isEmpty()) {
|
|
75
|
+
return "application/octet-stream";
|
|
76
|
+
}
|
|
77
|
+
String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension.toLowerCase());
|
|
78
|
+
if (mimeType == null || mimeType.isEmpty()) {
|
|
79
|
+
return "application/octet-stream";
|
|
80
|
+
}
|
|
81
|
+
return mimeType;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
package com.robylonreactnativesdk;
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.ReactPackage;
|
|
4
|
+
import com.facebook.react.bridge.NativeModule;
|
|
5
|
+
import com.facebook.react.bridge.ReactApplicationContext;
|
|
6
|
+
import com.facebook.react.uimanager.ViewManager;
|
|
7
|
+
|
|
8
|
+
import java.util.ArrayList;
|
|
9
|
+
import java.util.Collections;
|
|
10
|
+
import java.util.List;
|
|
11
|
+
|
|
12
|
+
public class RobylonReactNativeSdkPackage implements ReactPackage {
|
|
13
|
+
@Override
|
|
14
|
+
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
|
|
15
|
+
List<NativeModule> modules = new ArrayList<>();
|
|
16
|
+
modules.add(new RobylonDownloadModule(reactContext));
|
|
17
|
+
return modules;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
@Override
|
|
21
|
+
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
|
|
22
|
+
return Collections.emptyList();
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
var _interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault");Object.defineProperty(exports,"__esModule",{value:true});exports.default=exports.WidgetPositionEnums=exports.LauncherType=exports.ChatbotInterfaceType=void 0;var _asyncToGenerator2=_interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));var _slicedToArray2=_interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));var _react=_interopRequireWildcard(require("react"));var _reactNative=require("react-native");var _reactNativeWebview=require("react-native-webview");var _FloatingButton=_interopRequireDefault(require("./FloatingButton"));var _constants=require("./constants");var _systemInfo=require("./utils/systemInfo");var _useChatbotEvents2=require("./hooks/useChatbotEvents");var _events=require("./types/events");var _logger=require("./utils/logger");var _debugConfig=require("./utils/debugConfig");var _DebugButton=_interopRequireDefault(require("./components/DebugButton"));var _ErrorBoundary=require("./components/ErrorBoundary");var _errorConstants=require("./constants/errorConstants");var _ErrorTrackingService=require("./services/ErrorTrackingService");var _cookieUtils=require("./utils/cookieUtils");var _webViewStorage=require("./utils/webViewStorage");var _animations=require("./utils/animations");var _fileDownload=require("./utils/fileDownload");var _jsxRuntime=require("react/jsx-runtime");var _this=this,_jsxFileName="/Users/jobinabraham/Developer/professional/Mobile sdks/robylon-react-native-sdk/src/Chatbotsdk.tsx";function _interopRequireWildcard(e,t){if("function"==typeof WeakMap)var r=new WeakMap(),n=new WeakMap();return(_interopRequireWildcard=function _interopRequireWildcard(e,t){if(!t&&e&&e.__esModule)return e;var o,i,f={__proto__:null,default:e};if(null===e||"object"!=typeof e&&"function"!=typeof e)return f;if(o=t?n:r){if(o.has(e))return o.get(e);o.set(e,f);}for(var _t in e)"default"!==_t&&{}.hasOwnProperty.call(e,_t)&&((i=(o=Object.defineProperty)&&Object.getOwnPropertyDescriptor(e,_t))&&(i.get||i.set)?o(f,_t,i):f[_t]=e[_t]);return f;})(e,t);}var ChatbotInterfaceType=exports.ChatbotInterfaceType=function(ChatbotInterfaceType){ChatbotInterfaceType["WIDGET"]="WIDGET";ChatbotInterfaceType["POPOVER"]="POPOVER";ChatbotInterfaceType["EMBED"]="EMBED";return ChatbotInterfaceType;}({});var WidgetPositionEnums=exports.WidgetPositionEnums=function(WidgetPositionEnums){WidgetPositionEnums["RIGHT"]="Right";WidgetPositionEnums["LEFT"]="Left";return WidgetPositionEnums;}({});var LauncherType=exports.LauncherType=function(LauncherType){LauncherType["TEXT"]="TEXT";LauncherType["IMAGE"]="IMAGE";LauncherType["TEXTUAL_IMAGE"]="TEXTUAL_IMAGE";return LauncherType;}({});var Chatbot=(0,_react.forwardRef)(function(_ref,ref){var _chatbotConfig$interf,_chatbotConfig$interf2,_chatbotConfig$interf3,_chatbotConfig$interf4,_chatbotConfig$interf5;var api_key=_ref.api_key,user_id=_ref.user_id,user_token=_ref.user_token,_ref$show_floating_bu=_ref.show_floating_button,show_floating_button=_ref$show_floating_bu===void 0?true:_ref$show_floating_bu,onEvent=_ref.onEvent,onMessage=_ref.onMessage,_ref$isFullScreen=_ref.isFullScreen,isFullScreen=_ref$isFullScreen===void 0?true:_ref$isFullScreen,_ref$enableAnimation=_ref.enableAnimation,enableAnimation=_ref$enableAnimation===void 0?true:_ref$enableAnimation,externalOnOpen=_ref.onOpen,externalOnClose=_ref.onClose,onReady=_ref.onReady,user_profile=_ref.user_profile;var _useState=(0,_react.useState)(false),_useState2=(0,_slicedToArray2.default)(_useState,2),isWebViewVisible=_useState2[0],setIsWebViewVisible=_useState2[1];var _useState3=(0,_react.useState)(null),_useState4=(0,_slicedToArray2.default)(_useState3,2),chatbotConfig=_useState4[0],setChatbotConfig=_useState4[1];var _useState5=(0,_react.useState)(true),_useState6=(0,_slicedToArray2.default)(_useState5,2),loading=_useState6[0],setLoading=_useState6[1];var _useState7=(0,_react.useState)(false),_useState8=(0,_slicedToArray2.default)(_useState7,2),isInitialized=_useState8[0],setIsInitialized=_useState8[1];var webViewRef=(0,_react.useRef)(null);var isFirstLoadRef=(0,_react.useRef)(true);var _useState9=(0,_react.useState)(false),_useState10=(0,_slicedToArray2.default)(_useState9,2),toastVisible=_useState10[0],setToastVisible=_useState10[1];var _useState11=(0,_react.useState)(""),_useState12=(0,_slicedToArray2.default)(_useState11,2),toastMessage=_useState12[0],setToastMessage=_useState12[1];var _useState13=(0,_react.useState)(),_useState14=(0,_slicedToArray2.default)(_useState13,2),effectiveUserId=_useState14[0],setEffectiveUserId=_useState14[1];var _useState15=(0,_react.useState)(false),_useState16=(0,_slicedToArray2.default)(_useState15,2),isStorageReady=_useState16[0],setIsStorageReady=_useState16[1];var pendingStorageOps=(0,_react.useRef)([]);var memoryCache=(0,_react.useRef)({});var _useState17=(0,_react.useState)({os:"",browser:""}),_useState18=(0,_slicedToArray2.default)(_useState17,2),systemInfo=_useState18[0],setSystemInfo=_useState18[1];var systemInfoRef=(0,_react.useRef)({os:"",browser:""});var animatedValues=(0,_react.useRef)({scale:new _reactNative.Animated.Value(1),translateY:new _reactNative.Animated.Value(0),opacity:new _reactNative.Animated.Value(1)}).current;var chatbotConfigForEvents=(0,_react.useMemo)(function(){return{userId:effectiveUserId,isAnonymous:!user_id&&user_id!==0};},[effectiveUserId,user_id]);var _useChatbotEvents=(0,_useChatbotEvents2.useChatbotEvents)({api_key:api_key,chatbotConfig:chatbotConfigForEvents!=null?chatbotConfigForEvents:{},user_profile:user_profile,onEvent:onEvent,systemInfo:systemInfo!=null?systemInfo:{os:"",browser:""}}),emitEvent=_useChatbotEvents.emitEvent,onInternalEvent=_useChatbotEvents.onInternalEvent;(0,_react.useImperativeHandle)(ref,function(){return{open:function open(){if(isInitialized){openWebView();}},close:function close(){if(isInitialized){closeWebView();}},toggle:function toggle(){if(isInitialized){if(isWebViewVisible){closeWebView();}else{openWebView();}}},isReady:function isReady(){return isInitialized;}};},[isInitialized,isWebViewVisible]);var triggerAppInit=function triggerAppInit(){if(webViewRef.current){var _webViewRef$current;(_webViewRef$current=webViewRef.current)==null?void 0:_webViewRef$current.injectJavaScript((0,_systemInfo.getBrowserAndOSInfoScript)());webViewRef.current.injectJavaScript(`
|
|
1
|
+
var _interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault");Object.defineProperty(exports,"__esModule",{value:true});exports.default=exports.WidgetPositionEnums=exports.LauncherType=exports.ChatbotInterfaceType=void 0;var _defineProperty2=_interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));var _asyncToGenerator2=_interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));var _slicedToArray2=_interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));var _react=_interopRequireWildcard(require("react"));var _reactNative=require("react-native");var _reactNativeWebview=require("react-native-webview");var _FloatingButton=_interopRequireDefault(require("./FloatingButton"));var _constants=require("./constants");var _systemInfo=require("./utils/systemInfo");var _useChatbotEvents2=require("./hooks/useChatbotEvents");var _events=require("./types/events");var _logger=require("./utils/logger");var _debugConfig=require("./utils/debugConfig");var _DebugButton=_interopRequireDefault(require("./components/DebugButton"));var _ErrorBoundary=require("./components/ErrorBoundary");var _errorConstants=require("./constants/errorConstants");var _ErrorTrackingService=require("./services/ErrorTrackingService");var _cookieUtils=require("./utils/cookieUtils");var _webViewStorage=require("./utils/webViewStorage");var _animations=require("./utils/animations");var _fileDownload=require("./utils/fileDownload");var _session=require("./utils/session");var _jsxRuntime=require("react/jsx-runtime");var _this=this,_jsxFileName="/Users/jobinabraham/Developer/professional/Mobile sdks/robylon-react-native-sdk/src/Chatbotsdk.tsx";function _interopRequireWildcard(e,t){if("function"==typeof WeakMap)var r=new WeakMap(),n=new WeakMap();return(_interopRequireWildcard=function _interopRequireWildcard(e,t){if(!t&&e&&e.__esModule)return e;var o,i,f={__proto__:null,default:e};if(null===e||"object"!=typeof e&&"function"!=typeof e)return f;if(o=t?n:r){if(o.has(e))return o.get(e);o.set(e,f);}for(var _t in e)"default"!==_t&&{}.hasOwnProperty.call(e,_t)&&((i=(o=Object.defineProperty)&&Object.getOwnPropertyDescriptor(e,_t))&&(i.get||i.set)?o(f,_t,i):f[_t]=e[_t]);return f;})(e,t);}var ChatbotInterfaceType=exports.ChatbotInterfaceType=function(ChatbotInterfaceType){ChatbotInterfaceType["WIDGET"]="WIDGET";ChatbotInterfaceType["POPOVER"]="POPOVER";ChatbotInterfaceType["EMBED"]="EMBED";return ChatbotInterfaceType;}({});var WidgetPositionEnums=exports.WidgetPositionEnums=function(WidgetPositionEnums){WidgetPositionEnums["RIGHT"]="Right";WidgetPositionEnums["LEFT"]="Left";return WidgetPositionEnums;}({});var LauncherType=exports.LauncherType=function(LauncherType){LauncherType["TEXT"]="TEXT";LauncherType["IMAGE"]="IMAGE";LauncherType["TEXTUAL_IMAGE"]="TEXTUAL_IMAGE";return LauncherType;}({});var Chatbot=(0,_react.forwardRef)(function(_ref,ref){var _chatbotConfig$interf,_chatbotConfig$interf2,_chatbotConfig$interf3,_chatbotConfig$interf4,_chatbotConfig$interf5;var api_key=_ref.api_key,user_id=_ref.user_id,user_token=_ref.user_token,_ref$show_floating_bu=_ref.show_floating_button,show_floating_button=_ref$show_floating_bu===void 0?true:_ref$show_floating_bu,onEvent=_ref.onEvent,onMessage=_ref.onMessage,_ref$isFullScreen=_ref.isFullScreen,isFullScreen=_ref$isFullScreen===void 0?true:_ref$isFullScreen,_ref$enableAnimation=_ref.enableAnimation,enableAnimation=_ref$enableAnimation===void 0?true:_ref$enableAnimation,externalOnOpen=_ref.onOpen,externalOnClose=_ref.onClose,onReady=_ref.onReady,user_profile=_ref.user_profile,session_id=_ref.session_id,session_context=_ref.session_context,onSession=_ref.onSession;var _useState=(0,_react.useState)(false),_useState2=(0,_slicedToArray2.default)(_useState,2),isWebViewVisible=_useState2[0],setIsWebViewVisible=_useState2[1];var _useState3=(0,_react.useState)(null),_useState4=(0,_slicedToArray2.default)(_useState3,2),chatbotConfig=_useState4[0],setChatbotConfig=_useState4[1];var _useState5=(0,_react.useState)(true),_useState6=(0,_slicedToArray2.default)(_useState5,2),loading=_useState6[0],setLoading=_useState6[1];var _useState7=(0,_react.useState)(false),_useState8=(0,_slicedToArray2.default)(_useState7,2),isInitialized=_useState8[0],setIsInitialized=_useState8[1];var webViewRef=(0,_react.useRef)(null);var isFirstLoadRef=(0,_react.useRef)(true);var _useState9=(0,_react.useState)(false),_useState10=(0,_slicedToArray2.default)(_useState9,2),toastVisible=_useState10[0],setToastVisible=_useState10[1];var _useState11=(0,_react.useState)(""),_useState12=(0,_slicedToArray2.default)(_useState11,2),toastMessage=_useState12[0],setToastMessage=_useState12[1];var _useState13=(0,_react.useState)(),_useState14=(0,_slicedToArray2.default)(_useState13,2),effectiveUserId=_useState14[0],setEffectiveUserId=_useState14[1];var _useState15=(0,_react.useState)(false),_useState16=(0,_slicedToArray2.default)(_useState15,2),isStorageReady=_useState16[0],setIsStorageReady=_useState16[1];var pendingStorageOps=(0,_react.useRef)([]);var memoryCache=(0,_react.useRef)({});var _useState17=(0,_react.useState)({os:"",browser:""}),_useState18=(0,_slicedToArray2.default)(_useState17,2),systemInfo=_useState18[0],setSystemInfo=_useState18[1];var systemInfoRef=(0,_react.useRef)({os:"",browser:""});var sessionIdRef=(0,_react.useRef)(undefined);var onSessionRef=(0,_react.useRef)(onSession);var sessionContextRef=(0,_react.useRef)(session_context);var resumeSessionRef=(0,_react.useRef)(session_id);onSessionRef.current=onSession;sessionContextRef.current=session_context;resumeSessionRef.current=session_id;var animatedValues=(0,_react.useRef)({scale:new _reactNative.Animated.Value(1),translateY:new _reactNative.Animated.Value(0),opacity:new _reactNative.Animated.Value(1)}).current;var chatbotConfigForEvents=(0,_react.useMemo)(function(){return{userId:effectiveUserId,isAnonymous:!user_id&&user_id!==0};},[effectiveUserId,user_id]);var _useChatbotEvents=(0,_useChatbotEvents2.useChatbotEvents)({api_key:api_key,chatbotConfig:chatbotConfigForEvents!=null?chatbotConfigForEvents:{},user_profile:user_profile,onEvent:onEvent,systemInfo:systemInfo!=null?systemInfo:{os:"",browser:""}}),emitEvent=_useChatbotEvents.emitEvent,onInternalEvent=_useChatbotEvents.onInternalEvent;(0,_react.useImperativeHandle)(ref,function(){return{open:function open(){if(isInitialized){openWebView();}},close:function close(){if(isInitialized){closeWebView();}},toggle:function toggle(){if(isInitialized){if(isWebViewVisible){closeWebView();}else{openWebView();}}},isReady:function isReady(){return isInitialized;},getSessionId:function getSessionId(){return sessionIdRef.current;}};},[isInitialized,isWebViewVisible]);var emitSession=(0,_react.useCallback)(function(data){var sessionId=(0,_session.extractSessionId)(data);if(!sessionId||sessionId===sessionIdRef.current)return;sessionIdRef.current=sessionId;try{var _sessionContextRef$cu;onSessionRef.current==null?void 0:onSessionRef.current(sessionId,(_sessionContextRef$cu=sessionContextRef.current)!=null?_sessionContextRef$cu:{});}catch(error){_ErrorTrackingService.errorTracker.trackError(error instanceof Error?error:new Error("onSession handler threw an error"),"ChatbotSDK",{type:_errorConstants.ErrorTypes.RUNTIME_ERROR,context:{source:_session.SESSION_UPDATED_MESSAGE_TYPE}});}},[]);var triggerAppInit=function triggerAppInit(){if(webViewRef.current){var _webViewRef$current;(_webViewRef$current=webViewRef.current)==null?void 0:_webViewRef$current.injectJavaScript((0,_systemInfo.getBrowserAndOSInfoScript)());webViewRef.current.injectJavaScript(`
|
|
2
2
|
// Trigger APP_READY equivalent
|
|
3
3
|
window.ReactNativeWebView.postMessage(JSON.stringify({ type: 'APP_READY' }));
|
|
4
4
|
true;
|
|
5
|
-
`);}};var executeStorageOp=(0,_react.useCallback)(function(operation){if(isStorageReady){operation();}else{pendingStorageOps.current.push(operation);}},[isStorageReady]);var handleMessage=(0,_react.useCallback)(function(){var _ref2=(0,_asyncToGenerator2.default)(function*(event){var _webViewRef$current2;var data=event.nativeEvent.data;try{var parsedData=JSON.parse(data);if(Object.values(_webViewStorage.StorageMessageType).includes(parsedData.type)){var storageMessage=parsedData;switch(storageMessage.type){case _webViewStorage.StorageMessageType.STORAGE_READY:setIsStorageReady(true);pendingStorageOps.current.forEach(function(op){return op();});pendingStorageOps.current=[];(_webViewRef$current2=webViewRef.current)==null?void 0:_webViewRef$current2.injectJavaScript((0,_webViewStorage.createStorageMessage)(_webViewStorage.StorageMessageType.GET_STORAGE,"rblyn_anon"));break;case _webViewStorage.StorageMessageType.STORAGE_RESPONSE:if(storageMessage.key&&storageMessage.value){memoryCache.current[storageMessage.key]=storageMessage.value;if(storageMessage.key==="rblyn_anon"){setEffectiveUserId(storageMessage.value);}}break;case _webViewStorage.StorageMessageType.STORAGE_ERROR:_logger.logger.error("WebView storage error:",storageMessage.error);break;}return;}if(__DEV__){if((parsedData==null?void 0:parsedData.type)==="CONSOLE"){console.log(`WebView ${parsedData==null?void 0:parsedData.level}:`,parsedData==null?void 0:parsedData.data);return;}if((parsedData==null?void 0:parsedData.type)==="ERROR"){console.error("WebView Error:",parsedData==null?void 0:parsedData.data);return;}}if((parsedData==null?void 0:parsedData.type)==="SYSTEM_INFO"){var _parsedData$data;setSystemInfo((_parsedData$data=parsedData==null?void 0:parsedData.data)!=null?_parsedData$data:{os:"",browser:""});systemInfoRef.current=parsedData==null?void 0:parsedData.data;return;}if((parsedData==null?void 0:parsedData.type)==="APP_READY"){emitEvent(_events.ChatbotEventType.CHATBOT_APP_READY);if(webViewRef.current&&isWebViewVisible){var _webViewRef$current3,_webViewRef$current4;(_webViewRef$current3=webViewRef.current)==null?void 0:_webViewRef$current3.injectJavaScript((0,_systemInfo.getBrowserAndOSInfoScript)());var messageData={name:"registerUserId",action:"registerUserId",data:{userId:effectiveUserId,token
|
|
5
|
+
`);}};var executeStorageOp=(0,_react.useCallback)(function(operation){if(isStorageReady){operation();}else{pendingStorageOps.current.push(operation);}},[isStorageReady]);var handleMessage=(0,_react.useCallback)(function(){var _ref2=(0,_asyncToGenerator2.default)(function*(event){var _webViewRef$current2;var data=event.nativeEvent.data;try{var parsedData=JSON.parse(data);if(Object.values(_webViewStorage.StorageMessageType).includes(parsedData.type)){var storageMessage=parsedData;switch(storageMessage.type){case _webViewStorage.StorageMessageType.STORAGE_READY:setIsStorageReady(true);pendingStorageOps.current.forEach(function(op){return op();});pendingStorageOps.current=[];(_webViewRef$current2=webViewRef.current)==null?void 0:_webViewRef$current2.injectJavaScript((0,_webViewStorage.createStorageMessage)(_webViewStorage.StorageMessageType.GET_STORAGE,"rblyn_anon"));break;case _webViewStorage.StorageMessageType.STORAGE_RESPONSE:if(storageMessage.key&&storageMessage.value){memoryCache.current[storageMessage.key]=storageMessage.value;if(storageMessage.key==="rblyn_anon"){setEffectiveUserId(storageMessage.value);}}break;case _webViewStorage.StorageMessageType.STORAGE_ERROR:_logger.logger.error("WebView storage error:",storageMessage.error);break;}return;}if(__DEV__){if((parsedData==null?void 0:parsedData.type)==="CONSOLE"){console.log(`WebView ${parsedData==null?void 0:parsedData.level}:`,parsedData==null?void 0:parsedData.data);return;}if((parsedData==null?void 0:parsedData.type)==="ERROR"){console.error("WebView Error:",parsedData==null?void 0:parsedData.data);return;}}if((parsedData==null?void 0:parsedData.type)==="SYSTEM_INFO"){var _parsedData$data;setSystemInfo((_parsedData$data=parsedData==null?void 0:parsedData.data)!=null?_parsedData$data:{os:"",browser:""});systemInfoRef.current=parsedData==null?void 0:parsedData.data;return;}if((parsedData==null?void 0:parsedData.type)===_session.SESSION_UPDATED_MESSAGE_TYPE){emitSession(parsedData==null?void 0:parsedData.data);return;}if((parsedData==null?void 0:parsedData.type)==="APP_READY"){emitEvent(_events.ChatbotEventType.CHATBOT_APP_READY);if(webViewRef.current&&isWebViewVisible){var _webViewRef$current3,_webViewRef$current4;(_webViewRef$current3=webViewRef.current)==null?void 0:_webViewRef$current3.injectJavaScript((0,_systemInfo.getBrowserAndOSInfoScript)());var messageData={name:"registerUserId",action:"registerUserId",data:(0,_defineProperty2.default)((0,_defineProperty2.default)((0,_defineProperty2.default)({userId:effectiveUserId},_session.RESUME_SESSION_KEY,resumeSessionRef.current||undefined),"token",user_token?`${user_token}`:undefined),"userProfile",Object.assign({},user_profile,(0,_systemInfo.getSystemInfo)(systemInfoRef==null?void 0:systemInfoRef.current),{__INT_SYS_INFO__:Object.assign({},(0,_systemInfo.getSystemInfo)(systemInfoRef==null?void 0:systemInfoRef.current))}))};_logger.logger.debug("messageData====>",JSON.stringify(Object.assign({},messageData,{data:Object.assign({},messageData.data,(0,_defineProperty2.default)({},_session.RESUME_SESSION_KEY,resumeSessionRef.current?"[redacted]":undefined))})));(_webViewRef$current4=webViewRef.current)==null?void 0:_webViewRef$current4.injectJavaScript(`
|
|
6
6
|
window.postMessage(${JSON.stringify({name:"openFrame",domain:"app-domain.com"})}, '*');
|
|
7
7
|
window.postMessage(${JSON.stringify(messageData)}, '*');
|
|
8
8
|
`);}}switch(parsedData==null?void 0:parsedData.type){case"close_chatbot":closeWebView();break;case"download_file":if(parsedData!=null&&parsedData.data||parsedData!=null&&parsedData.url&&parsedData!=null&&parsedData.filename){var downloadData=(parsedData==null?void 0:parsedData.data)||{url:parsedData==null?void 0:parsedData.url,filename:parsedData==null?void 0:parsedData.filename,inPlace:parsedData==null?void 0:parsedData.inPlace};(0,_fileDownload.handleDownloadRequest)(downloadData);}break;case"CHATBOT_LOADED":emitEvent(_events.ChatbotEventType.CHATBOT_LOADED,parsedData==null?void 0:parsedData.data);break;case"CHAT_INITIALIZED":emitEvent(_events.ChatbotEventType.CHAT_INITIALIZED,parsedData==null?void 0:parsedData.data);break;case"SESSION_REFRESHED":emitEvent(_events.ChatbotEventType.SESSION_REFRESHED,parsedData==null?void 0:parsedData.data);break;case"CHAT_INITIALIZATION_FAILED":emitEvent(_events.ChatbotEventType.CHAT_INITIALIZATION_FAILED,parsedData==null?void 0:parsedData.data);break;case"REQUEST_MIC_PERMISSION":var granted=yield requestAndroidMicPermission();if(webViewRef.current&&isWebViewVisible){var _webViewRef$current5;var _messageData={name:"requestMicPermission",action:"requestMicPermission",type:granted?"MIC_PERMISSION_GRANTED":"MIC_PERMISSION_DENIED"};(_webViewRef$current5=webViewRef.current)==null?void 0:_webViewRef$current5.injectJavaScript(`
|
|
9
|
-
window.postMessage(${JSON.stringify(_messageData)}, '*');`);}break;default:if(onMessage)onMessage(parsedData!=null?parsedData:{});}}catch(error){_ErrorTrackingService.errorTracker.trackError(error instanceof Error?error:new Error("Failed to parse WebView message"),"ChatbotSDK",{type:_errorConstants.ErrorTypes.RUNTIME_ERROR,context:{messageData:data}});}});return function(_x){return _ref2.apply(this,arguments);};}(),[emitEvent,isWebViewVisible,onMessage,systemInfo,effectiveUserId,user_token,user_profile]);(0,_react.useEffect)(function(){var initializeUserId=function(){var _ref3=(0,_asyncToGenerator2.default)(function*(){var userId=user_id?String(user_id):undefined;if(!userId){userId=memoryCache.current["rblyn_anon"];if(!userId){userId=(0,_cookieUtils.generateUUID)();executeStorageOp(function(){var _webViewRef$current6;(_webViewRef$current6=webViewRef.current)==null?void 0:_webViewRef$current6.injectJavaScript((0,_webViewStorage.createStorageMessage)(_webViewStorage.StorageMessageType.SET_STORAGE,"rblyn_anon",userId));});}}setEffectiveUserId(userId);});return function initializeUserId(){return _ref3.apply(this,arguments);};}();initializeUserId();},[user_id,executeStorageOp]);(0,_react.useEffect)(function(){if(webViewRef.current){webViewRef.current.injectJavaScript((0,_webViewStorage.getStorageScript)());executeStorageOp(function(){var _webViewRef$current7;(_webViewRef$current7=webViewRef.current)==null?void 0:_webViewRef$current7.injectJavaScript((0,_webViewStorage.createStorageMessage)(_webViewStorage.StorageMessageType.GET_STORAGE,"rblyn_anon"));});}},[]);(0,_react.useEffect)(function(){var fetchChatbotConfig=function(){var _ref4=(0,_asyncToGenerator2.default)(function*(){try{var _data$user;var endpointUrl=`${_constants.API_URL}/chat/chatbot/get/`;var payload={client_user_id:effectiveUserId,org_id:api_key,token:user_token,extra_info:{}};var response=yield fetch(endpointUrl,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(payload)});if(!response.ok){throw new Error("Failed to fetch chatbot configuration");}var data=yield response.json();var orgInfo=data==null?void 0:(_data$user=data.user)==null?void 0:_data$user.org_info;if(orgInfo){var _orgInfo$brand_config,_orgInfo$brand_config2,_orgInfo$brand_config3,_orgInfo$brand_config4,_orgInfo$brand_config5,_orgInfo$brand_config6,_orgInfo$brand_config7,_orgInfo$brand_config8,_orgInfo$brand_config9,_orgInfo$brand_config10,_orgInfo$brand_config11,_orgInfo$brand_config12,_orgInfo$brand_config13,_orgInfo$brand_config14,_orgInfo$brand_config15,_orgInfo$brand_config16,_orgInfo$brand_config17,_orgInfo$brand_config18,_orgInfo$brand_config19,_orgInfo$brand_config20,_orgInfo$brand_config21,_orgInfo$brand_config22;var config={brand_colour:((_orgInfo$brand_config=orgInfo.brand_config)==null?void 0:(_orgInfo$brand_config2=_orgInfo$brand_config.colors)==null?void 0:_orgInfo$brand_config2.brand_color)||"",image_url:((_orgInfo$brand_config3=orgInfo.brand_config)==null?void 0:_orgInfo$brand_config3.launcher_logo_url)||"",chat_interface_config:{chat_bubble_prompts:[],display_name:((_orgInfo$brand_config4=orgInfo.brand_config)==null?void 0:_orgInfo$brand_config4.display_name)||"",welcome_message:((_orgInfo$brand_config5=orgInfo.brand_config)==null?void 0:_orgInfo$brand_config5.welcome_message)||"Hey! What can we help you with today?",redirect_url:((_orgInfo$brand_config6=orgInfo.brand_config)==null?void 0:_orgInfo$brand_config6.redirect_url)||""},interface_properties:{position:((_orgInfo$brand_config7=orgInfo.brand_config)==null?void 0:(_orgInfo$brand_config8=_orgInfo$brand_config7.interface_properties)==null?void 0:_orgInfo$brand_config8.position)||WidgetPositionEnums.RIGHT,side_spacing:(_orgInfo$brand_config9=(_orgInfo$brand_config10=orgInfo.brand_config)==null?void 0:(_orgInfo$brand_config11=_orgInfo$brand_config10.interface_properties)==null?void 0:_orgInfo$brand_config11.side_spacing)!=null?_orgInfo$brand_config9:20,bottom_spacing:(_orgInfo$brand_config12=(_orgInfo$brand_config13=orgInfo.brand_config)==null?void 0:(_orgInfo$brand_config14=_orgInfo$brand_config13.interface_properties)==null?void 0:_orgInfo$brand_config14.bottom_spacing)!=null?_orgInfo$brand_config12:20},interface_type:((_orgInfo$brand_config15=orgInfo.brand_config)==null?void 0:_orgInfo$brand_config15.interface_type)||ChatbotInterfaceType.WIDGET,launcher_type:((_orgInfo$brand_config16=orgInfo.brand_config)==null?void 0:_orgInfo$brand_config16.launcher_type)||LauncherType.IMAGE,launcher_properties:{text:((_orgInfo$brand_config17=orgInfo.brand_config)==null?void 0:(_orgInfo$brand_config18=_orgInfo$brand_config17.launcher_properties)==null?void 0:_orgInfo$brand_config18.text)||""},images:{launcher_image_url:{url:((_orgInfo$brand_config19=orgInfo.brand_config)==null?void 0:(_orgInfo$brand_config20=_orgInfo$brand_config19.images)==null?void 0:(_orgInfo$brand_config21=_orgInfo$brand_config20.launcher_image_url)==null?void 0:_orgInfo$brand_config21.url)||_constants.DEFAULT_LAUNCHER_IMAGE}},chat_iframe_url:((_orgInfo$brand_config22=orgInfo.brand_config)==null?void 0:_orgInfo$brand_config22.chat_iframe_url)||""};setChatbotConfig(config);}}catch(error){_ErrorTrackingService.errorTracker.trackError(error instanceof Error?error:new Error("Failed to fetch chatbot configuration"),"ChatbotSDK",{type:_errorConstants.ErrorTypes.NETWORK_ERROR,context:{api_key:api_key,user_id:user_id}});}finally{setLoading(false);}});return function fetchChatbotConfig(){return _ref4.apply(this,arguments);};}();if(api_key&&effectiveUserId){fetchChatbotConfig();}},[api_key,effectiveUserId,user_token]);function constructUrl(){if(!effectiveUserId)return"";var params=new URLSearchParams({id:api_key});return`${_constants.BASE_CHATBOT_URL}?${params.toString()}`;}var openWebView=(0,_react.useCallback)(function(){setIsWebViewVisible(true);if(enableAnimation){(0,_animations.animateWebViewOpen)(animatedValues,function(){externalOnOpen==null?void 0:externalOnOpen();emitEvent(_events.ChatbotEventType.CHATBOT_OPENED);if(!isFirstLoadRef.current){setTimeout(triggerAppInit,100);}});}else{requestAnimationFrame(function(){externalOnOpen==null?void 0:externalOnOpen();emitEvent(_events.ChatbotEventType.CHATBOT_OPENED);if(!isFirstLoadRef.current){setTimeout(triggerAppInit,100);}});}},[enableAnimation,animatedValues,externalOnOpen,emitEvent]);var closeWebView=(0,_react.useCallback)(function(){if(webViewRef.current){webViewRef.current.postMessage(JSON.stringify({name:"closeFrame",domain:"app-domain.com"}));}if(enableAnimation){(0,_animations.animateWebViewClose)(animatedValues,function(){setIsWebViewVisible(false);externalOnClose==null?void 0:externalOnClose();emitEvent(_events.ChatbotEventType.CHATBOT_CLOSED);});}else{setIsWebViewVisible(false);externalOnClose==null?void 0:externalOnClose();emitEvent(_events.ChatbotEventType.CHATBOT_CLOSED);}},[enableAnimation,animatedValues,externalOnClose,emitEvent]);(0,_react.useEffect)(function(){if(show_floating_button&&chatbotConfig){emitEvent(_events.ChatbotEventType.CHATBOT_BUTTON_LOADED);}},[show_floating_button,chatbotConfig,emitEvent]);(0,_react.useEffect)(function(){if(!loading&&chatbotConfig&&effectiveUserId&&!isInitialized){setIsInitialized(true);onReady==null?void 0:onReady();}},[loading,chatbotConfig,effectiveUserId,isInitialized,onReady]);var getScreenDimensions=function getScreenDimensions(){var windowHeight=_reactNative.Dimensions.get("window").height;var windowWidth=_reactNative.Dimensions.get("window").width;var statusBarHeight=_reactNative.Platform.OS==="ios"?0:_reactNative.StatusBar.currentHeight||0;return{height:windowHeight-statusBarHeight,width:windowWidth};};var requestAndroidMicPermission=(0,_react.useCallback)((0,_asyncToGenerator2.default)(function*(){try{if(_reactNative.Platform.OS==="ios"){return true;}var alreadyGranted=yield _reactNative.PermissionsAndroid.check(_reactNative.PermissionsAndroid.PERMISSIONS.RECORD_AUDIO);if(alreadyGranted){return true;}var result=yield _reactNative.PermissionsAndroid.request(_reactNative.PermissionsAndroid.PERMISSIONS.RECORD_AUDIO,{title:"Microphone permission",message:"This app uses your microphone for voice features.",buttonPositive:"Allow",buttonNegative:"Deny"});var granted=result===_reactNative.PermissionsAndroid.RESULTS.GRANTED;if(!granted){_reactNative.Alert.alert("Microphone required","Voice features will not work unless you allow microphone access.");}return granted;}catch(err){console.warn("Error requesting mic permission",err);return false;}}),[]);var screenDimensions=getScreenDimensions();(0,_react.useEffect)(function(){if(__DEV__){(0,_debugConfig.enableNetworkDebug)();}},[]);var position=(chatbotConfig==null?void 0:(_chatbotConfig$interf=chatbotConfig.interface_properties)==null?void 0:_chatbotConfig$interf.position)||"Right";var sideSpacing=(_chatbotConfig$interf2=chatbotConfig==null?void 0:(_chatbotConfig$interf3=chatbotConfig.interface_properties)==null?void 0:_chatbotConfig$interf3.side_spacing)!=null?_chatbotConfig$interf2:20;var bottomSpacing=(_chatbotConfig$interf4=chatbotConfig==null?void 0:(_chatbotConfig$interf5=chatbotConfig.interface_properties)==null?void 0:_chatbotConfig$interf5.bottom_spacing)!=null?_chatbotConfig$interf4:20;return(0,_jsxRuntime.jsx)(_ErrorBoundary.ErrorBoundary,{componentName:"ChatbotSDK",children:(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles==null?void 0:styles.mainContainer,children:[!loading&&(0,_jsxRuntime.jsxs)(_jsxRuntime.Fragment,{children:[(0,_jsxRuntime.jsx)(_ErrorBoundary.ErrorBoundary,{componentName:"FloatingButton",children:show_floating_button&&api_key&&chatbotConfig&&(0,_jsxRuntime.jsx)(_FloatingButton.default,{chatbotConfig:chatbotConfig,isWebViewVisible:isWebViewVisible,onPress:function onPress(){emitEvent(_events.ChatbotEventType.CHATBOT_BUTTON_CLICKED);openWebView();},brandColor:chatbotConfig.brand_colour,imageUrl:chatbotConfig.image_url})}),(0,_jsxRuntime.jsx)(_reactNative.View,{style:[styles.webViewWrapper,{height:isWebViewVisible?"100%":0}],pointerEvents:isWebViewVisible?"auto":"none",children:(0,_jsxRuntime.jsx)(_reactNative.Animated.View,{style:[styles.fullScreenContainer,{opacity:animatedValues.opacity,transform:[{scale:animatedValues.scale},{translateY:animatedValues.translateY}]}],children:(0,_jsxRuntime.jsx)(_ErrorBoundary.ErrorBoundary,{componentName:"ChatbotWebView",children:(0,_jsxRuntime.jsx)(_reactNativeWebview.WebView,{mediaCapturePermissionGrantType:"grant",webviewDebuggingEnabled:true,ref:webViewRef,source:{uri:constructUrl()},onMessage:handleMessage,style:styles.webview,containerStyle:isFullScreen?{width:screenDimensions.width,height:screenDimensions.height-40}:undefined,allowsInlineMediaPlayback:true,mediaPlaybackRequiresUserAction:false,allowFileAccess:false,geolocationEnabled:false,javaScriptEnabled:true,domStorageEnabled:true,cacheEnabled:true,scrollEnabled:true,bounces:false,onShouldStartLoadWithRequest:function onShouldStartLoadWithRequest(request){return request.url.startsWith(_constants.BASE_CHATBOT_URL)||request.url.startsWith((chatbotConfig==null?void 0:chatbotConfig.chat_iframe_url)||"");},startInLoadingState:isFirstLoadRef.current,onLoadEnd:function onLoadEnd(){var _webViewRef$current8;if(__DEV__){(0,_debugConfig.enableWebViewDebug)(webViewRef);}(_webViewRef$current8=webViewRef.current)==null?void 0:_webViewRef$current8.injectJavaScript(`
|
|
9
|
+
window.postMessage(${JSON.stringify(_messageData)}, '*');`);}break;default:if(onMessage)onMessage(parsedData!=null?parsedData:{});}}catch(error){_ErrorTrackingService.errorTracker.trackError(error instanceof Error?error:new Error("Failed to parse WebView message"),"ChatbotSDK",{type:_errorConstants.ErrorTypes.RUNTIME_ERROR,context:{messageData:data}});}});return function(_x){return _ref2.apply(this,arguments);};}(),[emitEvent,emitSession,isWebViewVisible,onMessage,systemInfo,effectiveUserId,user_token,user_profile]);(0,_react.useEffect)(function(){var initializeUserId=function(){var _ref3=(0,_asyncToGenerator2.default)(function*(){var userId=user_id?String(user_id):undefined;if(!userId){userId=memoryCache.current["rblyn_anon"];if(!userId){userId=(0,_cookieUtils.generateUUID)();executeStorageOp(function(){var _webViewRef$current6;(_webViewRef$current6=webViewRef.current)==null?void 0:_webViewRef$current6.injectJavaScript((0,_webViewStorage.createStorageMessage)(_webViewStorage.StorageMessageType.SET_STORAGE,"rblyn_anon",userId));});}}setEffectiveUserId(userId);});return function initializeUserId(){return _ref3.apply(this,arguments);};}();initializeUserId();},[user_id,executeStorageOp]);(0,_react.useEffect)(function(){if(webViewRef.current){webViewRef.current.injectJavaScript((0,_webViewStorage.getStorageScript)());executeStorageOp(function(){var _webViewRef$current7;(_webViewRef$current7=webViewRef.current)==null?void 0:_webViewRef$current7.injectJavaScript((0,_webViewStorage.createStorageMessage)(_webViewStorage.StorageMessageType.GET_STORAGE,"rblyn_anon"));});}},[]);(0,_react.useEffect)(function(){var fetchChatbotConfig=function(){var _ref4=(0,_asyncToGenerator2.default)(function*(){try{var _data$user;var endpointUrl=`${_constants.API_URL}/chat/chatbot/get/`;var payload={client_user_id:effectiveUserId,resumable_session_id:resumeSessionRef.current||undefined,org_id:api_key,token:user_token,extra_info:{}};var response=yield fetch(endpointUrl,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(payload)});if(!response.ok){throw new Error("Failed to fetch chatbot configuration");}var data=yield response.json();var orgInfo=data==null?void 0:(_data$user=data.user)==null?void 0:_data$user.org_info;if(orgInfo){var _orgInfo$brand_config,_orgInfo$brand_config2,_orgInfo$brand_config3,_orgInfo$brand_config4,_orgInfo$brand_config5,_orgInfo$brand_config6,_orgInfo$brand_config7,_orgInfo$brand_config8,_orgInfo$brand_config9,_orgInfo$brand_config10,_orgInfo$brand_config11,_orgInfo$brand_config12,_orgInfo$brand_config13,_orgInfo$brand_config14,_orgInfo$brand_config15,_orgInfo$brand_config16,_orgInfo$brand_config17,_orgInfo$brand_config18,_orgInfo$brand_config19,_orgInfo$brand_config20,_orgInfo$brand_config21,_orgInfo$brand_config22;var config={brand_colour:((_orgInfo$brand_config=orgInfo.brand_config)==null?void 0:(_orgInfo$brand_config2=_orgInfo$brand_config.colors)==null?void 0:_orgInfo$brand_config2.brand_color)||"",image_url:((_orgInfo$brand_config3=orgInfo.brand_config)==null?void 0:_orgInfo$brand_config3.launcher_logo_url)||"",chat_interface_config:{chat_bubble_prompts:[],display_name:((_orgInfo$brand_config4=orgInfo.brand_config)==null?void 0:_orgInfo$brand_config4.display_name)||"",welcome_message:((_orgInfo$brand_config5=orgInfo.brand_config)==null?void 0:_orgInfo$brand_config5.welcome_message)||"Hey! What can we help you with today?",redirect_url:((_orgInfo$brand_config6=orgInfo.brand_config)==null?void 0:_orgInfo$brand_config6.redirect_url)||""},interface_properties:{position:((_orgInfo$brand_config7=orgInfo.brand_config)==null?void 0:(_orgInfo$brand_config8=_orgInfo$brand_config7.interface_properties)==null?void 0:_orgInfo$brand_config8.position)||WidgetPositionEnums.RIGHT,side_spacing:(_orgInfo$brand_config9=(_orgInfo$brand_config10=orgInfo.brand_config)==null?void 0:(_orgInfo$brand_config11=_orgInfo$brand_config10.interface_properties)==null?void 0:_orgInfo$brand_config11.side_spacing)!=null?_orgInfo$brand_config9:20,bottom_spacing:(_orgInfo$brand_config12=(_orgInfo$brand_config13=orgInfo.brand_config)==null?void 0:(_orgInfo$brand_config14=_orgInfo$brand_config13.interface_properties)==null?void 0:_orgInfo$brand_config14.bottom_spacing)!=null?_orgInfo$brand_config12:20},interface_type:((_orgInfo$brand_config15=orgInfo.brand_config)==null?void 0:_orgInfo$brand_config15.interface_type)||ChatbotInterfaceType.WIDGET,launcher_type:((_orgInfo$brand_config16=orgInfo.brand_config)==null?void 0:_orgInfo$brand_config16.launcher_type)||LauncherType.IMAGE,launcher_properties:{text:((_orgInfo$brand_config17=orgInfo.brand_config)==null?void 0:(_orgInfo$brand_config18=_orgInfo$brand_config17.launcher_properties)==null?void 0:_orgInfo$brand_config18.text)||""},images:{launcher_image_url:{url:((_orgInfo$brand_config19=orgInfo.brand_config)==null?void 0:(_orgInfo$brand_config20=_orgInfo$brand_config19.images)==null?void 0:(_orgInfo$brand_config21=_orgInfo$brand_config20.launcher_image_url)==null?void 0:_orgInfo$brand_config21.url)||_constants.DEFAULT_LAUNCHER_IMAGE}},chat_iframe_url:((_orgInfo$brand_config22=orgInfo.brand_config)==null?void 0:_orgInfo$brand_config22.chat_iframe_url)||""};setChatbotConfig(config);}}catch(error){_ErrorTrackingService.errorTracker.trackError(error instanceof Error?error:new Error("Failed to fetch chatbot configuration"),"ChatbotSDK",{type:_errorConstants.ErrorTypes.NETWORK_ERROR,context:{api_key:api_key,user_id:user_id}});}finally{setLoading(false);}});return function fetchChatbotConfig(){return _ref4.apply(this,arguments);};}();if(api_key&&effectiveUserId){fetchChatbotConfig();}},[api_key,effectiveUserId,user_token]);function constructUrl(){if(!effectiveUserId)return"";var params=new URLSearchParams({id:api_key});return`${_constants.BASE_CHATBOT_URL}?${params.toString()}`;}var openWebView=(0,_react.useCallback)(function(){setIsWebViewVisible(true);if(enableAnimation){(0,_animations.animateWebViewOpen)(animatedValues,function(){externalOnOpen==null?void 0:externalOnOpen();emitEvent(_events.ChatbotEventType.CHATBOT_OPENED);if(!isFirstLoadRef.current){setTimeout(triggerAppInit,100);}});}else{requestAnimationFrame(function(){externalOnOpen==null?void 0:externalOnOpen();emitEvent(_events.ChatbotEventType.CHATBOT_OPENED);if(!isFirstLoadRef.current){setTimeout(triggerAppInit,100);}});}},[enableAnimation,animatedValues,externalOnOpen,emitEvent]);var closeWebView=(0,_react.useCallback)(function(){if(webViewRef.current){webViewRef.current.postMessage(JSON.stringify({name:"closeFrame",domain:"app-domain.com"}));}if(enableAnimation){(0,_animations.animateWebViewClose)(animatedValues,function(){setIsWebViewVisible(false);externalOnClose==null?void 0:externalOnClose();emitEvent(_events.ChatbotEventType.CHATBOT_CLOSED);});}else{setIsWebViewVisible(false);externalOnClose==null?void 0:externalOnClose();emitEvent(_events.ChatbotEventType.CHATBOT_CLOSED);}},[enableAnimation,animatedValues,externalOnClose,emitEvent]);(0,_react.useEffect)(function(){if(show_floating_button&&chatbotConfig){emitEvent(_events.ChatbotEventType.CHATBOT_BUTTON_LOADED);}},[show_floating_button,chatbotConfig,emitEvent]);(0,_react.useEffect)(function(){if(!loading&&chatbotConfig&&effectiveUserId&&!isInitialized){setIsInitialized(true);onReady==null?void 0:onReady();}},[loading,chatbotConfig,effectiveUserId,isInitialized,onReady]);var getScreenDimensions=function getScreenDimensions(){var windowHeight=_reactNative.Dimensions.get("window").height;var windowWidth=_reactNative.Dimensions.get("window").width;var statusBarHeight=_reactNative.Platform.OS==="ios"?0:_reactNative.StatusBar.currentHeight||0;return{height:windowHeight-statusBarHeight,width:windowWidth};};var requestAndroidMicPermission=(0,_react.useCallback)((0,_asyncToGenerator2.default)(function*(){try{if(_reactNative.Platform.OS==="ios"){return true;}var alreadyGranted=yield _reactNative.PermissionsAndroid.check(_reactNative.PermissionsAndroid.PERMISSIONS.RECORD_AUDIO);if(alreadyGranted){return true;}var result=yield _reactNative.PermissionsAndroid.request(_reactNative.PermissionsAndroid.PERMISSIONS.RECORD_AUDIO,{title:"Microphone permission",message:"This app uses your microphone for voice features.",buttonPositive:"Allow",buttonNegative:"Deny"});var granted=result===_reactNative.PermissionsAndroid.RESULTS.GRANTED;if(!granted){_reactNative.Alert.alert("Microphone required","Voice features will not work unless you allow microphone access.");}return granted;}catch(err){console.warn("Error requesting mic permission",err);return false;}}),[]);var screenDimensions=getScreenDimensions();(0,_react.useEffect)(function(){if(__DEV__){(0,_debugConfig.enableNetworkDebug)();}},[]);var position=(chatbotConfig==null?void 0:(_chatbotConfig$interf=chatbotConfig.interface_properties)==null?void 0:_chatbotConfig$interf.position)||"Right";var sideSpacing=(_chatbotConfig$interf2=chatbotConfig==null?void 0:(_chatbotConfig$interf3=chatbotConfig.interface_properties)==null?void 0:_chatbotConfig$interf3.side_spacing)!=null?_chatbotConfig$interf2:20;var bottomSpacing=(_chatbotConfig$interf4=chatbotConfig==null?void 0:(_chatbotConfig$interf5=chatbotConfig.interface_properties)==null?void 0:_chatbotConfig$interf5.bottom_spacing)!=null?_chatbotConfig$interf4:20;return(0,_jsxRuntime.jsx)(_ErrorBoundary.ErrorBoundary,{componentName:"ChatbotSDK",children:(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles==null?void 0:styles.mainContainer,pointerEvents:isWebViewVisible?"auto":"box-none",children:[!loading&&(0,_jsxRuntime.jsxs)(_jsxRuntime.Fragment,{children:[(0,_jsxRuntime.jsx)(_ErrorBoundary.ErrorBoundary,{componentName:"FloatingButton",children:show_floating_button&&api_key&&chatbotConfig&&(0,_jsxRuntime.jsx)(_FloatingButton.default,{chatbotConfig:chatbotConfig,isWebViewVisible:isWebViewVisible,onPress:function onPress(){emitEvent(_events.ChatbotEventType.CHATBOT_BUTTON_CLICKED);openWebView();},brandColor:chatbotConfig.brand_colour,imageUrl:chatbotConfig.image_url})}),(0,_jsxRuntime.jsx)(_reactNative.View,{style:[styles.webViewWrapper,{height:isWebViewVisible?"100%":0}],pointerEvents:isWebViewVisible?"auto":"none",children:(0,_jsxRuntime.jsx)(_reactNative.Animated.View,{style:[styles.fullScreenContainer,{opacity:animatedValues.opacity,transform:[{scale:animatedValues.scale},{translateY:animatedValues.translateY}]}],children:(0,_jsxRuntime.jsx)(_ErrorBoundary.ErrorBoundary,{componentName:"ChatbotWebView",children:(0,_jsxRuntime.jsx)(_reactNativeWebview.WebView,{mediaCapturePermissionGrantType:"grant",webviewDebuggingEnabled:true,ref:webViewRef,source:{uri:constructUrl()},onMessage:handleMessage,style:styles.webview,containerStyle:isFullScreen?{width:screenDimensions.width,height:screenDimensions.height-40}:undefined,allowsInlineMediaPlayback:true,mediaPlaybackRequiresUserAction:false,allowFileAccess:false,geolocationEnabled:false,javaScriptEnabled:true,domStorageEnabled:true,cacheEnabled:true,scrollEnabled:true,bounces:false,onShouldStartLoadWithRequest:function onShouldStartLoadWithRequest(request){return request.url.startsWith(_constants.BASE_CHATBOT_URL)||request.url.startsWith((chatbotConfig==null?void 0:chatbotConfig.chat_iframe_url)||"");},startInLoadingState:isFirstLoadRef.current,onLoadEnd:function onLoadEnd(){var _webViewRef$current8;if(__DEV__){(0,_debugConfig.enableWebViewDebug)(webViewRef);}(_webViewRef$current8=webViewRef.current)==null?void 0:_webViewRef$current8.injectJavaScript(`
|
|
10
10
|
if (!document.querySelector('meta[name="viewport"]')) {
|
|
11
11
|
var meta = document.createElement('meta');
|
|
12
12
|
meta.name = 'viewport';
|