103 lines
3.5 KiB
JavaScript
103 lines
3.5 KiB
JavaScript
/**
|
||
* WijiBoard – Shared UI Utilities
|
||
* web/js/ui.js
|
||
*
|
||
* Exports a UI object with helpers used across all sections.
|
||
* Requires the SPA shell to contain:
|
||
* #ble-status, #ble-label (top-bar BLE indicator)
|
||
* #log-console (global event log)
|
||
* #btn-ble-connect (top-bar connect button)
|
||
*/
|
||
|
||
import BLE from './ble.js';
|
||
|
||
const UI = (() => {
|
||
|
||
// ── Log console ─────────────────────────────────────────────
|
||
function log(message, type = 'info') {
|
||
const console = document.getElementById('log-console');
|
||
if (!console) return;
|
||
|
||
const ts = new Date().toLocaleTimeString('en-US', { hour12: false });
|
||
const entry = document.createElement('span');
|
||
entry.className = `log-entry ${type}`;
|
||
entry.textContent = `[${ts}] ${message}`;
|
||
|
||
const br = document.createElement('br');
|
||
console.appendChild(entry);
|
||
console.appendChild(br);
|
||
console.scrollTop = console.scrollHeight;
|
||
}
|
||
|
||
function clearLog() {
|
||
const el = document.getElementById('log-console');
|
||
if (el) el.innerHTML = '';
|
||
}
|
||
|
||
// ── BLE status indicator (top bar) ──────────────────────────
|
||
function setConnectionStatus(connected, deviceName = null) {
|
||
const statusEl = document.getElementById('ble-status');
|
||
const labelEl = document.getElementById('ble-label');
|
||
const btn = document.getElementById('btn-ble-connect');
|
||
|
||
if (statusEl) statusEl.classList.toggle('connected', connected);
|
||
if (labelEl) labelEl.textContent = connected
|
||
? (deviceName ?? 'Connected')
|
||
: 'Disconnected';
|
||
if (btn) {
|
||
btn.disabled = false;
|
||
const btnText = btn.querySelector('.btn-text');
|
||
if (btnText) {
|
||
btnText.textContent = connected ? 'Disconnect' : 'Connect';
|
||
}
|
||
btn.classList.toggle('btn-danger', connected);
|
||
btn.classList.toggle('btn-primary', !connected);
|
||
}
|
||
}
|
||
|
||
// ── Button loading state ─────────────────────────────────────
|
||
function setButtonLoading(btnId, loading) {
|
||
const btn = document.getElementById(btnId);
|
||
if (!btn) return;
|
||
btn.classList.toggle('loading', loading);
|
||
btn.disabled = loading;
|
||
|
||
// Toggle spinner visibility
|
||
const spinner = btn.querySelector('.spinner');
|
||
if (spinner) spinner.style.display = loading ? 'block' : 'none';
|
||
}
|
||
|
||
// ── Wire BLE events to UI ────────────────────────────────────
|
||
function initBLEListeners() {
|
||
BLE.on('connecting', () => {
|
||
log('Scanning for WijiBoard…', 'info');
|
||
setButtonLoading('btn-ble-connect', true);
|
||
});
|
||
|
||
BLE.on('connected', (name) => {
|
||
setButtonLoading('btn-ble-connect', false);
|
||
setConnectionStatus(true, name);
|
||
log(`Connected to "${name}" [INFO]`, 'success');
|
||
});
|
||
|
||
BLE.on('disconnected', () => {
|
||
setButtonLoading('btn-ble-connect', false);
|
||
setConnectionStatus(false);
|
||
log('BLE connection lost.', 'warn');
|
||
});
|
||
|
||
BLE.on('sent', (cmd) => {
|
||
log(`[SEND] ${cmd}`, 'sent');
|
||
});
|
||
|
||
BLE.on('status', (msg) => {
|
||
// Forward raw status messages to sections that need them
|
||
document.dispatchEvent(new CustomEvent('ble:status', { detail: msg }));
|
||
});
|
||
}
|
||
|
||
return { log, clearLog, setConnectionStatus, setButtonLoading, initBLEListeners };
|
||
})();
|
||
|
||
export default UI;
|