diff --git a/static/css/modes/tscm.css b/static/css/modes/tscm.css index a5d167f..ea742ff 100644 --- a/static/css/modes/tscm.css +++ b/static/css/modes/tscm.css @@ -1354,6 +1354,28 @@ color: var(--text-secondary); } +/* Classification Dots - replaces emoji circles for risk levels */ +.classification-dot { + display: inline-block; + width: 10px; + height: 10px; + border-radius: 50%; + vertical-align: middle; + margin-right: 4px; +} + +.classification-dot.high { + background-color: var(--accent-red); +} + +.classification-dot.review { + background-color: var(--accent-orange); +} + +.classification-dot.info { + background-color: var(--accent-green); +} + /* Device Indicators with Icons */ .device-indicator-icon { display: inline-flex; diff --git a/static/js/components/signal-cards.js b/static/js/components/signal-cards.js index 2f3187e..1cf5914 100644 --- a/static/js/components/signal-cards.js +++ b/static/js/components/signal-cards.js @@ -1072,22 +1072,19 @@ const SignalCards = (function() { const stats = getAddressStats('meter', msg.id); const seenCount = stats ? stats.count : 1; - // Determine meter type icon and color - let meterIcon = '⚡'; + // Determine meter type color let meterTypeClass = 'electric'; const meterType = (msg.type || '').toLowerCase(); if (meterType.includes('gas')) { - meterIcon = '🔥'; meterTypeClass = 'gas'; } else if (meterType.includes('water')) { - meterIcon = '💧'; meterTypeClass = 'water'; } card.innerHTML = `
- ${meterIcon} ${escapeHtml(msg.type || 'Meter')} + ${escapeHtml(msg.type || 'Meter')} ID: ${escapeHtml(msg.id || 'N/A')}
${status !== 'baseline' ? ` diff --git a/static/js/components/signal-timeline.js b/static/js/components/signal-timeline.js index c4bca50..df08dae 100644 --- a/static/js/components/signal-timeline.js +++ b/static/js/components/signal-timeline.js @@ -730,16 +730,17 @@ const SignalTimeline = (function() { container.style.display = 'block'; container.innerHTML = recentAnnotations.map(ann => { - const icons = { - new: '🆕', - burst: '⚡', - pattern: '🔄', - flagged: '🚩', - gone: '📴' + const iconFuncs = { + new: () => Icons.newBadge('icon--sm'), + burst: () => Icons.meter('icon--sm'), + pattern: () => Icons.refresh('icon--sm'), + flagged: () => Icons.flag('icon--sm'), + gone: () => Icons.offline('icon--sm') }; + const iconHtml = iconFuncs[ann.type] ? iconFuncs[ann.type]() : Icons.sensor('icon--sm'); return `
- ${icons[ann.type] || '📡'} + ${iconHtml} ${ann.message} ${formatTimeAgo(ann.timestamp)}
diff --git a/static/js/core/audio.js b/static/js/core/audio.js index 2b58c0e..b99c2df 100644 --- a/static/js/core/audio.js +++ b/static/js/core/audio.js @@ -211,7 +211,7 @@ function isMuted() { function updateMuteButton() { const btn = document.getElementById('muteBtn'); if (btn) { - btn.innerHTML = audioMuted ? '🔇 UNMUTE' : '🔊 MUTE'; + btn.innerHTML = audioMuted ? Icons.volumeOff('icon--sm') + ' UNMUTE' : Icons.volumeOn('icon--sm') + ' MUTE'; btn.classList.toggle('muted', audioMuted); } } @@ -226,7 +226,7 @@ function requestNotificationPermission() { Notification.requestPermission().then(permission => { notificationsEnabled = permission === 'granted'; if (notificationsEnabled && typeof showInfo === 'function') { - showInfo('🔔 Desktop notifications enabled'); + showInfo('Desktop notifications enabled'); } }); } diff --git a/static/js/core/utils.js b/static/js/core/utils.js index 6f9676a..d09f7a1 100644 --- a/static/js/core/utils.js +++ b/static/js/core/utils.js @@ -277,119 +277,170 @@ function mapRange(value, inMin, inMax, outMin, outMax) { // Designed for screenshot legibility - standard symbols only. const Icons = { - /** - * WiFi icon - standard arc/fan shape - */ + // ===== Signal Type Icons ===== wifi: function(className) { - return ` - - - - - - - `; + return ``; }, - - /** - * Bluetooth icon - standard rune - */ bluetooth: function(className) { - return ` - - - - `; + return ``; }, - - /** - * Cellular icon - ascending bars - */ cellular: function(className) { - return ` - - - - - - - `; + return ``; + }, + radio: function(className) { + return ``; }, - /** - * Unknown/RF signal - generic wave - */ - signalUnknown: function(className) { - return ` - - - - `; + // ===== Mode Icons ===== + pager: function(className) { + return ``; + }, + sensor: function(className) { + return ``; + }, + aircraft: function(className) { + return ``; + }, + satellite: function(className) { + return ``; + }, + location: function(className) { + return ``; + }, + search: function(className) { + return ``; + }, + meter: function(className) { + return ``; + }, + scanner: function(className) { + return ``; }, - /** - * Recording indicator - filled circle - */ + // ===== Status Icons ===== + warning: function(className) { + return ``; + }, + check: function(className) { + return ``; + }, + x: function(className) { + return ``; + }, recording: function(className) { - return ` - - - - `; + return ``; }, - - /** - * Anomaly indicator - filled circle (amber by default via CSS) - */ anomaly: function(className) { - return ` - - - - `; + return ``; + }, + flag: function(className) { + return ``; + }, + newBadge: function(className) { + return ``; + }, + offline: function(className) { + return ``; }, - /** - * Export icon - arrow out of box - */ - export: function(className) { - return ` - - - - - - `; + // ===== Device Type Icons ===== + user: function(className) { + return ``; + }, + drone: function(className) { + return ``; + }, + military: function(className) { + return ``; + }, + handshake: function(className) { + return ``; }, - /** - * Refresh icon - circular arrows - */ + // ===== Action Icons ===== refresh: function(className) { - return ` - - - - - - `; + return ``; + }, + download: function(className) { + return ``; + }, + export: function(className) { + return ``; + }, + copy: function(className) { + return ``; + }, + link: function(className) { + return ``; + }, + chart: function(className) { + return ``; + }, + star: function(className) { + return ``; + }, + target: function(className) { + return ``; + }, + settings: function(className) { + return ``; }, - /** - * Get icon by signal type - * Maps protocol names to appropriate icons - */ + // ===== Playback Controls ===== + play: function(className) { + return ``; + }, + pause: function(className) { + return ``; + }, + stop: function(className) { + return ``; + }, + headphones: function(className) { + return ``; + }, + volumeOn: function(className) { + return ``; + }, + volumeOff: function(className) { + return ``; + }, + + // ===== UI Icons ===== + sun: function(className) { + return ``; + }, + moon: function(className) { + return ``; + }, + arrowDown: function(className) { + return ``; + }, + chevronDown: function(className) { + return ``; + }, + chevronRight: function(className) { + return ``; + }, + chevronLeft: function(className) { + return ``; + }, + mail: function(className) { + return ``; + }, + loader: function(className) { + return ``; + }, + bell: function(className) { + return ``; + }, + + // ===== Helper function ===== forSignalType: function(type, className) { const t = (type || '').toLowerCase(); - if (t.includes('wifi') || t.includes('802.11')) { - return this.wifi(className); - } - if (t.includes('bluetooth') || t.includes('bt') || t.includes('ble')) { - return this.bluetooth(className); - } - if (t.includes('cellular') || t.includes('lte') || t.includes('gsm') || t.includes('5g')) { - return this.cellular(className); - } - return this.signalUnknown(className); + if (t.includes('wifi') || t.includes('802.11')) return this.wifi(className); + if (t.includes('bluetooth') || t.includes('bt') || t.includes('ble')) return this.bluetooth(className); + if (t.includes('cellular') || t.includes('lte') || t.includes('gsm') || t.includes('5g')) return this.cellular(className); + return this.radio(className); } }; diff --git a/static/js/modes/listening-post.js b/static/js/modes/listening-post.js index 1fb87fb..5f9f588 100644 --- a/static/js/modes/listening-post.js +++ b/static/js/modes/listening-post.js @@ -216,7 +216,7 @@ function startScanner() { // Update radio scan button to show STOP const radioScanBtn = document.getElementById('radioScanBtn'); if (radioScanBtn) { - radioScanBtn.innerHTML = '⏹ STOP'; + radioScanBtn.innerHTML = Icons.stop('icon--sm') + ' STOP'; radioScanBtn.style.background = 'var(--accent-red)'; radioScanBtn.style.borderColor = 'var(--accent-red)'; } @@ -268,7 +268,7 @@ function stopScanner() { const pauseBtn = document.getElementById('scannerPauseBtn'); if (pauseBtn) { pauseBtn.disabled = true; - pauseBtn.textContent = '⏸ Pause'; + pauseBtn.innerHTML = Icons.pause('icon--sm') + ' Pause'; } // Update radio scan button @@ -338,7 +338,7 @@ function pauseScanner() { .then(data => { isScannerPaused = !isScannerPaused; const pauseBtn = document.getElementById('scannerPauseBtn'); - if (pauseBtn) pauseBtn.textContent = isScannerPaused ? '▶ Resume' : '⏸ Pause'; + if (pauseBtn) pauseBtn.innerHTML = isScannerPaused ? Icons.play('icon--sm') + ' Resume' : Icons.pause('icon--sm') + ' Pause'; const statusText = document.getElementById('scannerStatusText'); if (statusText) { statusText.textContent = isScannerPaused ? 'PAUSED' : 'SCANNING'; @@ -873,7 +873,7 @@ function startAudio() { } }); - document.getElementById('audioStartBtn').textContent = '⏹ Stop Audio'; + document.getElementById('audioStartBtn').innerHTML = Icons.stop('icon--sm') + ' Stop Audio'; document.getElementById('audioStartBtn').classList.add('active'); document.getElementById('audioTunedFreq').textContent = frequency.toFixed(2) + ' MHz (' + modulation.toUpperCase() + ')'; document.getElementById('audioDeviceStatus').textContent = 'SDR ' + device; @@ -896,7 +896,7 @@ async function stopAudio() { await fetch('/listening/audio/stop', { method: 'POST' }); if (typeof releaseDevice === 'function') releaseDevice('audio'); isAudioPlaying = false; - document.getElementById('audioStartBtn').textContent = '▶ Play Audio'; + document.getElementById('audioStartBtn').innerHTML = Icons.play('icon--sm') + ' Play Audio'; document.getElementById('audioStartBtn').classList.remove('active'); document.getElementById('audioStatus').textContent = 'STOPPED'; document.getElementById('audioStatus').style.color = 'var(--text-muted)'; @@ -1741,7 +1741,7 @@ async function _startDirectListenInternal() { const listenBtn = document.getElementById('radioListenBtn'); if (listenBtn) { - listenBtn.innerHTML = '⏳ TUNING...'; + listenBtn.innerHTML = Icons.loader('icon--sm') + ' TUNING...'; listenBtn.style.background = 'var(--accent-orange)'; listenBtn.style.borderColor = 'var(--accent-orange)'; } @@ -1879,11 +1879,11 @@ function updateDirectListenUI(isPlaying, freq) { if (listenBtn) { if (isPlaying) { - listenBtn.innerHTML = '⏹ STOP'; + listenBtn.innerHTML = Icons.stop('icon--sm') + ' STOP'; listenBtn.style.background = 'var(--accent-red)'; listenBtn.style.borderColor = 'var(--accent-red)'; } else { - listenBtn.innerHTML = '🎧 LISTEN'; + listenBtn.innerHTML = Icons.headphones('icon--sm') + ' LISTEN'; listenBtn.style.background = 'var(--accent-purple)'; listenBtn.style.borderColor = 'var(--accent-purple)'; } diff --git a/templates/index.html b/templates/index.html index cbf6ad3..030fbe4 100644 --- a/templates/index.html +++ b/templates/index.html @@ -78,47 +78,47 @@

Select Mode

- ✈️ + Aircraft ADS-B tracking @@ -137,7 +137,7 @@