mirror of
https://github.com/handsomezhuzhu/AeroStart.git
synced 2026-02-20 12:00:15 +00:00
Implement a modern, customizable browser start page with comprehensive features: - Multi-theme support with 8 preset color schemes - Custom wallpaper system supporting images and videos with multiple fit modes - Integrated search functionality with 5 major search engines (Google, Baidu, Bing, DuckDuckGo, Bilibili) - Real-time clock component with 12/24 hour format options - Dynamic background blur effect during search for enhanced focus - Complete i18n system with English and Chinese language support - Responsive design with smooth animations and transitions - Local storage integration for persistent user preferences - Context menu system for quick settings access - Toast notification system for user feedback - Error boundary for robust error handling Tech Stack: - React 19 with TypeScript - Vite 6 for build tooling - Tailwind CSS for styling - Local storage for data persistence Project Structure: - Core components: Clock, SearchBox, SettingsModal, ThemeSettings, WallpaperManager - Utility modules: storage management, search suggestions - Context providers: Toast notifications, i18n - Type definitions and constants configuration 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
187 lines
7.4 KiB
TypeScript
187 lines
7.4 KiB
TypeScript
|
|
import React from 'react';
|
|
import { CheckIcon } from './Icons';
|
|
import { UserSettings, Language } from '../types';
|
|
import { THEMES } from '../constants';
|
|
import { useTranslation } from '../i18n';
|
|
|
|
interface ThemeSettingsProps {
|
|
settings: UserSettings;
|
|
onUpdateSettings: (newSettings: UserSettings) => void;
|
|
}
|
|
|
|
const ThemeSettings: React.FC<ThemeSettingsProps> = ({ settings, onUpdateSettings }) => {
|
|
const { t } = useTranslation();
|
|
|
|
const toggleSeconds = () => {
|
|
onUpdateSettings({ ...settings, showSeconds: !settings.showSeconds });
|
|
};
|
|
|
|
const toggleMaskBlur = () => {
|
|
onUpdateSettings({ ...settings, enableMaskBlur: !settings.enableMaskBlur });
|
|
};
|
|
|
|
const toggle24Hour = () => {
|
|
onUpdateSettings({ ...settings, use24HourFormat: !settings.use24HourFormat });
|
|
};
|
|
|
|
const toggleSearchHistory = () => {
|
|
onUpdateSettings({ ...settings, enableSearchHistory: !settings.enableSearchHistory });
|
|
};
|
|
|
|
const handleBlurChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
onUpdateSettings({ ...settings, backgroundBlur: parseInt(e.target.value) });
|
|
};
|
|
|
|
const handleOpacityChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
onUpdateSettings({ ...settings, searchOpacity: parseFloat(e.target.value) });
|
|
};
|
|
|
|
const handleThemeChange = (colorHex: string) => {
|
|
onUpdateSettings({ ...settings, themeColor: colorHex });
|
|
};
|
|
|
|
const handleLanguageChange = (lang: Language) => {
|
|
onUpdateSettings({ ...settings, language: lang });
|
|
};
|
|
|
|
return (
|
|
<div className="space-y-6">
|
|
{/* Language Selection */}
|
|
<div className="space-y-3">
|
|
<span className="text-white/80 font-light block">{t.language}</span>
|
|
<div className="flex gap-2">
|
|
<button
|
|
onClick={() => handleLanguageChange('en')}
|
|
className={`
|
|
flex-1 px-4 py-2 rounded-lg text-sm font-medium transition-all duration-200
|
|
${settings.language === 'en'
|
|
? 'bg-white text-black'
|
|
: 'bg-white/5 text-white/60 hover:bg-white/10 hover:text-white'}
|
|
`}
|
|
>
|
|
{t.english}
|
|
</button>
|
|
<button
|
|
onClick={() => handleLanguageChange('zh')}
|
|
className={`
|
|
flex-1 px-4 py-2 rounded-lg text-sm font-medium transition-all duration-200
|
|
${settings.language === 'zh'
|
|
? 'bg-white text-black'
|
|
: 'bg-white/5 text-white/60 hover:bg-white/10 hover:text-white'}
|
|
`}
|
|
>
|
|
{t.chinese}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Theme color */}
|
|
<div className="space-y-3">
|
|
<span className="text-white/80 font-light block">{t.themeColor}</span>
|
|
<div className="flex flex-wrap gap-3">
|
|
{THEMES.map((theme) => (
|
|
<button
|
|
key={theme.hex}
|
|
onClick={() => handleThemeChange(theme.hex)}
|
|
className={`
|
|
w-8 h-8 rounded-full flex items-center justify-center transition-all duration-300
|
|
${settings.themeColor === theme.hex ? 'ring-2 ring-white scale-110' : 'hover:scale-110 opacity-80 hover:opacity-100'}
|
|
`}
|
|
style={{ backgroundColor: theme.hex }}
|
|
title={theme.name}
|
|
>
|
|
{settings.themeColor === theme.hex && (
|
|
<CheckIcon className="w-4 h-4 text-white drop-shadow-md" />
|
|
)}
|
|
</button>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
{/* Toggle settings */}
|
|
<div className="space-y-4">
|
|
<div className="flex items-center justify-between">
|
|
<span className="text-white/80 font-light">{t.showSeconds}</span>
|
|
<button
|
|
onClick={toggleSeconds}
|
|
className="w-12 h-6 rounded-full transition-colors duration-300 relative bg-white/10"
|
|
style={{ backgroundColor: settings.showSeconds ? settings.themeColor : undefined }}
|
|
>
|
|
<div className={`absolute top-1 w-4 h-4 rounded-full bg-white transition-transform duration-300 shadow-md ${settings.showSeconds ? 'left-7' : 'left-1'}`} />
|
|
</button>
|
|
</div>
|
|
|
|
<div className="flex items-center justify-between">
|
|
<span className="text-white/80 font-light">{t.use24HourFormat}</span>
|
|
<button
|
|
onClick={toggle24Hour}
|
|
className="w-12 h-6 rounded-full transition-colors duration-300 relative bg-white/10"
|
|
style={{ backgroundColor: settings.use24HourFormat ? settings.themeColor : undefined }}
|
|
>
|
|
<div className={`absolute top-1 w-4 h-4 rounded-full bg-white transition-transform duration-300 shadow-md ${settings.use24HourFormat ? 'left-7' : 'left-1'}`} />
|
|
</button>
|
|
</div>
|
|
|
|
<div className="flex items-center justify-between">
|
|
<span className="text-white/80 font-light">{t.maskBlurEffect}</span>
|
|
<button
|
|
onClick={toggleMaskBlur}
|
|
className="w-12 h-6 rounded-full transition-colors duration-300 relative bg-white/10"
|
|
style={{ backgroundColor: settings.enableMaskBlur ? settings.themeColor : undefined }}
|
|
>
|
|
<div className={`absolute top-1 w-4 h-4 rounded-full bg-white transition-transform duration-300 shadow-md ${settings.enableMaskBlur ? 'left-7' : 'left-1'}`} />
|
|
</button>
|
|
</div>
|
|
|
|
<div className="flex items-center justify-between">
|
|
<span className="text-white/80 font-light">{t.searchHistory}</span>
|
|
<button
|
|
onClick={toggleSearchHistory}
|
|
className="w-12 h-6 rounded-full transition-colors duration-300 relative bg-white/10"
|
|
style={{ backgroundColor: settings.enableSearchHistory ? settings.themeColor : undefined }}
|
|
>
|
|
<div className={`absolute top-1 w-4 h-4 rounded-full bg-white transition-transform duration-300 shadow-md ${settings.enableSearchHistory ? 'left-7' : 'left-1'}`} />
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Background blur slider */}
|
|
<div className="space-y-3">
|
|
<div className="flex justify-between text-sm text-white/60 font-light">
|
|
<span>{t.backgroundBlur}</span>
|
|
<span>{settings.backgroundBlur}px</span>
|
|
</div>
|
|
<input
|
|
type="range"
|
|
min="0"
|
|
max="20"
|
|
step="1"
|
|
value={settings.backgroundBlur}
|
|
onChange={handleBlurChange}
|
|
className="w-full h-1 bg-white/20 rounded-lg appearance-none cursor-pointer [&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:w-4 [&::-webkit-slider-thumb]:h-4 [&::-webkit-slider-thumb]:bg-white [&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:shadow-lg"
|
|
/>
|
|
</div>
|
|
|
|
{/* Search box opacity slider */}
|
|
<div className="space-y-3">
|
|
<div className="flex justify-between text-sm text-white/60 font-light">
|
|
<span>{t.searchBoxOpacity}</span>
|
|
<span>{Math.round(settings.searchOpacity * 100)}%</span>
|
|
</div>
|
|
<input
|
|
type="range"
|
|
min="0.1"
|
|
max="1"
|
|
step="0.05"
|
|
value={settings.searchOpacity}
|
|
onChange={handleOpacityChange}
|
|
className="w-full h-1 bg-white/20 rounded-lg appearance-none cursor-pointer [&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:w-4 [&::-webkit-slider-thumb]:h-4 [&::-webkit-slider-thumb]:bg-white [&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:shadow-lg"
|
|
/>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default ThemeSettings;
|