Initial commit
This commit is contained in:
+111
@@ -0,0 +1,111 @@
|
||||
/**
|
||||
* 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 = connected;
|
||||
btn.innerHTML = connected
|
||||
? '<span class="btn-text">Disconnect</span>'
|
||||
: '<span class="btn-text">Connect</span>';
|
||||
btn.className = connected
|
||||
? 'btn btn-sm btn-danger'
|
||||
: 'btn btn-sm btn-primary';
|
||||
|
||||
// Rebind: when connected, button should disconnect
|
||||
btn.onclick = connected
|
||||
? () => BLE.disconnect()
|
||||
: () => BLE.connect().catch(e => {
|
||||
if (!e.message?.includes('cancelled')) {
|
||||
log(`Connect failed: ${e.message}`, 'error');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// ── 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}" ✓`, 'success');
|
||||
});
|
||||
|
||||
BLE.on('disconnected', () => {
|
||||
setButtonLoading('btn-ble-connect', false);
|
||||
setConnectionStatus(false);
|
||||
log('BLE connection lost.', 'warn');
|
||||
});
|
||||
|
||||
BLE.on('sent', (cmd) => {
|
||||
log(`→ ${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;
|
||||
Reference in New Issue
Block a user