Skip to content

Commit

Permalink
Merge pull request #262 from rao-pics/224-系统托盘
Browse files Browse the repository at this point in the history
224 系统托盘
  • Loading branch information
meetqy authored Jun 19, 2023
2 parents 75ce890 + 8df97dc commit 019b147
Show file tree
Hide file tree
Showing 11 changed files with 152 additions and 20 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

中文 | [English](./README.en.md)

![Coverage Badge](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/meetqy/5c4881f21bab2cf4f09a8658354fb997/raw/1e45502a948e69132afe85a923f4f54fdc77fbee/rao-pics_core__coverage.json)
![Coverage Badge](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/meetqy/5c4881f21bab2cf4f09a8658354fb997/raw/fde0a6c36d83cdd5ac45d6e324cb6b0196ac016e/rao-pics_core__coverage.json)
[![License](https://img.shields.io/github/license/rao-pics/core)](https://github.com/rao-pics/core/blob/turbo-electron-prisma/LICENSE)
[![release](https://img.shields.io/github/v/release/rao-pics/core)](https://github.com/rao-pics/core/releases)
![download](https://img.shields.io/github/downloads/rao-pics/core/total)
Expand Down
Binary file added apps/electron/buildResources/tray-dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added apps/electron/buildResources/tray-light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions apps/electron/main/global.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
const globalApp = globalThis as {
/** 是否退出 App */
isQuite?: boolean;
};

globalApp.isQuite = false;

export default globalApp;
53 changes: 39 additions & 14 deletions apps/electron/main/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { app, ipcMain, shell, type IpcMain } from "electron";
import { app, ipcMain, nativeTheme, shell, type IpcMain, type Tray } from "electron";

import "./security-restrictions";
import type cp from "child_process";
Expand All @@ -8,10 +8,13 @@ import { appRouter, createContext } from "@acme/api";
import { closeAssetsServer } from "@acme/assets-server";

import type { IPCRequestOptions } from "../types";
import globalApp from "./global";
import LibraryIPC from "./ipc/library";
import { syncIpc } from "./ipc/sync";
import { pageUrl, restoreOrCreateWindow } from "./mainWindow";
import { createWebServer } from "./src/createWebServer";
import createMenu from "./src/menu";
import createTray, { getTrayIcon } from "./src/tray";

let nextjsWebChild: cp.ChildProcess | undefined;

Expand Down Expand Up @@ -43,7 +46,13 @@ app.on("window-all-closed", () => {
}
});

app.on("will-quit", () => {
app.on("before-quit", (e) => {
if (!globalApp.isQuite) {
e.preventDefault();
}
});

app.on("quit", () => {
closeAssetsServer();
nextjsWebChild?.kill();
});
Expand All @@ -61,18 +70,42 @@ app.on("activate", () => {
});
});

let tray: Tray;
// 创建菜单
createMenu();

if (process.platform === "darwin") {
// 隐藏 docker
app.dock.hide();
}

/**
* Create the application window when the background process is ready.
*/
app
.whenReady()
.then(async () => {
await restoreOrCreateWindow().catch((err) => {
throw err;
});
.then(() => {
restoreOrCreateWindow()
.then(async () => {
// 托盘图标
tray = createTray();

// 创建 Web/Assets 服务
nextjsWebChild = await createWebServer();
if (!nextjsWebChild) {
throw Error("NextJS child process was not created, exiting...");
}
})
.catch((err) => {
throw err;
});
})
.catch((e) => console.error("Failed create window:", e));

nativeTheme.on("updated", () => {
tray && tray.setImage(getTrayIcon());
});

function validateSender(frame: Electron.WebFrameMain) {
const frameUrlObj = new URL(frame.url);
const pageUrlObj = new URL(pageUrl);
Expand Down Expand Up @@ -144,12 +177,4 @@ async function resolveIPCResponse(opts: IPCRequestOptions) {

app.on("ready", () => {
createIPCHandler({ ipcMain });

void (async () => {
nextjsWebChild = await createWebServer();

if (!nextjsWebChild) {
throw Error("NextJS child process was not created, exiting...");
}
})();
});
21 changes: 21 additions & 0 deletions apps/electron/main/mainWindow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ async function createWindow() {
height: 450,
resizable: false,
autoHideMenuBar: true,
fullscreen: false,
// frame: false,
webPreferences: {
allowRunningInsecureContent: false, // https://www.electronjs.org/docs/latest/tutorial/security#8-do-not-enable-allowrunninginsecurecontent
enableBlinkFeatures: "", // https://www.electronjs.org/docs/latest/tutorial/security#10-do-not-use-enableblinkfeatures
Expand Down Expand Up @@ -50,11 +52,29 @@ async function createWindow() {
}
});

browserWindow.on("close", (e) => {
if (browserWindow.isFullScreen()) {
e.preventDefault();
browserWindow.setFullScreen(false);
browserWindow.hide();
}
});

await browserWindow.loadURL(pageUrl);

return browserWindow;
}

/**
* 隐藏 window
*/
export const hideWindow = () => {
const window = BrowserWindow.getAllWindows().find((w) => !w.isDestroyed());
if (window) {
window.hide();
}
};

/**
* Restore an existing BrowserWindow or Create a new BrowserWindow.
*/
Expand All @@ -69,5 +89,6 @@ export async function restoreOrCreateWindow() {
window.restore();
}

window.show();
window.focus();
}
5 changes: 4 additions & 1 deletion apps/electron/main/src/createWebServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import ip from "ip";

import { createSqlite } from "@acme/db";

/**
* 创建 Web/Assets 服务
*/
export const createWebServer = async (preNextChild?: cp.ChildProcess) => {
let nextjsChild: cp.ChildProcess;

Expand All @@ -20,7 +23,7 @@ export const createWebServer = async (preNextChild?: cp.ChildProcess) => {
process.env["WEB_PORT"] = _web_port;
process.env["ASSETS_PORT"] = _assets_port;

if (app.isPackaged) {
if (isPackaged) {
preNextChild?.kill();
// app config production
// dev 在 watchDesktop.ts 中指定
Expand Down
24 changes: 24 additions & 0 deletions apps/electron/main/src/menu.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { Menu, app } from "electron";

import { hideWindow } from "../mainWindow";

/**
* 创建菜单
*/
const createMenu = () => {
const menu = Menu.buildFromTemplate([
{
label: app.name,
submenu: [
{
label: "Quit",
accelerator: "CmdOrCtrl+Q",
click: () => hideWindow(),
},
],
},
]);
Menu.setApplicationMenu(menu);
};

export default createMenu;
45 changes: 45 additions & 0 deletions apps/electron/main/src/tray.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { join } from "path";
import { Menu, Tray, app, nativeTheme } from "electron";

import globalApp from "../global";
import { restoreOrCreateWindow } from "../mainWindow";

export const getTrayIcon = () => {
if (app.isPackaged) {
return join(process.resourcesPath, "buildResources", nativeTheme.shouldUseDarkColors ? "tray-dark.png" : "tray-light.png");
} else {
return join(__dirname, "../../buildResources", nativeTheme.shouldUseDarkColors ? "tray-dark.png" : "tray-light.png");
}
};

/**
* 系统托盘
* @returns {Tray}
*/
const createTray = () => {
// 托盘图标
const tray = new Tray(getTrayIcon());

const contextMenu = Menu.buildFromTemplate([
{
label: "打开 Rao Pics",
type: "normal",
click: () => {
void restoreOrCreateWindow();
},
},
{
label: "退出",
type: "normal",
click: () => {
globalApp.isQuite = true;
app.quit();
},
},
]);
tray.setContextMenu(contextMenu);

return tray;
};

export default createTray;
4 changes: 4 additions & 0 deletions apps/electron/scripts/compile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ export const AppConfig: builder.Configuration = {
"!**/node_modules/@acme/**/*",
].concat(excludeFileDir),
extraResources: [
{
from: "./buildResources",
to: "buildResources",
},
{
from: "../../packages/db/prisma/db.sqlite",
to: "packages/db/prisma/db.sqlite",
Expand Down
10 changes: 6 additions & 4 deletions turbo.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,20 @@
"$schema": "https://turborepo.org/schema.json",
"globalDependencies": ["**/.env"],
"pipeline": {
"db:reset": { "inputs": ["prisma/schema.prisma"] },
"db:reset": { "inputs": ["prisma/schema.prisma"], "cache": false },
"dev": {
"persistent": true,
"cache": false
},
"build": {
"outputs": ["./.next/standalone/**", "!.next/cache/**", "electron/**/dist/**"],
"dependsOn": ["^build"]
"outputs": ["nextjs/.next/standalone", "!nextjs/.next/cache", "electron/**/dist"],
"dependsOn": ["^build"],
"cache": false
},
"compile": {
"outputs": ["electron/dist/*.exe", "electron/dist/*.dmg"],
"dependsOn": ["db:reset", "build"]
"dependsOn": ["db:reset", "build"],
"cache": false
},
"lint": {}
},
Expand Down

0 comments on commit 019b147

Please sign in to comment.