增加插件,自定义座右铭

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 - 🎨 **多主题支持** - 内置 8 种精选主题色
- 🖼️ **Custom Wallpapers** - Support for image and video backgrounds with multiple fit modes - 🖼️ **本地壁纸与离线支持** - **新增 PWA 支持**,首次加载后即可**离线使用**,内置多张精美壁纸
- 🔍 **Multiple Search Engines** - Built-in Google, Baidu, Bing, DuckDuckGo, Bilibili - 🧩 **浏览器插件模式** - 支持打包为 Chrome/Edge 浏览器扩展,完美替代原生新标签页
- **Real-time Clock** - Support for 12/24 hour format with optional seconds display - 🔍 **多搜索引擎** - 内置 Google, 百度, Bing, DuckDuckGo, Bilibili一键切换
- 🎭 **Dynamic Blur** - Background automatically blurs during search for enhanced focus - **实时时钟** - 支持 12/24 小时制及秒针显示,包含座右铭展示
- 💾 **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 - 📱 **响应式设计** - 完美适配各种屏幕尺寸
- 🎬 **流畅动画** - 精心设计的过渡与交互动画
## 🚀 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 ```bash
pnpm install pnpm install
``` ```
### Run Development Server ### 启动开发服务器
```bash ```bash
pnpm dev pnpm dev
``` ```
Visit `http://localhost:3000` to view the application. 访问 `http://localhost:3000` 查看效果。
### Build for Production ### 构建生产版本
```bash ```bash
pnpm build 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 ### 方式一:网页版 (PWA)
- 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
### Wallpaper Settings 您可以直接将部署后的网站(或本地运行的地址)设为浏览器主页。
- Support for image and video backgrounds 得益于 PWA 技术,**只要您访问过一次,网站资源(包括壁纸)就会被缓存在本地**。之后即使在没有网络的情况下,您依然可以正常打开并使用起始页。
- 5 fit modes: Cover, Contain, Fill, Center, Repeat
- Add custom wallpaper URLs
## 🛠️ Tech Stack ### 方式二:浏览器插件 (Chrome Extension)
- **Framework:** React 19 如果您希望每次打开**新标签页 (New Tab)** 都是 AeroStart可以将其作为插件安装
- **Build Tool:** Vite 6
- **Language:** TypeScript
- **Styling:** Tailwind CSS
## 📁 Project Structure
1. 执行构建命令:
```bash
pnpm build
``` ```
AeroStart/ 2. 进入 `dist` 目录,将 `manifest.extension.json` 重命名为 `manifest.json`
├── components/ # React components * Windows (PowerShell): `mv dist/manifest.extension.json dist/manifest.json`
├── Clock.tsx # Clock component * Linux/Mac: `mv dist/manifest.extension.json dist/manifest.json`
│ ├── SearchBox.tsx # Search box component * 或者手动重命名。
├── SettingsModal.tsx # Settings panel * *(注意:如果存在原有的 `manifest.webmanifest` 可以忽略或删除,插件只需要 `manifest.json`)*
│ └── ... 3. 打开 Chrome 或 Edge 浏览器,在地址栏输入 `chrome://extensions` 并回车。
├── utils/ # Utility functions 4. 打开右上角的 **"开发者模式" (Developer mode)** 开关。
├── context/ # React Context 5. 点击左上角的 **"加载已解压的扩展程序" (Load unpacked)**。
├── constants.ts # Constants configuration 6. 选择项目下的 `dist` 文件夹。
├── types.ts # TypeScript type definitions
├── App.tsx # Main application component
└── index.tsx # Application entry point
```
## 📄 License 现在,您的浏览器新标签页就已经变成 AeroStart 了!
## 🎯 使用指南
### 搜索功能
- 在搜索框输入关键词并回车即可搜索
- 点击搜索框左侧图标切换搜索引擎
- 搜索时背景会自动模糊
### 设置面板
- 在背景空白处 **右键点击** 进入仪表盘 (Dashboard) 模式
- 点击右上角的设置图标打开面板
- 可自定义:
- 时钟格式
- 背景壁纸支持本地上传、URL、视频
- 主题颜色
- 搜索框透明度
- 模糊强度
## 🛠️ 技术栈
- **框架:** React 19
- **构建工具:** Vite 6
- **语言:** TypeScript
- **样式:** Tailwind CSS
- **离线支持:** Vite PWA Plugin
## 📄 许可证
Copyright (C) 2025 AeroStart Contributors Copyright (C) 2025 AeroStart Contributors
This program is free software: you can redistribute it and/or modify 本项目基于 GNU General Public License v3.0 开源。
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!

View File

@@ -22,6 +22,7 @@
"postcss": "^8.5.6", "postcss": "^8.5.6",
"tailwindcss": "^4.1.17", "tailwindcss": "^4.1.17",
"typescript": "~5.8.2", "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: [], customWallpapers: [],
enableSearchHistory: true, enableSearchHistory: true,
searchHistory: [], searchHistory: [],
language: 'en' language: 'zh',
motto: '同是天涯沦落人,相逢何必曾相识'
}; };
type ViewMode = 'search' | 'dashboard'; type ViewMode = 'search' | 'dashboard';
@@ -232,6 +233,7 @@ const App: React.FC = () => {
<Clock <Clock
showSeconds={settings.showSeconds} showSeconds={settings.showSeconds}
use24HourFormat={settings.use24HourFormat} use24HourFormat={settings.use24HourFormat}
motto={settings.motto}
/> />
</div> </div>
</ErrorBoundary> </ErrorBoundary>

View File

@@ -4,9 +4,10 @@ import { useTranslation } from '../i18n';
interface ClockProps { interface ClockProps {
showSeconds?: boolean; showSeconds?: boolean;
use24HourFormat?: 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 [time, setTime] = useState(new Date());
const { language } = useTranslation(); const { language } = useTranslation();
@@ -83,8 +84,8 @@ const Clock: React.FC<ClockProps> = ({ showSeconds = true, use24HourFormat = tru
</div> </div>
{/* Motto */} {/* 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>
</div> </div>
); );

View File

@@ -49,6 +49,10 @@ const ThemeSettings: React.FC<ThemeSettingsProps> = ({ settings, onUpdateSetting
onUpdateSettings({ ...settings, language: lang }); onUpdateSettings({ ...settings, language: lang });
}; };
const handleMottoChange = (e: React.ChangeEvent<HTMLInputElement>) => {
onUpdateSettings({ ...settings, motto: e.target.value });
};
return ( return (
<div className="space-y-5"> <div className="space-y-5">
{/* Language Selection */} {/* Language Selection */}
@@ -103,6 +107,18 @@ const ThemeSettings: React.FC<ThemeSettingsProps> = ({ settings, onUpdateSetting
</div> </div>
</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 */} {/* Toggle settings */}
<div className="space-y-3"> <div className="space-y-3">
<div className="flex items-center justify-between"> <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[] = [ export const PRESET_WALLPAPERS: PresetWallpaper[] = [
{ {
name: 'Default', name: 'Bench',
type: 'image', 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', type: 'image',
url: 'https://images.unsplash.com/photo-1464822759023-fed622ff2c3b?auto=format&fit=crop&w=1920&q=80', url: '/wallpapers/people-10019345.jpg',
thumbnail: 'https://images.unsplash.com/photo-1464822759023-fed622ff2c3b?auto=format&fit=crop&w=200&q=60' thumbnail: '/wallpapers/people-10019345.jpg'
},
{
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'
} }
]; ];

View File

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

View File

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

View File

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

View File

@@ -3,6 +3,12 @@ import ReactDOM from 'react-dom/client';
import './index.css'; import './index.css';
import App from './App'; import App from './App';
import { ToastProvider } from './context/ToastContext'; 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'); const rootElement = document.getElementById('root');
if (!rootElement) { if (!rootElement) {

View File

@@ -38,6 +38,7 @@ export interface UserSettings {
enableSearchHistory: boolean; enableSearchHistory: boolean;
searchHistory: string[]; searchHistory: string[];
language: Language; language: Language;
motto: string;
} }
export type SettingsSection = 'general' | 'wallpaper' | 'search'; 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 path from 'path';
import { defineConfig } from 'vite'; import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react'; import react from '@vitejs/plugin-react';
import { VitePWA } from 'vite-plugin-pwa';
export default defineConfig({ export default defineConfig({
server: { 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: { resolve: {
alias: { alias: {
'@': path.resolve(__dirname, './src'), '@': path.resolve(__dirname, './src'),