223 lines
6.0 KiB
JavaScript
223 lines
6.0 KiB
JavaScript
(() => {
|
|
// Utils
|
|
function scrollElementToEnd(ele) {
|
|
ele.scrollTop = ele.scrollHeight;
|
|
}
|
|
|
|
let messageIdCounter = 0;
|
|
function makeChatMessage(messageContent, messageType) {
|
|
return JSON.stringify({
|
|
user: {
|
|
id: "FakeUserID",
|
|
},
|
|
chat: {
|
|
id: "FakeChatID",
|
|
},
|
|
message: {
|
|
type: messageType,
|
|
content: messageContent,
|
|
id: `FakeMessageID_${messageIdCounter++}`,
|
|
},
|
|
});
|
|
}
|
|
|
|
let socketIoAddr = document.location.origin;
|
|
let socket = io(socketIoAddr);
|
|
let status = document.getElementById("status");
|
|
let input = document.getElementById("input");
|
|
let sendButton = document.getElementById("send_button");
|
|
let resetButton = document.getElementById("reset_button");
|
|
let testButton = document.getElementById("test_button");
|
|
|
|
let testContentArray = [
|
|
"What's the date today?",
|
|
"Who are you?",
|
|
"What technology are you based on?",
|
|
"Generate a picture of a panda.",
|
|
"I need the panda in a house.",
|
|
"Tell me about the newest videos of @tiabtc.",
|
|
"Give me a summary of the latest video above.",
|
|
"What this video is talking about: https://www.youtube.com/watch?v=HtcPWORWJ1U",
|
|
"Remind me to go shopping tomorrow 6pm.",
|
|
"What reminders do I currently have?",
|
|
"Tweet out: Hello, this is a message from AI.",
|
|
]
|
|
const mdCvt = new showdown.Converter({
|
|
tables: true,
|
|
});
|
|
|
|
function appendChatItem(who, msg) {
|
|
let item = document.createElement("li");
|
|
if (who == "me") {
|
|
item.classList.add("align_right");
|
|
}
|
|
item.innerHTML = msg;
|
|
messages.appendChild(item);
|
|
scrollElementToEnd(messages);
|
|
}
|
|
|
|
let isProcessing = false;
|
|
let notification = "";
|
|
function startProcessing() {
|
|
notification = "";
|
|
isProcessing = true;
|
|
|
|
let dotCount = 0;
|
|
|
|
scrollElementToEnd(messages);
|
|
|
|
let inter = setInterval(() => {
|
|
if (!isProcessing) {
|
|
status.classList.add("hidden");
|
|
clearInterval(inter);
|
|
return;
|
|
}
|
|
status.classList.remove("hidden");
|
|
status.innerHTML = notification;
|
|
if (notification.length > 0) {
|
|
status.innerHTML += "<br/>";
|
|
}
|
|
status.innerHTML += "Processing";
|
|
for (let i = 0; i < dotCount; ++i) {
|
|
status.innerHTML += ".";
|
|
}
|
|
dotCount += 1;
|
|
if (dotCount == 4) {
|
|
dotCount = 0;
|
|
}
|
|
}, 500);
|
|
}
|
|
function stopProcessing() {
|
|
isProcessing = false;
|
|
}
|
|
|
|
socket.on("chat_message", (msg) => {
|
|
if (typeof(msg) !== 'object') {
|
|
console.log("Expecting object, got: ", msg);
|
|
return;
|
|
}
|
|
let msgType = msg.message.type;
|
|
let msgContent = msg.message.content;
|
|
switch (msgType) {
|
|
case "text":
|
|
msgContent = msgContent.replaceAll('\n', '<br/>');
|
|
console.log("text message: " + msgContent);
|
|
appendChatItem("remote", msgContent);
|
|
break;
|
|
case "image": {
|
|
var item = document.createElement("li");
|
|
item.innerHTML = `<img src="data:image/png;base64,${msgContent}" alt="Image" class="replied-img">`;
|
|
messages.appendChild(item);
|
|
scrollElementToEnd(messages);
|
|
break;
|
|
}
|
|
case "markdown": {
|
|
const item = document.createElement("li");
|
|
console.log(msgContent);
|
|
item.innerHTML = mdCvt.makeHtml(msgContent);
|
|
messages.appendChild(item);
|
|
scrollElementToEnd(messages);
|
|
break;
|
|
}
|
|
case "notification": {
|
|
notification = msgContent;
|
|
break;
|
|
}
|
|
case "end": {
|
|
stopProcessing();
|
|
break;
|
|
}
|
|
}
|
|
});
|
|
socket.on("connect", () => {
|
|
let tzOffset = `${-new Date().getTimezoneOffset()/60}`;
|
|
socket.emit("chat_message", makeChatMessage(tzOffset, 'set_ts_offset'));
|
|
});
|
|
socket.on("disconnect", (reason) => {
|
|
console.log("Disconnect due to: ", reason)
|
|
});
|
|
|
|
function submitMessage() {
|
|
if (input.value) {
|
|
socket.emit(
|
|
"chat_message",
|
|
makeChatMessage(input.value, 'text')
|
|
);
|
|
appendChatItem("me", input.value);
|
|
startProcessing();
|
|
input.value = "";
|
|
}
|
|
}
|
|
sendButton.addEventListener('click', function (e) {
|
|
submitMessage();
|
|
});
|
|
resetButton.addEventListener('click', function(e) {
|
|
socket.emit('chat_message', makeChatMessage('', 'clear'));
|
|
stopProcessing();
|
|
messages.innerHTML = "";
|
|
})
|
|
testButton.addEventListener('click', function(e) {
|
|
let index = 0;
|
|
let isWaitingForResponse = false;
|
|
|
|
function sendNextMessage() {
|
|
if (index < testContentArray.length && !isWaitingForResponse) {
|
|
input.value = testContentArray[index];
|
|
submitMessage();
|
|
index++;
|
|
isWaitingForResponse = true;
|
|
}
|
|
}
|
|
|
|
socket.on("chat_message", function(msg) {
|
|
if (isWaitingForResponse) {
|
|
if (msg.message.type === 'end') {
|
|
isWaitingForResponse = false;
|
|
sendNextMessage();
|
|
} else {
|
|
// Jarvis have not finish his reply, just wait
|
|
}
|
|
}
|
|
});
|
|
|
|
sendNextMessage();
|
|
});
|
|
|
|
input.addEventListener('keyup', function (e) {
|
|
if (e.key === 'Enter') {
|
|
submitMessage();
|
|
}
|
|
});
|
|
|
|
input.addEventListener('drop', function(e) {
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
|
|
const files = e.dataTransfer.files;
|
|
for (let i = 0; i < files.length; i++) {
|
|
const file = files[i];
|
|
const reader = new FileReader();
|
|
reader.onload = function(e) {
|
|
const file = e.currentTarget.result;
|
|
if (file.startsWith('data:image')) {
|
|
const base64Index = file.indexOf('base64,');
|
|
const base64Content = file.substring(base64Index + 7)
|
|
// Send to jarvis
|
|
socket.emit(
|
|
"chat_message",
|
|
makeChatMessage(base64Content, 'image')
|
|
);
|
|
|
|
// display on the page
|
|
var item = document.createElement("li");
|
|
item.innerHTML = `<img src="${file}" alt="Image" class="replied-img">`;
|
|
item.classList.add("align_right");
|
|
messages.appendChild(item);
|
|
scrollElementToEnd(messages);
|
|
}
|
|
};
|
|
reader.readAsDataURL(file);
|
|
}
|
|
});
|
|
})();
|