some more stuffs.
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
<script lang="ts" context="module">
|
||||
import { fetchUIState } from "$lib/client/lucifer";
|
||||
import type { IconName } from "$lib/components/DeviceIcon.svelte";
|
||||
import type Device from "$lib/models/device";
|
||||
import type { UIStatePatch } from "$lib/models/uistate";
|
||||
import type UIState from "$lib/models/uistate";
|
||||
@@ -13,6 +14,7 @@
|
||||
state: Readable<UIState>
|
||||
error: Readable<string | null>
|
||||
deviceList: Readable<Device[]>
|
||||
roomList: Readable<{name: string, devices: Device[]}[]>
|
||||
}
|
||||
|
||||
export function getStateContext(): StateContextData {
|
||||
@@ -24,10 +26,12 @@
|
||||
const state = writable<UIState>({
|
||||
assignments: {},
|
||||
devices: {},
|
||||
script: {},
|
||||
scripts: {},
|
||||
});
|
||||
const error = writable<string | null>(null);
|
||||
|
||||
let socket: WebSocket | null = null;
|
||||
|
||||
const deviceList = derived(state, state => {
|
||||
if (state == null) {
|
||||
return [];
|
||||
@@ -35,10 +39,29 @@
|
||||
|
||||
return Object.keys(state.devices)
|
||||
.map(k => state.devices[k])
|
||||
.sort((a,b) => a.id.localeCompare(b.id));
|
||||
})
|
||||
.sort((a,b) => a.name.localeCompare(b.name));
|
||||
});
|
||||
|
||||
const roomList = derived(state, state => {
|
||||
const roomMap: Record<string, Device[]> = {};
|
||||
for (const id in state.devices) {
|
||||
if (!state.devices.hasOwnProperty(id)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const roomAlias = state.devices[id].aliases.find(a => a.startsWith("lucifer:room:"));
|
||||
const roomName = roomAlias?.slice("lucifer:room:".length) || "Unroomed";
|
||||
|
||||
if (!roomMap[roomName]) {
|
||||
roomMap[roomName] = [];
|
||||
}
|
||||
roomMap[roomName].push(state.devices[id]);
|
||||
}
|
||||
|
||||
return Object.keys(roomMap)
|
||||
.map(k => ({ name: k, devices: roomMap[k] }))
|
||||
.sort((a,b) => a.name.localeCompare(b.name));
|
||||
});
|
||||
|
||||
async function reload() {
|
||||
error.set(null);
|
||||
@@ -57,9 +80,9 @@
|
||||
url = import.meta.env.VITE_LUCIFER4_BACKEND_URL.replace("http", "ws") +"/subscribe";
|
||||
}
|
||||
|
||||
const socket = new WebSocket(url);
|
||||
const currSocket = new WebSocket(url);
|
||||
|
||||
socket.onmessage = (msg) => {
|
||||
currSocket.onmessage = (msg) => {
|
||||
const patch: UIStatePatch = JSON.parse(msg.data);
|
||||
|
||||
state.update(s => {
|
||||
@@ -73,10 +96,47 @@
|
||||
...s,
|
||||
devices: {
|
||||
...s.devices,
|
||||
[patch.device.id]: {
|
||||
...s.devices[patch.device.id],
|
||||
...patch.device,
|
||||
}
|
||||
[patch.device.id]: ((patch) => {
|
||||
if (patch.addAlias) {
|
||||
const aliases = [...(s.devices[patch.id].aliases || [])];
|
||||
const exclPrefix = ["lucifer:icon:", "lucifer:group:", "lucifer:name:"].find(p => patch.addAlias?.startsWith(p));
|
||||
const exclExisting = exclPrefix && aliases.find(a => a.startsWith(exclPrefix));
|
||||
|
||||
if (patch.addAlias.startsWith("lucifer:name:")) {
|
||||
patch.name = patch.addAlias.slice("lucifer:name:".length)
|
||||
}
|
||||
if (patch.addAlias.startsWith("lucifer:icon:")) {
|
||||
patch.icon = patch.addAlias.slice("lucifer:icon:".length) as IconName
|
||||
}
|
||||
|
||||
if (exclExisting) {
|
||||
return {
|
||||
...s.devices[patch.id],
|
||||
aliases: [...aliases.filter(a => a != exclExisting), patch.addAlias].sort(),
|
||||
name: patch.name || s.devices[patch.id].name,
|
||||
icon: patch.icon || s.devices[patch.id].icon,
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
...s.devices[patch.id],
|
||||
aliases: [...aliases, patch.addAlias].sort(),
|
||||
name: patch.name || s.devices[patch.id].name,
|
||||
icon: patch.icon || s.devices[patch.id].icon,
|
||||
};
|
||||
}
|
||||
} else if (patch.removeAlias != null) {
|
||||
const aliases = [...(s.devices[patch.id].aliases || [])];
|
||||
return {
|
||||
...s.devices[patch.id],
|
||||
aliases: aliases.filter(a => a !== patch.removeAlias),
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
...s.devices[patch.id],
|
||||
...patch,
|
||||
};
|
||||
}
|
||||
})(patch.device)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -124,14 +184,26 @@
|
||||
})
|
||||
}
|
||||
|
||||
socket.onerror = err => {
|
||||
console.warn("Socket failed:", err);
|
||||
socket.close();
|
||||
currSocket.onopen = () => {
|
||||
if (socket !== null) {
|
||||
socket.close();
|
||||
}
|
||||
|
||||
socket = currSocket;
|
||||
}
|
||||
|
||||
socket.onclose = () => {
|
||||
currSocket.onerror = err => {
|
||||
console.warn("Socket failed:", err);
|
||||
currSocket.close();
|
||||
|
||||
setTimeout(() => connectSocket(), 3000);
|
||||
}
|
||||
|
||||
currSocket.onclose = () => {
|
||||
if (currSocket === socket) {
|
||||
socket = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
@@ -140,6 +212,19 @@
|
||||
|
||||
connectSocket();
|
||||
|
||||
window.addEventListener("visibilitychange", () => {
|
||||
if (document.visibilityState == "visible") {
|
||||
console.log("Reconnecting");
|
||||
reload();
|
||||
connectSocket();
|
||||
} else {
|
||||
if (socket != null) {
|
||||
console.log("Disconnecting")
|
||||
socket.close();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return () => clearInterval(interval);
|
||||
});
|
||||
|
||||
@@ -148,6 +233,7 @@
|
||||
error: { subscribe: error.subscribe },
|
||||
state: { subscribe: state.subscribe },
|
||||
deviceList,
|
||||
roomList,
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user