feat: implement night mode functionality with UI updates and journey tracking
- Added NightScreen component for displaying night mode information and alerts. - Introduced NextStops component to show upcoming stops during a journey. - Implemented logic for determining night mode activation based on schedule and user settings. - Created journey utility functions to manage onward journey data and stop information. - Updated tests to cover new night mode features and journey logic. - Added fixture for testing night mode scenarios with specific timestamps. - Removed QR code from night screen for a cleaner UI experience. - Enhanced admin settings to manage night mode configurations.
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import type { Config, Settings } from './types';
|
||||
import { isManagedState, MANAGED_KEY } from './lib/device.mjs';
|
||||
import { hydrateManagedState, isManagedState, MANAGED_KEY } from './lib/device.mjs';
|
||||
export type ManagedState = { state: 'paired'; enabled: true; adminUrl: string; config: Config; device: { id: string; name: string; cityId: number; revision: number; settings: Settings } };
|
||||
type Control = { state: string; enabled?: boolean; code?: string; expiresAt?: string; adminUrl?: string };
|
||||
function cached(): ManagedState | null { try { const value = JSON.parse(localStorage.getItem(MANAGED_KEY) || 'null'); return isManagedState(value) ? value : null; } catch { return null; } }
|
||||
function cached(): ManagedState | null { try { const value = hydrateManagedState(JSON.parse(localStorage.getItem(MANAGED_KEY) || 'null')); return isManagedState(value) ? value : null; } catch { return null; } }
|
||||
const info = () => ({ width: innerWidth, height: innerHeight, version: 'board-0.1.0' });
|
||||
export function useDeviceControl() {
|
||||
const [managed, setManaged] = useState<ManagedState | null>(cached), [control, setControl] = useState<Control>({ state: 'loading' });
|
||||
@@ -38,6 +38,7 @@ export function useDeviceControl() {
|
||||
if (['unpaired', 'expired'].includes(value.state)) { if (!stopped) { setManaged(null); applied.current = 0; localStorage.removeItem(MANAGED_KEY); } value = await call('pair', info()); }
|
||||
if (value.state === 'paired' && !value.config) value = await call('status');
|
||||
if (value.state === 'paired') {
|
||||
value = hydrateManagedState(value);
|
||||
if (!isManagedState(value)) throw new Error('invalid_settings');
|
||||
if (!stopped) { setManaged(previous => previous && previous.device.id === value.device.id && previous.device.revision === value.device.revision ? previous : value); setControl(value); setFailed(false); }
|
||||
if (Date.now() - lastHeartbeat >= 30000) { await call('heartbeat', { ...info(), appliedRevision: current.current?.device.id === value.device.id ? applied.current : 0 }); lastHeartbeat = Date.now(); }
|
||||
|
||||
Reference in New Issue
Block a user