From 072d57f068960921f4d34d613e73273bc567018e Mon Sep 17 00:00:00 2001 From: muwoo <2424880409@qq.com> Date: Fri, 19 Nov 2021 15:57:25 +0800 Subject: [PATCH] =?UTF-8?q?:tada:=20=E5=88=9D=E5=A7=8B=E5=8C=96=E9=A1=B9?= =?UTF-8?q?=E7=9B=AE=20electron13=20+=20vue3=20+=20typescript?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/common/constans/index.js | 5 + src/common/utils/commonConst.ts | 17 ++++ src/main/browsers/index.ts | 3 + src/main/browsers/main.ts | 66 +++++++++++++ src/main/index.ts | 160 ++++++++++++++++++-------------- src/renderer/shims-vue.d.ts | 4 + tsconfig.json | 1 + vue.config.js | 56 +++++++++-- 8 files changed, 237 insertions(+), 75 deletions(-) create mode 100644 src/common/constans/index.js create mode 100644 src/common/utils/commonConst.ts create mode 100644 src/main/browsers/index.ts create mode 100644 src/main/browsers/main.ts diff --git a/src/common/constans/index.js b/src/common/constans/index.js new file mode 100644 index 0000000..7e679cb --- /dev/null +++ b/src/common/constans/index.js @@ -0,0 +1,5 @@ +const APP_FINDER_PATH = process.platform === 'darwin' ? ['/System/Applications', '/Applications', '/System/Library/PreferencePanes'] : [] + +export { + APP_FINDER_PATH +} diff --git a/src/common/utils/commonConst.ts b/src/common/utils/commonConst.ts new file mode 100644 index 0000000..3c523b2 --- /dev/null +++ b/src/common/utils/commonConst.ts @@ -0,0 +1,17 @@ +export default { + linux(): boolean { + return process.platform === "linux"; + }, + macOS(): boolean { + return process.platform === "darwin"; + }, + windows(): boolean { + return process.platform === "win32"; + }, + production(): boolean { + return process.env.NODE_ENV !== "development"; + }, + dev(): boolean { + return process.env.NODE_ENV === "development"; + }, +}; diff --git a/src/main/browsers/index.ts b/src/main/browsers/index.ts new file mode 100644 index 0000000..636afc3 --- /dev/null +++ b/src/main/browsers/index.ts @@ -0,0 +1,3 @@ +import main from "./main"; +console.log(111); +export { main }; diff --git a/src/main/browsers/main.ts b/src/main/browsers/main.ts new file mode 100644 index 0000000..d5d9e0d --- /dev/null +++ b/src/main/browsers/main.ts @@ -0,0 +1,66 @@ +import { app, BrowserWindow, protocol } from "electron"; +import { createProtocol } from "vue-cli-plugin-electron-builder/lib"; +export default () => { + let win: any; + + const init = () => { + createWindow(); + }; + + const createWindow = async () => { + win = new BrowserWindow({ + height: 600, + useContentSize: true, + resizable: true, + width: 800, + frame: false, + title: "拉比克", + show: false, + skipTaskbar: true, + webPreferences: { + webSecurity: false, + enableRemoteModule: true, + backgroundThrottling: false, + contextIsolation: false, + webviewTag: true, + nodeIntegration: true, + }, + }); + if (process.env.WEBPACK_DEV_SERVER_URL) { + // Load the url of the dev server if in development mode + win.loadURL(process.env.WEBPACK_DEV_SERVER_URL as string); + } else { + createProtocol("app"); + // Load the index.html when not in development + win.loadURL("app://./index.html"); + } + + protocol.interceptFileProtocol("image", (req, callback) => { + const url = req.url.substr(8); + callback(decodeURI(url)); + }); + + win.once("ready-to-show", () => { + win.show(); + // 非隐藏式启动需要显示主窗口 + if (!app.getLoginItemSettings().wasOpenedAsHidden) { + win.show(); + } + }); + win.on("closed", () => { + win = undefined; + }); + + // 判断失焦是否隐藏 + win.on("blur", () => { + app.isPackaged && win.hide(); + }); + }; + + const getWindow = () => win; + + return { + init, + getWindow, + }; +}; diff --git a/src/main/index.ts b/src/main/index.ts index 02d321a..34c025e 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -1,80 +1,104 @@ "use strict"; -import { app, protocol, BrowserWindow } from "electron"; -import { createProtocol } from "vue-cli-plugin-electron-builder/lib"; -import installExtension, { VUEJS3_DEVTOOLS } from "electron-devtools-installer"; -const isDevelopment = process.env.NODE_ENV !== "production"; +import { app, globalShortcut, protocol, BrowserWindow } from "electron"; +import { main } from "./browsers"; +import commonConst from "../common/utils/commonConst"; -// Scheme must be registered before the app is ready -protocol.registerSchemesAsPrivileged([ - { scheme: "app", privileges: { secure: true, standard: true } }, -]); +class App { + private windowCreator: { init: () => void; getWindow: () => BrowserWindow }; -async function createWindow() { - // Create the browser window. - const win = new BrowserWindow({ - width: 800, - height: 600, - webPreferences: { - // Use pluginOptions.nodeIntegration, leave this alone - // See nklayman.github.io/vue-cli-plugin-electron-builder/guide/security.html#node-integration for more info - nodeIntegration: process.env - .ELECTRON_NODE_INTEGRATION as unknown as boolean, - contextIsolation: !process.env.ELECTRON_NODE_INTEGRATION, - }, - }); - - if (process.env.WEBPACK_DEV_SERVER_URL) { - // Load the url of the dev server if in development mode - await win.loadURL(process.env.WEBPACK_DEV_SERVER_URL as string); - if (!process.env.IS_TEST) win.webContents.openDevTools(); - } else { - createProtocol("app"); - // Load the index.html when not in development - win.loadURL("app://./index.html"); - } -} - -// Quit when all windows are closed. -app.on("window-all-closed", () => { - // On macOS it is common for applications and their menu bar - // to stay active until the user quits explicitly with Cmd + Q - if (process.platform !== "darwin") { - app.quit(); - } -}); - -app.on("activate", () => { - // On macOS it's common to re-create a window in the app when the - // dock icon is clicked and there are no other windows open. - if (BrowserWindow.getAllWindows().length === 0) createWindow(); -}); - -// This method will be called when Electron has finished -// initialization and is ready to create browser windows. -// Some APIs can only be used after this event occurs. -app.on("ready", async () => { - if (isDevelopment && !process.env.IS_TEST) { - // Install Vue Devtools - try { - await installExtension(VUEJS3_DEVTOOLS); - } catch (e) { - console.error("Vue Devtools failed to install:", e.toString()); + constructor() { + protocol.registerSchemesAsPrivileged([ + { scheme: "app", privileges: { secure: true, standard: true } }, + ]); + this.windowCreator = main(); + const gotTheLock = app.requestSingleInstanceLock(); + if (!gotTheLock) { + app.quit(); + } else { + this.beforeReady(); + this.onReady(); + this.onRunning(); + this.onQuit(); } } - createWindow(); -}); -// Exit cleanly on request from parent process in development mode. -if (isDevelopment) { - if (process.platform === "win32") { - process.on("message", (data) => { - if (data === "graceful-exit") { + beforeReady() { + // 系统托盘 + if (commonConst.macOS()) { + if (commonConst.production() && !app.isInApplicationsFolder()) { + app.moveToApplicationsFolder(); + } else { + app.dock.hide(); + } + } else { + app.disableHardwareAcceleration(); + } + } + + createWindow() { + this.windowCreator.init(); + } + + onReady() { + const readyFunction = () => { + this.createWindow(); + // this.init() + // createTray(this.windowCreator.getWindow()) + // autoUpdate() + }; + if (!app.isReady()) { + app.on("ready", readyFunction); + } else { + readyFunction(); + } + } + + onRunning() { + app.on("second-instance", () => { + // 当运行第二个实例时,将会聚焦到myWindow这个窗口 + const win = this.windowCreator.getWindow(); + if (win) { + if (win.isMinimized()) { + win.restore(); + } + win.focus(); + } + }); + app.on("activate", () => { + if (!this.windowCreator.getWindow()) { + this.createWindow(); + } + }); + if (commonConst.windows()) { + // app.setAppUserModelId(pkg.build.appId) + } + } + + onQuit() { + app.on("window-all-closed", () => { + if (process.platform !== "darwin") { app.quit(); } }); - } else { - process.on("SIGTERM", () => { - app.quit(); + + app.on("will-quit", () => { + globalShortcut.unregisterAll(); }); + + if (commonConst.dev()) { + if (process.platform === "win32") { + process.on("message", (data) => { + if (data === "graceful-exit") { + app.quit(); + } + }); + } else { + process.on("SIGTERM", () => { + app.quit(); + }); + } + } } } + +new App(); diff --git a/src/renderer/shims-vue.d.ts b/src/renderer/shims-vue.d.ts index 3804a43..ce9492b 100644 --- a/src/renderer/shims-vue.d.ts +++ b/src/renderer/shims-vue.d.ts @@ -4,3 +4,7 @@ declare module '*.vue' { const component: DefineComponent<{}, {}, any> export default component } + +declare module 'main' { + export function main (): any +} diff --git a/tsconfig.json b/tsconfig.json index e621cbc..b7d3b4a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -10,6 +10,7 @@ "esModuleInterop": true, "allowSyntheticDefaultImports": true, "sourceMap": true, + "resolveJsonModule": true, "baseUrl": ".", "types": [ "webpack-env" diff --git a/vue.config.js b/vue.config.js index bfa0799..423537d 100644 --- a/vue.config.js +++ b/vue.config.js @@ -1,5 +1,5 @@ // eslint-disable-next-line @typescript-eslint/no-var-requires -const path = require('path'); +const path = require("path"); module.exports = { configureWebpack: { @@ -9,16 +9,58 @@ module.exports = { }, }, }, + pages: { + index: { + entry: "src/renderer/main.ts", + }, + }, pluginOptions: { electronBuilder: { - mainProcessFile: 'src/main/index.ts', + mainProcessFile: "src/main/index.ts", + mainProcessWatch: ["src/main"], // Use this to change the entry point of your app's render process. default src/[main|index].[js|ts] builderOptions: { - // options placed here will be merged with default configuration and passed to electron-builder - }, - chainWebpackRendererProcess: (config) => { - config.entryPoints.clear(); // 清空默认入口 - config.entry('test').add(path.join(__dirname, "./src/renderer/main.ts")); // 重新设置 + productName: "rubick2", + appId: "com.muwoo.rubick", + compression: "maximum", + directories: { + output: "build", + }, + files: ["dist/electron/**/*"], + dmg: { + contents: [ + { + x: 410, + y: 150, + type: "link", + path: "/Applications", + }, + { + x: 130, + y: 150, + type: "file", + }, + ], + }, + mac: { + icon: "build/icons/icon.icns", + target: "pkg", + extendInfo: { + LSUIElement: 1, + }, + }, + win: { + icon: "build/icons/icon.ico", + target: "nsis", + }, + nsis: { + oneClick: false, + allowToChangeInstallationDirectory: true, + }, + linux: { + icon: "build/icons/", + publish: ["github"], + }, }, }, },