105 lines
2.6 KiB
TypeScript
Executable File
105 lines
2.6 KiB
TypeScript
Executable File
// _app.tsx
|
|
import { define, type PageProps } from "../utils.ts";
|
|
import WelcomeBar from "../islands/WelcomeBar/WelcomeBar.tsx";
|
|
import { createPublicId } from "../helpers.ts";
|
|
import { SessionCookie } from "./auth/callback.ts";
|
|
|
|
export default define.page(async function App(props: PageProps) {
|
|
const {
|
|
Component,
|
|
state,
|
|
url,
|
|
} = props;
|
|
const stateData: SessionCookie = state.data ??
|
|
{
|
|
started_on: 0,
|
|
user_name: "",
|
|
user_id: "",
|
|
role: "",
|
|
user_encrypted: false,
|
|
};
|
|
|
|
const publicId = stateData.user_id
|
|
? await createPublicId(stateData.user_id)
|
|
: "";
|
|
|
|
return (
|
|
<html>
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
<title>Cyber Hybrid Hub</title>
|
|
</head>
|
|
<body>
|
|
<WelcomeBar
|
|
publicId={publicId}
|
|
user_name={stateData.user_name}
|
|
currentRoute={url.pathname}
|
|
isEncrypted={stateData.user_encrypted}
|
|
stateId={state.stateId}
|
|
/>
|
|
<div class="page-offset">
|
|
<Component />
|
|
</div>
|
|
<script
|
|
dangerouslySetInnerHTML={{
|
|
__html: `(function () {
|
|
var KEY = "cyberhybrid-theme-preference";
|
|
var root = document.documentElement;
|
|
|
|
function applyTheme(mode) {
|
|
root.setAttribute("data-theme-mode", mode);
|
|
}
|
|
|
|
function readTheme() {
|
|
try {
|
|
var stored = localStorage.getItem(KEY);
|
|
if (stored === "light" || stored === "dark") return stored;
|
|
} catch (_error) {}
|
|
return "dark";
|
|
}
|
|
|
|
function syncToggleLabels() {
|
|
var isDark = root.getAttribute("data-theme-mode") !== "light";
|
|
var label = isDark ? "Switch to light mode" : "Switch to dark mode";
|
|
var toggles = document.querySelectorAll("[data-theme-toggle]");
|
|
for (var i = 0; i < toggles.length; i++) {
|
|
toggles[i].setAttribute("aria-label", label);
|
|
toggles[i].setAttribute("title", label);
|
|
}
|
|
}
|
|
|
|
function persistTheme(mode) {
|
|
try {
|
|
localStorage.setItem(KEY, mode);
|
|
} catch (_error) {}
|
|
}
|
|
|
|
applyTheme(readTheme());
|
|
syncToggleLabels();
|
|
|
|
document.addEventListener("click", function (event) {
|
|
var target = event.target;
|
|
if (!(target instanceof Element)) return;
|
|
var toggle = target.closest("[data-theme-toggle]");
|
|
if (!toggle) return;
|
|
|
|
event.preventDefault();
|
|
event.stopPropagation();
|
|
|
|
var current = root.getAttribute("data-theme-mode") === "light"
|
|
? "light"
|
|
: "dark";
|
|
var next = current === "dark" ? "light" : "dark";
|
|
applyTheme(next);
|
|
persistTheme(next);
|
|
syncToggleLabels();
|
|
}, true);
|
|
})();`,
|
|
}}
|
|
/>
|
|
</body>
|
|
</html>
|
|
);
|
|
});
|