Update templates/index.html
Browse files- templates/index.html +180 -21
templates/index.html
CHANGED
@@ -333,6 +333,90 @@
|
|
333 |
}
|
334 |
pre:hover .code-copy-btn { opacity: 0.7; }
|
335 |
pre:hover .code-copy-btn:hover { opacity: 1; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
336 |
</style>
|
337 |
</head>
|
338 |
<body class="bg-gray-50 text-gray-900 antialiased">
|
@@ -451,23 +535,25 @@
|
|
451 |
</div>
|
452 |
</div>
|
453 |
</div>
|
454 |
-
<!-- Formulaire de chat -->
|
455 |
<form id="chat-form" class="p-3 sm:p-4 bg-white dark:bg-gray-900">
|
456 |
<div class="relative">
|
457 |
-
<
|
458 |
-
type="text"
|
459 |
id="prompt"
|
460 |
name="prompt"
|
461 |
-
class="chat-input w-full pl-4 pr-12 py-3 rounded-full border focus:outline-none text-sm sm:text-base"
|
462 |
placeholder="Posez votre question à Mariam..."
|
463 |
-
autocomplete="off"
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
|
|
|
|
|
|
471 |
</div>
|
472 |
<div class="text-xs text-center mt-2 text-gray-400 dark:text-gray-500">
|
473 |
Appuyez sur <kbd class="px-1.5 py-0.5 bg-gray-100 dark:bg-gray-800 rounded border border-gray-300 dark:border-gray-700">Entrée</kbd> pour envoyer • <kbd class="px-1.5 py-0.5 bg-gray-100 dark:bg-gray-800 rounded border border-gray-300 dark:border-gray-700">Shift+Entrée</kbd> pour une nouvelle ligne
|
@@ -526,6 +612,23 @@
|
|
526 |
themeToggleBtn.addEventListener('click', toggleTheme);
|
527 |
initializeTheme();
|
528 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
529 |
// Défilement vers le bas
|
530 |
function scrollToBottom(smooth = true) {
|
531 |
setTimeout(() => {
|
@@ -588,6 +691,22 @@
|
|
588 |
`;
|
589 |
}
|
590 |
messageWrapper.innerHTML = html;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
591 |
chatMessages.insertBefore(messageWrapper, loadingIndicator);
|
592 |
scrollToBottom();
|
593 |
}
|
@@ -713,6 +832,25 @@
|
|
713 |
}
|
714 |
clearFileButton.addEventListener('click', clearFileInput);
|
715 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
716 |
// Soumission du formulaire
|
717 |
chatForm.addEventListener('submit', async (e) => {
|
718 |
e.preventDefault();
|
@@ -746,6 +884,7 @@
|
|
746 |
formData.append('advanced_reasoning', useAdvanced);
|
747 |
showLoading(true);
|
748 |
promptInput.value = '';
|
|
|
749 |
clearFileInput();
|
750 |
advancedToggle.checked = false;
|
751 |
if (useAdvanced) startAdvancedCooldownTimer();
|
@@ -819,17 +958,37 @@
|
|
819 |
});
|
820 |
});
|
821 |
|
822 |
-
|
823 |
-
|
824 |
-
|
825 |
-
|
826 |
-
|
827 |
-
|
|
|
828 |
});
|
829 |
|
830 |
-
|
831 |
-
|
832 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
833 |
const prefersDarkScheme = window.matchMedia('(prefers-color-scheme: dark)');
|
834 |
prefersDarkScheme.addEventListener('change', (e) => {
|
835 |
if (!localStorage.theme) {
|
|
|
333 |
}
|
334 |
pre:hover .code-copy-btn { opacity: 0.7; }
|
335 |
pre:hover .code-copy-btn:hover { opacity: 1; }
|
336 |
+
|
337 |
+
/* Styles pour améliorer les tableaux Markdown */
|
338 |
+
.prose table {
|
339 |
+
width: 100%;
|
340 |
+
border-collapse: collapse;
|
341 |
+
margin: 1rem 0;
|
342 |
+
overflow-x: auto;
|
343 |
+
display: block;
|
344 |
+
}
|
345 |
+
|
346 |
+
.prose table th,
|
347 |
+
.prose table td {
|
348 |
+
border: 1px solid #e2e8f0;
|
349 |
+
padding: 0.5rem 0.75rem;
|
350 |
+
text-align: left;
|
351 |
+
}
|
352 |
+
|
353 |
+
.dark .prose table th,
|
354 |
+
.dark .prose table td {
|
355 |
+
border-color: #334155;
|
356 |
+
}
|
357 |
+
|
358 |
+
.prose table thead {
|
359 |
+
background-color: #f8fafc;
|
360 |
+
font-weight: 600;
|
361 |
+
}
|
362 |
+
|
363 |
+
.dark .prose table thead {
|
364 |
+
background-color: #1e293b;
|
365 |
+
}
|
366 |
+
|
367 |
+
.prose table tbody tr:nth-child(even) {
|
368 |
+
background-color: #f8fafc;
|
369 |
+
}
|
370 |
+
|
371 |
+
.dark .prose table tbody tr:nth-child(even) {
|
372 |
+
background-color: #1e293b;
|
373 |
+
}
|
374 |
+
|
375 |
+
/* Pour le textarea qui s'adapte au contenu */
|
376 |
+
.chat-textarea {
|
377 |
+
resize: none;
|
378 |
+
min-height: 40px;
|
379 |
+
max-height: 200px;
|
380 |
+
overflow-y: auto;
|
381 |
+
line-height: 1.5;
|
382 |
+
width: 100%;
|
383 |
+
border-radius: 9999px;
|
384 |
+
padding-top: 0.75rem;
|
385 |
+
padding-bottom: 0.75rem;
|
386 |
+
}
|
387 |
+
|
388 |
+
/* Ajustements pour le responsive */
|
389 |
+
@media (max-width: 640px) {
|
390 |
+
.message-bubble {
|
391 |
+
max-width: 90%;
|
392 |
+
padding: 0.75rem 0.875rem;
|
393 |
+
}
|
394 |
+
|
395 |
+
.chat-textarea {
|
396 |
+
max-height: 120px;
|
397 |
+
font-size: 0.95rem;
|
398 |
+
padding-top: 0.625rem;
|
399 |
+
padding-bottom: 0.625rem;
|
400 |
+
}
|
401 |
+
|
402 |
+
.prose table {
|
403 |
+
font-size: 0.85rem;
|
404 |
+
}
|
405 |
+
|
406 |
+
.prose table th,
|
407 |
+
.prose table td {
|
408 |
+
padding: 0.375rem 0.5rem;
|
409 |
+
}
|
410 |
+
|
411 |
+
.send-button-wrapper {
|
412 |
+
top: 0;
|
413 |
+
right: 0;
|
414 |
+
height: 100%;
|
415 |
+
display: flex;
|
416 |
+
align-items: center;
|
417 |
+
padding-right: 0.5rem;
|
418 |
+
}
|
419 |
+
}
|
420 |
</style>
|
421 |
</head>
|
422 |
<body class="bg-gray-50 text-gray-900 antialiased">
|
|
|
535 |
</div>
|
536 |
</div>
|
537 |
</div>
|
538 |
+
<!-- Formulaire de chat avec textarea au lieu d'input -->
|
539 |
<form id="chat-form" class="p-3 sm:p-4 bg-white dark:bg-gray-900">
|
540 |
<div class="relative">
|
541 |
+
<textarea
|
|
|
542 |
id="prompt"
|
543 |
name="prompt"
|
544 |
+
class="chat-input chat-textarea w-full pl-4 pr-12 py-3 rounded-full border focus:outline-none text-sm sm:text-base"
|
545 |
placeholder="Posez votre question à Mariam..."
|
546 |
+
autocomplete="off"
|
547 |
+
rows="1"></textarea>
|
548 |
+
<div class="send-button-wrapper absolute right-2 top-1/2 transform -translate-y-1/2">
|
549 |
+
<button
|
550 |
+
type="submit"
|
551 |
+
id="send-button"
|
552 |
+
class="bg-primary-500 hover:bg-primary-600 disabled:bg-primary-300 text-white rounded-full p-2 transition focus:outline-none focus:ring-2 focus:ring-primary-400"
|
553 |
+
title="Envoyer le message">
|
554 |
+
<i class="fa-solid fa-paper-plane"></i>
|
555 |
+
</button>
|
556 |
+
</div>
|
557 |
</div>
|
558 |
<div class="text-xs text-center mt-2 text-gray-400 dark:text-gray-500">
|
559 |
Appuyez sur <kbd class="px-1.5 py-0.5 bg-gray-100 dark:bg-gray-800 rounded border border-gray-300 dark:border-gray-700">Entrée</kbd> pour envoyer • <kbd class="px-1.5 py-0.5 bg-gray-100 dark:bg-gray-800 rounded border border-gray-300 dark:border-gray-700">Shift+Entrée</kbd> pour une nouvelle ligne
|
|
|
612 |
themeToggleBtn.addEventListener('click', toggleTheme);
|
613 |
initializeTheme();
|
614 |
|
615 |
+
// Fonction pour ajuster la hauteur du textarea
|
616 |
+
function adjustTextareaHeight(textarea) {
|
617 |
+
textarea.style.height = 'auto';
|
618 |
+
const newHeight = Math.min(200, textarea.scrollHeight);
|
619 |
+
textarea.style.height = newHeight + 'px';
|
620 |
+
|
621 |
+
// Ajuste la position du bouton d'envoi
|
622 |
+
const sendButtonWrapper = document.querySelector('.send-button-wrapper');
|
623 |
+
if (sendButtonWrapper) {
|
624 |
+
if (window.innerWidth <= 640) {
|
625 |
+
sendButtonWrapper.style.top = '';
|
626 |
+
} else {
|
627 |
+
sendButtonWrapper.style.top = (newHeight / 2) + 'px';
|
628 |
+
}
|
629 |
+
}
|
630 |
+
}
|
631 |
+
|
632 |
// Défilement vers le bas
|
633 |
function scrollToBottom(smooth = true) {
|
634 |
setTimeout(() => {
|
|
|
691 |
`;
|
692 |
}
|
693 |
messageWrapper.innerHTML = html;
|
694 |
+
|
695 |
+
// Activer les boutons de copie sur les nouveaux messages
|
696 |
+
const copyBtns = messageWrapper.querySelectorAll('.copy-btn');
|
697 |
+
copyBtns.forEach(btn => {
|
698 |
+
btn.addEventListener('click', function() {
|
699 |
+
const textToCopy = this.closest('.message-bubble').querySelector('.prose').innerText;
|
700 |
+
navigator.clipboard.writeText(textToCopy).then(() => {
|
701 |
+
const originalText = this.innerHTML;
|
702 |
+
this.innerHTML = '<i class="fa-solid fa-check mr-1"></i> Copié';
|
703 |
+
setTimeout(() => {
|
704 |
+
this.innerHTML = originalText;
|
705 |
+
}, 2000);
|
706 |
+
});
|
707 |
+
});
|
708 |
+
});
|
709 |
+
|
710 |
chatMessages.insertBefore(messageWrapper, loadingIndicator);
|
711 |
scrollToBottom();
|
712 |
}
|
|
|
832 |
}
|
833 |
clearFileButton.addEventListener('click', clearFileInput);
|
834 |
|
835 |
+
// Événements pour le textarea
|
836 |
+
promptInput.addEventListener('input', function() {
|
837 |
+
adjustTextareaHeight(this);
|
838 |
+
});
|
839 |
+
|
840 |
+
promptInput.addEventListener('keydown', (e) => {
|
841 |
+
if (isComposing) return;
|
842 |
+
if (e.key === 'Enter' && !e.shiftKey) {
|
843 |
+
e.preventDefault();
|
844 |
+
if (!sendButton.disabled) chatForm.dispatchEvent(new Event('submit'));
|
845 |
+
} else if (e.key === 'Enter' && e.shiftKey) {
|
846 |
+
// Laisser le comportement par défaut (nouvelle ligne)
|
847 |
+
setTimeout(() => adjustTextareaHeight(promptInput), 0);
|
848 |
+
}
|
849 |
+
});
|
850 |
+
|
851 |
+
promptInput.addEventListener('compositionstart', () => { isComposing = true; });
|
852 |
+
promptInput.addEventListener('compositionend', () => { isComposing = false; });
|
853 |
+
|
854 |
// Soumission du formulaire
|
855 |
chatForm.addEventListener('submit', async (e) => {
|
856 |
e.preventDefault();
|
|
|
884 |
formData.append('advanced_reasoning', useAdvanced);
|
885 |
showLoading(true);
|
886 |
promptInput.value = '';
|
887 |
+
promptInput.style.height = 'auto'; // Réinitialiser la hauteur du textarea
|
888 |
clearFileInput();
|
889 |
advancedToggle.checked = false;
|
890 |
if (useAdvanced) startAdvancedCooldownTimer();
|
|
|
958 |
});
|
959 |
});
|
960 |
|
961 |
+
// Init
|
962 |
+
loadChatHistory();
|
963 |
+
adjustTextareaHeight(promptInput);
|
964 |
+
|
965 |
+
// Gérer les changements de taille de l'écran
|
966 |
+
window.addEventListener('resize', () => {
|
967 |
+
adjustTextareaHeight(promptInput);
|
968 |
});
|
969 |
|
970 |
+
// Observer pour les tableaux Markdown et ajouter une classe spéciale si nécessaire
|
971 |
+
const observeMarkdownTables = () => {
|
972 |
+
const observer = new MutationObserver(mutations => {
|
973 |
+
mutations.forEach(mutation => {
|
974 |
+
if (mutation.type === 'childList') {
|
975 |
+
const tables = document.querySelectorAll('.prose table:not(.markdown-enhanced)');
|
976 |
+
tables.forEach(table => {
|
977 |
+
table.classList.add('markdown-enhanced');
|
978 |
+
const wrapper = document.createElement('div');
|
979 |
+
wrapper.className = 'overflow-x-auto';
|
980 |
+
table.parentNode.insertBefore(wrapper, table);
|
981 |
+
wrapper.appendChild(table);
|
982 |
+
});
|
983 |
+
}
|
984 |
+
});
|
985 |
+
});
|
986 |
+
|
987 |
+
observer.observe(chatMessages, { childList: true, subtree: true });
|
988 |
+
};
|
989 |
+
|
990 |
+
observeMarkdownTables();
|
991 |
+
|
992 |
const prefersDarkScheme = window.matchMedia('(prefers-color-scheme: dark)');
|
993 |
prefersDarkScheme.addEventListener('change', (e) => {
|
994 |
if (!localStorage.theme) {
|