import { app, nativeImage, BrowserWindow, clipboard, globalShortcut, ipcMain, Notification, screen, TouchBar, session } from "electron"; import { exec, spawn } from "child_process"; import robot from "robotjs"; import Api from "./api"; import ioHook from "iohook"; import { throttle, commonConst } from "./utils"; import path from "path"; import fs from "fs"; import mito from "./monitor"; const browsers = require("../browsers")(); const { picker, separator, superPanel, login } = browsers; class Listener { constructor() { this.optionPlugin = {}; this.isWin = process.platform === "win32"; } getSelectedContent() { return new Promise(resolve => { const lastText = clipboard.readText("clipboard"); // todo 缓存文件 clipboard.clear(); // 复制选中文案 if (commonConst.macOS()) { robot.keyTap("c", "command"); } else { robot.keyTap("c", "control"); } setTimeout(() => { // 延时一定时间才能从剪切板内读取到内容 const text = clipboard.readText("clipboard") || ""; const fileUrl = clipboard.read("public.file-url"); if (this.isWin) { // todo https://github.com/njzydark/Aragorn/blob/afe4a60972b4255dd417480ca6aca2af1fd8e637/packages/aragorn-app-main/src/uploaderManager.ts#L88 } // 如果之前是文案,则回填 clipboard.writeText(lastText); resolve({ text, fileUrl }); }, 300); }); } registerShortCut(mainWindow) { const config = global.opConfig.get(); globalShortcut.unregisterAll(); // 注册偏好快捷键 globalShortcut.register(config.perf.shortCut.showAndHidden, () => { const { x, y } = screen.getCursorScreenPoint(); const currentDisplay = screen.getDisplayNearestPoint({ x, y }); const wx = parseInt( currentDisplay.workArea.x + currentDisplay.workArea.width / 2 - 400 ); const wy = parseInt( currentDisplay.workArea.y + currentDisplay.workArea.height / 2 - 200 ); mainWindow.setAlwaysOnTop(true); mainWindow.setVisibleOnAllWorkspaces(true, { visibleOnFullScreen: true }); mainWindow.focus(); mainWindow.setVisibleOnAllWorkspaces(false, { visibleOnFullScreen: true }); mainWindow.setPosition(wx, wy); mainWindow.show(); }); globalShortcut.register(config.perf.shortCut.separate, () => { mainWindow.webContents.send("new-window"); }); globalShortcut.register(config.perf.shortCut.quit, () => { mainWindow.webContents.send("init-rubick"); mainWindow.show(); }); // 注册自定义全局快捷键 config.global.forEach(sc => { if (!sc.key || !sc.value) return; globalShortcut.register(sc.key, () => { mainWindow.webContents.send("global-short-key", sc.value); }); }); } init(mainWindow) { this.fn = throttle(({ x, y }, picker) => { const { scaleFactor } = screen.getDisplayNearestPoint({ x, y }); const img = robot.screen.capture( x - parseInt(5 / scaleFactor), y - parseInt(5 / scaleFactor), 10, 10 ); const colors = {}; for (let i = 0; i < 9; i++) { colors[i] = {}; for (let j = 0; j < 9; j++) { colors[i][j] = img.colorAt(j, i); } } picker.getWindow().webContents.send("updatePicker", colors); }, 100); this.setAutoLogin(); this.colorPicker(); this.initPlugin(); this.lockScreen(); this.separate(); this.initCapture(); this.login(mainWindow); this.initTouchBar(mainWindow); this.superPanel(mainWindow); this.reRegisterShortCut(mainWindow); this.changeSize(mainWindow); this.changePos(mainWindow); this.msgTrigger(mainWindow); this.windowMoveInit(mainWindow); } colorPicker() { // 拾色器 ipcMain.on("start-picker", () => { // 开启输入侦测 ioHook.start(false); !this.isWin && ioHook.load(); picker.init(); picker.getWindow().on("close", () => { ioHook.stop(); ioHook.removeAllListeners(); !this.isWin && ioHook.unload(); }); let pos = this.getPos(robot.getMousePos()); picker .getWindow() .setPosition(parseInt(pos.x) + 10, parseInt(pos.y) + 10); const img = robot.screen.capture( parseInt(pos.x) - 5, parseInt(pos.y) - 5, 9, 9 ); const colors = {}; for (let i = 0; i < 9; i++) { colors[i] = {}; for (let j = 0; j < 9; j++) { colors[i][j] = img.colorAt(j, i); } } picker.getWindow().webContents.send("updatePicker", colors); ipcMain.on("closePicker", () => { this.closePicker(); }); ioHook.on("mousemove", e => { let { x, y } = this.getPos(e); if (!picker.getWindow()) return; picker.getWindow().setPosition(parseInt(x) + 10, parseInt(y) + 10); this.fn(e, picker); }); ioHook.on("mouseup", e => { if (e.button === 1) { let x = e.x; let y = e.y; const color = "#" + robot.getPixelColor(parseInt(x), parseInt(y)); clipboard.writeText( "#" + robot.getPixelColor(parseInt(x), parseInt(y)) ); new Notification({ title: "Quicker 通知", body: `${color} 已保存到剪切板` }).show(); this.closePicker(); } }); ioHook.on("mouseup", e => { if (e.button === 3) { this.closePicker(); } }); }); } login(mainWindow) { login.init(mainWindow); ipcMain.on("login", (e, args) => { const win = login.getWindow(); console.log("win", win); if (win === null || win === undefined) { login.createWindow(mainWindow); } else { win.show() } }); } closePicker() { if (picker.getWindow()) { ipcMain.removeListener("closePicker", this.closePicker); picker.getWindow().close(); } } initTouchBar(mainWindow) { if (!commonConst.macOS()) return; const { TouchBarButton, TouchBarGroup, TouchBarPopover } = TouchBar; let items = []; let system = []; ipcMain.on("pluginInit", (e, args) => { this.optionPlugin = args; items = args.plugins .map(item => { const iconPath = path.join(item.sourceFile, "../", item.logo); if (!fs.existsSync(iconPath)) return false; const icon = nativeImage .createFromPath(iconPath) .resize({ width: 20, height: 20 }); return new TouchBarButton({ icon, click() { mainWindow.webContents.send("superPanel-openPlugin", { cmd: item.features[0].cmds.filter( cmd => typeof cmd === "string" )[0], plugin: item, feature: item.features[0] }); } }); }) .filter(Boolean); system = args.plugins .map(item => { if (item.type === "system") { return new TouchBarButton({ icon: nativeImage .createFromDataURL(item.logo) .resize({ width: 20, height: 20 }), click() { mainWindow.webContents.send("superPanel-openPlugin", { cmd: item.features[0].cmds.filter( cmd => typeof cmd === "string" )[0], plugin: item, feature: item.features[0] }); } }); } return false; }) .filter(Boolean); const plugin = new TouchBarPopover({ items: new TouchBar({ items }), label: "已安装插件", showCloseButton: true }); const monitor = new TouchBarPopover({ items: mito.touchBar, label: "系统监控", showCloseButton: true }); const touchBar = new TouchBar({ items: [plugin, monitor, ...system] }); mainWindow.setTouchBar(touchBar); mito.start(mainWindow); }); } initPlugin() { ipcMain.on("optionPlugin", (e, args) => { this.optionPlugin = args; }); } lockScreen() { // 锁屏 ipcMain.on("lock-screen", () => { const lockCommands = { darwin: "/System/Library/CoreServices/ScreenSaverEngine.app/Contents/MacOS/ScreenSaverEngine", win32: "rundll32.exe user32.dll, LockWorkStation", linux: "(hash gnome-screensaver-command 2>/dev/null && gnome-screensaver-command -l) || (hash dm-tool 2>/dev/null && dm-tool lock)" }; exec(lockCommands[process.platform]); }); } superPanel(mainWindow) { // 长按右击呼起超级面板 superPanel.init(mainWindow); ipcMain.on("right-down", async () => { const copyResult = await this.getSelectedContent(); let win = superPanel.getWindow(); win.webContents.send("trigger-super-panel", { ...copyResult, optionPlugin: this.optionPlugin.plugins }); const pos = this.getPos(robot.getMousePos()); win.setPosition(parseInt(pos.x), parseInt(pos.y)); win.setAlwaysOnTop(true); win.setVisibleOnAllWorkspaces(true, { visibleOnFullScreen: true }); win.focus(); win.setVisibleOnAllWorkspaces(false, { visibleOnFullScreen: true }); win.show(); }); } getPos(point) { return this.isWin ? screen.screenToDipPoint({ x: point.x, y: point.y }) : point; } reRegisterShortCut(mainWindow) { ipcMain.on("re-register", (event, arg) => { this.setAutoLogin(); this.registerShortCut(mainWindow); }); } setAutoLogin() { // 设置开机启动 const config = global.opConfig.get(); app.setLoginItemSettings({ openAtLogin: config.perf.common.start, openAsHidden: true }); } changeSize(mainWindow) { // 修改窗口尺寸 ipcMain.on("changeWindowSize-rubick", (event, arg) => { mainWindow.setSize(arg.width || 920, arg.height); }); } changePos(mainWindow) { // 修改窗口位置 ipcMain.on("changeWindowPos-rubick", (event, arg) => { mainWindow.setPosition(arg.x, arg.y); }); } msgTrigger(mainWindow) { // 响应 preload.js 事件 ipcMain.on("msg-trigger", async (event, arg) => { const window = arg.winId ? BrowserWindow.fromId(arg.winId) : mainWindow; const operators = arg.type.split("."); let fn = Api; operators.forEach(op => { fn = fn[op]; }); const data = await fn(arg, window); event.sender.send(`msg-back-${arg.type}`, data); }); } separate() { // 窗口分离 ipcMain.on("new-window", (event, arg) => { const opts = { ...arg, searchType: "subWindow" }; separator.init(JSON.stringify(opts)); }); } initCapture() { ipcMain.on("capture-screen", () => { if (process.platform === "darwin") { spawn("/usr/sbin/screencapture", ["-c", "-i", "-r"], { detached: !0 }); } // todo win }); } windowMoveInit(win) { let hasInit = false; ipcMain.on("window-move", () => { let bounds = win.getBounds(); if (!hasInit) { hasInit = true; ioHook.start(false); !this.isWin && ioHook.load(); const winPosition = win.getPosition(); const winStartPosition = { x: winPosition[0], y: winPosition[1] }; const mouseStartPosition = screen.getCursorScreenPoint(); ioHook.on("mousedrag", e => { const cursorPosition = screen.getCursorScreenPoint(); const dx = winStartPosition.x + cursorPosition.x - mouseStartPosition.x; const dy = winStartPosition.y + cursorPosition.y - mouseStartPosition.y; bounds.x = parseInt(dx); bounds.y = parseInt(dy); win.setBounds(bounds); }); ioHook.on("mouseup", e => { hasInit = false; ioHook.stop(); ioHook.removeAllListeners(); !this.isWin && ioHook.unload(); }); } }); } } export default Listener;