feat(desktop): add tray behavior and packaging config
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1 +1,2 @@
|
|||||||
node_modules/
|
node_modules/
|
||||||
|
dist/
|
||||||
|
|||||||
36
README.md
36
README.md
@@ -26,3 +26,39 @@ npm run start:dev
|
|||||||
```bash
|
```bash
|
||||||
npm start
|
npm start
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Build / Release
|
||||||
|
|
||||||
|
先安装依赖(包含 `electron-builder`):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
仅打包目录(不生成安装包):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run pack
|
||||||
|
```
|
||||||
|
|
||||||
|
跨平台构建入口:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run dist
|
||||||
|
```
|
||||||
|
|
||||||
|
按平台构建:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run dist:linux
|
||||||
|
npm run dist:mac
|
||||||
|
npm run dist:win
|
||||||
|
```
|
||||||
|
|
||||||
|
构建产物输出到:
|
||||||
|
|
||||||
|
- `dist/`
|
||||||
|
|
||||||
|
产物命名规范:
|
||||||
|
|
||||||
|
- `Fabric-Desktop-${version}-${os}-${arch}.${ext}`
|
||||||
|
|||||||
78
main.js
78
main.js
@@ -1,4 +1,4 @@
|
|||||||
const { app, BrowserWindow, Menu, ipcMain, Notification, shell } = require('electron')
|
const { app, BrowserWindow, Menu, Tray, ipcMain, Notification, nativeImage, shell } = require('electron')
|
||||||
const fs = require('fs')
|
const fs = require('fs')
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
|
|
||||||
@@ -6,6 +6,10 @@ const isDev = !!process.env.FABRIC_DESKTOP_URL
|
|||||||
const DEFAULT_DEV_URL = 'http://localhost:5173'
|
const DEFAULT_DEV_URL = 'http://localhost:5173'
|
||||||
const DEFAULT_PROD_ENTRY = path.join(__dirname, 'offline.html')
|
const DEFAULT_PROD_ENTRY = path.join(__dirname, 'offline.html')
|
||||||
|
|
||||||
|
let mainWindow = null
|
||||||
|
let tray = null
|
||||||
|
let isQuitting = false
|
||||||
|
|
||||||
function configPath() {
|
function configPath() {
|
||||||
return path.join(app.getPath('userData'), 'fabric-desktop.config.json')
|
return path.join(app.getPath('userData'), 'fabric-desktop.config.json')
|
||||||
}
|
}
|
||||||
@@ -81,11 +85,72 @@ function createWindow() {
|
|||||||
} else {
|
} else {
|
||||||
win.loadFile(DEFAULT_PROD_ENTRY)
|
win.loadFile(DEFAULT_PROD_ENTRY)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
win.on('close', (event) => {
|
||||||
|
if (!isQuitting) {
|
||||||
|
event.preventDefault()
|
||||||
|
win.hide()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return win
|
||||||
|
}
|
||||||
|
|
||||||
|
function createTrayIcon() {
|
||||||
|
if (tray) return tray
|
||||||
|
|
||||||
|
const iconDataUrl =
|
||||||
|
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAAfElEQVR4AWNw4PjPwMDA8J+BgYHhP4MDA8N/BgYGhv8MDAwM/2dgYGB4R2JgYGB4w8DAwPCfgYGB4R8DAwPDf4aGhob/BgwMDAz/Z2BgYHhHYmBgYHjDwMDA8J+BgYHhHwMDA8N/hoYGhv8GDAwMDP9nYGBgeEdiYGAAAB7RImfVq6X8AAAAAElFTkSuQmCC'
|
||||||
|
const icon = nativeImage.createFromDataURL(iconDataUrl)
|
||||||
|
|
||||||
|
tray = new Tray(icon)
|
||||||
|
tray.setToolTip('Fabric Desktop')
|
||||||
|
|
||||||
|
const buildTrayMenu = () =>
|
||||||
|
Menu.buildFromTemplate([
|
||||||
|
{
|
||||||
|
label: mainWindow?.isVisible() ? '隐藏窗口' : '显示窗口',
|
||||||
|
click: () => {
|
||||||
|
if (!mainWindow) {
|
||||||
|
mainWindow = createWindow()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (mainWindow.isVisible()) mainWindow.hide()
|
||||||
|
else {
|
||||||
|
mainWindow.show()
|
||||||
|
mainWindow.focus()
|
||||||
|
}
|
||||||
|
tray.setContextMenu(buildTrayMenu())
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '退出',
|
||||||
|
click: () => {
|
||||||
|
isQuitting = true
|
||||||
|
app.quit()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
tray.setContextMenu(buildTrayMenu())
|
||||||
|
|
||||||
|
tray.on('double-click', () => {
|
||||||
|
if (!mainWindow) {
|
||||||
|
mainWindow = createWindow()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
mainWindow.show()
|
||||||
|
mainWindow.focus()
|
||||||
|
tray.setContextMenu(buildTrayMenu())
|
||||||
|
})
|
||||||
|
|
||||||
|
return tray
|
||||||
}
|
}
|
||||||
|
|
||||||
app.whenReady().then(() => {
|
app.whenReady().then(() => {
|
||||||
createMenu()
|
createMenu()
|
||||||
createWindow()
|
mainWindow = createWindow()
|
||||||
|
createTrayIcon()
|
||||||
|
|
||||||
ipcMain.handle('fabric:config:get', () => readConfig())
|
ipcMain.handle('fabric:config:get', () => readConfig())
|
||||||
ipcMain.handle('fabric:config:set', (_evt, next) => writeConfig(next || {}))
|
ipcMain.handle('fabric:config:set', (_evt, next) => writeConfig(next || {}))
|
||||||
@@ -100,10 +165,15 @@ app.whenReady().then(() => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
app.on('activate', () => {
|
app.on('activate', () => {
|
||||||
if (BrowserWindow.getAllWindows().length === 0) createWindow()
|
if (BrowserWindow.getAllWindows().length === 0) mainWindow = createWindow()
|
||||||
|
else if (mainWindow && !mainWindow.isVisible()) mainWindow.show()
|
||||||
|
})
|
||||||
|
|
||||||
|
app.on('before-quit', () => {
|
||||||
|
isQuitting = true
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
app.on('window-all-closed', () => {
|
app.on('window-all-closed', () => {
|
||||||
if (process.platform !== 'darwin') app.quit()
|
// 保持后台驻留,由托盘控制退出
|
||||||
})
|
})
|
||||||
|
|||||||
3239
package-lock.json
generated
3239
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
53
package.json
53
package.json
@@ -2,12 +2,61 @@
|
|||||||
"name": "fabric-desktop",
|
"name": "fabric-desktop",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
|
"description": "Electron desktop shell for Fabric frontend.",
|
||||||
|
"homepage": "https://github.com/hangman0414/Fabric",
|
||||||
|
"author": {
|
||||||
|
"name": "Hangman",
|
||||||
|
"email": "hangman@example.com"
|
||||||
|
},
|
||||||
"main": "main.js",
|
"main": "main.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "electron .",
|
"start": "electron .",
|
||||||
"start:dev": "FABRIC_DESKTOP_URL=http://localhost:5173 electron ."
|
"start:dev": "FABRIC_DESKTOP_URL=http://localhost:5173 electron .",
|
||||||
|
"pack": "electron-builder --dir",
|
||||||
|
"dist": "electron-builder",
|
||||||
|
"dist:linux": "electron-builder --linux AppImage deb tar.gz",
|
||||||
|
"dist:mac": "electron-builder --mac dmg zip",
|
||||||
|
"dist:win": "electron-builder --win nsis zip"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"electron": "^37.2.1"
|
"electron": "^37.2.1",
|
||||||
|
"electron-builder": "^24.13.3"
|
||||||
|
},
|
||||||
|
"build": {
|
||||||
|
"appId": "ai.hangman.fabric.desktop",
|
||||||
|
"productName": "Fabric Desktop",
|
||||||
|
"artifactName": "Fabric-Desktop-${version}-${os}-${arch}.${ext}",
|
||||||
|
"directories": {
|
||||||
|
"output": "dist"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"main.js",
|
||||||
|
"preload.js",
|
||||||
|
"offline.html",
|
||||||
|
"package.json"
|
||||||
|
],
|
||||||
|
"asar": true,
|
||||||
|
"linux": {
|
||||||
|
"target": [
|
||||||
|
"AppImage",
|
||||||
|
"deb",
|
||||||
|
"tar.gz"
|
||||||
|
],
|
||||||
|
"category": "Utility",
|
||||||
|
"maintainer": "Hangman <hangman@example.com>"
|
||||||
|
},
|
||||||
|
"mac": {
|
||||||
|
"target": [
|
||||||
|
"dmg",
|
||||||
|
"zip"
|
||||||
|
],
|
||||||
|
"category": "public.app-category.productivity"
|
||||||
|
},
|
||||||
|
"win": {
|
||||||
|
"target": [
|
||||||
|
"nsis",
|
||||||
|
"zip"
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user