Athspi commited on
Commit
51b17f6
Β·
verified Β·
1 Parent(s): 76141c4

Update static/index.html

Browse files
Files changed (1) hide show
  1. static/index.html +62 -51
static/index.html CHANGED
@@ -289,15 +289,12 @@
289
  <div class="welcome-screen">
290
  <h2>Welcome to Athspi!</h2>
291
  <p>Hello! I'm your AI assistant Athspi powered by Gemini. Ask me anything - I can explain concepts, generate ideas, or help with coding!</p>
292
- <p>Try asking me something like: <em>"Explain quantum computing in simple terms"</em> or <em>"Help me debug this Python code"</em></p>
293
  </div>
294
  </main>
295
 
296
  <footer class="input-area">
297
  <form id="chat-form" class="input-wrapper">
298
- <button type="button" class="icon-button" id="attach-button">
299
- <svg viewBox="0 0 24 24"><path d="M16.5 6v11.5c0 2.21-1.79 4-4 4s-4-1.79-4-4V5a2.5 2.5 0 0 1 5 0v10.5c0 .83-.67 1.5-1.5 1.5s-1.5-.67-1.5-1.5V6H10v9.5a2.5 2.5 0 0 0 5 0V5c-1.38 0-2.5 1.12-2.5 2.5v10.5c0 1.38-1.12 2.5-2.5 2.5s-2.5-1.12-2.5-2.5V5a4 4 0 0 1 8 0v11.5c-1.1 0-2-.9-2-2V6h-1.5z"></path></svg>
300
- </button>
301
  <textarea id="message-input" placeholder="Ask anything..." rows="1"></textarea>
302
  <button type="submit" id="send-button" class="icon-button send-button disabled">
303
  <svg viewBox="0 0 24 24"><path d="M2 21l21-9L2 3v7l15 2-15 2v7z"></path></svg>
@@ -313,7 +310,6 @@
313
  const chatArea = document.querySelector('.chat-area');
314
  const welcomeScreen = document.querySelector('.welcome-screen');
315
  const sendButton = document.getElementById('send-button');
316
- const attachButton = document.getElementById('attach-button');
317
 
318
  let currentAudio = null;
319
 
@@ -333,7 +329,7 @@
333
  chatArea.scrollTop = chatArea.scrollHeight;
334
  };
335
 
336
- const addMessage = (content, sender, isHTML = false, plainText = '') => {
337
  welcomeScreen.classList.add('hidden');
338
 
339
  const messageElement = document.createElement('div');
@@ -348,19 +344,30 @@
348
  }
349
  messageElement.appendChild(contentDiv);
350
 
351
- if (sender === 'ai' && plainText) {
352
- const audioButton = document.createElement('button');
353
- audioButton.classList.add('audio-button');
354
- audioButton.dataset.plainText = plainText;
355
- audioButton.innerHTML = `
356
- <svg class="speaker-icon" viewBox="0 0 24 24">
357
- <path d="M3 10v4c0 .55.45 1 1 1h3.5l5.5 5V5L7.5 9H4c-.55 0-1 .45-1 1zm14 0h-1.5c-2.31 0-4.22-1.74-4.47-4H10v12h1.5v-2.22c.25-2.26 2.16-4.22 4.47-4.22H17c1.1 0 2 .9 2 2s-.9 2-2 2h-1.5v2H17c2.21 0 4-1.79 4-4s-1.79-4-4-4z"/>
358
- </svg>
359
- <div class="loader"></div>
360
- `;
361
- audioButton.title = "Listen to response";
362
- audioButton.addEventListener('click', () => playAudio(audioButton, plainText));
363
- messageElement.appendChild(audioButton);
 
 
 
 
 
 
 
 
 
 
 
364
  }
365
 
366
  chatArea.appendChild(messageElement);
@@ -377,7 +384,7 @@
377
  return indicatorElement;
378
  };
379
 
380
- const playAudio = async (buttonElement, text) => {
381
  if (currentAudio) {
382
  currentAudio.pause();
383
  currentAudio.currentTime = 0;
@@ -388,19 +395,23 @@
388
  buttonElement.disabled = true;
389
 
390
  try {
391
- const response = await fetch('/generate-audio', {
392
- method: 'POST',
393
- headers: { 'Content-Type': 'application/json' },
394
- body: JSON.stringify({ text: text })
395
- });
396
-
397
- const data = await response.json();
398
-
399
- if (data.error) {
400
- throw new Error(data.error);
 
 
401
  }
402
-
403
- currentAudio = new Audio(data.audio_url);
 
 
404
  currentAudio.play();
405
 
406
  currentAudio.onended = () => {
@@ -410,16 +421,15 @@
410
  };
411
 
412
  currentAudio.onerror = () => {
413
- console.error("Error playing audio.");
414
- alert("Could not play audio. Please try again.");
415
  buttonElement.classList.remove('loading');
416
  buttonElement.disabled = false;
417
  currentAudio = null;
418
  };
419
 
420
  } catch (error) {
421
- console.error("Error generating audio:", error);
422
- alert("Failed to generate audio. " + (error.message || "Please try again."));
423
  buttonElement.classList.remove('loading');
424
  buttonElement.disabled = false;
425
  }
@@ -431,9 +441,7 @@
431
  try {
432
  const response = await fetch('/chat', {
433
  method: 'POST',
434
- headers: {
435
- 'Content-Type': 'application/json',
436
- },
437
  body: JSON.stringify({ message: userMessage })
438
  });
439
 
@@ -444,7 +452,21 @@
444
  }
445
 
446
  chatArea.removeChild(indicator);
447
- addMessage(data.response_html, 'ai', true, data.response_text);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
448
 
449
  } catch (error) {
450
  chatArea.removeChild(indicator);
@@ -475,19 +497,8 @@
475
 
476
  messageInput.addEventListener('input', adjustTextareaHeight);
477
 
478
- attachButton.addEventListener('click', () => {
479
- alert("Attachment feature not implemented yet!");
480
- messageInput.focus();
481
- });
482
-
483
  updateSendButtonState();
484
  messageInput.focus();
485
-
486
- const isFirstVisit = !localStorage.getItem('chatVisited');
487
- if (isFirstVisit) {
488
- localStorage.setItem('chatVisited', 'true');
489
- setTimeout(() => {}, 500);
490
- }
491
  });
492
  </script>
493
  </body>
 
289
  <div class="welcome-screen">
290
  <h2>Welcome to Athspi!</h2>
291
  <p>Hello! I'm your AI assistant Athspi powered by Gemini. Ask me anything - I can explain concepts, generate ideas, or help with coding!</p>
292
+ <p>You can request audio responses by saying things like: <em>"Give me the answer in audio"</em> or <em>"Speak the response"</em></p>
293
  </div>
294
  </main>
295
 
296
  <footer class="input-area">
297
  <form id="chat-form" class="input-wrapper">
 
 
 
298
  <textarea id="message-input" placeholder="Ask anything..." rows="1"></textarea>
299
  <button type="submit" id="send-button" class="icon-button send-button disabled">
300
  <svg viewBox="0 0 24 24"><path d="M2 21l21-9L2 3v7l15 2-15 2v7z"></path></svg>
 
310
  const chatArea = document.querySelector('.chat-area');
311
  const welcomeScreen = document.querySelector('.welcome-screen');
312
  const sendButton = document.getElementById('send-button');
 
313
 
314
  let currentAudio = null;
315
 
 
329
  chatArea.scrollTop = chatArea.scrollHeight;
330
  };
331
 
332
+ const addMessage = (content, sender, isHTML = false, plainText = '', audioUrl = null) => {
333
  welcomeScreen.classList.add('hidden');
334
 
335
  const messageElement = document.createElement('div');
 
344
  }
345
  messageElement.appendChild(contentDiv);
346
 
347
+ if (sender === 'ai') {
348
+ // Add audio button if audio is available or if response starts with πŸ”Š
349
+ const shouldShowAudio = audioUrl || content.startsWith("πŸ”Š");
350
+ const audioText = plainText || content;
351
+
352
+ if (shouldShowAudio) {
353
+ const audioButton = document.createElement('button');
354
+ audioButton.classList.add('audio-button');
355
+ audioButton.dataset.audioUrl = audioUrl;
356
+ audioButton.dataset.plainText = audioText.replace(/^πŸ”Š\s*/, '');
357
+ audioButton.innerHTML = `
358
+ <svg class="speaker-icon" viewBox="0 0 24 24">
359
+ <path d="M3 10v4c0 .55.45 1 1 1h3.5l5.5 5V5L7.5 9H4c-.55 0-1 .45-1 1zm14 0h-1.5c-2.31 0-4.22-1.74-4.47-4H10v12h1.5v-2.22c.25-2.26 2.16-4.22 4.47-4.22H17c1.1 0 2 .9 2 2s-.9 2-2 2h-1.5v2H17c2.21 0 4-1.79 4-4s-1.79-4-4-4z"/>
360
+ </svg>
361
+ <div class="loader"></div>
362
+ `;
363
+ audioButton.title = "Listen to response";
364
+ audioButton.addEventListener('click', (e) => {
365
+ const url = e.currentTarget.dataset.audioUrl;
366
+ const text = e.currentTarget.dataset.plainText;
367
+ playAudio(e.currentTarget, url, text);
368
+ });
369
+ messageElement.appendChild(audioButton);
370
+ }
371
  }
372
 
373
  chatArea.appendChild(messageElement);
 
384
  return indicatorElement;
385
  };
386
 
387
+ const playAudio = async (buttonElement, audioUrl, text) => {
388
  if (currentAudio) {
389
  currentAudio.pause();
390
  currentAudio.currentTime = 0;
 
395
  buttonElement.disabled = true;
396
 
397
  try {
398
+ // If we don't have a URL but have text, generate audio first
399
+ if (!audioUrl && text) {
400
+ const response = await fetch('/generate-audio', {
401
+ method: 'POST',
402
+ headers: { 'Content-Type': 'application/json' },
403
+ body: JSON.stringify({ text: text })
404
+ });
405
+
406
+ const data = await response.json();
407
+ if (data.error) throw new Error(data.error);
408
+ audioUrl = data.audio_url;
409
+ buttonElement.dataset.audioUrl = audioUrl;
410
  }
411
+
412
+ if (!audioUrl) throw new Error("No audio available");
413
+
414
+ currentAudio = new Audio(audioUrl);
415
  currentAudio.play();
416
 
417
  currentAudio.onended = () => {
 
421
  };
422
 
423
  currentAudio.onerror = () => {
424
+ console.error("Error playing audio");
 
425
  buttonElement.classList.remove('loading');
426
  buttonElement.disabled = false;
427
  currentAudio = null;
428
  };
429
 
430
  } catch (error) {
431
+ console.error("Audio error:", error);
432
+ alert("Failed to play audio. " + (error.message || "Please try again."));
433
  buttonElement.classList.remove('loading');
434
  buttonElement.disabled = false;
435
  }
 
441
  try {
442
  const response = await fetch('/chat', {
443
  method: 'POST',
444
+ headers: { 'Content-Type': 'application/json' },
 
 
445
  body: JSON.stringify({ message: userMessage })
446
  });
447
 
 
452
  }
453
 
454
  chatArea.removeChild(indicator);
455
+ addMessage(
456
+ data.response_html,
457
+ 'ai',
458
+ true,
459
+ data.response_text,
460
+ data.audio_url
461
+ );
462
+
463
+ // Auto-play audio if response starts with πŸ”Š
464
+ if (data.response_text.startsWith("πŸ”Š")) {
465
+ const audioBtn = document.querySelector('.ai-message:last-child .audio-button');
466
+ if (audioBtn) {
467
+ setTimeout(() => audioBtn.click(), 500);
468
+ }
469
+ }
470
 
471
  } catch (error) {
472
  chatArea.removeChild(indicator);
 
497
 
498
  messageInput.addEventListener('input', adjustTextareaHeight);
499
 
 
 
 
 
 
500
  updateSendButtonState();
501
  messageInput.focus();
 
 
 
 
 
 
502
  });
503
  </script>
504
  </body>