feat: add multi-user support for favorites management and room clock synchronization

- Implemented a new API endpoint for retrieving and managing user favorites in /api/users.
- Added functionality for admins to edit the shared "main" user's favorites.
- Created a one-shot DB smoke test script for verifying multi-user kiosk migrations.
- Introduced a RoomClock class for synchronizing server time across clients using WebSocket.
This commit is contained in:
Marco Mooren
2026-05-13 13:53:12 +02:00
parent f6cdfd975c
commit 29423288ca
41 changed files with 4229 additions and 275 deletions

View File

@@ -117,11 +117,12 @@ export function ensurePersonalRoom(user) {
export function getRoomState(roomId) {
const row = getDb().prepare('SELECT * FROM room_state WHERE room_id = ?').get(roomId);
if (!row) return { station_id: null, playing: false, volume: 0.7, updated_at: null };
if (!row) return { station_id: null, playing: false, volume: 0.7, started_at: null, updated_at: null };
return {
station_id: row.station_id,
playing: !!row.playing,
volume: row.volume,
started_at: row.started_at ?? null,
updated_at: row.updated_at
};
}
@@ -130,13 +131,14 @@ export function setRoomState(roomId, patch) {
const cur = getRoomState(roomId);
const next = { ...cur, ...patch };
getDb().prepare(`
INSERT INTO room_state (room_id, station_id, playing, volume, updated_at)
VALUES (?, ?, ?, ?, datetime('now'))
INSERT INTO room_state (room_id, station_id, playing, volume, started_at, updated_at)
VALUES (?, ?, ?, ?, ?, datetime('now'))
ON CONFLICT(room_id) DO UPDATE SET
station_id = excluded.station_id,
playing = excluded.playing,
volume = excluded.volume,
started_at = excluded.started_at,
updated_at = excluded.updated_at
`).run(roomId, next.station_id ?? null, next.playing ? 1 : 0, next.volume ?? 0.7);
`).run(roomId, next.station_id ?? null, next.playing ? 1 : 0, next.volume ?? 0.7, next.started_at ?? null);
return getRoomState(roomId);
}