Fix card rendering - use string concat instead of template literals

- Change card HTML generation from template literals to string concatenation
- This avoids potential issues with special characters in device data
- Also disable legacy handleBtDeviceImmediate when BluetoothMode exists
- Use device_id as fallback name if name is missing

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Smittix
2026-01-21 17:52:32 +00:00
parent bac7f8d55c
commit 91b07fe797
2 changed files with 42 additions and 45 deletions
+37 -45
View File
@@ -184,57 +184,49 @@ const DeviceCard = (function() {
const protocolBadge = createProtocolBadge(device.protocol) || ''; const protocolBadge = createProtocolBadge(device.protocol) || '';
// Build card with explicit defaults for all values // Build card with explicit defaults for all values
const deviceName = device.name || 'Unknown Device'; const deviceName = device.name || device.device_id || 'Unknown Device';
const deviceAddress = device.address || 'Unknown'; const deviceAddress = device.address || 'Unknown';
const addressType = device.address_type || 'unknown'; const addressType = device.address_type || 'unknown';
const rssiDisplay = device.rssi_current !== null && device.rssi_current !== undefined const rssiDisplay = (device.rssi_current !== null && device.rssi_current !== undefined)
? device.rssi_current + ' dBm' : '--'; ? device.rssi_current + ' dBm' : '--';
const seenCount = device.seen_count || 0; const seenCount = device.seen_count || 0;
const inBaseline = device.in_baseline || false; const inBaseline = device.in_baseline || false;
const mfrName = device.manufacturer_name || '';
card.innerHTML = ` // Build the HTML parts separately to avoid template issues
<div class="signal-card-header"> const headerHtml = '<div class="signal-card-header">' +
<div class="signal-card-badges"> '<div class="signal-card-badges">' + protocolBadge + heuristicBadges + '</div>' +
${protocolBadge} '<span class="signal-status-pill" data-status="' + (inBaseline ? 'baseline' : 'new') + '">' +
${heuristicBadges} '<span class="status-dot"></span>' + (inBaseline ? 'Known' : 'New') + '</span>' +
</div> '</div>';
<span class="signal-status-pill" data-status="${inBaseline ? 'baseline' : 'new'}">
<span class="status-dot"></span> const identityHtml = '<div class="device-identity">' +
${inBaseline ? 'Known' : 'New'} '<div class="device-name">' + escapeHtml(deviceName) + '</div>' +
</span> '<div class="device-address">' +
</div> '<span class="address-value">' + escapeHtml(deviceAddress) + '</span>' +
<div class="signal-card-body"> '<span class="address-type">(' + escapeHtml(addressType) + ')</span>' +
<div class="device-identity"> '</div></div>';
<div class="device-name">${escapeHtml(deviceName)}</div>
<div class="device-address"> const signalHtml = '<div class="device-signal-row">' +
<span class="address-value">${escapeHtml(deviceAddress)}</span> '<div class="rssi-display">' +
<span class="address-type">(${escapeHtml(addressType)})</span> '<span class="rssi-current" title="Current RSSI">' + rssiDisplay + '</span>' +
</div> sparkline + '</div>' + rangeBand + '</div>';
</div>
<div class="device-signal-row"> const mfrHtml = mfrName ?
<div class="rssi-display"> '<div class="device-manufacturer">' +
<span class="rssi-current" title="Current RSSI">${rssiDisplay}</span> '<span class="mfr-icon">🏭</span>' +
${sparkline} '<span class="mfr-name">' + escapeHtml(mfrName) + '</span></div>' : '';
</div>
${rangeBand} const metaHtml = '<div class="device-meta-row">' +
</div> '<span class="device-seen-count" title="Observation count">' +
${device.manufacturer_name ? ` '<span class="seen-icon">👁</span>' + seenCount + '×</span>' +
<div class="device-manufacturer"> '<span class="device-timestamp" data-timestamp="' + escapeHtml(device.last_seen || '') + '">' +
<span class="mfr-icon">🏭</span> escapeHtml(relativeTime) + '</span></div>';
<span class="mfr-name">${escapeHtml(device.manufacturer_name)}</span>
</div> const bodyHtml = '<div class="signal-card-body">' +
` : ''} identityHtml + signalHtml + mfrHtml + metaHtml + '</div>';
<div class="device-meta-row">
<span class="device-seen-count" title="Observation count"> card.innerHTML = headerHtml + bodyHtml;
<span class="seen-icon">👁</span>
${seenCount}×
</span>
<span class="device-timestamp" data-timestamp="${escapeHtml(device.last_seen || '')}">
${escapeHtml(relativeTime)}
</span>
</div>
</div>
`;
// Make card clickable - opens modal with full details // Make card clickable - opens modal with full details
card.addEventListener('click', () => { card.addEventListener('click', () => {
+5
View File
@@ -6090,6 +6090,11 @@
// Handle discovered Bluetooth device (called from batched update) // Handle discovered Bluetooth device (called from batched update)
function handleBtDeviceImmediate(device) { function handleBtDeviceImmediate(device) {
// Skip if new BluetoothMode is handling devices
if (typeof BluetoothMode !== 'undefined') {
return;
}
const isNew = !btDevices[device.mac]; const isNew = !btDevices[device.mac];
// Check for Find My network // Check for Find My network