websocket backend + frontend patching.

This commit is contained in:
2023-08-30 22:56:58 +02:00
parent e8b77ae69c
commit 64bb737569
17 changed files with 664 additions and 361 deletions
+100 -3
View File
@@ -1,6 +1,7 @@
<script lang="ts" context="module">
import { fetchUIState } from "$lib/client/lucifer";
import type Device from "$lib/models/device";
import type { UIStatePatch } from "$lib/models/uistate";
import type UIState from "$lib/models/uistate";
import { getContext, onMount, setContext } from "svelte";
import { derived, writable, type Readable } from "svelte/store";
@@ -9,7 +10,7 @@
export interface StateContextData {
reload(): Promise<void>
state: Readable<UIState | null>
state: Readable<UIState>
error: Readable<string | null>
deviceList: Readable<Device[]>
}
@@ -20,7 +21,11 @@
</script>
<script lang="ts">
const state = writable<UIState | null>(null);
const state = writable<UIState>({
assignments: {},
devices: {},
script: {},
});
const error = writable<string | null>(null);
const deviceList = derived(state, state => {
@@ -33,6 +38,8 @@
.sort((a,b) => a.id.localeCompare(b.id));
})
async function reload() {
error.set(null);
@@ -44,7 +51,97 @@
}
}
onMount(() => { reload(); });
async function connectSocket() {
let url = `ws://${window.location.host}/subscribe`;
if (import.meta.env.VITE_LUCIFER4_BACKEND_URL != null) {
url = import.meta.env.VITE_LUCIFER4_BACKEND_URL.replace("http", "ws") +"/subscribe";
}
const socket = new WebSocket(url);
socket.onmessage = (msg) => {
const patch: UIStatePatch = JSON.parse(msg.data);
state.update(s => {
if (patch.device) {
if (patch.device.delete) {
const devices = {...s.devices};
delete devices[patch.device.id];
return {...s, devices};
} else {
return {
...s,
devices: {
...s.devices,
[patch.device.id]: {
...s.devices[patch.device.id],
...patch.device,
}
}
}
}
}
if (patch.assignment) {
if (patch.assignment.delete) {
const assignments = {...s.assignments};
delete assignments[patch.assignment.id];
return {...s, assignments};
} else {
return {
...s,
assignments: {
...s.assignments,
[patch.assignment.id]: {
...s.assignments[patch.assignment.id],
...patch.assignment,
}
}
}
}
}
if (patch.script) {
if (patch.script.delete) {
const scripts = {...s.scripts};
delete scripts[patch.script.id];
return {...s, scripts};
} else {
return {
...s,
scripts: {
...s.scripts,
[patch.script.id]: {
...s.scripts[patch.script.id],
...patch.script,
}
}
}
}
}
return s;
})
}
socket.onerror = err => {
console.warn("Socket failed:", err);
socket.close();
}
socket.onclose = () => {
setTimeout(() => connectSocket(), 3000);
}
}
onMount(() => {
reload();
const interval = setInterval(reload, 60000);
connectSocket();
return () => clearInterval(interval);
});
setContext<StateContextData>(ctxKey, {
reload,