@modochats/widget 0.1.4 → 1.1.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/.github/workflows/build-and-publish.yml +116 -174
- package/.releaserc +59 -0
- package/CHANGELOG.md +16 -0
- package/README.md +191 -191
- package/package.json +79 -76
- package/src/app.ts +117 -117
- package/src/constants/index.ts +21 -21
- package/src/constants/regex.ts +2 -2
- package/src/constants/version.ts +2 -0
- package/src/index.ts +16 -16
- package/src/services/chat/conversation.ts +135 -135
- package/src/services/chat/message-utils.ts +221 -221
- package/src/services/chat/model.ts +139 -139
- package/src/services/chatbot/chatbot.ts +66 -66
- package/src/services/checker.ts +10 -10
- package/src/services/listeners/fn.ts +77 -77
- package/src/services/socket/utils.ts +9 -9
- package/src/services/user/customer-data.ts +78 -78
- package/src/services/voice-chat/model.ts +79 -79
- package/src/services/voice-chat/utils.ts +137 -137
- package/src/tools/fetch.ts +7 -7
- package/src/types/app.ts +17 -17
- package/src/types/conversation.ts +14 -14
- package/src/types/socket.ts +7 -7
- package/src/types/window.ts +12 -12
- package/src/utils/audio.ts +67 -67
- package/src/utils/browser.ts +4 -4
- package/src/utils/fetch.ts +98 -98
- package/src/utils/uuid.ts +13 -13
- package/dist/src/app.d.ts +0 -29
- package/dist/src/app.js +0 -1
- package/dist/src/app.js.map +0 -1
- package/dist/src/constants/index.d.ts +0 -9
- package/dist/src/constants/index.js +0 -1
- package/dist/src/constants/index.js.map +0 -1
- package/dist/src/constants/regex.d.ts +0 -2
- package/dist/src/constants/regex.js +0 -1
- package/dist/src/constants/regex.js.map +0 -1
- package/dist/src/index.d.ts +0 -9
- package/dist/src/index.js +0 -1
- package/dist/src/index.js.map +0 -1
- package/dist/src/models/chatbot.d.ts +0 -23
- package/dist/src/models/chatbot.js +0 -1
- package/dist/src/models/chatbot.js.map +0 -1
- package/dist/src/models/conversation.d.ts +0 -22
- package/dist/src/models/conversation.js +0 -1
- package/dist/src/models/conversation.js.map +0 -1
- package/dist/src/models/customer-data.d.ts +0 -31
- package/dist/src/models/customer-data.js +0 -1
- package/dist/src/models/customer-data.js.map +0 -1
- package/dist/src/models/message-utils.d.ts +0 -12
- package/dist/src/models/message-utils.js +0 -1
- package/dist/src/models/message-utils.js.map +0 -1
- package/dist/src/services/chat/conversation.d.ts +0 -22
- package/dist/src/services/chat/conversation.js +0 -1
- package/dist/src/services/chat/conversation.js.map +0 -1
- package/dist/src/services/chat/message-utils.d.ts +0 -12
- package/dist/src/services/chat/message-utils.js +0 -1
- package/dist/src/services/chat/message-utils.js.map +0 -1
- package/dist/src/services/chat/model.d.ts +0 -27
- package/dist/src/services/chat/model.js +0 -1
- package/dist/src/services/chat/model.js.map +0 -1
- package/dist/src/services/chatbot/chatbot.d.ts +0 -23
- package/dist/src/services/chatbot/chatbot.js +0 -1
- package/dist/src/services/chatbot/chatbot.js.map +0 -1
- package/dist/src/services/checker.d.ts +0 -3
- package/dist/src/services/checker.js +0 -1
- package/dist/src/services/checker.js.map +0 -1
- package/dist/src/services/listeners/adders.d.ts +0 -3
- package/dist/src/services/listeners/adders.js +0 -1
- package/dist/src/services/listeners/adders.js.map +0 -1
- package/dist/src/services/listeners/fn.d.ts +0 -3
- package/dist/src/services/listeners/fn.js +0 -1
- package/dist/src/services/listeners/fn.js.map +0 -1
- package/dist/src/services/socket/utils.d.ts +0 -2
- package/dist/src/services/socket/utils.js +0 -1
- package/dist/src/services/socket/utils.js.map +0 -1
- package/dist/src/services/ui/fn.d.ts +0 -13
- package/dist/src/services/ui/fn.js +0 -1
- package/dist/src/services/ui/fn.js.map +0 -1
- package/dist/src/services/ui/html.d.ts +0 -3
- package/dist/src/services/ui/html.js +0 -1
- package/dist/src/services/ui/html.js.map +0 -1
- package/dist/src/services/user/customer-data.d.ts +0 -31
- package/dist/src/services/user/customer-data.js +0 -1
- package/dist/src/services/user/customer-data.js.map +0 -1
- package/dist/src/services/voice-chat/model.d.ts +0 -12
- package/dist/src/services/voice-chat/model.js +0 -1
- package/dist/src/services/voice-chat/model.js.map +0 -1
- package/dist/src/services/voice-chat/utils.d.ts +0 -9
- package/dist/src/services/voice-chat/utils.js +0 -1
- package/dist/src/services/voice-chat/utils.js.map +0 -1
- package/dist/src/tools/fetch.d.ts +0 -2
- package/dist/src/tools/fetch.js +0 -1
- package/dist/src/tools/fetch.js.map +0 -1
- package/dist/src/types/app.d.ts +0 -17
- package/dist/src/types/app.js +0 -1
- package/dist/src/types/app.js.map +0 -1
- package/dist/src/types/conversation.d.ts +0 -14
- package/dist/src/types/conversation.js +0 -1
- package/dist/src/types/conversation.js.map +0 -1
- package/dist/src/types/socket.d.ts +0 -6
- package/dist/src/types/socket.js +0 -1
- package/dist/src/types/socket.js.map +0 -1
- package/dist/src/types/window.d.ts +0 -9
- package/dist/src/types/window.js +0 -1
- package/dist/src/types/window.js.map +0 -1
- package/dist/src/utils/audio.d.ts +0 -3
- package/dist/src/utils/audio.js +0 -1
- package/dist/src/utils/audio.js.map +0 -1
- package/dist/src/utils/browser.d.ts +0 -2
- package/dist/src/utils/browser.js +0 -1
- package/dist/src/utils/browser.js.map +0 -1
- package/dist/src/utils/fetch.d.ts +0 -18
- package/dist/src/utils/fetch.js +0 -1
- package/dist/src/utils/fetch.js.map +0 -1
- package/dist/src/utils/uuid.d.ts +0 -6
- package/dist/src/utils/uuid.js +0 -1
- package/dist/src/utils/uuid.js.map +0 -1
- 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
|
@@ -1,139 +1,139 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
class Chat {
|
|
6
|
-
private instance?: ChatClient;
|
|
7
|
-
fileMaster: CFileMaster;
|
|
8
|
-
replyMaster: CReplyMaster;
|
|
9
|
-
conversation: Conversation;
|
|
10
|
-
constructor() {
|
|
11
|
-
this.fileMaster = new CFileMaster();
|
|
12
|
-
this.replyMaster = new CReplyMaster();
|
|
13
|
-
this.conversation = new Conversation();
|
|
14
|
-
}
|
|
15
|
-
initInstance() {
|
|
16
|
-
const widget = window.getMWidget?.();
|
|
17
|
-
const savedUUid = localStorage.getItem(`modo-chat:${widget?.chatbot?.uuid}-conversation-uuid`);
|
|
18
|
-
this.instance = new ChatClient({
|
|
19
|
-
chatbotUuid: widget?.chatbot?.uuid as string,
|
|
20
|
-
userData: {uuid: widget?.customerData.uniqueId as string, phoneNumber: widget?.customerData.phoneNumber},
|
|
21
|
-
conversationUUid: savedUUid || undefined
|
|
22
|
-
});
|
|
23
|
-
this.instance.on(EventType.CONVERSATION_SYSTEM_MESSAGE, ev => {
|
|
24
|
-
this.conversation.addSystemMessage(ev.message);
|
|
25
|
-
});
|
|
26
|
-
this.instance.on(EventType.CONVERSATION_MESSAGE, ev => {
|
|
27
|
-
this.conversation.addMessage(ev.message, {incoming: ev.incoming});
|
|
28
|
-
});
|
|
29
|
-
this.instance.on(EventType.SOCKET_CONNECTED, ev => {
|
|
30
|
-
onSocketConnectionUpdate(true);
|
|
31
|
-
});
|
|
32
|
-
this.instance.on(EventType.SOCKET_DISCONNECTED, ev => {
|
|
33
|
-
onSocketConnectionUpdate(false);
|
|
34
|
-
});
|
|
35
|
-
this.instance.on(EventType.CONVERSATION_LOAD, ev => {
|
|
36
|
-
this.conversation.clearContainerEl();
|
|
37
|
-
this.conversation.setStatus();
|
|
38
|
-
this.conversation.onInit();
|
|
39
|
-
|
|
40
|
-
localStorage.setItem(`modo-chat:${widget?.chatbot?.uuid}-conversation-uuid`, this.instance?.conversation?.uuid as string);
|
|
41
|
-
});
|
|
42
|
-
this.instance.on(EventType.CONVERSATION_MESSAGES_CLEAR, () => {
|
|
43
|
-
this.conversation.clearContainerEl();
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
|
-
get socket() {
|
|
47
|
-
return this.instance?.socket;
|
|
48
|
-
}
|
|
49
|
-
// conversation data , since the instance only stores and handles data ^^
|
|
50
|
-
get conversationD() {
|
|
51
|
-
return this.instance?.conversation;
|
|
52
|
-
}
|
|
53
|
-
clear() {
|
|
54
|
-
this.conversation.clear();
|
|
55
|
-
this.instance?.clearConversation();
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
sendMessage(...args: Parameters<ChatClient["sendMessage"]>) {
|
|
59
|
-
return this.instance?.sendMessage(...args);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
class CFileMaster {
|
|
63
|
-
file?: File;
|
|
64
|
-
|
|
65
|
-
clearFile() {
|
|
66
|
-
this.file = undefined;
|
|
67
|
-
this.toggleUiState();
|
|
68
|
-
}
|
|
69
|
-
setFile(file: File) {
|
|
70
|
-
this.file = file;
|
|
71
|
-
this.toggleUiState();
|
|
72
|
-
}
|
|
73
|
-
toggleUiState() {
|
|
74
|
-
const container = window.getMWidget?.().container;
|
|
75
|
-
const fileUploadBtn = container?.querySelector(".mw-file-upload-btn") as HTMLButtonElement;
|
|
76
|
-
const fileInput = container?.querySelector(".mw-file-input") as HTMLInputElement;
|
|
77
|
-
const uploadIcon = container?.querySelector(".mw-file-upload-icon") as SVGElement;
|
|
78
|
-
const removeIcon = container?.querySelector(".mw-file-remove-icon") as SVGElement;
|
|
79
|
-
|
|
80
|
-
if (this.file) {
|
|
81
|
-
uploadIcon.classList.add("mw-hidden");
|
|
82
|
-
removeIcon.classList.remove("mw-hidden");
|
|
83
|
-
fileUploadBtn.classList.add("mw-file-uploaded");
|
|
84
|
-
} else {
|
|
85
|
-
fileInput.value = "";
|
|
86
|
-
uploadIcon.classList.remove("mw-hidden");
|
|
87
|
-
removeIcon.classList.add("mw-hidden");
|
|
88
|
-
fileUploadBtn.classList.remove("mw-file-uploaded");
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
class CReplyMaster {
|
|
94
|
-
replyingTo?: ConversationMessage;
|
|
95
|
-
|
|
96
|
-
setReply(message: ConversationMessage) {
|
|
97
|
-
this.replyingTo = message;
|
|
98
|
-
this.updateReplyUI();
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
clearReply() {
|
|
102
|
-
this.replyingTo = undefined;
|
|
103
|
-
|
|
104
|
-
this.updateReplyUI();
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
private updateReplyUI() {
|
|
108
|
-
const container = window.getMWidget?.().container;
|
|
109
|
-
const replyPreview = container?.querySelector(".mw-reply-preview") as HTMLDivElement;
|
|
110
|
-
const replyText = container?.querySelector(".mw-reply-preview-text") as HTMLElement;
|
|
111
|
-
const chatMessagesContainer = container?.querySelector(".mw-chat-messages-con") as HTMLDivElement;
|
|
112
|
-
|
|
113
|
-
if (this.replyingTo) {
|
|
114
|
-
// Show reply preview
|
|
115
|
-
if (replyPreview && replyText) {
|
|
116
|
-
// Truncate content to 50 chars
|
|
117
|
-
const content = this.replyingTo.content.length > 50 ? this.replyingTo.content.substring(0, 50) + "..." : this.replyingTo.content;
|
|
118
|
-
replyText.textContent = content;
|
|
119
|
-
replyPreview.classList.remove("mw-hidden");
|
|
120
|
-
|
|
121
|
-
// Add reply active class to messages container
|
|
122
|
-
if (chatMessagesContainer) {
|
|
123
|
-
chatMessagesContainer.classList.add("mw-reply-active");
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
} else {
|
|
127
|
-
// Hide reply preview
|
|
128
|
-
if (replyPreview) {
|
|
129
|
-
replyPreview.classList.add("mw-hidden");
|
|
130
|
-
|
|
131
|
-
// Remove reply active class from messages container
|
|
132
|
-
if (chatMessagesContainer) {
|
|
133
|
-
chatMessagesContainer.classList.remove("mw-reply-active");
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
export {Chat};
|
|
1
|
+
import {ChatClient, ConversationMessage, EventType} from "@modochats/chat-client";
|
|
2
|
+
import {onSocketConnectionUpdate} from "../socket/utils.js";
|
|
3
|
+
import {Conversation} from "./conversation.js";
|
|
4
|
+
|
|
5
|
+
class Chat {
|
|
6
|
+
private instance?: ChatClient;
|
|
7
|
+
fileMaster: CFileMaster;
|
|
8
|
+
replyMaster: CReplyMaster;
|
|
9
|
+
conversation: Conversation;
|
|
10
|
+
constructor() {
|
|
11
|
+
this.fileMaster = new CFileMaster();
|
|
12
|
+
this.replyMaster = new CReplyMaster();
|
|
13
|
+
this.conversation = new Conversation();
|
|
14
|
+
}
|
|
15
|
+
initInstance() {
|
|
16
|
+
const widget = window.getMWidget?.();
|
|
17
|
+
const savedUUid = localStorage.getItem(`modo-chat:${widget?.chatbot?.uuid}-conversation-uuid`);
|
|
18
|
+
this.instance = new ChatClient({
|
|
19
|
+
chatbotUuid: widget?.chatbot?.uuid as string,
|
|
20
|
+
userData: {uuid: widget?.customerData.uniqueId as string, phoneNumber: widget?.customerData.phoneNumber},
|
|
21
|
+
conversationUUid: savedUUid || undefined
|
|
22
|
+
});
|
|
23
|
+
this.instance.on(EventType.CONVERSATION_SYSTEM_MESSAGE, ev => {
|
|
24
|
+
this.conversation.addSystemMessage(ev.message);
|
|
25
|
+
});
|
|
26
|
+
this.instance.on(EventType.CONVERSATION_MESSAGE, ev => {
|
|
27
|
+
this.conversation.addMessage(ev.message, {incoming: ev.incoming});
|
|
28
|
+
});
|
|
29
|
+
this.instance.on(EventType.SOCKET_CONNECTED, ev => {
|
|
30
|
+
onSocketConnectionUpdate(true);
|
|
31
|
+
});
|
|
32
|
+
this.instance.on(EventType.SOCKET_DISCONNECTED, ev => {
|
|
33
|
+
onSocketConnectionUpdate(false);
|
|
34
|
+
});
|
|
35
|
+
this.instance.on(EventType.CONVERSATION_LOAD, ev => {
|
|
36
|
+
this.conversation.clearContainerEl();
|
|
37
|
+
this.conversation.setStatus();
|
|
38
|
+
this.conversation.onInit();
|
|
39
|
+
|
|
40
|
+
localStorage.setItem(`modo-chat:${widget?.chatbot?.uuid}-conversation-uuid`, this.instance?.conversation?.uuid as string);
|
|
41
|
+
});
|
|
42
|
+
this.instance.on(EventType.CONVERSATION_MESSAGES_CLEAR, () => {
|
|
43
|
+
this.conversation.clearContainerEl();
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
get socket() {
|
|
47
|
+
return this.instance?.socket;
|
|
48
|
+
}
|
|
49
|
+
// conversation data , since the instance only stores and handles data ^^
|
|
50
|
+
get conversationD() {
|
|
51
|
+
return this.instance?.conversation;
|
|
52
|
+
}
|
|
53
|
+
clear() {
|
|
54
|
+
this.conversation.clear();
|
|
55
|
+
this.instance?.clearConversation();
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
sendMessage(...args: Parameters<ChatClient["sendMessage"]>) {
|
|
59
|
+
return this.instance?.sendMessage(...args);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
class CFileMaster {
|
|
63
|
+
file?: File;
|
|
64
|
+
|
|
65
|
+
clearFile() {
|
|
66
|
+
this.file = undefined;
|
|
67
|
+
this.toggleUiState();
|
|
68
|
+
}
|
|
69
|
+
setFile(file: File) {
|
|
70
|
+
this.file = file;
|
|
71
|
+
this.toggleUiState();
|
|
72
|
+
}
|
|
73
|
+
toggleUiState() {
|
|
74
|
+
const container = window.getMWidget?.().container;
|
|
75
|
+
const fileUploadBtn = container?.querySelector(".mw-file-upload-btn") as HTMLButtonElement;
|
|
76
|
+
const fileInput = container?.querySelector(".mw-file-input") as HTMLInputElement;
|
|
77
|
+
const uploadIcon = container?.querySelector(".mw-file-upload-icon") as SVGElement;
|
|
78
|
+
const removeIcon = container?.querySelector(".mw-file-remove-icon") as SVGElement;
|
|
79
|
+
|
|
80
|
+
if (this.file) {
|
|
81
|
+
uploadIcon.classList.add("mw-hidden");
|
|
82
|
+
removeIcon.classList.remove("mw-hidden");
|
|
83
|
+
fileUploadBtn.classList.add("mw-file-uploaded");
|
|
84
|
+
} else {
|
|
85
|
+
fileInput.value = "";
|
|
86
|
+
uploadIcon.classList.remove("mw-hidden");
|
|
87
|
+
removeIcon.classList.add("mw-hidden");
|
|
88
|
+
fileUploadBtn.classList.remove("mw-file-uploaded");
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
class CReplyMaster {
|
|
94
|
+
replyingTo?: ConversationMessage;
|
|
95
|
+
|
|
96
|
+
setReply(message: ConversationMessage) {
|
|
97
|
+
this.replyingTo = message;
|
|
98
|
+
this.updateReplyUI();
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
clearReply() {
|
|
102
|
+
this.replyingTo = undefined;
|
|
103
|
+
|
|
104
|
+
this.updateReplyUI();
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
private updateReplyUI() {
|
|
108
|
+
const container = window.getMWidget?.().container;
|
|
109
|
+
const replyPreview = container?.querySelector(".mw-reply-preview") as HTMLDivElement;
|
|
110
|
+
const replyText = container?.querySelector(".mw-reply-preview-text") as HTMLElement;
|
|
111
|
+
const chatMessagesContainer = container?.querySelector(".mw-chat-messages-con") as HTMLDivElement;
|
|
112
|
+
|
|
113
|
+
if (this.replyingTo) {
|
|
114
|
+
// Show reply preview
|
|
115
|
+
if (replyPreview && replyText) {
|
|
116
|
+
// Truncate content to 50 chars
|
|
117
|
+
const content = this.replyingTo.content.length > 50 ? this.replyingTo.content.substring(0, 50) + "..." : this.replyingTo.content;
|
|
118
|
+
replyText.textContent = content;
|
|
119
|
+
replyPreview.classList.remove("mw-hidden");
|
|
120
|
+
|
|
121
|
+
// Add reply active class to messages container
|
|
122
|
+
if (chatMessagesContainer) {
|
|
123
|
+
chatMessagesContainer.classList.add("mw-reply-active");
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
} else {
|
|
127
|
+
// Hide reply preview
|
|
128
|
+
if (replyPreview) {
|
|
129
|
+
replyPreview.classList.add("mw-hidden");
|
|
130
|
+
|
|
131
|
+
// Remove reply active class from messages container
|
|
132
|
+
if (chatMessagesContainer) {
|
|
133
|
+
chatMessagesContainer.classList.remove("mw-reply-active");
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
export {Chat};
|
|
@@ -1,66 +1,66 @@
|
|
|
1
|
-
class Chatbot {
|
|
2
|
-
name: string;
|
|
3
|
-
image: string;
|
|
4
|
-
shortDescription: string;
|
|
5
|
-
starters: string[] = [];
|
|
6
|
-
voiceChat: boolean;
|
|
7
|
-
createdAt: string;
|
|
8
|
-
updatedAt: string;
|
|
9
|
-
deletedAt: string | null;
|
|
10
|
-
uuid: string;
|
|
11
|
-
allowedHosts: string[] = [];
|
|
12
|
-
id: number;
|
|
13
|
-
greetingMessage?: string;
|
|
14
|
-
uiConfig: {
|
|
15
|
-
primaryColor: string;
|
|
16
|
-
foregroundColor: string;
|
|
17
|
-
theme: "dark" | "light";
|
|
18
|
-
};
|
|
19
|
-
constructor(data: Record<string, any>) {
|
|
20
|
-
this.name = data.name;
|
|
21
|
-
this.image = data.image;
|
|
22
|
-
this.shortDescription = data.short_description;
|
|
23
|
-
this.starters = data.starters;
|
|
24
|
-
this.voiceChat = data.voice_agent;
|
|
25
|
-
this.createdAt = data.setting.created_at;
|
|
26
|
-
this.updatedAt = data.setting.updated_at;
|
|
27
|
-
this.deletedAt = data.setting.deleted_at;
|
|
28
|
-
this.uuid = data.setting.unique_id;
|
|
29
|
-
this.allowedHosts = data.setting.allow_hosts?.split(",") ?? [];
|
|
30
|
-
this.id = data.setting.chatbot;
|
|
31
|
-
this.allowedHosts.push("modochats.com");
|
|
32
|
-
this.uiConfig = {
|
|
33
|
-
primaryColor: data.primary_color,
|
|
34
|
-
foregroundColor: data.foreground_color,
|
|
35
|
-
theme: data.theme
|
|
36
|
-
};
|
|
37
|
-
this.greetingMessage = data.greeting_message;
|
|
38
|
-
}
|
|
39
|
-
showTooltip() {
|
|
40
|
-
const widget = window.getMWidget?.();
|
|
41
|
-
const tooltip = widget?.container?.querySelector(".mw-toggle-tooltip");
|
|
42
|
-
const tooltipText = widget?.container?.querySelector(".mw-toggle-tooltip-text");
|
|
43
|
-
const hasSeen = localStorage.getItem(`modochats:${widget?.publicKey}-has-seen-greeting-message`) === "true";
|
|
44
|
-
|
|
45
|
-
if (tooltip && tooltipText && this.greetingMessage && !hasSeen) {
|
|
46
|
-
// Show the tooltip
|
|
47
|
-
tooltip.classList.remove("mw-hidden");
|
|
48
|
-
|
|
49
|
-
// Update tooltip text with greeting message
|
|
50
|
-
tooltipText.textContent = this.greetingMessage;
|
|
51
|
-
|
|
52
|
-
// Auto-hide after 5 seconds
|
|
53
|
-
// setTimeout(() => {
|
|
54
|
-
// tooltip.classList.add("mw-hidden");
|
|
55
|
-
// }, 5000);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
hideTooltip() {
|
|
59
|
-
const widget = window.getMWidget?.();
|
|
60
|
-
const tooltip = widget?.container?.querySelector(".mw-toggle-tooltip");
|
|
61
|
-
if (tooltip) {
|
|
62
|
-
tooltip.classList.add("mw-hidden");
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
export {Chatbot};
|
|
1
|
+
class Chatbot {
|
|
2
|
+
name: string;
|
|
3
|
+
image: string;
|
|
4
|
+
shortDescription: string;
|
|
5
|
+
starters: string[] = [];
|
|
6
|
+
voiceChat: boolean;
|
|
7
|
+
createdAt: string;
|
|
8
|
+
updatedAt: string;
|
|
9
|
+
deletedAt: string | null;
|
|
10
|
+
uuid: string;
|
|
11
|
+
allowedHosts: string[] = [];
|
|
12
|
+
id: number;
|
|
13
|
+
greetingMessage?: string;
|
|
14
|
+
uiConfig: {
|
|
15
|
+
primaryColor: string;
|
|
16
|
+
foregroundColor: string;
|
|
17
|
+
theme: "dark" | "light";
|
|
18
|
+
};
|
|
19
|
+
constructor(data: Record<string, any>) {
|
|
20
|
+
this.name = data.name;
|
|
21
|
+
this.image = data.image;
|
|
22
|
+
this.shortDescription = data.short_description;
|
|
23
|
+
this.starters = data.starters;
|
|
24
|
+
this.voiceChat = data.voice_agent;
|
|
25
|
+
this.createdAt = data.setting.created_at;
|
|
26
|
+
this.updatedAt = data.setting.updated_at;
|
|
27
|
+
this.deletedAt = data.setting.deleted_at;
|
|
28
|
+
this.uuid = data.setting.unique_id;
|
|
29
|
+
this.allowedHosts = data.setting.allow_hosts?.split(",") ?? [];
|
|
30
|
+
this.id = data.setting.chatbot;
|
|
31
|
+
this.allowedHosts.push("modochats.com");
|
|
32
|
+
this.uiConfig = {
|
|
33
|
+
primaryColor: data.primary_color,
|
|
34
|
+
foregroundColor: data.foreground_color,
|
|
35
|
+
theme: data.theme
|
|
36
|
+
};
|
|
37
|
+
this.greetingMessage = data.greeting_message;
|
|
38
|
+
}
|
|
39
|
+
showTooltip() {
|
|
40
|
+
const widget = window.getMWidget?.();
|
|
41
|
+
const tooltip = widget?.container?.querySelector(".mw-toggle-tooltip");
|
|
42
|
+
const tooltipText = widget?.container?.querySelector(".mw-toggle-tooltip-text");
|
|
43
|
+
const hasSeen = localStorage.getItem(`modochats:${widget?.publicKey}-has-seen-greeting-message`) === "true";
|
|
44
|
+
|
|
45
|
+
if (tooltip && tooltipText && this.greetingMessage && !hasSeen) {
|
|
46
|
+
// Show the tooltip
|
|
47
|
+
tooltip.classList.remove("mw-hidden");
|
|
48
|
+
|
|
49
|
+
// Update tooltip text with greeting message
|
|
50
|
+
tooltipText.textContent = this.greetingMessage;
|
|
51
|
+
|
|
52
|
+
// Auto-hide after 5 seconds
|
|
53
|
+
// setTimeout(() => {
|
|
54
|
+
// tooltip.classList.add("mw-hidden");
|
|
55
|
+
// }, 5000);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
hideTooltip() {
|
|
59
|
+
const widget = window.getMWidget?.();
|
|
60
|
+
const tooltip = widget?.container?.querySelector(".mw-toggle-tooltip");
|
|
61
|
+
if (tooltip) {
|
|
62
|
+
tooltip.classList.add("mw-hidden");
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
export {Chatbot};
|
package/src/services/checker.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {Widget} from "#src/app.js";
|
|
2
|
-
import {parse} from "tldts";
|
|
3
|
-
|
|
4
|
-
const checkIfHostIsAllowed = (widget: Widget) => {
|
|
5
|
-
const currentHost = parse(window.location.origin).hostname;
|
|
6
|
-
const allowedHosts = widget.chatbot?.allowedHosts || [];
|
|
7
|
-
if (currentHost) return allowedHosts.includes(currentHost);
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
export {checkIfHostIsAllowed};
|
|
1
|
+
import {Widget} from "#src/app.js";
|
|
2
|
+
import {parse} from "tldts";
|
|
3
|
+
|
|
4
|
+
const checkIfHostIsAllowed = (widget: Widget) => {
|
|
5
|
+
const currentHost = parse(window.location.origin).hostname;
|
|
6
|
+
const allowedHosts = widget.chatbot?.allowedHosts || [];
|
|
7
|
+
if (currentHost) return allowedHosts.includes(currentHost);
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export {checkIfHostIsAllowed};
|
|
@@ -1,77 +1,77 @@
|
|
|
1
|
-
import {PhoneNumberRegex} from "#src/constants/regex.js";
|
|
2
|
-
|
|
3
|
-
const sendMessage = async (message: string) => {
|
|
4
|
-
if (message.trim().length) {
|
|
5
|
-
if (checkIfUserHasPhoneNumber()) {
|
|
6
|
-
const widget = window.getMWidget?.();
|
|
7
|
-
|
|
8
|
-
if (widget) {
|
|
9
|
-
const savedFile = widget.chat.fileMaster.file;
|
|
10
|
-
const savedReply = widget.chat.replyMaster.replyingTo?.id;
|
|
11
|
-
if (widget?.conversation?.d?.uuid) {
|
|
12
|
-
const chatInput = widget.container?.querySelector(".mw-chat-input") as HTMLInputElement;
|
|
13
|
-
if (chatInput) chatInput.value = "";
|
|
14
|
-
}
|
|
15
|
-
widget.chat.fileMaster.clearFile();
|
|
16
|
-
widget.chat.replyMaster.clearReply();
|
|
17
|
-
await widget?.chat.sendMessage(message, {file: savedFile, replyTo: savedReply});
|
|
18
|
-
} else {
|
|
19
|
-
console.error("Widget instance not found");
|
|
20
|
-
}
|
|
21
|
-
} else {
|
|
22
|
-
throw new Error("User has not submitted the phone number form");
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
const checkIfUserHasPhoneNumber = () => {
|
|
28
|
-
const widget = window.getMWidget?.();
|
|
29
|
-
if (widget?.customerData?.hasSubmittedPhoneForm()) {
|
|
30
|
-
// User has already submitted the phone number form (whether empty or with phone number)
|
|
31
|
-
return true;
|
|
32
|
-
} else {
|
|
33
|
-
// Show phone number form
|
|
34
|
-
switchToPhoneNumberFormView();
|
|
35
|
-
return false;
|
|
36
|
-
}
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
const switchToPhoneNumberFormView = () => {
|
|
40
|
-
const formOverlay = window.getMWidget?.().container?.querySelector(".mw-form-overlay");
|
|
41
|
-
if (formOverlay) {
|
|
42
|
-
formOverlay.classList.remove("mw-hidden");
|
|
43
|
-
formOverlay.classList.add("mw-active");
|
|
44
|
-
}
|
|
45
|
-
};
|
|
46
|
-
const submitPhoneNumberForm = (phoneNumber: string) => {
|
|
47
|
-
// Allow empty phone number or valid phone number
|
|
48
|
-
const parsedPhoneNumber = phoneNumber.replace(/[۰-۹٠-٩]/g, ch => {
|
|
49
|
-
const fa = "۰۱۲۳۴۵۶۷۸۹".indexOf(ch);
|
|
50
|
-
if (fa > -1) return String(fa);
|
|
51
|
-
const ar = "٠١٢٣٤٥٦٧٨٩".indexOf(ch);
|
|
52
|
-
if (ar > -1) return String(ar);
|
|
53
|
-
return ch;
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
if (parsedPhoneNumber.trim() === "" || PhoneNumberRegex.test(parsedPhoneNumber)) {
|
|
57
|
-
const widget = window.getMWidget?.();
|
|
58
|
-
if (widget) {
|
|
59
|
-
// Update the phone number
|
|
60
|
-
widget.customerData.savePhoneNumber(phoneNumber.trim() || undefined);
|
|
61
|
-
|
|
62
|
-
const formOverlay = widget.container?.querySelector(".mw-form-overlay");
|
|
63
|
-
if (formOverlay) {
|
|
64
|
-
formOverlay.classList.remove("mw-active");
|
|
65
|
-
formOverlay.classList.add("mw-hidden");
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
(widget.container?.querySelector(".mw-send-message-btn") as HTMLButtonElement)?.click();
|
|
69
|
-
} else {
|
|
70
|
-
console.error("Widget instance not found");
|
|
71
|
-
}
|
|
72
|
-
} else {
|
|
73
|
-
alert("لطفا شماره تلفن معتبر وارد کنید یا فیلد را خالی بگذارید.");
|
|
74
|
-
}
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
export {sendMessage, submitPhoneNumberForm};
|
|
1
|
+
import {PhoneNumberRegex} from "#src/constants/regex.js";
|
|
2
|
+
|
|
3
|
+
const sendMessage = async (message: string) => {
|
|
4
|
+
if (message.trim().length) {
|
|
5
|
+
if (checkIfUserHasPhoneNumber()) {
|
|
6
|
+
const widget = window.getMWidget?.();
|
|
7
|
+
|
|
8
|
+
if (widget) {
|
|
9
|
+
const savedFile = widget.chat.fileMaster.file;
|
|
10
|
+
const savedReply = widget.chat.replyMaster.replyingTo?.id;
|
|
11
|
+
if (widget?.conversation?.d?.uuid) {
|
|
12
|
+
const chatInput = widget.container?.querySelector(".mw-chat-input") as HTMLInputElement;
|
|
13
|
+
if (chatInput) chatInput.value = "";
|
|
14
|
+
}
|
|
15
|
+
widget.chat.fileMaster.clearFile();
|
|
16
|
+
widget.chat.replyMaster.clearReply();
|
|
17
|
+
await widget?.chat.sendMessage(message, {file: savedFile, replyTo: savedReply});
|
|
18
|
+
} else {
|
|
19
|
+
console.error("Widget instance not found");
|
|
20
|
+
}
|
|
21
|
+
} else {
|
|
22
|
+
throw new Error("User has not submitted the phone number form");
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const checkIfUserHasPhoneNumber = () => {
|
|
28
|
+
const widget = window.getMWidget?.();
|
|
29
|
+
if (widget?.customerData?.hasSubmittedPhoneForm()) {
|
|
30
|
+
// User has already submitted the phone number form (whether empty or with phone number)
|
|
31
|
+
return true;
|
|
32
|
+
} else {
|
|
33
|
+
// Show phone number form
|
|
34
|
+
switchToPhoneNumberFormView();
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const switchToPhoneNumberFormView = () => {
|
|
40
|
+
const formOverlay = window.getMWidget?.().container?.querySelector(".mw-form-overlay");
|
|
41
|
+
if (formOverlay) {
|
|
42
|
+
formOverlay.classList.remove("mw-hidden");
|
|
43
|
+
formOverlay.classList.add("mw-active");
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
const submitPhoneNumberForm = (phoneNumber: string) => {
|
|
47
|
+
// Allow empty phone number or valid phone number
|
|
48
|
+
const parsedPhoneNumber = phoneNumber.replace(/[۰-۹٠-٩]/g, ch => {
|
|
49
|
+
const fa = "۰۱۲۳۴۵۶۷۸۹".indexOf(ch);
|
|
50
|
+
if (fa > -1) return String(fa);
|
|
51
|
+
const ar = "٠١٢٣٤٥٦٧٨٩".indexOf(ch);
|
|
52
|
+
if (ar > -1) return String(ar);
|
|
53
|
+
return ch;
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
if (parsedPhoneNumber.trim() === "" || PhoneNumberRegex.test(parsedPhoneNumber)) {
|
|
57
|
+
const widget = window.getMWidget?.();
|
|
58
|
+
if (widget) {
|
|
59
|
+
// Update the phone number
|
|
60
|
+
widget.customerData.savePhoneNumber(phoneNumber.trim() || undefined);
|
|
61
|
+
|
|
62
|
+
const formOverlay = widget.container?.querySelector(".mw-form-overlay");
|
|
63
|
+
if (formOverlay) {
|
|
64
|
+
formOverlay.classList.remove("mw-active");
|
|
65
|
+
formOverlay.classList.add("mw-hidden");
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
(widget.container?.querySelector(".mw-send-message-btn") as HTMLButtonElement)?.click();
|
|
69
|
+
} else {
|
|
70
|
+
console.error("Widget instance not found");
|
|
71
|
+
}
|
|
72
|
+
} else {
|
|
73
|
+
alert("لطفا شماره تلفن معتبر وارد کنید یا فیلد را خالی بگذارید.");
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
export {sendMessage, submitPhoneNumberForm};
|
|
@@ -1,9 +1,9 @@
|
|
|
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};
|
|
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};
|