1import "./index.d"
2import type { App } from "./elm/types"
3import { version } from "../../../package.json"
4
5
6// 🏔️
7
8
9let app: App
10let channel: BroadcastChannel
11
12
13
14// 🚀
15
16
17export const load = ({ isNativeWrapper, reg }: { isNativeWrapper: boolean, reg: ServiceWorkerRegistration }) => Elm.UI.init({
18 node: document.getElementById("elm") || undefined,
19 flags: {
20 buildTimestamp: BUILD_TIMESTAMP,
21 darkMode: preferredColorScheme().matches,
22 initialTime: Date.now(),
23 isInstallingServiceWorker: !!reg.installing,
24 isOnline: navigator.onLine,
25 isTauri: isNativeWrapper,
26 version,
27 viewport: {
28 height: window.innerHeight,
29 width: window.innerWidth
30 }
31 }
32})
33
34
35export function init(a: App, c: BroadcastChannel) {
36 app = a
37 channel = c
38
39 app.ports.downloadJsonUsingTauri.subscribe(downloadJsonUsingTauri)
40 app.ports.openUrlOnNewPage.subscribe(openUrlOnNewPage)
41 app.ports.reloadApp.subscribe(reloadApp)
42}
43
44
45
46// 🌗
47
48
49function preferredColorScheme() {
50 const m =
51 window.matchMedia &&
52 window.matchMedia("(prefers-color-scheme: dark)")
53
54 m?.addEventListener("change", e => {
55 app.ports.preferredColorSchemaChanged.send({ dark: e.matches })
56 })
57
58 return m
59}
60
61
62
63// PORTS
64
65
66async function downloadJsonUsingTauri(
67 { filename, json }: { filename: string, json: string }
68) {
69 const { save } = await import("@tauri-apps/plugin-dialog")
70 const { writeTextFile } = await import("@tauri-apps/plugin-fs")
71 const { BaseDirectory } = await import("@tauri-apps/api/path")
72
73 const filePath = await save({ defaultPath: filename })
74 await writeTextFile(filePath || filename, json, { baseDir: BaseDirectory.Download })
75}
76
77
78function openUrlOnNewPage(url: string) {
79 if (globalThis.__TAURI__) {
80 globalThis.__TAURI__.shell.open(
81 url.includes("://") ? url : `${location.origin}/${url.replace(/^\.\//, "")}`
82 )
83
84 } else {
85 window.open(url, "_blank")
86
87 }
88}
89
90
91function reloadApp() {
92 const timeout = setTimeout(async () => {
93 const reg = await navigator.serviceWorker.getRegistration()
94 if (reg?.waiting) reg.waiting.postMessage("skipWaiting")
95 window.location.reload()
96 }, 250)
97
98 channel.addEventListener("message", event => {
99 if (event.data === "PONG") {
100 clearTimeout(timeout)
101 alert("⚠️ You can only update the app when you have no more than one instance open.")
102 }
103 })
104
105 channel.postMessage("PING")
106}