this repo has no description
1import { api } from "./api";
2
3interface ServerConfigState {
4 serverName: string | null;
5 primaryColor: string | null;
6 primaryColorDark: string | null;
7 secondaryColor: string | null;
8 secondaryColorDark: string | null;
9 hasLogo: boolean;
10 loading: boolean;
11}
12
13const state = $state<ServerConfigState>({
14 serverName: null,
15 primaryColor: null,
16 primaryColorDark: null,
17 secondaryColor: null,
18 secondaryColorDark: null,
19 hasLogo: false,
20 loading: true,
21});
22
23let initialized = false;
24let darkModeQuery: MediaQueryList | null = null;
25
26function isDarkMode(): boolean {
27 return darkModeQuery?.matches ?? false;
28}
29
30function applyColors() {
31 const root = document.documentElement;
32 const dark = isDarkMode();
33
34 if (dark) {
35 if (state.primaryColorDark) {
36 root.style.setProperty("--accent", state.primaryColorDark);
37 } else {
38 root.style.removeProperty("--accent");
39 }
40 if (state.secondaryColorDark) {
41 root.style.setProperty("--secondary", state.secondaryColorDark);
42 } else {
43 root.style.removeProperty("--secondary");
44 }
45 } else {
46 if (state.primaryColor) {
47 root.style.setProperty("--accent", state.primaryColor);
48 } else {
49 root.style.removeProperty("--accent");
50 }
51 if (state.secondaryColor) {
52 root.style.setProperty("--secondary", state.secondaryColor);
53 } else {
54 root.style.removeProperty("--secondary");
55 }
56 }
57}
58
59function setFavicon(hasLogo: boolean) {
60 let link = document.querySelector<HTMLLinkElement>("link[rel~='icon']");
61 if (hasLogo) {
62 if (!link) {
63 link = document.createElement("link");
64 link.rel = "icon";
65 document.head.appendChild(link);
66 }
67 link.href = "/logo";
68 } else if (link) {
69 link.remove();
70 }
71}
72
73export async function initServerConfig(): Promise<void> {
74 if (initialized) return;
75 initialized = true;
76
77 darkModeQuery = globalThis.matchMedia("(prefers-color-scheme: dark)");
78 darkModeQuery.addEventListener("change", applyColors);
79
80 try {
81 const config = await api.getServerConfig();
82 state.serverName = config.serverName;
83 state.primaryColor = config.primaryColor;
84 state.primaryColorDark = config.primaryColorDark;
85 state.secondaryColor = config.secondaryColor;
86 state.secondaryColorDark = config.secondaryColorDark;
87 state.hasLogo = !!config.logoCid;
88 document.title = config.serverName;
89 applyColors();
90 setFavicon(state.hasLogo);
91 } catch {
92 state.serverName = null;
93 } finally {
94 state.loading = false;
95 }
96}
97
98export function getServerConfigState() {
99 return state;
100}
101
102export function setServerName(name: string) {
103 state.serverName = name;
104 document.title = name;
105}
106
107export function setColors(colors: {
108 primaryColor?: string | null;
109 primaryColorDark?: string | null;
110 secondaryColor?: string | null;
111 secondaryColorDark?: string | null;
112}) {
113 if (colors.primaryColor !== undefined) {
114 state.primaryColor = colors.primaryColor;
115 }
116 if (colors.primaryColorDark !== undefined) {
117 state.primaryColorDark = colors.primaryColorDark;
118 }
119 if (colors.secondaryColor !== undefined) {
120 state.secondaryColor = colors.secondaryColor;
121 }
122 if (colors.secondaryColorDark !== undefined) {
123 state.secondaryColorDark = colors.secondaryColorDark;
124 }
125 applyColors();
126}
127
128export function setHasLogo(hasLogo: boolean) {
129 state.hasLogo = hasLogo;
130 setFavicon(hasLogo);
131}