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.
Files changed (2) hide show
  1. package/EmbeddedChat.js +128 -33
  2. 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://embedgpt.chat/';
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('/') ? this.serverUrl.slice(0, -1) : this.serverUrl;
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 = `position: fixed; right: 0; bottom: 0; width: ${this.width}px; height: ${this.minimizedHeight}; z-index: 100000; ${this.enableAnimation ? 'transition: height 0.3s ease, opacity 0.3s ease;' : ''}`;
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
- <iframe id="embedded-chat" style="${this.positionStyle}; display: none; border:none; overflow:hidden;" frameborder="0" sandbox="allow-same-origin allow-scripts allow-popups allow-forms allow-top-navigation-by-user-activation" src="${this.buildIframeUrl(baseIframeUrl, { isPreview: this.isPreview, mode: this.mode, locale: this.locale, conversationId: this.conversationId })}"></iframe>
85
- <iframe id="embedded-chat-minimized" style="${minimizedPositionStyle}; display: none; border:none; overflow:hidden;" frameborder="0" sandbox="allow-same-origin allow-scripts allow-popups allow-forms" src="${this.buildIframeUrl(baseIframeUrl, { isPreview: this.isPreview, isMinimized: true, locale: this.locale, conversationId: this.conversationId })}"></iframe>
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("#embedded-chat");
90
- this.minimizedIframe = this.containerDiv.querySelector("#embedded-chat-minimized");
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 = "100%";
96
- this.iframe.style.display = "block";
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({ message: "show" }, "*");
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({ message: "show" }, "*");
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
- const iframe = this.containerDiv.querySelector("#embedded-chat");
387
-
388
- const postMessage = () => {
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": "1.8.0",
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": {