Spaces:
Running
Running
Update static/application.js
Browse files- static/application.js +70 -70
static/application.js
CHANGED
@@ -8,18 +8,16 @@ document.addEventListener("DOMContentLoaded", () => {
|
|
8 |
let selectedFile = null;
|
9 |
let filePreviewBubble = null;
|
10 |
|
11 |
-
//
|
12 |
const fileInput = document.createElement("input");
|
13 |
fileInput.type = "file";
|
14 |
fileInput.accept = ".pdf,.docx,.pptx,.xlsx,image/*";
|
15 |
fileInput.style.display = "none";
|
16 |
document.body.appendChild(fileInput);
|
17 |
|
18 |
-
// Handle file icon click
|
19 |
fileBtn.addEventListener("click", () => fileInput.click());
|
20 |
imageBtn.addEventListener("click", () => fileInput.click());
|
21 |
|
22 |
-
// Handle file selection
|
23 |
fileInput.addEventListener("change", () => {
|
24 |
const file = fileInput.files[0];
|
25 |
if (file) {
|
@@ -34,57 +32,57 @@ document.addEventListener("DOMContentLoaded", () => {
|
|
34 |
}
|
35 |
});
|
36 |
|
37 |
-
function createMessageBubble(text, sender = "You", audioSrc = null) {
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
messageRow.style.justifyContent = "space-between";
|
49 |
-
messageRow.style.alignItems = "center";
|
50 |
-
messageRow.style.gap = "8px";
|
51 |
-
|
52 |
-
const messageText = document.createElement("span");
|
53 |
-
messageText.innerText = text;
|
54 |
-
|
55 |
-
messageRow.appendChild(messageText);
|
56 |
-
|
57 |
-
// Only add icon for Chris's answer
|
58 |
-
if (sender === "Chris" && audioSrc) {
|
59 |
-
const icon = document.createElement("i");
|
60 |
-
icon.className = "fa-solid fa-volume-high audio-toggle";
|
61 |
-
icon.style.cursor = "pointer";
|
62 |
-
icon.style.fontSize = "18px";
|
63 |
-
icon.title = "Click to mute";
|
64 |
-
|
65 |
-
let isMuted = false;
|
66 |
-
let audio = new Audio(audioSrc);
|
67 |
-
audio.play();
|
68 |
-
|
69 |
-
icon.addEventListener("click", () => {
|
70 |
-
isMuted = !isMuted;
|
71 |
-
audio.muted = isMuted;
|
72 |
-
icon.classList.toggle("fa-volume-high", !isMuted);
|
73 |
-
icon.classList.toggle("fa-volume-xmark", isMuted);
|
74 |
-
icon.title = isMuted ? "Click to unmute" : "Click to mute";
|
75 |
-
});
|
76 |
-
|
77 |
-
messageRow.appendChild(icon);
|
78 |
-
}
|
79 |
|
80 |
-
|
81 |
-
|
|
|
|
|
|
|
|
|
|
|
82 |
|
83 |
-
|
84 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
85 |
|
86 |
-
|
87 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
88 |
|
89 |
sendBtn.addEventListener("click", async () => {
|
90 |
const question = input.value.trim();
|
@@ -95,16 +93,17 @@ function createMessageBubble(text, sender = "You", audioSrc = null) {
|
|
95 |
return;
|
96 |
}
|
97 |
|
98 |
-
// Remove file preview
|
99 |
if (filePreviewBubble) {
|
100 |
filePreviewBubble.remove();
|
101 |
filePreviewBubble = null;
|
102 |
}
|
103 |
|
104 |
-
|
|
|
105 |
|
106 |
-
//
|
107 |
-
const thinkingBubble = createMessageBubble("Wait ,
|
108 |
|
109 |
const formData = new FormData();
|
110 |
formData.append("question", question);
|
@@ -115,22 +114,26 @@ function createMessageBubble(text, sender = "You", audioSrc = null) {
|
|
115 |
method: "POST",
|
116 |
body: formData
|
117 |
});
|
|
|
118 |
const result = await response.json();
|
|
|
|
|
119 |
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
const audio = document.createElement("audio");
|
124 |
-
audio.src = result.audio;
|
125 |
-
audio.controls = true;
|
126 |
-
audio.autoplay = true;
|
127 |
|
|
|
128 |
const icon = document.createElement("i");
|
129 |
icon.className = "fa-solid fa-volume-high audio-toggle";
|
130 |
icon.title = "Click to mute";
|
131 |
icon.style.cursor = "pointer";
|
|
|
132 |
icon.style.marginLeft = "10px";
|
133 |
|
|
|
|
|
|
|
134 |
icon.addEventListener("click", () => {
|
135 |
audio.muted = !audio.muted;
|
136 |
icon.classList.toggle("fa-volume-high", !audio.muted);
|
@@ -138,16 +141,13 @@ function createMessageBubble(text, sender = "You", audioSrc = null) {
|
|
138 |
icon.title = audio.muted ? "Click to unmute" : "Click to mute";
|
139 |
});
|
140 |
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
audioWrap.appendChild(icon);
|
145 |
-
audioWrap.appendChild(audio);
|
146 |
-
thinkingBubble.appendChild(audioWrap);
|
147 |
}
|
148 |
-
|
149 |
} catch (err) {
|
150 |
-
thinkingBubble.querySelector(".text")
|
|
|
151 |
}
|
152 |
|
153 |
input.value = "";
|
|
|
8 |
let selectedFile = null;
|
9 |
let filePreviewBubble = null;
|
10 |
|
11 |
+
// Hidden file input
|
12 |
const fileInput = document.createElement("input");
|
13 |
fileInput.type = "file";
|
14 |
fileInput.accept = ".pdf,.docx,.pptx,.xlsx,image/*";
|
15 |
fileInput.style.display = "none";
|
16 |
document.body.appendChild(fileInput);
|
17 |
|
|
|
18 |
fileBtn.addEventListener("click", () => fileInput.click());
|
19 |
imageBtn.addEventListener("click", () => fileInput.click());
|
20 |
|
|
|
21 |
fileInput.addEventListener("change", () => {
|
22 |
const file = fileInput.files[0];
|
23 |
if (file) {
|
|
|
32 |
}
|
33 |
});
|
34 |
|
35 |
+
function createMessageBubble(text, sender = "You", audioSrc = null, fileName = null) {
|
36 |
+
const bubble = document.createElement("div");
|
37 |
+
bubble.className = `bubble ${sender === "You" ? "right" : "left"}`;
|
38 |
+
|
39 |
+
const label = document.createElement("div");
|
40 |
+
label.className = "label";
|
41 |
+
label.innerText = sender;
|
42 |
+
|
43 |
+
const message = document.createElement("div");
|
44 |
+
message.className = "text";
|
45 |
+
message.style.whiteSpace = "pre-wrap"; // preserve line breaks
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
46 |
|
47 |
+
if (sender === "You") {
|
48 |
+
let fileLine = fileName ? `📎 Selected file: ${fileName}\n` : "";
|
49 |
+
message.innerText = `${fileLine}❓ ${text}`;
|
50 |
+
} else {
|
51 |
+
message.style.display = "flex";
|
52 |
+
message.style.justifyContent = "space-between";
|
53 |
+
message.style.alignItems = "center";
|
54 |
|
55 |
+
const msgSpan = document.createElement("span");
|
56 |
+
msgSpan.innerText = text;
|
57 |
+
message.appendChild(msgSpan);
|
58 |
+
|
59 |
+
if (audioSrc) {
|
60 |
+
const icon = document.createElement("i");
|
61 |
+
icon.className = "fa-solid fa-volume-high audio-toggle";
|
62 |
+
icon.title = "Click to mute";
|
63 |
+
icon.style.cursor = "pointer";
|
64 |
+
icon.style.fontSize = "18px";
|
65 |
|
66 |
+
const audio = new Audio(audioSrc);
|
67 |
+
audio.play();
|
68 |
+
|
69 |
+
icon.addEventListener("click", () => {
|
70 |
+
audio.muted = !audio.muted;
|
71 |
+
icon.classList.toggle("fa-volume-high", !audio.muted);
|
72 |
+
icon.classList.toggle("fa-volume-xmark", audio.muted);
|
73 |
+
icon.title = audio.muted ? "Click to unmute" : "Click to mute";
|
74 |
+
});
|
75 |
+
|
76 |
+
message.appendChild(icon);
|
77 |
+
}
|
78 |
+
}
|
79 |
+
|
80 |
+
bubble.appendChild(label);
|
81 |
+
bubble.appendChild(message);
|
82 |
+
convo.appendChild(bubble);
|
83 |
+
convo.scrollTop = convo.scrollHeight;
|
84 |
+
return bubble;
|
85 |
+
}
|
86 |
|
87 |
sendBtn.addEventListener("click", async () => {
|
88 |
const question = input.value.trim();
|
|
|
93 |
return;
|
94 |
}
|
95 |
|
96 |
+
// Remove file preview bubble
|
97 |
if (filePreviewBubble) {
|
98 |
filePreviewBubble.remove();
|
99 |
filePreviewBubble = null;
|
100 |
}
|
101 |
|
102 |
+
// User message with file info
|
103 |
+
createMessageBubble(question, "You", null, selectedFile.name);
|
104 |
|
105 |
+
// Chris is thinking...
|
106 |
+
const thinkingBubble = createMessageBubble("Wait , Let me think 🤔...", "Chris");
|
107 |
|
108 |
const formData = new FormData();
|
109 |
formData.append("question", question);
|
|
|
114 |
method: "POST",
|
115 |
body: formData
|
116 |
});
|
117 |
+
|
118 |
const result = await response.json();
|
119 |
+
const answerText = result.answer || "No response.";
|
120 |
+
const audioSrc = result.audio || null;
|
121 |
|
122 |
+
// Replace "Let me think..." with actual answer
|
123 |
+
const message = thinkingBubble.querySelector(".text");
|
124 |
+
message.innerText = answerText;
|
|
|
|
|
|
|
|
|
125 |
|
126 |
+
if (audioSrc) {
|
127 |
const icon = document.createElement("i");
|
128 |
icon.className = "fa-solid fa-volume-high audio-toggle";
|
129 |
icon.title = "Click to mute";
|
130 |
icon.style.cursor = "pointer";
|
131 |
+
icon.style.fontSize = "18px";
|
132 |
icon.style.marginLeft = "10px";
|
133 |
|
134 |
+
const audio = new Audio(audioSrc);
|
135 |
+
audio.play();
|
136 |
+
|
137 |
icon.addEventListener("click", () => {
|
138 |
audio.muted = !audio.muted;
|
139 |
icon.classList.toggle("fa-volume-high", !audio.muted);
|
|
|
141 |
icon.title = audio.muted ? "Click to unmute" : "Click to mute";
|
142 |
});
|
143 |
|
144 |
+
message.style.display = "flex";
|
145 |
+
message.style.justifyContent = "space-between";
|
146 |
+
message.appendChild(icon);
|
|
|
|
|
|
|
147 |
}
|
|
|
148 |
} catch (err) {
|
149 |
+
const message = thinkingBubble.querySelector(".text");
|
150 |
+
message.innerText = "⚠️ Chris had trouble responding.";
|
151 |
}
|
152 |
|
153 |
input.value = "";
|