增加插件,自定义座右铭

This commit is contained in:
2025-12-20 22:47:03 +08:00
parent afab936d70
commit a7556418ae
18 changed files with 3078 additions and 122 deletions

146
README.md
View File

@@ -1,113 +1,97 @@
# AeroStart
# AeroStart - 极简浏览器起始页
A modern, customizable browser start page with elegant search experience and personalized settings.
一个现代化、可定制的浏览器起始页,为您提供优雅的搜索体验和个性化设置。支持 PWA 离线使用,亦可作为浏览器插件使用。
## ✨ Features
## ✨ 核心特性
- 🎨 **Multi-Theme Support** - 8 preset theme colors to choose from
- 🖼️ **Custom Wallpapers** - Support for image and video backgrounds with multiple fit modes
- 🔍 **Multiple Search Engines** - Built-in Google, Baidu, Bing, DuckDuckGo, Bilibili
- **Real-time Clock** - Support for 12/24 hour format with optional seconds display
- 🎭 **Dynamic Blur** - Background automatically blurs during search for enhanced focus
- 💾 **Local Storage** - All settings automatically saved to browser local storage
- 📱 **Responsive Design** - Perfect adaptation to all screen sizes
- 🎬 **Smooth Animations** - Carefully designed transitions and interactive animations
- 🎨 **多主题支持** - 内置 8 种精选主题色
- 🖼️ **本地壁纸与离线支持** - **新增 PWA 支持**,首次加载后即可**离线使用**,内置多张精美壁纸
- 🧩 **浏览器插件模式** - 支持打包为 Chrome/Edge 浏览器扩展,完美替代原生新标签页
- 🔍 **多搜索引擎** - 内置 Google, 百度, Bing, DuckDuckGo, Bilibili一键切换
- **实时时钟** - 支持 12/24 小时制及秒针显示,包含座右铭展示
- 🎭 **动态模糊** - 搜索时背景自动模糊,让您更专注于内容
- 💾 **本地存储** - 所有设置自动保存至浏览器本地,无需账号
- 📱 **响应式设计** - 完美适配各种屏幕尺寸
- 🎬 **流畅动画** - 精心设计的过渡与交互动画
## 🚀 Quick Start
## 🚀 快速开始
### Deploy to Vercel
[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https://github.com/yourusername/AeroStart)
Click the button above to deploy your own instance of AeroStart to Vercel in minutes.
### Local Development
**Prerequisites:** Node.js 16+
### Install Dependencies
### 安装依赖
```bash
pnpm install
```
### Run Development Server
### 启动开发服务器
```bash
pnpm dev
```
Visit `http://localhost:3000` to view the application.
访问 `http://localhost:3000` 查看效果。
### Build for Production
### 构建生产版本
```bash
pnpm build
```
## 🎯 Usage Guide
构建产物将输出到 `dist` 目录。
### Search Functionality
- Enter keywords in the search box and press Enter to search
- Click the icon on the left side of the search box to switch search engines
- Background automatically blurs during search to enhance focus
## 📱 如何安装与使用
### Settings Panel
- Right-click the background to enter Dashboard mode
- Click the settings icon in the top right corner to open the settings panel
- Customizable options:
- Clock format (12/24 hour)
- Background wallpaper (preset or custom URL)
- Theme color
- Search box opacity
- Background blur intensity
### 方式一:网页版 (PWA)
### Wallpaper Settings
- Support for image and video backgrounds
- 5 fit modes: Cover, Contain, Fill, Center, Repeat
- Add custom wallpaper URLs
您可以直接将部署后的网站(或本地运行的地址)设为浏览器主页。
得益于 PWA 技术,**只要您访问过一次,网站资源(包括壁纸)就会被缓存在本地**。之后即使在没有网络的情况下,您依然可以正常打开并使用起始页。
## 🛠️ Tech Stack
### 方式二:浏览器插件 (Chrome Extension)
- **Framework:** React 19
- **Build Tool:** Vite 6
- **Language:** TypeScript
- **Styling:** Tailwind CSS
如果您希望每次打开**新标签页 (New Tab)** 都是 AeroStart可以将其作为插件安装
## 📁 Project Structure
1. 执行构建命令:
```bash
pnpm build
```
2. 进入 `dist` 目录,将 `manifest.extension.json` 重命名为 `manifest.json`
* Windows (PowerShell): `mv dist/manifest.extension.json dist/manifest.json`
* Linux/Mac: `mv dist/manifest.extension.json dist/manifest.json`
* 或者手动重命名。
* *(注意:如果存在原有的 `manifest.webmanifest` 可以忽略或删除,插件只需要 `manifest.json`)*
3. 打开 Chrome 或 Edge 浏览器,在地址栏输入 `chrome://extensions` 并回车。
4. 打开右上角的 **"开发者模式" (Developer mode)** 开关。
5. 点击左上角的 **"加载已解压的扩展程序" (Load unpacked)**。
6. 选择项目下的 `dist` 文件夹。
```
AeroStart/
├── components/ # React components
│ ├── Clock.tsx # Clock component
│ ├── SearchBox.tsx # Search box component
│ ├── SettingsModal.tsx # Settings panel
│ └── ...
├── utils/ # Utility functions
├── context/ # React Context
├── constants.ts # Constants configuration
├── types.ts # TypeScript type definitions
├── App.tsx # Main application component
└── index.tsx # Application entry point
```
现在,您的浏览器新标签页就已经变成 AeroStart 了!
## 📄 License
## 🎯 使用指南
### 搜索功能
- 在搜索框输入关键词并回车即可搜索
- 点击搜索框左侧图标切换搜索引擎
- 搜索时背景会自动模糊
### 设置面板
- 在背景空白处 **右键点击** 进入仪表盘 (Dashboard) 模式
- 点击右上角的设置图标打开面板
- 可自定义:
- 时钟格式
- 背景壁纸支持本地上传、URL、视频
- 主题颜色
- 搜索框透明度
- 模糊强度
## 🛠️ 技术栈
- **框架:** React 19
- **构建工具:** Vite 6
- **语言:** TypeScript
- **样式:** Tailwind CSS
- **离线支持:** Vite PWA Plugin
## 📄 许可证
Copyright (C) 2025 AeroStart Contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
## 🤝 Contributing
Issues and Pull Requests are welcome!
本项目基于 GNU General Public License v3.0 开源。

View File

@@ -22,6 +22,7 @@
"postcss": "^8.5.6",
"tailwindcss": "^4.1.17",
"typescript": "~5.8.2",
"vite": "^6.2.0"
"vite": "^6.2.0",
"vite-plugin-pwa": "^1.2.0"
}
}

2942
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

BIN
public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

View File

@@ -0,0 +1,15 @@
{
"manifest_version": 3,
"name": "AeroStart",
"version": "1.0.0",
"description": "极简、高效、美观的新标签页",
"chrome_url_overrides": {
"newtab": "index.html"
},
"permissions": ["storage"],
"icons": {
"16": "favicon.ico",
"48": "favicon.ico",
"128": "favicon.ico"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 MiB

View File

@@ -29,7 +29,8 @@ const DEFAULT_SETTINGS: UserSettings = {
customWallpapers: [],
enableSearchHistory: true,
searchHistory: [],
language: 'en'
language: 'zh',
motto: '同是天涯沦落人,相逢何必曾相识'
};
type ViewMode = 'search' | 'dashboard';
@@ -232,6 +233,7 @@ const App: React.FC = () => {
<Clock
showSeconds={settings.showSeconds}
use24HourFormat={settings.use24HourFormat}
motto={settings.motto}
/>
</div>
</ErrorBoundary>

View File

@@ -4,9 +4,10 @@ import { useTranslation } from '../i18n';
interface ClockProps {
showSeconds?: boolean;
use24HourFormat?: boolean;
motto?: string;
}
const Clock: React.FC<ClockProps> = ({ showSeconds = true, use24HourFormat = true }) => {
const Clock: React.FC<ClockProps> = ({ showSeconds = true, use24HourFormat = true, motto = '同是天涯沦落人,相逢何必曾相识' }) => {
const [time, setTime] = useState(new Date());
const { language } = useTranslation();
@@ -83,8 +84,8 @@ const Clock: React.FC<ClockProps> = ({ showSeconds = true, use24HourFormat = tru
</div>
{/* Motto */}
<div className="mt-4 text-lg md:text-xl font-light text-white/70 tracking-widest uppercase">
<div className="mt-4 text-lg md:text-xl font-light text-white/70 tracking-widest uppercase text-center max-w-2xl">
{motto}
</div>
</div>
);

View File

@@ -49,6 +49,10 @@ const ThemeSettings: React.FC<ThemeSettingsProps> = ({ settings, onUpdateSetting
onUpdateSettings({ ...settings, language: lang });
};
const handleMottoChange = (e: React.ChangeEvent<HTMLInputElement>) => {
onUpdateSettings({ ...settings, motto: e.target.value });
};
return (
<div className="space-y-5">
{/* Language Selection */}
@@ -103,6 +107,18 @@ const ThemeSettings: React.FC<ThemeSettingsProps> = ({ settings, onUpdateSetting
</div>
</div>
{/* Motto Input */}
<div className="space-y-2">
<span className="text-xs font-semibold text-white/50 uppercase tracking-wider block">{t.motto}</span>
<input
type="text"
value={settings.motto || ''}
onChange={handleMottoChange}
className="w-full bg-white/10 border border-white/10 rounded-lg px-3 py-2 text-sm text-white focus:border-white/30 focus:outline-none transition-colors"
placeholder={t.enterMotto}
/>
</div>
{/* Toggle settings */}
<div className="space-y-3">
<div className="flex items-center justify-between">

View File

@@ -16,33 +16,16 @@ export const DEFAULT_BACKGROUND_IMAGE = "https://picsum.photos/1920/1080?graysca
export const PRESET_WALLPAPERS: PresetWallpaper[] = [
{
name: 'Default',
name: 'Bench',
type: 'image',
url: 'https://tc-new.z.wiki/autoupload/f/JPb3wcBYRgvdgjBZlDTRdWSEpzNQ5XwArLwhNo1hcymyl5f0KlZfm6UsKj-HyTuv/20250828/JmPj/3840X2160/light-background.png/webp'
url: '/wallpapers/bench-9964046.jpg',
thumbnail: '/wallpapers/bench-9964046.jpg'
},
{
name: 'Mountains',
name: 'People',
type: 'image',
url: 'https://images.unsplash.com/photo-1464822759023-fed622ff2c3b?auto=format&fit=crop&w=1920&q=80',
thumbnail: 'https://images.unsplash.com/photo-1464822759023-fed622ff2c3b?auto=format&fit=crop&w=200&q=60'
},
{
name: 'Nebula',
type: 'image',
url: 'https://images.unsplash.com/photo-1462331940025-496dfbfc7564?auto=format&fit=crop&w=1920&q=80',
thumbnail: 'https://images.unsplash.com/photo-1462331940025-496dfbfc7564?auto=format&fit=crop&w=200&q=60'
},
{
name: 'City',
type: 'image',
url: 'https://images.unsplash.com/photo-1477959858617-67f85cf4f1df?auto=format&fit=crop&w=1920&q=80',
thumbnail: 'https://images.unsplash.com/photo-1477959858617-67f85cf4f1df?auto=format&fit=crop&w=200&q=60'
},
{
name: 'Rain',
type: 'video',
url: 'https://assets.mixkit.co/videos/preview/mixkit-rain-falling-on-the-window-glass-1634-large.mp4',
thumbnail: 'https://images.unsplash.com/photo-1515694346937-94d85e41e6f0?auto=format&fit=crop&w=200&q=60'
url: '/wallpapers/people-10019345.jpg',
thumbnail: '/wallpapers/people-10019345.jpg'
}
];

View File

@@ -8,6 +8,8 @@ export const en: Translation = {
// Theme Settings
themeColor: 'Theme Color',
motto: 'Motto',
enterMotto: 'Enter your motto...',
showSeconds: 'Show Seconds',
use24HourFormat: '24-Hour Format',
maskBlurEffect: 'Mask Blur Effect',

View File

@@ -8,6 +8,8 @@ export const zh: Translation = {
// Theme Settings
themeColor: '主题颜色',
motto: '座右铭',
enterMotto: '输入您的座右铭...',
showSeconds: '显示秒数',
use24HourFormat: '24小时制',
maskBlurEffect: '遮罩层毛玻璃',

View File

@@ -8,6 +8,8 @@ export interface Translation {
// Theme Settings
themeColor: string;
motto: string;
enterMotto: string;
showSeconds: string;
use24HourFormat: string;
maskBlurEffect: string;

View File

@@ -3,6 +3,12 @@ import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import { ToastProvider } from './context/ToastContext';
import { registerSW } from 'virtual:pwa-register';
// Register PWA Service Worker only if not running as an extension
if (!window.location.protocol.includes('chrome-extension')) {
registerSW({ immediate: true });
}
const rootElement = document.getElementById('root');
if (!rootElement) {

View File

@@ -38,6 +38,7 @@ export interface UserSettings {
enableSearchHistory: boolean;
searchHistory: string[];
language: Language;
motto: string;
}
export type SettingsSection = 'general' | 'wallpaper' | 'search';

2
src/vite-env.d.ts vendored Normal file
View File

@@ -0,0 +1,2 @@
/// <reference types="vite/client" />
/// <reference types="vite-plugin-pwa/client" />

View File

@@ -1,6 +1,7 @@
import path from 'path';
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import { VitePWA } from 'vite-plugin-pwa';
export default defineConfig({
server: {
@@ -15,7 +16,27 @@ export default defineConfig({
}
}
},
plugins: [react()],
plugins: [
react(),
VitePWA({
injectRegister: null,
registerType: 'autoUpdate',
includeAssets: ['favicon.ico', 'apple-touch-icon.png', 'masked-icon.svg', 'wallpapers/*'],
manifest: {
name: 'AeroStart',
short_name: 'AeroStart',
description: 'A beautiful, fast, and customizable start page for your browser.',
theme_color: '#000000',
icons: [
{
src: 'favicon.ico',
sizes: '64x64 32x32 24x24 16x16',
type: 'image/x-icon'
}
]
}
})
],
resolve: {
alias: {
'@': path.resolve(__dirname, './src'),