index.html:
<!DOCTYPE html>
<html lang="ar">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>محادثة الذكاء الاصطناعي</title>
    <link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
    <style>
        @import url('https://fonts.googleapis.com/css2?family=Amiri:wght@400;700&display=swap');
        body { font-family: 'Amiri', serif; background-color: #1a1a1a; }
        /* أنماط المرئي الدائري */
        #visualizerContainer {
            width: 100px;
            height: 100px;
            margin: 0 auto;
            position: relative;
        }
        #visualizer {
            width: 100%;
            height: 100%;
            background: transparent;
        }
        .circle {
            width: 100%;
            height: 100%;
            border: 4px solid #38bdf8;
            border-radius: 50%;
            animation: pulse 1.5s infinite;
            position: absolute;
            top: 0;
            left: 0;
            box-shadow: 0 0 10px #38bdf8;
        }
        @keyframes pulse {
            0% {
                transform: scale(0.75);
                opacity: 1;
            }
            100% {
                transform: scale(1.25);
                opacity: 0;
            }
        }
        .hidden {
            display: none;
        }
        /* أنماط الرسائل */
        .user-message {
            background-color: #2563eb;
            color: white;
            padding: 10px 15px;
            border-radius: 20px 20px 0px 20px;
            display: inline-block;
            max-width: 80%;
            margin-bottom: 10px;
        }
        .ai-message {
            background-color: #374151;
            color: white;
            padding: 10px 15px;
            border-radius: 20px 20px 20px 0px;
            display: inline-block;
            max-width: 80%;
            margin-bottom: 10px;
        }
    </style>
</head>
<body class="text-white flex flex-col items-center justify-center min-h-screen">
    <h1 class="text-4xl mb-8">محادثة الذكاء الاصطناعي</h1>

    <!-- مرئي التحدث -->
    <div id="visualizerContainer" class="mb-8">
        <canvas id="visualizer"></canvas>
        <div id="circleVisualizer" class="circle hidden"></div>
    </div>

    <!-- التحكم في المحادثة -->
    <div class="w-2/3 flex flex-col items-center">
        <button id="talkButton" onclick="toggleChat()" 
                class="bg-green-500 px-6 py-3 mt-6 rounded hover:bg-green-700 w-full">
            🎤 ابدأ المحادثة
        </button>
        <button id="stopButton" onclick="stopRecognition()" 
                class="bg-red-500 px-6 py-3 mt-4 rounded hover:bg-red-700 w-full hidden">
            ⛔ إيقاف المحادثة
        </button>
    </div>

    <!-- سجل المحادثة -->
    <div id="historyContainer" class="mt-8 p-4 bg-gray-800 rounded w-2/3 overflow-auto max-h-96">
        <!-- ستتم إضافة الرسائل هنا -->
    </div>

    <script src="/static/script.js" defer></script>
</body>
</html>


script.js:
const historyContainer = document.getElementById('historyContainer');
const talkButton = document.getElementById('talkButton');
const stopButton = document.getElementById('stopButton');
const circleVisualizer = document.getElementById('circleVisualizer');

let recognition;
let isListening = false;

// سجل المحادثة
let conversationHistory = [];

// تحميل سجل المحادثة من Local Storage
function loadConversationHistory() {
    const history = localStorage.getItem('conversationHistory');
    if (history) {
        conversationHistory = JSON.parse(history);
        displayConversationHistory();
    }
}

// حفظ سجل المحادثة إلى Local Storage
function saveConversationHistory() {
    localStorage.setItem('conversationHistory', JSON.stringify(conversationHistory));
}

// عرض سجل المحادثة
function displayConversationHistory() {
    historyContainer.innerHTML = '';
    conversationHistory.forEach(item => {
        const messageDiv = document.createElement('div');
        messageDiv.className = 'mb-4';

        // رسالة المستخدم
        const userMessageDiv = document.createElement('div');
        userMessageDiv.className = 'text-right';
        const userMessageSpan = document.createElement('span');
        userMessageSpan.className = 'user-message';
        userMessageSpan.textContent = item.user;
        userMessageDiv.appendChild(userMessageSpan);

        // رسالة الذكاء الاصطناعي
        const aiMessageDiv = document.createElement('div');
        aiMessageDiv.className = 'text-left';
        const aiMessageSpan = document.createElement('span');
        aiMessageSpan.className = 'ai-message';
        aiMessageSpan.textContent = item.ai;
        aiMessageDiv.appendChild(aiMessageSpan);

        messageDiv.appendChild(userMessageDiv);
        messageDiv.appendChild(aiMessageDiv);
        historyContainer.appendChild(messageDiv);
    });
    // التمرير إلى الأسفل
    historyContainer.scrollTop = historyContainer.scrollHeight;
}

// إعداد Web Speech API
function initRecognition() {
    recognition = new (window.SpeechRecognition || window.webkitSpeechRecognition)();
    recognition.lang = 'ar-SA';
    recognition.interimResults = false;
    recognition.maxAlternatives = 1;

    recognition.onstart = function() {
        circleVisualizer.classList.remove('hidden');
    };

    recognition.onend = function() {
        circleVisualizer.classList.add('hidden');
    };

    recognition.onresult = async function(event) {
        const transcript = event.results[0][0].transcript;
        addMessageToHistory('user', transcript);
        await sendMessage(transcript);

        if (isListening) {
            recognition.start();
        }
    };

    recognition.onerror = function(event) {
        console.error('خطأ في التعرف على الكلام:', event.error);
        if (isListening) {
            recognition.start();
        }
    };
}

// بدء المحادثة
async function toggleChat() {
    isListening = true;
    talkButton.classList.add('hidden');
    stopButton.classList.remove('hidden');

    if (!recognition) initRecognition();
    recognition.start();
}

// إيقاف المحادثة
function stopRecognition() {
    isListening = false;
    recognition.stop();
    talkButton.classList.remove('hidden');
    stopButton.classList.add('hidden');
}

// إرسال الرسالة إلى الخادم والحصول على الرد
async function sendMessage(message) {
    try {
        const response = await fetch('/chat', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ message: message })
        });

        const result = await response.json();
        addMessageToHistory('ai', result.response);

        // تشغيل الرد باستخدام تحويل النص إلى كلام
        await playAudio(result.response);
    } catch (error) {
        console.error('خطأ في إرسال الرسالة:', error);
    }
}

// إضافة الرسائل إلى السجل
function addMessageToHistory(sender, message) {
    if (sender === 'user') {
        conversationHistory.push({ user: message, ai: '' });
    } else if (sender === 'ai') {
        conversationHistory[conversationHistory.length - 1].ai = message;
    }
    displayConversationHistory();
    saveConversationHistory();
}

// تحويل النص إلى كلام وتشغيله
async function playAudio(text) {
    try {
        const response = await fetch('/text-to-speech', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ text: text })
        });

        const audioBlob = await response.blob();
        const audioUrl = URL.createObjectURL(audioBlob);
        const audio = new Audio(audioUrl);

        audio.onplay = function() {
            circleVisualizer.classList.remove('hidden');
        };

        audio.onended = function() {
            circleVisualizer.classList.add('hidden');
            if (isListening) {
                recognition.start();
            }
        };

        await audio.play();
    } catch (error) {
        console.error('خطأ في تشغيل الصوت:', error);
    }
}

// تحميل سجل المحادثة عند تحميل الصفحة
loadConversationHistory();


improve this code make it more modern and make visualizer visualize with audio more modern