embeddedaichatux 1.8.0 → 2.0.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/EmbeddedChat.js +128 -33
- package/package.json +1 -1
package/EmbeddedChat.js
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
this.isPreview = this.options.isPreview || false;
|
|
10
10
|
this.locale = options.locale || 'en';
|
|
11
11
|
this.previewParam = this.isPreview ? "?isPreview=true" : "";
|
|
12
|
-
this.serverUrl = this.options.serverUrl || 'https://
|
|
12
|
+
this.serverUrl = this.options.serverUrl || 'https://app.bizdriver.ai/';
|
|
13
13
|
this.height = options.height || 600; // Default height
|
|
14
14
|
this.width = options.width || 320; // Default width
|
|
15
15
|
this.marginBottom = options.marginBottom || 0;
|
|
@@ -18,6 +18,13 @@
|
|
|
18
18
|
this.mouseInsideChat = false;
|
|
19
19
|
this.hasRefreshed = false; // Flag to prevent endless loop
|
|
20
20
|
this.conversationId = null;
|
|
21
|
+
this.userTokenProvider = options.userTokenProvider;
|
|
22
|
+
|
|
23
|
+
try {
|
|
24
|
+
this.targetOrigin = new URL(this.serverUrl).origin;
|
|
25
|
+
} catch {
|
|
26
|
+
this.targetOrigin = "*";
|
|
27
|
+
}
|
|
21
28
|
|
|
22
29
|
// Determine transition styles
|
|
23
30
|
const transitionStyle = this.enableAnimation ? 'transition: height 0.3s ease, opacity 0.3s ease;' : '';
|
|
@@ -70,40 +77,81 @@
|
|
|
70
77
|
}
|
|
71
78
|
}
|
|
72
79
|
|
|
73
|
-
init() {
|
|
74
|
-
this.updateIframes();
|
|
75
|
-
this.addEventListeners();
|
|
80
|
+
async init() {
|
|
81
|
+
await this.updateIframes();
|
|
76
82
|
}
|
|
77
83
|
|
|
78
84
|
async updateIframes() {
|
|
79
|
-
const cleanedServerUrl = this.serverUrl.endsWith('/')
|
|
85
|
+
const cleanedServerUrl = this.serverUrl.endsWith('/')
|
|
86
|
+
? this.serverUrl.slice(0, -1)
|
|
87
|
+
: this.serverUrl;
|
|
80
88
|
const baseIframeUrl = `${cleanedServerUrl}/ChatUX/${this.chatId}`;
|
|
81
|
-
const minimizedPositionStyle = `
|
|
89
|
+
const minimizedPositionStyle = `
|
|
90
|
+
position: fixed; right: 0; bottom: 0;
|
|
91
|
+
width: ${this.width}px;
|
|
92
|
+
height: ${this.minimizedHeight};
|
|
93
|
+
z-index: 100000;
|
|
94
|
+
${this.enableAnimation ? 'transition: height 0.3s ease, opacity 0.3s ease;' : ''}
|
|
95
|
+
`;
|
|
96
|
+
|
|
97
|
+
const params = {
|
|
98
|
+
isPreview: this.isPreview,
|
|
99
|
+
mode: this.mode,
|
|
100
|
+
locale: this.locale,
|
|
101
|
+
conversationId: this.conversationId
|
|
102
|
+
};
|
|
82
103
|
|
|
83
104
|
const iframeHtml = `
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
105
|
+
<iframe
|
|
106
|
+
id="embedded-chat"
|
|
107
|
+
style="${this.positionStyle}; display: none; border:none; overflow:hidden;"
|
|
108
|
+
frameborder="0"
|
|
109
|
+
sandbox="allow-same-origin allow-scripts allow-popups allow-forms allow-top-navigation-by-user-activation"
|
|
110
|
+
src="${this.buildIframeUrl(baseIframeUrl, params)}"
|
|
111
|
+
></iframe>
|
|
112
|
+
<iframe
|
|
113
|
+
id="embedded-chat-minimized"
|
|
114
|
+
style="${minimizedPositionStyle}; display: none; border:none; overflow:hidden;"
|
|
115
|
+
frameborder="0"
|
|
116
|
+
sandbox="allow-same-origin allow-scripts allow-popups allow-forms"
|
|
117
|
+
src="${this.buildIframeUrl(baseIframeUrl, { ...params, isMinimized: true })}"
|
|
118
|
+
></iframe>
|
|
119
|
+
`;
|
|
120
|
+
|
|
121
|
+
// inject and capture references
|
|
88
122
|
this.containerDiv.innerHTML = iframeHtml;
|
|
89
|
-
this.iframe = this.containerDiv.querySelector(
|
|
90
|
-
this.minimizedIframe = this.containerDiv.querySelector(
|
|
123
|
+
this.iframe = this.containerDiv.querySelector('#embedded-chat');
|
|
124
|
+
this.minimizedIframe = this.containerDiv.querySelector('#embedded-chat-minimized');
|
|
91
125
|
|
|
126
|
+
// wait for the real <iframe> element to load
|
|
92
127
|
await this.waitForIframeLoad(this.iframe);
|
|
93
128
|
|
|
129
|
+
// now that this.iframe & this.minimizedIframe exist, hook up events
|
|
130
|
+
this.addEventListeners();
|
|
131
|
+
|
|
132
|
+
// Send auth to iframes after load
|
|
133
|
+
await this.postAuthToIframes();
|
|
134
|
+
|
|
135
|
+
// restore your ContactForm logic
|
|
94
136
|
if (this.mode === 'ContactForm') {
|
|
95
|
-
this.iframe.style.maxWidth =
|
|
96
|
-
this.iframe.style.display =
|
|
137
|
+
this.iframe.style.maxWidth = '100%';
|
|
138
|
+
this.iframe.style.display = 'block';
|
|
97
139
|
}
|
|
98
140
|
}
|
|
99
141
|
|
|
100
142
|
addEventListeners() {
|
|
143
|
+
if (!this.iframe || !this.minimizedIframe) {
|
|
144
|
+
console.error('EmbeddedChat: iframe or minimizedIframe is not defined when trying to add event listeners.', this.iframe, this.minimizedIframe);
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
101
147
|
this.iframe.addEventListener("mouseenter", () => { this.mouseInsideChat = true; });
|
|
102
148
|
this.iframe.addEventListener("mouseleave", () => { this.mouseInsideChat = false; });
|
|
103
149
|
this.minimizedIframe.addEventListener("mouseenter", () => { this.mouseInsideChat = true; });
|
|
104
150
|
this.minimizedIframe.addEventListener("mouseleave", () => { this.mouseInsideChat = false; });
|
|
105
151
|
|
|
106
152
|
window.addEventListener("message", (e) => {
|
|
153
|
+
// Only trust messages from our server (when targetOrigin is not "*")
|
|
154
|
+
if (this.targetOrigin !== "*" && e.origin !== this.targetOrigin) return;
|
|
107
155
|
this.handleMessage(e);
|
|
108
156
|
});
|
|
109
157
|
|
|
@@ -128,11 +176,26 @@
|
|
|
128
176
|
message: "resize",
|
|
129
177
|
width: window.innerWidth, // Ensure correct size
|
|
130
178
|
height: window.innerHeight
|
|
131
|
-
},
|
|
179
|
+
}, this.targetOrigin);
|
|
132
180
|
}
|
|
133
181
|
}
|
|
134
182
|
|
|
135
183
|
handleMessage(e) {
|
|
184
|
+
console.log('[EmbeddedChat] Received message:', {
|
|
185
|
+
origin: e.origin,
|
|
186
|
+
type: e.data?.type,
|
|
187
|
+
message: e.data?.message,
|
|
188
|
+
chatId: e.data?.chatId,
|
|
189
|
+
data: e.data
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
// Allow the iframe to request a fresh token
|
|
193
|
+
if (typeof e.data === "object" && e.data?.type === "requestAuth") {
|
|
194
|
+
console.log('[EmbeddedChat] Received requestAuth message, calling postAuthToIframes');
|
|
195
|
+
this.postAuthToIframes();
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
|
|
136
199
|
if (typeof e.data === "object" && (!e.data.chatId || e.data.chatId === this.chatId)) {
|
|
137
200
|
const updates = {};
|
|
138
201
|
|
|
@@ -332,12 +395,18 @@
|
|
|
332
395
|
showMaximized(animate = false) {
|
|
333
396
|
const schedulePostMessage = () => {
|
|
334
397
|
if (this.iframe.contentWindow) {
|
|
335
|
-
this.iframe.contentWindow.postMessage({
|
|
398
|
+
this.iframe.contentWindow.postMessage({
|
|
399
|
+
message: "show",
|
|
400
|
+
sessionInfo: this.sessionInfo || null
|
|
401
|
+
}, this.targetOrigin);
|
|
336
402
|
} else {
|
|
337
403
|
// Schedule a single retry with a delay
|
|
338
404
|
setTimeout(() => {
|
|
339
405
|
if (this.iframe.contentWindow) {
|
|
340
|
-
this.iframe.contentWindow.postMessage({
|
|
406
|
+
this.iframe.contentWindow.postMessage({
|
|
407
|
+
message: "show",
|
|
408
|
+
sessionInfo: this.sessionInfo || null
|
|
409
|
+
}, this.targetOrigin);
|
|
341
410
|
} else {
|
|
342
411
|
console.warn("iframe contentWindow is not available.");
|
|
343
412
|
}
|
|
@@ -347,20 +416,17 @@
|
|
|
347
416
|
|
|
348
417
|
if (animate) {
|
|
349
418
|
this.animateMaximize();
|
|
350
|
-
}
|
|
351
|
-
else {
|
|
419
|
+
} else {
|
|
352
420
|
this.minimizedIframe.style.display = "none";
|
|
353
421
|
this.minimizedIframe.style.height = `${this.height}px`;
|
|
354
422
|
this.minimizedIframe.style.opacity = ''; // Reset opacity to unset
|
|
355
423
|
|
|
356
424
|
this.iframe.style.display = "block";
|
|
357
|
-
|
|
358
|
-
|
|
359
425
|
this.iframe.style.height = `${this.height}px`;
|
|
360
426
|
this.iframe.style.opacity = '1';
|
|
361
|
-
|
|
362
|
-
schedulePostMessage();
|
|
363
427
|
}
|
|
428
|
+
|
|
429
|
+
schedulePostMessage();
|
|
364
430
|
}
|
|
365
431
|
|
|
366
432
|
applyScale(scale) {
|
|
@@ -380,17 +446,11 @@
|
|
|
380
446
|
|
|
381
447
|
setSessionInfo(sessionInfo) {
|
|
382
448
|
console.log('setSessionInfo called with sessionInfo:', sessionInfo);
|
|
383
|
-
|
|
384
449
|
this.sessionInfo = sessionInfo;
|
|
385
450
|
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
iframe.contentWindow.postMessage({ type: 'setSessionInfo', sessionInfo: sessionInfo }, "*");
|
|
390
|
-
};
|
|
391
|
-
|
|
392
|
-
if (iframe.style.display !== "none") {
|
|
393
|
-
postMessage();
|
|
451
|
+
// Send session info immediately if the chat is already maximized
|
|
452
|
+
if (this.iframe?.contentWindow && this.iframe.style.display !== "none") {
|
|
453
|
+
this.iframe.contentWindow.postMessage({ type: 'setSessionInfo', sessionInfo: this.sessionInfo }, this.targetOrigin);
|
|
394
454
|
}
|
|
395
455
|
}
|
|
396
456
|
|
|
@@ -422,7 +482,7 @@
|
|
|
422
482
|
}
|
|
423
483
|
|
|
424
484
|
for (const [key, value] of Object.entries(params)) {
|
|
425
|
-
if (key !== 'mode' && key !== 'isPreview' && key !== 'conversationId' && value !== null && value !== undefined) {
|
|
485
|
+
if (key !== 'mode' && key !== 'isPreview' && key !== 'conversationId' && key !== 'userToken' && value !== null && value !== undefined) {
|
|
426
486
|
urlParams.set(key, value);
|
|
427
487
|
}
|
|
428
488
|
}
|
|
@@ -450,6 +510,41 @@
|
|
|
450
510
|
}, { once: true }); // Ensure the listener is triggered only once
|
|
451
511
|
});
|
|
452
512
|
}
|
|
513
|
+
|
|
514
|
+
async postAuthToIframes() {
|
|
515
|
+
console.log('[EmbeddedChat] postAuthToIframes called');
|
|
516
|
+
if (typeof this.userTokenProvider !== 'function') {
|
|
517
|
+
console.warn('[EmbeddedChat] No userTokenProvider function provided');
|
|
518
|
+
return;
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
try {
|
|
522
|
+
console.log('[EmbeddedChat] Calling userTokenProvider...');
|
|
523
|
+
const userToken = await this.userTokenProvider();
|
|
524
|
+
|
|
525
|
+
if (!userToken) {
|
|
526
|
+
console.warn('[EmbeddedChat] userTokenProvider returned null/empty token');
|
|
527
|
+
return;
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
console.log('[EmbeddedChat] Got user token, length:', userToken?.length || 0);
|
|
531
|
+
|
|
532
|
+
if (this.iframe?.contentWindow) {
|
|
533
|
+
console.log('[EmbeddedChat] Sending auth message to iframe with targetOrigin:', this.targetOrigin);
|
|
534
|
+
this.iframe.contentWindow.postMessage({
|
|
535
|
+
type: 'auth',
|
|
536
|
+
userToken: userToken,
|
|
537
|
+
chatId: this.chatId
|
|
538
|
+
}, this.targetOrigin);
|
|
539
|
+
console.log('[EmbeddedChat] Auth message sent successfully');
|
|
540
|
+
} else {
|
|
541
|
+
console.error('[EmbeddedChat] iframe.contentWindow is not available');
|
|
542
|
+
}
|
|
543
|
+
// No longer send auth to minimizedIframe
|
|
544
|
+
} catch (err) {
|
|
545
|
+
console.error('[EmbeddedChat] Failed to get user token:', err);
|
|
546
|
+
}
|
|
547
|
+
}
|
|
453
548
|
}
|
|
454
549
|
|
|
455
550
|
export function initEmbeddedChat(containerDiv, chatId, options) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "embeddedaichatux",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "A lightweight and customizable embedded AI chat UI component that seamlessly integrates into web applications, offering minimized and expanded views, with iframe-based content rendering.",
|
|
5
5
|
"main": "EmbeddedChat.js",
|
|
6
6
|
"scripts": {
|