mirror of
https://github.com/smittix/intercept.git
synced 2026-06-08 14:11:54 -07:00
fix: Resolve TSCM function strip visibility and clipping issues
- Fix function strip content being clipped by changing overflow to visible - Add min-height and increased padding to function strip - Add explicit colors for TSCM strip stat values and labels - Fix output-panel overflow for TSCM mode using :has() selector - Add CSS variables --bg-dark and --bg-panel aliases - Clean up sidebar section margins for consistent spacing - Add unique IDs to WiFi/Bluetooth export sections for restore function Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -6,9 +6,10 @@
|
||||
background: linear-gradient(180deg, var(--bg-panel) 0%, var(--bg-dark) 100%);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 6px;
|
||||
padding: 6px 12px;
|
||||
padding: 8px 12px;
|
||||
margin-bottom: 10px;
|
||||
overflow-x: auto;
|
||||
overflow: visible;
|
||||
min-height: 44px;
|
||||
}
|
||||
|
||||
.function-strip-inner {
|
||||
@@ -23,7 +24,7 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 4px 10px;
|
||||
padding: 6px 10px;
|
||||
background: rgba(74, 158, 255, 0.05);
|
||||
border: 1px solid rgba(74, 158, 255, 0.15);
|
||||
border-radius: 4px;
|
||||
@@ -307,16 +308,37 @@
|
||||
color: var(--accent-orange);
|
||||
}
|
||||
|
||||
.function-strip.tscm-strip {
|
||||
margin-top: 4px; /* Extra clearance to prevent top clipping */
|
||||
}
|
||||
|
||||
.function-strip.tscm-strip .strip-stat {
|
||||
background: rgba(255, 59, 48, 0.05);
|
||||
border-color: rgba(255, 59, 48, 0.15);
|
||||
background: rgba(255, 59, 48, 0.15);
|
||||
border: 1px solid rgba(255, 59, 48, 0.4);
|
||||
}
|
||||
.function-strip.tscm-strip .strip-stat:hover {
|
||||
background: rgba(255, 59, 48, 0.1);
|
||||
border-color: rgba(255, 59, 48, 0.3);
|
||||
background: rgba(255, 59, 48, 0.25);
|
||||
border-color: rgba(255, 59, 48, 0.6);
|
||||
}
|
||||
.function-strip.tscm-strip .strip-value {
|
||||
color: var(--accent-red);
|
||||
color: #ef4444; /* Explicit red color */
|
||||
}
|
||||
.function-strip.tscm-strip .strip-label {
|
||||
color: #9ca3af; /* Explicit light gray */
|
||||
}
|
||||
.function-strip.tscm-strip .strip-select {
|
||||
color: #e8eaed; /* Explicit white for selects */
|
||||
background: rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
.function-strip.tscm-strip .strip-btn {
|
||||
color: #e8eaed; /* Explicit white for buttons */
|
||||
}
|
||||
.function-strip.tscm-strip .strip-tool {
|
||||
color: #e8eaed; /* Explicit white for tool indicators */
|
||||
}
|
||||
.function-strip.tscm-strip .strip-time,
|
||||
.function-strip.tscm-strip .strip-status span {
|
||||
color: #9ca3af; /* Explicit gray for status/time */
|
||||
}
|
||||
|
||||
.function-strip.rtlamr-strip .strip-stat {
|
||||
|
||||
@@ -593,7 +593,7 @@
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
padding: 0 20px;
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
|
||||
@@ -17,6 +17,10 @@
|
||||
--bg-elevated: #1a202c;
|
||||
--bg-overlay: rgba(0, 0, 0, 0.7);
|
||||
|
||||
/* Background aliases for components */
|
||||
--bg-dark: var(--bg-primary);
|
||||
--bg-panel: var(--bg-secondary);
|
||||
|
||||
/* Accent colors */
|
||||
--accent-cyan: #4a9eff;
|
||||
--accent-cyan-dim: rgba(74, 158, 255, 0.15);
|
||||
@@ -150,6 +154,10 @@
|
||||
--bg-elevated: #f8fafc;
|
||||
--bg-overlay: rgba(255, 255, 255, 0.9);
|
||||
|
||||
/* Background aliases for components */
|
||||
--bg-dark: var(--bg-primary);
|
||||
--bg-panel: var(--bg-secondary);
|
||||
|
||||
--accent-cyan: #2563eb;
|
||||
--accent-cyan-dim: rgba(37, 99, 235, 0.1);
|
||||
--accent-cyan-hover: #1d4ed8;
|
||||
|
||||
@@ -1414,6 +1414,7 @@ header h1 .tagline {
|
||||
overflow: visible;
|
||||
padding: 12px;
|
||||
position: relative;
|
||||
margin: 0; /* Reset any inherited margins - spacing handled by parent gap */
|
||||
}
|
||||
|
||||
.section h3 {
|
||||
@@ -1590,6 +1591,101 @@ header h1 .tagline {
|
||||
border-color: var(--accent-cyan);
|
||||
}
|
||||
|
||||
/* WiFi Mode Tab Buttons */
|
||||
.wifi-mode-tab {
|
||||
flex: 1;
|
||||
padding: 8px;
|
||||
font-size: 11px;
|
||||
font-family: 'JetBrains Mono', monospace;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
background: var(--bg-tertiary);
|
||||
color: var(--text-secondary);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
transition: all 0.15s ease;
|
||||
}
|
||||
|
||||
.wifi-mode-tab:hover {
|
||||
background: var(--bg-secondary);
|
||||
color: var(--text-primary);
|
||||
border-color: var(--accent-cyan);
|
||||
}
|
||||
|
||||
.wifi-mode-tab.active {
|
||||
background: var(--accent-green);
|
||||
color: #000;
|
||||
border-color: var(--accent-green);
|
||||
}
|
||||
|
||||
.wifi-mode-tab.active:hover {
|
||||
background: #1db954;
|
||||
border-color: #1db954;
|
||||
}
|
||||
|
||||
/* WiFi Start/Stop Buttons */
|
||||
.wifi-start-btn {
|
||||
background: var(--accent-green) !important;
|
||||
color: #000 !important;
|
||||
border-color: var(--accent-green) !important;
|
||||
}
|
||||
|
||||
.wifi-start-btn:hover {
|
||||
background: #1db954 !important;
|
||||
border-color: #1db954 !important;
|
||||
box-shadow: 0 2px 8px rgba(34, 197, 94, 0.3);
|
||||
}
|
||||
|
||||
.wifi-stop-btn {
|
||||
background: var(--accent-red) !important;
|
||||
color: #fff !important;
|
||||
border-color: var(--accent-red) !important;
|
||||
}
|
||||
|
||||
.wifi-stop-btn:hover {
|
||||
background: #e62e50 !important;
|
||||
border-color: #e62e50 !important;
|
||||
box-shadow: 0 2px 8px rgba(255, 51, 102, 0.3);
|
||||
}
|
||||
|
||||
/* WiFi Monitor Mode Buttons */
|
||||
.wifi-monitor-btn {
|
||||
background: var(--accent-green) !important;
|
||||
color: #000 !important;
|
||||
border-color: var(--accent-green) !important;
|
||||
}
|
||||
|
||||
.wifi-monitor-btn:hover {
|
||||
background: #1db954 !important;
|
||||
border-color: #1db954 !important;
|
||||
box-shadow: 0 2px 8px rgba(34, 197, 94, 0.3);
|
||||
}
|
||||
|
||||
.wifi-monitor-stop-btn {
|
||||
background: var(--accent-orange) !important;
|
||||
color: #000 !important;
|
||||
border-color: var(--accent-orange) !important;
|
||||
}
|
||||
|
||||
.wifi-monitor-stop-btn:hover {
|
||||
background: #e68a00 !important;
|
||||
border-color: #e68a00 !important;
|
||||
box-shadow: 0 2px 8px rgba(255, 159, 28, 0.3);
|
||||
}
|
||||
|
||||
/* WiFi Danger/Attack Buttons */
|
||||
.wifi-danger-btn {
|
||||
border-color: var(--accent-red) !important;
|
||||
color: var(--accent-red) !important;
|
||||
}
|
||||
|
||||
.wifi-danger-btn:hover {
|
||||
background: var(--accent-red) !important;
|
||||
color: #fff !important;
|
||||
box-shadow: 0 2px 8px rgba(255, 51, 102, 0.3);
|
||||
}
|
||||
|
||||
.run-btn {
|
||||
width: 100%;
|
||||
padding: 12px;
|
||||
|
||||
@@ -32,12 +32,17 @@
|
||||
.threat-card.low.active { background: rgba(0,255,136,0.2); }
|
||||
|
||||
/* TSCM Dashboard */
|
||||
/* Ensure output-panel doesn't clip TSCM content */
|
||||
.output-panel:has(.tscm-dashboard) {
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.tscm-dashboard {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
overflow-y: auto;
|
||||
padding-bottom: 80px; /* Space for status bar */
|
||||
overflow: visible;
|
||||
padding: 20px 16px 80px 16px; /* Extra top padding for function strip visibility */
|
||||
}
|
||||
.tscm-threat-banner {
|
||||
display: flex;
|
||||
|
||||
@@ -227,6 +227,9 @@ function startScanner() {
|
||||
isScannerPaused = false;
|
||||
scannerSignalActive = false;
|
||||
|
||||
// Update listening strip
|
||||
updateListeningStripRunning(true);
|
||||
|
||||
// Update controls (with null checks)
|
||||
const startBtn = document.getElementById('scannerStartBtn');
|
||||
if (startBtn) {
|
||||
@@ -289,6 +292,9 @@ function stopScanner() {
|
||||
scannerSignalActive = false;
|
||||
currentSignalLevel = 0;
|
||||
|
||||
// Update listening strip
|
||||
updateListeningStripRunning(false);
|
||||
|
||||
// Re-enable listen button (will be in local mode after stop)
|
||||
updateListenButtonState(false);
|
||||
|
||||
@@ -572,6 +578,10 @@ function handleFrequencyUpdate(data) {
|
||||
const mainFreq = document.getElementById('mainScannerFreq');
|
||||
if (mainFreq) mainFreq.textContent = freqStr;
|
||||
|
||||
// Update function strip frequency
|
||||
const stripFreq = document.getElementById('listeningStripFreq');
|
||||
if (stripFreq) stripFreq.textContent = freqStr;
|
||||
|
||||
// Update progress bar
|
||||
const progress = ((data.frequency - scannerStartFreq) / (scannerEndFreq - scannerStartFreq)) * 100;
|
||||
const progressBar = document.getElementById('scannerProgressBar');
|
||||
@@ -622,6 +632,10 @@ function handleSignalFound(data) {
|
||||
const mainSignalCount = document.getElementById('mainSignalCount');
|
||||
if (mainSignalCount) mainSignalCount.textContent = scannerSignalCount;
|
||||
|
||||
// Update function strip signal count
|
||||
const stripSignals = document.getElementById('listeningStripSignals');
|
||||
if (stripSignals) stripSignals.textContent = scannerSignalCount;
|
||||
|
||||
// Update sidebar
|
||||
updateScannerDisplay('SIGNAL FOUND', 'var(--accent-green)');
|
||||
const signalPanel = document.getElementById('scannerSignalPanel');
|
||||
@@ -2597,3 +2611,81 @@ window.tuneToFrequency = tuneToFrequency;
|
||||
window.clearScannerLog = clearScannerLog;
|
||||
window.exportScannerLog = exportScannerLog;
|
||||
|
||||
// ============== FUNCTION STRIP SUPPORT ==============
|
||||
|
||||
/**
|
||||
* Update the listening post function strip running state
|
||||
*/
|
||||
function updateListeningStripRunning(running) {
|
||||
const listeningStripDot = document.getElementById('listeningStripDot');
|
||||
const listeningStripStatus = document.getElementById('listeningStripStatus');
|
||||
const listeningStripStartBtn = document.getElementById('listeningStripStartBtn');
|
||||
const listeningStripStopBtn = document.getElementById('listeningStripStopBtn');
|
||||
const listeningStripFreqInput = document.getElementById('listeningStripFreqInput');
|
||||
const listeningStripMode = document.getElementById('listeningStripMode');
|
||||
const listeningStripGain = document.getElementById('listeningStripGain');
|
||||
|
||||
if (listeningStripDot) listeningStripDot.className = 'status-dot ' + (running ? 'scanning' : 'inactive');
|
||||
if (listeningStripStatus) {
|
||||
listeningStripStatus.textContent = running ? 'SCANNING' : 'STANDBY';
|
||||
listeningStripStatus.style.color = running ? 'var(--accent-cyan)' : '';
|
||||
}
|
||||
if (listeningStripStartBtn) listeningStripStartBtn.style.display = running ? 'none' : 'inline-block';
|
||||
if (listeningStripStopBtn) listeningStripStopBtn.style.display = running ? 'inline-block' : 'none';
|
||||
if (listeningStripFreqInput) listeningStripFreqInput.disabled = running;
|
||||
if (listeningStripMode) listeningStripMode.disabled = running;
|
||||
if (listeningStripGain) listeningStripGain.disabled = running;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update listening strip stats
|
||||
*/
|
||||
function updateListeningStrip(freq, bandwidth, signalCount) {
|
||||
const freqEl = document.getElementById('listeningStripFreq');
|
||||
const bwEl = document.getElementById('listeningStripBW');
|
||||
const signalsEl = document.getElementById('listeningStripSignals');
|
||||
|
||||
if (freqEl && freq !== undefined) freqEl.textContent = freq;
|
||||
if (bwEl && bandwidth !== undefined) bwEl.textContent = bandwidth;
|
||||
if (signalsEl && signalCount !== undefined) signalsEl.textContent = signalCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start listening from the function strip
|
||||
*/
|
||||
function startListeningFromStrip() {
|
||||
// Get values from strip
|
||||
const freq = document.getElementById('listeningStripFreqInput')?.value;
|
||||
const mode = document.getElementById('listeningStripMode')?.value;
|
||||
const gain = document.getElementById('listeningStripGain')?.value;
|
||||
|
||||
// Update the main controls if they exist
|
||||
if (freq) {
|
||||
const mainFreqInput = document.getElementById('radioScanStart');
|
||||
if (mainFreqInput) mainFreqInput.value = freq;
|
||||
}
|
||||
if (mode) {
|
||||
currentModulation = mode.toLowerCase();
|
||||
}
|
||||
if (gain) {
|
||||
const gainValueEl = document.getElementById('radioGainValue');
|
||||
if (gainValueEl) gainValueEl.textContent = gain;
|
||||
}
|
||||
|
||||
// Start the scanner
|
||||
startScanner();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop listening from the function strip
|
||||
*/
|
||||
function stopListening() {
|
||||
stopScanner();
|
||||
}
|
||||
|
||||
// Export strip functions
|
||||
window.updateListeningStripRunning = updateListeningStripRunning;
|
||||
window.updateListeningStrip = updateListeningStrip;
|
||||
window.startListeningFromStrip = startListeningFromStrip;
|
||||
window.stopListening = stopListening;
|
||||
|
||||
|
||||
+435
-11
@@ -336,6 +336,9 @@ const WiFiMode = (function() {
|
||||
if (elements.scanModeDeep) {
|
||||
elements.scanModeDeep.addEventListener('click', () => setScanMode('deep'));
|
||||
}
|
||||
|
||||
// Initialize button visibility (default to quick mode)
|
||||
setScanMode('quick');
|
||||
}
|
||||
|
||||
function setScanMode(mode) {
|
||||
@@ -349,6 +352,21 @@ const WiFiMode = (function() {
|
||||
elements.scanModeDeep.classList.toggle('active', mode === 'deep');
|
||||
}
|
||||
|
||||
// Update button visibility based on mode
|
||||
if (!isScanning) {
|
||||
if (elements.quickScanBtn) {
|
||||
elements.quickScanBtn.style.display = mode === 'quick' ? 'inline-block' : 'none';
|
||||
elements.quickScanBtn.textContent = 'Start Quick Scan';
|
||||
}
|
||||
if (elements.deepScanBtn) {
|
||||
elements.deepScanBtn.style.display = mode === 'deep' ? 'inline-block' : 'none';
|
||||
elements.deepScanBtn.textContent = 'Start Deep Scan';
|
||||
}
|
||||
if (elements.stopScanBtn) {
|
||||
elements.stopScanBtn.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
console.log('[WiFiMode] Scan mode set to:', mode);
|
||||
}
|
||||
|
||||
@@ -357,7 +375,10 @@ const WiFiMode = (function() {
|
||||
// ==========================================================================
|
||||
|
||||
async function startQuickScan() {
|
||||
if (isScanning) return;
|
||||
if (isScanning) {
|
||||
showInfo('Scan already in progress');
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for agent mode conflicts
|
||||
if (!checkAgentConflicts()) {
|
||||
@@ -365,6 +386,7 @@ const WiFiMode = (function() {
|
||||
}
|
||||
|
||||
console.log('[WiFiMode] Starting quick scan...');
|
||||
showInfo('Starting quick scan...');
|
||||
setScanning(true, 'quick');
|
||||
|
||||
try {
|
||||
@@ -436,6 +458,9 @@ const WiFiMode = (function() {
|
||||
// Process results
|
||||
processQuickScanResult({ ...scanResult, access_points: accessPoints });
|
||||
|
||||
// Show success notification
|
||||
showInfo(`Found ${accessPoints.length} network${accessPoints.length !== 1 ? 's' : ''}`);
|
||||
|
||||
// For quick scan, we're done after one scan
|
||||
// But keep polling if user wants continuous updates
|
||||
if (scanMode === 'quick') {
|
||||
@@ -449,7 +474,10 @@ const WiFiMode = (function() {
|
||||
}
|
||||
|
||||
async function startDeepScan() {
|
||||
if (isScanning) return;
|
||||
if (isScanning) {
|
||||
showInfo('Scan already in progress');
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for agent mode conflicts
|
||||
if (!checkAgentConflicts()) {
|
||||
@@ -457,6 +485,7 @@ const WiFiMode = (function() {
|
||||
}
|
||||
|
||||
console.log('[WiFiMode] Starting deep scan...');
|
||||
showInfo('Starting deep scan (requires monitor mode)...');
|
||||
setScanning(true, 'deep');
|
||||
|
||||
try {
|
||||
@@ -516,6 +545,7 @@ const WiFiMode = (function() {
|
||||
|
||||
async function stopScan() {
|
||||
console.log('[WiFiMode] Stopping scan...');
|
||||
showInfo('Stopping scan...');
|
||||
|
||||
// Stop polling
|
||||
if (pollTimer) {
|
||||
@@ -538,6 +568,7 @@ const WiFiMode = (function() {
|
||||
} else if (scanMode === 'deep') {
|
||||
await fetch(`${CONFIG.apiBase}/scan/stop`, { method: 'POST' });
|
||||
}
|
||||
showInfo('Scan stopped');
|
||||
} catch (error) {
|
||||
console.warn('[WiFiMode] Error stopping scan:', error);
|
||||
}
|
||||
@@ -549,15 +580,21 @@ const WiFiMode = (function() {
|
||||
isScanning = scanning;
|
||||
if (mode) scanMode = mode;
|
||||
|
||||
// Update buttons
|
||||
if (elements.quickScanBtn) {
|
||||
elements.quickScanBtn.style.display = scanning ? 'none' : 'inline-block';
|
||||
}
|
||||
if (elements.deepScanBtn) {
|
||||
elements.deepScanBtn.style.display = scanning ? 'none' : 'inline-block';
|
||||
}
|
||||
if (elements.stopScanBtn) {
|
||||
elements.stopScanBtn.style.display = scanning ? 'inline-block' : 'none';
|
||||
// Update buttons based on scanning state and current mode
|
||||
if (scanning) {
|
||||
// Scanning: hide start buttons, show stop button
|
||||
if (elements.quickScanBtn) elements.quickScanBtn.style.display = 'none';
|
||||
if (elements.deepScanBtn) elements.deepScanBtn.style.display = 'none';
|
||||
if (elements.stopScanBtn) elements.stopScanBtn.style.display = 'inline-block';
|
||||
} else {
|
||||
// Not scanning: show appropriate start button based on mode, hide stop
|
||||
if (elements.quickScanBtn) {
|
||||
elements.quickScanBtn.style.display = scanMode === 'quick' ? 'inline-block' : 'none';
|
||||
}
|
||||
if (elements.deepScanBtn) {
|
||||
elements.deepScanBtn.style.display = scanMode === 'deep' ? 'inline-block' : 'none';
|
||||
}
|
||||
if (elements.stopScanBtn) elements.stopScanBtn.style.display = 'none';
|
||||
}
|
||||
|
||||
// Update status
|
||||
@@ -1426,3 +1463,390 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
WiFiMode.init();
|
||||
}
|
||||
});
|
||||
|
||||
// =============================================================================
|
||||
// WiFi Helper Functions
|
||||
// Implements UI helper functions for Monitor Mode, Deauth, Watch List, etc.
|
||||
// =============================================================================
|
||||
|
||||
const WiFiHelpers = (function() {
|
||||
'use strict';
|
||||
|
||||
// Note: Monitor mode and attack endpoints are in /wifi/ (v1), not /wifi/v2/
|
||||
const CONFIG = {
|
||||
apiBase: '/wifi/v2',
|
||||
apiV1Base: '/wifi',
|
||||
};
|
||||
|
||||
// Watch list state
|
||||
let watchList = [];
|
||||
|
||||
// ==========================================================================
|
||||
// Monitor Mode
|
||||
// ==========================================================================
|
||||
|
||||
async function enableMonitorMode() {
|
||||
const iface = document.getElementById('wifiInterfaceSelect')?.value;
|
||||
const killProcesses = document.getElementById('killProcesses')?.checked || false;
|
||||
const startBtn = document.getElementById('monitorStartBtn');
|
||||
const stopBtn = document.getElementById('monitorStopBtn');
|
||||
const statusEl = document.getElementById('monitorStatus');
|
||||
|
||||
// Provide immediate feedback
|
||||
console.log('[WiFiHelpers] Enable monitor mode clicked');
|
||||
showNotification('Monitor Mode', 'Enabling monitor mode...', 'info');
|
||||
|
||||
if (!iface) {
|
||||
showNotification('Monitor Mode', 'No interface selected. Please wait for interface detection.', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
// Update UI to show processing
|
||||
if (startBtn) {
|
||||
startBtn.disabled = true;
|
||||
startBtn.textContent = 'Enabling...';
|
||||
}
|
||||
|
||||
try {
|
||||
// Use v1 API which has monitor mode support
|
||||
const response = await fetch(`${CONFIG.apiV1Base}/monitor`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
interface: iface,
|
||||
action: 'enable',
|
||||
kill_processes: killProcesses
|
||||
}),
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (!response.ok || result.error) {
|
||||
throw new Error(result.error || result.message || 'Failed to enable monitor mode');
|
||||
}
|
||||
|
||||
// Success - update UI
|
||||
if (startBtn) {
|
||||
startBtn.style.display = 'none';
|
||||
startBtn.disabled = false;
|
||||
startBtn.textContent = 'Enable Monitor';
|
||||
}
|
||||
if (stopBtn) stopBtn.style.display = 'inline-block';
|
||||
if (statusEl) {
|
||||
statusEl.innerHTML = `Monitor mode: <span style="color: var(--accent-green);">Active</span> (${result.monitor_interface || iface})`;
|
||||
}
|
||||
|
||||
showNotification('Monitor Mode', `Enabled on ${result.monitor_interface || iface}`, 'success');
|
||||
} catch (error) {
|
||||
console.error('[WiFiHelpers] Enable monitor mode error:', error);
|
||||
showNotification('Monitor Mode', error.message, 'error');
|
||||
|
||||
// Reset button
|
||||
if (startBtn) {
|
||||
startBtn.disabled = false;
|
||||
startBtn.textContent = 'Enable Monitor';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function disableMonitorMode() {
|
||||
const iface = document.getElementById('wifiInterfaceSelect')?.value;
|
||||
const startBtn = document.getElementById('monitorStartBtn');
|
||||
const stopBtn = document.getElementById('monitorStopBtn');
|
||||
const statusEl = document.getElementById('monitorStatus');
|
||||
|
||||
console.log('[WiFiHelpers] Disable monitor mode clicked');
|
||||
showNotification('Monitor Mode', 'Disabling monitor mode...', 'info');
|
||||
|
||||
if (stopBtn) {
|
||||
stopBtn.disabled = true;
|
||||
stopBtn.textContent = 'Disabling...';
|
||||
}
|
||||
|
||||
try {
|
||||
// Use v1 API which has monitor mode support
|
||||
const response = await fetch(`${CONFIG.apiV1Base}/monitor`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
interface: iface,
|
||||
action: 'disable'
|
||||
}),
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (!response.ok || result.error) {
|
||||
throw new Error(result.error || result.message || 'Failed to disable monitor mode');
|
||||
}
|
||||
|
||||
// Success - update UI
|
||||
if (stopBtn) {
|
||||
stopBtn.style.display = 'none';
|
||||
stopBtn.disabled = false;
|
||||
stopBtn.textContent = 'Disable Monitor';
|
||||
}
|
||||
if (startBtn) startBtn.style.display = 'inline-block';
|
||||
if (statusEl) {
|
||||
statusEl.innerHTML = `Monitor mode: <span style="color: var(--accent-red);">Inactive</span>`;
|
||||
}
|
||||
|
||||
showNotification('Monitor Mode', 'Disabled successfully', 'info');
|
||||
} catch (error) {
|
||||
console.error('[WiFiHelpers] Disable monitor mode error:', error);
|
||||
showNotification('Monitor Mode', error.message, 'error');
|
||||
|
||||
// Reset button
|
||||
if (stopBtn) {
|
||||
stopBtn.disabled = false;
|
||||
stopBtn.textContent = 'Disable Monitor';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ==========================================================================
|
||||
// Deauth Attack
|
||||
// ==========================================================================
|
||||
|
||||
async function sendDeauth() {
|
||||
const bssid = document.getElementById('targetBssid')?.value?.trim();
|
||||
const client = document.getElementById('targetClient')?.value?.trim() || 'FF:FF:FF:FF:FF:FF';
|
||||
const count = parseInt(document.getElementById('deauthCount')?.value) || 5;
|
||||
const iface = document.getElementById('wifiInterfaceSelect')?.value;
|
||||
|
||||
console.log('[WiFiHelpers] Send deauth clicked');
|
||||
|
||||
if (!bssid || !/^([0-9A-Fa-f]{2}:){5}[0-9A-Fa-f]{2}$/.test(bssid)) {
|
||||
showNotification('Deauth Attack', 'Please enter a valid target BSSID (e.g., AA:BB:CC:DD:EE:FF)', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
// Confirm action
|
||||
if (!confirm(`Send ${count} deauth frames to ${bssid}?\n\nWARNING: Only use on networks you are authorized to test.`)) {
|
||||
return;
|
||||
}
|
||||
|
||||
showNotification('Deauth Attack', `Sending ${count} deauth frames...`, 'info');
|
||||
|
||||
try {
|
||||
// Use v1 API which has deauth support
|
||||
const response = await fetch(`${CONFIG.apiV1Base}/deauth`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
bssid: bssid,
|
||||
client: client,
|
||||
count: count,
|
||||
interface: iface
|
||||
}),
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (!response.ok || result.error) {
|
||||
throw new Error(result.error || result.message || 'Deauth attack failed');
|
||||
}
|
||||
|
||||
showNotification('Deauth Attack', `Sent ${count} deauth frames to ${bssid}`, 'success');
|
||||
} catch (error) {
|
||||
console.error('[WiFiHelpers] Deauth error:', error);
|
||||
showNotification('Deauth Attack', error.message, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
// ==========================================================================
|
||||
// Watch List (Proximity Alerts)
|
||||
// ==========================================================================
|
||||
|
||||
function addWatchMac() {
|
||||
const input = document.getElementById('watchMacInput');
|
||||
const mac = input?.value?.trim().toUpperCase();
|
||||
|
||||
console.log('[WiFiHelpers] Add watch MAC clicked, value:', mac);
|
||||
|
||||
if (!mac) {
|
||||
showNotification('Watch List', 'Please enter a MAC address', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!/^([0-9A-Fa-f]{2}:){5}[0-9A-Fa-f]{2}$/.test(mac)) {
|
||||
showNotification('Watch List', 'Invalid format. Use XX:XX:XX:XX:XX:XX', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
if (watchList.includes(mac)) {
|
||||
showNotification('Watch List', 'MAC address already in watch list', 'info');
|
||||
return;
|
||||
}
|
||||
|
||||
watchList.push(mac);
|
||||
input.value = '';
|
||||
updateWatchListDisplay();
|
||||
showNotification('Watch List', `Added ${mac} to watch list`, 'success');
|
||||
|
||||
// Save to localStorage
|
||||
try {
|
||||
localStorage.setItem('wifiWatchList', JSON.stringify(watchList));
|
||||
} catch (e) {
|
||||
console.warn('[WiFiHelpers] Could not save watch list to localStorage');
|
||||
}
|
||||
}
|
||||
|
||||
function removeWatchMac(mac) {
|
||||
watchList = watchList.filter(m => m !== mac);
|
||||
updateWatchListDisplay();
|
||||
|
||||
// Save to localStorage
|
||||
try {
|
||||
localStorage.setItem('wifiWatchList', JSON.stringify(watchList));
|
||||
} catch (e) {
|
||||
console.warn('[WiFiHelpers] Could not save watch list to localStorage');
|
||||
}
|
||||
}
|
||||
|
||||
function updateWatchListDisplay() {
|
||||
const container = document.getElementById('watchList');
|
||||
if (!container) return;
|
||||
|
||||
if (watchList.length === 0) {
|
||||
container.innerHTML = '<span style="color: var(--text-dim);">No MAC addresses in watch list</span>';
|
||||
return;
|
||||
}
|
||||
|
||||
container.innerHTML = watchList.map(mac => `
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; padding: 4px 0; border-bottom: 1px solid var(--border-color);">
|
||||
<code style="font-size: 10px;">${mac}</code>
|
||||
<button onclick="WiFiHelpers.removeWatchMac('${mac}')" style="background: none; border: none; color: var(--accent-red); cursor: pointer; font-size: 12px; padding: 2px 6px;">×</button>
|
||||
</div>
|
||||
`).join('');
|
||||
}
|
||||
|
||||
function loadWatchList() {
|
||||
try {
|
||||
const saved = localStorage.getItem('wifiWatchList');
|
||||
if (saved) {
|
||||
watchList = JSON.parse(saved);
|
||||
updateWatchListDisplay();
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn('[WiFiHelpers] Could not load watch list from localStorage');
|
||||
}
|
||||
}
|
||||
|
||||
// ==========================================================================
|
||||
// Handshake Capture
|
||||
// ==========================================================================
|
||||
|
||||
async function checkCaptureStatus() {
|
||||
const statusEl = document.getElementById('captureStatus');
|
||||
const bssid = document.getElementById('captureTargetBssid')?.textContent;
|
||||
|
||||
console.log('[WiFiHelpers] Check capture status clicked');
|
||||
showNotification('Handshake Capture', 'Checking capture status...', 'info');
|
||||
|
||||
try {
|
||||
// Use v1 API which has handshake capture support
|
||||
const response = await fetch(`${CONFIG.apiV1Base}/handshake/status`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ bssid: bssid }),
|
||||
});
|
||||
const result = await response.json();
|
||||
|
||||
if (statusEl) {
|
||||
if (result.capturing || result.running) {
|
||||
statusEl.textContent = result.handshake_found ? 'Handshake captured!' : 'Capturing...';
|
||||
statusEl.style.color = result.handshake_found ? 'var(--accent-green)' : 'var(--accent-orange)';
|
||||
} else {
|
||||
statusEl.textContent = 'Not capturing';
|
||||
statusEl.style.color = 'var(--text-secondary)';
|
||||
}
|
||||
}
|
||||
|
||||
if (result.handshake_found) {
|
||||
showNotification('Handshake Capture', `Handshake captured! File: ${result.capture_file || 'check captures folder'}`, 'success');
|
||||
} else if (result.capturing || result.running) {
|
||||
showNotification('Handshake Capture', 'Still capturing, no handshake yet...', 'info');
|
||||
} else {
|
||||
showNotification('Handshake Capture', 'No active capture', 'info');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[WiFiHelpers] Check capture status error:', error);
|
||||
showNotification('Handshake Capture', error.message, 'error');
|
||||
if (statusEl) {
|
||||
statusEl.textContent = 'Error checking status';
|
||||
statusEl.style.color = 'var(--accent-red)';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function stopHandshakeCapture() {
|
||||
const panel = document.getElementById('captureStatusPanel');
|
||||
const statusEl = document.getElementById('captureStatus');
|
||||
|
||||
console.log('[WiFiHelpers] Stop handshake capture clicked');
|
||||
showNotification('Handshake Capture', 'Stopping capture...', 'info');
|
||||
|
||||
try {
|
||||
// Use v1 API - handshake stop endpoint
|
||||
const response = await fetch(`${CONFIG.apiV1Base}/scan/stop`, {
|
||||
method: 'POST',
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (!response.ok || result.error) {
|
||||
throw new Error(result.error || result.message || 'Failed to stop capture');
|
||||
}
|
||||
|
||||
if (statusEl) {
|
||||
statusEl.textContent = 'Stopped';
|
||||
statusEl.style.color = 'var(--text-secondary)';
|
||||
}
|
||||
|
||||
// Hide panel after delay
|
||||
setTimeout(() => {
|
||||
if (panel) panel.style.display = 'none';
|
||||
}, 2000);
|
||||
|
||||
showNotification('Handshake Capture', 'Capture stopped', 'success');
|
||||
} catch (error) {
|
||||
console.error('[WiFiHelpers] Stop capture error:', error);
|
||||
showNotification('Handshake Capture', error.message, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
// ==========================================================================
|
||||
// Utility
|
||||
// ==========================================================================
|
||||
|
||||
function showNotification(title, message, type) {
|
||||
if (typeof window.showNotification === 'function') {
|
||||
window.showNotification(title, message, type);
|
||||
} else {
|
||||
console.log(`[${type.toUpperCase()}] ${title}: ${message}`);
|
||||
}
|
||||
}
|
||||
|
||||
// ==========================================================================
|
||||
// Initialize
|
||||
// ==========================================================================
|
||||
|
||||
// Load watch list on page load
|
||||
document.addEventListener('DOMContentLoaded', loadWatchList);
|
||||
|
||||
// ==========================================================================
|
||||
// Public API
|
||||
// ==========================================================================
|
||||
|
||||
return {
|
||||
enableMonitorMode,
|
||||
disableMonitorMode,
|
||||
sendDeauth,
|
||||
addWatchMac,
|
||||
removeWatchMac,
|
||||
checkCaptureStatus,
|
||||
stopHandshakeCapture,
|
||||
getWatchList: () => [...watchList],
|
||||
};
|
||||
})();
|
||||
|
||||
@@ -47,8 +47,6 @@
|
||||
<input type="checkbox" id="showAllAgents" onchange="toggleShowAllAgents()"> All
|
||||
</label>
|
||||
</div>
|
||||
<a href="#" onclick="history.back(); return false;" class="back-link">Back</a>
|
||||
<a href="/" class="back-link">Main Dashboard</a>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
|
||||
@@ -223,26 +223,6 @@
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
/* Navigation links */
|
||||
.nav-links {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.back-link {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
color: var(--accent-cyan);
|
||||
text-decoration: none;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.back-link:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/* Toast notifications */
|
||||
.toast {
|
||||
position: fixed;
|
||||
@@ -301,21 +281,6 @@
|
||||
</header>
|
||||
|
||||
<div class="agents-container">
|
||||
<div class="nav-links">
|
||||
<a href="#" onclick="history.back(); return false;" class="back-link">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<path d="M19 12H5M12 19l-7-7 7-7"/>
|
||||
</svg>
|
||||
Back
|
||||
</a>
|
||||
<a href="/" class="back-link">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/>
|
||||
<polyline points="9 22 9 12 15 12 15 22"/>
|
||||
</svg>
|
||||
Dashboard
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="agents-header">
|
||||
<h1>Remote Agents</h1>
|
||||
|
||||
@@ -48,8 +48,6 @@
|
||||
<input type="checkbox" id="showAllAgents" onchange="toggleShowAllAgents()"> All
|
||||
</label>
|
||||
</div>
|
||||
<a href="#" onclick="history.back(); return false;" class="back-link">Back</a>
|
||||
<a href="/" class="back-link">Main Dashboard</a>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
|
||||
@@ -1500,7 +1500,7 @@
|
||||
</div>
|
||||
|
||||
<!-- TSCM Dashboard -->
|
||||
<div id="tscmVisuals" class="tscm-dashboard" style="display: none; padding: 16px;">
|
||||
<div id="tscmVisuals" class="tscm-dashboard" style="display: none;">
|
||||
<!-- TSCM Function Bar -->
|
||||
<div class="function-strip tscm-strip" id="tscmStrip" style="margin-bottom: 12px;">
|
||||
<div class="function-strip-inner">
|
||||
@@ -3017,8 +3017,8 @@
|
||||
restoreSectionsToMode('rtlamrMode', ['#rtlamrPpm', '#rtlamrUnique', '#rtlamrLogging'], 'Utility Meter');
|
||||
restoreSectionsToMode('aprsMode', [], 'APRS Tracking');
|
||||
restoreSectionsToMode('spystationsMode', ['#filterTypeNumber', '#countryFilters', '#modeFilters', '#spyStatsNumber'], 'Spy Stations');
|
||||
restoreSectionsToMode('wifiMode', ['#wifiScanModeQuick', '#monitorStartBtn', '#wifiChannel', '#watchMacInput', '#targetBssid'], 'WiFi Scanning');
|
||||
restoreSectionsToMode('bluetoothMode', ['#btAdapterSelect', '#btTransport', '#btScanDuration'], 'Bluetooth Scanning');
|
||||
restoreSectionsToMode('wifiMode', ['#wifiScanModeQuick', '#monitorStartBtn', '#wifiChannel', '#watchMacInput', '#targetBssid', '#wifiExportCsvBtn'], 'WiFi Scanning');
|
||||
restoreSectionsToMode('bluetoothMode', ['#btAdapterSelect', '#btTransport', '#btScanDuration', '#btExportCsvBtn', '#btCapabilityMarker'], 'Bluetooth Scanning');
|
||||
restoreSectionsToMode('tscmMode', ['#tscmWifiEnabled', '#tscmVerboseResults', '#tscmBaselineName'], 'TSCM Sweep');
|
||||
restoreSectionsToMode('satelliteMode', ['#satTrackingList', '#obsLat', '#obsLon'], 'Satellite Command');
|
||||
restoreSectionsToMode('sstvMode', ['#sstvFrequency'], 'ISS SSTV Decoder');
|
||||
|
||||
@@ -159,8 +159,6 @@
|
||||
{% block dashboard_header_center %}{% endblock %}
|
||||
<div class="header-utilities" style="gap: var(--space-2);">
|
||||
{% block agent_selector %}{% endblock %}
|
||||
<a href="#" onclick="history.back(); return false;" class="back-link" style="font-size: var(--text-sm);">Back</a>
|
||||
<a href="/" class="back-link" style="font-size: var(--text-sm);">Main Dashboard</a>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
@@ -514,8 +514,6 @@
|
||||
<span>// MULTI-AGENT VIEW</span>
|
||||
</div>
|
||||
<nav class="header-nav">
|
||||
<a href="#" onclick="history.back(); return false;">Back</a>
|
||||
<a href="/">Dashboard</a>
|
||||
<a href="/controller/manage">Manage Agents</a>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
<div id="bluetoothMode" class="mode-content">
|
||||
<!-- Capability Status -->
|
||||
<div id="btCapabilityStatus" class="section" style="display: none;">
|
||||
<span id="btCapabilityMarker" style="display: none;"></span>
|
||||
<!-- Populated by JavaScript with capability warnings -->
|
||||
</div>
|
||||
|
||||
@@ -50,10 +51,10 @@
|
||||
<!-- Message Container for status cards -->
|
||||
<div id="btMessageContainer"></div>
|
||||
|
||||
<div class="section" style="margin-top: 10px;">
|
||||
<div class="section" id="btExportSection" style="margin-top: 10px;">
|
||||
<h3>Export</h3>
|
||||
<div style="display: flex; gap: 8px;">
|
||||
<button class="preset-btn" onclick="btExport('csv')" style="flex: 1;">
|
||||
<button class="preset-btn" id="btExportCsvBtn" onclick="btExport('csv')" style="flex: 1;">
|
||||
Export CSV
|
||||
</button>
|
||||
<button class="preset-btn" onclick="btExport('json')" style="flex: 1;">
|
||||
|
||||
@@ -97,8 +97,8 @@
|
||||
</div>
|
||||
|
||||
<!-- Advanced -->
|
||||
<div class="section" style="margin-top: 12px;">
|
||||
<h3 style="margin-bottom: 12px;">Baseline Recording</h3>
|
||||
<div class="section">
|
||||
<h3>Baseline Recording</h3>
|
||||
<div class="form-group">
|
||||
<input type="text" id="tscmBaselineName" placeholder="Baseline name...">
|
||||
</div>
|
||||
@@ -111,8 +111,8 @@
|
||||
<div id="tscmBaselineStatus" style="margin-top: 8px; font-size: 11px; color: var(--text-muted);"></div>
|
||||
</div>
|
||||
|
||||
<div class="section" style="margin-top: 12px;">
|
||||
<h3 style="margin-bottom: 12px;">Meeting Window</h3>
|
||||
<div class="section">
|
||||
<h3>Meeting Window</h3>
|
||||
<div id="tscmMeetingStatus" style="font-size: 11px; color: var(--text-muted); margin-bottom: 8px;">
|
||||
No active meeting
|
||||
</div>
|
||||
@@ -131,8 +131,8 @@
|
||||
</div>
|
||||
|
||||
<!-- Tools -->
|
||||
<div class="section" style="margin-top: 12px;">
|
||||
<h3 style="margin-bottom: 10px;">Tools</h3>
|
||||
<div class="section">
|
||||
<h3>Tools</h3>
|
||||
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 6px;">
|
||||
<button class="preset-btn" onclick="tscmShowCapabilities()" style="font-size: 10px; padding: 8px;">
|
||||
Capabilities
|
||||
|
||||
@@ -5,19 +5,28 @@
|
||||
<p style="color: var(--text-secondary); font-size: 11px; line-height: 1.5; margin-bottom: 15px;">
|
||||
Scan for nearby WiFi networks, analyze channels, and monitor wireless activity.
|
||||
</p>
|
||||
<div style="background: rgba(74, 158, 255, 0.1); border: 1px solid rgba(74, 158, 255, 0.3); border-radius: 4px; padding: 8px; font-size: 10px;">
|
||||
<span style="color: var(--accent-cyan);">Controls in function bar above</span>
|
||||
</div>
|
||||
<!-- Scan Mode Tabs -->
|
||||
<div style="margin-top: 12px;">
|
||||
<div class="wifi-scan-mode-tabs" style="display: flex; gap: 4px;">
|
||||
<button id="wifiScanModeQuick" class="wifi-mode-tab active" style="flex: 1; padding: 8px; font-size: 11px; background: var(--accent-green); color: #000; border: none; border-radius: 4px; cursor: pointer;">
|
||||
<div class="wifi-scan-mode-tabs" style="display: flex; gap: 4px; margin-bottom: 10px;">
|
||||
<button id="wifiScanModeQuick" class="wifi-mode-tab active">
|
||||
Quick Scan
|
||||
</button>
|
||||
<button id="wifiScanModeDeep" class="wifi-mode-tab" style="flex: 1; padding: 8px; font-size: 11px; background: var(--bg-tertiary); color: #888; border: 1px solid var(--border-color); border-radius: 4px; cursor: pointer;">
|
||||
<button id="wifiScanModeDeep" class="wifi-mode-tab">
|
||||
Deep Scan
|
||||
</button>
|
||||
</div>
|
||||
<!-- Scan Control Buttons -->
|
||||
<div id="wifiScanControls" style="display: flex; gap: 8px;">
|
||||
<button id="wifiQuickScanBtn" class="preset-btn wifi-start-btn" onclick="if(typeof WiFiMode !== 'undefined') WiFiMode.startQuickScan()" style="flex: 1;">
|
||||
Start Quick Scan
|
||||
</button>
|
||||
<button id="wifiDeepScanBtn" class="preset-btn wifi-start-btn" onclick="if(typeof WiFiMode !== 'undefined') WiFiMode.startDeepScan()" style="flex: 1; display: none;">
|
||||
Start Deep Scan
|
||||
</button>
|
||||
<button id="wifiStopScanBtn" class="preset-btn wifi-stop-btn" onclick="if(typeof WiFiMode !== 'undefined') WiFiMode.stopScan()" style="flex: 1; display: none;">
|
||||
Stop Scan
|
||||
</button>
|
||||
</div>
|
||||
<div id="wifiCapabilityStatus" class="info-text" style="margin-top: 8px; font-size: 10px;"></div>
|
||||
<!-- Show All Agents option (visible when agents are available) -->
|
||||
<div id="wifiShowAllAgentsContainer" style="margin-top: 8px; display: none;">
|
||||
@@ -32,10 +41,10 @@
|
||||
<div class="section">
|
||||
<h3>Monitor Mode</h3>
|
||||
<div style="display: flex; gap: 8px;">
|
||||
<button class="preset-btn" id="monitorStartBtn" onclick="enableMonitorMode()" style="flex: 1; background: var(--accent-green); color: #000;">
|
||||
<button class="preset-btn wifi-monitor-btn" id="monitorStartBtn" onclick="WiFiHelpers.enableMonitorMode()" style="flex: 1;">
|
||||
Enable Monitor
|
||||
</button>
|
||||
<button class="preset-btn" id="monitorStopBtn" onclick="disableMonitorMode()" style="flex: 1; display: none;">
|
||||
<button class="preset-btn wifi-monitor-stop-btn" id="monitorStopBtn" onclick="WiFiHelpers.disableMonitorMode()" style="flex: 1; display: none;">
|
||||
Disable Monitor
|
||||
</button>
|
||||
</div>
|
||||
@@ -75,7 +84,7 @@
|
||||
<label>Deauth Count</label>
|
||||
<input type="text" id="deauthCount" value="5" placeholder="5">
|
||||
</div>
|
||||
<button class="preset-btn" onclick="sendDeauth()" style="width: 100%; border-color: var(--accent-red); color: var(--accent-red);">
|
||||
<button class="preset-btn wifi-danger-btn" onclick="WiFiHelpers.sendDeauth()" style="width: 100%;">
|
||||
Send Deauth
|
||||
</button>
|
||||
</div>
|
||||
@@ -88,7 +97,7 @@
|
||||
<div class="form-group">
|
||||
<input type="text" id="watchMacInput" placeholder="AA:BB:CC:DD:EE:FF">
|
||||
</div>
|
||||
<button class="preset-btn" onclick="addWatchMac()" style="width: 100%; margin-bottom: 8px;">
|
||||
<button class="preset-btn" onclick="WiFiHelpers.addWatchMac()" style="width: 100%; margin-bottom: 8px;">
|
||||
Add to Watch List
|
||||
</button>
|
||||
<div id="watchList" style="max-height: 80px; overflow-y: auto; font-size: 10px; color: var(--text-dim);"></div>
|
||||
@@ -115,10 +124,10 @@
|
||||
<span id="captureStatus" style="font-weight: bold;">--</span>
|
||||
</div>
|
||||
<div style="display: flex; gap: 8px;">
|
||||
<button class="preset-btn" onclick="checkCaptureStatus()" style="flex: 1; font-size: 10px; padding: 4px;">
|
||||
<button class="preset-btn" onclick="WiFiHelpers.checkCaptureStatus()" style="flex: 1; font-size: 10px; padding: 4px;">
|
||||
Check Status
|
||||
</button>
|
||||
<button class="preset-btn" onclick="stopHandshakeCapture()" style="flex: 1; font-size: 10px; padding: 4px; background: var(--accent-red); border: none; color: #fff;">
|
||||
<button class="preset-btn wifi-stop-btn" onclick="WiFiHelpers.stopHandshakeCapture()" style="flex: 1; font-size: 10px; padding: 4px;">
|
||||
Stop Capture
|
||||
</button>
|
||||
</div>
|
||||
@@ -137,10 +146,10 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<div class="section" id="wifiExportSection">
|
||||
<h3>Export</h3>
|
||||
<div style="display: flex; gap: 8px;">
|
||||
<button class="preset-btn" onclick="WiFiMode.exportData('csv')" style="flex: 1;">
|
||||
<button class="preset-btn" id="wifiExportCsvBtn" onclick="WiFiMode.exportData('csv')" style="flex: 1;">
|
||||
Export CSV
|
||||
</button>
|
||||
<button class="preset-btn" onclick="WiFiMode.exportData('json')" style="flex: 1;">
|
||||
|
||||
@@ -68,7 +68,6 @@
|
||||
<span id="trackingStatus">TRACKING</span>
|
||||
</div>
|
||||
<div class="datetime" id="utcTime">--:--:-- UTC</div>
|
||||
<a href="/" class="back-link">Main Dashboard</a>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
@@ -304,10 +303,6 @@
|
||||
|
||||
function setupEmbeddedMode() {
|
||||
if (isEmbedded) {
|
||||
// Hide back link when embedded
|
||||
const backLink = document.querySelector('.back-link');
|
||||
if (backLink) backLink.style.display = 'none';
|
||||
|
||||
// Add embedded class to body for CSS adjustments
|
||||
document.body.classList.add('embedded');
|
||||
|
||||
|
||||
Reference in New Issue
Block a user