Athspi commited on
Commit
c6db92f
·
verified ·
1 Parent(s): 1d2d978

Update static/index.html

Browse files
Files changed (1) hide show
  1. static/index.html +11 -50
static/index.html CHANGED
@@ -21,18 +21,15 @@
21
  --link-color: #64b5f6;
22
  --quote-color: #4CAF50;
23
  }
24
-
25
  * {
26
  box-sizing: border-box;
27
  margin: 0;
28
  padding: 0;
29
  }
30
-
31
  html, body {
32
  height: 100%;
33
  overflow: hidden;
34
  }
35
-
36
  body {
37
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
38
  background-color: var(--background-color);
@@ -42,7 +39,6 @@
42
  height: 100%;
43
  line-height: 1.6;
44
  }
45
-
46
  .chat-container {
47
  display: flex;
48
  flex-direction: column;
@@ -53,7 +49,6 @@
53
  border-left: 1px solid var(--border-color);
54
  border-right: 1px solid var(--border-color);
55
  }
56
-
57
  .chat-area {
58
  flex-grow: 1;
59
  overflow-y: auto;
@@ -61,29 +56,24 @@
61
  display: flex;
62
  flex-direction: column;
63
  }
64
-
65
  .welcome-screen {
66
  text-align: center;
67
  margin: auto;
68
  color: var(--placeholder-color);
69
  padding: 20px;
70
  }
71
-
72
  .welcome-screen h2 {
73
  font-size: 1.8rem;
74
  font-weight: 400;
75
  margin-bottom: 10px;
76
  }
77
-
78
  .welcome-screen p {
79
  font-size: 1rem;
80
  line-height: 1.5;
81
  }
82
-
83
  .welcome-screen.hidden {
84
  display: none;
85
  }
86
-
87
  .message {
88
  max-width: 85%;
89
  padding: 12px 16px;
@@ -95,20 +85,17 @@
95
  position: relative;
96
  animation: fadeIn 0.3s ease-out;
97
  }
98
-
99
  .user-message {
100
  background-color: var(--user-bubble-color);
101
  align-self: flex-end;
102
  border-bottom-right-radius: 4px;
103
  }
104
-
105
  .ai-message {
106
  background-color: var(--ai-bubble-color);
107
  align-self: flex-start;
108
  border-bottom-left-radius: 4px;
109
  padding-bottom: 30px;
110
  }
111
-
112
  .ai-message-content {
113
  overflow: hidden;
114
  }
@@ -148,7 +135,6 @@
148
  background-color: transparent;
149
  color: inherit;
150
  }
151
-
152
  .audio-button {
153
  position: absolute;
154
  bottom: 6px;
@@ -192,7 +178,6 @@
192
  .audio-button.loading .loader {
193
  display: block;
194
  }
195
-
196
  .download-button {
197
  position: absolute;
198
  bottom: 6px;
@@ -221,12 +206,10 @@
221
  .download-button:hover svg {
222
  fill: #4CAF50;
223
  }
224
-
225
  @keyframes spin {
226
  0% { transform: rotate(0deg); }
227
  100% { transform: rotate(360deg); }
228
  }
229
-
230
  .typing-indicator {
231
  display: flex;
232
  align-items: center;
@@ -238,12 +221,10 @@
238
  }
239
  .typing-indicator span:nth-child(2) { animation-delay: 0.2s; }
240
  .typing-indicator span:nth-child(3) { animation-delay: 0.4s; }
241
-
242
  @keyframes bounce {
243
  0%, 80%, 100% { transform: scale(0); }
244
  40% { transform: scale(1.0); }
245
  }
246
-
247
  .input-area {
248
  display: flex;
249
  align-items: flex-end;
@@ -275,7 +256,6 @@
275
  outline: none;
276
  }
277
  .input-area textarea::placeholder { color: var(--placeholder-color); }
278
-
279
  .input-area .icon-button {
280
  background: none;
281
  border: none;
@@ -290,7 +270,6 @@
290
  opacity: 0.8;
291
  }
292
  .input-area .icon-button svg { width: 24px; height: 24px; fill: var(--icon-color); }
293
-
294
  .send-button {
295
  background-color: var(--send-button-color);
296
  border-radius: 50%;
@@ -306,7 +285,6 @@
306
  fill: #888;
307
  }
308
  .send-button svg { fill: white; width: 24px; height: 24px; }
309
-
310
  @keyframes fadeIn {
311
  from { opacity: 0; transform: translateY(10px); }
312
  to { opacity: 1; transform: translateY(0); }
@@ -322,7 +300,6 @@
322
  <p>For audio responses, try: <em>"Tell me a bedtime story with audio"</em></p>
323
  </div>
324
  </main>
325
-
326
  <footer class="input-area">
327
  <form id="chat-form" class="input-wrapper">
328
  <textarea id="message-input" placeholder="Ask anything..." rows="1"></textarea>
@@ -340,7 +317,6 @@
340
  const chatArea = document.querySelector('.chat-area');
341
  const welcomeScreen = document.querySelector('.welcome-screen');
342
  const sendButton = document.getElementById('send-button');
343
-
344
  let currentAudio = null;
345
 
346
  const adjustTextareaHeight = () => {
@@ -354,17 +330,16 @@
354
  sendButton.classList.toggle('disabled', isDisabled);
355
  sendButton.disabled = isDisabled;
356
  };
357
-
358
  const scrollToBottom = () => {
359
  chatArea.scrollTop = chatArea.scrollHeight;
360
  };
361
 
362
  const addMessage = (content, sender, isHTML = false, audioFilename = null) => {
363
  welcomeScreen.classList.add('hidden');
364
-
365
  const messageElement = document.createElement('div');
366
  messageElement.classList.add('message', `${sender}-message`);
367
-
368
  const contentDiv = document.createElement('div');
369
  if (isHTML) {
370
  contentDiv.classList.add(`${sender}-message-content`);
@@ -375,7 +350,7 @@
375
  messageElement.appendChild(contentDiv);
376
 
377
  if (sender === 'ai' && audioFilename) {
378
- // Add download button
379
  const downloadButton = document.createElement('button');
380
  downloadButton.classList.add('download-button');
381
  downloadButton.title = "Download audio";
@@ -388,8 +363,8 @@
388
  window.location.href = `/download/${audioFilename}`;
389
  });
390
  messageElement.appendChild(downloadButton);
391
-
392
- // Add play button
393
  const playButton = document.createElement('button');
394
  playButton.classList.add('audio-button');
395
  playButton.dataset.audioUrl = `/static/audio/${audioFilename}`;
@@ -405,16 +380,16 @@
405
  playAudio(e.currentTarget, url);
406
  });
407
  messageElement.appendChild(playButton);
408
-
409
- // Auto-play audio
410
  setTimeout(() => playButton.click(), 300);
411
  }
412
-
413
  chatArea.appendChild(messageElement);
414
  scrollToBottom();
415
  return messageElement;
416
  };
417
-
418
  const showTypingIndicator = () => {
419
  const indicatorElement = document.createElement('div');
420
  indicatorElement.classList.add('message', 'ai-message', 'typing-indicator');
@@ -430,29 +405,23 @@
430
  currentAudio.currentTime = 0;
431
  currentAudio = null;
432
  }
433
-
434
  buttonElement.classList.add('loading');
435
  buttonElement.disabled = true;
436
-
437
  try {
438
  if (!audioUrl) throw new Error("No audio available");
439
-
440
  currentAudio = new Audio(audioUrl);
441
  currentAudio.play();
442
-
443
  currentAudio.onended = () => {
444
  buttonElement.classList.remove('loading');
445
  buttonElement.disabled = false;
446
  currentAudio = null;
447
  };
448
-
449
  currentAudio.onerror = () => {
450
  console.error("Error playing audio");
451
  buttonElement.classList.remove('loading');
452
  buttonElement.disabled = false;
453
  currentAudio = null;
454
  };
455
-
456
  } catch (error) {
457
  console.error("Audio error:", error);
458
  alert("Failed to play audio. " + (error.message || "Please try again."));
@@ -463,28 +432,23 @@
463
 
464
  const getAIResponse = async (userMessage) => {
465
  const indicator = showTypingIndicator();
466
-
467
  try {
468
  const response = await fetch('/chat', {
469
  method: 'POST',
470
  headers: { 'Content-Type': 'application/json' },
471
  body: JSON.stringify({ message: userMessage })
472
  });
473
-
474
  const data = await response.json();
475
-
476
  if (data.error) {
477
  throw new Error(data.error);
478
  }
479
-
480
  chatArea.removeChild(indicator);
481
  addMessage(
482
- data.response_html,
483
- 'ai',
484
  true,
485
  data.audio_filename
486
  );
487
-
488
  } catch (error) {
489
  chatArea.removeChild(indicator);
490
  addMessage("Sorry, I encountered an error. Please try again.", 'ai');
@@ -495,12 +459,10 @@
495
  chatForm.addEventListener('submit', async (e) => {
496
  e.preventDefault();
497
  const message = messageInput.value.trim();
498
-
499
  if (message) {
500
  addMessage(message, 'user');
501
  messageInput.value = '';
502
  adjustTextareaHeight();
503
-
504
  await getAIResponse(message);
505
  }
506
  });
@@ -513,7 +475,6 @@
513
  });
514
 
515
  messageInput.addEventListener('input', adjustTextareaHeight);
516
-
517
  updateSendButtonState();
518
  messageInput.focus();
519
  });
 
21
  --link-color: #64b5f6;
22
  --quote-color: #4CAF50;
23
  }
 
24
  * {
25
  box-sizing: border-box;
26
  margin: 0;
27
  padding: 0;
28
  }
 
29
  html, body {
30
  height: 100%;
31
  overflow: hidden;
32
  }
 
33
  body {
34
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
35
  background-color: var(--background-color);
 
39
  height: 100%;
40
  line-height: 1.6;
41
  }
 
42
  .chat-container {
43
  display: flex;
44
  flex-direction: column;
 
49
  border-left: 1px solid var(--border-color);
50
  border-right: 1px solid var(--border-color);
51
  }
 
52
  .chat-area {
53
  flex-grow: 1;
54
  overflow-y: auto;
 
56
  display: flex;
57
  flex-direction: column;
58
  }
 
59
  .welcome-screen {
60
  text-align: center;
61
  margin: auto;
62
  color: var(--placeholder-color);
63
  padding: 20px;
64
  }
 
65
  .welcome-screen h2 {
66
  font-size: 1.8rem;
67
  font-weight: 400;
68
  margin-bottom: 10px;
69
  }
 
70
  .welcome-screen p {
71
  font-size: 1rem;
72
  line-height: 1.5;
73
  }
 
74
  .welcome-screen.hidden {
75
  display: none;
76
  }
 
77
  .message {
78
  max-width: 85%;
79
  padding: 12px 16px;
 
85
  position: relative;
86
  animation: fadeIn 0.3s ease-out;
87
  }
 
88
  .user-message {
89
  background-color: var(--user-bubble-color);
90
  align-self: flex-end;
91
  border-bottom-right-radius: 4px;
92
  }
 
93
  .ai-message {
94
  background-color: var(--ai-bubble-color);
95
  align-self: flex-start;
96
  border-bottom-left-radius: 4px;
97
  padding-bottom: 30px;
98
  }
 
99
  .ai-message-content {
100
  overflow: hidden;
101
  }
 
135
  background-color: transparent;
136
  color: inherit;
137
  }
 
138
  .audio-button {
139
  position: absolute;
140
  bottom: 6px;
 
178
  .audio-button.loading .loader {
179
  display: block;
180
  }
 
181
  .download-button {
182
  position: absolute;
183
  bottom: 6px;
 
206
  .download-button:hover svg {
207
  fill: #4CAF50;
208
  }
 
209
  @keyframes spin {
210
  0% { transform: rotate(0deg); }
211
  100% { transform: rotate(360deg); }
212
  }
 
213
  .typing-indicator {
214
  display: flex;
215
  align-items: center;
 
221
  }
222
  .typing-indicator span:nth-child(2) { animation-delay: 0.2s; }
223
  .typing-indicator span:nth-child(3) { animation-delay: 0.4s; }
 
224
  @keyframes bounce {
225
  0%, 80%, 100% { transform: scale(0); }
226
  40% { transform: scale(1.0); }
227
  }
 
228
  .input-area {
229
  display: flex;
230
  align-items: flex-end;
 
256
  outline: none;
257
  }
258
  .input-area textarea::placeholder { color: var(--placeholder-color); }
 
259
  .input-area .icon-button {
260
  background: none;
261
  border: none;
 
270
  opacity: 0.8;
271
  }
272
  .input-area .icon-button svg { width: 24px; height: 24px; fill: var(--icon-color); }
 
273
  .send-button {
274
  background-color: var(--send-button-color);
275
  border-radius: 50%;
 
285
  fill: #888;
286
  }
287
  .send-button svg { fill: white; width: 24px; height: 24px; }
 
288
  @keyframes fadeIn {
289
  from { opacity: 0; transform: translateY(10px); }
290
  to { opacity: 1; transform: translateY(0); }
 
300
  <p>For audio responses, try: <em>"Tell me a bedtime story with audio"</em></p>
301
  </div>
302
  </main>
 
303
  <footer class="input-area">
304
  <form id="chat-form" class="input-wrapper">
305
  <textarea id="message-input" placeholder="Ask anything..." rows="1"></textarea>
 
317
  const chatArea = document.querySelector('.chat-area');
318
  const welcomeScreen = document.querySelector('.welcome-screen');
319
  const sendButton = document.getElementById('send-button');
 
320
  let currentAudio = null;
321
 
322
  const adjustTextareaHeight = () => {
 
330
  sendButton.classList.toggle('disabled', isDisabled);
331
  sendButton.disabled = isDisabled;
332
  };
333
+
334
  const scrollToBottom = () => {
335
  chatArea.scrollTop = chatArea.scrollHeight;
336
  };
337
 
338
  const addMessage = (content, sender, isHTML = false, audioFilename = null) => {
339
  welcomeScreen.classList.add('hidden');
 
340
  const messageElement = document.createElement('div');
341
  messageElement.classList.add('message', `${sender}-message`);
342
+
343
  const contentDiv = document.createElement('div');
344
  if (isHTML) {
345
  contentDiv.classList.add(`${sender}-message-content`);
 
350
  messageElement.appendChild(contentDiv);
351
 
352
  if (sender === 'ai' && audioFilename) {
353
+ // Download button
354
  const downloadButton = document.createElement('button');
355
  downloadButton.classList.add('download-button');
356
  downloadButton.title = "Download audio";
 
363
  window.location.href = `/download/${audioFilename}`;
364
  });
365
  messageElement.appendChild(downloadButton);
366
+
367
+ // Play button
368
  const playButton = document.createElement('button');
369
  playButton.classList.add('audio-button');
370
  playButton.dataset.audioUrl = `/static/audio/${audioFilename}`;
 
380
  playAudio(e.currentTarget, url);
381
  });
382
  messageElement.appendChild(playButton);
383
+
384
+ // Auto-play first AI audio
385
  setTimeout(() => playButton.click(), 300);
386
  }
387
+
388
  chatArea.appendChild(messageElement);
389
  scrollToBottom();
390
  return messageElement;
391
  };
392
+
393
  const showTypingIndicator = () => {
394
  const indicatorElement = document.createElement('div');
395
  indicatorElement.classList.add('message', 'ai-message', 'typing-indicator');
 
405
  currentAudio.currentTime = 0;
406
  currentAudio = null;
407
  }
 
408
  buttonElement.classList.add('loading');
409
  buttonElement.disabled = true;
 
410
  try {
411
  if (!audioUrl) throw new Error("No audio available");
 
412
  currentAudio = new Audio(audioUrl);
413
  currentAudio.play();
 
414
  currentAudio.onended = () => {
415
  buttonElement.classList.remove('loading');
416
  buttonElement.disabled = false;
417
  currentAudio = null;
418
  };
 
419
  currentAudio.onerror = () => {
420
  console.error("Error playing audio");
421
  buttonElement.classList.remove('loading');
422
  buttonElement.disabled = false;
423
  currentAudio = null;
424
  };
 
425
  } catch (error) {
426
  console.error("Audio error:", error);
427
  alert("Failed to play audio. " + (error.message || "Please try again."));
 
432
 
433
  const getAIResponse = async (userMessage) => {
434
  const indicator = showTypingIndicator();
 
435
  try {
436
  const response = await fetch('/chat', {
437
  method: 'POST',
438
  headers: { 'Content-Type': 'application/json' },
439
  body: JSON.stringify({ message: userMessage })
440
  });
 
441
  const data = await response.json();
 
442
  if (data.error) {
443
  throw new Error(data.error);
444
  }
 
445
  chatArea.removeChild(indicator);
446
  addMessage(
447
+ data.response_html,
448
+ 'ai',
449
  true,
450
  data.audio_filename
451
  );
 
452
  } catch (error) {
453
  chatArea.removeChild(indicator);
454
  addMessage("Sorry, I encountered an error. Please try again.", 'ai');
 
459
  chatForm.addEventListener('submit', async (e) => {
460
  e.preventDefault();
461
  const message = messageInput.value.trim();
 
462
  if (message) {
463
  addMessage(message, 'user');
464
  messageInput.value = '';
465
  adjustTextareaHeight();
 
466
  await getAIResponse(message);
467
  }
468
  });
 
475
  });
476
 
477
  messageInput.addEventListener('input', adjustTextareaHeight);
 
478
  updateSendButtonState();
479
  messageInput.focus();
480
  });