Add alerts/recording, WiFi/TSCM updates, optimize waterfall

This commit is contained in:
Smittix
2026-02-07 18:29:58 +00:00
parent 4bbc00b765
commit 86e4ba7e29
42 changed files with 2514 additions and 485 deletions

View File

@@ -366,7 +366,10 @@ const BluetoothMode = (function() {
// Badges
const badgesEl = document.getElementById('btDetailBadges');
let badgesHtml = `<span class="bt-detail-badge ${protocol}">${protocol.toUpperCase()}</span>`;
badgesHtml += `<span class="bt-detail-badge ${device.in_baseline ? 'baseline' : 'new'}">${device.in_baseline ? '✓ KNOWN' : '● NEW'}</span>`;
badgesHtml += `<span class="bt-detail-badge ${device.in_baseline ? 'baseline' : 'new'}">${device.in_baseline ? '✓ KNOWN' : '● NEW'}</span>`;
if (device.seen_before) {
badgesHtml += `<span class="bt-detail-badge flag">SEEN BEFORE</span>`;
}
// Tracker badge
if (device.is_tracker) {
@@ -448,12 +451,14 @@ const BluetoothMode = (function() {
? minMax[0] + '/' + minMax[1]
: '--';
document.getElementById('btDetailFirstSeen').textContent = device.first_seen
? new Date(device.first_seen).toLocaleTimeString()
: '--';
document.getElementById('btDetailLastSeen').textContent = device.last_seen
? new Date(device.last_seen).toLocaleTimeString()
: '--';
document.getElementById('btDetailFirstSeen').textContent = device.first_seen
? new Date(device.first_seen).toLocaleTimeString()
: '--';
document.getElementById('btDetailLastSeen').textContent = device.last_seen
? new Date(device.last_seen).toLocaleTimeString()
: '--';
updateWatchlistButton(device);
// Services
const servicesContainer = document.getElementById('btDetailServices');
@@ -465,13 +470,29 @@ const BluetoothMode = (function() {
servicesContainer.style.display = 'none';
}
// Show content, hide placeholder
placeholder.style.display = 'none';
content.style.display = 'block';
// Show content, hide placeholder
placeholder.style.display = 'none';
content.style.display = 'block';
// Highlight selected device in list
highlightSelectedDevice(deviceId);
}
}
/**
* Update watchlist button state
*/
function updateWatchlistButton(device) {
const btn = document.getElementById('btDetailWatchBtn');
if (!btn) return;
if (typeof AlertCenter === 'undefined') {
btn.style.display = 'none';
return;
}
btn.style.display = '';
const watchlisted = AlertCenter.isWatchlisted(device.address);
btn.textContent = watchlisted ? 'Watching' : 'Watchlist';
btn.classList.toggle('active', watchlisted);
}
/**
* Clear device selection
@@ -525,24 +546,43 @@ const BluetoothMode = (function() {
/**
* Copy selected device address to clipboard
*/
function copyAddress() {
if (!selectedDeviceId) return;
const device = devices.get(selectedDeviceId);
if (!device) return;
function copyAddress() {
if (!selectedDeviceId) return;
const device = devices.get(selectedDeviceId);
if (!device) return;
navigator.clipboard.writeText(device.address).then(() => {
const btn = document.querySelector('.bt-detail-btn');
if (btn) {
const originalText = btn.textContent;
btn.textContent = 'Copied!';
btn.style.background = '#22c55e';
navigator.clipboard.writeText(device.address).then(() => {
const btn = document.getElementById('btDetailCopyBtn');
if (btn) {
const originalText = btn.textContent;
btn.textContent = 'Copied!';
btn.style.background = '#22c55e';
setTimeout(() => {
btn.textContent = originalText;
btn.style.background = '';
}, 1500);
}
});
}
});
}
/**
* Toggle Bluetooth watchlist for selected device
*/
function toggleWatchlist() {
if (!selectedDeviceId) return;
const device = devices.get(selectedDeviceId);
if (!device || typeof AlertCenter === 'undefined') return;
if (AlertCenter.isWatchlisted(device.address)) {
AlertCenter.removeBluetoothWatchlist(device.address);
showInfo('Removed from watchlist');
} else {
AlertCenter.addBluetoothWatchlist(device.address, device.name || device.address);
showInfo('Added to watchlist');
}
setTimeout(() => updateWatchlistButton(device), 200);
}
/**
* Select a device - opens modal with details
@@ -1090,10 +1130,11 @@ const BluetoothMode = (function() {
const isNew = !inBaseline;
const hasName = !!device.name;
const isTracker = device.is_tracker === true;
const trackerType = device.tracker_type;
const trackerConfidence = device.tracker_confidence;
const riskScore = device.risk_score || 0;
const agentName = device._agent || 'Local';
const trackerType = device.tracker_type;
const trackerConfidence = device.tracker_confidence;
const riskScore = device.risk_score || 0;
const agentName = device._agent || 'Local';
const seenBefore = device.seen_before === true;
// Calculate RSSI bar width (0-100%)
// RSSI typically ranges from -100 (weak) to -30 (very strong)
@@ -1145,8 +1186,9 @@ const BluetoothMode = (function() {
// Build secondary info line
let secondaryParts = [addr];
if (mfr) secondaryParts.push(mfr);
secondaryParts.push('Seen ' + seenCount + '×');
if (mfr) secondaryParts.push(mfr);
secondaryParts.push('Seen ' + seenCount + '×');
if (seenBefore) secondaryParts.push('<span class="bt-history-badge">SEEN BEFORE</span>');
// Add agent name if not Local
if (agentName !== 'Local') {
secondaryParts.push('<span class="agent-badge agent-remote" style="font-size:8px;padding:1px 4px;">' + escapeHtml(agentName) + '</span>');
@@ -1358,9 +1400,10 @@ const BluetoothMode = (function() {
setBaseline,
clearBaseline,
exportData,
selectDevice,
clearSelection,
copyAddress,
selectDevice,
clearSelection,
copyAddress,
toggleWatchlist,
// Agent handling
handleAgentChange,