Compare commits

...

6 Commits

Author SHA1 Message Date
mozzie
b46ab5ce9d feat: better-sqlite3 to sovle platform compile 2024-08-14 14:41:50 +08:00
mozzie
5d5879711e feat: update 2024-08-14 13:18:16 +08:00
mozzie
51c32f1f43 feat: change electron-builder 2024-08-14 12:39:03 +08:00
mozzie
b458c72ae9 feat: v 2024-08-14 12:04:47 +08:00
mozzie
900c1c75d4 feat: test 2024-08-14 12:02:08 +08:00
mozzie
6c9ba88a4e feat: test 2024-08-13 17:07:35 +08:00
15 changed files with 188 additions and 753 deletions

1
.npmrc
View File

@ -1,3 +1,4 @@
electron_mirror=https://npmmirror.com/mirrors/electron/ electron_mirror=https://npmmirror.com/mirrors/electron/
electron_builder_binaries_mirror=https://npmmirror.com/mirrors/electron-builder-binaries/ electron_builder_binaries_mirror=https://npmmirror.com/mirrors/electron-builder-binaries/
shamefully-hoist=true shamefully-hoist=true
better_sqlite3_binary_host=https://registry.npmmirror.com/-/binary/better-sqlite3

View File

@ -1,3 +1,3 @@
provider: generic provider: generic
url: https://example.com/auto-updates url: http://192.168.1.7:5500/update
updaterCacheDirName: cvpilot-desktop-updater updaterCacheDirName: cvpilot-desktop-updater

View File

@ -1,4 +1,4 @@
appId: com.electron.app appId: com.tavi.app
productName: cvpilot-desktop productName: cvpilot-desktop
directories: directories:
buildResources: build buildResources: build
@ -40,6 +40,6 @@ appImage:
npmRebuild: false npmRebuild: false
publish: publish:
provider: generic provider: generic
url: https://example.com/auto-updates url: https://assets.maxshader.com
electronDownload: electronDownload:
mirror: https://npmmirror.com/mirrors/electron/ mirror: https://npmmirror.com/mirrors/electron/

View File

@ -1,13 +1,13 @@
import { resolve } from 'path' import { resolve } from 'path'
import { defineConfig, externalizeDepsPlugin } from 'electron-vite' import { defineConfig, externalizeDepsPlugin, bytecodePlugin } from 'electron-vite'
import react from '@vitejs/plugin-react' import react from '@vitejs/plugin-react'
export default defineConfig({ export default defineConfig({
main: { main: {
plugins: [externalizeDepsPlugin()] plugins: [externalizeDepsPlugin(), bytecodePlugin()]
}, },
preload: { preload: {
plugins: [externalizeDepsPlugin()] plugins: [externalizeDepsPlugin(), bytecodePlugin()]
}, },
renderer: { renderer: {
resolve: { resolve: {

View File

@ -1,6 +1,6 @@
{ {
"name": "cvpilot-desktop", "name": "cvpilot-desktop",
"version": "1.0.0", "version": "1.0.5",
"description": "An Electron application with React and TypeScript", "description": "An Electron application with React and TypeScript",
"main": "./out/main/index.js", "main": "./out/main/index.js",
"author": "example.com", "author": "example.com",
@ -12,8 +12,8 @@
"typecheck:web": "tsc --noEmit -p tsconfig.web.json --composite false", "typecheck:web": "tsc --noEmit -p tsconfig.web.json --composite false",
"typecheck": "npm run typecheck:node && npm run typecheck:web", "typecheck": "npm run typecheck:node && npm run typecheck:web",
"start": "electron-vite preview", "start": "electron-vite preview",
"dev": "electron-vite dev", "dev": "electron-vite dev --watch",
"build": "npm run typecheck && electron-vite build", "build": "electron-vite build",
"postinstall": "electron-builder install-app-deps", "postinstall": "electron-builder install-app-deps",
"build:unpack": "npm run build && electron-builder --dir", "build:unpack": "npm run build && electron-builder --dir",
"build:win": "npm run build && electron-builder --win", "build:win": "npm run build && electron-builder --win",
@ -23,9 +23,9 @@
"dependencies": { "dependencies": {
"@electron-toolkit/preload": "^3.0.1", "@electron-toolkit/preload": "^3.0.1",
"@electron-toolkit/utils": "^3.0.0", "@electron-toolkit/utils": "^3.0.0",
"better-sqlite3": "^11.1.2",
"electron-updater": "^6.1.7", "electron-updater": "^6.1.7",
"knex": "^3.1.0", "knex": "^3.1.0"
"sqlite3": "^5.1.7"
}, },
"devDependencies": { "devDependencies": {
"@electron-toolkit/eslint-config-prettier": "^2.0.0", "@electron-toolkit/eslint-config-prettier": "^2.0.0",
@ -36,7 +36,7 @@
"@types/react-dom": "^18.3.0", "@types/react-dom": "^18.3.0",
"@vitejs/plugin-react": "^4.3.1", "@vitejs/plugin-react": "^4.3.1",
"electron": "^31.0.2", "electron": "^31.0.2",
"electron-builder": "^24.13.3", "electron-builder": "24.6.3",
"electron-vite": "^2.3.0", "electron-vite": "^2.3.0",
"eslint": "^8.57.0", "eslint": "^8.57.0",
"eslint-plugin-react": "^7.34.3", "eslint-plugin-react": "^7.34.3",

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,8 @@ import { app, shell, BrowserWindow } from 'electron'
import { join } from 'path' import { join } from 'path'
import { electronApp, optimizer, is } from '@electron-toolkit/utils' import { electronApp, optimizer, is } from '@electron-toolkit/utils'
import icon from '../../resources/icon.png?asset' import icon from '../../resources/icon.png?asset'
import { setupSignals } from './ipc' import { setupIpcHandle } from './ipc'
import { setupAutoUpdater } from './updater'
import './sqlite3' import './sqlite3'
function createWindow(): void { function createWindow(): void {
@ -35,6 +36,9 @@ function createWindow(): void {
} else { } else {
mainWindow.loadFile(join(__dirname, '../renderer/index.html')) mainWindow.loadFile(join(__dirname, '../renderer/index.html'))
} }
setupIpcHandle()
setupAutoUpdater(mainWindow)
} }
// This method will be called when Electron has finished // This method will be called when Electron has finished
@ -51,8 +55,6 @@ app.whenReady().then(() => {
optimizer.watchWindowShortcuts(window) optimizer.watchWindowShortcuts(window)
}) })
setupSignals()
createWindow() createWindow()
app.on('activate', function () { app.on('activate', function () {

View File

@ -1,8 +1,18 @@
import { ipcMain } from 'electron' import { ipcMain } from 'electron'
import { autoUpdater } from 'electron-updater'
/** /**
* ipc signals * ipc signals
*/ */
export const setupSignals = (): void => { export const setupIpcHandle = (): void => {
ipcMain.on('ping', () => console.log('pong')) ipcMain.on('ping', () => console.log('pong'))
ipcMain.handle('check-for-updates', (event) => {
console.log('检查更新')
autoUpdater.checkForUpdates()
console.log('执行')
})
ipcMain.handle('quit-and-install', () => {
autoUpdater.quitAndInstall()
})
} }

View File

@ -5,21 +5,26 @@ import path = require('path')
// 初始化 Knex 配置 // 初始化 Knex 配置
const initKnex = (): Knex => const initKnex = (): Knex =>
knex({ knex({
client: 'sqlite3', client: 'better-sqlite3',
connection: { connection: {
filename: path.join(app.getPath('userData'), 'cvpilot.db') filename: path.join(app.getPath('userData'), 'cvpilot.db')
}, },
useNullAsDefault: true useNullAsDefault: true
}) })
// 创建一个表 // 创建一个表,如果它不存在
const createTable = async (db: Knex) => { const createTable = async (db: Knex) => {
await db.schema.createTable('users', (table) => { const exists = await db.schema.hasTable('users')
table.increments('id') if (!exists) {
table.string('name') await db.schema.createTable('users', (table) => {
table.integer('age') table.increments('id')
}) table.string('name')
console.log('Table created') table.integer('age')
})
console.log('Table created')
} else {
console.log('Table already exists')
}
} }
// 插入数据 // 插入数据

47
src/main/updater.ts Normal file
View File

@ -0,0 +1,47 @@
import { app, BrowserWindow, dialog } from 'electron'
import { autoUpdater } from 'electron-updater'
/**
* 文档地址: https://www.electron.build/auto-update
*/
export const setupAutoUpdater = (win: BrowserWindow) => {
// 配置更新服务器地址
const updateServerUrl = `https://assets.maxshader.com`
const isDevelopment = process.env.NODE_ENV === 'development'
if (isDevelopment) {
// 强制在开发环境进行更新检查
autoUpdater.forceDevUpdateConfig = true
}
// 关闭自动更新
autoUpdater.autoDownload = false
// 设置自动更新的 feed URL
autoUpdater.setFeedURL({ provider: 'generic', url: updateServerUrl })
autoUpdater.on('update-downloaded', (res) => {
console.log('下载完成')
autoUpdater.quitAndInstall()
})
autoUpdater.on('checking-for-update', () => {
console.log('checking-for-update,开始检查更新')
})
autoUpdater.on('update-available', (info) => {
console.log('update-available,有可用更新')
autoUpdater.downloadUpdate()
})
autoUpdater.on('download-progress', (progress) => {
console.log('下载进度download-progress')
console.log(progress)
win.webContents.send('update-progress', progress)
})
autoUpdater.on('error', (error) => {
console.log('更新错误', error)
win.webContents.send('update-error', { error, updateServerUrl })
})
}

View File

@ -3,6 +3,10 @@ import { ElectronAPI } from '@electron-toolkit/preload'
declare global { declare global {
interface Window { interface Window {
electron: ElectronAPI electron: ElectronAPI
api: unknown api: {
checkUpdate
confirmUpdate
quitInstall
}
} }
} }

View File

@ -1,8 +1,12 @@
import { contextBridge } from 'electron' import { contextBridge, ipcRenderer } from 'electron'
import { electronAPI } from '@electron-toolkit/preload' import { electronAPI } from '@electron-toolkit/preload'
// Custom APIs for renderer // Custom APIs for renderer
const api = {} const api = {
checkUpdate: () => ipcRenderer.invoke('check-for-updates'),
confirmUpdate: (version) => ipcRenderer.invoke('confirmUpdate', version),
quitInstall: () => ipcRenderer.invoke('quit-and-install')
}
// Use `contextBridge` APIs to expose Electron APIs to // Use `contextBridge` APIs to expose Electron APIs to
// renderer only if context isolation is enabled, otherwise // renderer only if context isolation is enabled, otherwise

View File

@ -1,13 +1,29 @@
import Versions from './components/Versions' import Versions from './components/Versions'
import electronLogo from './assets/electron.svg' import electronLogo from './assets/electron.svg'
import { useEffect, useState } from 'react'
function App(): JSX.Element { function App(): JSX.Element {
const ipcHandle = (): void => window.electron.ipcRenderer.send('ping') const updateHandle = () => window.api.checkUpdate()
const [percent, setPercent] = useState()
useEffect(() => {
window.electron.ipcRenderer.on('update-error', (e, data) => {
// console.log(e)
console.log(data)
})
}, [])
useEffect(() => {
window.electron.ipcRenderer.on('update-progress', (e, data) => {
setPercent(data.percent)
})
}, [])
return ( return (
<> <>
<img alt="logo" className="logo" src={electronLogo} /> <img alt="logo" className="logo" src={electronLogo} />
<div className="creator">Powered by electron-vite</div> <button onClick={updateHandle}>1.0.5</button>
<div className="creator">{percent}</div>
<div className="text"> <div className="text">
Build an Electron app with <span className="react">React</span> Build an Electron app with <span className="react">React</span>
&nbsp;and <span className="ts">TypeScript</span> &nbsp;and <span className="ts">TypeScript</span>
@ -21,11 +37,6 @@ function App(): JSX.Element {
Documentation Documentation
</a> </a>
</div> </div>
<div className="action">
<a target="_blank" rel="noreferrer" onClick={ipcHandle}>
Send IPC
</a>
</div>
</div> </div>
<Versions></Versions> <Versions></Versions>
</> </>

View File

@ -8,6 +8,7 @@ function Versions(): JSX.Element {
<li className="electron-version">Electron v{versions.electron}</li> <li className="electron-version">Electron v{versions.electron}</li>
<li className="chrome-version">Chromium v{versions.chrome}</li> <li className="chrome-version">Chromium v{versions.chrome}</li>
<li className="node-version">Node v{versions.node}</li> <li className="node-version">Node v{versions.node}</li>
<li>{window.electron.process.platform}</li>
</ul> </ul>
) )
} }

View File

@ -1,11 +1,5 @@
import './assets/main.css' import './assets/main.css'
import React from 'react'
import ReactDOM from 'react-dom/client' import ReactDOM from 'react-dom/client'
import App from './App' import App from './App'
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render( ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(<App />)
<React.StrictMode>
<App />
</React.StrictMode>
)