active les fonctionalité
Browse files- chat.html +90 -20
- components/navbar.js +6 -3
- index.html +52 -11
chat.html
CHANGED
|
@@ -51,9 +51,9 @@
|
|
| 51 |
<div class="flex flex-wrap items-center gap-4">
|
| 52 |
<div class="status-pill flex items-center px-3 py-1 rounded-full text-sm bg-green-900/30 text-green-400">
|
| 53 |
<i data-feather="check-circle" class="w-4 h-4 mr-1"></i>
|
| 54 |
-
<span>Connected</span>
|
| 55 |
</div>
|
| 56 |
-
|
| 57 |
<i data-feather="clock" class="w-5 h-5"></i>
|
| 58 |
<span class="text-sm" id="current-time">14:45:32</span>
|
| 59 |
</div>
|
|
@@ -199,41 +199,92 @@
|
|
| 199 |
feather.replace();
|
| 200 |
chatMessages.scrollTop = chatMessages.scrollHeight;
|
| 201 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 202 |
|
| 203 |
// Simulate AI response streaming
|
| 204 |
async function simulateAIResponse(userMessage) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 205 |
// Show typing indicator
|
| 206 |
typingIndicator.classList.remove('hidden');
|
| 207 |
chatMessages.scrollTop = chatMessages.scrollHeight;
|
| 208 |
|
| 209 |
-
// Simulate API delay
|
| 210 |
-
|
|
|
|
| 211 |
|
| 212 |
// Hide typing indicator
|
| 213 |
typingIndicator.classList.add('hidden');
|
| 214 |
|
| 215 |
-
// Simulated responses based on user input
|
| 216 |
let response = "";
|
| 217 |
const lowerMsg = userMessage.toLowerCase();
|
| 218 |
|
| 219 |
-
if (lowerMsg.includes("hello") || lowerMsg.includes("hi")) {
|
| 220 |
-
|
| 221 |
-
|
| 222 |
-
|
| 223 |
-
|
| 224 |
-
|
| 225 |
-
|
| 226 |
-
|
| 227 |
-
|
| 228 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 229 |
} else {
|
| 230 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 231 |
}
|
| 232 |
|
| 233 |
addMessage('ai', response);
|
| 234 |
}
|
| 235 |
-
|
| 236 |
-
// Handle form submission
|
| 237 |
chatForm.addEventListener('submit', async (e) => {
|
| 238 |
e.preventDefault();
|
| 239 |
|
|
@@ -247,7 +298,6 @@
|
|
| 247 |
// Get AI response
|
| 248 |
await simulateAIResponse(message);
|
| 249 |
});
|
| 250 |
-
|
| 251 |
// Allow sending with Enter key
|
| 252 |
userInput.addEventListener('keypress', (e) => {
|
| 253 |
if (e.key === 'Enter' && !e.shiftKey) {
|
|
@@ -255,6 +305,26 @@
|
|
| 255 |
chatForm.dispatchEvent(new Event('submit'));
|
| 256 |
}
|
| 257 |
});
|
| 258 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 259 |
</body>
|
| 260 |
</html>
|
|
|
|
| 51 |
<div class="flex flex-wrap items-center gap-4">
|
| 52 |
<div class="status-pill flex items-center px-3 py-1 rounded-full text-sm bg-green-900/30 text-green-400">
|
| 53 |
<i data-feather="check-circle" class="w-4 h-4 mr-1"></i>
|
| 54 |
+
<span id="connection-status">Connected</span>
|
| 55 |
</div>
|
| 56 |
+
<div class="flex items-center space-x-1">
|
| 57 |
<i data-feather="clock" class="w-5 h-5"></i>
|
| 58 |
<span class="text-sm" id="current-time">14:45:32</span>
|
| 59 |
</div>
|
|
|
|
| 199 |
feather.replace();
|
| 200 |
chatMessages.scrollTop = chatMessages.scrollHeight;
|
| 201 |
}
|
| 202 |
+
// Connection status simulation
|
| 203 |
+
let isConnected = true;
|
| 204 |
+
|
| 205 |
+
function updateConnectionStatus() {
|
| 206 |
+
const statusElement = document.getElementById('connection-status');
|
| 207 |
+
if (isConnected) {
|
| 208 |
+
statusElement.textContent = 'Connected';
|
| 209 |
+
statusElement.parentElement.className = 'status-pill flex items-center px-3 py-1 rounded-full text-sm bg-green-900/30 text-green-400';
|
| 210 |
+
} else {
|
| 211 |
+
statusElement.textContent = 'Disconnected';
|
| 212 |
+
statusElement.parentElement.className = 'status-pill flex items-center px-3 py-1 rounded-full text-sm bg-red-900/30 text-red-400';
|
| 213 |
+
}
|
| 214 |
+
}
|
| 215 |
+
|
| 216 |
+
// Simulate connection issues randomly
|
| 217 |
+
setInterval(() => {
|
| 218 |
+
if (Math.random() > 0.8) {
|
| 219 |
+
isConnected = !isConnected;
|
| 220 |
+
updateConnectionStatus();
|
| 221 |
+
|
| 222 |
+
if (!isConnected) {
|
| 223 |
+
addMessage('ai', 'Warning: Connection to Mission Control has been lost. Attempting to reestablish...');
|
| 224 |
+
} else {
|
| 225 |
+
addMessage('ai', 'Connection restored. Mission Control is now online.');
|
| 226 |
+
}
|
| 227 |
+
}
|
| 228 |
+
}, 15000);
|
| 229 |
|
| 230 |
// Simulate AI response streaming
|
| 231 |
async function simulateAIResponse(userMessage) {
|
| 232 |
+
// Check connection first
|
| 233 |
+
if (!isConnected) {
|
| 234 |
+
addMessage('ai', 'Unable to process request: No connection to Mission Control. Please check your communication systems.');
|
| 235 |
+
return;
|
| 236 |
+
}
|
| 237 |
+
|
| 238 |
// Show typing indicator
|
| 239 |
typingIndicator.classList.remove('hidden');
|
| 240 |
chatMessages.scrollTop = chatMessages.scrollHeight;
|
| 241 |
|
| 242 |
+
// Simulate variable API delay
|
| 243 |
+
const delay = 500 + Math.random() * 1500;
|
| 244 |
+
await new Promise(resolve => setTimeout(resolve, delay));
|
| 245 |
|
| 246 |
// Hide typing indicator
|
| 247 |
typingIndicator.classList.add('hidden');
|
| 248 |
|
| 249 |
+
// Simulated responses based on user input with more variety
|
| 250 |
let response = "";
|
| 251 |
const lowerMsg = userMessage.toLowerCase();
|
| 252 |
|
| 253 |
+
if (lowerMsg.includes("hello") || lowerMsg.includes("hi") || lowerMsg.includes("hey")) {
|
| 254 |
+
const greetings = [
|
| 255 |
+
"Greetings, operative. How can I assist with your mission today?",
|
| 256 |
+
"Hello! Ready to support your operational needs. What can I do for you?",
|
| 257 |
+
"Hi there! I'm monitoring all channels. What's your request?"
|
| 258 |
+
];
|
| 259 |
+
response = greetings[Math.floor(Math.random() * greetings.length)];
|
| 260 |
+
} else if (lowerMsg.includes("emergency") || lowerMsg.includes("help") || lowerMsg.includes("mayday")) {
|
| 261 |
+
response = "CRITICAL ALERT: Emergency protocols activated. Contacting Mission Control immediately on Channel 1. Please state your emergency clearly.";
|
| 262 |
+
} else if (lowerMsg.includes("procedure") || lowerMsg.includes("protocol") || lowerMsg.includes("sop")) {
|
| 263 |
+
response = "Accessing Standard Operating Procedures database... Please specify which protocol you require:\n- Emergency Evacuation\n- Medical Response\n- Security Breach\n- Equipment Failure";
|
| 264 |
+
} else if (lowerMsg.includes("location") || lowerMsg.includes("position") || lowerMsg.includes("where")) {
|
| 265 |
+
response = "Integrating GPS tracking systems...\nLatest known positions:\n- John Smith: Sector 7 (40.74844°N, -73.98566°W)\n- Maria Garcia: Base Camp (40.74890°N, -73.98750°W)\n- Robert Johnson: Sector 3 (40.74780°N, -73.98620°W)";
|
| 266 |
+
} else if (lowerMsg.includes("weather") || lowerMsg.includes("climate") || lowerMsg.includes("conditions")) {
|
| 267 |
+
response = "Accessing meteorological data...\nCurrent Conditions:\n- Visibility: Excellent (10km+)\n- Temperature: 22°C (72°F)\n- Wind: 5 km/h NE\n- Atmospheric Pressure: Stable\n- Precipitation: None forecasted";
|
| 268 |
+
} else if (lowerMsg.includes("status") || lowerMsg.includes("update") || lowerMsg.includes("report")) {
|
| 269 |
+
response = "System Status Report:\n- Network: Online\n- GPS: Active\n- Signal Strength: Good\n- Battery: 85%\n- Team Members: 3 Online\nAll systems functioning within normal parameters.";
|
| 270 |
+
} else if (lowerMsg.includes("channel") || lowerMsg.includes("frequency") || lowerMsg.includes("communication")) {
|
| 271 |
+
response = "Communication Channels Status:\n- Channel 1 (Operations): Active\n- Channel 2 (Logistics): Active\n- Channel 3 (Medical): Active\n- Channel 4 (Security): Active\nAll channels monitored and operational.";
|
| 272 |
} else {
|
| 273 |
+
const responses = [
|
| 274 |
+
"Acknowledged. Processing your request...",
|
| 275 |
+
"Understood. I've logged this information in the system.",
|
| 276 |
+
"Confirmed. All team members notified.",
|
| 277 |
+
"Analyzing your query... Operational parameters remain stable.",
|
| 278 |
+
"Request received. Cross-referencing with mission protocols...",
|
| 279 |
+
"Data processed. No anomalies detected in current operations.",
|
| 280 |
+
"Command understood. Executing requested action sequence."
|
| 281 |
+
];
|
| 282 |
+
response = responses[Math.floor(Math.random() * responses.length)];
|
| 283 |
}
|
| 284 |
|
| 285 |
addMessage('ai', response);
|
| 286 |
}
|
| 287 |
+
// Handle form submission
|
|
|
|
| 288 |
chatForm.addEventListener('submit', async (e) => {
|
| 289 |
e.preventDefault();
|
| 290 |
|
|
|
|
| 298 |
// Get AI response
|
| 299 |
await simulateAIResponse(message);
|
| 300 |
});
|
|
|
|
| 301 |
// Allow sending with Enter key
|
| 302 |
userInput.addEventListener('keypress', (e) => {
|
| 303 |
if (e.key === 'Enter' && !e.shiftKey) {
|
|
|
|
| 305 |
chatForm.dispatchEvent(new Event('submit'));
|
| 306 |
}
|
| 307 |
});
|
| 308 |
+
|
| 309 |
+
// Add click handler for settings button
|
| 310 |
+
document.querySelector('.settings-btn').addEventListener('click', function() {
|
| 311 |
+
alert('AI Assistant settings would open here in a full implementation.');
|
| 312 |
+
});
|
| 313 |
+
|
| 314 |
+
// Simulate periodic status updates
|
| 315 |
+
setInterval(() => {
|
| 316 |
+
if (isConnected && Math.random() > 0.7) {
|
| 317 |
+
const statuses = [
|
| 318 |
+
"Mission Control reports all systems nominal.",
|
| 319 |
+
"Weather conditions remain stable across all sectors.",
|
| 320 |
+
"All team members accounted for and reporting normal status.",
|
| 321 |
+
"Communications network integrity at 98.7% efficiency.",
|
| 322 |
+
"Power levels maintaining optimal charge across all units."
|
| 323 |
+
];
|
| 324 |
+
const randomStatus = statuses[Math.floor(Math.random() * statuses.length)];
|
| 325 |
+
addMessage('ai', `[SYSTEM UPDATE] ${randomStatus}`);
|
| 326 |
+
}
|
| 327 |
+
}, 30000);
|
| 328 |
+
</script>
|
| 329 |
</body>
|
| 330 |
</html>
|
components/navbar.js
CHANGED
|
@@ -50,7 +50,10 @@ class CustomNavbar extends HTMLElement {
|
|
| 50 |
.nav-link.active {
|
| 51 |
color: #60a5fa;
|
| 52 |
}
|
| 53 |
-
|
|
|
|
|
|
|
|
|
|
| 54 |
.nav-container {
|
| 55 |
flex-direction: column;
|
| 56 |
gap: 1rem;
|
|
@@ -68,7 +71,7 @@ class CustomNavbar extends HTMLElement {
|
|
| 68 |
<span>ComSync Pro</span>
|
| 69 |
</a>
|
| 70 |
<div class="nav-links">
|
| 71 |
-
<a href="/" class="nav-link">
|
| 72 |
<i data-feather="map"></i>
|
| 73 |
<span>Dashboard</span>
|
| 74 |
</a>
|
|
@@ -77,7 +80,7 @@ class CustomNavbar extends HTMLElement {
|
|
| 77 |
<span>AI Assistant</span>
|
| 78 |
</a>
|
| 79 |
</div>
|
| 80 |
-
|
| 81 |
</nav>
|
| 82 |
`;
|
| 83 |
|
|
|
|
| 50 |
.nav-link.active {
|
| 51 |
color: #60a5fa;
|
| 52 |
}
|
| 53 |
+
.nav-link.active i {
|
| 54 |
+
color: #60a5fa;
|
| 55 |
+
}
|
| 56 |
+
@media (max-width: 768px) {
|
| 57 |
.nav-container {
|
| 58 |
flex-direction: column;
|
| 59 |
gap: 1rem;
|
|
|
|
| 71 |
<span>ComSync Pro</span>
|
| 72 |
</a>
|
| 73 |
<div class="nav-links">
|
| 74 |
+
<a href="/" class="nav-link active">
|
| 75 |
<i data-feather="map"></i>
|
| 76 |
<span>Dashboard</span>
|
| 77 |
</a>
|
|
|
|
| 80 |
<span>AI Assistant</span>
|
| 81 |
</a>
|
| 82 |
</div>
|
| 83 |
+
</div>
|
| 84 |
</nav>
|
| 85 |
`;
|
| 86 |
|
index.html
CHANGED
|
@@ -278,7 +278,7 @@
|
|
| 278 |
<i data-feather="minus" class="w-4 h-4 text-gray-700"></i>
|
| 279 |
</button>
|
| 280 |
</div>
|
| 281 |
-
</div>
|
| 282 |
</div>
|
| 283 |
|
| 284 |
<!-- Selected Member Details -->
|
|
@@ -315,19 +315,18 @@
|
|
| 315 |
</div>
|
| 316 |
</div>
|
| 317 |
</div>
|
| 318 |
-
|
| 319 |
-
<!-- Communication Panel -->
|
| 320 |
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
| 321 |
<!-- Transmit Panel -->
|
| 322 |
<div class="bg-gray-800/80 backdrop-blur-md rounded-xl p-5 border border-gray-700/50 shadow-lg">
|
| 323 |
<div class="flex justify-between items-center mb-4">
|
| 324 |
<h2 class="text-lg font-semibold"><span id="current-channel">Channel 1</span> - Operations</h2>
|
| 325 |
<div class="flex items-center space-x-2">
|
| 326 |
-
<div class="w-2 h-2 rounded-full bg-green-500"></div>
|
| 327 |
<span class="text-xs">READY</span>
|
| 328 |
</div>
|
| 329 |
</div>
|
| 330 |
-
|
| 331 |
<div class="flex justify-center my-6">
|
| 332 |
<button id="transmit-btn" class="transmit-btn w-24 h-24 rounded-full bg-blue-600 hover:bg-blue-500 hover:scale-105 transition-all flex items-center justify-center shadow-lg">
|
| 333 |
<i data-feather="mic" class="w-10 h-10 text-white"></i>
|
|
@@ -690,7 +689,6 @@
|
|
| 690 |
document.getElementById('video-call-btn').addEventListener('click', () => {
|
| 691 |
alert(`Initiating video call with ${currentSelectedMember}...`);
|
| 692 |
});
|
| 693 |
-
|
| 694 |
// Simulate real-time data updates
|
| 695 |
function simulateRealTimeUpdates() {
|
| 696 |
// Update battery levels
|
|
@@ -702,10 +700,11 @@
|
|
| 702 |
});
|
| 703 |
|
| 704 |
// Update main battery indicator
|
| 705 |
-
const
|
| 706 |
-
if (
|
| 707 |
-
const
|
| 708 |
-
|
|
|
|
| 709 |
}
|
| 710 |
|
| 711 |
// Update selected member if needed
|
|
@@ -725,12 +724,54 @@
|
|
| 725 |
bar.classList.add('bg-gray-600');
|
| 726 |
}
|
| 727 |
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 728 |
}
|
| 729 |
|
| 730 |
// Run updates every 5 seconds
|
| 731 |
setInterval(simulateRealTimeUpdates, 5000);
|
| 732 |
|
| 733 |
-
//
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 734 |
document.addEventListener('keydown', (e) => {
|
| 735 |
if (e.code === 'Space' && !transmitActive && !e.target.matches('input')) {
|
| 736 |
e.preventDefault();
|
|
|
|
| 278 |
<i data-feather="minus" class="w-4 h-4 text-gray-700"></i>
|
| 279 |
</button>
|
| 280 |
</div>
|
| 281 |
+
</div>
|
| 282 |
</div>
|
| 283 |
|
| 284 |
<!-- Selected Member Details -->
|
|
|
|
| 315 |
</div>
|
| 316 |
</div>
|
| 317 |
</div>
|
| 318 |
+
<!-- Communication Panel -->
|
|
|
|
| 319 |
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
| 320 |
<!-- Transmit Panel -->
|
| 321 |
<div class="bg-gray-800/80 backdrop-blur-md rounded-xl p-5 border border-gray-700/50 shadow-lg">
|
| 322 |
<div class="flex justify-between items-center mb-4">
|
| 323 |
<h2 class="text-lg font-semibold"><span id="current-channel">Channel 1</span> - Operations</h2>
|
| 324 |
<div class="flex items-center space-x-2">
|
| 325 |
+
<div class="w-2 h-2 rounded-full bg-green-500 animate-pulse"></div>
|
| 326 |
<span class="text-xs">READY</span>
|
| 327 |
</div>
|
| 328 |
</div>
|
| 329 |
+
<!-- Transmit Button -->
|
| 330 |
<div class="flex justify-center my-6">
|
| 331 |
<button id="transmit-btn" class="transmit-btn w-24 h-24 rounded-full bg-blue-600 hover:bg-blue-500 hover:scale-105 transition-all flex items-center justify-center shadow-lg">
|
| 332 |
<i data-feather="mic" class="w-10 h-10 text-white"></i>
|
|
|
|
| 689 |
document.getElementById('video-call-btn').addEventListener('click', () => {
|
| 690 |
alert(`Initiating video call with ${currentSelectedMember}...`);
|
| 691 |
});
|
|
|
|
| 692 |
// Simulate real-time data updates
|
| 693 |
function simulateRealTimeUpdates() {
|
| 694 |
// Update battery levels
|
|
|
|
| 700 |
});
|
| 701 |
|
| 702 |
// Update main battery indicator
|
| 703 |
+
const batteryElement = document.querySelector('.flex.items-center.space-x-1:nth-child(3) span');
|
| 704 |
+
if (batteryElement) {
|
| 705 |
+
const currentBattery = parseInt(batteryElement.textContent);
|
| 706 |
+
const newBattery = Math.max(0, currentBattery - Math.floor(Math.random() * 2));
|
| 707 |
+
batteryElement.textContent = `${newBattery}%`;
|
| 708 |
}
|
| 709 |
|
| 710 |
// Update selected member if needed
|
|
|
|
| 724 |
bar.classList.add('bg-gray-600');
|
| 725 |
}
|
| 726 |
});
|
| 727 |
+
|
| 728 |
+
// Update last seen time
|
| 729 |
+
const lastSeenElement = document.getElementById('last-seen');
|
| 730 |
+
if (lastSeenElement) {
|
| 731 |
+
const minutes = Math.floor(Math.random() * 10) + 1;
|
| 732 |
+
lastSeenElement.textContent = `${minutes} minute${minutes > 1 ? 's' : ''} ago`;
|
| 733 |
+
}
|
| 734 |
}
|
| 735 |
|
| 736 |
// Run updates every 5 seconds
|
| 737 |
setInterval(simulateRealTimeUpdates, 5000);
|
| 738 |
|
| 739 |
+
// Add click handler for map controls
|
| 740 |
+
document.getElementById('map-zoom-in').addEventListener('click', function() {
|
| 741 |
+
this.classList.add('bg-gray-300');
|
| 742 |
+
setTimeout(() => this.classList.remove('bg-gray-300'), 200);
|
| 743 |
+
});
|
| 744 |
+
|
| 745 |
+
document.getElementById('map-zoom-out').addEventListener('click', function() {
|
| 746 |
+
this.classList.add('bg-gray-300');
|
| 747 |
+
setTimeout(() => this.classList.remove('bg-gray-300'), 200);
|
| 748 |
+
});
|
| 749 |
+
|
| 750 |
+
// Add click handlers for recent communications
|
| 751 |
+
document.querySelectorAll('.bg-gray-700\\/50.p-3.rounded-lg').forEach(item => {
|
| 752 |
+
item.addEventListener('click', function() {
|
| 753 |
+
const channel = this.querySelector('.bg-gray-600\\/50').textContent;
|
| 754 |
+
const sender = this.querySelector('.font-medium').textContent;
|
| 755 |
+
|
| 756 |
+
// Highlight the clicked communication
|
| 757 |
+
document.querySelectorAll('.bg-gray-700\\/50.p-3.rounded-lg').forEach(el => {
|
| 758 |
+
el.classList.remove('bg-blue-900/20', 'border', 'border-blue-500');
|
| 759 |
+
});
|
| 760 |
+
this.classList.add('bg-blue-900/20', 'border', 'border-blue-500');
|
| 761 |
+
|
| 762 |
+
// Update channel if needed
|
| 763 |
+
if (channel === 'Channel 1') {
|
| 764 |
+
document.querySelectorAll('.channel-content').forEach(el => {
|
| 765 |
+
el.classList.remove('bg-blue-600/20', 'border-l-4', 'border-blue-400');
|
| 766 |
+
el.classList.add('bg-gray-700/50', 'hover:bg-gray-600/50');
|
| 767 |
+
});
|
| 768 |
+
document.querySelector('[data-channel="Channel 1"] .channel-content').classList.remove('bg-gray-700/50', 'hover:bg-gray-600/50');
|
| 769 |
+
document.querySelector('[data-channel="Channel 1"] .channel-content').classList.add('bg-blue-600/20', 'border-l-4', 'border-blue-400');
|
| 770 |
+
document.getElementById('current-channel').textContent = 'Channel 1';
|
| 771 |
+
}
|
| 772 |
+
});
|
| 773 |
+
});
|
| 774 |
+
// Keyboard shortcut for push-to-talk (Spacebar)
|
| 775 |
document.addEventListener('keydown', (e) => {
|
| 776 |
if (e.code === 'Space' && !transmitActive && !e.target.matches('input')) {
|
| 777 |
e.preventDefault();
|