feat: motd

This commit is contained in:
2026-03-07 16:50:56 +01:00
parent b1dc4835b3
commit c506108ca8
2 changed files with 51 additions and 2 deletions

View File

@@ -12,6 +12,8 @@ for (const line of lines.slice(1)) {
} }
} }
const MOTD = process.env.MOTD || "50;";
export let displaySockets: ServerWebSocket<unknown>[] = []; export let displaySockets: ServerWebSocket<unknown>[] = [];
export async function broadcastDisplayUpdate() { export async function broadcastDisplayUpdate() {
@@ -111,7 +113,7 @@ Bun.serve({
if(!displaySockets.includes(ws)) { if(!displaySockets.includes(ws)) {
displaySockets.push(ws); displaySockets.push(ws);
console.log("Added display socket. Total:", displaySockets.length); console.log("Added display socket. Total:", displaySockets.length);
ws.send(JSON.stringify({ type: "display", tickets: await getDisplayTickets() })); ws.send(JSON.stringify({ type: "display", tickets: await getDisplayTickets(), motd: MOTD }));
} }
} }
}, // a message is received }, // a message is received

View File

@@ -24,6 +24,12 @@
withSound = location.search.includes("sound=true"); withSound = location.search.includes("sound=true");
eventTarget.addEventListener("display", (e) => { eventTarget.addEventListener("display", (e) => {
const detail = (e as CustomEvent).detail; const detail = (e as CustomEvent).detail;
if(detail.motd) {
const [speed, ...text] = detail.motd.split(" ");
marqueeText = text.join(" ");
marqueeSpeed = parseInt(speed);
updateMarqueeSpeed();
}
const _newCalls = detail.tickets.filter( const _newCalls = detail.tickets.filter(
(call: CallEntry) => !calls.find((c) => c.num === call.num) (call: CallEntry) => !calls.find((c) => c.num === call.num)
); );
@@ -48,9 +54,22 @@
); );
}); });
function updateMarqueeSpeed() {
requestAnimationFrame(() => {
const marqueeContent = document.querySelectorAll(".marquee-content") as NodeListOf<HTMLElement>;
const speed = marqueeSpeed; // px per second
const width = marqueeContent[0].offsetWidth;
marqueeContent[0].style.animationDuration = `${width / speed}s`;
marqueeContent[1].style.animationDuration = `${width / speed}s`;
});
}
const ENTRIES: Record<string, number> = { A: 1, B: 2, C: 1, D: 2, E: 1 }; const ENTRIES: Record<string, number> = { A: 1, B: 2, C: 1, D: 2, E: 1 };
const ENTRIES_PER_TABLE = 10; const ENTRIES_PER_TABLE = 10;
let marqueeSpeed = 50;
let marqueeText = $state("");
</script> </script>
{#if newCalls.length > 0} {#if newCalls.length > 0}
@@ -84,6 +103,10 @@
</div> </div>
{/if} {/if}
<div class="marquee">
<div class="marquee-content">{marqueeText}</div>
<div class="marquee-content">{marqueeText}</div>
</div>
<div class="p-4 flex justify-around gap-4 text-5xl"> <div class="p-4 flex justify-around gap-4 text-5xl">
<!-- <h1 class="text-6xl font-bold">Aufruf</h1> --> <!-- <h1 class="text-6xl font-bold">Aufruf</h1> -->
<table class="self-start"> <table class="self-start">
@@ -136,7 +159,7 @@
</table> </table>
<div <div
class="fixed h-full w-1 top-0 left-1/2 -translate-x-1/2 {wsState.closed class="fixed h-full w-1 top-15 left-1/2 -translate-x-1/2 {wsState.closed
? 'bg-red-800' ? 'bg-red-800'
: !wsState.connected : !wsState.connected
? 'bg-amber-800' ? 'bg-amber-800'
@@ -239,4 +262,28 @@
background-color: var(--accent); background-color: var(--accent);
border: 2px solid var(--background); border: 2px solid var(--background);
} }
.marquee {
display: flex;
overflow: hidden;
width: 100vw;
white-space: nowrap;
font-size: 2.5rem;
gap: 4rem;
}
.marquee-content {
animation-iteration-count: infinite;
animation-name: marquee;
animation-timing-function: linear;
}
@keyframes marquee {
from {
transform: translateX(0%);
}
to {
transform: translateX(-100%);
}
}
</style> </style>