mirror of
https://github.com/CharaChorder/DeviceManager.git
synced 2025-12-11 13:26:16 +00:00
165 lines
4.4 KiB
Svelte
165 lines
4.4 KiB
Svelte
<script lang="ts">
|
|
import "$lib/fonts/noto-sans-mono.scss";
|
|
import "$lib/fonts/material-symbols-rounded.scss";
|
|
import "$lib/style/scrollbar.scss";
|
|
import "$lib/style/tippy.scss";
|
|
import "$lib/style/theme.scss";
|
|
import { onDestroy, onMount } from "svelte";
|
|
import {
|
|
applyTheme,
|
|
argbFromHex,
|
|
themeFromSourceColor,
|
|
} from "@material/material-color-utilities";
|
|
import Navigation from "./Navigation.svelte";
|
|
import { canAutoConnect } from "$lib/serial/device";
|
|
import { initSerial } from "$lib/serial/connection";
|
|
import type { LayoutData } from "./$types";
|
|
import { browser } from "$app/environment";
|
|
import BrowserWarning from "./BrowserWarning.svelte";
|
|
import "tippy.js/animations/shift-away.css";
|
|
import "tippy.js/dist/tippy.css";
|
|
import tippy from "tippy.js";
|
|
import { theme, userPreferences } from "$lib/preferences.js";
|
|
import { LL, setLocale } from "../i18n/i18n-svelte";
|
|
import { loadLocale } from "../i18n/i18n-util.sync";
|
|
import { detectLocale } from "../i18n/i18n-util";
|
|
import type { Locales } from "../i18n/i18n-types";
|
|
import Footer from "./Footer.svelte";
|
|
import { osLayout, runLayoutDetection } from "$lib/os-layout.js";
|
|
import PageTransition from "./PageTransition.svelte";
|
|
import { restoreFromFile } from "$lib/backup/backup";
|
|
import { goto } from "$app/navigation";
|
|
import { hotkeys } from "$lib/title";
|
|
|
|
const locale =
|
|
((browser && localStorage.getItem("locale")) as Locales) || detectLocale();
|
|
loadLocale(locale);
|
|
setLocale(locale);
|
|
let stopLayoutDetection: () => void;
|
|
|
|
if (browser) {
|
|
stopLayoutDetection = runLayoutDetection();
|
|
tippy.setDefaultProps({
|
|
animation: "shift-away",
|
|
theme: "surface-variant",
|
|
allowHTML: true,
|
|
duration: 250,
|
|
maxWidth: "none",
|
|
arrow: true,
|
|
});
|
|
}
|
|
|
|
export let data: LayoutData;
|
|
|
|
onMount(async () => {
|
|
theme.subscribe((it) => {
|
|
const theme = themeFromSourceColor(argbFromHex(it.color));
|
|
const dark = it.mode === "dark"; // window.matchMedia("(prefers-color-scheme: dark)").matches
|
|
applyTheme(theme, { target: document.body, dark });
|
|
});
|
|
|
|
if (import.meta.env.TAURI_FAMILY === undefined) {
|
|
const { initPwa } = await import("./pwa-setup");
|
|
webManifestLink = await initPwa();
|
|
}
|
|
|
|
if (browser && $userPreferences.autoConnect && (await canAutoConnect())) {
|
|
await initSerial();
|
|
}
|
|
|
|
if (data.importFile) {
|
|
restoreFromFile(data.importFile);
|
|
const url = new URL(location.href);
|
|
url.searchParams.delete("import");
|
|
await goto(url.href, { replaceState: true });
|
|
}
|
|
});
|
|
|
|
onDestroy(() => {
|
|
stopLayoutDetection?.();
|
|
});
|
|
|
|
let webManifestLink = "";
|
|
|
|
function handleHotkey(event: KeyboardEvent) {
|
|
let key = $osLayout.get(event.code);
|
|
if (!key && event.code === "Escape") key = "esc";
|
|
if (!key && event.code === "ArrowLeft") key = "left";
|
|
if (!key && event.code === "ArrowRight") key = "right";
|
|
if (!key && event.code === "ArrowUp") key = "up";
|
|
if (!key && event.code === "ArrowDown") key = "down";
|
|
|
|
if (!key) return;
|
|
const str = [
|
|
event.ctrlKey ? "ctrl" : undefined,
|
|
event.shiftKey ? "shift" : undefined,
|
|
event.altKey ? "alt" : undefined,
|
|
key,
|
|
]
|
|
.filter((it) => !!it)
|
|
.join("+");
|
|
|
|
const node = hotkeys.get(str);
|
|
if (node) {
|
|
event.preventDefault();
|
|
node.click();
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<svelte:head>
|
|
{@html webManifestLink}
|
|
<title>{$LL.TITLE()}</title>
|
|
<meta name="description" content={$LL.DESCRIPTION()} />
|
|
<meta name="theme-color" content={data.themeColor} />
|
|
</svelte:head>
|
|
|
|
<svelte:window on:keydown={handleHotkey} />
|
|
|
|
<Navigation />
|
|
|
|
<!-- <PickChangesDialog /> -->
|
|
|
|
<PageTransition>
|
|
<slot />
|
|
</PageTransition>
|
|
|
|
<Footer />
|
|
|
|
{#if import.meta.env.TAURI_FAMILY === undefined && browser && !("serial" in navigator)}
|
|
<BrowserWarning />
|
|
{/if}
|
|
|
|
<style lang="scss" global>
|
|
body {
|
|
overflow: hidden;
|
|
display: flex;
|
|
flex-direction: column;
|
|
|
|
width: 100vw;
|
|
height: 100vh;
|
|
margin: 0;
|
|
|
|
font-family: "Noto Sans Mono", monospace;
|
|
color: var(--md-sys-color-on-background);
|
|
|
|
background: var(--md-sys-color-background);
|
|
}
|
|
|
|
main {
|
|
contain: strict;
|
|
display: flex;
|
|
flex-direction: column;
|
|
flex-grow: 1;
|
|
align-items: center;
|
|
padding-inline: 16px;
|
|
}
|
|
|
|
h1 {
|
|
margin-block-start: 0;
|
|
font-size: 4rem;
|
|
font-weight: 700;
|
|
color: var(--md-sys-color-secondary);
|
|
}
|
|
</style>
|