From a4e4373737c0b7368d6f603e557acea920c5de62 Mon Sep 17 00:00:00 2001 From: npmrun <1549469775@qq.com> Date: Fri, 14 Feb 2025 21:21:59 +0800 Subject: [PATCH] init --- .npmrc | 1 + electron.vite.config.ts | 2 +- package.json | 5 +- packages/IPC/common/utils.ts | 5 ++ packages/IPC/main/index.ts | 0 packages/IPC/package.json | 12 +++ packages/IPC/renderer/index.ts | 0 packages/IPC/tsconfig.json | 4 + packages/IPC/tsconfig.node.json | 10 +++ packages/IPC/tsconfig.web.json | 12 +++ packages/IPC/types/index.d.ts | 0 pnpm-lock.yaml | 4 +- pnpm-workspace.yaml | 2 + src/main/App.ts | 3 + src/main/commands/TabsCommand.ts | 13 +-- src/main/controller/BasicService.ts | 6 +- src/main/controller/TabsService.ts | 6 +- src/main/index.ts | 4 +- src/main/modules/_ioc.ts | 4 + src/main/modules/api/index.ts | 6 +- src/main/modules/commands/index.ts | 6 +- src/main/modules/db/index.ts | 2 +- src/main/modules/setting/index.ts | 2 +- src/main/modules/tabs/Tab.ts | 2 +- src/main/modules/tabs/index.ts | 6 +- src/main/modules/updater/index.ts | 112 ++++++++++++++++++++++++++ src/main/modules/window-manager/index.ts | 2 +- src/main/modules/window-manager/windowsMap.ts | 2 +- src/main/modules/zephyr/index.ts | 8 +- src/renderer/src/App.vue | 7 +- tsconfig.node.json | 2 +- 31 files changed, 208 insertions(+), 42 deletions(-) create mode 100644 packages/IPC/common/utils.ts create mode 100644 packages/IPC/main/index.ts create mode 100644 packages/IPC/package.json create mode 100644 packages/IPC/renderer/index.ts create mode 100644 packages/IPC/tsconfig.json create mode 100644 packages/IPC/tsconfig.node.json create mode 100644 packages/IPC/tsconfig.web.json create mode 100644 packages/IPC/types/index.d.ts create mode 100644 pnpm-workspace.yaml create mode 100644 src/main/modules/updater/index.ts diff --git a/.npmrc b/.npmrc index 2ced952..f6280a0 100644 --- a/.npmrc +++ b/.npmrc @@ -1,3 +1,4 @@ electron_mirror=https://npmmirror.com/mirrors/electron/ electron_builder_binaries_mirror=https://npmmirror.com/mirrors/electron-builder-binaries/ shamefully-hoist=true +link-workspace-packages=true diff --git a/electron.vite.config.ts b/electron.vite.config.ts index 5327a38..a5b2cf9 100644 --- a/electron.vite.config.ts +++ b/electron.vite.config.ts @@ -8,7 +8,7 @@ export default defineConfig({ resolve: { alias: { config: resolve("config"), - vc: resolve("src/main"), + main: resolve("src/main"), res: resolve("resources"), }, }, diff --git a/package.json b/package.json index 858836b..5d9e746 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,7 @@ { - "name": "my-app", + "name": "zephyr", "type": "module", + "private": true, "version": "1.0.0", "description": "An Electron application with Vue and TypeScript", "main": "./out/main/index.js", @@ -53,7 +54,7 @@ "typescript": "^5.5.2", "unocss": "^0.64.1", "vite": "^5.3.1", - "vue": "^3.4.30", + "vue": "^3.5.12", "vue-tsc": "^2.0.22" } } diff --git a/packages/IPC/common/utils.ts b/packages/IPC/common/utils.ts new file mode 100644 index 0000000..9464d65 --- /dev/null +++ b/packages/IPC/common/utils.ts @@ -0,0 +1,5 @@ +import { webContents } from "electron" + +export const broadcast = (event: string, ...args: any[]) => { + webContents.getAllWebContents().forEach(browser => browser.send(event, ...args)) +} diff --git a/packages/IPC/main/index.ts b/packages/IPC/main/index.ts new file mode 100644 index 0000000..e69de29 diff --git a/packages/IPC/package.json b/packages/IPC/package.json new file mode 100644 index 0000000..847b14d --- /dev/null +++ b/packages/IPC/package.json @@ -0,0 +1,12 @@ +{ + "name": "z-ipc", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC" +} diff --git a/packages/IPC/renderer/index.ts b/packages/IPC/renderer/index.ts new file mode 100644 index 0000000..e69de29 diff --git a/packages/IPC/tsconfig.json b/packages/IPC/tsconfig.json new file mode 100644 index 0000000..d6f9b7b --- /dev/null +++ b/packages/IPC/tsconfig.json @@ -0,0 +1,4 @@ +{ + "files": [], + "references": [{ "path": "./tsconfig.node.json" }, { "path": "./tsconfig.web.json" }] + } diff --git a/packages/IPC/tsconfig.node.json b/packages/IPC/tsconfig.node.json new file mode 100644 index 0000000..76fb401 --- /dev/null +++ b/packages/IPC/tsconfig.node.json @@ -0,0 +1,10 @@ +{ + "extends": "@electron-toolkit/tsconfig/tsconfig.node.json", + "include": ["main/**/*", "preload/**/*", "common/**/*", "types/**/*"], + "compilerOptions": { + "composite": true, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "types": ["electron-vite/node"], + } +} diff --git a/packages/IPC/tsconfig.web.json b/packages/IPC/tsconfig.web.json new file mode 100644 index 0000000..e3b4220 --- /dev/null +++ b/packages/IPC/tsconfig.web.json @@ -0,0 +1,12 @@ +{ + "extends": "@electron-toolkit/tsconfig/tsconfig.web.json", + "include": [ + "renderer/**/*", + "preload/**/*", + "common/**/*", + "types/**/*" + ], + "compilerOptions": { + "composite": true + } +} diff --git a/packages/IPC/types/index.d.ts b/packages/IPC/types/index.d.ts new file mode 100644 index 0000000..e69de29 diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 39e3dda..268e3bd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -94,12 +94,14 @@ importers: specifier: ^5.3.1 version: 5.4.11(@types/node@20.15.0)(sass@1.81.0) vue: - specifier: ^3.4.30 + specifier: ^3.5.12 version: 3.5.12(typescript@5.6.3) vue-tsc: specifier: ^2.0.22 version: 2.1.10(typescript@5.6.3) + packages/IPC: {} + packages: 7zip-bin@5.2.0: diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml new file mode 100644 index 0000000..6de82ae --- /dev/null +++ b/pnpm-workspace.yaml @@ -0,0 +1,2 @@ +packages: + - "packages/*" diff --git a/src/main/App.ts b/src/main/App.ts index c61b521..037e164 100644 --- a/src/main/App.ts +++ b/src/main/App.ts @@ -10,6 +10,7 @@ import BaseClass from "./base/base" import IOC from "./_ioc" import DB from "./modules/db" import Zephyr from "./modules/zephyr" +import Updater from "./modules/updater" protocol.registerSchemesAsPrivileged([ // { @@ -54,11 +55,13 @@ class App extends BaseClass { @inject(DB) private _DB: DB, @inject(WindowManager) private _WindowManager: WindowManager, @inject(Zephyr) private _Zephyr: Zephyr, + @inject(Updater) private _Updater: Updater, ) { super() } async init() { + this._Updater.init() this._DB.init() this._Command.init() this._WindowManager.init() diff --git a/src/main/commands/TabsCommand.ts b/src/main/commands/TabsCommand.ts index f75647b..7f7a519 100644 --- a/src/main/commands/TabsCommand.ts +++ b/src/main/commands/TabsCommand.ts @@ -1,7 +1,7 @@ import { inject } from "inversify" -import Tabs from "vc/modules/tabs" -import WindowManager from "vc/modules/window-manager" -import { broadcast } from "vc/utils" +import Tabs from "main/modules/tabs" +import WindowManager from "main/modules/window-manager" +import { broadcast } from "main/utils" class TabsCommand { static name: string = "TabsCommand" @@ -11,12 +11,7 @@ class TabsCommand { @inject(WindowManager) private _WindowManager: WindowManager, ) { this.listenerTabActive = this.listenerTabActive.bind(this) - this._Tabs.events.addListener("update", this.listenerTabActive) - } - - init() { - const mainWindow = this._WindowManager.getMainWindow() - this._Tabs.init(mainWindow) + this._Tabs.events.on("update", this.listenerTabActive) } bindElement(rect) { diff --git a/src/main/controller/BasicService.ts b/src/main/controller/BasicService.ts index 38addf0..84383ff 100644 --- a/src/main/controller/BasicService.ts +++ b/src/main/controller/BasicService.ts @@ -1,7 +1,7 @@ import { inject, injectable } from "inversify" -import BaseContainer from "vc/base/baseContainer" -import Tabs from "vc/modules/tabs" -import WindowManager from "vc/modules/window-manager" +import BaseContainer from "main/base/baseContainer" +import Tabs from "main/modules/tabs" +import WindowManager from "main/modules/window-manager" @injectable() class BasicService extends BaseContainer { diff --git a/src/main/controller/TabsService.ts b/src/main/controller/TabsService.ts index cd9e378..f736574 100644 --- a/src/main/controller/TabsService.ts +++ b/src/main/controller/TabsService.ts @@ -1,7 +1,7 @@ import { inject, injectable } from "inversify" -import BaseContainer from "vc/base/baseContainer" -import Tabs from "vc/modules/tabs" -import WindowManager from "vc/modules/window-manager" +import BaseContainer from "main/base/baseContainer" +import Tabs from "main/modules/tabs" +import WindowManager from "main/modules/window-manager" @injectable() class TabsService extends BaseContainer { diff --git a/src/main/index.ts b/src/main/index.ts index 92794b5..5823e9d 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -1,6 +1,6 @@ import "reflect-metadata" -import { _ioc } from "vc/_ioc" -import { App } from "vc/App" +import { _ioc } from "main/_ioc" +import { App } from "main/App" const curApp = _ioc.get(App) curApp.init() diff --git a/src/main/modules/_ioc.ts b/src/main/modules/_ioc.ts index 830a4d7..7196178 100644 --- a/src/main/modules/_ioc.ts +++ b/src/main/modules/_ioc.ts @@ -6,10 +6,12 @@ import { WindowManager } from "./window-manager" import { Tabs } from "./tabs" import Commands from "./commands" import Zephyr from "./zephyr" +import Updater from "./updater" const modules = new ContainerModule(bind => { bind(Setting).toConstantValue(new Setting()) bind(Zephyr).toSelf().inSingletonScope() + bind(Updater).toSelf().inSingletonScope() bind(Api).toSelf().inSingletonScope() bind(WindowManager).toSelf().inSingletonScope() bind(Commands).toSelf().inSingletonScope() @@ -22,6 +24,8 @@ async function destroyAllModules(ioc: Container) { ioc.get(Setting).destroy(), ioc.get(WindowManager).destroy(), ioc.get(Commands).destroy(), + ioc.get(Updater).destroy(), + ioc.get(Zephyr).destroy(), ioc.get(Tabs).destroy(), ioc.get(Api).destroy(), ioc.get(DB).destroy(), diff --git a/src/main/modules/api/index.ts b/src/main/modules/api/index.ts index e4105dd..6abe99e 100644 --- a/src/main/modules/api/index.ts +++ b/src/main/modules/api/index.ts @@ -1,7 +1,7 @@ import { session, net } from "electron" import { inject, injectable } from "inversify" -import IOC from "vc/_ioc" -import BaseClass from "vc/base/base" +import IOC from "main/_ioc" +import BaseClass from "main/base/base" @injectable() class Api extends BaseClass { @@ -32,7 +32,7 @@ class Api extends BaseClass { const fnName = array[array.length - 1] // https://vitejs.cn/vite5-cn/guide/features.html#dynamic-import const module = await this._IOC.getAsync(routePath) - // const module = await import(`vc/controller/${routePath}.ts`) + // const module = await import(`main/controller/${routePath}.ts`) const opts = { body: {}, query: {} } if (isPost) { opts.body = await request.json() diff --git a/src/main/modules/commands/index.ts b/src/main/modules/commands/index.ts index 33ccc5d..0bdfe56 100644 --- a/src/main/modules/commands/index.ts +++ b/src/main/modules/commands/index.ts @@ -1,9 +1,9 @@ import { IMenuItemOption, IPopupMenuOption } from "#" import { ipcMain, Menu, MenuItem } from "electron" import { inject } from "inversify" -import IOC from "vc/_ioc" -import BaseClass from "vc/base/base" -import { isPromise } from "vc/utils" +import IOC from "main/_ioc" +import BaseClass from "main/base/base" +import { isPromise } from "main/utils" import WindowManager from "../window-manager" export default class Commands extends BaseClass { diff --git a/src/main/modules/db/index.ts b/src/main/modules/db/index.ts index 80d071e..1f13419 100644 --- a/src/main/modules/db/index.ts +++ b/src/main/modules/db/index.ts @@ -2,7 +2,7 @@ import { inject, injectable } from "inversify" import Setting from "../setting" import { CustomAdapter, CustomLow } from "./custom" import path from "node:path" -import BaseClass from "vc/base/base" +import BaseClass from "main/base/base" import _debug from "debug" const debug = _debug("app:db") diff --git a/src/main/modules/setting/index.ts b/src/main/modules/setting/index.ts index d35d4c7..0ba1dee 100644 --- a/src/main/modules/setting/index.ts +++ b/src/main/modules/setting/index.ts @@ -5,7 +5,7 @@ import { cloneDeep } from "lodash" import { injectable } from "inversify" import Config from "config" import _debug from "debug" -import BaseClass from "vc/base/base" +import BaseClass from "main/base/base" const debug = _debug("app:setting") diff --git a/src/main/modules/tabs/Tab.ts b/src/main/modules/tabs/Tab.ts index 4f21181..5a211ee 100644 --- a/src/main/modules/tabs/Tab.ts +++ b/src/main/modules/tabs/Tab.ts @@ -1,6 +1,6 @@ import { BrowserWindow, WebContentsView, WebPreferences } from "electron" import { join } from "node:path" -import BaseClass from "vc/base/base" +import BaseClass from "main/base/base" import _debug from "debug" // import { Layout } from "./Constant" import FuckHTML from "res/fuck.html?asset" diff --git a/src/main/modules/tabs/index.ts b/src/main/modules/tabs/index.ts index 924548d..fedbee0 100644 --- a/src/main/modules/tabs/index.ts +++ b/src/main/modules/tabs/index.ts @@ -1,5 +1,5 @@ import Tab from "./Tab" -import BaseClass from "vc/base/base" +import BaseClass from "main/base/base" import _debug from "debug" import { BrowserWindow } from "electron" import EventEmitter from "events" @@ -34,8 +34,8 @@ class Tabs extends BaseClass { _tabs: Tab[] = [] - init(mainWindow) { - this.add("about:blank", true, mainWindow) + init() { + // 初始化 } updateRect(curRect: IRect) { diff --git a/src/main/modules/updater/index.ts b/src/main/modules/updater/index.ts new file mode 100644 index 0000000..0bb3835 --- /dev/null +++ b/src/main/modules/updater/index.ts @@ -0,0 +1,112 @@ +import pkg from "electron-updater" +import { app, dialog } from "electron" +import { injectable, inject } from "inversify" +import BaseClass from "main/base/base" +import { Setting } from "../setting" +import _debug from "debug" +import EventEmitter from "events" + +const debug = _debug("app:updater") +const { autoUpdater } = pkg + +@injectable() +export class Updater extends BaseClass { + public events = new EventEmitter() + + constructor(@inject(Setting) private _Setting: Setting) { + super() + + // 配置自动更新 + autoUpdater.autoDownload = false + autoUpdater.autoInstallOnAppQuit = true + + // 检查更新错误 + autoUpdater.on("error", error => { + debug("Update error:", error) + }) + + // 检查更新 + autoUpdater.on("checking-for-update", () => { + debug("Checking for updates...") + }) + + // 有可用更新 + autoUpdater.on("update-available", info => { + debug("Update available:", info) + this.promptUserToUpdate() + }) + + // 没有可用更新 + autoUpdater.on("update-not-available", info => { + debug("Update not available:", info) + }) + + // 更新下载进度 + autoUpdater.on("download-progress", progressObj => { + debug( + `Download speed: ${progressObj.bytesPerSecond} - Downloaded ${progressObj.percent}% (${progressObj.transferred}/${progressObj.total})`, + ) + }) + + // 更新下载完成 + autoUpdater.on("update-downloaded", info => { + debug("Update downloaded:", info) + this.promptUserToInstall() + }) + } + + init() { + // 定期检查更新 + this.checkForUpdates() + setInterval( + () => { + this.checkForUpdates() + }, + 1000 * 60 * 60, + ) // 每小时检查一次 + } + + destroy() { + // 清理工作 + } + + private async checkForUpdates() { + if (app.isPackaged) { + try { + await autoUpdater.checkForUpdates() + } catch (error) { + debug("Failed to check for updates:", error) + } + } + } + + private async promptUserToUpdate() { + const result = await dialog.showMessageBox({ + type: "info", + title: "发现新版本", + message: "是否下载新版本?", + buttons: ["下载", "暂不更新"], + defaultId: 0, + }) + + if (result.response === 0) { + autoUpdater.downloadUpdate() + } + } + + private async promptUserToInstall() { + const result = await dialog.showMessageBox({ + type: "info", + title: "更新已就绪", + message: "新版本已下载完成,是否立即安装?", + buttons: ["立即安装", "稍后安装"], + defaultId: 0, + }) + + if (result.response === 0) { + autoUpdater.quitAndInstall(false, true) + } + } +} + +export default Updater diff --git a/src/main/modules/window-manager/index.ts b/src/main/modules/window-manager/index.ts index 60e32cc..df9d72c 100644 --- a/src/main/modules/window-manager/index.ts +++ b/src/main/modules/window-manager/index.ts @@ -2,7 +2,7 @@ import { BrowserWindow, app, dialog } from "electron" import { cloneDeep, merge } from "lodash" import { defaultConfig, defaultWindowConfig, getWindowsMap, IConfig, Param } from "./windowsMap" import { optimizer } from "@electron-toolkit/utils" -import BaseClass from "vc/base/base" +import BaseClass from "main/base/base" import _debug from "debug" const debug = _debug("app:window-manager") diff --git a/src/main/modules/window-manager/windowsMap.ts b/src/main/modules/window-manager/windowsMap.ts index 9606a9b..644934d 100644 --- a/src/main/modules/window-manager/windowsMap.ts +++ b/src/main/modules/window-manager/windowsMap.ts @@ -1,6 +1,6 @@ import config from "config" import { BrowserWindowConstructorOptions } from "electron" -import { getFileUrl } from "vc/utils" +import { getFileUrl } from "main/utils" import icon from "res/icon.png?asset" import { join } from "path" diff --git a/src/main/modules/zephyr/index.ts b/src/main/modules/zephyr/index.ts index 96264c8..7f8c7c6 100644 --- a/src/main/modules/zephyr/index.ts +++ b/src/main/modules/zephyr/index.ts @@ -1,13 +1,17 @@ import { session, net } from "electron" import { inject, injectable } from "inversify" -import IOC from "vc/_ioc" -import BaseClass from "vc/base/base" +import IOC from "main/_ioc" +import BaseClass from "main/base/base" +import _debug from "debug" + +const debug = _debug("app:zephyr") @injectable() class Zephyr extends BaseClass { constructor(@inject(IOC) private _IOC: IOC) { super() this.interceptHandlerZephyr = this.interceptHandlerZephyr.bind(this) + debug("aaaaaaaaaaaaaaaaaaaaaa") } destroy() { diff --git a/src/renderer/src/App.vue b/src/renderer/src/App.vue index b2c9e01..6ef55b1 100644 --- a/src/renderer/src/App.vue +++ b/src/renderer/src/App.vue @@ -1,11 +1,11 @@