feat: initialize AeroStart browser start page project

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>
This commit is contained in:
ZyphrZero
2025-12-05 02:55:50 +08:00
parent aa197e4e48
commit 56dd6d8bf2
31 changed files with 5270 additions and 0 deletions

122
utils/storage.ts Normal file
View File

@@ -0,0 +1,122 @@
import { UserSettings } from '../types';
const STORAGE_KEY = 'aerostart_settings';
const DEBOUNCE_DELAY = 100; // 100ms debounce delay
// Debounce timer
let debounceTimer: ReturnType<typeof setTimeout> | null = null;
/**
* Load user settings from Local Storage
* @param defaultSettings Default settings
* @returns Merged user settings
*/
export const loadSettings = (defaultSettings: UserSettings): UserSettings => {
try {
const stored = localStorage.getItem(STORAGE_KEY);
if (!stored) {
return defaultSettings;
}
const parsed = JSON.parse(stored);
// Merge default settings with stored settings to ensure new config items have default values
return {
...defaultSettings,
...parsed,
};
} catch (error) {
console.error('Failed to load settings:', error);
return defaultSettings;
}
};
/**
* Calculate data size in bytes
* @param data Data to calculate
* @returns Data size in bytes
*/
const getDataSize = (data: string): number => {
return new Blob([data]).size;
};
/**
* Check localStorage available space
* @param dataSize Data size to store (bytes)
* @returns Whether there is enough space
*/
const checkStorageQuota = (dataSize: number): boolean => {
// localStorage is typically limited to 5-10MB
const QUOTA_LIMIT = 5 * 1024 * 1024; // 5MB safe limit
try {
// Calculate currently used space
let currentSize = 0;
for (let key in localStorage) {
if (localStorage.hasOwnProperty(key)) {
currentSize += getDataSize(localStorage[key] + key);
}
}
return (currentSize + dataSize) < QUOTA_LIMIT;
} catch {
return false;
}
};
/**
* Immediately save user settings to Local Storage (without debounce)
* @param settings User settings
* @throws Error when storage space is insufficient
*/
const saveSettingsImmediate = (settings: UserSettings): void => {
try {
const settingsJson = JSON.stringify(settings);
const dataSize = getDataSize(settingsJson);
// Check storage quota
if (!checkStorageQuota(dataSize)) {
throw new Error('QUOTA_EXCEEDED');
}
localStorage.setItem(STORAGE_KEY, settingsJson);
} catch (error) {
if (error instanceof Error && error.message === 'QUOTA_EXCEEDED') {
console.error('Insufficient storage space, cannot save settings');
throw error;
} else if (error instanceof DOMException && error.name === 'QuotaExceededError') {
console.error('localStorage quota exceeded, cannot save settings');
throw new Error('QUOTA_EXCEEDED');
} else {
console.error('Failed to save settings:', error);
throw error;
}
}
};
/**
* Save user settings to Local Storage (with debounce)
* @param settings User settings
*/
export const saveSettings = (settings: UserSettings): void => {
// Clear previous timer
if (debounceTimer) {
clearTimeout(debounceTimer);
}
// Set new timer
debounceTimer = setTimeout(() => {
saveSettingsImmediate(settings);
debounceTimer = null;
}, DEBOUNCE_DELAY);
};
/**
* Clear all stored settings
*/
export const clearSettings = (): void => {
try {
localStorage.removeItem(STORAGE_KEY);
} catch (error) {
console.error('Failed to clear settings:', error);
}
};