@crestapps/ai-chat-ui 1.0.0-preview-22.6 → 1.0.0-preview.7

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.
@@ -30,7 +30,7 @@ window.chatInteractionManager = function () {
30
30
  downloadChartButtonText: 'Download',
31
31
  codeCopiedText: 'Copied!',
32
32
  assistantLabel: 'Assistant',
33
- messageTemplate: "\n <div class=\"ai-chat-messages\">\n <div v-for=\"(message, index) in messages\" :key=\"index\" class=\"ai-chat-message-item\">\n <div>\n <div v-if=\"message.role === 'user'\" class=\"ai-chat-msg-role ai-chat-msg-role-user\">You</div>\n <div v-else-if=\"message.role !== 'indicator'\" :class=\"getAssistantRoleClasses(message)\">\n <span :class=\"getAssistantIconClasses(message, index)\"><i :class=\"getAssistantIcon(message)\"></i></span>\n {{ getAssistantLabel(message) }}\n </div>\n <div class=\"lh-base\">\n <h4 v-if=\"message.title\">{{ message.title }}</h4>\n <div v-html=\"message.htmlContent\"></div>\n <span class=\"message-buttons-container\" v-if=\"!isIndicator(message)\">\n <button v-if=\"textToSpeechEnabled && message.role === 'assistant' && !message.isStreaming\" class=\"btn btn-sm btn-link text-secondary p-0 me-1 button-message-toolbox\" :class=\"{ 'tts-playing': ttsPlayingMessageIndex === index }\" @click=\"toggleMessageTts(message, index)\" :title=\"ttsPlayingMessageIndex === index ? 'Pause audio' : 'Read aloud'\">\n <i :class=\"ttsPlayingMessageIndex === index ? 'fa-solid fa-circle-pause' : 'fa-solid fa-circle-play'\"></i>\n </button>\n <button class=\"btn btn-sm btn-link text-secondary p-0 button-message-toolbox\" @click=\"copyResponse(message.content)\" title=\"Click here to copy response to clipboard.\">\n <i class=\"fa-solid fa-copy\"></i>\n </button>\n </span>\n </div>\n </div>\n </div>\n <div v-for=\"notification in notifications\" :key=\"'notif-' + notification.type\" class=\"ai-chat-notification\" :class=\"'ai-chat-notification-' + (notification.type || 'info') + ' ' + (notification.cssClass || '')\">\n <div class=\"ai-chat-notification-content\">\n <i v-if=\"notification.icon\" :class=\"notification.icon\" class=\"ai-chat-notification-icon\"></i>\n <span class=\"ai-chat-notification-text\">{{ notification.content }}</span>\n <button v-if=\"notification.dismissible\" class=\"btn btn-sm btn-link p-0 ms-2 ai-chat-notification-dismiss\" @click=\"dismissNotification(notification.type)\" title=\"Dismiss\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n <div v-if=\"notification.actions && notification.actions.length\" class=\"ai-chat-notification-actions\">\n <button v-for=\"action in notification.actions\" :key=\"action.name\" class=\"btn btn-sm\" :class=\"action.cssClass || 'btn-outline-secondary'\" @click=\"handleNotificationAction(notification.type, action.name)\">\n <i v-if=\"action.icon\" :class=\"action.icon\" class=\"me-1\"></i>\n {{ action.label }}\n </button>\n </div>\n </div>\n </div>\n ",
33
+ messageTemplate: "\n <div class=\"ai-chat-messages\">\n <div v-for=\"(message, index) in messages\" :key=\"index\" class=\"ai-chat-message-item\">\n <div>\n <div v-if=\"message.role === 'user'\" class=\"ai-chat-msg-role ai-chat-msg-role-user\">You</div>\n <div v-else-if=\"message.role !== 'indicator'\" :class=\"getAssistantRoleClasses(message)\">\n <span :class=\"getAssistantIconClasses(message, index)\"><i :class=\"getAssistantIcon(message)\"></i></span>\n {{ getAssistantLabel(message) }}\n </div>\n <div class=\"ai-chat-message-body lh-base\">\n <h4 v-if=\"message.title\">{{ message.title }}</h4>\n <div v-html=\"message.htmlContent\"></div>\n <span class=\"message-buttons-container\" v-if=\"!isIndicator(message)\">\n <button v-if=\"textToSpeechEnabled && !isConversationMode && message.role === 'assistant' && !message.isStreaming\" class=\"btn btn-sm btn-link text-secondary p-0 me-1 button-message-toolbox\" :class=\"{ 'tts-playing': ttsPlayingMessageIndex === index }\" @click=\"toggleMessageTts(message, index)\" :title=\"ttsPlayingMessageIndex === index ? 'Pause audio' : 'Read aloud'\">\n <i :class=\"ttsPlayingMessageIndex === index ? 'fa-solid fa-circle-pause' : 'fa-solid fa-circle-play'\"></i>\n </button>\n <button class=\"btn btn-sm btn-link text-secondary p-0 button-message-toolbox\" @click=\"copyResponse(message.content)\" title=\"Click here to copy response to clipboard.\">\n <i class=\"fa-solid fa-copy\"></i>\n </button>\n </span>\n </div>\n </div>\n </div>\n <div v-for=\"notification in notifications\" :key=\"'notif-' + notification.type\" class=\"ai-chat-notification\" :class=\"'ai-chat-notification-' + (notification.type || 'info') + ' ' + (notification.cssClass || '')\">\n <div class=\"ai-chat-notification-content\">\n <i v-if=\"notification.icon\" :class=\"notification.icon\" class=\"ai-chat-notification-icon\"></i>\n <span class=\"ai-chat-notification-text\">{{ notification.content }}</span>\n <button v-if=\"notification.dismissible\" class=\"btn btn-sm btn-link p-0 ms-2 ai-chat-notification-dismiss\" @click=\"dismissNotification(notification.type)\" title=\"Dismiss\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n <div v-if=\"notification.actions && notification.actions.length\" class=\"ai-chat-notification-actions\">\n <button v-for=\"action in notification.actions\" :key=\"action.name\" class=\"btn btn-sm\" :class=\"action.cssClass || 'btn-outline-secondary'\" @click=\"handleNotificationAction(notification.type, action.name)\">\n <i v-if=\"action.icon\" :class=\"action.icon\" class=\"me-1\"></i>\n {{ action.label }}\n </button>\n </div>\n </div>\n </div>\n ",
34
34
  indicatorTemplate: "\n <div class=\"ai-chat-msg-role ai-chat-msg-role-assistant\">\n <span class=\"ai-streaming-icon\"><i class=\"fa fa-robot\" style=\"display: inline-block;\"></i></span>\n Assistant\n </div>\n ",
35
35
  // Localizable strings
36
36
  untitledText: 'Untitled',
@@ -331,8 +331,10 @@ window.chatInteractionManager = function () {
331
331
  audioPlayQueue: [],
332
332
  isPlayingAudio: false,
333
333
  currentAudioElement: null,
334
+ currentAudioUrl: null,
334
335
  ttsPlayingMessageIndex: -1,
335
336
  ttsAudioCache: {},
337
+ ttsInstanceId: 'chat-interaction-' + Math.random().toString(36).slice(2),
336
338
  conversationModeEnabled: config.chatMode === 'Conversation',
337
339
  conversationButton: null,
338
340
  isConversationMode: false,
@@ -1030,6 +1032,13 @@ window.chatInteractionManager = function () {
1030
1032
  this.debouncedSaveSettings();
1031
1033
  }
1032
1034
  },
1035
+ handleExternalTtsStop: function handleExternalTtsStop(e) {
1036
+ var _e$detail;
1037
+ if ((e === null || e === void 0 || (_e$detail = e.detail) === null || _e$detail === void 0 ? void 0 : _e$detail.sourceId) === this.ttsInstanceId) {
1038
+ return;
1039
+ }
1040
+ this.stopAudio(false);
1041
+ },
1033
1042
  synthesizeSpeech: function synthesizeSpeech(text, cacheIndex) {
1034
1043
  var _this7 = this;
1035
1044
  if (!this.textToSpeechEnabled || !text || !this.connection) {
@@ -1050,7 +1059,12 @@ window.chatInteractionManager = function () {
1050
1059
  this.stopAudio();
1051
1060
  return;
1052
1061
  }
1053
- this.stopAudio();
1062
+ this.stopAudio(false);
1063
+ window.dispatchEvent(new CustomEvent('crestapps-ai-chat-stop-tts', {
1064
+ detail: {
1065
+ sourceId: this.ttsInstanceId
1066
+ }
1067
+ }));
1054
1068
  this.ttsPlayingMessageIndex = index;
1055
1069
  if (this.ttsAudioCache[index]) {
1056
1070
  this.playAudioBlob(this.ttsAudioCache[index]);
@@ -1062,6 +1076,7 @@ window.chatInteractionManager = function () {
1062
1076
  if (this.audioChunks.length === 0) {
1063
1077
  if (!this.isPlayingAudio && this.audioPlayQueue.length === 0) {
1064
1078
  this.isPlayingAudio = false;
1079
+ this.ttsPlayingMessageIndex = -1;
1065
1080
  }
1066
1081
  return;
1067
1082
  }
@@ -1103,23 +1118,29 @@ window.chatInteractionManager = function () {
1103
1118
  var _this8 = this;
1104
1119
  var url = URL.createObjectURL(blob);
1105
1120
  var audio = new Audio(url);
1121
+ this.currentAudioUrl = url;
1106
1122
  this.currentAudioElement = audio;
1107
1123
  this.isPlayingAudio = true;
1108
1124
  audio.addEventListener('ended', function () {
1109
- URL.revokeObjectURL(url);
1110
1125
  _this8.currentAudioElement = null;
1126
+ _this8.currentAudioUrl = null;
1127
+ URL.revokeObjectURL(url);
1111
1128
  _this8.playNextInQueue();
1112
1129
  });
1113
1130
  audio.addEventListener('error', function () {
1114
- URL.revokeObjectURL(url);
1115
1131
  _this8.currentAudioElement = null;
1132
+ _this8.currentAudioUrl = null;
1133
+ URL.revokeObjectURL(url);
1116
1134
  _this8.playNextInQueue();
1117
1135
  });
1118
1136
  audio.play()["catch"](function (err) {
1119
1137
  console.error("Audio playback error:", err);
1120
- URL.revokeObjectURL(url);
1121
1138
  _this8.currentAudioElement = null;
1139
+ _this8.currentAudioUrl = null;
1140
+ URL.revokeObjectURL(url);
1141
+ _this8.audioPlayQueue = [];
1122
1142
  _this8.isPlayingAudio = false;
1143
+ _this8.ttsPlayingMessageIndex = -1;
1123
1144
  });
1124
1145
  },
1125
1146
  playNextInQueue: function playNextInQueue() {
@@ -1138,6 +1159,10 @@ window.chatInteractionManager = function () {
1138
1159
  this.currentAudioElement.currentTime = 0;
1139
1160
  this.currentAudioElement = null;
1140
1161
  }
1162
+ if (this.currentAudioUrl) {
1163
+ URL.revokeObjectURL(this.currentAudioUrl);
1164
+ this.currentAudioUrl = null;
1165
+ }
1141
1166
  this.audioChunks = [];
1142
1167
  this.audioPlayQueue = [];
1143
1168
  this.isPlayingAudio = false;
@@ -2046,9 +2071,12 @@ window.chatInteractionManager = function () {
2046
2071
  }, _callee5);
2047
2072
  }))();
2048
2073
  window.addEventListener('beforeunload', this.handleBeforeUnload);
2074
+ window.addEventListener('crestapps-ai-chat-stop-tts', this.handleExternalTtsStop);
2049
2075
  },
2050
2076
  beforeUnmount: function beforeUnmount() {
2051
2077
  window.removeEventListener('beforeunload', this.handleBeforeUnload);
2078
+ window.removeEventListener('crestapps-ai-chat-stop-tts', this.handleExternalTtsStop);
2079
+ this.stopAudio(false);
2052
2080
  if (this.stream) {
2053
2081
  this.stream.dispose();
2054
2082
  this.stream = null;