@lorikeetai/react-native-sdk 2.0.0-alpha.1 → 2.0.0-alpha.2
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 +97 -5
- package/dist/index.cjs +222 -44
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +70 -4
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +70 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +223 -45
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -22,7 +22,7 @@ bare `pnpm add @lorikeetai/react-native-sdk` installs the 1.x line, and no
|
|
|
22
22
|
semver range reaches a prerelease either.
|
|
23
23
|
|
|
24
24
|
```bash
|
|
25
|
-
pnpm add @lorikeetai/react-native-sdk@2.0.0-alpha.
|
|
25
|
+
pnpm add @lorikeetai/react-native-sdk@2.0.0-alpha.2 \
|
|
26
26
|
react-native-webview@^13.15.0 \
|
|
27
27
|
react-native-safe-area-context@^5.6.0 \
|
|
28
28
|
react-native-svg@^15.13.0
|
|
@@ -67,9 +67,12 @@ export default function Screen() {
|
|
|
67
67
|
- `publicKey` (required): The public key for your Lorikeet account
|
|
68
68
|
- `authToken` (required): Authentication token for the user
|
|
69
69
|
- `baseUrl` (optional): Base URL for the Lorikeet API (defaults to `https://chat.lorikeetcx.ai`)
|
|
70
|
-
- `customisations` (optional): Widget
|
|
70
|
+
- `customisations` (optional): Widget customisation options. Exported as
|
|
71
|
+
`Customisations` from this package, so there is nothing else to install
|
|
71
72
|
- `styles` (optional): Style overrides for the header text
|
|
72
|
-
- `
|
|
73
|
+
- `onEvent` (optional): What the page reported, as typed events. See [Events](#events)
|
|
74
|
+
- `onWebViewMessage` (optional): Handler for raw messages from the webview.
|
|
75
|
+
Deprecated in favour of `onEvent`, and still called
|
|
73
76
|
- `ticketId` (optional): Resume this conversation instead of starting a new one
|
|
74
77
|
- `session` (optional): The session token that authorises `ticketId`
|
|
75
78
|
- `metadata` (optional): Arbitrary context attached to the conversation, for
|
|
@@ -121,13 +124,102 @@ Pass both or neither. `session` authorises exactly the ticket it was issued
|
|
|
121
124
|
for, and a resume without it fails with `CUSTOMER_ID_MISSING`.
|
|
122
125
|
|
|
123
126
|
The SDK does not store these for you, and it does not clear them. On logout,
|
|
124
|
-
clear your own copy
|
|
125
|
-
|
|
127
|
+
clear your own copy and call the widget's `logout()`; see
|
|
128
|
+
[Logging out](#logging-out).
|
|
126
129
|
|
|
127
130
|
While `ticketId` is set, the header's new-chat icon reloads that conversation
|
|
128
131
|
rather than starting a new one. To start a new one, clear your stored
|
|
129
132
|
`ticketId` and `session` and let the next mount fall back to `/widget`.
|
|
130
133
|
|
|
134
|
+
## Events
|
|
135
|
+
|
|
136
|
+
`onEvent` reports what the page said, as a `LorikeetWidgetEvent`:
|
|
137
|
+
|
|
138
|
+
| Event | Means |
|
|
139
|
+
| --------------------------------- | --------------------------------------------------------------- |
|
|
140
|
+
| `ready` | The conversation is usable |
|
|
141
|
+
| `ticket_created` | A ticket this page load created. Once per ticket, never a resume |
|
|
142
|
+
| `customer_message` | The customer sent something |
|
|
143
|
+
| `agent_message` | The agent replied. `markUnread` is the page asking for an unread indicator |
|
|
144
|
+
| `close` | The page hid itself, with a `reason` of `ended_by_customer` or `minimised` |
|
|
145
|
+
| `conversation_ended` | It ended without the customer ending it |
|
|
146
|
+
| `new_chat` | The page is asking for a replacement conversation |
|
|
147
|
+
| `persist_ticket_id` | Store this, with the session, to resume later |
|
|
148
|
+
| `persist_session` | The other half of that pair |
|
|
149
|
+
| `logged_out` | `/logout` cleared this frame. See [Logging out](#logging-out) |
|
|
150
|
+
| `logout_failed` | `/logout` did not confirm. The widget stays unavailable |
|
|
151
|
+
| `error` | A page-level failure. `LORIKEET_ERROR_CODES` lists the codes |
|
|
152
|
+
|
|
153
|
+
Names match the web SDK's wherever it has one, so a host integrating both does
|
|
154
|
+
not learn two vocabularies.
|
|
155
|
+
|
|
156
|
+
`preload_complete` is in the union but cannot reach React Native: the preload
|
|
157
|
+
page posts it to a web parent only. Do not wait on it.
|
|
158
|
+
|
|
159
|
+
## Logging out
|
|
160
|
+
|
|
161
|
+
Clearing your own stored `ticketId` and `session` is not enough. The chat keeps
|
|
162
|
+
cookies and its own storage inside the WebView, which native code cannot reach,
|
|
163
|
+
so the next person on the device can reopen the previous customer's
|
|
164
|
+
conversation. Only the chat's `/logout` page can clear those, and only if the
|
|
165
|
+
WebView is navigated to it.
|
|
166
|
+
|
|
167
|
+
With the drop-in, call `logout()` on its ref:
|
|
168
|
+
|
|
169
|
+
```tsx
|
|
170
|
+
const widget = useRef<LorikeetWidgetHandle>(null)
|
|
171
|
+
|
|
172
|
+
return (
|
|
173
|
+
<>
|
|
174
|
+
<LorikeetWidgetView {...props} ref={widget} />
|
|
175
|
+
<Button
|
|
176
|
+
onPress={() => {
|
|
177
|
+
widget.current?.logout()
|
|
178
|
+
void clearResumeForCustomer(customerId)
|
|
179
|
+
}}
|
|
180
|
+
title="Sign out"
|
|
181
|
+
/>
|
|
182
|
+
</>
|
|
183
|
+
)
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
The widget stays on that page until the chat confirms, and nothing you pass it
|
|
187
|
+
in the meantime changes that: handing it the next customer's credentials while
|
|
188
|
+
the clear is still running would unmount the page mid-clear and leave the last
|
|
189
|
+
customer's cookies on the device. Pass them once `logged_out` has arrived and
|
|
190
|
+
the next chat starts normally.
|
|
191
|
+
|
|
192
|
+
A logout that does not confirm within ten seconds reports `logout_failed` and
|
|
193
|
+
leaves the widget unavailable rather than opening a chat on a device the
|
|
194
|
+
previous customer's credentials still unlock. Call `logout()` again to retry.
|
|
195
|
+
|
|
196
|
+
That obligation outlives the component. The SDK stores nothing, so a widget
|
|
197
|
+
unmounted before the clear confirmed, by a screen change or an app restart,
|
|
198
|
+
comes back with no memory of it and opens a chat normally, on a device whose
|
|
199
|
+
cookies were never cleared. Record the failure alongside the conversation you
|
|
200
|
+
already store, and call `logout()` again before mounting a chat for anyone
|
|
201
|
+
else. We would rather own this than ask you to, and
|
|
202
|
+
[ADP-3160](https://linear.app/lorikeet/issue/ADP-3160) is where that storage
|
|
203
|
+
layer belongs.
|
|
204
|
+
|
|
205
|
+
If you compose the parts yourself, build the URL and navigate to it:
|
|
206
|
+
|
|
207
|
+
```tsx
|
|
208
|
+
const client = new LorikeetClient({ public_key: publicKey, api_base: baseUrl })
|
|
209
|
+
|
|
210
|
+
setUri(client.getLogoutUrl())
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
Either way, wait for `logged_out` before treating the device as clean. The
|
|
214
|
+
WebView's load event does not prove anything: an error page fires it too.
|
|
215
|
+
|
|
216
|
+
The anonymous customer's long-lived token is deliberately not among these
|
|
217
|
+
events. It identifies the same anonymous customer for a year, this SDK offers
|
|
218
|
+
no way to hand one back, and the web SDK keeps the same message inside the
|
|
219
|
+
frame. A host that genuinely needs it can read the raw bridge, but storing it
|
|
220
|
+
is storing a credential, and [ADP-3160](https://linear.app/lorikeet/issue/ADP-3160)
|
|
221
|
+
is the work that should remove the need.
|
|
222
|
+
|
|
131
223
|
## Identity
|
|
132
224
|
|
|
133
225
|
The public key, base URL and auth token are one unit, and a conversation belongs
|
package/dist/index.cjs
CHANGED
|
@@ -144,6 +144,26 @@ var LorikeetClient = class {
|
|
|
144
144
|
if (this.metadata) url.searchParams.append("metadata", JSON.stringify(this.metadata));
|
|
145
145
|
return url.toString();
|
|
146
146
|
});
|
|
147
|
+
_defineProperty(
|
|
148
|
+
this,
|
|
149
|
+
/**
|
|
150
|
+
* The page that clears this key's credentials from the WebView: its cookies,
|
|
151
|
+
* server-side, and the storage the frame keeps. Navigating a WebView here is
|
|
152
|
+
* the only way to reach either, so a host that only drops its own copy of
|
|
153
|
+
* `ticketId` and `session` leaves the next person on the device able to
|
|
154
|
+
* reopen the conversation.
|
|
155
|
+
*
|
|
156
|
+
* The page confirms with a `loggedOut` message, which the SDK reports as
|
|
157
|
+
* `logged_out`. The load event does not: an error page fires that too.
|
|
158
|
+
*/
|
|
159
|
+
"getLogoutUrl",
|
|
160
|
+
() => {
|
|
161
|
+
const url = new URL(this.baseUrl);
|
|
162
|
+
url.pathname = "/logout";
|
|
163
|
+
url.searchParams.append("public_key", this.publicKey);
|
|
164
|
+
return url.toString();
|
|
165
|
+
}
|
|
166
|
+
);
|
|
147
167
|
if (api_base) this.baseUrl = api_base;
|
|
148
168
|
this.publicKey = public_key;
|
|
149
169
|
if (customisations) this.customisations = customisations;
|
|
@@ -210,7 +230,10 @@ const eventFromMessage = (message) => {
|
|
|
210
230
|
switch (record.type) {
|
|
211
231
|
case "ready": return { type: "ready" };
|
|
212
232
|
case "customerMessage": return { type: "customer_message" };
|
|
213
|
-
case "agentMessage": return
|
|
233
|
+
case "agentMessage": return typeof record.markUnread === "boolean" ? {
|
|
234
|
+
type: "agent_message",
|
|
235
|
+
markUnread: record.markUnread
|
|
236
|
+
} : { type: "agent_message" };
|
|
214
237
|
case "closeChat": {
|
|
215
238
|
const reason = asNonEmptyString(record.reason);
|
|
216
239
|
return reason === "ended_by_customer" || reason === "minimised" ? {
|
|
@@ -234,6 +257,7 @@ const eventFromMessage = (message) => {
|
|
|
234
257
|
session
|
|
235
258
|
};
|
|
236
259
|
}
|
|
260
|
+
case "loggedOut": return { type: "logged_out" };
|
|
237
261
|
case "error": {
|
|
238
262
|
const error = asNonEmptyString(record.error);
|
|
239
263
|
return error === null ? null : {
|
|
@@ -284,6 +308,13 @@ const resumedTicketIdFromUri = (uri) => {
|
|
|
284
308
|
*/
|
|
285
309
|
const BACKGROUND_RELOAD_THRESHOLD_MS = 18e4;
|
|
286
310
|
/**
|
|
311
|
+
* How long `/logout` gets to confirm it cleared the frame before the host is
|
|
312
|
+
* told it did not. Matches the web SDK's own budget, and like it, a logout that
|
|
313
|
+
* misses the deadline leaves the widget unavailable rather than letting the next
|
|
314
|
+
* customer start a chat on a device the previous one's credentials still open.
|
|
315
|
+
*/
|
|
316
|
+
const LOGOUT_CONFIRMATION_TIMEOUT_MS = 1e4;
|
|
317
|
+
/**
|
|
287
318
|
* Elapsed time is the only signal available: the bridge reports `ready`,
|
|
288
319
|
* `error` and the persistence messages, but never stream health, so the SDK
|
|
289
320
|
* cannot ask whether the connection actually survived.
|
|
@@ -410,6 +441,7 @@ const stylesheet = react_native.StyleSheet.create({
|
|
|
410
441
|
textAlign: "center",
|
|
411
442
|
fontSize: 16
|
|
412
443
|
},
|
|
444
|
+
closedControl: { padding: 16 },
|
|
413
445
|
webView: { flex: 1 },
|
|
414
446
|
closed: {
|
|
415
447
|
flex: 1,
|
|
@@ -488,8 +520,8 @@ const LorikeetWidgetHeader = ({ title, style, icon = /* @__PURE__ */ (0, react_j
|
|
|
488
520
|
]
|
|
489
521
|
});
|
|
490
522
|
};
|
|
491
|
-
function LorikeetWidgetView({ publicKey, baseUrl, authToken, customisations, styles, onEvent, onWebViewMessage, ticketId, session, metadata, webviewProps }) {
|
|
492
|
-
var _customisations$title;
|
|
523
|
+
const LorikeetWidgetView = (0, react.forwardRef)(function LorikeetWidgetView({ publicKey, baseUrl, authToken, customisations, styles, onEvent, onWebViewMessage, ticketId, session, metadata, webviewProps }, ref) {
|
|
524
|
+
var _customisations$hideH, _customisations$title;
|
|
493
525
|
const [lorikeetClient, setLorikeetClient] = (0, react.useState)(null);
|
|
494
526
|
const [loaded, setLoaded] = (0, react.useState)(null);
|
|
495
527
|
const [generation, setGeneration] = (0, react.useState)(0);
|
|
@@ -514,7 +546,12 @@ function LorikeetWidgetView({ publicKey, baseUrl, authToken, customisations, sty
|
|
|
514
546
|
});
|
|
515
547
|
const resumingTicketId = ticketId !== void 0 && ticketId !== refusedTicketId ? ticketId : void 0;
|
|
516
548
|
const [attemptedTicketId, setAttemptedTicketId] = (0, react.useState)(void 0);
|
|
517
|
-
const [closed, setClosed] = (0, react.useState)(
|
|
549
|
+
const [closed, setClosed] = (0, react.useState)(null);
|
|
550
|
+
const [clearing, setClearing] = (0, react.useState)(null);
|
|
551
|
+
const [loggedOutIdentity, setLoggedOutIdentity] = (0, react.useState)(null);
|
|
552
|
+
const onEventRef = (0, react.useRef)(onEvent);
|
|
553
|
+
onEventRef.current = onEvent;
|
|
554
|
+
const hideHeader = (_customisations$hideH = customisations === null || customisations === void 0 ? void 0 : customisations.hideHeader) !== null && _customisations$hideH !== void 0 ? _customisations$hideH : true;
|
|
518
555
|
const load = (0, react.useCallback)((client, forIdentity, intendedTicketId, resume, force = false) => {
|
|
519
556
|
const next = client.getWebviewUrl({
|
|
520
557
|
token: authToken,
|
|
@@ -522,7 +559,7 @@ function LorikeetWidgetView({ publicKey, baseUrl, authToken, customisations, sty
|
|
|
522
559
|
session: resume === null || resume === void 0 ? void 0 : resume.session
|
|
523
560
|
});
|
|
524
561
|
const unchanged = uriRef.current === next;
|
|
525
|
-
if (loadedForRef.current.identity !== forIdentity || loadedForRef.current.intendedTicketId !== intendedTicketId) setClosed(
|
|
562
|
+
if (loadedForRef.current.identity !== forIdentity || loadedForRef.current.intendedTicketId !== intendedTicketId) setClosed(null);
|
|
526
563
|
uriRef.current = next;
|
|
527
564
|
loadedForRef.current = {
|
|
528
565
|
identity: forIdentity,
|
|
@@ -551,10 +588,12 @@ function LorikeetWidgetView({ publicKey, baseUrl, authToken, customisations, sty
|
|
|
551
588
|
metadata,
|
|
552
589
|
customisations: {
|
|
553
590
|
...customisations,
|
|
554
|
-
hideHeader
|
|
591
|
+
hideHeader
|
|
555
592
|
}
|
|
556
593
|
});
|
|
557
594
|
setLorikeetClient(lorikeetClient);
|
|
595
|
+
if (clearing !== null || loggedOutIdentity === identity) return;
|
|
596
|
+
if (loggedOutIdentity !== null) setLoggedOutIdentity(null);
|
|
558
597
|
const resume = resumingTicketId !== void 0 ? {
|
|
559
598
|
session,
|
|
560
599
|
ticketId: resumingTicketId
|
|
@@ -564,13 +603,108 @@ function LorikeetWidgetView({ publicKey, baseUrl, authToken, customisations, sty
|
|
|
564
603
|
publicKey,
|
|
565
604
|
baseUrl,
|
|
566
605
|
authToken,
|
|
606
|
+
clearing,
|
|
567
607
|
customisations,
|
|
608
|
+
hideHeader,
|
|
609
|
+
loggedOutIdentity,
|
|
568
610
|
metadata,
|
|
569
611
|
session,
|
|
570
612
|
resumingTicketId,
|
|
571
613
|
identity,
|
|
572
614
|
load
|
|
573
615
|
]);
|
|
616
|
+
/**
|
|
617
|
+
* Clear this customer's chat from the device. Loads the page's own `/logout`,
|
|
618
|
+
* the only thing that can drop the chat's cookies and the storage the page
|
|
619
|
+
* keeps; a host clearing its stored `ticketId` and `session` leaves both
|
|
620
|
+
* behind.
|
|
621
|
+
*
|
|
622
|
+
* Nothing else loads until the page confirms with `logged_out`, and nothing
|
|
623
|
+
* loads for these credentials after it, so pass the next customer's in to
|
|
624
|
+
* start their chat. Clear your own stored `ticketId` and `session` too.
|
|
625
|
+
*/
|
|
626
|
+
const logout = (0, react.useCallback)(() => {
|
|
627
|
+
observedRef.current = null;
|
|
628
|
+
setClosed(null);
|
|
629
|
+
setClearing((previous) => {
|
|
630
|
+
if (previous !== null) return {
|
|
631
|
+
...previous,
|
|
632
|
+
attempt: previous.attempt + 1
|
|
633
|
+
};
|
|
634
|
+
setLoggedOutIdentity(identity);
|
|
635
|
+
return {
|
|
636
|
+
attempt: 1,
|
|
637
|
+
baseUrl,
|
|
638
|
+
identity,
|
|
639
|
+
uri: new LorikeetClient({
|
|
640
|
+
api_base: baseUrl,
|
|
641
|
+
public_key: publicKey
|
|
642
|
+
}).getLogoutUrl(),
|
|
643
|
+
webviewProps: {
|
|
644
|
+
...webviewProps,
|
|
645
|
+
injectedJavaScript: void 0,
|
|
646
|
+
injectedJavaScriptBeforeContentLoaded: void 0,
|
|
647
|
+
onMessage: void 0,
|
|
648
|
+
onShouldStartLoadWithRequest: void 0
|
|
649
|
+
}
|
|
650
|
+
};
|
|
651
|
+
});
|
|
652
|
+
}, [
|
|
653
|
+
baseUrl,
|
|
654
|
+
identity,
|
|
655
|
+
publicKey,
|
|
656
|
+
webviewProps
|
|
657
|
+
]);
|
|
658
|
+
/**
|
|
659
|
+
* Show a minimised conversation again, exactly as the customer left it.
|
|
660
|
+
*
|
|
661
|
+
* A no-op unless something is minimised, so a host with its own launcher can
|
|
662
|
+
* call it without first asking.
|
|
663
|
+
*/
|
|
664
|
+
const reopen = (0, react.useCallback)(() => {
|
|
665
|
+
setClosed((previous) => previous === "minimised" ? null : previous);
|
|
666
|
+
}, []);
|
|
667
|
+
/**
|
|
668
|
+
* What the widget is actually on, for a host that has to store it or draw its
|
|
669
|
+
* own launcher around it.
|
|
670
|
+
*/
|
|
671
|
+
const getConversation = (0, react.useCallback)(() => {
|
|
672
|
+
const resumable = resumableConversation(observedRef.current, identity, resumingTicketId);
|
|
673
|
+
if (resumable === null) return null;
|
|
674
|
+
return {
|
|
675
|
+
minimised: closed === "minimised",
|
|
676
|
+
session: resumable.session,
|
|
677
|
+
ticketId: resumable.ticketId
|
|
678
|
+
};
|
|
679
|
+
}, [
|
|
680
|
+
closed,
|
|
681
|
+
identity,
|
|
682
|
+
resumingTicketId
|
|
683
|
+
]);
|
|
684
|
+
(0, react.useImperativeHandle)(ref, () => ({
|
|
685
|
+
getConversation,
|
|
686
|
+
logout,
|
|
687
|
+
reopen
|
|
688
|
+
}), [
|
|
689
|
+
getConversation,
|
|
690
|
+
logout,
|
|
691
|
+
reopen
|
|
692
|
+
]);
|
|
693
|
+
const clearingAttempt = clearing === null || clearing === void 0 ? void 0 : clearing.attempt;
|
|
694
|
+
(0, react.useEffect)(() => {
|
|
695
|
+
if (clearingAttempt === void 0) return;
|
|
696
|
+
const timer = setTimeout(() => {
|
|
697
|
+
var _onEventRef$current;
|
|
698
|
+
(_onEventRef$current = onEventRef.current) === null || _onEventRef$current === void 0 || _onEventRef$current.call(onEventRef, { type: "logout_failed" });
|
|
699
|
+
}, LOGOUT_CONFIRMATION_TIMEOUT_MS);
|
|
700
|
+
return () => {
|
|
701
|
+
clearTimeout(timer);
|
|
702
|
+
};
|
|
703
|
+
}, [clearingAttempt]);
|
|
704
|
+
const handleClearingEvent = (0, react.useCallback)((event) => {
|
|
705
|
+
if (event.type === "logged_out") setClearing((previous) => (previous === null || previous === void 0 ? void 0 : previous.attempt) === clearingAttempt ? null : previous);
|
|
706
|
+
onEvent === null || onEvent === void 0 || onEvent(event);
|
|
707
|
+
}, [clearingAttempt, onEvent]);
|
|
574
708
|
const reload = (0, react.useCallback)(() => {
|
|
575
709
|
const resume = resumableConversation(observedRef.current, identity, resumingTicketId);
|
|
576
710
|
if (lorikeetClient !== null && resume !== null) {
|
|
@@ -602,7 +736,7 @@ function LorikeetWidgetView({ publicKey, baseUrl, authToken, customisations, sty
|
|
|
602
736
|
};
|
|
603
737
|
}, [reload]);
|
|
604
738
|
const startNewChat = (0, react.useCallback)(() => {
|
|
605
|
-
setClosed(
|
|
739
|
+
setClosed(null);
|
|
606
740
|
if (lorikeetClient !== null && resumingTicketId === void 0) {
|
|
607
741
|
observedRef.current = null;
|
|
608
742
|
load(lorikeetClient, identity, void 0, null, true);
|
|
@@ -628,7 +762,7 @@ function LorikeetWidgetView({ publicKey, baseUrl, authToken, customisations, sty
|
|
|
628
762
|
intendedTicketId: resumingTicketId
|
|
629
763
|
};
|
|
630
764
|
}
|
|
631
|
-
if (event.type === "close") setClosed(
|
|
765
|
+
if (event.type === "close") setClosed(event.reason === "minimised" ? "minimised" : "ended");
|
|
632
766
|
if (event.type === "new_chat") startNewChat();
|
|
633
767
|
if (event.type === "error" && attemptedTicketId !== void 0 && isUnusableConversationCode(event.error)) {
|
|
634
768
|
observedRef.current = null;
|
|
@@ -652,7 +786,31 @@ function LorikeetWidgetView({ publicKey, baseUrl, authToken, customisations, sty
|
|
|
652
786
|
onWebViewMessage === null || onWebViewMessage === void 0 || onWebViewMessage(event);
|
|
653
787
|
webviewProps === null || webviewProps === void 0 || (_webviewProps$onMessa2 = webviewProps.onMessage) === null || _webviewProps$onMessa2 === void 0 || _webviewProps$onMessa2.call(webviewProps, event);
|
|
654
788
|
}, [onWebViewMessage, webviewProps]);
|
|
655
|
-
if (
|
|
789
|
+
if (clearing !== null) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native_safe_area_context.SafeAreaView, {
|
|
790
|
+
edges: [
|
|
791
|
+
"top",
|
|
792
|
+
"left",
|
|
793
|
+
"right"
|
|
794
|
+
],
|
|
795
|
+
style: stylesheet.root,
|
|
796
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
|
|
797
|
+
accessibilityElementsHidden: true,
|
|
798
|
+
importantForAccessibility: "no-hide-descendants",
|
|
799
|
+
pointerEvents: "none",
|
|
800
|
+
style: stylesheet.closed,
|
|
801
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LorikeetWidgetWebView, {
|
|
802
|
+
baseUrl: clearing.baseUrl,
|
|
803
|
+
onEvent: handleClearingEvent,
|
|
804
|
+
uri: clearing.uri,
|
|
805
|
+
webviewProps: {
|
|
806
|
+
...clearing.webviewProps,
|
|
807
|
+
style: stylesheet.webView
|
|
808
|
+
}
|
|
809
|
+
}, `logout|${clearing.attempt}`)
|
|
810
|
+
})
|
|
811
|
+
});
|
|
812
|
+
if (lorikeetClient === null || loaded === null || loaded.identity !== identity || loaded.intendedTicketId !== resumingTicketId || loggedOutIdentity === identity) return null;
|
|
813
|
+
const isClosed = closed !== null;
|
|
656
814
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native_safe_area_context.SafeAreaView, {
|
|
657
815
|
edges: [
|
|
658
816
|
"top",
|
|
@@ -662,44 +820,64 @@ function LorikeetWidgetView({ publicKey, baseUrl, authToken, customisations, sty
|
|
|
662
820
|
style: stylesheet.root,
|
|
663
821
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native.View, {
|
|
664
822
|
style: stylesheet.container,
|
|
665
|
-
children: [
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
823
|
+
children: [
|
|
824
|
+
hideHeader && closed !== "minimised" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LorikeetWidgetHeader, {
|
|
825
|
+
onIconPress: startNewChat,
|
|
826
|
+
style: styles === null || styles === void 0 ? void 0 : styles.header,
|
|
827
|
+
title: (_customisations$title = customisations === null || customisations === void 0 ? void 0 : customisations.title) !== null && _customisations$title !== void 0 ? _customisations$title : "Lorikeet AI Agent"
|
|
828
|
+
}) : null,
|
|
829
|
+
closed === "minimised" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.TouchableOpacity, {
|
|
830
|
+
onPress: reopen,
|
|
831
|
+
style: stylesheet.closedControl,
|
|
832
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
|
|
833
|
+
style: stylesheet.headerText,
|
|
834
|
+
children: "Reopen chat"
|
|
835
|
+
})
|
|
836
|
+
}) : null,
|
|
837
|
+
!hideHeader && closed === "ended" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.TouchableOpacity, {
|
|
838
|
+
onPress: startNewChat,
|
|
839
|
+
style: stylesheet.closedControl,
|
|
840
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
|
|
841
|
+
style: stylesheet.headerText,
|
|
842
|
+
children: "Start new chat"
|
|
843
|
+
})
|
|
844
|
+
}) : null,
|
|
845
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
|
|
846
|
+
accessibilityElementsHidden: isClosed,
|
|
847
|
+
importantForAccessibility: isClosed ? "no-hide-descendants" : "auto",
|
|
848
|
+
pointerEvents: isClosed ? "none" : "auto",
|
|
849
|
+
style: isClosed ? stylesheet.closed : stylesheet.webView,
|
|
850
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LorikeetWidgetWebView, {
|
|
851
|
+
baseUrl: lorikeetClient.baseUrl,
|
|
852
|
+
onEvent: handleEvent,
|
|
853
|
+
ref: webViewRef,
|
|
854
|
+
uri: loaded.uri,
|
|
855
|
+
webviewProps: {
|
|
856
|
+
allowsInlineMediaPlayback: true,
|
|
857
|
+
mediaPlaybackRequiresUserAction: false,
|
|
858
|
+
scalesPageToFit: true,
|
|
859
|
+
startInLoadingState: true,
|
|
860
|
+
style: stylesheet.webView,
|
|
861
|
+
...webviewProps,
|
|
862
|
+
onMessage: handleMessage,
|
|
863
|
+
onRenderProcessGone: (event) => {
|
|
864
|
+
var _webviewProps$onRende;
|
|
865
|
+
if (generation === generationRef.current) reload();
|
|
866
|
+
webviewProps === null || webviewProps === void 0 || (_webviewProps$onRende = webviewProps.onRenderProcessGone) === null || _webviewProps$onRende === void 0 || _webviewProps$onRende.call(webviewProps, event);
|
|
867
|
+
},
|
|
868
|
+
onContentProcessDidTerminate: (event) => {
|
|
869
|
+
var _webviewProps$onConte;
|
|
870
|
+
if (generation === generationRef.current) reload();
|
|
871
|
+
webviewProps === null || webviewProps === void 0 || (_webviewProps$onConte = webviewProps.onContentProcessDidTerminate) === null || _webviewProps$onConte === void 0 || _webviewProps$onConte.call(webviewProps, event);
|
|
872
|
+
}
|
|
696
873
|
}
|
|
697
|
-
}
|
|
698
|
-
}
|
|
699
|
-
|
|
874
|
+
}, `${identity}|${resumingTicketId !== null && resumingTicketId !== void 0 ? resumingTicketId : ""}|${generation}`)
|
|
875
|
+
})
|
|
876
|
+
]
|
|
700
877
|
})
|
|
701
878
|
});
|
|
702
|
-
}
|
|
879
|
+
});
|
|
880
|
+
LorikeetWidgetView.displayName = "LorikeetWidgetView";
|
|
703
881
|
|
|
704
882
|
//#endregion
|
|
705
883
|
exports.LORIKEET_ERROR_CODES = LORIKEET_ERROR_CODES;
|