feat: add system theme mode

This commit is contained in:
t8y2
2026-05-13 10:48:34 +08:00
parent 7ce2cf2163
commit b0a808bc14
8 changed files with 159 additions and 27 deletions
+55 -17
View File
@@ -1,25 +1,63 @@
import { ref } from "vue";
import { computed, ref } from "vue";
import {
APP_THEME_STORAGE_KEY,
getTauriThemeForMode,
normalizeAppThemeMode,
resolveAppThemeAppearance,
type AppThemeMode,
} from "@/lib/appTheme";
import { isTauriRuntime } from "@/lib/tauriRuntime";
import type { Theme } from "@tauri-apps/api/window";
const themeMode = ref<AppThemeMode>(
normalizeAppThemeMode(typeof localStorage === "undefined" ? null : localStorage.getItem(APP_THEME_STORAGE_KEY)),
);
const systemPrefersDark = ref(readSystemPrefersDark());
const isDark = computed(() => resolveAppThemeAppearance(themeMode.value, systemPrefersDark.value) === "dark");
let mediaQuery: MediaQueryList | null = null;
let isListeningForSystemTheme = false;
function readSystemPrefersDark() {
if (typeof window === "undefined" || typeof window.matchMedia !== "function") return false;
return window.matchMedia("(prefers-color-scheme: dark)").matches;
}
function setupSystemThemeListener() {
if (isListeningForSystemTheme || typeof window === "undefined" || typeof window.matchMedia !== "function") return;
mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
systemPrefersDark.value = mediaQuery.matches;
const onChange = (event: MediaQueryListEvent) => {
systemPrefersDark.value = event.matches;
if (themeMode.value === "system") applyTheme();
};
mediaQuery.addEventListener("change", onChange);
isListeningForSystemTheme = true;
}
function applyTheme() {
if (typeof document !== "undefined") {
document.documentElement.classList.toggle("dark", isDark.value);
}
if (!isTauriRuntime()) return;
import("@tauri-apps/api/window").then(({ getCurrentWindow }) => {
getCurrentWindow()
.setTheme(getTauriThemeForMode(themeMode.value))
.catch(() => {});
});
}
function setThemeMode(mode: AppThemeMode) {
themeMode.value = mode;
localStorage.setItem(APP_THEME_STORAGE_KEY, mode);
applyTheme();
}
export function useTheme() {
const isDark = ref(localStorage.getItem("dbx-theme") === "dark");
function applyTheme() {
document.documentElement.classList.toggle("dark", isDark.value);
if (!isTauriRuntime()) return;
import("@tauri-apps/api/window").then(({ getCurrentWindow }) => {
getCurrentWindow()
.setTheme(isDark.value ? ("dark" as Theme) : ("light" as Theme))
.catch(() => {});
});
}
setupSystemThemeListener();
function toggleTheme() {
isDark.value = !isDark.value;
localStorage.setItem("dbx-theme", isDark.value ? "dark" : "light");
applyTheme();
setThemeMode(isDark.value ? "light" : "dark");
}
return { isDark, applyTheme, toggleTheme };
return { isDark, themeMode, applyTheme, setThemeMode, toggleTheme };
}