@worktual/react-native-ai-bot 1.0.0 → 1.0.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/dist/WorktualAIBot.d.ts +26 -0
- package/dist/WorktualAIBot.d.ts.map +1 -0
- package/dist/WorktualAIBot.js +223 -0
- package/dist/WorktualAIBot.js.map +1 -0
- package/{src/index.ts → dist/index.d.ts} +1 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/package.json +4 -4
- package/src/WorktualAIBot.tsx +0 -293
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
export interface WorktualAIBotProps {
|
|
3
|
+
/** Your unique webchat ID provided by Worktual */
|
|
4
|
+
webchatId: string;
|
|
5
|
+
/** Called when the bot sends a close/end event (navigate back, dismiss modal, etc.) */
|
|
6
|
+
onClose: () => void;
|
|
7
|
+
/** Optional: custom base URL (defaults to Worktual production) */
|
|
8
|
+
baseUrl?: string;
|
|
9
|
+
/** Optional: loading screen title (default: "AI Assistant") */
|
|
10
|
+
loadingTitle?: string;
|
|
11
|
+
/** Optional: loading screen subtitle (default: "Loading your chat...") */
|
|
12
|
+
loadingSubtitle?: string;
|
|
13
|
+
/** Optional: primary colour for progress bar & spinner (default: "#575CFF") */
|
|
14
|
+
primaryColor?: string;
|
|
15
|
+
/** Optional: loading screen background colour (default: "#f8f9fb") */
|
|
16
|
+
loadingBackground?: string;
|
|
17
|
+
/** Optional: maximum time (ms) to wait before force-hiding loader (default: 6000) */
|
|
18
|
+
maxLoadTime?: number;
|
|
19
|
+
/** Optional: called when bot content is fully loaded */
|
|
20
|
+
onReady?: () => void;
|
|
21
|
+
/** Optional: called on every postMessage from the WebView */
|
|
22
|
+
onMessage?: (data: Record<string, unknown>) => void;
|
|
23
|
+
}
|
|
24
|
+
declare const WorktualAIBot: React.FC<WorktualAIBotProps>;
|
|
25
|
+
export default WorktualAIBot;
|
|
26
|
+
//# sourceMappingURL=WorktualAIBot.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WorktualAIBot.d.ts","sourceRoot":"","sources":["../src/WorktualAIBot.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmD,MAAM,OAAO,CAAC;AAiBxE,MAAM,WAAW,kBAAkB;IACjC,kDAAkD;IAClD,SAAS,EAAE,MAAM,CAAC;IAElB,uFAAuF;IACvF,OAAO,EAAE,MAAM,IAAI,CAAC;IAEpB,kEAAkE;IAClE,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,+DAA+D;IAC/D,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,0EAA0E;IAC1E,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB,+EAA+E;IAC/E,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,sEAAsE;IACtE,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B,qFAAqF;IACrF,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,wDAAwD;IACxD,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IAErB,6DAA6D;IAC7D,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;CACrD;AA2CD,QAAA,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CA4J/C,CAAC;AA8CF,eAAe,aAAa,CAAC"}
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
const react_1 = __importStar(require("react"));
|
|
37
|
+
const react_native_1 = require("react-native");
|
|
38
|
+
const react_native_webview_1 = require("react-native-webview");
|
|
39
|
+
const react_native_safe_area_context_1 = require("react-native-safe-area-context");
|
|
40
|
+
/* ────────────────────────────────────────────────────────
|
|
41
|
+
* Constants
|
|
42
|
+
* ──────────────────────────────────────────────────────── */
|
|
43
|
+
const DEFAULT_BASE_URL = "https://ccaas-storage.worktual.co.uk/chat/ailivebot.html";
|
|
44
|
+
const buildUrl = (baseUrl, webchatId) => {
|
|
45
|
+
const sep = baseUrl.includes("?") ? "&" : "?";
|
|
46
|
+
return `${baseUrl}${sep}webchatid=${webchatId}&isHeader=1`;
|
|
47
|
+
};
|
|
48
|
+
/** Injected JS – polls for chat content then posts webchat_ready */
|
|
49
|
+
const buildInjectedJS = (maxMs) => `
|
|
50
|
+
(function() {
|
|
51
|
+
var t = setInterval(function() {
|
|
52
|
+
var m = document.querySelectorAll(
|
|
53
|
+
'.message, .chat-message, .msg-content, [class*="message"]'
|
|
54
|
+
);
|
|
55
|
+
var i = document.querySelector('input[placeholder], textarea[placeholder]');
|
|
56
|
+
if (m.length > 0 || i) {
|
|
57
|
+
clearInterval(t);
|
|
58
|
+
window.ReactNativeWebView.postMessage(
|
|
59
|
+
JSON.stringify({ type: "webchat_ready" })
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
}, 200);
|
|
63
|
+
setTimeout(function() {
|
|
64
|
+
clearInterval(t);
|
|
65
|
+
window.ReactNativeWebView.postMessage(
|
|
66
|
+
JSON.stringify({ type: "webchat_ready" })
|
|
67
|
+
);
|
|
68
|
+
}, ${maxMs});
|
|
69
|
+
})();
|
|
70
|
+
true;
|
|
71
|
+
`;
|
|
72
|
+
/* ────────────────────────────────────────────────────────
|
|
73
|
+
* Component
|
|
74
|
+
* ──────────────────────────────────────────────────────── */
|
|
75
|
+
const WorktualAIBot = ({ webchatId, onClose, baseUrl = DEFAULT_BASE_URL, loadingTitle = "AI Assistant", loadingSubtitle = "Loading your chat...", primaryColor = "#575CFF", loadingBackground = "#f8f9fb", maxLoadTime = 6000, onReady, onMessage: onMessageProp, }) => {
|
|
76
|
+
const insets = (0, react_native_safe_area_context_1.useSafeAreaInsets)();
|
|
77
|
+
const [showLoader, setShowLoader] = (0, react_1.useState)(true);
|
|
78
|
+
// Animations
|
|
79
|
+
const progressAnim = (0, react_1.useRef)(new react_native_1.Animated.Value(0)).current;
|
|
80
|
+
const fadeAnim = (0, react_1.useRef)(new react_native_1.Animated.Value(1)).current;
|
|
81
|
+
const dotAnim = (0, react_1.useRef)(new react_native_1.Animated.Value(0)).current;
|
|
82
|
+
const url = buildUrl(baseUrl, webchatId);
|
|
83
|
+
const injectedJS = buildInjectedJS(maxLoadTime);
|
|
84
|
+
/* ── Animations ── */
|
|
85
|
+
(0, react_1.useEffect)(() => {
|
|
86
|
+
// Progress bar: fast to 70%, then slow to 90%
|
|
87
|
+
react_native_1.Animated.sequence([
|
|
88
|
+
react_native_1.Animated.timing(progressAnim, {
|
|
89
|
+
toValue: 0.7,
|
|
90
|
+
duration: 800,
|
|
91
|
+
useNativeDriver: false,
|
|
92
|
+
}),
|
|
93
|
+
react_native_1.Animated.timing(progressAnim, {
|
|
94
|
+
toValue: 0.9,
|
|
95
|
+
duration: 2500,
|
|
96
|
+
useNativeDriver: false,
|
|
97
|
+
}),
|
|
98
|
+
]).start();
|
|
99
|
+
// Pulsing dots
|
|
100
|
+
react_native_1.Animated.loop(react_native_1.Animated.sequence([
|
|
101
|
+
react_native_1.Animated.timing(dotAnim, { toValue: 1, duration: 500, useNativeDriver: true }),
|
|
102
|
+
react_native_1.Animated.timing(dotAnim, { toValue: 0.3, duration: 500, useNativeDriver: true }),
|
|
103
|
+
])).start();
|
|
104
|
+
}, []);
|
|
105
|
+
/* ── Hide loader ── */
|
|
106
|
+
const hideLoader = (0, react_1.useCallback)(() => {
|
|
107
|
+
if (!showLoader)
|
|
108
|
+
return;
|
|
109
|
+
// Complete progress bar
|
|
110
|
+
react_native_1.Animated.timing(progressAnim, {
|
|
111
|
+
toValue: 1,
|
|
112
|
+
duration: 150,
|
|
113
|
+
useNativeDriver: false,
|
|
114
|
+
}).start();
|
|
115
|
+
// Fade out
|
|
116
|
+
setTimeout(() => {
|
|
117
|
+
react_native_1.Animated.timing(fadeAnim, {
|
|
118
|
+
toValue: 0,
|
|
119
|
+
duration: 200,
|
|
120
|
+
useNativeDriver: true,
|
|
121
|
+
}).start(() => setShowLoader(false));
|
|
122
|
+
}, 150);
|
|
123
|
+
}, [showLoader]);
|
|
124
|
+
/* ── WebView message handler ── */
|
|
125
|
+
const handleMessage = (0, react_1.useCallback)((event) => {
|
|
126
|
+
try {
|
|
127
|
+
const data = JSON.parse(event.nativeEvent.data);
|
|
128
|
+
// Forward to client's onMessage if provided
|
|
129
|
+
onMessageProp === null || onMessageProp === void 0 ? void 0 : onMessageProp(data);
|
|
130
|
+
if ((data === null || data === void 0 ? void 0 : data.type) === "webchat_ready") {
|
|
131
|
+
hideLoader();
|
|
132
|
+
onReady === null || onReady === void 0 ? void 0 : onReady();
|
|
133
|
+
}
|
|
134
|
+
if ((data === null || data === void 0 ? void 0 : data.type) === "webchat_end") {
|
|
135
|
+
onClose();
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
catch (_) {
|
|
139
|
+
// Ignore non-JSON messages
|
|
140
|
+
}
|
|
141
|
+
}, [hideLoader, onClose, onReady, onMessageProp]);
|
|
142
|
+
/* ── Render ── */
|
|
143
|
+
const progressWidth = progressAnim.interpolate({
|
|
144
|
+
inputRange: [0, 1],
|
|
145
|
+
outputRange: ["0%", "100%"],
|
|
146
|
+
});
|
|
147
|
+
return (<react_native_1.View style={[styles.container, { paddingTop: insets.top }]}>
|
|
148
|
+
<react_native_1.StatusBar barStyle="dark-content" backgroundColor="#fff"/>
|
|
149
|
+
|
|
150
|
+
{/* WebView loads immediately behind the loader */}
|
|
151
|
+
<react_native_webview_1.WebView source={{ uri: url }} style={styles.webview} javaScriptEnabled domStorageEnabled allowsInlineMediaPlayback mediaPlaybackRequiresUserAction={false} onMessage={handleMessage} injectedJavaScript={injectedJS}
|
|
152
|
+
// Prevent white flash on Android
|
|
153
|
+
{...(react_native_1.Platform.OS === "android" && {
|
|
154
|
+
overScrollMode: "never",
|
|
155
|
+
setBuiltInZoomControls: false,
|
|
156
|
+
})}/>
|
|
157
|
+
|
|
158
|
+
{/* Loading overlay */}
|
|
159
|
+
{showLoader && (<react_native_1.Animated.View style={[
|
|
160
|
+
styles.loaderOverlay,
|
|
161
|
+
{ opacity: fadeAnim, backgroundColor: loadingBackground },
|
|
162
|
+
]}>
|
|
163
|
+
{/* Spinner */}
|
|
164
|
+
<react_native_1.ActivityIndicator size="large" color={primaryColor} style={styles.spinner}/>
|
|
165
|
+
|
|
166
|
+
{/* Title */}
|
|
167
|
+
<react_native_1.Text style={styles.loaderTitle}>{loadingTitle}</react_native_1.Text>
|
|
168
|
+
|
|
169
|
+
{/* Subtitle with pulsing opacity */}
|
|
170
|
+
<react_native_1.Animated.Text style={[styles.loaderSubtitle, { opacity: dotAnim }]}>
|
|
171
|
+
{loadingSubtitle}
|
|
172
|
+
</react_native_1.Animated.Text>
|
|
173
|
+
|
|
174
|
+
{/* Progress bar */}
|
|
175
|
+
<react_native_1.View style={styles.progressTrack}>
|
|
176
|
+
<react_native_1.Animated.View style={[
|
|
177
|
+
styles.progressBar,
|
|
178
|
+
{ width: progressWidth, backgroundColor: primaryColor },
|
|
179
|
+
]}/>
|
|
180
|
+
</react_native_1.View>
|
|
181
|
+
</react_native_1.Animated.View>)}
|
|
182
|
+
</react_native_1.View>);
|
|
183
|
+
};
|
|
184
|
+
/* ────────────────────────────────────────────────────────
|
|
185
|
+
* Styles
|
|
186
|
+
* ──────────────────────────────────────────────────────── */
|
|
187
|
+
const styles = react_native_1.StyleSheet.create({
|
|
188
|
+
container: {
|
|
189
|
+
flex: 1,
|
|
190
|
+
backgroundColor: "#fff",
|
|
191
|
+
},
|
|
192
|
+
webview: {
|
|
193
|
+
flex: 1,
|
|
194
|
+
},
|
|
195
|
+
loaderOverlay: Object.assign(Object.assign({}, react_native_1.StyleSheet.absoluteFillObject), { justifyContent: "center", alignItems: "center" }),
|
|
196
|
+
spinner: {
|
|
197
|
+
marginBottom: 20,
|
|
198
|
+
},
|
|
199
|
+
loaderTitle: {
|
|
200
|
+
fontSize: 18,
|
|
201
|
+
fontWeight: "600",
|
|
202
|
+
color: "#1a1a2e",
|
|
203
|
+
marginBottom: 6,
|
|
204
|
+
},
|
|
205
|
+
loaderSubtitle: {
|
|
206
|
+
fontSize: 14,
|
|
207
|
+
color: "#8e8ea0",
|
|
208
|
+
marginBottom: 28,
|
|
209
|
+
},
|
|
210
|
+
progressTrack: {
|
|
211
|
+
width: 200,
|
|
212
|
+
height: 4,
|
|
213
|
+
backgroundColor: "#e4e4e7",
|
|
214
|
+
borderRadius: 2,
|
|
215
|
+
overflow: "hidden",
|
|
216
|
+
},
|
|
217
|
+
progressBar: {
|
|
218
|
+
height: "100%",
|
|
219
|
+
borderRadius: 2,
|
|
220
|
+
},
|
|
221
|
+
});
|
|
222
|
+
exports.default = WorktualAIBot;
|
|
223
|
+
//# sourceMappingURL=WorktualAIBot.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WorktualAIBot.js","sourceRoot":"","sources":["../src/WorktualAIBot.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAC3D,YAAY,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.WorktualAIBot = void 0;
|
|
7
|
+
var WorktualAIBot_1 = require("./WorktualAIBot");
|
|
8
|
+
Object.defineProperty(exports, "WorktualAIBot", { enumerable: true, get: function () { return __importDefault(WorktualAIBot_1).default; } });
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;AAAA,iDAA2D;AAAlD,+HAAA,OAAO,OAAiB"}
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@worktual/react-native-ai-bot",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "Worktual AI Bot - Embeddable AI chatbot for React Native apps",
|
|
5
|
-
"main": "
|
|
6
|
-
"types": "
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
7
|
"scripts": {
|
|
8
8
|
"build": "tsc",
|
|
9
9
|
"prepublishOnly": "npm run build"
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"typescript": "^5.9.3"
|
|
30
30
|
},
|
|
31
31
|
"files": [
|
|
32
|
-
"
|
|
32
|
+
"dist/",
|
|
33
33
|
"README.md"
|
|
34
34
|
]
|
|
35
35
|
}
|
package/src/WorktualAIBot.tsx
DELETED
|
@@ -1,293 +0,0 @@
|
|
|
1
|
-
import React, { useState, useEffect, useRef, useCallback } from "react";
|
|
2
|
-
import {
|
|
3
|
-
View,
|
|
4
|
-
StyleSheet,
|
|
5
|
-
Animated,
|
|
6
|
-
Text,
|
|
7
|
-
ActivityIndicator,
|
|
8
|
-
StatusBar,
|
|
9
|
-
Platform,
|
|
10
|
-
} from "react-native";
|
|
11
|
-
import { WebView, WebViewMessageEvent } from "react-native-webview";
|
|
12
|
-
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
|
13
|
-
|
|
14
|
-
/* ────────────────────────────────────────────────────────
|
|
15
|
-
* Public types
|
|
16
|
-
* ──────────────────────────────────────────────────────── */
|
|
17
|
-
|
|
18
|
-
export interface WorktualAIBotProps {
|
|
19
|
-
/** Your unique webchat ID provided by Worktual */
|
|
20
|
-
webchatId: string;
|
|
21
|
-
|
|
22
|
-
/** Called when the bot sends a close/end event (navigate back, dismiss modal, etc.) */
|
|
23
|
-
onClose: () => void;
|
|
24
|
-
|
|
25
|
-
/** Optional: custom base URL (defaults to Worktual production) */
|
|
26
|
-
baseUrl?: string;
|
|
27
|
-
|
|
28
|
-
/** Optional: loading screen title (default: "AI Assistant") */
|
|
29
|
-
loadingTitle?: string;
|
|
30
|
-
|
|
31
|
-
/** Optional: loading screen subtitle (default: "Loading your chat...") */
|
|
32
|
-
loadingSubtitle?: string;
|
|
33
|
-
|
|
34
|
-
/** Optional: primary colour for progress bar & spinner (default: "#575CFF") */
|
|
35
|
-
primaryColor?: string;
|
|
36
|
-
|
|
37
|
-
/** Optional: loading screen background colour (default: "#f8f9fb") */
|
|
38
|
-
loadingBackground?: string;
|
|
39
|
-
|
|
40
|
-
/** Optional: maximum time (ms) to wait before force-hiding loader (default: 6000) */
|
|
41
|
-
maxLoadTime?: number;
|
|
42
|
-
|
|
43
|
-
/** Optional: called when bot content is fully loaded */
|
|
44
|
-
onReady?: () => void;
|
|
45
|
-
|
|
46
|
-
/** Optional: called on every postMessage from the WebView */
|
|
47
|
-
onMessage?: (data: Record<string, unknown>) => void;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/* ────────────────────────────────────────────────────────
|
|
51
|
-
* Constants
|
|
52
|
-
* ──────────────────────────────────────────────────────── */
|
|
53
|
-
|
|
54
|
-
const DEFAULT_BASE_URL =
|
|
55
|
-
"https://ccaas-storage.worktual.co.uk/chat/ailivebot.html";
|
|
56
|
-
|
|
57
|
-
const buildUrl = (baseUrl: string, webchatId: string): string => {
|
|
58
|
-
const sep = baseUrl.includes("?") ? "&" : "?";
|
|
59
|
-
return `${baseUrl}${sep}webchatid=${webchatId}&isHeader=1`;
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
/** Injected JS – polls for chat content then posts webchat_ready */
|
|
63
|
-
const buildInjectedJS = (maxMs: number): string => `
|
|
64
|
-
(function() {
|
|
65
|
-
var t = setInterval(function() {
|
|
66
|
-
var m = document.querySelectorAll(
|
|
67
|
-
'.message, .chat-message, .msg-content, [class*="message"]'
|
|
68
|
-
);
|
|
69
|
-
var i = document.querySelector('input[placeholder], textarea[placeholder]');
|
|
70
|
-
if (m.length > 0 || i) {
|
|
71
|
-
clearInterval(t);
|
|
72
|
-
window.ReactNativeWebView.postMessage(
|
|
73
|
-
JSON.stringify({ type: "webchat_ready" })
|
|
74
|
-
);
|
|
75
|
-
}
|
|
76
|
-
}, 200);
|
|
77
|
-
setTimeout(function() {
|
|
78
|
-
clearInterval(t);
|
|
79
|
-
window.ReactNativeWebView.postMessage(
|
|
80
|
-
JSON.stringify({ type: "webchat_ready" })
|
|
81
|
-
);
|
|
82
|
-
}, ${maxMs});
|
|
83
|
-
})();
|
|
84
|
-
true;
|
|
85
|
-
`;
|
|
86
|
-
|
|
87
|
-
/* ────────────────────────────────────────────────────────
|
|
88
|
-
* Component
|
|
89
|
-
* ──────────────────────────────────────────────────────── */
|
|
90
|
-
|
|
91
|
-
const WorktualAIBot: React.FC<WorktualAIBotProps> = ({
|
|
92
|
-
webchatId,
|
|
93
|
-
onClose,
|
|
94
|
-
baseUrl = DEFAULT_BASE_URL,
|
|
95
|
-
loadingTitle = "AI Assistant",
|
|
96
|
-
loadingSubtitle = "Loading your chat...",
|
|
97
|
-
primaryColor = "#575CFF",
|
|
98
|
-
loadingBackground = "#f8f9fb",
|
|
99
|
-
maxLoadTime = 6000,
|
|
100
|
-
onReady,
|
|
101
|
-
onMessage: onMessageProp,
|
|
102
|
-
}) => {
|
|
103
|
-
const insets = useSafeAreaInsets();
|
|
104
|
-
const [showLoader, setShowLoader] = useState(true);
|
|
105
|
-
|
|
106
|
-
// Animations
|
|
107
|
-
const progressAnim = useRef(new Animated.Value(0)).current;
|
|
108
|
-
const fadeAnim = useRef(new Animated.Value(1)).current;
|
|
109
|
-
const dotAnim = useRef(new Animated.Value(0)).current;
|
|
110
|
-
|
|
111
|
-
const url = buildUrl(baseUrl, webchatId);
|
|
112
|
-
const injectedJS = buildInjectedJS(maxLoadTime);
|
|
113
|
-
|
|
114
|
-
/* ── Animations ── */
|
|
115
|
-
useEffect(() => {
|
|
116
|
-
// Progress bar: fast to 70%, then slow to 90%
|
|
117
|
-
Animated.sequence([
|
|
118
|
-
Animated.timing(progressAnim, {
|
|
119
|
-
toValue: 0.7,
|
|
120
|
-
duration: 800,
|
|
121
|
-
useNativeDriver: false,
|
|
122
|
-
}),
|
|
123
|
-
Animated.timing(progressAnim, {
|
|
124
|
-
toValue: 0.9,
|
|
125
|
-
duration: 2500,
|
|
126
|
-
useNativeDriver: false,
|
|
127
|
-
}),
|
|
128
|
-
]).start();
|
|
129
|
-
|
|
130
|
-
// Pulsing dots
|
|
131
|
-
Animated.loop(
|
|
132
|
-
Animated.sequence([
|
|
133
|
-
Animated.timing(dotAnim, { toValue: 1, duration: 500, useNativeDriver: true }),
|
|
134
|
-
Animated.timing(dotAnim, { toValue: 0.3, duration: 500, useNativeDriver: true }),
|
|
135
|
-
])
|
|
136
|
-
).start();
|
|
137
|
-
}, []);
|
|
138
|
-
|
|
139
|
-
/* ── Hide loader ── */
|
|
140
|
-
const hideLoader = useCallback(() => {
|
|
141
|
-
if (!showLoader) return;
|
|
142
|
-
// Complete progress bar
|
|
143
|
-
Animated.timing(progressAnim, {
|
|
144
|
-
toValue: 1,
|
|
145
|
-
duration: 150,
|
|
146
|
-
useNativeDriver: false,
|
|
147
|
-
}).start();
|
|
148
|
-
|
|
149
|
-
// Fade out
|
|
150
|
-
setTimeout(() => {
|
|
151
|
-
Animated.timing(fadeAnim, {
|
|
152
|
-
toValue: 0,
|
|
153
|
-
duration: 200,
|
|
154
|
-
useNativeDriver: true,
|
|
155
|
-
}).start(() => setShowLoader(false));
|
|
156
|
-
}, 150);
|
|
157
|
-
}, [showLoader]);
|
|
158
|
-
|
|
159
|
-
/* ── WebView message handler ── */
|
|
160
|
-
const handleMessage = useCallback(
|
|
161
|
-
(event: WebViewMessageEvent) => {
|
|
162
|
-
try {
|
|
163
|
-
const data = JSON.parse(event.nativeEvent.data);
|
|
164
|
-
|
|
165
|
-
// Forward to client's onMessage if provided
|
|
166
|
-
onMessageProp?.(data);
|
|
167
|
-
|
|
168
|
-
if (data?.type === "webchat_ready") {
|
|
169
|
-
hideLoader();
|
|
170
|
-
onReady?.();
|
|
171
|
-
}
|
|
172
|
-
if (data?.type === "webchat_end") {
|
|
173
|
-
onClose();
|
|
174
|
-
}
|
|
175
|
-
} catch (_) {
|
|
176
|
-
// Ignore non-JSON messages
|
|
177
|
-
}
|
|
178
|
-
},
|
|
179
|
-
[hideLoader, onClose, onReady, onMessageProp]
|
|
180
|
-
);
|
|
181
|
-
|
|
182
|
-
/* ── Render ── */
|
|
183
|
-
const progressWidth = progressAnim.interpolate({
|
|
184
|
-
inputRange: [0, 1],
|
|
185
|
-
outputRange: ["0%", "100%"],
|
|
186
|
-
});
|
|
187
|
-
|
|
188
|
-
return (
|
|
189
|
-
<View style={[styles.container, { paddingTop: insets.top }]}>
|
|
190
|
-
<StatusBar barStyle="dark-content" backgroundColor="#fff" />
|
|
191
|
-
|
|
192
|
-
{/* WebView loads immediately behind the loader */}
|
|
193
|
-
<WebView
|
|
194
|
-
source={{ uri: url }}
|
|
195
|
-
style={styles.webview}
|
|
196
|
-
javaScriptEnabled
|
|
197
|
-
domStorageEnabled
|
|
198
|
-
allowsInlineMediaPlayback
|
|
199
|
-
mediaPlaybackRequiresUserAction={false}
|
|
200
|
-
onMessage={handleMessage}
|
|
201
|
-
injectedJavaScript={injectedJS}
|
|
202
|
-
// Prevent white flash on Android
|
|
203
|
-
{...(Platform.OS === "android" && {
|
|
204
|
-
overScrollMode: "never" as const,
|
|
205
|
-
setBuiltInZoomControls: false,
|
|
206
|
-
})}
|
|
207
|
-
/>
|
|
208
|
-
|
|
209
|
-
{/* Loading overlay */}
|
|
210
|
-
{showLoader && (
|
|
211
|
-
<Animated.View
|
|
212
|
-
style={[
|
|
213
|
-
styles.loaderOverlay,
|
|
214
|
-
{ opacity: fadeAnim, backgroundColor: loadingBackground },
|
|
215
|
-
]}
|
|
216
|
-
>
|
|
217
|
-
{/* Spinner */}
|
|
218
|
-
<ActivityIndicator
|
|
219
|
-
size="large"
|
|
220
|
-
color={primaryColor}
|
|
221
|
-
style={styles.spinner}
|
|
222
|
-
/>
|
|
223
|
-
|
|
224
|
-
{/* Title */}
|
|
225
|
-
<Text style={styles.loaderTitle}>{loadingTitle}</Text>
|
|
226
|
-
|
|
227
|
-
{/* Subtitle with pulsing opacity */}
|
|
228
|
-
<Animated.Text
|
|
229
|
-
style={[styles.loaderSubtitle, { opacity: dotAnim }]}
|
|
230
|
-
>
|
|
231
|
-
{loadingSubtitle}
|
|
232
|
-
</Animated.Text>
|
|
233
|
-
|
|
234
|
-
{/* Progress bar */}
|
|
235
|
-
<View style={styles.progressTrack}>
|
|
236
|
-
<Animated.View
|
|
237
|
-
style={[
|
|
238
|
-
styles.progressBar,
|
|
239
|
-
{ width: progressWidth, backgroundColor: primaryColor },
|
|
240
|
-
]}
|
|
241
|
-
/>
|
|
242
|
-
</View>
|
|
243
|
-
</Animated.View>
|
|
244
|
-
)}
|
|
245
|
-
</View>
|
|
246
|
-
);
|
|
247
|
-
};
|
|
248
|
-
|
|
249
|
-
/* ────────────────────────────────────────────────────────
|
|
250
|
-
* Styles
|
|
251
|
-
* ──────────────────────────────────────────────────────── */
|
|
252
|
-
|
|
253
|
-
const styles = StyleSheet.create({
|
|
254
|
-
container: {
|
|
255
|
-
flex: 1,
|
|
256
|
-
backgroundColor: "#fff",
|
|
257
|
-
},
|
|
258
|
-
webview: {
|
|
259
|
-
flex: 1,
|
|
260
|
-
},
|
|
261
|
-
loaderOverlay: {
|
|
262
|
-
...StyleSheet.absoluteFillObject,
|
|
263
|
-
justifyContent: "center",
|
|
264
|
-
alignItems: "center",
|
|
265
|
-
},
|
|
266
|
-
spinner: {
|
|
267
|
-
marginBottom: 20,
|
|
268
|
-
},
|
|
269
|
-
loaderTitle: {
|
|
270
|
-
fontSize: 18,
|
|
271
|
-
fontWeight: "600",
|
|
272
|
-
color: "#1a1a2e",
|
|
273
|
-
marginBottom: 6,
|
|
274
|
-
},
|
|
275
|
-
loaderSubtitle: {
|
|
276
|
-
fontSize: 14,
|
|
277
|
-
color: "#8e8ea0",
|
|
278
|
-
marginBottom: 28,
|
|
279
|
-
},
|
|
280
|
-
progressTrack: {
|
|
281
|
-
width: 200,
|
|
282
|
-
height: 4,
|
|
283
|
-
backgroundColor: "#e4e4e7",
|
|
284
|
-
borderRadius: 2,
|
|
285
|
-
overflow: "hidden",
|
|
286
|
-
},
|
|
287
|
-
progressBar: {
|
|
288
|
-
height: "100%",
|
|
289
|
-
borderRadius: 2,
|
|
290
|
-
},
|
|
291
|
-
});
|
|
292
|
-
|
|
293
|
-
export default WorktualAIBot;
|