mirror of https://github.com/djteang/OrangeTV.git
90 lines
2.4 KiB
TypeScript
90 lines
2.4 KiB
TypeScript
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
|
|
'use client';
|
|
|
|
import { Moon, Sun } from 'lucide-react';
|
|
import { usePathname } from '@/client/router';
|
|
import { useTheme } from '@/client/theme-provider';
|
|
import { useEffect, useState } from 'react';
|
|
|
|
import { AppIconButton } from './ui/HeroPrimitives';
|
|
|
|
export function ThemeToggle() {
|
|
const [mounted, setMounted] = useState(false);
|
|
const [isMobile, setIsMobile] = useState(false);
|
|
const { setTheme, resolvedTheme } = useTheme();
|
|
const pathname = usePathname();
|
|
|
|
const setThemeColor = (theme?: string) => {
|
|
const meta = document.querySelector('meta[name="theme-color"]');
|
|
if (!meta) {
|
|
const meta = document.createElement('meta');
|
|
meta.name = 'theme-color';
|
|
meta.content = theme === 'dark' ? '#080707' : '#151212';
|
|
document.head.appendChild(meta);
|
|
} else {
|
|
meta.setAttribute('content', theme === 'dark' ? '#080707' : '#151212');
|
|
}
|
|
};
|
|
|
|
useEffect(() => {
|
|
setMounted(true);
|
|
|
|
const checkMobile = () => {
|
|
setIsMobile(window.innerWidth < 768);
|
|
};
|
|
|
|
checkMobile();
|
|
window.addEventListener('resize', checkMobile);
|
|
|
|
return () => {
|
|
window.removeEventListener('resize', checkMobile);
|
|
};
|
|
}, []);
|
|
|
|
// 监听主题变化和路由变化,确保主题色始终同步
|
|
useEffect(() => {
|
|
if (mounted) {
|
|
setThemeColor(resolvedTheme);
|
|
}
|
|
}, [mounted, resolvedTheme, pathname]);
|
|
|
|
if (!mounted) {
|
|
// 渲染一个占位符以避免布局偏移
|
|
return <div className='w-10 h-10' />;
|
|
}
|
|
|
|
const toggleTheme = () => {
|
|
// 检查浏览器是否支持 View Transitions API
|
|
const targetTheme = resolvedTheme === 'dark' ? 'light' : 'dark';
|
|
setThemeColor(targetTheme);
|
|
if (!(document as any).startViewTransition) {
|
|
setTheme(targetTheme);
|
|
return;
|
|
}
|
|
|
|
(document as any).startViewTransition(() => {
|
|
setTheme(targetTheme);
|
|
});
|
|
};
|
|
|
|
return (
|
|
<>
|
|
<div className={`flex items-center ${isMobile ? 'space-x-1' : 'space-x-2'}`}>
|
|
{/* 主题切换按钮 */}
|
|
<AppIconButton
|
|
onPress={toggleTheme}
|
|
size={isMobile ? 'sm' : 'md'}
|
|
aria-label='Toggle theme'
|
|
>
|
|
{resolvedTheme === 'dark' ? (
|
|
<Sun className='h-5 w-5' />
|
|
) : (
|
|
<Moon className='h-5 w-5' />
|
|
)}
|
|
</AppIconButton>
|
|
</div>
|
|
</>
|
|
);
|
|
}
|