redsputnik / script.js
Redsputnik's picture
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));
});