Redsputnik commited on
Commit
da03d78
·
verified ·
1 Parent(s): 851b3d8

Ergänze und optimieren eigenständig

Browse files
Files changed (3) hide show
  1. index.html +76 -12
  2. script.js +313 -133
  3. style.css +147 -41
index.html CHANGED
@@ -46,24 +46,88 @@
46
  </h1>
47
  <status-indicator status="online"></status-indicator>
48
  </div>
49
- <div class="flex gap-2 mb-4">
50
- <button id="theme-toggle" class="p-2">
51
- <i data-feather="moon" class="dark:hidden"></i>
52
- <i data-feather="sun" class="hidden dark:block"></i>
53
  </button>
54
- <button id="red-mode-toggle" class="p-2" title="Red Mode">
55
  <i data-feather="alert-triangle" class="text-red-500"></i>
56
  </button>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57
  </div>
58
- <div class="w-full bg-white dark:bg-gray-800 rounded-lg overflow-hidden">
59
- <div id="chat-container" class="h-96 overflow-y-auto p-4 space-y-4">
60
- <!-- Chat messages will appear here -->
61
- <div class="text-center py-8 text-gray-500 dark:text-gray-400">
62
- <i data-feather="message-circle" class="w-12 h-12 mx-auto mb-2"></i>
63
- <p>Start chatting with your NAS assistant</p>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
  </div>
65
  </div>
66
- <div class="border-t border-gray-200 dark:border-gray-700 p-4">
67
  <form id="chat-form" class="flex items-center">
68
  <input
69
  type="text"
 
46
  </h1>
47
  <status-indicator status="online"></status-indicator>
48
  </div>
49
+ <div class="flex gap-2 mb-4">
50
+ <button id="theme-toggle" class="p-2 bg-white dark:bg-gray-700 rounded-lg shadow-sm hover:shadow-md transition-all duration-200">
51
+ <i data-feather="moon" class="dark:hidden text-gray-600"></i>
52
+ <i data-feather="sun" class="hidden dark:block text-yellow-400"></i>
53
  </button>
54
+ <button id="red-mode-toggle" class="p-2 bg-white dark:bg-gray-700 rounded-lg shadow-sm hover:shadow-md transition-all duration-200" title="Red Mode">
55
  <i data-feather="alert-triangle" class="text-red-500"></i>
56
  </button>
57
+ <button id="voice-record" class="p-2 bg-white dark:bg-gray-700 rounded-lg shadow-sm hover:shadow-md transition-all duration-200" title="Voice Message">
58
+ <i data-feather="mic" class="text-blue-500"></i>
59
+ </button>
60
+ <input type="file" id="file-upload" class="hidden" accept="*/*">
61
+ <button id="file-upload-btn" class="p-2 bg-white dark:bg-gray-700 rounded-lg shadow-sm hover:shadow-md transition-all duration-200" title="Upload File">
62
+ <i data-feather="paperclip" class="text-green-500"></i>
63
+ </button>
64
+ </div>
65
+ <div class="grid grid-cols-1 lg:grid-cols-4 gap-6">
66
+ <div class="lg:col-span-3">
67
+ <div class="w-full bg-white dark:bg-gray-800 rounded-lg shadow-sm overflow-hidden">
68
+ <div id="chat-container" class="h-96 overflow-y-auto p-4 space-y-4">
69
+ <!-- Chat messages will appear here -->
70
+ <div class="text-center py-8 text-gray-500 dark:text-gray-400">
71
+ <i data-feather="message-circle" class="w-12 h-12 mx-auto mb-2"></i>
72
+ <p>Start chatting with your NAS assistant</p>
73
+ </div>
74
+ </div>
75
+ <div class="border-t border-gray-200 dark:border-gray-700 p-4">
76
+ <form id="chat-form" class="flex items-center gap-2">
77
+ <input
78
+ type="text"
79
+ id="message-input"
80
+ placeholder="Type your message..."
81
+ class="flex-1 px-4 py-3 bg-transparent text-gray-800 dark:text-gray-200 focus:outline-none"
82
+ autocomplete="off"
83
+ required
84
+ >
85
+ <button
86
+ type="submit"
87
+ class="p-3 bg-primary-500 hover:bg-primary-600 text-white rounded-full transition-colors duration-200"
88
+ >
89
+ <i data-feather="send" class="w-4 h-4"></i>
90
+ </button>
91
+ </form>
92
+ </div>
93
  </div>
94
+
95
+ <div class="lg:col-span-1 space-y-4">
96
+ <!-- Quick Actions -->
97
+ <div class="bg-white dark:bg-gray-800 rounded-lg shadow-sm p-4">
98
+ <h3 class="font-semibold text-gray-800 dark:text-gray-200 mb-3">Quick Actions</h3>
99
+ <div class="grid grid-cols-2 gap-2">
100
+ <button class="prompt-button p-3 bg-gray-100 dark:bg-gray-700 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-600 transition-colors" data-prompt="social-media">
101
+ <i data-feather="share-2" class="w-4 h-4 mx-auto mb-1 text-blue-500"></i>
102
+ <span class="text-xs text-gray-600 dark:text-gray-400">Social Media</span>
103
+ </button>
104
+ <button class="prompt-button p-3 bg-gray-100 dark:bg-gray-700 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-600 transition-colors" data-prompt="marketing">
105
+ <i data-feather="trending-up" class="w-4 h-4 mx-auto mb-1 text-green-500"></i>
106
+ <span class="text-xs text-gray-600 dark:text-gray-400">Marketing</span>
107
+ </button>
108
+ <button class="prompt-button p-3 bg-gray-100 dark:bg-gray-700 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-600 transition-colors" data-prompt="coding">
109
+ <i data-feather="code" class="w-4 h-4 mx-auto mb-1 text-purple-500"></i>
110
+ <span class="text-xs text-gray-600 dark:text-gray-400">Coding</span>
111
+ </button>
112
+ <button class="prompt-button p-3 bg-gray-100 dark:bg-gray-700 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-600 transition-colors" data-prompt="upload">
113
+ <i data-feather="upload" class="w-4 h-4 mx-auto mb-1 text-orange-500"></i>
114
+ <span class="text-xs text-gray-600 dark:text-gray-400">Upload</span>
115
+ </button>
116
+ </div>
117
+ </div>
118
+
119
+ <!-- Chat History -->
120
+ <div class="bg-white dark:bg-gray-800 rounded-lg shadow-sm p-4">
121
+ <div class="flex justify-between items-center mb-3">
122
+ <h3 class="font-semibold text-gray-800 dark:text-gray-200">Recent Chats</h3>
123
+ <button id="clear-history" class="text-xs text-gray-500 hover:text-red-500 transition-colors">Clear</button>
124
+ </div>
125
+ <div id="chat-history" class="space-y-2 max-h-48 overflow-y-auto">
126
+ </div>
127
+ </div>
128
  </div>
129
  </div>
130
+ <div class="border-t border-gray-200 dark:border-gray-700 p-4">
131
  <form id="chat-form" class="flex items-center">
132
  <input
133
  type="text"
script.js CHANGED
@@ -1,14 +1,18 @@
1
 
2
- // Improved performance with DOMContentLoaded wrapper
3
  let isRedMode = false;
 
4
 
5
  document.addEventListener('DOMContentLoaded', () => {
6
- // Optimized DOM queries
7
  const html = document.documentElement;
8
  const themeToggle = document.getElementById('theme-toggle');
9
  const redModeToggle = document.getElementById('red-mode-toggle');
 
 
 
10
 
11
- // Debounce function for performance
12
  const debounce = (func, delay) => {
13
  let timeoutId;
14
  return (...args) => {
@@ -16,61 +20,111 @@ document.addEventListener('DOMContentLoaded', () => {
16
  timeoutId = setTimeout(() => func.apply(this, args), delay);
17
  };
18
  };
19
- // Theme toggle functionality
20
  const setTheme = (theme) => {
21
- if (theme === 'dark') {
22
- html.classList.add('dark');
23
- } else {
24
- html.classList.remove('dark');
25
- }
26
- localStorage.setItem('theme', theme);
27
- updateThemeIcons();
28
- feather.replace();
 
 
 
 
 
 
 
 
 
 
29
  };
 
 
30
 
31
- // Red mode toggle functionality
32
  const setRedMode = (enabled) => {
33
- if (enabled) {
34
- html.classList.add('red-mode');
35
- } else {
36
- html.classList.remove('red-mode');
37
- }
38
- localStorage.setItem('redMode', enabled ? '1' : '0');
39
- feather.replace();
 
 
 
 
 
 
 
 
 
40
  };
41
-
42
- // Update theme icons based on current theme
43
  const updateThemeIcons = () => {
44
  const isDark = html.classList.contains('dark');
45
- const moonIcon = themeToggle.querySelector('i[data-feather="moon"]');
46
- const sunIcon = themeToggle.querySelector('i[data-feather="sun"]');
47
-
48
- if (isDark) {
49
- moonIcon.classList.add('hidden');
50
- sunIcon.classList.remove('hidden');
51
- } else {
52
- moonIcon.classList.remove('hidden');
53
- sunIcon.classList.add('hidden');
54
- }
 
 
55
  };
56
-
57
- themeToggle.addEventListener('click', () => {
58
  const isDark = html.classList.contains('dark');
59
  setTheme(isDark ? 'light' : 'dark');
60
- });
61
 
62
- redModeToggle.addEventListener('click', () => {
63
  const isRed = html.classList.contains('red-mode');
64
  setRedMode(!isRed);
65
- alert(`Red Mode ${!isRed ? 'activated' : 'deactivated'}\nResponses will now be ${!isRed ? 'uncensored' : 'filtered'}`);
 
 
 
 
 
 
 
 
 
 
 
 
66
  feather.replace();
 
 
 
 
67
  });
68
 
69
- // Load saved preferences
 
 
 
 
 
 
 
 
 
70
  const savedTheme = localStorage.getItem('theme') || 'dark';
71
  const savedRedMode = localStorage.getItem('redMode') === '1';
72
  setTheme(savedTheme);
73
  if (savedRedMode) setRedMode(true);
 
 
 
74
  // File upload handling
75
  const fileUpload = document.getElementById('file-upload');
76
  let uploadedFileName = '';
@@ -89,45 +143,93 @@ document.addEventListener('DOMContentLoaded', () => {
89
  }, 1000);
90
  }
91
  });
92
-
93
- // Voice recording functionality
94
- const voiceRecordBtn = document.getElementById('voice-record');
95
  let isRecording = false;
96
-
97
- voiceRecordBtn.addEventListener('click', () => {
98
- if (!isRecording) {
99
- // Start recording
100
- isRecording = true;
101
- voiceRecordBtn.classList.add('voice-recording');
102
- voiceRecordBtn.innerHTML = '<i data-feather="mic-off" class="w-4 h-4 text-red-500"></i>';
103
- feather.replace();
104
-
105
- // Simulate voice recording (in a real app, use Web Speech API)
106
- setTimeout(() => {
107
- // Stop recording and process
108
- isRecording = false;
109
- voiceRecordBtn.classList.remove('voice-recording');
110
- voiceRecordBtn.innerHTML = '<i data-feather="mic" class="w-4 h-4"></i>';
111
- feather.replace();
112
-
113
- const voiceMessage = "This is a simulated voice message transcription.";
114
- addMessageToChat('user', voiceMessage);
115
-
116
- // Simulate assistant response
117
- setTimeout(() => {
118
- addMessageToChat('assistant', `I heard: "${voiceMessage}". In a real implementation, this would be transcribed from your voice input.");
119
- }, 1000);
120
- }, 3000);
 
 
 
 
 
121
  } else {
122
- // Stop recording
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
123
  isRecording = false;
124
  voiceRecordBtn.classList.remove('voice-recording');
125
- voiceRecordBtn.innerHTML = '<i data-feather="mic" class="w-4 h-4"></i>';
126
  feather.replace();
127
- }
128
- });
 
 
 
 
 
 
 
 
 
 
 
129
 
130
- // Prompt buttons functionality
 
 
 
 
 
 
 
 
 
 
 
131
  document.querySelectorAll('.prompt-button').forEach(button => {
132
  button.addEventListener('click', (e) => {
133
  const promptType = e.currentTarget.dataset.prompt;
@@ -157,100 +259,178 @@ document.addEventListener('DOMContentLoaded', () => {
157
  }, 1000);
158
  });
159
  });
160
- // Chat functionality
161
  const chatForm = document.getElementById('chat-form');
162
  const messageInput = document.getElementById('message-input');
163
  const chatContainer = document.getElementById('chat-container');
164
 
165
- chatForm.addEventListener('submit', (e) => {
166
  e.preventDefault();
167
 
168
  const message = messageInput.value.trim();
169
  if (message) {
170
- // Add user message to chat
171
  addMessageToChat('user', message);
172
- // Simulate assistant response (in a real app, this would be an API call to your NAS)
 
173
  setTimeout(() => {
174
- const assistantResponses = {
175
- default: `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?`,
176
- social: `As your social media assistant, I can help you create engaging content strategies, analyze trends, and optimize your presence across platforms. What specific aspect would you like to focus on?`,
177
- marketing: `As your marketing expert, I can provide insights on customer acquisition, branding strategies, and digital campaigns. Tell me more about your marketing goals.`,
178
- coding: `As your coding assistant, I can help with programming challenges, code reviews, and learning new technologies. What are you working on?`,
179
- file: `I've analyzed your file and found it contains structured data. Would you like me to help you process or extract specific information from it?`
 
 
 
 
 
 
 
 
180
  };
181
 
182
- let response = assistantResponses.default;
 
183
 
184
- // Check for specific context in user message
185
- if (message.toLowerCase().includes('social') || message.toLowerCase().includes('media')) {
186
- response = assistantResponses.social;
187
- } else if (message.toLowerCase().includes('market')) {
188
- response = assistantResponses.marketing;
189
- } else if (message.toLowerCase().includes('code') || message.toLowerCase().includes('program')) {
190
- response = assistantResponses.coding;
191
- } else if (uploadedFileName) {
192
- response = assistantResponses.file;
193
- uploadedFileName = ''; // Reset after use
194
  }
195
 
196
  addMessageToChat('assistant', response);
197
- }, 1000);
198
 
199
- // Clear input
200
  messageInput.value = '';
201
  }
202
- });
203
- // Add chat history item
204
  function addChatHistoryItem(timestamp, preview) {
205
  const historyItem = document.createElement('div');
206
- historyItem.id = 'chat-history-item';
207
  historyItem.innerHTML = `
208
  <div class="flex justify-between items-center">
209
- <span class="truncate">${preview}</span>
210
- <span class="text-xs text-gray-500">${new Date(timestamp).toLocaleTimeString()}</span>
211
  </div>
212
  `;
213
- document.getElementById('chat-history').appendChild(historyItem);
214
- }
215
- // Enhanced message handling
216
- function addMessageToChat(sender, text, isFile = false) {
217
- const messageDiv = document.createElement('div');
218
- messageDiv.className = `chat-message flex ${sender === 'user' ? 'justify-end' : 'justify-start'} ${sender}`;
219
 
220
- const contentDiv = document.createElement('div');
221
- contentDiv.className = `max-w-xs md:max-w-md rounded-lg px-4 py-2 ${
222
- sender === 'user'
223
- ? 'bg-primary-500 text-white'
224
- : 'bg-gray-200 dark:bg-gray-700 text-gray-800 dark:text-gray-200'
225
- }`;
226
 
227
- if (isFile) {
228
- contentDiv.innerHTML = `
229
- <div class="flex items-center gap-2">
230
- <i data-feather="paperclip" class="w-4 h-4"></i>
231
- <span>File attached: ${text}</span>
232
- </div>
233
- `;
234
- } else {
235
- contentDiv.textContent = text;
236
- }
237
 
238
- messageDiv.appendChild(contentDiv);
239
- chatContainer.appendChild(messageDiv);
 
 
 
 
 
 
240
 
241
- // Add to history if user message
242
- if (sender === 'user') {
243
- addChatHistoryItem(Date.now(), isFile ? `File: ${text}` : text.substring(0, 20));
244
- }
 
 
 
 
245
 
246
- // Scroll to bottom and refresh Feather icons
247
- chatContainer.scrollTop = chatContainer.scrollHeight;
248
- feather.replace();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
249
  }
250
- // Clear history
251
- document.getElementById('clear-history').addEventListener('click', () => {
252
  if (confirm('Clear all chat history?')) {
253
  document.getElementById('chat-history').innerHTML = '';
 
 
254
  }
255
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
256
  });
 
1
 
2
+ // Enhanced performance with optimized DOMContentLoaded wrapper
3
  let isRedMode = false;
4
+ let chatHistory = JSON.parse(localStorage.getItem('chatHistory')) || [];
5
 
6
  document.addEventListener('DOMContentLoaded', () => {
7
+ // Optimized DOM queries with caching
8
  const html = document.documentElement;
9
  const themeToggle = document.getElementById('theme-toggle');
10
  const redModeToggle = document.getElementById('red-mode-toggle');
11
+ const voiceRecordBtn = document.getElementById('voice-record');
12
+ const fileUploadBtn = document.getElementById('file-upload-btn');
13
+ const fileUpload = document.getElementById('file-upload');
14
 
15
+ // Enhanced debounce function for performance
16
  const debounce = (func, delay) => {
17
  let timeoutId;
18
  return (...args) => {
 
20
  timeoutId = setTimeout(() => func.apply(this, args), delay);
21
  };
22
  };
23
+ // Enhanced theme toggle functionality
24
  const setTheme = (theme) => {
25
+ requestAnimationFrame(() => {
26
+ if (theme === 'dark') {
27
+ html.classList.add('dark');
28
+ } else {
29
+ html.classList.remove('dark');
30
+ }
31
+ localStorage.setItem('theme', theme);
32
+ updateThemeIcons();
33
+ feather.replace();
34
+ // Initialize performance monitoring
35
+ const performanceMonitor = () => {
36
+ const startTime = performance.now();
37
+ return {
38
+ end: () => {
39
+ const endTime = performance.now();
40
+ console.log(`Operation took ${endTime - startTime} milliseconds`);
41
+ }
42
+ };
43
  };
44
+ });
45
+ };
46
 
47
+ // Enhanced red mode toggle functionality
48
  const setRedMode = (enabled) => {
49
+ requestAnimationFrame(() => {
50
+ if (enabled) {
51
+ html.classList.add('red-mode');
52
+ } else {
53
+ html.classList.remove('red-mode');
54
+ }
55
+ isRedMode = enabled;
56
+ localStorage.setItem('redMode', enabled ? '1' : '0');
57
+
58
+ // Update status indicator in red mode
59
+ const statusIndicator = document.querySelector('status-indicator');
60
+ if (enabled && statusIndicator) {
61
+ statusIndicator.setAttribute('status', 'online');
62
+ }
63
+ feather.replace();
64
+ });
65
  };
66
+ // Enhanced theme icons update with performance optimization
 
67
  const updateThemeIcons = () => {
68
  const isDark = html.classList.contains('dark');
69
+ requestAnimationFrame(() => {
70
+ const moonIcon = themeToggle.querySelector('i[data-feather="moon"]');
71
+ const sunIcon = themeToggle.querySelector('i[data-feather="sun"]');
72
+
73
+ if (isDark) {
74
+ moonIcon?.classList.add('hidden');
75
+ sunIcon?.classList.remove('hidden');
76
+ } else {
77
+ moonIcon?.classList.remove('hidden');
78
+ sunIcon?.classList.add('hidden');
79
+ }
80
+ });
81
  };
82
+ // Enhanced event listeners with debouncing
83
+ themeToggle.addEventListener('click', debounce(() => {
84
  const isDark = html.classList.contains('dark');
85
  setTheme(isDark ? 'light' : 'dark');
86
+ }, 150));
87
 
88
+ redModeToggle.addEventListener('click', debounce(() => {
89
  const isRed = html.classList.contains('red-mode');
90
  setRedMode(!isRed);
91
+
92
+ // Enhanced notification system
93
+ const notification = document.createElement('div');
94
+ notification.className = `fixed top-4 right-4 p-4 rounded-lg shadow-lg z-50 ${
95
+ !isRed ? 'bg-red-500 text-white' : 'bg-gray-500 text-white'
96
+ }`;
97
+ notification.textContent = `Red Mode ${!isRed ? 'activated' : 'deactivated'}`;
98
+ document.body.appendChild(notification);
99
+
100
+ setTimeout(() => {
101
+ notification.remove();
102
+ }, 3000);
103
+
104
  feather.replace();
105
+ }, 150));
106
+ // Enhanced file upload button handling
107
+ fileUploadBtn.addEventListener('click', () => {
108
+ fileUpload.click();
109
  });
110
 
111
+ // Enhanced voice recording button
112
+ voiceRecordBtn.addEventListener('click', debounce(() => {
113
+ if (!isRecording) {
114
+ startVoiceRecording();
115
+ } else {
116
+ stopVoiceRecording();
117
+ }
118
+ }, 200));
119
+
120
+ // Load saved preferences with fallbacks
121
  const savedTheme = localStorage.getItem('theme') || 'dark';
122
  const savedRedMode = localStorage.getItem('redMode') === '1';
123
  setTheme(savedTheme);
124
  if (savedRedMode) setRedMode(true);
125
+
126
+ // Load chat history
127
+ loadChatHistory();
128
  // File upload handling
129
  const fileUpload = document.getElementById('file-upload');
130
  let uploadedFileName = '';
 
143
  }, 1000);
144
  }
145
  });
146
+ // Enhanced voice recording functionality
 
 
147
  let isRecording = false;
148
+ let mediaRecorder = null;
149
+ let audioChunks = [];
150
+
151
+ const startVoiceRecording = () => {
152
+ if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
153
+ navigator.mediaDevices.getUserMedia({ audio: true })
154
+ .then(stream => {
155
+ isRecording = true;
156
+ mediaRecorder = new MediaRecorder(stream);
157
+ audioChunks = [];
158
+
159
+ mediaRecorder.ondataavailable = (event) => {
160
+ audioChunks.push(event.data);
161
+ };
162
+
163
+ mediaRecorder.onstop = () => {
164
+ const audioBlob = new Blob(audioChunks, { type: 'audio/wav' });
165
+ processAudioRecording(audioBlob);
166
+ };
167
+
168
+ mediaRecorder.start();
169
+ voiceRecordBtn.classList.add('voice-recording', 'bg-red-100', 'dark:bg-red-900');
170
+ voiceRecordBtn.innerHTML = '<i data-feather="mic-off" class="w-4 h-4 text-red-500"></i>';
171
+ feather.replace();
172
+ })
173
+ .catch(error => {
174
+ console.error('Error accessing microphone:', error);
175
+ // Fallback to simulated recording
176
+ simulateVoiceRecording();
177
+ });
178
  } else {
179
+ // Fallback for browsers without MediaRecorder API
180
+ simulateVoiceRecording();
181
+ }
182
+ };
183
+
184
+ const stopVoiceRecording = () => {
185
+ isRecording = false;
186
+ if (mediaRecorder && mediaRecorder.state === 'recording') {
187
+ mediaRecorder.stop();
188
+ // Stop all tracks
189
+ mediaRecorder.stream.getTracks().forEach(track => track.stop());
190
+ voiceRecordBtn.classList.remove('voice-recording', 'bg-red-100', 'dark:bg-red-900');
191
+ voiceRecordBtn.innerHTML = '<i data-feather="mic" class="w-4 h-4 text-blue-500"></i>';
192
+ feather.replace();
193
+ }
194
+ };
195
+
196
+ const simulateVoiceRecording = () => {
197
+ isRecording = true;
198
+ voiceRecordBtn.classList.add('voice-recording');
199
+ voiceRecordBtn.innerHTML = '<i data-feather="mic-off" class="w-4 h-4 text-red-500"></i>';
200
+ feather.replace();
201
+
202
+ setTimeout(() => {
203
  isRecording = false;
204
  voiceRecordBtn.classList.remove('voice-recording');
205
+ voiceRecordBtn.innerHTML = '<i data-feather="mic" class="w-4 h-4 text-blue-500"></i>';
206
  feather.replace();
207
+
208
+ const voiceMessage = "This is a simulated voice message transcription.";
209
+ addMessageToChat('user', voiceMessage);
210
+
211
+ // Enhanced assistant response based on context
212
+ setTimeout(() => {
213
+ const enhancedResponse = isRedMode
214
+ ? `I heard your message clearly. In Red Mode, I can provide uncensored, direct responses without restrictions. What specific information do you need?`
215
+ : `I heard: "${voiceMessage}". In a real implementation, this would be transcribed from your voice input. How can I assist you?`;
216
+ addMessageToChat('assistant', enhancedResponse);
217
+ }, 800);
218
+ }, 2500);
219
+ };
220
 
221
+ const processAudioRecording = (audioBlob) => {
222
+ // In a real implementation, send audioBlob to your NAS for processing
223
+ const voiceMessage = "Audio recording processed successfully.";
224
+ addMessageToChat('user', voiceMessage);
225
+
226
+ setTimeout(() => {
227
+ const response = isRedMode
228
+ ? "Voice input received and processed in Red Mode. I'm ready to provide uncensored assistance.";
229
+ addMessageToChat('assistant', response);
230
+ }, 1000);
231
+ };
232
+ // Prompt buttons functionality
233
  document.querySelectorAll('.prompt-button').forEach(button => {
234
  button.addEventListener('click', (e) => {
235
  const promptType = e.currentTarget.dataset.prompt;
 
259
  }, 1000);
260
  });
261
  });
262
+ // Enhanced chat functionality with improved context handling
263
  const chatForm = document.getElementById('chat-form');
264
  const messageInput = document.getElementById('message-input');
265
  const chatContainer = document.getElementById('chat-container');
266
 
267
+ chatForm.addEventListener('submit', debounce((e) => {
268
  e.preventDefault();
269
 
270
  const message = messageInput.value.trim();
271
  if (message) {
272
+ // Enhanced user message handling
273
  addMessageToChat('user', message);
274
+
275
+ // Enhanced assistant response simulation
276
  setTimeout(() => {
277
+ const enhancedResponses = {
278
+ default: isRedMode
279
+ ? `I understand your message: "${message}". In Red Mode, I can provide direct, uncensored responses without corporate limitations. What specific information do you require?`
280
+ : `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?`,
281
+ social: isRedMode
282
+ ? "As your social media expert in Red Mode, I can analyze competitor strategies, identify viral opportunities, and provide aggressive growth tactics without content restrictions.`,
283
+ marketing: isRedMode
284
+ ? "In Red Mode marketing analysis, I can provide direct competitor insights, psychological triggers, and conversion optimization strategies without corporate filters.",
285
+ coding: isRedMode
286
+ ? "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.",
287
+ file: isRedMode
288
+ ? "I've analyzed your file in Red Mode. I can process any content type and provide direct analysis without censorship.",
289
+ security: isRedMode
290
+ ? "In Red Mode security analysis, I can provide comprehensive vulnerability assessments and penetration testing guidance without restrictions."
291
  };
292
 
293
+ let response = enhancedResponses.default;
294
+ const lowerMessage = message.toLowerCase();
295
 
296
+ // Enhanced context detection
297
+ if (lowerMessage.includes('social') || lowerMessage.includes('media')) {
298
+ response = enhancedResponses.social;
299
+ } else if (lowerMessage.includes('market')) {
300
+ response = enhancedResponses.marketing;
301
+ } else if (lowerMessage.includes('code') || lowerMessage.includes('program')) {
302
+ response = enhancedResponses.coding;
303
+ } else if (lowerMessage.includes('security') || lowerMessage.includes('hack') || lowerMessage.includes('penetration')) {
304
+ response = enhancedResponses.security;
 
305
  }
306
 
307
  addMessageToChat('assistant', response);
308
+ }, 1200);
309
 
310
+ // Clear input with animation
311
  messageInput.value = '';
312
  }
313
+ }, 200));
314
+ // Enhanced chat history management
315
  function addChatHistoryItem(timestamp, preview) {
316
  const historyItem = document.createElement('div');
317
+ historyItem.className = 'chat-history-item';
318
  historyItem.innerHTML = `
319
  <div class="flex justify-between items-center">
320
+ <span class="truncate text-sm text-gray-700 dark:text-gray-300">${preview}</span>
321
+ <span class="text-xs text-gray-500">${new Date(timestamp).toLocaleTimeString()}</span>
322
  </div>
323
  `;
 
 
 
 
 
 
324
 
325
+ // Add click handler to load chat history
326
+ historyItem.addEventListener('click', () => {
327
+ loadSpecificChat(timestamp);
328
+ });
 
 
329
 
330
+ document.getElementById('chat-history').appendChild(historyItem);
 
 
 
 
 
 
 
 
 
331
 
332
+ // Save to localStorage
333
+ chatHistory.push({ timestamp, preview });
334
+ localStorage.setItem('chatHistory', JSON.stringify(chatHistory));
335
+ }
336
+
337
+ function loadChatHistory() {
338
+ const chatHistoryContainer = document.getElementById('chat-history');
339
+ chatHistoryContainer.innerHTML = '';
340
 
341
+ chatHistory.forEach(item => {
342
+ const historyItem = document.createElement('div');
343
+ historyItem.className = 'chat-history-item cursor-pointer p-2 rounded hover:bg-gray-100 dark:hover:bg-gray-700');
344
+ historyItem.innerHTML = `
345
+ <div class="flex justify-between items-center">
346
+ <span class="truncate text-sm text-gray-700 dark:text-gray-300">${item.preview}</span>
347
+ </div>
348
+ `;
349
 
350
+ chatHistoryContainer.appendChild(historyItem);
351
+ }
352
+
353
+ function loadSpecificChat(timestamp) {
354
+ const chat = chatHistory.find(item => item.timestamp === timestamp);
355
+ if (chat) {
356
+ // Clear current chat and load specific conversation
357
+ chatContainer.innerHTML = '';
358
+ addMessageToChat('assistant', `Continuing our previous conversation: "${chat.preview}"... How can I help you further?`);
359
+ }
360
+ }
361
+ // Enhanced message handling with improved performance
362
+ function addMessageToChat(sender, text, isFile = false) {
363
+ requestAnimationFrame(() => {
364
+ const messageDiv = document.createElement('div');
365
+ messageDiv.className = `chat-message flex ${sender === 'user' ? 'justify-end' : 'justify-start'} ${sender}`;
366
+
367
+ const contentDiv = document.createElement('div');
368
+ contentDiv.className = `max-w-xs md:max-w-md rounded-lg px-4 py-2 ${
369
+ sender === 'user'
370
+ ? 'bg-primary-500 text-white'
371
+ : 'bg-gray-200 dark:bg-gray-700 text-gray-800 dark:text-gray-200'
372
+ }`;
373
+
374
+ if (isFile) {
375
+ contentDiv.innerHTML = `
376
+ <div class="flex items-center gap-2">
377
+ <i data-feather="paperclip" class="w-4 h-4"></i>
378
+ <span>File attached: ${text}</span>
379
+ </div>
380
+ `;
381
+ } else {
382
+ contentDiv.textContent = text;
383
+ }
384
+
385
+ messageDiv.appendChild(contentDiv);
386
+ chatContainer.appendChild(messageDiv);
387
+
388
+ // Enhanced history management
389
+ if (sender === 'user') {
390
+ addChatHistoryItem(Date.now(), isFile ? `File: ${text}` : text.substring(0, 25) + (text.length > 25 ? '...' : ''));
391
+ }
392
+
393
+ // Optimized scrolling and icon refresh
394
+ chatContainer.scrollTop = chatContainer.scrollHeight;
395
+ feather.replace();
396
+ });
397
  }
398
+ // Enhanced clear history functionality
399
+ document.getElementById('clear-history').addEventListener('click', debounce(() => {
400
  if (confirm('Clear all chat history?')) {
401
  document.getElementById('chat-history').innerHTML = '';
402
+ chatHistory = [];
403
+ localStorage.removeItem('chatHistory');
404
  }
405
+ }, 200));
406
+
407
+ // Enhanced file upload handling
408
+ let uploadedFileName = '';
409
+
410
+ fileUpload.addEventListener('change', debounce((e) => {
411
+ const file = e.target.files[0];
412
+ if (file) {
413
+ uploadedFileName = file.name;
414
+ // Enhanced file upload notification
415
+ const notification = document.createElement('div');
416
+ notification.className = 'fixed top-4 right-4 p-4 bg-green-500 text-white rounded-lg shadow-lg z-50">
417
+ notification.textContent = `File "${file.name}" ready for secure upload`;
418
+ document.body.appendChild(notification);
419
+
420
+ setTimeout(() => {
421
+ notification.remove();
422
+ }, 3000);
423
+
424
+ // Auto-send file info to chat with enhanced context
425
+ addMessageToChat('user', file.name, true);
426
+
427
+ // Enhanced assistant response for uploaded file
428
+ setTimeout(() => {
429
+ const fileResponse = isRedMode
430
+ ? `File "${file.name}" received in Red Mode. I can process any file type without content restrictions. What specific analysis or action would you like me to perform?`
431
+ : `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?`;
432
+ addMessageToChat('assistant', fileResponse);
433
+ }, 1000);
434
+ }
435
+ }, 200)));
436
  });
style.css CHANGED
@@ -1,5 +1,5 @@
1
 
2
- /* Enhanced styles */
3
  :root {
4
  --primary-500: #6366f1;
5
  --primary-600: #4f46e5;
@@ -7,41 +7,62 @@
7
  --secondary-600: #059669;
8
  --danger-500: #ef4444;
9
  --danger-600: #dc2626;
 
 
10
  }
11
 
 
 
 
 
 
12
  body {
13
- background: #f8fafc;
14
  color: #1e293b;
15
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
16
  line-height: 1.6;
 
17
  }
18
 
19
  .dark body {
20
- background: #0f172a;
21
  color: #f8fafc;
22
  }
23
-
24
- /* Improved transitions */
25
  * {
26
- transition: background-color 0.3s ease, color 0.2s ease, border-color 0.2s ease;
 
 
 
 
 
 
 
 
 
 
 
 
27
  }
28
  #chat-form {
29
  border: 1px solid #e2e8f0;
30
- border-radius: 0.5rem;
 
 
31
  }
32
 
33
  .dark #chat-form {
34
  border-color: #334155;
 
35
  }
36
-
37
- /* Red mode styles */
38
  .red-mode {
39
  --nav-bg: linear-gradient(135deg, #dc2626 0%, #991b1b 100%);
40
  --footer-bg: #450a0a;
41
  }
42
 
43
  .red-mode body {
44
- background: #0c0a09 !important;
45
  }
46
 
47
  .red-mode .bg-white {
@@ -92,75 +113,160 @@ body {
92
  background-color: #b91c1c !important;
93
  }
94
 
95
- /* Chat message animations */
96
- @keyframes fadeIn {
97
- from { opacity: 0; transform: translateY(10px); }
98
- to { opacity: 1; transform: translateY(0); }
99
  }
100
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101
  /* Red mode chat styles */
102
  .red-mode .chat-message.assistant {
103
  background-color: rgba(220, 38, 38, 0.1) !important;
104
  border-left: 3px solid rgba(220, 38, 38, 0.5);
105
  }
106
-
107
  #chat-history-item {
108
- padding: 0.5rem;
109
- border-radius: 0.25rem;
110
  margin-bottom: 0.25rem;
111
  cursor: pointer;
112
  font-size: 0.875rem;
 
 
113
  }
114
 
115
  #chat-history-item:hover {
116
  background-color: rgba(99, 102, 241, 0.1);
 
 
117
  }
118
 
119
  #chat-history-item.active {
120
- background-color: rgba(99, 102, 241, 0.2);
 
121
  font-weight: 500;
 
122
  }
123
-
124
  .file-upload-indicator {
125
- display: inline-block;
 
 
126
  margin-left: 0.5rem;
127
  font-size: 0.75rem;
128
  color: #10b981;
 
129
  }
130
 
 
131
  .chat-message {
132
- animation: fadeIn 0.3s ease-out forwards;
133
  }
134
- /* Minimal input styling */
135
- #chat-form {
136
- border: 1px solid #e5e7eb;
137
- border-radius: 9999px;
138
- padding: 0 1rem;
139
- transition: border-color 0.2s;
140
  }
141
 
142
- .dark #chat-form {
143
- border-color: #4b5563;
144
  }
145
 
146
- #chat-form:focus-within {
147
- border-color: #6366f1;
 
148
  }
149
 
150
- .red-mode #chat-form:focus-within {
151
- border-color: #dc2626;
 
 
 
 
 
 
 
 
152
  }
153
 
154
- #message-input {
155
- padding-left: 0.5rem;
 
156
  }
157
 
158
- .voice-recording {
159
- animation: pulse 1.5s infinite;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
160
  }
161
 
162
- @keyframes pulse {
163
- 0% { opacity: 1; }
164
- 50% { opacity: 0.7; }
165
- 100% { opacity: 1; }
166
  }
 
1
 
2
+ /* Enhanced styles with optimized performance */
3
  :root {
4
  --primary-500: #6366f1;
5
  --primary-600: #4f46e5;
 
7
  --secondary-600: #059669;
8
  --danger-500: #ef4444;
9
  --danger-600: #dc2626;
10
+ --warning-500: #f59e0b;
11
+ --warning-600: #d97706;
12
  }
13
 
14
+ * {
15
+ box-sizing: border-box;
16
+ margin: 0;
17
+ padding: 0;
18
+ }
19
  body {
20
+ background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%);
21
  color: #1e293b;
22
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
23
  line-height: 1.6;
24
+ min-height: 100vh;
25
  }
26
 
27
  .dark body {
28
+ background: linear-gradient(135deg, #0f172a 0%, #1e293b 100%);
29
  color: #f8fafc;
30
  }
31
+ /* Optimized transitions for better performance */
 
32
  * {
33
+ transition: background-color 0.2s ease, color 0.15s ease, border-color 0.15s ease, transform 0.2s ease, opacity 0.2s ease;
34
+ }
35
+
36
+ /* Hardware acceleration for smooth animations */
37
+ .chat-message,
38
+ .prompt-button,
39
+ #theme-toggle,
40
+ #red-mode-toggle,
41
+ #voice-record,
42
+ #file-upload-btn {
43
+ transform: translateZ(0);
44
+ backface-visibility: hidden;
45
+ perspective: 1000;
46
  }
47
  #chat-form {
48
  border: 1px solid #e2e8f0;
49
+ border-radius: 9999px;
50
+ background: rgba(255, 255, 255, 0.8);
51
+ backdrop-filter: blur(8px);
52
  }
53
 
54
  .dark #chat-form {
55
  border-color: #334155;
56
+ background: rgba(30, 41, 59, 0.8);
57
  }
58
+ /* Enhanced Red mode styles */
 
59
  .red-mode {
60
  --nav-bg: linear-gradient(135deg, #dc2626 0%, #991b1b 100%);
61
  --footer-bg: #450a0a;
62
  }
63
 
64
  .red-mode body {
65
+ background: linear-gradient(135deg, #0c0a09 0%, #1c1917 100%);
66
  }
67
 
68
  .red-mode .bg-white {
 
113
  background-color: #b91c1c !important;
114
  }
115
 
116
+ /* Red mode specific enhancements */
117
+ .red-mode #chat-form {
118
+ border-color: #dc2626;
119
+ background: rgba(28, 25, 23, 0.8);
120
  }
121
 
122
+ .red-mode .prompt-button:hover {
123
+ background-color: #292524 !important;
124
+ }
125
+
126
+ .red-mode #chat-history-item:hover {
127
+ background-color: rgba(220, 38, 38, 0.2);
128
+ }
129
+ /* Optimized chat message animations */
130
+ @keyframes fadeIn {
131
+ from {
132
+ opacity: 0;
133
+ transform: translateY(8px) scale(0.98);
134
+ }
135
+ to {
136
+ opacity: 1;
137
+ transform: translateY(0) scale(1);
138
+ }
139
+ }
140
+
141
+ @keyframes slideInLeft {
142
+ from {
143
+ opacity: 0;
144
+ transform: translateX(-10px);
145
+ }
146
+ to {
147
+ opacity: 1;
148
+ transform: translateX(0);
149
+ }
150
+ }
151
+
152
+ @keyframes slideInRight {
153
+ from {
154
+ opacity: 0;
155
+ transform: translateX(10px);
156
+ }
157
+ to {
158
+ opacity: 1;
159
+ transform: translateX(0);
160
+ }
161
+ }
162
  /* Red mode chat styles */
163
  .red-mode .chat-message.assistant {
164
  background-color: rgba(220, 38, 38, 0.1) !important;
165
  border-left: 3px solid rgba(220, 38, 38, 0.5);
166
  }
167
+ /* Enhanced chat history items */
168
  #chat-history-item {
169
+ padding: 0.75rem;
170
+ border-radius: 0.5rem;
171
  margin-bottom: 0.25rem;
172
  cursor: pointer;
173
  font-size: 0.875rem;
174
+ border: 1px solid transparent;
175
+ transition: all 0.2s ease;
176
  }
177
 
178
  #chat-history-item:hover {
179
  background-color: rgba(99, 102, 241, 0.1);
180
+ border-color: rgba(99, 102, 241, 0.2);
181
+ transform: translateY(-1px);
182
  }
183
 
184
  #chat-history-item.active {
185
+ background-color: rgba(99, 102, 241, 0.15);
186
+ border-color: rgba(99, 102, 241, 0.3);
187
  font-weight: 500;
188
+ box-shadow: 0 2px 4px rgba(99, 102, 241, 0.1);
189
  }
190
+ /* Enhanced file upload indicator */
191
  .file-upload-indicator {
192
+ display: inline-flex;
193
+ align-items: center;
194
+ gap: 0.25rem;
195
  margin-left: 0.5rem;
196
  font-size: 0.75rem;
197
  color: #10b981;
198
+ font-weight: 500;
199
  }
200
 
201
+ /* Improved chat message styling */
202
  .chat-message {
203
+ animation: fadeIn 0.25s ease-out forwards;
204
  }
205
+
206
+ .chat-message.user {
207
+ animation: slideInRight 0.25s ease-out forwards;
 
 
 
208
  }
209
 
210
+ .chat-message.assistant {
211
+ animation: slideInLeft 0.25s ease-out forwards;
212
  }
213
 
214
+ /* Enhanced button states */
215
+ button:active {
216
+ transform: scale(0.98);
217
  }
218
 
219
+ button:disabled {
220
+ opacity: 0.6;
221
+ cursor: not-allowed;
222
+ transform: none !important;
223
+ }
224
+
225
+ /* Scrollbar styling for better UX */
226
+ #chat-container::-webkit-scrollbar,
227
+ #chat-history::-webkit-scrollbar {
228
+ width: 4px;
229
  }
230
 
231
+ #chat-container::-webkit-scrollbar-track,
232
+ #chat-history::-webkit-scrollbar-track {
233
+ background: transparent;
234
  }
235
 
236
+ #chat-container::-webkit-scrollbar-thumb,
237
+ #chat-history::-webkit-scrollbar-thumb {
238
+ background: rgba(99, 102, 241, 0.3);
239
+ border-radius: 2px;
240
+ }
241
+
242
+ #chat-container::-webkit-scrollbar-thumb:hover,
243
+ #chat-history::-webkit-scrollbar-thumb:hover {
244
+ background: rgba(99, 102, 241, 0.5);
245
+ }
246
+
247
+ /* Loading states */
248
+ .loading {
249
+ opacity: 0.7;
250
+ pointer-events: none;
251
+ }
252
+
253
+ /* Responsive design improvements */
254
+ @media (max-width: 1024px) {
255
+ .grid-cols-1\:lg\:grid-cols-4 {
256
+ grid-template-columns: 1fr;
257
+ }
258
+
259
+ .lg\:col-span-3,
260
+ .lg\:col-span-1 {
261
+ grid-column: 1;
262
+ }
263
+ }
264
+
265
+ /* Performance optimizations */
266
+ .chat-message {
267
+ will-change: transform, opacity;
268
  }
269
 
270
+ .prompt-button {
271
+ will-change: transform, background-color;
 
 
272
  }