@lorikeetai/react-native-sdk 2.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +113 -15
- package/dist/index.cjs +88 -84
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +22 -18
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +22 -18
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +88 -83
- package/dist/index.js.map +1 -1
- package/package.json +7 -8
package/README.md
CHANGED
|
@@ -40,9 +40,6 @@ major. Widening them is a change that needs testing, not a version bump.
|
|
|
40
40
|
- **`webviewProps` now reach the WebView.** The drop-in previously discarded
|
|
41
41
|
them. If you were passing props that silently did nothing, they take effect
|
|
42
42
|
now.
|
|
43
|
-
- **Lazy ticket creation.** A ticket is no longer created when the widget opens,
|
|
44
|
-
which changes when conversations appear in your Lorikeet queue and in anything
|
|
45
|
-
counting them.
|
|
46
43
|
|
|
47
44
|
## Basic Usage
|
|
48
45
|
|
|
@@ -52,7 +49,7 @@ import { LorikeetWidgetView } from '@lorikeetai/react-native-sdk'
|
|
|
52
49
|
export default function Screen() {
|
|
53
50
|
return (
|
|
54
51
|
<LorikeetWidgetView
|
|
55
|
-
publicKey="
|
|
52
|
+
publicKey="your-public-key"
|
|
56
53
|
authToken="your-auth-token"
|
|
57
54
|
onWebViewMessage={(event) => console.log(event.nativeEvent.data)}
|
|
58
55
|
/>
|
|
@@ -62,7 +59,9 @@ export default function Screen() {
|
|
|
62
59
|
|
|
63
60
|
**Props:**
|
|
64
61
|
|
|
65
|
-
- `publicKey` (required): The public key for your Lorikeet account
|
|
62
|
+
- `publicKey` (required): The public key issued for your Lorikeet account. Use the value you were
|
|
63
|
+
given rather than matching a shape: the format has changed over time, and keys issued under
|
|
64
|
+
earlier ones keep working
|
|
66
65
|
- `authToken` (required): Authentication token for the user
|
|
67
66
|
- `baseUrl` (optional): Base URL for the Lorikeet API (defaults to `https://chat.lorikeetcx.ai`)
|
|
68
67
|
- `customisations` (optional): Widget customisation options. Exported as
|
|
@@ -79,6 +78,48 @@ export default function Screen() {
|
|
|
79
78
|
defaults for media playback, scaling and the loading state can all be
|
|
80
79
|
overridden; `onMessage` is additive, so the SDK reads the bridge first and
|
|
81
80
|
then calls yours
|
|
81
|
+
- `avoidKeyboard` (optional): Pads the widget clear of the keyboard. Defaults to
|
|
82
|
+
`true`. See [The keyboard](#the-keyboard)
|
|
83
|
+
|
|
84
|
+
## The keyboard
|
|
85
|
+
|
|
86
|
+
Android apps drawn edge to edge, the default for current Expo and React Native
|
|
87
|
+
apps, no longer resize their window for the keyboard. `adjustResize` in the
|
|
88
|
+
manifest does not change that. Nothing shrinks the WebView, so the keyboard
|
|
89
|
+
covers the composer and the page is never told the keyboard is there.
|
|
90
|
+
|
|
91
|
+
`LorikeetWidgetView` handles this itself: it wraps its content in a
|
|
92
|
+
`KeyboardAvoidingView` with `behavior="padding"` on both platforms, and measures
|
|
93
|
+
its own position so it works below a navigation header or tab bar. On iOS the
|
|
94
|
+
same padding keeps the page's header on screen. If your screen already makes
|
|
95
|
+
room for the keyboard, pass `avoidKeyboard={false}`, or the widget is padded
|
|
96
|
+
twice.
|
|
97
|
+
|
|
98
|
+
If you compose the parts yourself, the keyboard is yours. Wrap them in a
|
|
99
|
+
`KeyboardAvoidingView` with `behavior="padding"` on both platforms, and set
|
|
100
|
+
`keyboardVerticalOffset` to their distance from the top of the screen.
|
|
101
|
+
`apps/rn-widget-demo/src/components/WidgetPane.tsx` measures it with
|
|
102
|
+
`measureInWindow`. Check it on an Android device: an iOS simulator will not
|
|
103
|
+
show the problem.
|
|
104
|
+
|
|
105
|
+
## Which header you get
|
|
106
|
+
|
|
107
|
+
`hideHeader` decides whose header the customer sees, not whether there is one.
|
|
108
|
+
`LorikeetWidgetView` defaults it to `true`.
|
|
109
|
+
|
|
110
|
+
| Value | The chat page's header | The SDK's own header |
|
|
111
|
+
| ------------------------------ | ---------------------- | -------------------------------------------------- |
|
|
112
|
+
| `false` | Shown | Not rendered |
|
|
113
|
+
| `true` (the drop-in's default) | Hidden | Rendered, with a new-chat control and nothing else |
|
|
114
|
+
|
|
115
|
+
The page's header is the one carrying the controls for leaving a conversation.
|
|
116
|
+
The SDK's carries a new-chat control and nothing else, so under the drop-in's
|
|
117
|
+
default a host that neither sets `hideHeader: false` nor builds its own header
|
|
118
|
+
leaves the customer no way out of the chat.
|
|
119
|
+
|
|
120
|
+
Which controls the page's header offers, and what they are called, depends on
|
|
121
|
+
the account. Build against "the page's own controls" rather than a fixed set,
|
|
122
|
+
and ask us what your account serves before reproducing them.
|
|
82
123
|
|
|
83
124
|
## Resuming a conversation
|
|
84
125
|
|
|
@@ -101,7 +142,7 @@ useEffect(() => {
|
|
|
101
142
|
|
|
102
143
|
return (
|
|
103
144
|
<LorikeetWidgetView
|
|
104
|
-
publicKey="
|
|
145
|
+
publicKey="your-public-key"
|
|
105
146
|
authToken={token}
|
|
106
147
|
ticketId={resume.ticketId}
|
|
107
148
|
session={resume.session}
|
|
@@ -154,6 +195,43 @@ not learn two vocabularies.
|
|
|
154
195
|
`preload_complete` is in the union but cannot reach React Native: the preload
|
|
155
196
|
page posts it to a web parent only. Do not wait on it.
|
|
156
197
|
|
|
198
|
+
## Minimise, end and new chat
|
|
199
|
+
|
|
200
|
+
`close` means the page hid itself. It may carry a `reason`: a minimise keeps the
|
|
201
|
+
conversation and offers a control that reopens it, an end offers one that starts a
|
|
202
|
+
replacement. Treat an absent reason as an end, because that is what the widget
|
|
203
|
+
does.
|
|
204
|
+
|
|
205
|
+
Do not unmount on `close`. The end and any CSAT rating are still in flight, and
|
|
206
|
+
tearing the page down cancels them. The widget hides the chat itself.
|
|
207
|
+
|
|
208
|
+
While `ticketId` is set, the new-chat control reloads that conversation rather
|
|
209
|
+
than replacing it. To start a new conversation, clear your stored `ticketId` and
|
|
210
|
+
`session` and stop passing them, so the next load falls back to `/widget`.
|
|
211
|
+
|
|
212
|
+
## The widget handle
|
|
213
|
+
|
|
214
|
+
Pass a `ref` to `LorikeetWidgetView` to reach these.
|
|
215
|
+
|
|
216
|
+
```tsx
|
|
217
|
+
const widget = useRef<LorikeetWidgetHandle>(null)
|
|
218
|
+
|
|
219
|
+
widget.current?.getConversation() // { minimised, ticketId?, session? } | null
|
|
220
|
+
widget.current?.logout()
|
|
221
|
+
widget.current?.reopen()
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
- `getConversation()` reports the conversation the widget is on, which is not
|
|
225
|
+
always the one the host passed in: a refused resume is replaced, and a new chat
|
|
226
|
+
replaces the conversation before it. It returns `null` until the page has
|
|
227
|
+
reported a ticket, and it can report a ticket with no session, so it supplements
|
|
228
|
+
the persistence events rather than replacing them.
|
|
229
|
+
- `logout()` clears this customer's chat from the device. See
|
|
230
|
+
[Logging out](#logging-out).
|
|
231
|
+
- `reopen()` shows a minimised conversation again, exactly as the customer left
|
|
232
|
+
it. Nothing reloads and nothing is reported. A no-op unless the widget is
|
|
233
|
+
minimised, so a host with its own launcher can call it unconditionally.
|
|
234
|
+
|
|
157
235
|
## Logging out
|
|
158
236
|
|
|
159
237
|
Clearing your own stored `ticketId` and `session` is not enough. The chat keeps
|
|
@@ -194,11 +272,26 @@ previous customer's credentials still unlock. Call `logout()` again to retry.
|
|
|
194
272
|
That obligation outlives the component. The SDK stores nothing, so a widget
|
|
195
273
|
unmounted before the clear confirmed, by a screen change or an app restart,
|
|
196
274
|
comes back with no memory of it and opens a chat normally, on a device whose
|
|
197
|
-
cookies were never cleared.
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
275
|
+
cookies were never cleared.
|
|
276
|
+
|
|
277
|
+
So persist the logout before you start it, rather than recording that it failed.
|
|
278
|
+
Write down the `baseUrl`, `publicKey` and cookie-store `webviewProps` you are
|
|
279
|
+
clearing, read it at launch, and delete it only once `logged_out` has arrived.
|
|
280
|
+
Waiting for `logout_failed` is not enough on its own: unmounting cancels its
|
|
281
|
+
timer, so an app that dies inside the ten seconds reports nothing at all.
|
|
282
|
+
|
|
283
|
+
Recovery then has to clear that recorded target rather than whatever the next
|
|
284
|
+
launch happens to configure. The page drops only that public key's entry, and
|
|
285
|
+
settings such as `sharedCookiesEnabled` decide which cookie store it reaches, so
|
|
286
|
+
clearing another account or another store reports `logged_out` just the same.
|
|
287
|
+
|
|
288
|
+
It does not need the customer who left, though. The page needs no `authToken`, so
|
|
289
|
+
a host that no longer holds the departed customer's, which after a restart is the
|
|
290
|
+
normal case, can still clear the device by navigating a WebView to
|
|
291
|
+
`getLogoutUrl()` and waiting for its confirmation, as below. Do not reach for the
|
|
292
|
+
drop-in's `logout()` here: it clears for whichever credentials are in props and
|
|
293
|
+
then will not open a chat for them until they change, so calling it with the next
|
|
294
|
+
customer's props locks that customer out instead of the last one.
|
|
202
295
|
|
|
203
296
|
If you compose the parts yourself, build the URL and navigate to it:
|
|
204
297
|
|
|
@@ -215,8 +308,7 @@ The anonymous customer's long-lived token is deliberately not among these
|
|
|
215
308
|
events. It identifies the same anonymous customer for a year, this SDK offers
|
|
216
309
|
no way to hand one back, and the web SDK keeps the same message inside the
|
|
217
310
|
frame. A host that genuinely needs it can read the raw bridge, but storing it
|
|
218
|
-
is storing a credential
|
|
219
|
-
is the work that should remove the need.
|
|
311
|
+
is storing a credential.
|
|
220
312
|
|
|
221
313
|
## Identity
|
|
222
314
|
|
|
@@ -307,8 +399,14 @@ WebView component that handles the widget content.
|
|
|
307
399
|
|
|
308
400
|
## Development
|
|
309
401
|
|
|
310
|
-
|
|
311
|
-
|
|
402
|
+
This package is outside the root pnpm workspace, on its own lockfile, so run these from `packages/react-native-widget` after `pnpm install` there.
|
|
403
|
+
|
|
404
|
+
- Build: `pnpm build`
|
|
405
|
+
- Test: `pnpm test`
|
|
406
|
+
- Typecheck: `pnpm typecheck`
|
|
407
|
+
- Lint: `pnpm lint`. It uses the root's oxlint and oxfmt, so run `pnpm install` at the repository root first.
|
|
408
|
+
|
|
409
|
+
To release, bump `version` in `package.json` and add its `CHANGELOG.md` section in the same pull request. See `docs/engineering/sdk-releases.md`.
|
|
312
410
|
|
|
313
411
|
## License
|
|
314
412
|
|
package/dist/index.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
-
|
|
2
|
+
// \0rolldown/runtime.js
|
|
3
3
|
var __create = Object.create;
|
|
4
4
|
var __defProp = Object.defineProperty;
|
|
5
5
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
@@ -25,7 +25,6 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
25
25
|
enumerable: true
|
|
26
26
|
}) : target, mod));
|
|
27
27
|
|
|
28
|
-
//#endregion
|
|
29
28
|
let react = require("react");
|
|
30
29
|
let react_native = require("react-native");
|
|
31
30
|
let react_native_safe_area_context = require("react-native-safe-area-context");
|
|
@@ -34,7 +33,7 @@ let react_native_svg = require("react-native-svg");
|
|
|
34
33
|
react_native_svg = __toESM(react_native_svg, 1);
|
|
35
34
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
36
35
|
|
|
37
|
-
|
|
36
|
+
// src/bridge.ts
|
|
38
37
|
/**
|
|
39
38
|
* The public key, base URL and token are one unit, and a conversation belongs to
|
|
40
39
|
* the credentials that created it. Stamping an observation with them is what
|
|
@@ -54,8 +53,7 @@ const resumableConversation = (observed, identity, intendedTicketId) => {
|
|
|
54
53
|
};
|
|
55
54
|
};
|
|
56
55
|
|
|
57
|
-
|
|
58
|
-
//#region src/encode.ts
|
|
56
|
+
// src/encode.ts
|
|
59
57
|
const BASE64_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
60
58
|
/**
|
|
61
59
|
* Base64 of a string's UTF-8 bytes.
|
|
@@ -82,8 +80,7 @@ function base64EncodeUtf8(value) {
|
|
|
82
80
|
return encoded;
|
|
83
81
|
}
|
|
84
82
|
|
|
85
|
-
|
|
86
|
-
//#region \0@oxc-project+runtime@0.147.0/helpers/esm/typeof.js
|
|
83
|
+
// \0@oxc-project+runtime@0.156.0/helpers/esm/typeof.js
|
|
87
84
|
function _typeof(o) {
|
|
88
85
|
"@babel/helpers - typeof";
|
|
89
86
|
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o) {
|
|
@@ -93,8 +90,7 @@ function _typeof(o) {
|
|
|
93
90
|
}, _typeof(o);
|
|
94
91
|
}
|
|
95
92
|
|
|
96
|
-
|
|
97
|
-
//#region \0@oxc-project+runtime@0.147.0/helpers/esm/toPrimitive.js
|
|
93
|
+
// \0@oxc-project+runtime@0.156.0/helpers/esm/toPrimitive.js
|
|
98
94
|
function toPrimitive(t, r) {
|
|
99
95
|
if ("object" != _typeof(t) || !t) return t;
|
|
100
96
|
var e = t[Symbol.toPrimitive];
|
|
@@ -106,15 +102,13 @@ function toPrimitive(t, r) {
|
|
|
106
102
|
return ("string" === r ? String : Number)(t);
|
|
107
103
|
}
|
|
108
104
|
|
|
109
|
-
|
|
110
|
-
//#region \0@oxc-project+runtime@0.147.0/helpers/esm/toPropertyKey.js
|
|
105
|
+
// \0@oxc-project+runtime@0.156.0/helpers/esm/toPropertyKey.js
|
|
111
106
|
function toPropertyKey(t) {
|
|
112
107
|
var i = toPrimitive(t, "string");
|
|
113
108
|
return "symbol" == _typeof(i) ? i : i + "";
|
|
114
109
|
}
|
|
115
110
|
|
|
116
|
-
|
|
117
|
-
//#region \0@oxc-project+runtime@0.147.0/helpers/esm/defineProperty.js
|
|
111
|
+
// \0@oxc-project+runtime@0.156.0/helpers/esm/defineProperty.js
|
|
118
112
|
function _defineProperty(e, r, t) {
|
|
119
113
|
return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
|
|
120
114
|
value: t,
|
|
@@ -124,8 +118,7 @@ function _defineProperty(e, r, t) {
|
|
|
124
118
|
}) : e[r] = t, e;
|
|
125
119
|
}
|
|
126
120
|
|
|
127
|
-
|
|
128
|
-
//#region src/client.ts
|
|
121
|
+
// src/client.ts
|
|
129
122
|
var LorikeetClient = class {
|
|
130
123
|
constructor({ customisations, api_base, metadata, public_key }) {
|
|
131
124
|
_defineProperty(this, "baseUrl", "https://chat.lorikeetcx.ai");
|
|
@@ -171,8 +164,7 @@ var LorikeetClient = class {
|
|
|
171
164
|
}
|
|
172
165
|
};
|
|
173
166
|
|
|
174
|
-
|
|
175
|
-
//#region src/errors.ts
|
|
167
|
+
// src/errors.ts
|
|
176
168
|
/**
|
|
177
169
|
* The chat page's error vocabulary, as it reaches a host in
|
|
178
170
|
* `{ type: 'error', error: CODE }`. Mirrored here because the page publishes it
|
|
@@ -219,8 +211,7 @@ function isUnusableConversation(message) {
|
|
|
219
211
|
return type === "error" && typeof error === "string" ? isUnusableConversationCode(error) : false;
|
|
220
212
|
}
|
|
221
213
|
|
|
222
|
-
|
|
223
|
-
//#region src/events.ts
|
|
214
|
+
// src/events.ts
|
|
224
215
|
const asRecord = (message) => typeof message === "object" && message !== null && !Array.isArray(message) ? message : null;
|
|
225
216
|
const asNonEmptyString = (value) => typeof value === "string" && value !== "" ? value : null;
|
|
226
217
|
/**
|
|
@@ -298,8 +289,7 @@ const resumedTicketIdFromUri = (uri) => {
|
|
|
298
289
|
return (_segments$ = segments[2]) !== null && _segments$ !== void 0 ? _segments$ : null;
|
|
299
290
|
};
|
|
300
291
|
|
|
301
|
-
|
|
302
|
-
//#region src/lifecycle.ts
|
|
292
|
+
// src/lifecycle.ts
|
|
303
293
|
/**
|
|
304
294
|
* The page gives its message stream ten attempts with exponential backoff
|
|
305
295
|
* capped at 30s (`message-stream-utils.tsx`), so the budget runs out roughly
|
|
@@ -336,8 +326,7 @@ const shouldReloadAfterBackground = (backgroundedAt, now, thresholdMs = BACKGROU
|
|
|
336
326
|
return elapsed >= thresholdMs;
|
|
337
327
|
};
|
|
338
328
|
|
|
339
|
-
|
|
340
|
-
//#region src/links.ts
|
|
329
|
+
// src/links.ts
|
|
341
330
|
/**
|
|
342
331
|
* Schemes the WebView resolves for itself. None of them is a page the customer
|
|
343
332
|
* asked to leave the app for, and the OS cannot open them anyway.
|
|
@@ -382,8 +371,7 @@ const isInternalNavigation = (url, baseUrl) => {
|
|
|
382
371
|
return target.origin === base.origin;
|
|
383
372
|
};
|
|
384
373
|
|
|
385
|
-
|
|
386
|
-
//#region src/message-circle-plus-icon.tsx
|
|
374
|
+
// src/message-circle-plus-icon.tsx
|
|
387
375
|
const MessageCirclePlusIcon = ({ size = 24, color = "currentColor", strokeWidth = 2 }) => {
|
|
388
376
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native_svg.default, {
|
|
389
377
|
fill: "none",
|
|
@@ -420,13 +408,13 @@ const MessageCirclePlusIcon = ({ size = 24, color = "currentColor", strokeWidth
|
|
|
420
408
|
});
|
|
421
409
|
};
|
|
422
410
|
|
|
423
|
-
|
|
424
|
-
//#region src/widget.tsx
|
|
411
|
+
// src/widget.tsx
|
|
425
412
|
const stylesheet = react_native.StyleSheet.create({
|
|
426
413
|
root: {
|
|
427
414
|
flex: 1,
|
|
428
415
|
backgroundColor: "#fff"
|
|
429
416
|
},
|
|
417
|
+
keyboardAvoiding: { flex: 1 },
|
|
430
418
|
container: {
|
|
431
419
|
flex: 1,
|
|
432
420
|
borderRadius: 8,
|
|
@@ -530,7 +518,7 @@ const LorikeetWidgetHeader = ({ title, style, icon = /* @__PURE__ */ (0, react_j
|
|
|
530
518
|
]
|
|
531
519
|
});
|
|
532
520
|
};
|
|
533
|
-
const LorikeetWidgetView = (0, react.forwardRef)(function LorikeetWidgetView({ publicKey, baseUrl, authToken, customisations, styles, onEvent, onWebViewMessage, ticketId, session, metadata, webviewProps }, ref) {
|
|
521
|
+
const LorikeetWidgetView = (0, react.forwardRef)(function LorikeetWidgetView({ publicKey, baseUrl, authToken, customisations, styles, onEvent, onWebViewMessage, ticketId, session, metadata, webviewProps, avoidKeyboard = true }, ref) {
|
|
534
522
|
var _customisations$hideH, _customisations$title;
|
|
535
523
|
const [lorikeetClient, setLorikeetClient] = (0, react.useState)(null);
|
|
536
524
|
const [loaded, setLoaded] = (0, react.useState)(null);
|
|
@@ -541,6 +529,15 @@ const LorikeetWidgetView = (0, react.forwardRef)(function LorikeetWidgetView({ p
|
|
|
541
529
|
setGeneration((previous) => previous + 1);
|
|
542
530
|
}, []);
|
|
543
531
|
const webViewRef = (0, react.useRef)(null);
|
|
532
|
+
const containerRef = (0, react.useRef)(null);
|
|
533
|
+
const [keyboardOffset, setKeyboardOffset] = (0, react.useState)(0);
|
|
534
|
+
const measureKeyboardOffset = (0, react.useCallback)((event) => {
|
|
535
|
+
var _containerRef$current;
|
|
536
|
+
const { y } = event.nativeEvent.layout;
|
|
537
|
+
(_containerRef$current = containerRef.current) === null || _containerRef$current === void 0 || _containerRef$current.measureInWindow((_x, windowY) => {
|
|
538
|
+
setKeyboardOffset(windowY - y);
|
|
539
|
+
});
|
|
540
|
+
}, []);
|
|
544
541
|
const [refusedTicketId, setRefusedTicketId] = (0, react.useState)(null);
|
|
545
542
|
const observedRef = (0, react.useRef)(null);
|
|
546
543
|
const backgroundedAtRef = (0, react.useRef)(null);
|
|
@@ -828,68 +825,75 @@ const LorikeetWidgetView = (0, react.forwardRef)(function LorikeetWidgetView({ p
|
|
|
828
825
|
"right"
|
|
829
826
|
],
|
|
830
827
|
style: stylesheet.root,
|
|
831
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
style:
|
|
844
|
-
|
|
845
|
-
})
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
})
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
828
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.KeyboardAvoidingView, {
|
|
829
|
+
behavior: "padding",
|
|
830
|
+
enabled: avoidKeyboard,
|
|
831
|
+
keyboardVerticalOffset: keyboardOffset,
|
|
832
|
+
onLayout: measureKeyboardOffset,
|
|
833
|
+
style: stylesheet.keyboardAvoiding,
|
|
834
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native.View, {
|
|
835
|
+
ref: containerRef,
|
|
836
|
+
style: stylesheet.container,
|
|
837
|
+
children: [
|
|
838
|
+
hideHeader && closed !== "minimised" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LorikeetWidgetHeader, {
|
|
839
|
+
onIconPress: startNewChat,
|
|
840
|
+
style: styles === null || styles === void 0 ? void 0 : styles.header,
|
|
841
|
+
title: (_customisations$title = customisations === null || customisations === void 0 ? void 0 : customisations.title) !== null && _customisations$title !== void 0 ? _customisations$title : "Lorikeet AI Agent"
|
|
842
|
+
}) : null,
|
|
843
|
+
closed === "minimised" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.TouchableOpacity, {
|
|
844
|
+
onPress: reopen,
|
|
845
|
+
style: stylesheet.closedControl,
|
|
846
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
|
|
847
|
+
style: stylesheet.headerText,
|
|
848
|
+
children: "Reopen chat"
|
|
849
|
+
})
|
|
850
|
+
}) : null,
|
|
851
|
+
!hideHeader && closed === "ended" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.TouchableOpacity, {
|
|
852
|
+
onPress: startNewChat,
|
|
853
|
+
style: stylesheet.closedControl,
|
|
854
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
|
|
855
|
+
style: stylesheet.headerText,
|
|
856
|
+
children: "Start new chat"
|
|
857
|
+
})
|
|
858
|
+
}) : null,
|
|
859
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
|
|
860
|
+
accessibilityElementsHidden: isClosed,
|
|
861
|
+
importantForAccessibility: isClosed ? "no-hide-descendants" : "auto",
|
|
862
|
+
pointerEvents: isClosed ? "none" : "auto",
|
|
863
|
+
style: isClosed ? stylesheet.closed : stylesheet.webView,
|
|
864
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LorikeetWidgetWebView, {
|
|
865
|
+
baseUrl: lorikeetClient.baseUrl,
|
|
866
|
+
onEvent: handleEvent,
|
|
867
|
+
ref: webViewRef,
|
|
868
|
+
uri: loaded.uri,
|
|
869
|
+
webviewProps: {
|
|
870
|
+
allowsInlineMediaPlayback: true,
|
|
871
|
+
mediaPlaybackRequiresUserAction: false,
|
|
872
|
+
scalesPageToFit: true,
|
|
873
|
+
startInLoadingState: true,
|
|
874
|
+
style: stylesheet.webView,
|
|
875
|
+
...webviewProps,
|
|
876
|
+
onMessage: handleMessage,
|
|
877
|
+
onRenderProcessGone: (event) => {
|
|
878
|
+
var _webviewProps$onRende;
|
|
879
|
+
if (generation === generationRef.current) reload();
|
|
880
|
+
webviewProps === null || webviewProps === void 0 || (_webviewProps$onRende = webviewProps.onRenderProcessGone) === null || _webviewProps$onRende === void 0 || _webviewProps$onRende.call(webviewProps, event);
|
|
881
|
+
},
|
|
882
|
+
onContentProcessDidTerminate: (event) => {
|
|
883
|
+
var _webviewProps$onConte;
|
|
884
|
+
if (generation === generationRef.current) reload();
|
|
885
|
+
webviewProps === null || webviewProps === void 0 || (_webviewProps$onConte = webviewProps.onContentProcessDidTerminate) === null || _webviewProps$onConte === void 0 || _webviewProps$onConte.call(webviewProps, event);
|
|
886
|
+
}
|
|
882
887
|
}
|
|
883
|
-
}
|
|
884
|
-
}
|
|
885
|
-
|
|
886
|
-
|
|
888
|
+
}, `${identity}|${resumingTicketId !== null && resumingTicketId !== void 0 ? resumingTicketId : ""}|${generation}`)
|
|
889
|
+
})
|
|
890
|
+
]
|
|
891
|
+
})
|
|
887
892
|
})
|
|
888
893
|
});
|
|
889
894
|
});
|
|
890
895
|
LorikeetWidgetView.displayName = "LorikeetWidgetView";
|
|
891
896
|
|
|
892
|
-
//#endregion
|
|
893
897
|
exports.LOGOUT_CONFIRMATION_TIMEOUT_MS = LOGOUT_CONFIRMATION_TIMEOUT_MS;
|
|
894
898
|
exports.LORIKEET_ERROR_CODES = LORIKEET_ERROR_CODES;
|
|
895
899
|
exports.LorikeetClient = LorikeetClient;
|