@repzo/widget-react-native 1.1.0 → 1.2.1
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/CHANGELOG.md +64 -0
- package/README.md +92 -3
- package/lib/commonjs/api/client.js +35 -0
- package/lib/commonjs/api/client.js.map +1 -1
- package/lib/commonjs/i18n.js +14 -0
- package/lib/commonjs/i18n.js.map +1 -1
- package/lib/commonjs/index.js +2 -1
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/locales.js +13 -0
- package/lib/commonjs/locales.js.map +1 -1
- package/lib/commonjs/push/push-notifications.js +65 -8
- package/lib/commonjs/push/push-notifications.js.map +1 -1
- package/lib/commonjs/state/widget-store.js +451 -7
- package/lib/commonjs/state/widget-store.js.map +1 -1
- package/lib/commonjs/types.js +15 -0
- package/lib/commonjs/types.js.map +1 -1
- package/lib/commonjs/ui/WidgetProvider.js +64 -2
- package/lib/commonjs/ui/WidgetProvider.js.map +1 -1
- package/lib/commonjs/ui/components/Post.js +1241 -0
- package/lib/commonjs/ui/components/Post.js.map +1 -0
- package/lib/commonjs/ui/utils/html.js +1 -0
- package/lib/commonjs/ui/utils/html.js.map +1 -1
- package/lib/commonjs/ui/utils/post-html.js +276 -0
- package/lib/commonjs/ui/utils/post-html.js.map +1 -0
- package/lib/commonjs/ui/utils/safe-url.js +16 -0
- package/lib/commonjs/ui/utils/safe-url.js.map +1 -1
- package/lib/module/api/client.js +35 -0
- package/lib/module/api/client.js.map +1 -1
- package/lib/module/i18n.js +14 -0
- package/lib/module/i18n.js.map +1 -1
- package/lib/module/index.js +2 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/locales.js +13 -0
- package/lib/module/locales.js.map +1 -1
- package/lib/module/push/push-notifications.js +65 -8
- package/lib/module/push/push-notifications.js.map +1 -1
- package/lib/module/state/widget-store.js +450 -6
- package/lib/module/state/widget-store.js.map +1 -1
- package/lib/module/types.js +15 -0
- package/lib/module/types.js.map +1 -1
- package/lib/module/ui/WidgetProvider.js +65 -3
- package/lib/module/ui/WidgetProvider.js.map +1 -1
- package/lib/module/ui/components/Post.js +1236 -0
- package/lib/module/ui/components/Post.js.map +1 -0
- package/lib/module/ui/utils/html.js +1 -1
- package/lib/module/ui/utils/html.js.map +1 -1
- package/lib/module/ui/utils/post-html.js +271 -0
- package/lib/module/ui/utils/post-html.js.map +1 -0
- package/lib/module/ui/utils/safe-url.js +15 -0
- package/lib/module/ui/utils/safe-url.js.map +1 -1
- package/lib/typescript/commonjs/api/client.d.ts +21 -1
- package/lib/typescript/commonjs/api/client.d.ts.map +1 -1
- package/lib/typescript/commonjs/i18n.d.ts +13 -0
- package/lib/typescript/commonjs/i18n.d.ts.map +1 -1
- package/lib/typescript/commonjs/index.d.ts +14 -1
- package/lib/typescript/commonjs/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/locales.d.ts.map +1 -1
- package/lib/typescript/commonjs/push/push-notifications.d.ts +26 -2
- package/lib/typescript/commonjs/push/push-notifications.d.ts.map +1 -1
- package/lib/typescript/commonjs/state/widget-store.d.ts +84 -1
- package/lib/typescript/commonjs/state/widget-store.d.ts.map +1 -1
- package/lib/typescript/commonjs/types.d.ts +77 -0
- package/lib/typescript/commonjs/types.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/WidgetProvider.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/Post.d.ts +69 -0
- package/lib/typescript/commonjs/ui/components/Post.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/utils/html.d.ts +1 -0
- package/lib/typescript/commonjs/ui/utils/html.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/utils/post-html.d.ts +54 -0
- package/lib/typescript/commonjs/ui/utils/post-html.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/utils/safe-url.d.ts +6 -0
- package/lib/typescript/commonjs/ui/utils/safe-url.d.ts.map +1 -1
- package/lib/typescript/module/api/client.d.ts +21 -1
- package/lib/typescript/module/api/client.d.ts.map +1 -1
- package/lib/typescript/module/i18n.d.ts +13 -0
- package/lib/typescript/module/i18n.d.ts.map +1 -1
- package/lib/typescript/module/index.d.ts +14 -1
- package/lib/typescript/module/index.d.ts.map +1 -1
- package/lib/typescript/module/locales.d.ts.map +1 -1
- package/lib/typescript/module/push/push-notifications.d.ts +26 -2
- package/lib/typescript/module/push/push-notifications.d.ts.map +1 -1
- package/lib/typescript/module/state/widget-store.d.ts +84 -1
- package/lib/typescript/module/state/widget-store.d.ts.map +1 -1
- package/lib/typescript/module/types.d.ts +77 -0
- package/lib/typescript/module/types.d.ts.map +1 -1
- package/lib/typescript/module/ui/WidgetProvider.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/Post.d.ts +69 -0
- package/lib/typescript/module/ui/components/Post.d.ts.map +1 -0
- package/lib/typescript/module/ui/utils/html.d.ts +1 -0
- package/lib/typescript/module/ui/utils/html.d.ts.map +1 -1
- package/lib/typescript/module/ui/utils/post-html.d.ts +54 -0
- package/lib/typescript/module/ui/utils/post-html.d.ts.map +1 -0
- package/lib/typescript/module/ui/utils/safe-url.d.ts +6 -0
- package/lib/typescript/module/ui/utils/safe-url.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/api/client.ts +32 -0
- package/src/i18n.ts +14 -0
- package/src/index.tsx +17 -0
- package/src/locales.ts +13 -0
- package/src/push/push-notifications.ts +74 -8
- package/src/state/widget-store.ts +429 -6
- package/src/types.ts +77 -0
- package/src/ui/WidgetProvider.tsx +78 -2
- package/src/ui/components/Post.tsx +943 -0
- package/src/ui/utils/html.ts +1 -1
- package/src/ui/utils/post-html.ts +256 -0
- package/src/ui/utils/safe-url.ts +15 -0
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* the modal (or never mounting it) never drops a conversation.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import { useCallback, useMemo } from 'react';
|
|
9
|
+
import { useCallback, useEffect, useMemo, useState } from 'react';
|
|
10
10
|
import {
|
|
11
11
|
ActivityIndicator,
|
|
12
12
|
Modal,
|
|
@@ -29,10 +29,11 @@ import {
|
|
|
29
29
|
import { controller } from '../controller';
|
|
30
30
|
import { buildLabels, createTranslator, formatLabel, localizeWelcomeText } from '../i18n';
|
|
31
31
|
import { useWidgetState } from '../state/use-widget-state';
|
|
32
|
-
import type { AgentUiAction, OutgoingAttachment, WidgetSpaceType } from '../types';
|
|
32
|
+
import type { AgentUiAction, OutgoingAttachment, PostInteractionKind, WidgetSpaceType } from '../types';
|
|
33
33
|
import { WidgetErrorBoundary } from './components/ErrorBoundary';
|
|
34
34
|
import { AlertIcon } from './components/icons';
|
|
35
35
|
import { InAppNotification } from './components/InAppNotification';
|
|
36
|
+
import { PostOverlay } from './components/Post';
|
|
36
37
|
import { OutboundMessageCard } from './components/OutboundMessageCard';
|
|
37
38
|
import { WidgetPanel } from './components/WidgetPanel';
|
|
38
39
|
import { useKeyboardOverlap } from './hooks/use-keyboard-overlap';
|
|
@@ -62,6 +63,9 @@ export interface RepzoWidgetProviderProps {
|
|
|
62
63
|
presentationStyle?: 'pageSheet' | 'fullScreen';
|
|
63
64
|
}
|
|
64
65
|
|
|
66
|
+
/** Longest the messenger's iOS slide-out is waited on when `onDismiss` doesn't arrive. */
|
|
67
|
+
const MESSENGER_DISMISS_FALLBACK_MS = 600;
|
|
68
|
+
|
|
65
69
|
export function RepzoWidgetProvider({
|
|
66
70
|
children,
|
|
67
71
|
presentationStyle = 'pageSheet',
|
|
@@ -235,6 +239,57 @@ export function RepzoWidgetProvider({
|
|
|
235
239
|
);
|
|
236
240
|
const handleDismissNotification = useCallback(() => store.dismissInAppNotification(), [store]);
|
|
237
241
|
|
|
242
|
+
// iOS can't present the post's modal while the messenger's is still sliding
|
|
243
|
+
// away (it would silently never show), so a post waits for that to finish.
|
|
244
|
+
// `onDismiss` is the signal; the timer covers React Native versions where it
|
|
245
|
+
// doesn't fire.
|
|
246
|
+
const [messengerOnScreen, setMessengerOnScreen] = useState(state.isOpen);
|
|
247
|
+
useEffect(() => {
|
|
248
|
+
if (state.isOpen || Platform.OS !== 'ios') {
|
|
249
|
+
setMessengerOnScreen(state.isOpen);
|
|
250
|
+
return undefined;
|
|
251
|
+
}
|
|
252
|
+
const timer = setTimeout(() => setMessengerOnScreen(false), MESSENGER_DISMISS_FALLBACK_MS);
|
|
253
|
+
return () => clearTimeout(timer);
|
|
254
|
+
}, [state.isOpen]);
|
|
255
|
+
const handleMessengerDismiss = useCallback(() => setMessengerOnScreen(false), []);
|
|
256
|
+
|
|
257
|
+
const handlePostShown = useCallback((campaignId: string) => store.postDidShow(campaignId), [store]);
|
|
258
|
+
const handlePostExpand = useCallback((campaignId: string) => store.expandPost(campaignId), [store]);
|
|
259
|
+
const handlePostMinimize = useCallback((campaignId: string) => store.minimizePost(campaignId), [store]);
|
|
260
|
+
const handlePostCollapse = useCallback((campaignId: string) => store.collapsePost(campaignId), [store]);
|
|
261
|
+
// The post steps aside first: iOS can't present the messenger while the post's modal is still up.
|
|
262
|
+
const handlePostOpenConversation = useCallback(
|
|
263
|
+
(campaignId: string, conversationId: string) => {
|
|
264
|
+
store.collapsePost(campaignId);
|
|
265
|
+
setTimeout(() => void store.openConversation(conversationId), Platform.OS === 'ios' ? 400 : 0);
|
|
266
|
+
},
|
|
267
|
+
[store]
|
|
268
|
+
);
|
|
269
|
+
const handlePostInteract = useCallback(
|
|
270
|
+
(campaignId: string, kind: Exclude<PostInteractionKind, 'view' | 'open' | 'minimize'>, value?: string) =>
|
|
271
|
+
store.recordPostInteraction(campaignId, kind, value),
|
|
272
|
+
[store]
|
|
273
|
+
);
|
|
274
|
+
const postLabels = useMemo(
|
|
275
|
+
() => ({
|
|
276
|
+
from: labels.postFrom,
|
|
277
|
+
newMessage: labels.postNewMessage,
|
|
278
|
+
openHint: labels.postOpenHint,
|
|
279
|
+
close: labels.postClose,
|
|
280
|
+
minimize: labels.postMinimize,
|
|
281
|
+
replyPlaceholder: labels.postReplyPlaceholder,
|
|
282
|
+
send: labels.postSend,
|
|
283
|
+
sent: labels.postSent,
|
|
284
|
+
replyFailed: labels.postReplyFailed,
|
|
285
|
+
reactions: labels.postReactions,
|
|
286
|
+
thanks: labels.postThanks,
|
|
287
|
+
conversation: labels.postConversation,
|
|
288
|
+
continueChat: labels.postContinueChat,
|
|
289
|
+
}),
|
|
290
|
+
[labels]
|
|
291
|
+
);
|
|
292
|
+
|
|
238
293
|
const handleTabChange = useCallback((tab: WidgetSpaceType) => store.setActiveTab(tab), [store]);
|
|
239
294
|
|
|
240
295
|
// Rejections reach ChatView, which keeps unsent attachments for a retry.
|
|
@@ -463,6 +518,26 @@ export function RepzoWidgetProvider({
|
|
|
463
518
|
return (
|
|
464
519
|
<>
|
|
465
520
|
{children}
|
|
521
|
+
{/* A post steps aside while the messenger is open, and its card while a reply card shows. */}
|
|
522
|
+
{state.post && !state.isOpen && !messengerOnScreen && (state.postExpanded || !state.inAppNotification) ? (
|
|
523
|
+
<WidgetErrorBoundary resetKey={state.post.id} fallback={() => null}>
|
|
524
|
+
<PostOverlay
|
|
525
|
+
// A new post remounts, so it reports its view.
|
|
526
|
+
key={state.post.id}
|
|
527
|
+
post={state.post}
|
|
528
|
+
expanded={state.postExpanded}
|
|
529
|
+
color={theme.primaryColor}
|
|
530
|
+
insets={insets}
|
|
531
|
+
labels={postLabels}
|
|
532
|
+
onShown={handlePostShown}
|
|
533
|
+
onExpand={handlePostExpand}
|
|
534
|
+
onMinimize={handlePostMinimize}
|
|
535
|
+
onCollapse={handlePostCollapse}
|
|
536
|
+
onOpenConversation={handlePostOpenConversation}
|
|
537
|
+
onInteract={handlePostInteract}
|
|
538
|
+
/>
|
|
539
|
+
</WidgetErrorBoundary>
|
|
540
|
+
) : null}
|
|
466
541
|
{state.inAppNotification ? (
|
|
467
542
|
<InAppNotification
|
|
468
543
|
// A new reply remounts the card, so it slides in fresh.
|
|
@@ -486,6 +561,7 @@ export function RepzoWidgetProvider({
|
|
|
486
561
|
animationType="slide"
|
|
487
562
|
presentationStyle={Platform.OS === 'ios' ? presentationStyle : undefined}
|
|
488
563
|
onRequestClose={handleClose}
|
|
564
|
+
onDismiss={handleMessengerDismiss}
|
|
489
565
|
// Edge to edge on every Android version, so the insets below are the
|
|
490
566
|
// only top spacing (a non-translucent modal used to add a second one).
|
|
491
567
|
statusBarTranslucent>
|