diff --git a/src/hooks/use-verge.ts b/src/hooks/use-verge.ts
index 7385438ad..8750eaaec 100644
--- a/src/hooks/use-verge.ts
+++ b/src/hooks/use-verge.ts
@@ -1,18 +1,15 @@
import useSWR from "swr";
import { getVergeConfig, patchVergeConfig } from "@/services/cmds";
-import {
- getInitialVergeConfig,
- setInitialVergeConfig,
-} from "@/services/preloaded-verge-config";
+import { getPreloadConfig, setPreloadConfig } from "@/services/preload";
export const useVerge = () => {
- const initialVergeConfig = getInitialVergeConfig();
+ const initialVergeConfig = getPreloadConfig();
const { data: verge, mutate: mutateVerge } = useSWR(
"getVergeConfig",
async () => {
const config = await getVergeConfig();
- setInitialVergeConfig(config);
+ setPreloadConfig(config);
return config;
},
{
diff --git a/src/main.tsx b/src/main.tsx
index 5db9a594a..2ef58c97b 100644
--- a/src/main.tsx
+++ b/src/main.tsx
@@ -14,15 +14,12 @@ import { BaseErrorBoundary } from "./components/base";
import { router } from "./pages/_routers";
import { AppDataProvider } from "./providers/app-data-provider";
import { WindowProvider } from "./providers/window";
-import { getVergeConfig } from "./services/cmds";
+import { FALLBACK_LANGUAGE, initializeLanguage } from "./services/i18n";
import {
- FALLBACK_LANGUAGE,
- cacheLanguage,
- getCachedLanguage,
- initializeLanguage,
- resolveLanguage,
-} from "./services/i18n";
-import { setInitialVergeConfig } from "./services/preloaded-verge-config";
+ preloadAppData,
+ resolveThemeMode,
+ getPreloadConfig,
+} from "./services/preload";
import {
LoadingCacheProvider,
ThemeModeProvider,
@@ -56,42 +53,6 @@ document.addEventListener("keydown", (event) => {
}
});
-let cachedVergeConfig: IVergeConfig | null = null;
-
-const detectSystemTheme = (): "light" | "dark" => {
- if (typeof window === "undefined" || typeof window.matchMedia !== "function")
- return "light";
- return window.matchMedia("(prefers-color-scheme: dark)").matches
- ? "dark"
- : "light";
-};
-
-const getInitialThemeModeFromWindow = ():
- | IVergeConfig["theme_mode"]
- | undefined => {
- if (typeof window === "undefined") return undefined;
- const mode = (
- window as typeof window & {
- __VERGE_INITIAL_THEME_MODE?: unknown;
- }
- ).__VERGE_INITIAL_THEME_MODE;
- if (mode === "light" || mode === "dark" || mode === "system") {
- return mode;
- }
- return undefined;
-};
-
-const resolveInitialThemeMode = (
- vergeConfig?: IVergeConfig | null,
-): "light" | "dark" => {
- const initialMode =
- vergeConfig?.theme_mode ?? getInitialThemeModeFromWindow();
- if (initialMode === "dark" || initialMode === "light") {
- return initialMode;
- }
- return detectSystemTheme();
-};
-
const initializeApp = (initialThemeMode: "light" | "dark") => {
const contexts = [
,
@@ -115,80 +76,8 @@ const initializeApp = (initialThemeMode: "light" | "dark") => {
);
};
-const determineInitialLanguage = async (
- vergeConfig?: IVergeConfig | null,
- loadVergeConfig?: () => Promise,
-) => {
- const cachedLanguage = getCachedLanguage();
- if (cachedLanguage) {
- return cachedLanguage;
- }
-
- let resolvedConfig = vergeConfig;
-
- if (resolvedConfig === undefined) {
- if (loadVergeConfig) {
- try {
- resolvedConfig = await loadVergeConfig();
- } catch (error) {
- console.warn(
- "[main.tsx] Failed to read language from Verge config:",
- error,
- );
- resolvedConfig = null;
- }
- } else {
- try {
- resolvedConfig = await getVergeConfig();
- cachedVergeConfig = resolvedConfig;
- } catch (error) {
- console.warn(
- "[main.tsx] Failed to read language from Verge config:",
- error,
- );
- resolvedConfig = null;
- }
- }
- }
-
- const languageFromConfig = resolvedConfig?.language;
- if (languageFromConfig) {
- const resolved = resolveLanguage(languageFromConfig);
- cacheLanguage(resolved);
- return resolved;
- }
-
- const browserLanguage = resolveLanguage(
- typeof navigator !== "undefined" ? navigator.language : undefined,
- );
- cacheLanguage(browserLanguage);
- return browserLanguage;
-};
-
-const fetchVergeConfig = async () => {
- try {
- const config = await getVergeConfig();
- cachedVergeConfig = config;
- setInitialVergeConfig(config);
- return config;
- } catch (error) {
- console.warn("[main.tsx] Failed to read Verge config:", error);
- setInitialVergeConfig(null);
- return null;
- }
-};
-
const bootstrap = async () => {
- const vergeConfigPromise = fetchVergeConfig();
- const initialLanguage = await determineInitialLanguage(
- undefined,
- () => vergeConfigPromise,
- );
- const [vergeConfig] = await Promise.all([
- vergeConfigPromise,
- initializeLanguage(initialLanguage),
- ]);
- const initialThemeMode = resolveInitialThemeMode(vergeConfig);
+ const { initialThemeMode } = await preloadAppData();
initializeApp(initialThemeMode);
};
@@ -205,7 +94,7 @@ bootstrap().catch((error) => {
);
})
.finally(() => {
- initializeApp(resolveInitialThemeMode(cachedVergeConfig));
+ initializeApp(resolveThemeMode(getPreloadConfig()));
});
});
diff --git a/src/services/preload.ts b/src/services/preload.ts
new file mode 100644
index 000000000..daeca5e56
--- /dev/null
+++ b/src/services/preload.ts
@@ -0,0 +1,106 @@
+import { getVergeConfig } from "./cmds";
+import {
+ cacheLanguage,
+ getCachedLanguage,
+ initializeLanguage,
+ resolveLanguage,
+} from "./i18n";
+
+let vergeConfigCache: IVergeConfig | null | undefined;
+
+const detectSystemTheme = (): "light" | "dark" => {
+ if (typeof window === "undefined" || typeof window.matchMedia !== "function")
+ return "light";
+ return window.matchMedia("(prefers-color-scheme: dark)").matches
+ ? "dark"
+ : "light";
+};
+
+const getThemeModeFromWindow = (): IVergeConfig["theme_mode"] | undefined => {
+ if (typeof window === "undefined") return undefined;
+ const mode = (
+ window as typeof window & {
+ __VERGE_INITIAL_THEME_MODE?: unknown;
+ }
+ ).__VERGE_INITIAL_THEME_MODE;
+ if (mode === "light" || mode === "dark" || mode === "system") {
+ return mode;
+ }
+ return undefined;
+};
+
+export const resolveThemeMode = (
+ vergeConfig?: IVergeConfig | null,
+): "light" | "dark" => {
+ const initialMode = vergeConfig?.theme_mode ?? getThemeModeFromWindow();
+ if (initialMode === "dark" || initialMode === "light") {
+ return initialMode;
+ }
+ return detectSystemTheme();
+};
+
+export const setPreloadConfig = (config: IVergeConfig | null) => {
+ vergeConfigCache = config;
+};
+
+export const getPreloadConfig = () => vergeConfigCache;
+
+export const preloadConfig = async () => {
+ try {
+ const config = await getVergeConfig();
+ setPreloadConfig(config);
+ return config;
+ } catch (error) {
+ console.warn("[preload.ts] Failed to read Verge config:", error);
+ setPreloadConfig(null);
+ return null;
+ }
+};
+
+export const preloadLanguage = async (
+ vergeConfig?: IVergeConfig | null,
+ loadConfig: () => Promise = preloadConfig,
+) => {
+ const cachedLanguage = getCachedLanguage();
+ if (cachedLanguage) {
+ return cachedLanguage;
+ }
+
+ let resolvedConfig = vergeConfig;
+
+ if (resolvedConfig === undefined) {
+ try {
+ resolvedConfig = await loadConfig();
+ } catch (error) {
+ console.warn(
+ "[preload.ts] Failed to read language from Verge config:",
+ error,
+ );
+ resolvedConfig = null;
+ }
+ }
+
+ const languageFromConfig = resolvedConfig?.language;
+ if (languageFromConfig) {
+ const resolved = resolveLanguage(languageFromConfig);
+ cacheLanguage(resolved);
+ return resolved;
+ }
+
+ const browserLanguage = resolveLanguage(
+ typeof navigator !== "undefined" ? navigator.language : undefined,
+ );
+ cacheLanguage(browserLanguage);
+ return browserLanguage;
+};
+
+export const preloadAppData = async () => {
+ const configPromise = preloadConfig();
+ const initialLanguage = await preloadLanguage(undefined, () => configPromise);
+ const [config] = await Promise.all([
+ configPromise,
+ initializeLanguage(initialLanguage),
+ ]);
+ const initialThemeMode = resolveThemeMode(config);
+ return { initialThemeMode };
+};
diff --git a/src/services/preloaded-verge-config.ts b/src/services/preloaded-verge-config.ts
deleted file mode 100644
index 96e76070b..000000000
--- a/src/services/preloaded-verge-config.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-let initialVergeConfig: IVergeConfig | null | undefined;
-
-export const setInitialVergeConfig = (config: IVergeConfig | null) => {
- initialVergeConfig = config;
-};
-
-export const getInitialVergeConfig = () => initialVergeConfig;