app / src /components /common /ThemeManager.tsx
AZILS's picture
Upload 323 files
a21c316 verified
import { useEffect } from 'react';
import { useConfigStore } from '../../stores/useConfigStore';
import { getCurrentWindow } from '@tauri-apps/api/window';
import { isLinux } from '../../utils/env';
export default function ThemeManager() {
const { config, loadConfig } = useConfigStore();
// Load config on mount
useEffect(() => {
const init = async () => {
await loadConfig();
// Show window after a short delay to ensure React has painted
setTimeout(async () => {
if (typeof window !== 'undefined' && (window as any).__TAURI_INTERNALS__) {
await getCurrentWindow().show();
}
}, 100);
};
init();
}, [loadConfig]);
// Apply theme when config changes
useEffect(() => {
if (!config) return;
const applyTheme = async (theme: string) => {
const root = document.documentElement;
const isDark = theme === 'dark';
// Set Tauri window background color
// Skip on Linux due to crash with transparent windows + softbuffer
try {
if (!isLinux() && (window as any).__TAURI_INTERNALS__) {
const bgColor = isDark ? '#1d232a' : '#FAFBFC';
// Don't await this, let it happen in background to avoid blocking React render
getCurrentWindow().setBackgroundColor(bgColor).catch(e =>
console.error('Failed to set window background color:', e)
);
// Sync Windows title bar theme (for minimize/maximize/close button colors)
const { invoke } = await import('@tauri-apps/api/core');
invoke('set_window_theme', { theme }).catch(() => {
// Ignore errors on non-Windows platforms
});
}
} catch (e) {
console.error('Window background sync failed:', e);
}
// Set DaisyUI theme
root.setAttribute('data-theme', theme);
// Set inline style for immediate visual feedback
root.style.backgroundColor = isDark ? '#1d232a' : '#FAFBFC';
// Set Tailwind dark mode class
if (isDark) {
root.classList.add('dark');
} else {
root.classList.remove('dark');
}
};
const theme = config.theme || 'system';
// Sync to localStorage for early boot check
localStorage.setItem('app-theme-preference', theme);
if (theme === 'system') {
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
const handleSystemChange = (e: MediaQueryListEvent | MediaQueryList) => {
const systemTheme = e.matches ? 'dark' : 'light';
applyTheme(systemTheme);
};
// Initial alignment
handleSystemChange(mediaQuery);
// Listen for changes
mediaQuery.addEventListener('change', handleSystemChange);
return () => mediaQuery.removeEventListener('change', handleSystemChange);
} else {
applyTheme(theme);
}
}, [config?.theme]);
return null; // This component handles side effects only
}