mirror of
https://github.com/smittix/intercept.git
synced 2026-06-11 15:33:32 -07:00
Improve Bluetooth panel layout, signal bars, and add device filtering
- Rearranged layout: Proximity Radar on top, Tracker Detection and Signal Distribution side-by-side below for better space usage - Made signal distribution bars thicker (16px) with gradient styling for better visibility - Added device filtering with buttons: All, New, Named, Strong signal - Filter buttons show filtered count (e.g., "5/37") when active Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
+65
-10
@@ -3269,8 +3269,28 @@ header h1 .tagline {
|
||||
min-height: 400px;
|
||||
}
|
||||
|
||||
.bt-layout-container .wifi-visuals {
|
||||
.bt-visuals-column {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.bt-radar-panel {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.bt-bottom-panels {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.bt-compact-panel {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.bt-device-list {
|
||||
@@ -3281,33 +3301,68 @@ header h1 .tagline {
|
||||
color: var(--accent-purple);
|
||||
}
|
||||
|
||||
/* Bluetooth Device Filters */
|
||||
.bt-device-filters {
|
||||
display: flex;
|
||||
gap: 6px;
|
||||
padding: 8px 12px;
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.bt-filter-btn {
|
||||
padding: 5px 12px;
|
||||
font-size: 11px;
|
||||
background: var(--bg-tertiary);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 4px;
|
||||
color: var(--text-dim);
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.bt-filter-btn:hover {
|
||||
background: var(--bg-secondary);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.bt-filter-btn.active {
|
||||
background: var(--accent-purple);
|
||||
border-color: var(--accent-purple);
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* Bluetooth Signal Distribution */
|
||||
.bt-signal-dist {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
font-size: 10px;
|
||||
gap: 12px;
|
||||
font-size: 11px;
|
||||
padding: 4px 0;
|
||||
}
|
||||
|
||||
.signal-range {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.signal-range span:first-child {
|
||||
width: 70px;
|
||||
width: 80px;
|
||||
color: var(--text-dim);
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.signal-range span:last-child {
|
||||
width: 20px;
|
||||
width: 28px;
|
||||
text-align: right;
|
||||
font-weight: 600;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.signal-bar-bg {
|
||||
flex: 1;
|
||||
height: 8px;
|
||||
height: 16px;
|
||||
background: var(--bg-tertiary);
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
@@ -3320,15 +3375,15 @@ header h1 .tagline {
|
||||
}
|
||||
|
||||
.signal-bar.strong {
|
||||
background: var(--accent-green);
|
||||
background: linear-gradient(90deg, #22c55e, #16a34a);
|
||||
}
|
||||
|
||||
.signal-bar.medium {
|
||||
background: var(--accent-orange);
|
||||
background: linear-gradient(90deg, #eab308, #ca8a04);
|
||||
}
|
||||
|
||||
.signal-bar.weak {
|
||||
background: var(--accent-red);
|
||||
background: linear-gradient(90deg, #ef4444, #dc2626);
|
||||
}
|
||||
|
||||
/* Bluetooth Device Cards */
|
||||
|
||||
@@ -33,6 +33,9 @@ const BluetoothMode = (function() {
|
||||
let radarInitialized = false;
|
||||
let radarPaused = false;
|
||||
|
||||
// Device list filter
|
||||
let currentDeviceFilter = 'all';
|
||||
|
||||
/**
|
||||
* Initialize the Bluetooth mode
|
||||
*/
|
||||
@@ -64,10 +67,87 @@ const BluetoothMode = (function() {
|
||||
// Initialize legacy heatmap (zone counts)
|
||||
initHeatmap();
|
||||
|
||||
// Initialize device list filters
|
||||
initDeviceFilters();
|
||||
|
||||
// Set initial panel states
|
||||
updateVisualizationPanels();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize device list filter buttons
|
||||
*/
|
||||
function initDeviceFilters() {
|
||||
const filterContainer = document.getElementById('btDeviceFilters');
|
||||
if (!filterContainer) return;
|
||||
|
||||
filterContainer.addEventListener('click', (e) => {
|
||||
const btn = e.target.closest('.bt-filter-btn');
|
||||
if (!btn) return;
|
||||
|
||||
const filter = btn.dataset.filter;
|
||||
if (!filter) return;
|
||||
|
||||
// Update active state
|
||||
filterContainer.querySelectorAll('.bt-filter-btn').forEach(b => b.classList.remove('active'));
|
||||
btn.classList.add('active');
|
||||
|
||||
// Apply filter
|
||||
currentDeviceFilter = filter;
|
||||
applyDeviceFilter();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply current filter to device list
|
||||
*/
|
||||
function applyDeviceFilter() {
|
||||
if (!deviceContainer) return;
|
||||
|
||||
const cards = deviceContainer.querySelectorAll('[data-bt-device-id]');
|
||||
cards.forEach(card => {
|
||||
const isNew = card.dataset.isNew === 'true';
|
||||
const hasName = card.dataset.hasName === 'true';
|
||||
const rssi = parseInt(card.dataset.rssi) || -100;
|
||||
|
||||
let visible = true;
|
||||
switch (currentDeviceFilter) {
|
||||
case 'new':
|
||||
visible = isNew;
|
||||
break;
|
||||
case 'named':
|
||||
visible = hasName;
|
||||
break;
|
||||
case 'strong':
|
||||
visible = rssi >= -70;
|
||||
break;
|
||||
case 'all':
|
||||
default:
|
||||
visible = true;
|
||||
}
|
||||
|
||||
card.style.display = visible ? 'block' : 'none';
|
||||
});
|
||||
|
||||
// Update visible count
|
||||
updateFilteredCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the device count display based on visible devices
|
||||
*/
|
||||
function updateFilteredCount() {
|
||||
const countEl = document.getElementById('btDeviceListCount');
|
||||
if (!countEl || !deviceContainer) return;
|
||||
|
||||
if (currentDeviceFilter === 'all') {
|
||||
countEl.textContent = devices.size;
|
||||
} else {
|
||||
const visible = deviceContainer.querySelectorAll('[data-bt-device-id]:not([style*="display: none"])').length;
|
||||
countEl.textContent = visible + '/' + devices.size;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the new proximity radar component
|
||||
*/
|
||||
@@ -676,10 +756,7 @@ const BluetoothMode = (function() {
|
||||
}
|
||||
|
||||
function updateDeviceCount() {
|
||||
const countEl = document.getElementById('btDeviceListCount');
|
||||
if (countEl) {
|
||||
countEl.textContent = devices.size;
|
||||
}
|
||||
updateFilteredCount();
|
||||
}
|
||||
|
||||
function renderDevice(device) {
|
||||
@@ -697,6 +774,11 @@ const BluetoothMode = (function() {
|
||||
} else {
|
||||
deviceContainer.insertAdjacentHTML('afterbegin', cardHtml);
|
||||
}
|
||||
|
||||
// Re-apply filter after rendering
|
||||
if (currentDeviceFilter !== 'all') {
|
||||
applyDeviceFilter();
|
||||
}
|
||||
}
|
||||
|
||||
function createSimpleDeviceCard(device) {
|
||||
@@ -738,8 +820,10 @@ const BluetoothMode = (function() {
|
||||
const statusPillStyle = 'background:' + (inBaseline ? 'rgba(34,197,94,0.15)' : 'rgba(59,130,246,0.15)') + ';color:' + (inBaseline ? '#22c55e' : '#3b82f6') + ';padding:3px 10px;border-radius:12px;font-size:10px;font-weight:500;';
|
||||
|
||||
const deviceIdEscaped = escapeHtml(device.device_id).replace(/'/g, "\\'");
|
||||
const isNew = !inBaseline;
|
||||
const hasName = !!device.name;
|
||||
|
||||
return '<div data-bt-device-id="' + escapeHtml(device.device_id) + '" style="' + cardStyle + '" onclick="BluetoothMode.selectDevice(\'' + deviceIdEscaped + '\')" onmouseover="this.style.borderColor=\'#00d4ff\'" onmouseout="this.style.borderColor=\'#444\'">' +
|
||||
return '<div data-bt-device-id="' + escapeHtml(device.device_id) + '" data-is-new="' + isNew + '" data-has-name="' + hasName + '" data-rssi="' + (rssi || -100) + '" style="' + cardStyle + '" onclick="BluetoothMode.selectDevice(\'' + deviceIdEscaped + '\')" onmouseover="this.style.borderColor=\'#00d4ff\'" onmouseout="this.style.borderColor=\'#444\'">' +
|
||||
'<div style="' + headerStyle + '">' +
|
||||
'<div>' + protoBadge + badgesHtml + '</div>' +
|
||||
'<span style="' + statusPillStyle + '">' + (inBaseline ? '✓ Known' : '● New') + '</span>' +
|
||||
|
||||
+38
-31
@@ -706,9 +706,9 @@
|
||||
<!-- Bluetooth Layout Container (visualizations left, device cards right) -->
|
||||
<div class="bt-layout-container" id="btLayoutContainer" style="display: none;">
|
||||
<!-- Left: Bluetooth Visualizations -->
|
||||
<div class="wifi-visuals" id="btVisuals">
|
||||
<!-- Row 1: Proximity Radar + Device Types -->
|
||||
<div class="wifi-visual-panel" style="grid-row: span 2;">
|
||||
<div class="bt-visuals-column" id="btVisuals">
|
||||
<!-- Proximity Radar -->
|
||||
<div class="wifi-visual-panel bt-radar-panel">
|
||||
<h5>Proximity Radar</h5>
|
||||
<div id="btProximityRadar" style="display: flex; justify-content: center; padding: 8px 0;"></div>
|
||||
<div id="btRadarControls" style="display: flex; gap: 6px; justify-content: center; margin-top: 8px; flex-wrap: wrap;">
|
||||
@@ -717,46 +717,47 @@
|
||||
<button data-filter="unapproved" class="bt-radar-filter-btn" style="padding: 4px 10px; font-size: 10px; background: var(--bg-tertiary); border: 1px solid var(--border-color); border-radius: 4px; color: #888; cursor: pointer;">Unapproved</button>
|
||||
<button id="btRadarPauseBtn" style="padding: 4px 10px; font-size: 10px; background: var(--bg-tertiary); border: 1px solid var(--border-color); border-radius: 4px; color: #888; cursor: pointer;">Pause</button>
|
||||
</div>
|
||||
<div id="btZoneSummary" style="display: flex; justify-content: center; gap: 16px; margin-top: 12px; font-size: 11px;">
|
||||
<div id="btZoneSummary" style="display: flex; justify-content: center; gap: 24px; margin-top: 12px; font-size: 11px;">
|
||||
<div style="text-align: center;">
|
||||
<span id="btZoneImmediate" style="font-size: 18px; font-weight: 600; color: #22c55e;">0</span>
|
||||
<span id="btZoneImmediate" style="font-size: 20px; font-weight: 600; color: #22c55e;">0</span>
|
||||
<div style="color: #666;">Immediate</div>
|
||||
</div>
|
||||
<div style="text-align: center;">
|
||||
<span id="btZoneNear" style="font-size: 18px; font-weight: 600; color: #eab308;">0</span>
|
||||
<span id="btZoneNear" style="font-size: 20px; font-weight: 600; color: #eab308;">0</span>
|
||||
<div style="color: #666;">Near</div>
|
||||
</div>
|
||||
<div style="text-align: center;">
|
||||
<span id="btZoneFar" style="font-size: 18px; font-weight: 600; color: #ef4444;">0</span>
|
||||
<span id="btZoneFar" style="font-size: 20px; font-weight: 600; color: #ef4444;">0</span>
|
||||
<div style="color: #666;">Far</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Row 2: Tracker Detection + Signal Analysis -->
|
||||
<div class="wifi-visual-panel">
|
||||
<h5>Tracker Detection</h5>
|
||||
<div id="btTrackerList" style="max-height: 120px; overflow-y: auto; font-size: 11px;">
|
||||
<div style="color: var(--text-dim); padding: 10px; text-align: center;">Monitoring for
|
||||
AirTags, Tiles...</div>
|
||||
<!-- Bottom row: Tracker Detection + Signal Distribution -->
|
||||
<div class="bt-bottom-panels">
|
||||
<div class="wifi-visual-panel bt-compact-panel">
|
||||
<h5>Tracker Detection</h5>
|
||||
<div id="btTrackerList" style="font-size: 11px;">
|
||||
<div style="color: var(--text-dim); padding: 10px; text-align: center;">Monitoring for AirTags, Tiles...</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="wifi-visual-panel">
|
||||
<h5>Signal Distribution</h5>
|
||||
<div class="bt-signal-dist" id="btSignalDist">
|
||||
<div class="signal-range"><span>Strong (-50+)</span>
|
||||
<div class="signal-bar-bg">
|
||||
<div class="signal-bar strong" id="btSignalStrong" style="width: 0%;"></div>
|
||||
</div><span id="btSignalStrongCount">0</span>
|
||||
</div>
|
||||
<div class="signal-range"><span>Medium (-70)</span>
|
||||
<div class="signal-bar-bg">
|
||||
<div class="signal-bar medium" id="btSignalMedium" style="width: 0%;"></div>
|
||||
</div><span id="btSignalMediumCount">0</span>
|
||||
</div>
|
||||
<div class="signal-range"><span>Weak (-90)</span>
|
||||
<div class="signal-bar-bg">
|
||||
<div class="signal-bar weak" id="btSignalWeak" style="width: 0%;"></div>
|
||||
</div><span id="btSignalWeakCount">0</span>
|
||||
<div class="wifi-visual-panel bt-compact-panel">
|
||||
<h5>Signal Distribution</h5>
|
||||
<div class="bt-signal-dist" id="btSignalDist">
|
||||
<div class="signal-range"><span>Strong (-50+)</span>
|
||||
<div class="signal-bar-bg">
|
||||
<div class="signal-bar strong" id="btSignalStrong" style="width: 0%;"></div>
|
||||
</div><span id="btSignalStrongCount">0</span>
|
||||
</div>
|
||||
<div class="signal-range"><span>Medium (-70)</span>
|
||||
<div class="signal-bar-bg">
|
||||
<div class="signal-bar medium" id="btSignalMedium" style="width: 0%;"></div>
|
||||
</div><span id="btSignalMediumCount">0</span>
|
||||
</div>
|
||||
<div class="signal-range"><span>Weak (-90)</span>
|
||||
<div class="signal-bar-bg">
|
||||
<div class="signal-bar weak" id="btSignalWeak" style="width: 0%;"></div>
|
||||
</div><span id="btSignalWeakCount">0</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -767,6 +768,12 @@
|
||||
<h5>Bluetooth Devices</h5>
|
||||
<span class="device-count">(<span id="btDeviceListCount">0</span>)</span>
|
||||
</div>
|
||||
<div class="bt-device-filters" id="btDeviceFilters">
|
||||
<button class="bt-filter-btn active" data-filter="all">All</button>
|
||||
<button class="bt-filter-btn" data-filter="new">New</button>
|
||||
<button class="bt-filter-btn" data-filter="named">Named</button>
|
||||
<button class="bt-filter-btn" data-filter="strong">Strong</button>
|
||||
</div>
|
||||
<div class="wifi-device-list-content" id="btDeviceListContent">
|
||||
<div style="color: var(--text-dim); text-align: center; padding: 30px;">
|
||||
Start scanning to discover Bluetooth devices
|
||||
|
||||
Reference in New Issue
Block a user