feat: 初始化 Timeline 桌面客户端基础框架
添加 Electron 应用基础结构,包括: - package.json 配置文件 - 主进程和预加载脚本 - README 文档 - 自动更新功能 - 系统托盘和菜单 - IPC 通信机制
This commit is contained in:
300
README.md
Normal file
300
README.md
Normal file
@@ -0,0 +1,300 @@
|
||||
# Timeline 桌面客户端
|
||||
|
||||
> 记录生活中的每一个精彩时刻 - 桌面端应用
|
||||
|
||||
## 📖 项目简介
|
||||
|
||||
Timeline 桌面客户端是基于 Electron 构建的跨平台桌面应用,支持 Windows、macOS 和 Linux 系统。提供完整的离线支持、自动更新、系统托盘等功能。
|
||||
|
||||
## 🛠️ 技术栈
|
||||
|
||||
| 技术 | 版本 | 说明 |
|
||||
|-----|------|------|
|
||||
| Electron | 28.x | 跨平台桌面应用框架 |
|
||||
| Electron Vite | 2.x | Electron 构建工具 |
|
||||
| TypeScript | 5.x | 类型安全 |
|
||||
| Electron Builder | 24.x | 打包与分发 |
|
||||
| Electron Updater | 6.x | 自动更新 |
|
||||
|
||||
## 📁 项目结构
|
||||
|
||||
```
|
||||
timeline-desktop/
|
||||
├── src/
|
||||
│ ├── main/ # 主进程代码
|
||||
│ │ ├── main.ts # 主进程入口
|
||||
│ │ └── preload.ts # Preload 脚本
|
||||
│ └── renderer/ # 渲染进程(可选)
|
||||
├── build/ # 构建资源
|
||||
│ ├── icon.ico # Windows 图标
|
||||
│ ├── icon.icns # macOS 图标
|
||||
│ └── icon.png # Linux 图标
|
||||
├── release/ # 打包输出目录
|
||||
├── package.json
|
||||
├── electron.vite.config.ts # Vite 配置
|
||||
└── tsconfig.json
|
||||
```
|
||||
|
||||
## 🚀 快速开始
|
||||
|
||||
### 环境要求
|
||||
|
||||
- Node.js >= 18.x
|
||||
- npm >= 9.x 或 pnpm >= 8.x
|
||||
|
||||
### 安装依赖
|
||||
|
||||
```bash
|
||||
# 使用 npm
|
||||
npm install
|
||||
|
||||
# 或使用 pnpm
|
||||
pnpm install
|
||||
```
|
||||
|
||||
### 开发模式
|
||||
|
||||
```bash
|
||||
# 启动开发服务器
|
||||
npm run dev
|
||||
```
|
||||
|
||||
开发模式下,应用会自动加载 `http://localhost:8080`(Web 前端开发服务器)。
|
||||
|
||||
### 构建打包
|
||||
|
||||
```bash
|
||||
# 构建所有平台
|
||||
npm run build
|
||||
npm run dist
|
||||
|
||||
# 仅构建 Windows
|
||||
npm run dist:win
|
||||
|
||||
# 仅构建 macOS
|
||||
npm run dist:mac
|
||||
|
||||
# 仅构建 Linux
|
||||
npm run dist:linux
|
||||
```
|
||||
|
||||
## 📦 打包输出
|
||||
|
||||
打包完成后,安装包位于 `release/` 目录:
|
||||
|
||||
```
|
||||
release/
|
||||
├── win-unpacked/ # Windows 免安装版
|
||||
├── Timeline Setup 1.0.0.exe # Windows 安装包
|
||||
├── Timeline-1.0.0.dmg # macOS 安装包
|
||||
├── Timeline-1.0.0.AppImage # Linux AppImage
|
||||
└── timeline-desktop_1.0.0_amd64.deb # Linux DEB 包
|
||||
```
|
||||
|
||||
## ⚙️ 配置说明
|
||||
|
||||
### 应用配置 (package.json)
|
||||
|
||||
```json
|
||||
{
|
||||
"build": {
|
||||
"appId": "com.timeline.desktop",
|
||||
"productName": "Timeline",
|
||||
"directories": {
|
||||
"output": "release"
|
||||
},
|
||||
"win": {
|
||||
"icon": "build/icon.ico",
|
||||
"target": ["nsis"]
|
||||
},
|
||||
"mac": {
|
||||
"icon": "build/icon.icns",
|
||||
"target": ["dmg", "zip"]
|
||||
},
|
||||
"linux": {
|
||||
"icon": "build/icon.png",
|
||||
"target": ["AppImage", "deb"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 环境变量
|
||||
|
||||
| 变量名 | 说明 | 默认值 |
|
||||
|-------|------|-------|
|
||||
| NODE_ENV | 运行环境 | development |
|
||||
| API_URL | API 地址 | https://api.timeline.com |
|
||||
|
||||
## 🔄 自动更新
|
||||
|
||||
### 配置自动更新
|
||||
|
||||
1. 在 `package.json` 中配置发布地址:
|
||||
|
||||
```json
|
||||
{
|
||||
"build": {
|
||||
"publish": {
|
||||
"provider": "github",
|
||||
"owner": "your-github-username",
|
||||
"repo": "timeline-desktop"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
2. 在 GitHub 创建 Release 并上传安装包
|
||||
|
||||
3. 应用启动时会自动检查更新
|
||||
|
||||
### 更新流程
|
||||
|
||||
```
|
||||
应用启动 → 检查更新 → 发现新版本 → 提示用户 → 下载更新 → 安装更新
|
||||
```
|
||||
|
||||
## 🔌 IPC 通信 API
|
||||
|
||||
### 渲染进程可用 API
|
||||
|
||||
```typescript
|
||||
// 获取应用版本
|
||||
const version = await window.electronAPI.getVersion();
|
||||
|
||||
// 获取操作系统平台
|
||||
const platform = await window.electronAPI.getPlatform();
|
||||
|
||||
// 检查更新
|
||||
const updateInfo = await window.electronAPI.checkUpdate();
|
||||
|
||||
// 下载更新
|
||||
await window.electronAPI.downloadUpdate();
|
||||
|
||||
// 安装更新
|
||||
await window.electronAPI.installUpdate();
|
||||
|
||||
// 打开外部链接
|
||||
await window.electronAPI.openExternal('https://timeline.com');
|
||||
|
||||
// 监听更新事件
|
||||
window.electronAPI.onUpdateAvailable((info) => {
|
||||
console.log('发现新版本:', info.version);
|
||||
});
|
||||
|
||||
window.electronAPI.onUpdateDownloaded((info) => {
|
||||
console.log('更新已下载:', info.version);
|
||||
});
|
||||
```
|
||||
|
||||
## 🖥️ 功能特性
|
||||
|
||||
### 系统托盘
|
||||
|
||||
- 最小化到托盘
|
||||
- 托盘菜单快捷操作
|
||||
- 点击托盘图标显示窗口
|
||||
|
||||
### 应用菜单
|
||||
|
||||
- 文件操作
|
||||
- 编辑功能(撤销/重做/复制/粘贴)
|
||||
- 视图控制(缩放/全屏)
|
||||
- 帮助链接
|
||||
|
||||
### 安全特性
|
||||
|
||||
- Context Isolation 启用
|
||||
- Node Integration 禁用
|
||||
- 安全的 Preload 脚本
|
||||
|
||||
## 🔐 签名与公证
|
||||
|
||||
### Windows 代码签名
|
||||
|
||||
```bash
|
||||
# 设置环境变量
|
||||
set CSC_LINK=path/to/certificate.pfx
|
||||
set CSC_KEY_PASSWORD=your-password
|
||||
|
||||
# 打包时自动签名
|
||||
npm run dist:win
|
||||
```
|
||||
|
||||
### macOS 公证
|
||||
|
||||
```bash
|
||||
# 设置环境变量
|
||||
set APPLE_ID=your-apple-id
|
||||
set APPLE_ID_PASSWORD=app-specific-password
|
||||
set APPLE_TEAM_ID=your-team-id
|
||||
|
||||
# 打包并公证
|
||||
npm run dist:mac
|
||||
```
|
||||
|
||||
## 📋 后续拓展计划
|
||||
|
||||
### 短期计划 (1-2 个月)
|
||||
|
||||
| 功能 | 描述 | 优先级 |
|
||||
|-----|------|-------|
|
||||
| 离线模式 | 支持离线浏览和编辑 | P0 |
|
||||
| 本地存储 | 数据本地缓存 | P0 |
|
||||
| 快捷键 | 全局快捷键支持 | P1 |
|
||||
| 多窗口 | 支持多窗口操作 | P1 |
|
||||
| 深色模式 | 跟随系统深色模式 | P2 |
|
||||
|
||||
### 中期计划 (3-6 个月)
|
||||
|
||||
| 功能 | 描述 | 优先级 |
|
||||
|-----|------|-------|
|
||||
| 批量导入 | 批量导入本地照片/视频 | P1 |
|
||||
| 本地备份 | 数据本地备份与恢复 | P1 |
|
||||
| 剪贴板监听 | 自动识别剪贴板图片 | P2 |
|
||||
| 文件拖放 | 拖放文件快速上传 | P2 |
|
||||
| 系统通知 | 原生系统通知 | P2 |
|
||||
|
||||
### 长期计划 (6-12 个月)
|
||||
|
||||
| 功能 | 描述 | 优先级 |
|
||||
|-----|------|-------|
|
||||
| 插件系统 | 支持第三方插件 | P2 |
|
||||
| 主题定制 | 自定义主题和样式 | P3 |
|
||||
| 多语言 | 国际化支持 | P3 |
|
||||
| 云同步 | 数据云同步 | P3 |
|
||||
|
||||
## 🐛 常见问题
|
||||
|
||||
### Q: 开发模式下白屏?
|
||||
|
||||
检查 Web 前端开发服务器是否启动:
|
||||
|
||||
```bash
|
||||
cd ../timeline-frontend
|
||||
pnpm dev
|
||||
```
|
||||
|
||||
### Q: 打包后应用无法启动?
|
||||
|
||||
检查 `main.ts` 中的资源路径是否正确:
|
||||
|
||||
```typescript
|
||||
// 生产环境应使用打包后的路径
|
||||
mainWindow.loadFile(path.join(__dirname, '../renderer/index.html'));
|
||||
```
|
||||
|
||||
### Q: 自动更新不生效?
|
||||
|
||||
1. 检查 `publish` 配置是否正确
|
||||
2. 确保 GitHub Release 已发布
|
||||
3. 检查网络连接
|
||||
|
||||
## 📞 技术支持
|
||||
|
||||
- 问题反馈: https://github.com/timeline/timeline-desktop/issues
|
||||
- 文档地址: https://docs.timeline.com/desktop
|
||||
|
||||
## 📄 许可证
|
||||
|
||||
MIT License
|
||||
72
package.json
Normal file
72
package.json
Normal file
@@ -0,0 +1,72 @@
|
||||
{
|
||||
"name": "timeline-desktop",
|
||||
"version": "1.0.0",
|
||||
"description": "Timeline 桌面客户端 - 记录生活中的每一个精彩时刻",
|
||||
"main": "dist/main.js",
|
||||
"author": "Timeline Team",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"dev": "electron-vite dev",
|
||||
"build": "electron-vite build",
|
||||
"preview": "electron-vite preview",
|
||||
"pack": "electron-builder --dir",
|
||||
"dist": "electron-builder",
|
||||
"dist:win": "electron-builder --win",
|
||||
"dist:mac": "electron-builder --mac",
|
||||
"dist:linux": "electron-builder --linux"
|
||||
},
|
||||
"dependencies": {
|
||||
"electron-updater": "^6.1.7",
|
||||
"electron-store": "^8.1.0",
|
||||
"axios": "^1.6.0",
|
||||
"date-fns": "^3.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"electron": "^28.1.0",
|
||||
"electron-builder": "^24.9.1",
|
||||
"electron-vite": "^2.0.0",
|
||||
"vite": "^5.0.0",
|
||||
"typescript": "^5.3.0",
|
||||
"@types/node": "^20.10.0"
|
||||
},
|
||||
"build": {
|
||||
"appId": "com.timeline.desktop",
|
||||
"productName": "Timeline",
|
||||
"directories": {
|
||||
"output": "release"
|
||||
},
|
||||
"files": [
|
||||
"dist/**/*",
|
||||
"package.json"
|
||||
],
|
||||
"mac": {
|
||||
"category": "public.app-category.lifestyle",
|
||||
"icon": "build/icon.icns",
|
||||
"target": ["dmg", "zip"]
|
||||
},
|
||||
"win": {
|
||||
"icon": "build/icon.ico",
|
||||
"target": [
|
||||
{
|
||||
"target": "nsis",
|
||||
"arch": ["x64", "ia32"]
|
||||
}
|
||||
]
|
||||
},
|
||||
"linux": {
|
||||
"icon": "build/icon.png",
|
||||
"target": ["AppImage", "deb"]
|
||||
},
|
||||
"nsis": {
|
||||
"oneClick": false,
|
||||
"allowToChangeInstallationDirectory": true,
|
||||
"createDesktopShortcut": true,
|
||||
"createStartMenuShortcut": true
|
||||
},
|
||||
"publish": {
|
||||
"provider": "github",
|
||||
"owner": "timeline",
|
||||
"repo": "timeline-desktop"
|
||||
}
|
||||
}
|
||||
}
|
||||
317
src/main/main.ts
Normal file
317
src/main/main.ts
Normal file
@@ -0,0 +1,317 @@
|
||||
/**
|
||||
* Electron 主进程
|
||||
*
|
||||
* 功能描述:
|
||||
* Electron 应用的主进程,负责:
|
||||
* - 创建和管理窗口
|
||||
* - 处理系统菜单
|
||||
* - 自动更新
|
||||
* - IPC 通信
|
||||
*
|
||||
* @author Timeline Team
|
||||
* @date 2024
|
||||
*/
|
||||
|
||||
import { app, BrowserWindow, ipcMain, Menu, Tray, nativeImage, shell } from 'electron';
|
||||
import { autoUpdater } from 'electron-updater';
|
||||
import path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
// 主窗口引用
|
||||
let mainWindow: BrowserWindow | null = null;
|
||||
let tray: Tray | null = null;
|
||||
|
||||
// 是否为开发环境
|
||||
const isDev = process.env.NODE_ENV === 'development' || !app.isPackaged;
|
||||
|
||||
// API 基础地址
|
||||
const API_URL = isDev
|
||||
? 'http://localhost:8080'
|
||||
: 'https://api.timeline.com';
|
||||
|
||||
/**
|
||||
* 创建主窗口
|
||||
*/
|
||||
function createMainWindow(): void {
|
||||
mainWindow = new BrowserWindow({
|
||||
width: 1200,
|
||||
height: 800,
|
||||
minWidth: 800,
|
||||
minHeight: 600,
|
||||
title: 'Timeline',
|
||||
icon: path.join(__dirname, '../build/icon.png'),
|
||||
webPreferences: {
|
||||
nodeIntegration: false,
|
||||
contextIsolation: true,
|
||||
preload: path.join(__dirname, 'preload.js'),
|
||||
webSecurity: true,
|
||||
},
|
||||
frame: true,
|
||||
show: false,
|
||||
backgroundColor: '#ffffff',
|
||||
});
|
||||
|
||||
// 加载应用
|
||||
if (isDev) {
|
||||
mainWindow.loadURL('http://localhost:8000');
|
||||
mainWindow.webContents.openDevTools();
|
||||
} else {
|
||||
mainWindow.loadURL(API_URL);
|
||||
}
|
||||
|
||||
// 窗口准备好后显示
|
||||
mainWindow.once('ready-to-show', () => {
|
||||
mainWindow?.show();
|
||||
});
|
||||
|
||||
// 处理外部链接
|
||||
mainWindow.webContents.setWindowOpenHandler(({ url }) => {
|
||||
shell.openExternal(url);
|
||||
return { action: 'deny' };
|
||||
});
|
||||
|
||||
// 窗口关闭事件
|
||||
mainWindow.on('close', (event) => {
|
||||
if (process.platform === 'darwin') {
|
||||
event.preventDefault();
|
||||
mainWindow?.hide();
|
||||
}
|
||||
});
|
||||
|
||||
mainWindow.on('closed', () => {
|
||||
mainWindow = null;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建系统托盘
|
||||
*/
|
||||
function createTray(): void {
|
||||
const iconPath = path.join(__dirname, '../build/tray.png');
|
||||
const icon = nativeImage.createFromPath(iconPath);
|
||||
|
||||
tray = new Tray(icon.resize({ width: 16, height: 16 }));
|
||||
|
||||
const contextMenu = Menu.buildFromTemplate([
|
||||
{
|
||||
label: '显示主窗口',
|
||||
click: () => {
|
||||
mainWindow?.show();
|
||||
mainWindow?.focus();
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '创建时刻',
|
||||
click: () => {
|
||||
mainWindow?.show();
|
||||
mainWindow?.webContents.send('navigate', '/story/create');
|
||||
}
|
||||
},
|
||||
{ type: 'separator' },
|
||||
{
|
||||
label: '退出',
|
||||
click: () => {
|
||||
app.quit();
|
||||
}
|
||||
}
|
||||
]);
|
||||
|
||||
tray.setToolTip('Timeline');
|
||||
tray.setContextMenu(contextMenu);
|
||||
|
||||
tray.on('click', () => {
|
||||
mainWindow?.show();
|
||||
mainWindow?.focus();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建应用菜单
|
||||
*/
|
||||
function createMenu(): void {
|
||||
const template: Electron.MenuItemConstructorOptions[] = [
|
||||
{
|
||||
label: 'Timeline',
|
||||
submenu: [
|
||||
{ role: 'about' as const, label: '关于 Timeline' },
|
||||
{ type: 'separator' },
|
||||
{
|
||||
label: '偏好设置',
|
||||
accelerator: 'CmdOrCtrl+,',
|
||||
click: () => {
|
||||
mainWindow?.webContents.send('navigate', '/settings');
|
||||
}
|
||||
},
|
||||
{ type: 'separator' },
|
||||
{ role: 'quit' as const, label: '退出' }
|
||||
]
|
||||
},
|
||||
{
|
||||
label: '编辑',
|
||||
submenu: [
|
||||
{ role: 'undo' as const, label: '撤销' },
|
||||
{ role: 'redo' as const, label: '重做' },
|
||||
{ type: 'separator' },
|
||||
{ role: 'cut' as const, label: '剪切' },
|
||||
{ role: 'copy' as const, label: '复制' },
|
||||
{ role: 'paste' as const, label: '粘贴' },
|
||||
{ role: 'selectAll' as const, label: '全选' }
|
||||
]
|
||||
},
|
||||
{
|
||||
label: '视图',
|
||||
submenu: [
|
||||
{ role: 'reload' as const, label: '刷新' },
|
||||
{ role: 'forceReload' as const, label: '强制刷新' },
|
||||
{ type: 'separator' },
|
||||
{ role: 'resetZoom' as const, label: '重置缩放' },
|
||||
{ role: 'zoomIn' as const, label: '放大' },
|
||||
{ role: 'zoomOut' as const, label: '缩小' },
|
||||
{ type: 'separator' },
|
||||
{ role: 'togglefullscreen' as const, label: '全屏' }
|
||||
]
|
||||
},
|
||||
{
|
||||
label: '窗口',
|
||||
submenu: [
|
||||
{ role: 'minimize' as const, label: '最小化' },
|
||||
{ role: 'close' as const, label: '关闭' }
|
||||
]
|
||||
},
|
||||
{
|
||||
label: '帮助',
|
||||
submenu: [
|
||||
{
|
||||
label: '查看文档',
|
||||
click: () => shell.openExternal('https://docs.timeline.com')
|
||||
},
|
||||
{
|
||||
label: '反馈问题',
|
||||
click: () => shell.openExternal('https://github.com/timeline/issues')
|
||||
},
|
||||
{ type: 'separator' },
|
||||
{
|
||||
label: '检查更新',
|
||||
click: () => checkForUpdates()
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
// 开发环境添加开发者工具菜单
|
||||
if (isDev) {
|
||||
template[2].submenu?.push(
|
||||
{ type: 'separator' },
|
||||
{ role: 'toggleDevTools' as const, label: '开发者工具' }
|
||||
);
|
||||
}
|
||||
|
||||
const menu = Menu.buildFromTemplate(template);
|
||||
Menu.setApplicationMenu(menu);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查更新
|
||||
*/
|
||||
async function checkForUpdates(): Promise<void> {
|
||||
try {
|
||||
const result = await autoUpdater.checkForUpdates();
|
||||
if (result) {
|
||||
console.log('发现新版本:', result.updateInfo.version);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('检查更新失败:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置自动更新
|
||||
*/
|
||||
function setupAutoUpdater(): void {
|
||||
autoUpdater.autoDownload = false;
|
||||
autoUpdater.autoInstallOnAppQuit = true;
|
||||
|
||||
autoUpdater.on('update-available', (info) => {
|
||||
mainWindow?.webContents.send('update-available', info);
|
||||
});
|
||||
|
||||
autoUpdater.on('update-downloaded', (info) => {
|
||||
mainWindow?.webContents.send('update-downloaded', info);
|
||||
});
|
||||
|
||||
autoUpdater.on('error', (error) => {
|
||||
console.error('更新错误:', error);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置 IPC 通信
|
||||
*/
|
||||
function setupIpc(): void {
|
||||
// 获取应用版本
|
||||
ipcMain.handle('get-version', () => {
|
||||
return app.getVersion();
|
||||
});
|
||||
|
||||
// 获取平台
|
||||
ipcMain.handle('get-platform', () => {
|
||||
return process.platform;
|
||||
});
|
||||
|
||||
// 检查更新
|
||||
ipcMain.handle('check-update', async () => {
|
||||
try {
|
||||
const result = await autoUpdater.checkForUpdates();
|
||||
return result?.updateInfo;
|
||||
} catch (error) {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
// 下载更新
|
||||
ipcMain.handle('download-update', async () => {
|
||||
await autoUpdater.downloadUpdate();
|
||||
});
|
||||
|
||||
// 安装更新
|
||||
ipcMain.handle('install-update', () => {
|
||||
autoUpdater.quitAndInstall();
|
||||
});
|
||||
|
||||
// 打开外部链接
|
||||
ipcMain.handle('open-external', (_, url: string) => {
|
||||
shell.openExternal(url);
|
||||
});
|
||||
}
|
||||
|
||||
// 应用准备就绪
|
||||
app.whenReady().then(() => {
|
||||
createMainWindow();
|
||||
createMenu();
|
||||
createTray();
|
||||
setupAutoUpdater();
|
||||
setupIpc();
|
||||
|
||||
// macOS 激活应用
|
||||
app.on('activate', () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
createMainWindow();
|
||||
} else {
|
||||
mainWindow?.show();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// 所有窗口关闭时退出(Windows/Linux)
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit();
|
||||
}
|
||||
});
|
||||
|
||||
// 应用退出前清理
|
||||
app.on('before-quit', () => {
|
||||
tray?.destroy();
|
||||
});
|
||||
65
src/main/preload.ts
Normal file
65
src/main/preload.ts
Normal file
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* Electron Preload 脚本
|
||||
*
|
||||
* 功能描述:
|
||||
* 在渲染进程中安全地暴露主进程 API。
|
||||
* 使用 contextBridge 确保安全性。
|
||||
*
|
||||
* @author Timeline Team
|
||||
* @date 2024
|
||||
*/
|
||||
|
||||
import { contextBridge, ipcRenderer } from 'electron';
|
||||
|
||||
/**
|
||||
* 暴露给渲染进程的 API
|
||||
*/
|
||||
contextBridge.exposeInMainWorld('electronAPI', {
|
||||
// 应用信息
|
||||
getVersion: () => ipcRenderer.invoke('get-version'),
|
||||
getPlatform: () => ipcRenderer.invoke('get-platform'),
|
||||
|
||||
// 更新相关
|
||||
checkUpdate: () => ipcRenderer.invoke('check-update'),
|
||||
downloadUpdate: () => ipcRenderer.invoke('download-update'),
|
||||
installUpdate: () => ipcRenderer.invoke('install-update'),
|
||||
|
||||
// 更新事件监听
|
||||
onUpdateAvailable: (callback: (info: any) => void) => {
|
||||
ipcRenderer.on('update-available', (_, info) => callback(info));
|
||||
},
|
||||
onUpdateDownloaded: (callback: (info: any) => void) => {
|
||||
ipcRenderer.on('update-downloaded', (_, info) => callback(info));
|
||||
},
|
||||
|
||||
// 外部链接
|
||||
openExternal: (url: string) => ipcRenderer.invoke('open-external', url),
|
||||
|
||||
// 导航事件
|
||||
onNavigate: (callback: (path: string) => void) => {
|
||||
ipcRenderer.on('navigate', (_, path) => callback(path));
|
||||
},
|
||||
|
||||
// 移除监听器
|
||||
removeAllListeners: (channel: string) => {
|
||||
ipcRenderer.removeAllListeners(channel);
|
||||
}
|
||||
});
|
||||
|
||||
// 类型声明
|
||||
declare global {
|
||||
interface Window {
|
||||
electronAPI: {
|
||||
getVersion: () => Promise<string>;
|
||||
getPlatform: () => Promise<string>;
|
||||
checkUpdate: () => Promise<any>;
|
||||
downloadUpdate: () => Promise<void>;
|
||||
installUpdate: () => Promise<void>;
|
||||
onUpdateAvailable: (callback: (info: any) => void) => void;
|
||||
onUpdateDownloaded: (callback: (info: any) => void) => void;
|
||||
openExternal: (url: string) => Promise<void>;
|
||||
onNavigate: (callback: (path: string) => void) => void;
|
||||
removeAllListeners: (channel: string) => void;
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user