First version of Karten App
This commit is contained in:
+99
@@ -0,0 +1,99 @@
|
||||
import "ol/ol.css";
|
||||
import "./style.css";
|
||||
import { registerSW } from "virtual:pwa-register";
|
||||
import { createCacheStorage } from "./adapters/cache-storage";
|
||||
import { createKachelFetch } from "./adapters/kachel-fetch";
|
||||
import { createMarksDb } from "./adapters/marks-db";
|
||||
import { toEtrs, watchStandort } from "./adapters/standort";
|
||||
import { shippedConfig } from "./config";
|
||||
import { openKarte } from "./karte/session";
|
||||
import type { Point, Uebersicht } from "./karte/types";
|
||||
import { mountScreen } from "./ui/screen";
|
||||
|
||||
void main();
|
||||
|
||||
async function main(): Promise<void> {
|
||||
const root = document.querySelector("#app");
|
||||
if (!(root instanceof HTMLElement)) return;
|
||||
|
||||
if (navigator.storage?.persist) void navigator.storage.persist();
|
||||
registerSW({ immediate: true });
|
||||
|
||||
try {
|
||||
const [uebersicht, standort] = await Promise.all([
|
||||
loadUebersicht(),
|
||||
readOpeningStandort(),
|
||||
]);
|
||||
const session = await openKarte({
|
||||
uebersicht,
|
||||
cache: createCacheStorage(),
|
||||
marks: createMarksDb(),
|
||||
kacheln: createKachelFetch(),
|
||||
config: shippedConfig,
|
||||
viewport: {
|
||||
widthPx: window.innerWidth,
|
||||
heightPx: window.innerHeight,
|
||||
},
|
||||
...(standort !== undefined ? { standort } : {}),
|
||||
online: navigator.onLine,
|
||||
appOpen: document.visibilityState === "visible",
|
||||
});
|
||||
|
||||
mountScreen(root, session, uebersicht);
|
||||
bindDevice(session);
|
||||
} catch {
|
||||
root.replaceChildren();
|
||||
const message = document.createElement("p");
|
||||
message.className = "boot-error";
|
||||
message.textContent = "Die Karte konnte nicht geöffnet werden.";
|
||||
root.append(message);
|
||||
}
|
||||
}
|
||||
|
||||
async function loadUebersicht(): Promise<Uebersicht> {
|
||||
const response = await fetch("/uebersicht.json");
|
||||
if (!response.ok) throw new Error("Übersicht fehlt");
|
||||
return (await response.json()) as Uebersicht;
|
||||
}
|
||||
|
||||
function readOpeningStandort(): Promise<Point | "denied" | undefined> {
|
||||
if (!navigator.geolocation) return Promise.resolve("denied");
|
||||
return new Promise((resolve) => {
|
||||
navigator.geolocation.getCurrentPosition(
|
||||
(position) => {
|
||||
resolve(toEtrs(position.coords.longitude, position.coords.latitude));
|
||||
},
|
||||
(error) => {
|
||||
if (error.code === error.TIMEOUT) resolve(undefined);
|
||||
else resolve("denied");
|
||||
},
|
||||
{ maximumAge: 30_000, timeout: 2_000 },
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
function bindDevice(session: Awaited<ReturnType<typeof openKarte>>): void {
|
||||
let stopWatch: (() => void) | null = null;
|
||||
|
||||
const watch = (open: boolean) => {
|
||||
stopWatch?.();
|
||||
stopWatch = null;
|
||||
if (!open) return;
|
||||
stopWatch = watchStandort((standort) => session.reportStandort(standort));
|
||||
};
|
||||
|
||||
document.addEventListener("visibilitychange", () => {
|
||||
const open = document.visibilityState === "visible";
|
||||
if (!open) {
|
||||
watch(false);
|
||||
session.setAppOpen(false);
|
||||
return;
|
||||
}
|
||||
session.setAppOpen(true);
|
||||
watch(true);
|
||||
});
|
||||
|
||||
window.addEventListener("online", () => session.setOnline(true));
|
||||
window.addEventListener("offline", () => session.setOnline(false));
|
||||
watch(document.visibilityState === "visible");
|
||||
}
|
||||
Reference in New Issue
Block a user