Skip to content

Commit

Permalink
feat: add ipc invoke & shortcuts (#15)
Browse files Browse the repository at this point in the history
  • Loading branch information
lgz5689 committed Jun 16, 2024
1 parent 689169f commit 539518d
Show file tree
Hide file tree
Showing 13 changed files with 166 additions and 20 deletions.
34 changes: 34 additions & 0 deletions electron/constants/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
export enum IpcRenderToMain {
ShowDevTools = "showDevTools",
ShowMainWindow = "showMainWindow",
ClearChildWindows = "clearChildWindows",
}

export type IpcRenderToMainDataMap = {
[IpcRenderToMain.ShowDevTools]: void;
[IpcRenderToMain.ShowMainWindow]: void;
[IpcRenderToMain.ClearChildWindows]: void;
};

export enum IpcRenderToMainSync {
CheckChildWindowStatus = "checkChildWindowStatus",
}

export type IpcRenderToMainSyncDataMap = {
[IpcRenderToMainSync.CheckChildWindowStatus]: boolean;
};

export interface IElectronAPI {
fileExists: (path: string) => boolean;
getPlatform: () => string;
ipcInvoke: <T extends keyof IpcRenderToMainDataMap>(
channel: T,
...arg: unknown[]
) => Promise<IpcRenderToMainDataMap[T]>;
ipcSendSync: <T extends keyof IpcRenderToMainSyncDataMap>(
channel: T,
...arg: unknown[]
) => IpcRenderToMainSyncDataMap[T];
openFile: (path: string) => Promise<string>;
showFile: (path: string) => void;
}
2 changes: 1 addition & 1 deletion electron/i18n/i18next.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as en from "./resources/en_US";
import { defaultNS } from ".";
import * as en from "./resources/en_US";

declare module "i18next" {
interface CustomTypeOptions {
Expand Down
2 changes: 1 addition & 1 deletion electron/i18n/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import i18n from "i18next";
import { app } from "electron";
import i18n from "i18next";

import * as en from "./resources/en_US";
import * as zh from "./resources/zh_CN";
Expand Down
1 change: 1 addition & 0 deletions electron/main/appManage.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { join } from "node:path";

import { isProd, isWin } from "../utils";

export const electronDistPath = join(__dirname, "../");
Expand Down
6 changes: 5 additions & 1 deletion electron/main/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { app } from "electron";
import { createMainWindow } from "./windowManage";

import { initI18n } from "../i18n";
import { setIpcMainListener } from "./ipcHandlerManage";
import { createTray } from "./trayManage";
import { createMainWindow } from "./windowManage";

process.env["ELECTRON_DISABLE_SECURITY_WARNINGS"] = "true";

Expand All @@ -11,4 +13,6 @@ const init = () => {
createTray();
};

setIpcMainListener();

app.whenReady().then(init);
29 changes: 29 additions & 0 deletions electron/main/ipcHandlerManage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { BrowserWindow, ipcMain } from "electron";

import { IpcRenderToMain, IpcRenderToMainSync } from "../constants";
import {
childWindowMap,
clearChildWindows,
showMainWindow,
toggleDevTools,
} from "./windowManage";
export const setIpcMainListener = () => {
ipcMain.handle(IpcRenderToMain.ShowMainWindow, () => {
showMainWindow();
});

ipcMain.handle(IpcRenderToMain.ShowDevTools, () => {
toggleDevTools();
});

ipcMain.handle(IpcRenderToMain.ClearChildWindows, () => {
clearChildWindows();
});

ipcMain.on(IpcRenderToMainSync.CheckChildWindowStatus, (event, { key }) => {
const childWindow = BrowserWindow.getAllWindows().find(
(win) => win.id === childWindowMap[key],
);
event.returnValue = Boolean(childWindow);
});
};
11 changes: 11 additions & 0 deletions electron/main/shortcutManage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { globalShortcut } from "electron";

import { toggleDevTools } from "./windowManage";

export const registerShortcuts = () => {
globalShortcut.register("CmdOrCtrl+F12", toggleDevTools);
};

export const unregisterShortcuts = () => {
globalShortcut.unregisterAll();
};
7 changes: 4 additions & 3 deletions electron/main/trayManage.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import { app, Menu, Tray } from "electron";
import { t } from "i18next";
import { hideWindow, showWindow, toggleDevTools } from "./windowManage";

import { trayIcon } from "./appManage";
import { hideWindow, showMainWindow, toggleDevTools } from "./windowManage";

let appTray: Tray | null;
export const createTray = () => {
const trayMenu = Menu.buildFromTemplate([
{
label: t("showWindow"),
click: showWindow,
click: showMainWindow,
},
{
label: t("hideWindow"),
Expand All @@ -25,7 +26,7 @@ export const createTray = () => {
]);
appTray = new Tray(trayIcon);
appTray.setToolTip(app.getName());
appTray.on("click", showWindow);
appTray.on("click", showMainWindow);
appTray.setContextMenu(trayMenu);
};

Expand Down
34 changes: 32 additions & 2 deletions electron/main/windowManage.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,29 @@
import { BrowserWindow } from "electron";
import { join } from "node:path";

import { BrowserWindow } from "electron";

import { distPath, preload } from "./appManage";
import { registerShortcuts, unregisterShortcuts } from "./shortcutManage";

let mainWindow: BrowserWindow;

export const childWindowMap: { [key: string]: number } = {};

export const clearChildWindows = () => {
for (const key in childWindowMap) {
const childWindow = BrowserWindow.getAllWindows().find(
(win) => win.id === childWindowMap[key],
);
if (childWindow?.isDestroyed()) {
delete childWindowMap[key];
}
if (childWindow && !childWindow?.isDestroyed()) {
childWindow.close();
delete childWindowMap[key];
}
}
};

export function createMainWindow() {
mainWindow = new BrowserWindow({
title: "CD",
Expand All @@ -24,9 +45,18 @@ export function createMainWindow() {
} else {
mainWindow.loadFile(join(distPath, "index.html"));
}

mainWindow.on("focus", () => {
mainWindow?.flashFrame(false);
registerShortcuts();
});

mainWindow.on("blur", () => {
unregisterShortcuts();
});
}

export const showWindow = () => {
export const showMainWindow = () => {
if (mainWindow.isMinimized()) {
mainWindow.restore();
}
Expand Down
27 changes: 25 additions & 2 deletions electron/preload/index.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,34 @@
import { contextBridge, shell } from "electron";
import fs from "node:fs";

import { IElectronAPI } from "../../src/types/global";
import { contextBridge, ipcRenderer, shell } from "electron";

import {
IElectronAPI,
IpcRenderToMain,
IpcRenderToMainDataMap,
IpcRenderToMainSync,
IpcRenderToMainSyncDataMap,
} from "../constants";

const ipcInvoke = <T extends IpcRenderToMain>(
channel: T,
...arg: unknown[]
): Promise<IpcRenderToMainDataMap[T]> => {
return ipcRenderer.invoke(channel, ...arg);
};

const ipcSendSync = <T extends IpcRenderToMainSync>(
channel: T,
...arg: unknown[]
): IpcRenderToMainSyncDataMap[T] => {
return ipcRenderer.sendSync(channel, ...arg);
};

const Api: IElectronAPI = {
fileExists: fs.existsSync,
getPlatform: () => process.platform,
ipcInvoke,
ipcSendSync,
openFile: shell.openPath,
showFile: shell.showItemInFolder,
};
Expand Down
10 changes: 7 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
"scripts": {
"dev": "vite --host",
"build": "tsc && vite build",
"lint": "eslint --ext .js,.jsx,.ts,.tsx src",
"lint:fix": "eslint --ext .js,.jsx,.ts,.tsx --fix --quiet src",
"format": "prettier --write src",
"lint": "eslint --ext .js,.jsx,.ts,.tsx src electron",
"lint:fix": "eslint --ext .js,.jsx,.ts,.tsx --fix --quiet src electron",
"format": "prettier --write src electron",
"prepare": "husky install",
"preview": "vite preview"
},
Expand All @@ -18,6 +18,10 @@
]
},
"lint-staged": {
"electron": [
"prettier --write",
"eslint --fix"
],
"src/**/*.{tsx,ts}": [
"prettier --write",
"eslint --fix"
Expand Down
16 changes: 15 additions & 1 deletion src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { useState } from "react";

import { IpcRenderToMain, IpcRenderToMainSync } from "../electron/constants";

const App = () => {
// eslint has error
// const [first, setfirst] = useState("");
Expand All @@ -16,10 +18,22 @@ const App = () => {
console.log(first);
}

const ipc = () => {
window.electronAPI?.ipcInvoke(IpcRenderToMain.ShowDevTools);
const b = window.electronAPI?.ipcSendSync(
IpcRenderToMainSync.CheckChildWindowStatus,
"main",
);
console.log(b);
};

return (
<div className="flex h-screen flex-col bg-[#1B1B1F]">
<div className="app-drag h-9 min-h-9 w-full bg-[#282c34]"></div>
<div className="flex flex-1 items-center justify-center text-6xl font-bold text-sky-400">
<div
className="flex flex-1 items-center justify-center text-6xl font-bold text-sky-400"
onClick={ipc}
>
Web Template
</div>
</div>
Expand Down
7 changes: 1 addition & 6 deletions src/types/global.d.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
export interface IElectronAPI {
fileExists: (path: string) => boolean;
getPlatform: () => string;
openFile: (path: string) => Promise<string>;
showFile: (path: string) => void;
}
import { IElectronAPI } from "../../electron/constants/index";

declare global {
interface Window {
Expand Down

0 comments on commit 539518d

Please sign in to comment.