import { Credentials, DoorSaved, SiteConfigModel } from "@/lib/api"; import { Advent22 } from "@/plugins/advent22"; import { RemovableRef, useLocalStorage } from "@vueuse/core"; import { AxiosBasicCredentials } from "axios"; import { acceptHMRUpdate, defineStore } from "pinia"; declare global { interface Navigator { readonly msMaxTouchPoints: number; } } type State = { advent22: Advent22; api_creds: RemovableRef; is_touch_device: boolean; is_admin: boolean; site_config: SiteConfigModel; calendar_aspect_ratio: number; user_doors: DoorSaved[]; next_door_target: number | null; }; export const advent22Store = defineStore({ id: "advent22", state: (): State => ({ advent22: new Advent22(), api_creds: useLocalStorage("advent22/auth", ["", ""]), is_touch_device: window.matchMedia("(any-hover: none)").matches || "ontouchstart" in window || navigator.maxTouchPoints > 0 || navigator.msMaxTouchPoints > 0, is_admin: false, site_config: { title: document.title, subtitle: "", content: "", footer: "", }, calendar_aspect_ratio: 1, user_doors: [], next_door_target: null, }), getters: { axios_creds: (state): AxiosBasicCredentials => { const [username, password] = state.api_creds; return { username: username, password: password }; }, }, actions: { init(): void { this.update_is_admin(); this.advent22 .api_get_blob("user/favicon") .then((favicon_src) => { const link: HTMLLinkElement = document.querySelector("link[rel*='icon']") || document.createElement("link"); link.rel = "shortcut icon"; link.type = "image/x-icon"; link.href = favicon_src; if (link.parentElement === null) document.getElementsByTagName("head")[0].appendChild(link); }) .catch(() => {}); Promise.all([ this.advent22.api_get("user/site_config"), this.advent22.api_get("user/doors"), this.advent22.api_get("user/next_door"), ]) .then(([site_config, user_doors, next_door]) => { document.title = site_config.title; if (site_config.subtitle !== "") document.title += " – " + site_config.subtitle; this.site_config = site_config; this.user_doors = user_doors; if (next_door !== null) this.next_door_target = Date.now() + next_door; }) .catch(this.advent22.alert_user_error); }, update_is_admin(): Promise { return new Promise((resolve, reject) => { this.advent22 .api_get("admin/is_admin") .then((is_admin) => { this.is_admin = is_admin; resolve(is_admin); }) .catch(reject); }); }, login(creds: Credentials): Promise { this.api_creds = creds; return this.update_is_admin(); }, logout(): Promise { return this.login(["", ""]); }, toggle_touch_device(): void { this.is_touch_device = !this.is_touch_device; }, set_calendar_aspect_ratio(rect: DOMRectReadOnly): void { const result = rect.width / rect.height; // filter suspicious results if (result !== 0 && isFinite(result) && !isNaN(result)) this.calendar_aspect_ratio = result; }, }, }); if (import.meta.webpackHot) { import.meta.webpackHot.accept( acceptHMRUpdate(advent22Store, import.meta.webpackHot), ); }