Feat: Web loader

This commit is contained in:
MangoPig
2026-06-15 06:59:57 +01:00
parent 90de5ca868
commit 99538e30c8
14 changed files with 559 additions and 3 deletions

9
Loader/scripts/config.js Normal file
View File

@@ -0,0 +1,9 @@
// Path: Loader/scripts/config.js
export const LOADER_INTENT_STORAGE_KEY = "moku.loader.intent";
export const LOADER_META_STORAGE_KEY = "moku.loader.meta";
export const LOADER_SEEN_COOKIE_NAME = "moku_loader_seen";
export const LOADER_DEFAULT_INTENT = "/";
export const LOADER_ROOT_PREFIX = "/__loader";
export const LOADER_HANDOFF_DELAY_MS = 720;
export const LOADER_SEEN_COOKIE_MAX_AGE_SECONDS = 1800;

25
Loader/scripts/dom.js Normal file
View File

@@ -0,0 +1,25 @@
// Path: Loader/scripts/dom.js
export const getStatusElement = () => {
return document.getElementById("loader-status");
};
export const getIntentElement = () => {
return document.getElementById("loader-intent");
};
export const setStatus = (value) => {
const statusElement = getStatusElement();
if (statusElement instanceof HTMLElement) {
statusElement.textContent = value;
}
};
export const setIntentPreview = (value) => {
const intentElement = getIntentElement();
if (intentElement instanceof HTMLElement) {
intentElement.textContent = value;
}
};

13
Loader/scripts/handoff.js Normal file
View File

@@ -0,0 +1,13 @@
// Path: Loader/scripts/handoff.js
import { LOADER_HANDOFF_DELAY_MS } from "./config.js";
export const scheduleHandoff = (target, onBeforeHandoff) => {
window.setTimeout(() => {
if (typeof onBeforeHandoff === "function") {
onBeforeHandoff();
}
window.location.assign(target);
}, LOADER_HANDOFF_DELAY_MS);
};

19
Loader/scripts/hints.js Normal file
View File

@@ -0,0 +1,19 @@
// Path: Loader/scripts/hints.js
export const collectClientHints = () => {
const navigatorConnection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;
return {
capturedAt: new Date().toISOString(),
language: navigator.language,
languages: Array.isArray(navigator.languages) ? navigator.languages : [],
hardwareConcurrency: navigator.hardwareConcurrency ?? null,
deviceMemory: navigator.deviceMemory ?? null,
networkType: navigatorConnection?.effectiveType ?? null,
saveData: navigatorConnection?.saveData ?? null,
viewport: {
width: window.innerWidth,
height: window.innerHeight,
},
};
};

32
Loader/scripts/intent.js Normal file
View File

@@ -0,0 +1,32 @@
// Path: Loader/scripts/intent.js
import { LOADER_DEFAULT_INTENT, LOADER_ROOT_PREFIX } from "./config.js";
export const getExplicitIntent = () => {
const params = new URLSearchParams(window.location.search);
const next = params.get("next");
if (typeof next === "string" && next.startsWith("/")) {
return next;
}
return null;
};
export const getCurrentPathIntent = () => {
const current = `${window.location.pathname}${window.location.search}${window.location.hash}`;
if (current === "/" || current === LOADER_ROOT_PREFIX || current === `${LOADER_ROOT_PREFIX}/` || current.startsWith(`${LOADER_ROOT_PREFIX}/`)) {
return LOADER_DEFAULT_INTENT;
}
return current;
};
export const resolveIntent = () => {
return getExplicitIntent() ?? getCurrentPathIntent();
};
export const resolveHandoffTarget = (intent) => {
return intent || LOADER_DEFAULT_INTENT;
};

26
Loader/scripts/main.js Normal file
View File

@@ -0,0 +1,26 @@
// Path: Loader/scripts/main.js
import { setIntentPreview, setStatus } from "./dom.js";
import { scheduleHandoff } from "./handoff.js";
import { resolveHandoffTarget, resolveIntent } from "./intent.js";
import { markLoaderSeen, persistLoaderState } from "./storage.js";
const bootLoader = () => {
const intent = resolveIntent();
const handoffTarget = resolveHandoffTarget(intent);
setStatus("Capturing route intent");
setIntentPreview(intent);
persistLoaderState(intent);
window.setTimeout(() => {
setStatus("Preparing handoff");
}, 180);
scheduleHandoff(handoffTarget, () => {
setStatus("Handing off to application");
markLoaderSeen();
});
};
bootLoader();

24
Loader/scripts/storage.js Normal file
View File

@@ -0,0 +1,24 @@
// Path: Loader/scripts/storage.js
import { LOADER_INTENT_STORAGE_KEY, LOADER_META_STORAGE_KEY, LOADER_SEEN_COOKIE_MAX_AGE_SECONDS, LOADER_SEEN_COOKIE_NAME } from "./config.js";
import { collectClientHints } from "./hints.js";
export const persistLoaderState = (intent) => {
const payload = {
intent,
hints: collectClientHints(),
};
try {
window.sessionStorage.setItem(LOADER_INTENT_STORAGE_KEY, intent);
window.sessionStorage.setItem(LOADER_META_STORAGE_KEY, JSON.stringify(payload));
} catch (error) {
console.warn("[Loader] Unable to persist bootstrap state.", error);
}
return payload;
};
export const markLoaderSeen = () => {
document.cookie = `${LOADER_SEEN_COOKIE_NAME}=1; Path=/; Max-Age=${LOADER_SEEN_COOKIE_MAX_AGE_SECONDS}; SameSite=Lax`;
};