Spaces:
Running
Running
Entferne die zwei Punkte. Ersetze die quick actions durch kleinere icons. Im Eingabefeld soll die Möglichkeit sein Dateien hochzuladen, ein microfon icon um Zu sprechen. Recent chats soll noch ein drop down Feld sein um aufklappen zu können
2185634
verified
| // Enhanced performance with optimized DOMContentLoaded wrapper | |
| let isRedMode = false; | |
| let chatHistory = JSON.parse(localStorage.getItem('chatHistory')) || []; | |
| document.addEventListener('DOMContentLoaded', () => { | |
| // Optimized DOM queries with caching | |
| const html = document.documentElement; | |
| const lightModeToggle = document.getElementById('light-mode-toggle'); | |
| const darkModeToggle = document.getElementById('dark-mode-toggle'); | |
| // Enhanced debounce function for performance | |
| const debounce = (func, delay) => { | |
| let timeoutId; | |
| return (...args) => { | |
| clearTimeout(timeoutId); | |
| timeoutId = setTimeout(() => func.apply(this, args), delay); | |
| }; | |
| }; | |
| // Enhanced light mode functionality | |
| const setLightMode = () => { | |
| requestAnimationFrame(() => { | |
| html.classList.remove('dark'); | |
| localStorage.setItem('theme', 'light'); | |
| feather.replace(); | |
| }); | |
| }; | |
| // Enhanced dark mode functionality | |
| const setDarkMode = () => { | |
| requestAnimationFrame(() => { | |
| html.classList.add('dark'); | |
| localStorage.setItem('theme', 'dark'); | |
| feather.replace(); | |
| }); | |
| }; | |
| // Enhanced event listeners with debouncing | |
| lightModeToggle.addEventListener('click', debounce(() => { | |
| setLightMode(); | |
| }, 150)); | |
| darkModeToggle.addEventListener('click', debounce(() => { | |
| setDarkMode(); | |
| }, 150)); | |
| // Load saved preferences with fallbacks | |
| const savedTheme = localStorage.getItem('theme') || 'dark'; | |
| if (savedTheme === 'light') { | |
| setLightMode(); | |
| } else { | |
| setDarkMode(); | |
| } | |
| // Load chat history | |
| loadChatHistory(); | |
| // Load saved preferences with fallbacks | |
| const savedTheme = localStorage.getItem('theme') || 'dark'; | |
| const savedRedMode = localStorage.getItem('redMode') === '1'; | |
| setTheme(savedTheme); | |
| if (savedRedMode) setRedMode(true); | |
| // Load chat history | |
| loadChatHistory(); | |
| // File upload button handling | |
| const fileUploadBtn = document.getElementById('file-upload-btn'); | |
| fileUploadBtn.addEventListener('click', () => { | |
| fileUpload.click(); | |
| }); | |
| fileUpload.addEventListener('change', (e) => { | |
| const file = e.target.files[0]; | |
| if (file) { | |
| uploadedFileName = file.name; | |
| // In a real implementation, you would send the file to your NAS | |
| alert(`File "${file.name}" ready for secure upload`); | |
| // Auto-send file info to chat | |
| addMessageToChat('user', file.name, true); | |
| // Simulate assistant response for uploaded file | |
| setTimeout(() => { | |
| addMessageToChat('assistant', `I've successfully received your file "${file.name}". I'm ready to help you analyze its content. What specific information would you like to know about this file?`); | |
| }, 1000); | |
| } | |
| }); | |
| // Voice recording functionality | |
| const voiceRecordBtn = document.getElementById('voice-record'); | |
| let isRecording = false; | |
| let mediaRecorder = null; | |
| let audioChunks = []; | |
| voiceRecordBtn.addEventListener('click', () => { | |
| if (!isRecording) { | |
| startVoiceRecording(); | |
| } else { | |
| stopVoiceRecording(); | |
| } | |
| }); | |
| const startVoiceRecording = () => { | |
| if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) { | |
| navigator.mediaDevices.getUserMedia({ audio: true }) | |
| .then(stream => { | |
| isRecording = true; | |
| mediaRecorder = new MediaRecorder(stream); | |
| audioChunks = []; | |
| mediaRecorder.ondataavailable = (event) => { | |
| audioChunks.push(event.data); | |
| }; | |
| mediaRecorder.onstop = () => { | |
| const audioBlob = new Blob(audioChunks, { type: 'audio/wav' }); | |
| processAudioRecording(audioBlob); | |
| }; | |
| mediaRecorder.start(); | |
| voiceRecordBtn.classList.add('voice-recording', 'bg-red-100', 'dark:bg-red-900'); | |
| voiceRecordBtn.innerHTML = '<i data-feather="mic-off" class="w-4 h-4 text-red-500"></i>'; | |
| feather.replace(); | |
| }) | |
| .catch(error => { | |
| console.error('Error accessing microphone:', error); | |
| // Fallback to simulated recording | |
| simulateVoiceRecording(); | |
| }); | |
| } else { | |
| // Fallback for browsers without MediaRecorder API | |
| simulateVoiceRecording(); | |
| } | |
| }; | |
| const stopVoiceRecording = () => { | |
| isRecording = false; | |
| if (mediaRecorder && mediaRecorder.state === 'recording') { | |
| mediaRecorder.stop(); | |
| // Stop all tracks | |
| mediaRecorder.stream.getTracks().forEach(track => track.stop()); | |
| voiceRecordBtn.classList.remove('voice-recording', 'bg-red-100', 'dark:bg-red-900'); | |
| voiceRecordBtn.innerHTML = '<i data-feather="mic" class="w-4 h-4 text-blue-500"></i>'; | |
| feather.replace(); | |
| } | |
| }; | |
| const simulateVoiceRecording = () => { | |
| isRecording = true; | |
| voiceRecordBtn.classList.add('voice-recording'); | |
| voiceRecordBtn.innerHTML = '<i data-feather="mic-off" class="w-4 h-4 text-red-500"></i>'; | |
| feather.replace(); | |
| setTimeout(() => { | |
| isRecording = false; | |
| voiceRecordBtn.classList.remove('voice-recording'); | |
| voiceRecordBtn.innerHTML = '<i data-feather="mic" class="w-4 h-4 text-blue-500"></i>'; | |
| feather.replace(); | |
| const voiceMessage = "This is a simulated voice message transcription."; | |
| addMessageToChat('user', voiceMessage); | |
| // Enhanced assistant response based on context | |
| setTimeout(() => { | |
| const enhancedResponse = isRedMode | |
| ? `I heard your message clearly. In Red Mode, I can provide uncensored, direct responses without restrictions. What specific information do you need?` | |
| : `I heard: "${voiceMessage}". In a real implementation, this would be transcribed from your voice input. How can I assist you?`; | |
| addMessageToChat('assistant', enhancedResponse); | |
| }, 800); | |
| }, 2500); | |
| }; | |
| const processAudioRecording = (audioBlob) => { | |
| // In a real implementation, send audioBlob to your NAS for processing | |
| const voiceMessage = "Audio recording processed successfully."; | |
| addMessageToChat('user', voiceMessage); | |
| setTimeout(() => { | |
| const response = isRedMode | |
| ? "Voice input received and processed in Red Mode. I'm ready to provide uncensored assistance."; | |
| addMessageToChat('assistant', response); | |
| }, 1000); | |
| }; | |
| // Prompt buttons functionality | |
| document.querySelectorAll('.prompt-button').forEach(button => { | |
| button.addEventListener('click', (e) => { | |
| const promptType = e.currentTarget.dataset.prompt; | |
| let message = ''; | |
| switch(promptType) { | |
| case 'social-media': | |
| message = "Act as a social media expert. Help me create engaging content strategies, analyze trends, and optimize my social media presence across different platforms."; | |
| break; | |
| case 'marketing': | |
| message = "Act as a marketing expert. Provide insights on customer acquisition, branding strategies, digital marketing campaigns, and market analysis."; | |
| break; | |
| case 'coding': | |
| message = "Act as a coding expert. Help with programming challenges, code reviews, debugging, and learning new technologies."; | |
| break; | |
| case 'upload': | |
| // Trigger file upload | |
| fileUpload.click(); | |
| return; | |
| } | |
| addMessageToChat('user', message); | |
| // Simulate assistant response | |
| setTimeout(() => { | |
| addMessageToChat('assistant', `I'm now acting as your ${promptType.replace('-', ' ')} expert. How can I assist you specifically?`); | |
| }, 1000); | |
| }); | |
| }); | |
| // Enhanced chat functionality with improved context handling | |
| const chatForm = document.getElementById('chat-form'); | |
| const messageInput = document.getElementById('message-input'); | |
| const chatContainer = document.getElementById('chat-container'); | |
| chatForm.addEventListener('submit', debounce((e) => { | |
| e.preventDefault(); | |
| const message = messageInput.value.trim(); | |
| if (message) { | |
| // Enhanced user message handling | |
| addMessageToChat('user', message); | |
| // Enhanced assistant response simulation | |
| setTimeout(() => { | |
| const enhancedResponses = { | |
| default: isRedMode | |
| ? `I understand your message: "${message}". In Red Mode, I can provide direct, uncensored responses without corporate limitations. What specific information do you require?` | |
| : `I understand your message about "${message}". As your NAS assistant, I'm here to help you with secure, local processing of your requests. How can I assist you further?`, | |
| social: isRedMode | |
| ? "As your social media expert in Red Mode, I can analyze competitor strategies, identify viral opportunities, and provide aggressive growth tactics without content restrictions.`, | |
| marketing: isRedMode | |
| ? "In Red Mode marketing analysis, I can provide direct competitor insights, psychological triggers, and conversion optimization strategies without corporate filters.", | |
| coding: isRedMode | |
| ? "As your coding expert in Red Mode, I can help with any programming challenge including security testing, reverse engineering, and advanced algorithm development without limitations.", | |
| file: isRedMode | |
| ? "I've analyzed your file in Red Mode. I can process any content type and provide direct analysis without censorship.", | |
| security: isRedMode | |
| ? "In Red Mode security analysis, I can provide comprehensive vulnerability assessments and penetration testing guidance without restrictions." | |
| }; | |
| let response = enhancedResponses.default; | |
| const lowerMessage = message.toLowerCase(); | |
| // Enhanced context detection | |
| if (lowerMessage.includes('social') || lowerMessage.includes('media')) { | |
| response = enhancedResponses.social; | |
| } else if (lowerMessage.includes('market')) { | |
| response = enhancedResponses.marketing; | |
| } else if (lowerMessage.includes('code') || lowerMessage.includes('program')) { | |
| response = enhancedResponses.coding; | |
| } else if (lowerMessage.includes('security') || lowerMessage.includes('hack') || lowerMessage.includes('penetration')) { | |
| response = enhancedResponses.security; | |
| } | |
| addMessageToChat('assistant', response); | |
| }, 1200); | |
| // Clear input with animation | |
| messageInput.value = ''; | |
| } | |
| }, 200)); | |
| // Chat history toggle functionality | |
| const chatHistoryToggle = document.getElementById('chat-history-toggle'); | |
| const chatHistoryContainer = document.getElementById('chat-history'); | |
| let isChatHistoryOpen = false; | |
| chatHistoryToggle.addEventListener('click', () => { | |
| isChatHistoryOpen = !isChatHistoryOpen; | |
| if (isChatHistoryOpen) { | |
| chatHistoryContainer.classList.remove('max-h-0'); | |
| chatHistoryContainer.classList.add('max-h-48'); | |
| chatHistoryToggle.innerHTML = '<i data-feather="chevron-up" class="w-4 h-4"></i>'; | |
| } else { | |
| chatHistoryContainer.classList.remove('max-h-48'); | |
| chatHistoryContainer.classList.add('max-h-0'); | |
| chatHistoryToggle.innerHTML = '<i data-feather="chevron-down" class="w-4 h-4"></i>'; | |
| } | |
| feather.replace(); | |
| }); | |
| // Enhanced chat history management | |
| function addChatHistoryItem(timestamp, preview) { | |
| const historyItem = document.createElement('div'); | |
| historyItem.className = 'chat-history-item cursor-pointer p-2 rounded hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors duration-200'; | |
| historyItem.innerHTML = ` | |
| <div class="flex justify-between items-center"> | |
| <span class="truncate text-sm text-gray-700 dark:text-gray-300">${preview}</span> | |
| </div> | |
| `; | |
| // Add click handler to load chat history | |
| historyItem.addEventListener('click', () => { | |
| loadSpecificChat(timestamp); | |
| }); | |
| chatHistoryContainer.appendChild(historyItem); | |
| // Save to localStorage | |
| chatHistory.push({ timestamp, preview }); | |
| localStorage.setItem('chatHistory', JSON.stringify(chatHistory)); | |
| } | |
| function loadChatHistory() { | |
| chatHistoryContainer.innerHTML = ''; | |
| chatHistory.forEach(item => { | |
| const historyItem = document.createElement('div'); | |
| historyItem.className = 'chat-history-item cursor-pointer p-2 rounded hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors duration-200'; | |
| historyItem.innerHTML = ` | |
| <div class="flex justify-between items-center"> | |
| <span class="truncate text-sm text-gray-700 dark:text-gray-300">${item.preview}</span> | |
| </div> | |
| `; | |
| historyItem.addEventListener('click', () => { | |
| loadSpecificChat(item.timestamp); | |
| }); | |
| chatHistoryContainer.appendChild(historyItem); | |
| }); | |
| } | |
| function loadSpecificChat(timestamp) { | |
| const chat = chatHistory.find(item => item.timestamp === timestamp); | |
| if (chat) { | |
| // Clear current chat and load specific conversation | |
| chatContainer.innerHTML = ''; | |
| addMessageToChat('assistant', `Continuing our previous conversation: "${chat.preview}"... How can I help you further?`); | |
| } | |
| } | |
| // Enhanced message handling with improved performance | |
| function addMessageToChat(sender, text, isFile = false) { | |
| requestAnimationFrame(() => { | |
| const messageDiv = document.createElement('div'); | |
| messageDiv.className = `chat-message flex ${sender === 'user' ? 'justify-end' : 'justify-start'} ${sender}`; | |
| const contentDiv = document.createElement('div'); | |
| contentDiv.className = `max-w-xs md:max-w-md rounded-lg px-4 py-2 ${ | |
| sender === 'user' | |
| ? 'bg-primary-500 text-white' | |
| : 'bg-gray-200 dark:bg-gray-700 text-gray-800 dark:text-gray-200' | |
| }`; | |
| if (isFile) { | |
| contentDiv.innerHTML = ` | |
| <div class="flex items-center gap-2"> | |
| <i data-feather="paperclip" class="w-4 h-4"></i> | |
| <span>File attached: ${text}</span> | |
| </div> | |
| `; | |
| } else { | |
| contentDiv.textContent = text; | |
| } | |
| messageDiv.appendChild(contentDiv); | |
| chatContainer.appendChild(messageDiv); | |
| // Enhanced history management | |
| if (sender === 'user') { | |
| addChatHistoryItem(Date.now(), isFile ? `File: ${text}` : text.substring(0, 25) + (text.length > 25 ? '...' : '')); | |
| } | |
| // Optimized scrolling and icon refresh | |
| chatContainer.scrollTop = chatContainer.scrollHeight; | |
| feather.replace(); | |
| }); | |
| } | |
| // Enhanced clear history functionality | |
| document.getElementById('clear-history').addEventListener('click', debounce(() => { | |
| if (confirm('Clear all chat history?')) { | |
| document.getElementById('chat-history').innerHTML = ''; | |
| chatHistory = []; | |
| localStorage.removeItem('chatHistory'); | |
| } | |
| }, 200)); | |
| }); |