@modochats/widget 0.1.0 → 0.1.2
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/src/models/conversation.js +1 -1
- package/dist/src/types/app.js +1 -0
- package/package.json +1 -1
- package/.vscode/settings.json +0 -3
- package/.yarn/install-state.gz +0 -0
- package/cdn-dist/README.md +0 -42
- package/cdn-dist/modo-web-component.js +0 -1344
- package/cdn-dist/modo-web-component.min.js +0 -1
- package/cdn-dist/package.json +0 -27
- package/dist/types/src/app.d.ts +0 -30
- package/dist/types/src/app.d.ts.map +0 -1
- package/dist/types/src/constants/index.d.ts +0 -10
- package/dist/types/src/constants/index.d.ts.map +0 -1
- package/dist/types/src/constants/regex.d.ts +0 -3
- package/dist/types/src/constants/regex.d.ts.map +0 -1
- package/dist/types/src/index.d.ts +0 -10
- package/dist/types/src/index.d.ts.map +0 -1
- package/dist/types/src/models/chatbot.d.ts +0 -24
- package/dist/types/src/models/chatbot.d.ts.map +0 -1
- package/dist/types/src/models/conversation.d.ts +0 -23
- package/dist/types/src/models/conversation.d.ts.map +0 -1
- package/dist/types/src/models/customer-data.d.ts +0 -32
- package/dist/types/src/models/customer-data.d.ts.map +0 -1
- package/dist/types/src/models/message-utils.d.ts +0 -13
- package/dist/types/src/models/message-utils.d.ts.map +0 -1
- package/dist/types/src/services/chat/conversation.d.ts +0 -23
- package/dist/types/src/services/chat/conversation.d.ts.map +0 -1
- package/dist/types/src/services/chat/message-utils.d.ts +0 -13
- package/dist/types/src/services/chat/message-utils.d.ts.map +0 -1
- package/dist/types/src/services/chat/model.d.ts +0 -28
- package/dist/types/src/services/chat/model.d.ts.map +0 -1
- package/dist/types/src/services/chatbot/chatbot.d.ts +0 -24
- package/dist/types/src/services/chatbot/chatbot.d.ts.map +0 -1
- package/dist/types/src/services/checker.d.ts +0 -4
- package/dist/types/src/services/checker.d.ts.map +0 -1
- package/dist/types/src/services/listeners/adders.d.ts +0 -4
- package/dist/types/src/services/listeners/adders.d.ts.map +0 -1
- package/dist/types/src/services/listeners/fn.d.ts +0 -4
- package/dist/types/src/services/listeners/fn.d.ts.map +0 -1
- package/dist/types/src/services/socket/utils.d.ts +0 -3
- package/dist/types/src/services/socket/utils.d.ts.map +0 -1
- package/dist/types/src/services/ui/fn.d.ts +0 -14
- package/dist/types/src/services/ui/fn.d.ts.map +0 -1
- package/dist/types/src/services/ui/html.d.ts +0 -4
- package/dist/types/src/services/ui/html.d.ts.map +0 -1
- package/dist/types/src/services/user/customer-data.d.ts +0 -32
- package/dist/types/src/services/user/customer-data.d.ts.map +0 -1
- package/dist/types/src/services/voice-chat/model.d.ts +0 -13
- package/dist/types/src/services/voice-chat/model.d.ts.map +0 -1
- package/dist/types/src/services/voice-chat/utils.d.ts +0 -10
- package/dist/types/src/services/voice-chat/utils.d.ts.map +0 -1
- package/dist/types/src/tools/fetch.d.ts +0 -3
- package/dist/types/src/tools/fetch.d.ts.map +0 -1
- package/dist/types/src/types/app.d.ts +0 -18
- package/dist/types/src/types/app.d.ts.map +0 -1
- package/dist/types/src/types/conversation.d.ts +0 -15
- package/dist/types/src/types/conversation.d.ts.map +0 -1
- package/dist/types/src/types/socket.d.ts +0 -7
- package/dist/types/src/types/socket.d.ts.map +0 -1
- package/dist/types/src/types/window.d.ts +0 -10
- package/dist/types/src/types/window.d.ts.map +0 -1
- package/dist/types/src/utils/audio.d.ts +0 -4
- package/dist/types/src/utils/audio.d.ts.map +0 -1
- package/dist/types/src/utils/browser.d.ts +0 -3
- package/dist/types/src/utils/browser.d.ts.map +0 -1
- package/dist/types/src/utils/fetch.d.ts +0 -19
- package/dist/types/src/utils/fetch.d.ts.map +0 -1
- package/dist/types/src/utils/uuid.d.ts +0 -7
- package/dist/types/src/utils/uuid.d.ts.map +0 -1
- package/rollup.config.js +0 -18
- package/rollup.dev.config.js +0 -22
- package/scripts/create-umd-bundle.js +0 -213
- package/scripts/terser-minify.js +0 -112
- package/src/app.ts +0 -117
- package/src/constants/index.ts +0 -21
- package/src/constants/regex.ts +0 -2
- package/src/index.ts +0 -16
- package/src/services/chat/conversation.ts +0 -135
- package/src/services/chat/message-utils.ts +0 -221
- package/src/services/chat/model.ts +0 -139
- package/src/services/chatbot/chatbot.ts +0 -66
- package/src/services/checker.ts +0 -10
- package/src/services/listeners/adders.ts +0 -178
- package/src/services/listeners/fn.ts +0 -77
- package/src/services/socket/utils.ts +0 -9
- package/src/services/ui/fn.ts +0 -254
- package/src/services/ui/html.ts +0 -192
- package/src/services/user/customer-data.ts +0 -78
- package/src/services/voice-chat/model.ts +0 -79
- package/src/services/voice-chat/utils.ts +0 -137
- package/src/tools/fetch.ts +0 -7
- package/src/types/app.ts +0 -17
- package/src/types/conversation.ts +0 -14
- package/src/types/socket.ts +0 -7
- package/src/types/window.ts +0 -12
- package/src/utils/audio.ts +0 -67
- package/src/utils/browser.ts +0 -4
- package/src/utils/fetch.ts +0 -98
- package/src/utils/uuid.ts +0 -13
- package/temp/audio/new-message.mp3 +0 -0
- package/temp/audio/on-hold.mp3 +0 -0
- package/temp/audio-processor.js +0 -261
- package/temp/css/index.css +0 -2283
- package/temp/dev.html +0 -87
- package/temp/index.html +0 -16
- package/tsconfig.json +0 -119
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
const onSocketConnectionUpdate = (connected: boolean) => {
|
|
2
|
-
const widget = window.getMWidget?.();
|
|
3
|
-
const connectionIndicator = widget?.container?.querySelector(".mw-connection-status");
|
|
4
|
-
|
|
5
|
-
if (connectionIndicator) {
|
|
6
|
-
connectionIndicator.className = `mw-connection-status ${connected ? "mw-connected" : "mw-disconnected"}`;
|
|
7
|
-
}
|
|
8
|
-
};
|
|
9
|
-
export {onSocketConnectionUpdate};
|
package/src/services/ui/fn.ts
DELETED
|
@@ -1,254 +0,0 @@
|
|
|
1
|
-
import {BASE_STORAGE_URL, isDev} from "#src/constants/index.js";
|
|
2
|
-
import {ConversationStatus} from "#src/types/conversation.js";
|
|
3
|
-
|
|
4
|
-
function switchToConversationLayout() {
|
|
5
|
-
const widget = window.getMWidget?.();
|
|
6
|
-
widget?.container?.querySelector(".mw-new-conversation-btn")?.classList.remove("mw-hidden");
|
|
7
|
-
widget?.container?.querySelector(".mw-starters-con")?.classList.add("mw-hidden");
|
|
8
|
-
}
|
|
9
|
-
function switchToStarterLayout() {
|
|
10
|
-
const widget = window.getMWidget?.();
|
|
11
|
-
widget?.container?.querySelector(".mw-new-conversation-btn")?.classList.add("mw-hidden");
|
|
12
|
-
widget?.container?.querySelector(".mw-starters-con")?.classList.remove("mw-hidden");
|
|
13
|
-
widget?.container?.querySelector(".mw-conversation-status-icon")?.classList.add("mw-hidden");
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
function setConversationType(type: keyof typeof ConversationStatus) {
|
|
17
|
-
const widget = window.getMWidget?.();
|
|
18
|
-
widget?.container?.querySelector(".mw-conversation-status-icon")?.classList.remove("mw-hidden");
|
|
19
|
-
const statusIcon = widget?.container?.querySelector(".mw-conversation-status-icon");
|
|
20
|
-
|
|
21
|
-
if (statusIcon) {
|
|
22
|
-
// Remove existing mode classes
|
|
23
|
-
statusIcon.classList.remove("mw-ai-mode", "mw-human-mode");
|
|
24
|
-
|
|
25
|
-
// Add appropriate mode class
|
|
26
|
-
if (type === "AI_CHAT") {
|
|
27
|
-
statusIcon.classList.add("mw-ai-mode");
|
|
28
|
-
} else {
|
|
29
|
-
statusIcon.classList.add("mw-human-mode");
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
function loadStarters() {
|
|
35
|
-
const widget = window.getMWidget?.();
|
|
36
|
-
const startersContainer = widget?.container?.querySelector(".mw-starters-con");
|
|
37
|
-
const starterItemsContainer = widget?.container?.querySelector(".mw-starter-items");
|
|
38
|
-
|
|
39
|
-
startersContainer?.classList.remove("mw-hidden");
|
|
40
|
-
|
|
41
|
-
for (const starter of widget?.chatbot?.starters || []) {
|
|
42
|
-
const starterElement = document.createElement("div");
|
|
43
|
-
starterElement.className = "mw-starter-item";
|
|
44
|
-
starterElement.textContent = starter;
|
|
45
|
-
starterElement.addEventListener("click", async () => {
|
|
46
|
-
const inputEl = widget?.container?.querySelector(".mw-chat-input") as HTMLInputElement;
|
|
47
|
-
const sendMsgBtnEl = widget?.container?.querySelector(".mw-send-message-btn") as HTMLButtonElement;
|
|
48
|
-
switchToConversationLayout();
|
|
49
|
-
if (inputEl) {
|
|
50
|
-
inputEl.value = starter;
|
|
51
|
-
sendMsgBtnEl.click();
|
|
52
|
-
}
|
|
53
|
-
});
|
|
54
|
-
starterItemsContainer?.appendChild(starterElement);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
function updateChatToggleImage() {
|
|
59
|
-
const widget = window.getMWidget?.();
|
|
60
|
-
const toggleImageEl = widget?.container?.querySelector(".mw-chat-toggle-image") as HTMLImageElement;
|
|
61
|
-
const starterLogoEl = widget?.container?.querySelector(".mw-starter-logo") as HTMLImageElement;
|
|
62
|
-
|
|
63
|
-
const defaultSvg =
|
|
64
|
-
"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='white'%3E%3Cpath d='M12 2C13.1 2 14 2.9 14 4C14 5.1 13.1 6 12 6C10.9 6 10 5.1 10 4C10 2.9 10.9 2 12 2ZM21 9V7L15 1H5C3.89 1 3 1.89 3 3V21C3 22.1 3.9 23 5 23H11V21H5V3H13V9H21ZM23 18V16H15V18L19 22L15 26V28H23V26H19L23 22L19 18H23Z'/%3E%3C/svg%3E";
|
|
65
|
-
|
|
66
|
-
// Update toggle button image
|
|
67
|
-
if (toggleImageEl) {
|
|
68
|
-
if (widget?.chatbot?.image) {
|
|
69
|
-
toggleImageEl.src = widget.chatbot.image;
|
|
70
|
-
toggleImageEl.alt = widget.chatbot.name || "شروع گفتگو";
|
|
71
|
-
|
|
72
|
-
// Add error handling for failed image loads
|
|
73
|
-
toggleImageEl.onerror = () => {
|
|
74
|
-
toggleImageEl.src = defaultSvg;
|
|
75
|
-
toggleImageEl.alt = "پشتیبانی چت";
|
|
76
|
-
};
|
|
77
|
-
} else {
|
|
78
|
-
// Use default avatar if no image is provided
|
|
79
|
-
toggleImageEl.src = defaultSvg;
|
|
80
|
-
toggleImageEl.alt = "پشتیبانی چت";
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// Update starter logo
|
|
85
|
-
if (starterLogoEl) {
|
|
86
|
-
if (widget?.chatbot?.image) {
|
|
87
|
-
starterLogoEl.src = widget.chatbot.image;
|
|
88
|
-
starterLogoEl.alt = widget.chatbot.name || "لوگو چت بات";
|
|
89
|
-
starterLogoEl.style.display = "block";
|
|
90
|
-
|
|
91
|
-
// Add error handling for failed image loads
|
|
92
|
-
starterLogoEl.onerror = () => {
|
|
93
|
-
starterLogoEl.style.display = "none";
|
|
94
|
-
};
|
|
95
|
-
} else {
|
|
96
|
-
// Hide logo if no image is provided
|
|
97
|
-
starterLogoEl.style.display = "none";
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
function updateChatTitle() {
|
|
103
|
-
const widget = window.getMWidget?.();
|
|
104
|
-
const chatTitleEl = widget?.container?.querySelector(".mw-chat-title") as HTMLElement;
|
|
105
|
-
const starterTitleEl = widget?.container?.querySelector(".mw-starter-title") as HTMLElement;
|
|
106
|
-
|
|
107
|
-
if (chatTitleEl || starterTitleEl) {
|
|
108
|
-
// Use options title if no chatbot name is available
|
|
109
|
-
const displayTitle = widget?.options?.title || widget?.chatbot?.name || "Modo";
|
|
110
|
-
|
|
111
|
-
if (chatTitleEl) {
|
|
112
|
-
chatTitleEl.textContent = displayTitle;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
if (starterTitleEl) {
|
|
116
|
-
starterTitleEl.textContent = displayTitle;
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
function applyModoOptions() {
|
|
122
|
-
const widget = window.getMWidget?.();
|
|
123
|
-
if (!widget?.container || !widget?.options) return;
|
|
124
|
-
|
|
125
|
-
const container = widget.container;
|
|
126
|
-
const options = widget.options;
|
|
127
|
-
|
|
128
|
-
// Apply position option
|
|
129
|
-
applyPositionOption(container, options.position!);
|
|
130
|
-
|
|
131
|
-
// Apply theme option
|
|
132
|
-
applyThemeOption(container, options.theme!);
|
|
133
|
-
|
|
134
|
-
// Apply primary color option
|
|
135
|
-
applyPrimaryColorOption(container, options.primaryColor!);
|
|
136
|
-
|
|
137
|
-
// Apply foreground color option
|
|
138
|
-
applyForegroundColorOption(container, options.foregroundColor!);
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
function applyPositionOption(container: HTMLDivElement, position: "left" | "right") {
|
|
142
|
-
const widget = window.getMWidget?.()?.container as HTMLElement;
|
|
143
|
-
if (widget) {
|
|
144
|
-
if (position === "left") {
|
|
145
|
-
widget.style.right = "auto";
|
|
146
|
-
widget.style.left = "32px";
|
|
147
|
-
widget.style.direction = "ltr";
|
|
148
|
-
|
|
149
|
-
// Update chat body position for left alignment
|
|
150
|
-
const chatBody = widget.querySelector(".mw-chat-body") as HTMLElement;
|
|
151
|
-
if (chatBody) {
|
|
152
|
-
chatBody.style.right = "auto";
|
|
153
|
-
chatBody.style.left = "0";
|
|
154
|
-
}
|
|
155
|
-
} else {
|
|
156
|
-
// widget.style.left = "auto";
|
|
157
|
-
// widget.style.right = "32px";
|
|
158
|
-
// widget.style.direction = "rtl";
|
|
159
|
-
|
|
160
|
-
// Update chat body position for right alignment
|
|
161
|
-
const chatBody = widget.querySelector(".mw-chat-body") as HTMLElement;
|
|
162
|
-
if (chatBody) {
|
|
163
|
-
chatBody.style.left = "auto";
|
|
164
|
-
chatBody.style.right = "0";
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
function applyThemeOption(container: HTMLDivElement, theme: "dark" | "light") {
|
|
171
|
-
// Set the theme attribute on the container or document
|
|
172
|
-
const widget = document.querySelector(".modo-widget");
|
|
173
|
-
if (theme === "light") {
|
|
174
|
-
widget?.setAttribute("data-theme", "light");
|
|
175
|
-
} else {
|
|
176
|
-
widget?.removeAttribute("data-theme");
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
// Store theme preference
|
|
180
|
-
localStorage.setItem("modo-component:theme", theme);
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
function applyPrimaryColorOption(container: HTMLDivElement, primaryColor: string) {
|
|
184
|
-
// Create CSS custom properties for the primary color
|
|
185
|
-
const root = document.querySelector(".modo-widget") as HTMLDivElement;
|
|
186
|
-
if (root) {
|
|
187
|
-
// Set the primary color
|
|
188
|
-
root?.style.setProperty("--primary-color", primaryColor);
|
|
189
|
-
|
|
190
|
-
// Generate hover color (slightly darker)
|
|
191
|
-
const hoverColor = adjustColorBrightness(primaryColor, -20);
|
|
192
|
-
root?.style.setProperty("--primary-hover", hoverColor);
|
|
193
|
-
|
|
194
|
-
// Generate gradient using the primary color
|
|
195
|
-
const gradientColor = adjustColorBrightness(primaryColor, 15);
|
|
196
|
-
root?.style.setProperty("--primary-gradient", `linear-gradient(135deg, ${primaryColor} 0%, ${gradientColor} 100%)`);
|
|
197
|
-
} else console.error("modo chat widget not found");
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
function applyForegroundColorOption(container: HTMLDivElement, foregroundColor: string) {
|
|
201
|
-
// Create CSS custom properties for the foreground color
|
|
202
|
-
const root = document.querySelector(".modo-widget") as HTMLDivElement;
|
|
203
|
-
if (root) {
|
|
204
|
-
// Set the foreground color
|
|
205
|
-
root?.style.setProperty("--foreground-color", foregroundColor);
|
|
206
|
-
|
|
207
|
-
// Set white color to use foreground color for white text elements
|
|
208
|
-
root?.style.setProperty("--white", foregroundColor);
|
|
209
|
-
} else console.error("modo chat widget not found");
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
function adjustColorBrightness(hex: string, percent: number): string {
|
|
213
|
-
// Remove # if present
|
|
214
|
-
hex = hex.replace(/^#/, "");
|
|
215
|
-
|
|
216
|
-
// Parse r, g, b values
|
|
217
|
-
const num = parseInt(hex, 16);
|
|
218
|
-
const amt = Math.round(2.55 * percent);
|
|
219
|
-
const R = (num >> 16) + amt;
|
|
220
|
-
const G = ((num >> 8) & 0x00ff) + amt;
|
|
221
|
-
const B = (num & 0x0000ff) + amt;
|
|
222
|
-
|
|
223
|
-
// Ensure values stay within 0-255 range
|
|
224
|
-
const newR = Math.max(0, Math.min(255, R));
|
|
225
|
-
const newG = Math.max(0, Math.min(255, G));
|
|
226
|
-
const newB = Math.max(0, Math.min(255, B));
|
|
227
|
-
|
|
228
|
-
return `#${((newR << 16) | (newG << 8) | newB).toString(16).padStart(6, "0")}`;
|
|
229
|
-
}
|
|
230
|
-
async function loadCss() {
|
|
231
|
-
return await new Promise(resolve => {
|
|
232
|
-
const link = document.createElement("link");
|
|
233
|
-
const source = isDev ? "/css/index.css" : `${BASE_STORAGE_URL}/index.css`;
|
|
234
|
-
link.rel = "stylesheet";
|
|
235
|
-
link.href = source;
|
|
236
|
-
document.head.appendChild(link);
|
|
237
|
-
link.addEventListener("load", () => {
|
|
238
|
-
resolve("css loaded");
|
|
239
|
-
});
|
|
240
|
-
});
|
|
241
|
-
}
|
|
242
|
-
export {
|
|
243
|
-
switchToConversationLayout,
|
|
244
|
-
switchToStarterLayout,
|
|
245
|
-
setConversationType,
|
|
246
|
-
loadStarters,
|
|
247
|
-
loadCss,
|
|
248
|
-
updateChatToggleImage,
|
|
249
|
-
updateChatTitle,
|
|
250
|
-
applyModoOptions,
|
|
251
|
-
applyPositionOption,
|
|
252
|
-
applyThemeOption,
|
|
253
|
-
applyPrimaryColorOption
|
|
254
|
-
};
|
package/src/services/ui/html.ts
DELETED
|
@@ -1,192 +0,0 @@
|
|
|
1
|
-
import {Widget} from "#src/app.js";
|
|
2
|
-
import {registerListeners} from "../listeners/adders.js";
|
|
3
|
-
|
|
4
|
-
const createChatContainer = (widget: Widget) => {
|
|
5
|
-
widget.container = document.createElement("div");
|
|
6
|
-
widget.container.textContent = "Start Chat";
|
|
7
|
-
widget.container.classList.add("modo-widget");
|
|
8
|
-
|
|
9
|
-
// Add fullscreen class if fullscreen mode is enabled
|
|
10
|
-
if (widget.options.fullScreen) {
|
|
11
|
-
widget.container.classList.add("mw-fullscreen");
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
document.body.appendChild(widget.container);
|
|
15
|
-
let conBody = document.createElement("div");
|
|
16
|
-
widget.container.appendChild(conBody);
|
|
17
|
-
widget.container.innerHTML = `
|
|
18
|
-
<div dir="rtl" class="mw-chat-inner">
|
|
19
|
-
<div class="mw-chat-body ${widget.options.fullScreen ? "mw-active" : "mw-hidden"}">
|
|
20
|
-
<div class="mw-chat-container">
|
|
21
|
-
<!-- Chat Header -->
|
|
22
|
-
<div class="mw-chat-header">
|
|
23
|
-
<div style="display: flex; align-items: center; gap: 8px;">
|
|
24
|
-
<h3 class="mw-chat-title">پشتیبانی چت</h3>
|
|
25
|
-
<div class="mw-conversation-status-icon mw-hidden">
|
|
26
|
-
<!-- Clean AI/Bot icon -->
|
|
27
|
-
<svg class="mw-ai-chat-icon" style="width: 14px; height: 14px;" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><!-- Icon from Material Design Icons by Pictogrammers - https://github.com/Templarian/MaterialDesign/blob/master/LICENSE --><path fill="currentColor" d="M22 14h-1c0-3.87-3.13-7-7-7h-1V5.73A2 2 0 1 0 10 4c0 .74.4 1.39 1 1.73V7h-1c-3.87 0-7 3.13-7 7H2c-.55 0-1 .45-1 1v3c0 .55.45 1 1 1h1v1a2 2 0 0 0 2 2h14c1.11 0 2-.89 2-2v-1h1c.55 0 1-.45 1-1v-3c0-.55-.45-1-1-1m-1 3h-2v3H5v-3H3v-1h2v-2c0-2.76 2.24-5 5-5h4c2.76 0 5 2.24 5 5v2h2zM8.5 13.5l2.36 2.36l-1.18 1.18l-1.18-1.18l-1.18 1.18l-1.18-1.18zm7 0l2.36 2.36l-1.18 1.18l-1.18-1.18l-1.18 1.18l-1.18-1.18z"/></svg>
|
|
28
|
-
<!-- Clean Human/Person icon -->
|
|
29
|
-
<svg class="mw-human-chat-icon" viewBox="0 0 24 24" width="18" height="18">
|
|
30
|
-
<path fill="currentColor" d="M12 4C13.66 4 15 5.34 15 7C15 8.66 13.66 10 12 10C10.34 10 9 8.66 9 7C9 5.34 10.34 4 12 4ZM12 12C15.31 12 18 13.34 18 15V18H6V15C6 13.34 8.69 12 12 12Z"/>
|
|
31
|
-
</svg>
|
|
32
|
-
<div class="mw-tooltip">
|
|
33
|
-
<span class="mw-tooltip-text-ai">چت بات هوشمند</span>
|
|
34
|
-
<span class="mw-tooltip-text-human">پشتیبان انسانی</span>
|
|
35
|
-
</div>
|
|
36
|
-
</div>
|
|
37
|
-
<div class="mw-connection-status mw-disconnected"></div>
|
|
38
|
-
</div>
|
|
39
|
-
<div style="display: flex; align-items: center; gap: 8px;">
|
|
40
|
-
<button class="mw-new-conversation-btn mw-hidden">
|
|
41
|
-
+
|
|
42
|
-
</button>
|
|
43
|
-
<button class="mw-voice-call-btn mw-hidden">
|
|
44
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24"><!-- Icon from Google Material Icons by Material Design Authors - https://github.com/material-icons/material-icons/blob/master/LICENSE --><path fill="currentColor" d="M6.62 10.79c1.44 2.83 3.76 5.14 6.59 6.59l2.2-2.2c.27-.27.67-.36 1.02-.24c1.12.37 2.33.57 3.57.57c.55 0 1 .45 1 1V20c0 .55-.45 1-1 1c-9.39 0-17-7.61-17-17c0-.55.45-1 1-1h3.5c.55 0 1 .45 1 1c0 1.25.2 2.45.57 3.57c.11.35.03.74-.25 1.02z"/></svg>
|
|
45
|
-
<div class="mw-voice-call-tooltip mw-hidden">
|
|
46
|
-
<div class="mw-voice-call-tooltip-text">مکالمه با هوش مصنوعی</div>
|
|
47
|
-
</div>
|
|
48
|
-
</button>
|
|
49
|
-
</div>
|
|
50
|
-
</div>
|
|
51
|
-
|
|
52
|
-
<div class="mw-chat-messages-con">
|
|
53
|
-
</div>
|
|
54
|
-
<div class="mw-starters-con">
|
|
55
|
-
<div class="mw-starter-welcome">
|
|
56
|
-
<img class="mw-starter-logo" src="" alt="لوگو چت بات" style="display: none;">
|
|
57
|
-
<h2 class="mw-starter-title">پشتیبانی چت</h2>
|
|
58
|
-
</div>
|
|
59
|
-
<div class="mw-starter-items">
|
|
60
|
-
</div>
|
|
61
|
-
</div>
|
|
62
|
-
|
|
63
|
-
<div class="mw-reply-preview mw-hidden">
|
|
64
|
-
<div class="mw-reply-preview-content">
|
|
65
|
-
<div class="mw-reply-preview-info">
|
|
66
|
-
<span class="mw-reply-preview-label">پاسخ به:</span>
|
|
67
|
-
<span class="mw-reply-preview-text"></span>
|
|
68
|
-
</div>
|
|
69
|
-
<button class="mw-reply-preview-close" title="لغو پاسخ">
|
|
70
|
-
<svg viewBox="0 0 24 24" width="16" height="16">
|
|
71
|
-
<path fill="currentColor" d="M19 6.41L17.59 5L12 10.59L6.41 5L5 6.41L10.59 12L5 17.59L6.41 19L12 13.41L17.59 19L19 17.59L13.41 12L19 6.41Z"/>
|
|
72
|
-
</svg>
|
|
73
|
-
</button>
|
|
74
|
-
</div>
|
|
75
|
-
</div>
|
|
76
|
-
|
|
77
|
-
<div class="mw-chat-input-area">
|
|
78
|
-
<input type="text" placeholder="پیام خود را تایپ کنید..." class="mw-chat-input">
|
|
79
|
-
<button class="mw-file-upload-btn" title="آپلود فایل">
|
|
80
|
-
<input type="file" class="mw-file-input" hidden />
|
|
81
|
-
<svg class="mw-file-upload-icon" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24"><!-- Icon from Material Symbols Light by Google - https://github.com/google/material-design-icons/blob/master/LICENSE --><path fill="currentColor" d="M16.346 11.385V6.769h1v4.616zm-5.538 5.457q-.452-.269-.726-.734q-.274-.466-.274-1.031V6.769h1zM11.96 21q-2.271 0-3.846-1.595t-1.575-3.867v-8.73q0-1.587 1.09-2.697Q8.722 3 10.309 3t2.678 1.11t1.091 2.698V14h-1V6.789q-.006-1.166-.802-1.977T10.308 4q-1.163 0-1.966.821q-.804.821-.804 1.987v8.73q-.005 1.853 1.283 3.157Q10.11 20 11.961 20q.556 0 1.056-.124t.945-.372v1.11q-.468.2-.972.293q-.505.093-1.03.093m4.386-1v-2.616h-2.615v-1h2.615V13.77h1v2.615h2.616v1h-2.616V20z"/></svg>
|
|
82
|
-
<svg class="mw-file-remove-icon mw-hidden" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24"><!-- Icon from Material Symbols Light by Google - https://github.com/google/material-design-icons/blob/master/LICENSE --><path fill="currentColor" d="M11.962 21q-2.273 0-3.848-1.594t-1.575-3.867V7.954L2.091 3.508L2.8 2.8l18.4 18.4l-.708.708l-3.805-3.806q-.664 1.298-1.913 2.098t-2.812.8M7.539 8.954v6.584q-.006 1.852 1.282 3.157T11.961 20q1.356 0 2.413-.727t1.574-1.91l-1.98-1.98q-.087.742-.656 1.295q-.568.553-1.35.553q-.881 0-1.518-.627q-.636-.627-.636-1.527v-3.854zm3.269 3.269v2.854q0 .479.328.816q.328.338.806.338q.474 0 .801-.335t.334-.808v-.596zm5.538 1.33V6.77h1v7.804zm-3.269-3.307V6.79q-.006-1.166-.805-1.977T10.308 4q-.708 0-1.281.32q-.573.319-.961.857l-.714-.713q.529-.68 1.285-1.072T10.307 3q1.587 0 2.679 1.11t1.091 2.698v4.458zm-2.27-3.477v1.189l-1-1.02V6.77z"/></svg>
|
|
83
|
-
</button>
|
|
84
|
-
<button class="mw-send-message-btn" data-is-loading="false">
|
|
85
|
-
<svg class="mw-send-icon" viewBox="0 0 24 24">
|
|
86
|
-
<path d="M2.01 21L23 12 2.01 3 2 10l15 2-15 2z"/>
|
|
87
|
-
</svg>
|
|
88
|
-
<span class="mw-btn-loading">
|
|
89
|
-
<svg class="mw-loading-spinner" viewBox="0 0 24 24">
|
|
90
|
-
<circle class="mw-spinner-circle" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4" fill="none"></circle>
|
|
91
|
-
<path class="mw-spinner-path" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
|
92
|
-
</svg>
|
|
93
|
-
</span>
|
|
94
|
-
</button>
|
|
95
|
-
</div>
|
|
96
|
-
|
|
97
|
-
<div class="mw-form-overlay mw-hidden">
|
|
98
|
-
<div class="mw-form-content">
|
|
99
|
-
<h3 class="mw-form-title">اطلاعات تماس</h3>
|
|
100
|
-
<p class="mw-form-subtitle">لطفا برای اطلاع رسانی بهتر پیام ها شماره خود را وارد کنید (اختیاری)</p>
|
|
101
|
-
<div class="mw-form-input-area">
|
|
102
|
-
<input type="tel" placeholder="شماره تلفن (اختیاری)" class="mw-phone-input">
|
|
103
|
-
</div>
|
|
104
|
-
<div class="mw-form-buttons">
|
|
105
|
-
<button class="mw-form-submit-btn">
|
|
106
|
-
ارسال
|
|
107
|
-
</button>
|
|
108
|
-
<button class="mw-form-cancel-btn">
|
|
109
|
-
لغو
|
|
110
|
-
</button>
|
|
111
|
-
</div>
|
|
112
|
-
</div>
|
|
113
|
-
</div>
|
|
114
|
-
|
|
115
|
-
<!-- Chat Footer -->
|
|
116
|
-
<div class="mw-chat-footer">
|
|
117
|
-
<span class="mw-footer-text">ساخته شده با </span>
|
|
118
|
-
<a href="" class="mw-footer-link" target="_blank" rel="noopener noreferrer" title="">مودوچت</a>
|
|
119
|
-
</div>
|
|
120
|
-
|
|
121
|
-
<!-- Voice Agent Overlay -->
|
|
122
|
-
<div class="mw-voice-agent-overlay mw-hidden">
|
|
123
|
-
<div class="mw-voice-agent-content">
|
|
124
|
-
<button class="mw-voice-close-btn">
|
|
125
|
-
<svg viewBox="0 0 24 24" width="24" height="24">
|
|
126
|
-
<path fill="currentColor" d="M19 6.41L17.59 5L12 10.59L6.41 5L5 6.41L10.59 12L5 17.59L6.41 19L12 13.41L17.59 19L19 17.59L13.41 12L19 6.41Z"/>
|
|
127
|
-
</svg>
|
|
128
|
-
</button>
|
|
129
|
-
|
|
130
|
-
<div class="mw-voice-agent-center">
|
|
131
|
-
<img class="mw-voice-agent-logo" src="" alt="چت بات" />
|
|
132
|
-
<h2 class="mw-voice-agent-title">تماس صوتی</h2>
|
|
133
|
-
<p class="mw-voice-agent-status">درحال اتصال...</p>
|
|
134
|
-
</div>
|
|
135
|
-
|
|
136
|
-
<div class="mw-voice-agent-controls">
|
|
137
|
-
<button class="mw-voice-disconnect-btn" title="قطع تماس">
|
|
138
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 256 256"><!-- Icon from Phosphor by Phosphor Icons - https://github.com/phosphor-icons/core/blob/main/LICENSE --><path fill="currentColor" d="M231.59 90.13C175.44 34 80.56 34 24.41 90.13c-20 20-21.92 49.49-4.69 71.71A16 16 0 0 0 32.35 168a15.8 15.8 0 0 0 5.75-1.08l49-17.37l.29-.11a16 16 0 0 0 9.75-11.73l5.9-29.52a76.52 76.52 0 0 1 49.68-.11l6.21 29.75a16 16 0 0 0 9.72 11.59l.29.11l49 17.39a16 16 0 0 0 18.38-5.06c17.19-22.24 15.26-51.73-4.73-71.73M223.67 152l-.3-.12l-48.82-17.33l-6.21-29.74A16 16 0 0 0 158 93a92.56 92.56 0 0 0-60.34.13a16 16 0 0 0-10.32 12l-5.9 29.51l-48.81 17.22c-.1 0-.17.13-.27.17c-12.33-15.91-11-36.23 3.36-50.58c25-25 58.65-37.53 92.28-37.53s67.27 12.51 92.28 37.53c14.33 14.35 15.72 34.67 3.39 50.55m.32 48a8 8 0 0 1-8 8H40a8 8 0 0 1 0-16h176a8 8 0 0 1 8 8Z"/></svg>
|
|
139
|
-
</button>
|
|
140
|
-
</div>
|
|
141
|
-
</div>
|
|
142
|
-
</div>
|
|
143
|
-
</div>
|
|
144
|
-
</div>
|
|
145
|
-
${
|
|
146
|
-
!widget.options.fullScreen
|
|
147
|
-
? `
|
|
148
|
-
<button class="mw-toggle-chat-btn">
|
|
149
|
-
<img
|
|
150
|
-
class="mw-chat-toggle-image"
|
|
151
|
-
src=""
|
|
152
|
-
alt="شروع گفتگو" />
|
|
153
|
-
<svg
|
|
154
|
-
class="mw-chat-toggle-close"
|
|
155
|
-
viewBox="0 0 24 24"
|
|
156
|
-
width="24"
|
|
157
|
-
height="24">
|
|
158
|
-
<path
|
|
159
|
-
fill="currentColor"
|
|
160
|
-
d="M19 6.41L17.59 5L12 10.59L6.41 5L5 6.41L10.59 12L5 17.59L6.41 19L12 13.41L17.59 19L19 17.59L13.41 12L19 6.41Z" />
|
|
161
|
-
</svg>
|
|
162
|
-
<!-- Badge for unread messages -->
|
|
163
|
-
<div class="mw-badge mw-hidden">
|
|
164
|
-
<span class="mw-badge-text">0</span>
|
|
165
|
-
</div>
|
|
166
|
-
<!-- Tooltip for toggle button -->
|
|
167
|
-
<div class="mw-toggle-tooltip mw-hidden">
|
|
168
|
-
<div class="mw-tooltip-inner">
|
|
169
|
-
<div
|
|
170
|
-
class="mw-toggle-tooltip-close"
|
|
171
|
-
title="بستن">
|
|
172
|
-
<svg
|
|
173
|
-
viewBox="0 0 24 24"
|
|
174
|
-
width="16"
|
|
175
|
-
height="16">
|
|
176
|
-
<path
|
|
177
|
-
fill="currentColor"
|
|
178
|
-
d="M19 6.41L17.59 5L12 10.59L6.41 5L5 6.41L10.59 12L5 17.59L6.41 19L12 13.41L17.59 19L19 17.59L13.41 12L19 6.41Z" />
|
|
179
|
-
</svg>
|
|
180
|
-
</div>
|
|
181
|
-
<span class="mw-toggle-tooltip-text">شروع گفتگو</span>
|
|
182
|
-
</div>
|
|
183
|
-
</div>
|
|
184
|
-
</button>
|
|
185
|
-
`
|
|
186
|
-
: ""
|
|
187
|
-
}
|
|
188
|
-
</div>
|
|
189
|
-
`;
|
|
190
|
-
registerListeners(widget.container);
|
|
191
|
-
};
|
|
192
|
-
export {createChatContainer};
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import {Widget} from "#src/app.js";
|
|
2
|
-
import {fetchUpdateUserData} from "#src/utils/fetch.js";
|
|
3
|
-
import {generateUUID} from "#src/utils/uuid.js";
|
|
4
|
-
|
|
5
|
-
class CustomerData {
|
|
6
|
-
private _uniqueId?: string;
|
|
7
|
-
private _userData?: Record<string, any>;
|
|
8
|
-
private widget: Widget;
|
|
9
|
-
phoneNumber?: string;
|
|
10
|
-
|
|
11
|
-
constructor(widget: Widget, userData?: Record<string, any>) {
|
|
12
|
-
this.widget = widget;
|
|
13
|
-
this.initializeUniqueId();
|
|
14
|
-
this.updateUserData(userData);
|
|
15
|
-
this.initializePhoneNumber();
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
initializePhoneNumber() {
|
|
19
|
-
const savedPhoneNumber = localStorage.getItem(`modo-chat:${this.widget.publicKey}-user-phone-number`);
|
|
20
|
-
if (savedPhoneNumber) {
|
|
21
|
-
this.phoneNumber = savedPhoneNumber;
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Initialize unique ID from localStorage or generate a new one
|
|
27
|
-
* Unique ID is independent of user key/data and is generated by ourselves
|
|
28
|
-
*/
|
|
29
|
-
private initializeUniqueId(): void {
|
|
30
|
-
const savedUniqueId = localStorage.getItem(`modo-chat:${this.widget.publicKey}-user-unique-id`);
|
|
31
|
-
|
|
32
|
-
if (savedUniqueId) {
|
|
33
|
-
this._uniqueId = savedUniqueId;
|
|
34
|
-
} else {
|
|
35
|
-
// Generate a new UUID if no saved unique ID exists
|
|
36
|
-
this._uniqueId = crypto.randomUUID ? crypto.randomUUID() : generateUUID();
|
|
37
|
-
localStorage.setItem(`modo-chat:${this.widget.publicKey}-user-unique-id`, this._uniqueId);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Get the current unique ID
|
|
43
|
-
*/
|
|
44
|
-
get uniqueId(): string {
|
|
45
|
-
return this._uniqueId!;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Get the current user data
|
|
50
|
-
*/
|
|
51
|
-
get userData(): Record<string, any> {
|
|
52
|
-
return this._userData || {};
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Update user data with new values
|
|
57
|
-
* @param newUserData - Object containing new user data to merge
|
|
58
|
-
*/
|
|
59
|
-
async updateUserData(newUserData?: Record<string, any>): Promise<void> {
|
|
60
|
-
if (newUserData && typeof newUserData === "object") {
|
|
61
|
-
this._userData = newUserData;
|
|
62
|
-
} else if (newUserData) console.warn("Invalid user data");
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
hasSubmittedPhoneForm(): boolean {
|
|
66
|
-
return Boolean(this.phoneNumber);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
savePhoneNumber(phoneNumber?: string) {
|
|
70
|
-
this.phoneNumber = phoneNumber || "no phone number";
|
|
71
|
-
localStorage.setItem(`modo-chat:${this.widget.publicKey}-user-phone-number`, phoneNumber || "no phone number");
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
async fetchUpdate() {
|
|
75
|
-
await fetchUpdateUserData(this.widget.chatbot?.uuid as string, this.uniqueId, this.userData);
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
export {CustomerData};
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
import {VoiceClient, EventType} from "@modochats/voice-client";
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
initVoiceChatLayout,
|
|
5
|
-
handleVoiceConnected,
|
|
6
|
-
handleVoiceDisconnected,
|
|
7
|
-
handleVoiceConnectionError,
|
|
8
|
-
handleMicrophonePaused,
|
|
9
|
-
handleMicrophoneResumed
|
|
10
|
-
} from "./utils.js";
|
|
11
|
-
|
|
12
|
-
class VoiceChat {
|
|
13
|
-
instance?: VoiceClient;
|
|
14
|
-
isFirstInSession: boolean = true;
|
|
15
|
-
constructor() {
|
|
16
|
-
const widget = window.getMWidget?.();
|
|
17
|
-
this.instance = new VoiceClient({
|
|
18
|
-
apiBase: "https://live.modochats.com",
|
|
19
|
-
// apiBase: "http://localhost:8000",
|
|
20
|
-
chatbotUuid: widget?.chatbot?.uuid as string,
|
|
21
|
-
userUniqueId: widget?.customerData.uniqueId as string
|
|
22
|
-
});
|
|
23
|
-
this.instance.on(EventType.CONNECTED, (event: any) => {
|
|
24
|
-
handleVoiceConnected();
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
this.instance.on(EventType.DISCONNECTED, (event: any) => {
|
|
28
|
-
if (event.reason) {
|
|
29
|
-
}
|
|
30
|
-
handleVoiceDisconnected(event.reason);
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
this.instance.on(EventType.CONNECTION_ERROR, (event: any) => {
|
|
34
|
-
// console.error("🔴 Connection Error:", event.message);
|
|
35
|
-
handleVoiceConnectionError(event.message);
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
this.instance.on(EventType.MICROPHONE_PAUSED, () => {
|
|
39
|
-
handleMicrophonePaused();
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
this.instance.on(EventType.MICROPHONE_RESUMED, () => {
|
|
43
|
-
handleMicrophoneResumed();
|
|
44
|
-
});
|
|
45
|
-
// Initialize the voice agent UI
|
|
46
|
-
this.initHtml();
|
|
47
|
-
|
|
48
|
-
// session check
|
|
49
|
-
const hasSeen = sessionStorage.getItem("modochats:voice-agent-seen") === "true";
|
|
50
|
-
if (hasSeen) this.isFirstInSession = false;
|
|
51
|
-
else sessionStorage.setItem("modochats:voice-agent-seen", "true");
|
|
52
|
-
if (this.isFirstInSession) this.showTooltip();
|
|
53
|
-
}
|
|
54
|
-
async connect() {
|
|
55
|
-
try {
|
|
56
|
-
await this.instance?.connect();
|
|
57
|
-
} catch (error) {
|
|
58
|
-
// console.error("Failed to connect:", error);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
async disconnect() {
|
|
62
|
-
await this.instance?.disconnect();
|
|
63
|
-
}
|
|
64
|
-
initHtml() {
|
|
65
|
-
initVoiceChatLayout();
|
|
66
|
-
}
|
|
67
|
-
toggleLayout() {
|
|
68
|
-
this.toggleLayout();
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
showTooltip() {
|
|
72
|
-
const tooltip = document.querySelector(".mw-voice-call-tooltip");
|
|
73
|
-
tooltip?.classList.remove("mw-hidden");
|
|
74
|
-
setTimeout(() => {
|
|
75
|
-
tooltip?.classList.add("mw-hidden");
|
|
76
|
-
}, 6000);
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
export {VoiceChat};
|