Hadiil commited on
Commit
144b21b
·
verified ·
1 Parent(s): 773f129

Update static/scripts.js

Browse files
Files changed (1) hide show
  1. static/scripts.js +173 -214
static/scripts.js CHANGED
@@ -1,220 +1,179 @@
1
- document.addEventListener("DOMContentLoaded", () => {
2
- // Elements
3
- const starfield = document.getElementById("starfield")
4
- const ctx = starfield.getContext("2d")
5
- const messages = document.getElementById("messages")
6
- const messageInput = document.getElementById("messageInput")
7
- const sendButton = document.getElementById("sendButton")
8
- const fileInput = document.getElementById("fileInput")
9
- const themeToggle = document.getElementById("themeToggle")
10
- const loader = document.getElementById("loader")
11
- const welcomeMessage = document.getElementById("welcomeMessage")
12
-
13
- // Variables
14
- let stars = []
15
- let selectedFile = null
16
- let isDarkTheme = true
17
-
18
- // Initialize
19
- initStarfield()
20
- animateStars()
21
- setupEventListeners()
22
-
23
- // Functions
24
- function initStarfield() {
25
- starfield.width = window.innerWidth
26
- starfield.height = window.innerHeight
27
-
28
- // Create stars
29
- const starCount = Math.floor((window.innerWidth * window.innerHeight) / 10000)
30
- stars = []
31
-
32
- for (let i = 0; i < starCount; i++) {
33
- stars.push({
34
- x: Math.random() * starfield.width,
35
- y: Math.random() * starfield.height,
36
- radius: Math.random() * 1.5,
37
- opacity: Math.random() * 0.8 + 0.2,
38
- speed: Math.random() * 0.05,
39
- })
40
  }
41
- }
42
-
43
- function animateStars() {
44
- ctx.clearRect(0, 0, starfield.width, starfield.height)
45
-
46
- stars.forEach((star) => {
47
- // Update star position
48
- star.y += star.speed
49
-
50
- // Reset star if it goes off screen
51
- if (star.y > starfield.height) {
52
- star.y = 0
53
- star.x = Math.random() * starfield.width
54
- }
55
-
56
- // Draw star
57
- ctx.beginPath()
58
- ctx.arc(star.x, star.y, star.radius, 0, Math.PI * 2)
59
- ctx.fillStyle = `rgba(var(--star-color), ${star.opacity})`
60
- ctx.fill()
61
- })
62
-
63
- requestAnimationFrame(animateStars)
64
- }
65
-
66
- function setupEventListeners() {
67
- // Send message
68
- sendButton.addEventListener("click", sendMessage)
69
- messageInput.addEventListener("keypress", (e) => {
70
- if (e.key === "Enter") {
71
- e.preventDefault()
72
- sendMessage()
73
- }
74
- })
75
-
76
- // File input
77
- fileInput.addEventListener("change", handleFileSelection)
78
-
79
- // Theme toggle
80
- themeToggle.addEventListener("click", toggleTheme)
81
-
82
- // Window resize
83
- window.addEventListener("resize", initStarfield)
84
-
85
- // Suggestion chips
86
- document.querySelectorAll(".chip").forEach((chip) => {
87
- chip.addEventListener("click", () => {
88
- messageInput.value = chip.textContent.trim()
89
- messageInput.focus()
90
- })
91
- })
92
- }
93
-
94
- function sendMessage() {
95
- const text = messageInput.value.trim()
96
-
97
- if (!text && !selectedFile) return
98
-
99
- // Hide welcome message
100
- welcomeMessage.style.display = "none"
101
-
102
- // Add user message
103
- addMessage(text, true)
104
-
105
- // Clear input
106
- messageInput.value = ""
107
-
108
- // Show loader
109
- loader.classList.add("active")
110
-
111
- // Simulate AI response (replace with actual API call)
112
- setTimeout(() => {
113
- // Hide loader
114
- loader.classList.remove("active")
115
-
116
- // Add AI response
117
- if (selectedFile && selectedFile.type.startsWith("image/")) {
118
- addImageResponse(selectedFile, text)
119
- } else {
120
- const responses = [
121
- "I'm contemplating the vastness of your question. The stars suggest that patience leads to clarity.",
122
- "The cosmos whispers that your inquiry has many facets. Let me illuminate the path forward.",
123
- "Like distant galaxies, your question contains multitudes. Here's what the celestial patterns reveal.",
124
- "The stellar winds bring wisdom: your question touches on fundamental truths about our existence.",
125
- ]
126
-
127
- addMessage(responses[Math.floor(Math.random() * responses.length)])
128
- }
129
-
130
- // Clear selected file
131
- selectedFile = null
132
- if (document.querySelector(".file-preview")) {
133
- document.querySelector(".file-preview").remove()
134
- }
135
- }, 1500)
136
- }
137
-
138
- function addMessage(content, isUser = false) {
139
- if (!content && !isUser) return
140
-
141
- const messageElement = document.createElement("div")
142
- messageElement.className = `message ${isUser ? "user" : "bot"}`
143
- messageElement.textContent = content || "I understand your request. Let me process that for you."
144
-
145
- messages.appendChild(messageElement)
146
- messages.scrollTop = messages.scrollHeight
147
- }
148
-
149
- function addImageResponse(image, query) {
150
- const reader = new FileReader()
151
-
152
- reader.onload = (e) => {
153
- const messageElement = document.createElement("div")
154
- messageElement.className = "message bot"
155
-
156
- const imageResponse = `
157
- <div>I've analyzed the image you shared.</div>
158
- <div class="image-container">
159
- <img src="${e.target.result}" alt="Uploaded image">
160
- </div>
161
- <div style="margin-top: 0.75rem;">
162
- ${query ? `Regarding your question "${query}": ` : ""}
163
- This appears to be an interesting visual. The composition suggests harmony and balance.
164
- </div>
165
- `
166
-
167
- messageElement.innerHTML = imageResponse
168
- messages.appendChild(messageElement)
169
- messages.scrollTop = messages.scrollHeight
170
- }
171
-
172
- reader.readAsDataURL(image)
173
- }
174
 
175
- function handleFileSelection(e) {
176
- const file = e.target.files[0]
177
- if (!file) return
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
178
 
179
- selectedFile = file
 
180
 
181
- // Create file preview
182
- const preview = document.createElement("div")
183
- preview.className = "file-preview"
 
 
 
184
 
185
- let iconClass = "bx-file"
186
- if (file.type.startsWith("image/")) iconClass = "bx-image"
187
- else if (file.name.endsWith(".pdf")) iconClass = "bx-file-pdf"
188
- else if (file.name.endsWith(".xlsx") || file.name.endsWith(".xls")) iconClass = "bx-spreadsheet"
189
- else if (file.name.endsWith(".docx") || file.name.endsWith(".doc")) iconClass = "bx-file-doc"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
190
 
191
- preview.innerHTML = `
192
- <div class="file-preview-icon"><i class="bx ${iconClass}"></i></div>
193
- <div class="file-preview-name">${file.name}</div>
194
- <button class="file-preview-remove"><i class="bx bx-x"></i></button>
195
- `
196
-
197
- // Add preview before input
198
- document.querySelector(".input-container").insertBefore(preview, document.querySelector(".input-wrapper"))
199
-
200
- // Add remove event
201
- preview.querySelector(".file-preview-remove").addEventListener("click", () => {
202
- preview.remove()
203
- fileInput.value = ""
204
- selectedFile = null
205
- })
206
- }
207
-
208
- function toggleTheme() {
209
- document.body.classList.toggle("light-theme")
210
- isDarkTheme = !isDarkTheme
211
-
212
- // Update icon
213
- themeToggle.innerHTML = isDarkTheme ? '<i class="bx bx-moon"></i>' : '<i class="bx bx-sun"></i>'
214
-
215
- // Update star color based on theme
216
- const computedStyle = getComputedStyle(document.documentElement)
217
- const starColor = computedStyle.getPropertyValue("--star-color").trim()
218
- document.documentElement.style.setProperty("--star-color", starColor)
219
- }
220
- })
 
1
+ document.addEventListener('DOMContentLoaded', () => {
2
+ const chatBar = document.getElementById('chatBar');
3
+ const chatInput = document.getElementById('chatInput');
4
+ const sendButton = document.getElementById('sendButton');
5
+ const fileInput = document.getElementById('fileInput');
6
+ const loader = document.getElementById('loader');
7
+ const welcome = document.getElementById('welcome');
8
+
9
+ let selectedFile = null;
10
+
11
+ // Star Animation
12
+ const canvas = document.getElementById('stars');
13
+ const ctx = canvas.getContext('2d');
14
+ canvas.width = window.innerWidth;
15
+ canvas.height = window.innerHeight;
16
+
17
+ const stars = [];
18
+ for (let i = 0; i < 80; i++) {
19
+ stars.push({
20
+ x: Math.random() * canvas.width,
21
+ y: Math.random() * canvas.height,
22
+ radius: Math.random() * 2 + 0.5,
23
+ opacity: Math.random() * 0.5 + 0.4,
24
+ speed: Math.random() * 0.03
25
+ });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
 
28
+ function drawStars() {
29
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
30
+ stars.forEach(star => {
31
+ star.opacity += star.speed;
32
+ if (star.opacity > 1 || star.opacity < 0.4) star.speed *= -1;
33
+ ctx.beginPath();
34
+ ctx.arc(star.x, star.y, star.radius, 0, Math.PI * 2);
35
+ ctx.fillStyle = `rgba(163, 228, 215, ${star.opacity})`;
36
+ ctx.shadowBlur = 10;
37
+ ctx.shadowColor = 'rgba(163, 228, 215, 0.5)';
38
+ ctx.fill();
39
+ });
40
+ requestAnimationFrame(drawStars);
41
+ }
42
+ drawStars();
43
+
44
+ window.addEventListener('resize', () => {
45
+ canvas.width = window.innerWidth;
46
+ canvas.height = window.innerHeight;
47
+ });
48
+
49
+ // Event Listeners
50
+ sendButton.addEventListener('click', processInput);
51
+ chatInput.addEventListener('keypress', (e) => {
52
+ if (e.key === 'Enter') {
53
+ e.preventDefault();
54
+ processInput();
55
+ }
56
+ });
57
+
58
+ fileInput.addEventListener('change', handleFileSelection);
59
+
60
+ chatInput.addEventListener('input', () => {
61
+ welcome.classList.toggle('hidden', chatInput.value.trim().length > 0);
62
+ });
63
+
64
+ document.querySelectorAll('.star-link').forEach(link => {
65
+ link.addEventListener('click', (e) => {
66
+ e.preventDefault();
67
+ const action = link.getAttribute('title');
68
+ if (action === 'Upload') fileInput.click();
69
+ else if (action === 'Translate') chatInput.value = 'Translate to...';
70
+ chatInput.focus();
71
+ });
72
+ });
73
+
74
+ function handleFileSelection(e) {
75
+ const file = e.target.files[0];
76
+ if (!file) return;
77
+
78
+ selectedFile = file;
79
+
80
+ const preview = document.createElement('div');
81
+ preview.className = 'file-preview';
82
+
83
+ let iconClass = 'bx-file';
84
+ if (file.type.startsWith('image/')) iconClass = 'bx-image';
85
+ else if (file.name.endsWith('.pdf')) iconClass = 'bx-file-pdf';
86
+ else if (file.name.endsWith('.xlsx') || file.name.endsWith('.xls')) iconClass = 'bx-spreadsheet';
87
+ else if (file.name.endsWith('.docx') || file.name.endsWith('.doc')) iconClass = 'bx-file-doc';
88
+
89
+ preview.innerHTML = `
90
+ <div class="file-preview-icon"><i class="bx ${iconClass}"></i></div>
91
+ <div class="file-preview-name">${file.name}</div>
92
+ <button class="file-preview-remove"><i class="bx bx-x"></i></button>
93
+ `;
94
 
95
+ chatBar.appendChild(preview);
96
+ chatBar.scrollTop = chatBar.scrollHeight;
97
 
98
+ preview.querySelector('.file-preview-remove').addEventListener('click', () => {
99
+ preview.remove();
100
+ fileInput.value = '';
101
+ selectedFile = null;
102
+ });
103
+ }
104
 
105
+ async function processInput() {
106
+ const text = chatInput.value.trim();
107
+ const file = selectedFile;
108
+
109
+ if (!text && !file) return;
110
+
111
+ sendButton.disabled = true;
112
+ loader.classList.add('active');
113
+
114
+ if (text) addMessage(text, true);
115
+ if (file) addMessage(`Beaming up: ${file.name}`, true);
116
+
117
+ chatInput.value = '';
118
+ selectedFile = null;
119
+
120
+ try {
121
+ const formData = new FormData();
122
+ if (file) formData.append('file', file);
123
+ if (text) formData.append('text', text);
124
+
125
+ const response = await fetch('/process', {
126
+ method: 'POST',
127
+ body: formData
128
+ });
129
+
130
+ if (!response.ok) throw new Error(`Cosmic glitch: ${response.status}`);
131
+
132
+ const data = await response.json();
133
+
134
+ if (data.type === 'visual_qa' && file && file.type.startsWith('image/')) {
135
+ const reader = new FileReader();
136
+ reader.onload = () => {
137
+ addMessage(`
138
+ <div class="vqa-response">
139
+ <img src="${reader.result}" class="uploaded-image">
140
+ <div class="vqa-text">
141
+ <p><strong>You asked:</strong> ${text}</p>
142
+ <p><strong>I see:</strong> ${data.response}</p>
143
+ </div>
144
+ </div>`, false, true);
145
+ };
146
+ reader.readAsDataURL(file);
147
+ } else if (data.type === 'caption' && file && file.type.startsWith('image/')) {
148
+ const reader = new FileReader();
149
+ reader.onload = () => {
150
+ addMessage(`
151
+ <div class="image-result">
152
+ <img src="${reader.result}" class="uploaded-image">
153
+ <div class="image-caption">${data.response}</div>
154
+ </div>`, false, true);
155
+ };
156
+ reader.readAsDataURL(file);
157
+ } else if (data.type === 'visualization_code') {
158
+ addMessage(`<pre>${data.response}</pre>`, false, true);
159
+ } else {
160
+ addMessage(data.response);
161
+ }
162
+ } catch (error) {
163
+ console.error('Error:', error);
164
+ addMessage(`Oops, a starry hiccup: ${error.message}`);
165
+ } finally {
166
+ sendButton.disabled = false;
167
+ loader.classList.remove('active');
168
+ }
169
+ }
170
 
171
+ function addMessage(content, isUser = false, isHTML = false) {
172
+ const message = document.createElement('div');
173
+ message.className = `chat-message ${isUser ? 'user' : 'bot'}`;
174
+ if (isHTML) message.innerHTML = content;
175
+ else message.textContent = content;
176
+ chatBar.appendChild(message);
177
+ chatBar.scrollTop = chatBar.scrollHeight;
178
+ }
179
+ });