Make the app an installable PWA with phone layout and Web Push

Add a generated manifest, icon set, offline page and service worker that never caches authenticated HTML, plus install and update UI. Turn the rail into a drawer below md with container-query internals, dvh and safe-area handling, and reconnect the socket after visibility/network changes. Add Web Push subscriptions, presence-aware delivery, notification settings and tests.
This commit is contained in:
2026-10-19 17:12:16 +01:00
parent 61098a114c
commit dbfe48796b
100 changed files with 3573 additions and 117 deletions
+13
View File
@@ -11,6 +11,7 @@ import { wsSendData } from "./(functions)/ws-send-data";
import checkSessionAccess from "./(functions)/check-session-access";
import logEvent from "@/src/functions/backend/logger";
import { computerProxySocket } from "@/src/functions/server/computers/computer-proxy-socket";
import touchUserPresence from "@/src/functions/backend/db/push/touch-user-presence";
/**
* The twui `useWebSocket` hook sends a raw keepalive string to keep the
@@ -34,6 +35,10 @@ export const websocket = {
joinRoom(ws, "public");
if (user.id) {
void touchUserPresence({ user_id: user.id }).catch(() => {});
}
wsSendData({
ws,
data: {
@@ -59,6 +64,14 @@ export const websocket = {
) {
if (ws.data.proxy) return computerProxySocket.message(ws, message);
/**
* Every keepalive counts, including twui's raw ping string, so
* presence stays fresh while the app is open.
*/
if (ws.data.user?.id) {
void touchUserPresence({ user_id: ws.data.user.id }).catch(() => {});
}
const data = parseMessage(message);
if (!data) return;