class CustomChat extends HTMLElement { constructor() { super(); this._logs = [ "Rosalinda • Démarrage autonome...", "Chargement des services locaux...", "Initialisation sécurisée...", "Prêt à aider ✅" ]; this._messages = [ { role: "assistant", content: "Bonjour ! Je suis Rosalinda, votre IA de création. Je peux vous aider avec des projets, du code, des images et des vidéos. Que souhaitez-vous créer aujourd'hui ?" } ]; this._files = []; this._speechState = "idle"; // idle, listening, unsupported, denied } connectedCallback() { this.attachShadow({ mode: 'open' }); this.shadowRoot.innerHTML = `
${this._messages.map(msg => `
${msg.content}
`).join('')}
Voir l'ordinateur de Espace Codage En ligne
${this._logs.map(log => `
${log}
`).join('')}
`; this._setupEventListeners(); this._startLogsSimulation(); } _setupEventListeners() { const shadow = this.shadowRoot; const fileButton = shadow.getElementById('fileButton'); const fileInput = shadow.getElementById('fileInput'); const connectButton = shadow.getElementById('connectButton'); const micButton = shadow.getElementById('micButton'); const sendButton = shadow.getElementById('sendButton'); const messageInput = shadow.getElementById('messageInput'); const filesInfo = shadow.getElementById('filesInfo'); const micStatus = shadow.getElementById('micStatus'); const chatContainer = shadow.getElementById('chat'); let recognition; let isListening = false; // Enhanced microphone functionality micButton.addEventListener('click', () => { if (isListening) { this._stopSpeechRecognition(recognition, micButton, micStatus); isListening = false; return; } if (!('webkitSpeechRecognition' in window || 'SpeechRecognition' in window)) { this._addMessage('assistant', 'La reconnaissance vocale n\'est pas supportée par votre navigateur. Essayez Chrome ou Edge.'); return; } recognition = this._startSpeechRecognition(micButton, micStatus, messageInput); isListening = true; // Add visual feedback micButton.classList.add('listening'); micStatus.textContent = '🎤 En écoute...'; this._addMessage('assistant', 'Je vous écoute... Parlez maintenant.'); }); // Enhanced file upload with drag & drop fileButton.addEventListener('click', () => fileInput.click()); fileInput.addEventListener('change', (e) => { this._handleFiles(e.target.files, filesInfo); }); // Drag & drop support chatContainer.addEventListener('dragover', (e) => { e.preventDefault(); chatContainer.style.border = '2px dashed #3b82f6'; }); chatContainer.addEventListener('dragleave', () => { chatContainer.style.border = 'none'; }); chatContainer.addEventListener('drop', (e) => { e.preventDefault(); chatContainer.style.border = 'none'; if (e.dataTransfer.files.length) { this._handleFiles(e.dataTransfer.files, filesInfo); } }); // Connect apps with Rosalinda integration connectButton.addEventListener('click', () => { this._addMessage('assistant', `🔌 Rosalinda peut se connecter à: - Votre ordinateur (fichiers locaux) - Votre micro (dictée vocale) - Votre caméra (analyse visuelle) - Vos applications préférées Que souhaitez-vous connecter en premier ?`); }); // Enhanced send message with files const sendMessage = () => { const message = messageInput.value.trim(); if (message || this._files.length) { this._addMessage('user', message); messageInput.value = ''; // Simulate Rosalinda processing setTimeout(() => { let response; if (this._files.length > 0) { response = `J'ai bien reçu ${this._files.length} fichier(s). Je les analyse maintenant...`; this._files = []; filesInfo.innerHTML = ''; } else { response = this._generateRosalindaResponse(message); } this._addMessage('assistant', response); }, 1000); } }; // Helper methods _handleFiles(files, filesInfo) { this._files = Array.from(files); if (this._files.length) { filesInfo.innerHTML = `
${this._files.length} fichier(s) sélectionné(s)
`; shadow.getElementById('clearFiles').addEventListener('click', () => { this._files = []; filesInfo.innerHTML = ''; fileInput.value = ''; }); } else { filesInfo.textContent = ''; } } _generateRosalindaResponse(message) { if (message.toLowerCase().includes('projet')) { return `Pour votre projet, voici ce que je propose: 1. Structure claire et modulaire 2. Design cohérent avec votre identité 3. Tests automatisés 4. Documentation complète Par où commençons-nous ?`; } else if (message.toLowerCase().includes('image')) { return "Je peux générer des images personnalisées. Décrivez-moi ce que vous imaginez (couleurs, style, éléments)."; } else if (message.toLowerCase().includes('vidéo')) { return "Pour la vidéo, je peux vous aider avec:\n- Scénarisation\n- Montage\n- Effets\n- Sous-titres\nQuel aspect souhaitez-vous développer ?"; } else { const responses = [ "J'ai bien compris votre demande. Voici mes suggestions...", "Analyse terminée. Voici ce que je propose:", "Excellente idée ! Voici comment nous pourrions procéder:", "Je peux vous aider avec cela. Voici un plan d'action:" ]; return responses[Math.floor(Math.random() * responses.length)]; } } sendButton.addEventListener('click', sendMessage); messageInput.addEventListener('keydown', (e) => { if (e.key === 'Enter') sendMessage(); }); } _addMessage(role, content) { this._messages.push({ role, content }); this._renderMessages(); } _renderMessages() { const chatContainer = this.shadowRoot.getElementById('chat'); chatContainer.innerHTML = this._messages.map(msg => `
${msg.content}
`).join(''); chatContainer.scrollTop = chatContainer.scrollHeight; } _startLogsSimulation() { const logsContainer = this.shadowRoot.getElementById('logsContainer'); setInterval(() => { const actions = [ 'Analyse du projet', 'Optimisation des ressources', 'Génération de contenu', 'Connexion aux services', 'Préparation des résultats' ]; const randomAction = actions[Math.floor(Math.random() * actions.length)]; this._logs.push(`Rosalinda • ${new Date().toLocaleTimeString()} • ${randomAction}...`); if (this._logs.length > 20) this._logs.shift(); logsContainer.innerHTML = this._logs.map(log => `
${log}
` ).join(''); logsContainer.scrollTop = logsContainer.scrollHeight; }, 1400); } _startSpeechRecognition(micButton, micStatus, messageInput) { const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition; const recognition = new SpeechRecognition(); recognition.lang = 'fr-FR'; recognition.interimResults = true; recognition.continuous = true; micButton.classList.add('listening'); micStatus.textContent = 'Micro actif...'; recognition.onresult = (event) => { let transcript = ''; for (let i = event.resultIndex; i < event.results.length; i++) { transcript += event.results[i][0].transcript; } messageInput.value = transcript; }; recognition.onerror = (event) => { console.error('Speech recognition error', event.error); micButton.classList.remove('listening'); micStatus.textContent = 'Erreur micro'; setTimeout(() => micStatus.textContent = 'En ligne', 2000); }; recognition.onend = () => { micButton.classList.remove('listening'); micStatus.textContent = 'En ligne'; }; recognition.start(); return recognition; } _stopSpeechRecognition(recognition, micButton, micStatus) { if (recognition) { recognition.stop(); } micButton.classList.remove('listening'); micStatus.textContent = 'En ligne'; } `; } } customElements.define('custom-chat', CustomChat);