diff --git a/static/css/components/device-cards.css b/static/css/components/device-cards.css index 0489abd..26bdf07 100644 --- a/static/css/components/device-cards.css +++ b/static/css/components/device-cards.css @@ -555,27 +555,32 @@ } /* ============================================ - DEVICE CARD GRID LAYOUT + BLUETOOTH DEVICE LIST CONTAINER ============================================ */ #btDeviceListContent { - display: grid !important; - grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)) !important; - grid-auto-rows: auto !important; - gap: 12px !important; - padding: 12px !important; - align-items: start !important; + display: block !important; + padding: 10px !important; + overflow-y: auto !important; + overflow-x: hidden !important; } -#btDeviceListContent > * { - min-height: auto !important; +/* Pure inline-styled cards - ensure no interference */ +#btDeviceListContent > div[data-bt-device-id] { + display: block !important; + visibility: visible !important; + opacity: 1 !important; height: auto !important; + min-height: auto !important; + overflow: visible !important; } +/* Legacy card support */ #btDeviceListContent .device-card, #btDeviceListContent .signal-card { - margin: 0; + margin: 0 0 10px 0; height: auto !important; min-height: auto !important; + overflow: visible !important; } /* Ensure card body is visible */ diff --git a/static/js/modes/bluetooth.js b/static/js/modes/bluetooth.js index eee2e27..a15ccc7 100644 --- a/static/js/modes/bluetooth.js +++ b/static/js/modes/bluetooth.js @@ -311,76 +311,93 @@ const BluetoothMode = (function() { * Render a device card */ function renderDevice(device) { - console.log('[BT] Rendering device:', device.device_id, 'Container:', deviceContainer); + console.log('[BT] Rendering device:', device.device_id, device); if (!deviceContainer) { - console.warn('[BT] No device container found!'); - // Try to find it again deviceContainer = document.getElementById('btDeviceListContent'); if (!deviceContainer) { - console.error('[BT] Still no container - cannot render'); + console.error('[BT] No container - cannot render'); return; } } - const existingCard = deviceContainer.querySelector(`[data-device-id="${device.device_id}"]`); + // Use simple inline rendering with NO CSS classes to avoid any interference + const escapedId = CSS.escape(device.device_id); + const existingCard = deviceContainer.querySelector('[data-bt-device-id="' + escapedId + '"]'); + const cardHtml = createSimpleDeviceCard(device); - if (typeof DeviceCard !== 'undefined') { - // DeviceCard.createDeviceCard returns a DOM element - const cardElement = DeviceCard.createDeviceCard(device); + console.log('[BT] Card HTML length:', cardHtml.length, 'existing:', !!existingCard); - if (existingCard) { - existingCard.replaceWith(cardElement); - } else { - deviceContainer.prepend(cardElement); - } - - // Attach click handler - cardElement.addEventListener('click', () => showDeviceDetails(device.device_id)); + if (existingCard) { + existingCard.outerHTML = cardHtml; } else { - // Fallback simple rendering (returns HTML string) - const cardHtml = createSimpleDeviceCard(device); - - if (existingCard) { - existingCard.outerHTML = cardHtml; - } else { - deviceContainer.insertAdjacentHTML('afterbegin', cardHtml); - } + deviceContainer.insertAdjacentHTML('afterbegin', cardHtml); } + + // Log container state + console.log('[BT] Container now has', deviceContainer.children.length, 'children'); } /** - * Simple device card fallback + * Simple device card - pure inline rendering with NO CSS classes + * This avoids any CSS conflicts by using only inline styles */ function createSimpleDeviceCard(device) { - const protoBadge = device.protocol === 'ble' - ? 'BLE' - : 'CLASSIC'; + const protocol = device.protocol || 'ble'; + const protoBadge = protocol === 'ble' + ? 'BLE' + : 'CLASSIC'; - const badges = []; - if (device.is_new) badges.push('New'); - if (device.is_persistent) badges.push('Persistent'); - if (device.is_beacon_like) badges.push('Beacon-like'); + const flags = device.heuristic_flags || []; + let badgesHtml = ''; + if (flags.includes('random_address')) { + badgesHtml += 'RANDOM'; + } + if (flags.includes('persistent')) { + badgesHtml += 'PERSISTENT'; + } - const rssiColor = getRssiColor(device.rssi_current); + const name = escapeHtml(device.name || device.device_id || 'Unknown'); + const addr = escapeHtml(device.address || 'Unknown'); + const addrType = escapeHtml(device.address_type || 'unknown'); + const rssi = device.rssi_current; + const rssiStr = (rssi !== null && rssi !== undefined) ? rssi + ' dBm' : '--'; + const rssiColor = getRssiColor(rssi); + const mfr = device.manufacturer_name ? escapeHtml(device.manufacturer_name) : ''; + const seenCount = device.seen_count || 0; + const rangeBand = device.range_band || 'unknown'; + const inBaseline = device.in_baseline || false; - return ` -