import { app, BrowserWindow, screen, globalShortcut, ipcMain, nativeImage as NativeImage, Menu, Tray, } from "electron"; import fs from "fs"; import tmp from 'tmp'; import Screenshots from "electron-screenshots"; import { join } from "path"; import logo, { getNoMessageTrayIcon } from "./logo"; import TSDD_FONFIG from "./confing"; let forceQuit = false; let mainWindow: any; let isMainWindowFocusedWhenStartScreenshot = false; let screenshots: any; let tray: any; let trayIcon: any; let settings: any = {}; let screenShotWindowId = 0; let isFullScreen = false; let isOsx = process.platform === "darwin"; let isWin = !isOsx; const isDevelopment = process.env.NODE_ENV === "development"; let mainMenu: (Electron.MenuItemConstructorOptions | Electron.MenuItem)[] = [ { label: "唐僧叨叨", submenu: [ { label: `关于唐僧叨叨`, }, { label: "服务", role: "services" }, { type: "separator" }, { label: "退出", accelerator: "Command+Q", click() { forceQuit = true; mainWindow = null; setTimeout(() => { app.exit(0); }, 1000); }, }, ], }, { label: "编辑", submenu: [ { role: "undo", label: "撤销", }, { role: "redo", label: "重做", }, { type: "separator", }, { role: "cut", label: "剪切", }, { role: "copy", label: "复制", }, { role: "paste", label: "粘贴", }, { role: "pasteAndMatchStyle", label: "粘贴并匹配样式", }, { role: "delete", label: "删除", }, { role: "selectAll", label: "全选", }, ], }, { label: "显示", submenu: [ { label: isFullScreen ? "全屏" : "退出全屏", accelerator: "Shift+Cmd+F", click() { isFullScreen = !isFullScreen; mainWindow.show(); mainWindow.setFullScreen(isFullScreen); }, }, { label: "切换会话", accelerator: "Shift+Cmd+M", click() { mainWindow.show(); mainWindow.webContents.send("show-conversations"); }, }, { type: "separator", }, { type: "separator", }, { role: "toggleDevTools", label: "切换开发者工具", }, { role: "togglefullscreen", label: "切换全屏", }, ], }, { label: "窗口", role: "window", submenu: [ { label: "最小化", role: "minimize", }, { label: "关闭窗口", role: "close", }, ], }, { label: "帮助", role: "help", submenu: [ { type: "separator", }, { role: "reload", label: "刷新", }, { role: "forceReload", label: "强制刷新", }, ], }, ]; let trayMenu: Electron.MenuItemConstructorOptions[] = [ { label: "显示窗口", click() { let isVisible = mainWindow.isVisible(); isVisible ? mainWindow.hide() : mainWindow.show(); }, }, { type: "separator", }, { label: "退出", accelerator: "Command+Q", click() { forceQuit = true; mainWindow = null; setTimeout(() => { app.exit(0); }, 1000); }, }, ]; function updateTray(unread = 0): any { settings.showOnTray = true; // linux 系统不支持 tray if (process.platform === "linux") { return; } if (settings.showOnTray) { let contextmenu = Menu.buildFromTemplate(trayMenu); if (!trayIcon) { trayIcon = getNoMessageTrayIcon(); } setTimeout(() => { if (!tray) { // Init tray icon tray = new Tray(trayIcon); if (process.platform === "linux") { tray.setContextMenu(contextmenu); } tray.on("right-click", () => { tray.popUpContextMenu(contextmenu); }); tray.on("click", () => { mainWindow.show(); }); } if (isOsx) { tray.setTitle(unread > 0 ? " " + unread : ""); } tray.setImage(trayIcon); }); } else { if (!tray) return; tray.destroy(); tray = null; } } function createMenu() { var menu = Menu.buildFromTemplate(mainMenu); if (isOsx) { Menu.setApplicationMenu(menu); } else { mainWindow.setMenu(null); } } function regShortcut() { globalShortcut.register("CommandOrControl+shift+a", () => { isMainWindowFocusedWhenStartScreenshot = mainWindow.isFocused(); console.log( "isMainWindowFocusedWhenStartScreenshot", mainWindow.isFocused() ); screenshots.startCapture(); }); // 打开所有窗口控制台 globalShortcut.register("ctrl+shift+i", () => { let windows = BrowserWindow.getAllWindows(); windows.forEach((win: any) => win.openDevTools()); }); } const createMainWindow = async () => { const NODE_ENV = process.env.NODE_ENV; const { width, height } = screen.getPrimaryDisplay().workAreaSize; mainWindow = new BrowserWindow({ width: 960, height: 600, minWidth: 960, minHeight: 600, // frame: true, // * app边框(包括关闭,全屏,最小化按钮的导航栏) @false: 隐藏 // titleBarStyle: "hidden", // transparent: true, // * app 背景透明 hasShadow: false, // * app 边框阴影 show: false, // 启动窗口时隐藏,直到渲染进程加载完成「ready-to-show 监听事件」 再显示窗口,防止加载时闪烁 resizable: true, // 禁止手动修改窗口尺寸 webPreferences: { // 加载脚本 preload: join(__dirname, "..", "preload/index"), nodeIntegration: true, }, // frame: !isWin, }); mainWindow.center(); mainWindow.once("ready-to-show", () => { mainWindow.show(); // 显示窗口 mainWindow.focus(); }); mainWindow.on("close", (e: any) => { if (forceQuit || !tray) { mainWindow = null; } else { e.preventDefault(); if (mainWindow.isFullScreen()) { mainWindow.setFullScreen(false); mainWindow.once("leave-full-screen", () => mainWindow.hide()); } else { mainWindow.hide(); } } }); if (NODE_ENV === "development") mainWindow.loadURL("http://localhost:3000"); if (NODE_ENV !== "development") { process.env.DIST_ELECTRON = join(__dirname, "../"); const WEB_URL = join(process.env.DIST_ELECTRON, "../build/index.html"); mainWindow.loadFile(WEB_URL); } ipcMain.on("screenshots-start", (event, args) => { console.log("main voip-message event", args); screenShotWindowId = event.sender.id; screenshots.startCapture(); }); createMenu(); }; function onDeepLink(url: string) { console.log("onOpenDeepLink", url); mainWindow.webContents.send("deep-link", url); } app.setName(TSDD_FONFIG.name); isDevelopment && app.dock && app.dock.setIcon(logo); app.on("open-url", (event, url) => { onDeepLink(url); }); // 单例模式启动 const gotTheLock = app.requestSingleInstanceLock(); if (!gotTheLock) { app.quit(); } else { app.on("second-instance", (event, argv) => { if (mainWindow) { mainWindow.show(); if (mainWindow.isMinimized()) { mainWindow.restore(); } mainWindow.focus(); } }); } app.on("ready", () => { regShortcut(); createMainWindow(); // 创建窗口 screenshots = new Screenshots({ singleWindow: true, }); const onScreenShotEnd = (result?: any) => { console.log( "onScreenShotEnd", isMainWindowFocusedWhenStartScreenshot, screenShotWindowId ); if (isMainWindowFocusedWhenStartScreenshot) { if (result) { mainWindow.webContents.send("screenshots-ok", result); } mainWindow.show(); isMainWindowFocusedWhenStartScreenshot = false; } else if (screenShotWindowId) { let windows = BrowserWindow.getAllWindows(); let tms = windows.filter( (win) => win.webContents.id === screenShotWindowId ); if (tms.length > 0) { if (result) { tms[0].webContents.send("screenshots-ok", result); } tms[0].show(); } screenShotWindowId = 0; } }; // 截图添加快捷键esc screenshots.on('windowCreated', ($win) => { $win.on('focus', () => { globalShortcut.register('esc', () => { if ($win?.isFocused()) { screenshots.endCapture(); } }); }); $win.on('blur', () => { globalShortcut.unregister('esc'); }); }); // 点击确定按钮回调事件 screenshots.on("ok", (e, buffer, bounds) => { let filename = tmp.tmpNameSync() + '.png'; let image = NativeImage.createFromBuffer(buffer); fs.writeFileSync(filename, image.toPNG()); console.log("screenshots ok", e); onScreenShotEnd({ filePath: filename }); }); // 点击取消按钮回调事件 screenshots.on("cancel", (e: any) => { // 执行了preventDefault // 点击取消不会关闭截图窗口 // e.preventDefault() // console.log('capture', 'cancel2') console.log("screenshots cancel", e); onScreenShotEnd(); }); // 点击保存按钮回调事件 screenshots.on("save", (e, { viewer }) => { console.log("screenshots save", e); onScreenShotEnd(); }); try { updateTray(); } catch (e) { // do nothing console.log("==updateTray==", e); } }); app.on("activate", () => { if (!mainWindow) { return createMainWindow(); } if (!mainWindow.isVisible()) { mainWindow.show(); } }); app.on("before-quit", () => { forceQuit = true; if (!tray) return; tray.destroy(); tray = null; }); // 除了 macOS 外,当所有窗口都被关闭的时候退出程序。 macOS窗口全部关闭时,dock中程序不会退出 app.on("window-all-closed", () => { process.platform !== "darwin" && app.quit(); });