diff --git a/package.json b/package.json index 8b11e28..f85906b 100644 --- a/package.json +++ b/package.json @@ -59,6 +59,7 @@ "dependencies": { "ant-design-vue": "^1.7.5", "axios": "^0.18.1", + "download": "^8.0.0", "download-git-repo": "^3.0.2", "electron-store": "^8.0.0", "marked": "^2.0.7", diff --git a/src/main/browsers/capture.js b/src/main/browsers/capture.js new file mode 100644 index 0000000..53885b8 --- /dev/null +++ b/src/main/browsers/capture.js @@ -0,0 +1,102 @@ +const { BrowserWindow, ipcMain, globalShortcut } = require("electron"); +const os = require('os') +const path = require('path') + +module.exports = () => { + let captureWins = [] + + let init = () => { + if (captureWins.length) { + return + } + createWindow(); + }; + + let createWindow = () => { + const { screen } = require('electron'); + let displays = screen.getAllDisplays(); + captureWins = displays.map((display) => { + let captureWin = new BrowserWindow({ + // window 使用 fullscreen, mac 设置为 undefined, 不可为 false + fullscreen: os.platform() === 'win32' || undefined, + width: display.bounds.width, + height: display.bounds.height, + x: display.bounds.x, + y: display.bounds.y, + transparent: true, + frame: false, + movable: false, + resizable: false, + enableLargerThanScreen: true, + hasShadow: false, + show: false, + webPreferences: { + enableRemoteModule: true, + nodeIntegration: true, + webSecurity: false, + // devTools: false, + } + }) + captureWin.setAlwaysOnTop(true, 'screen-saver') + captureWin.setVisibleOnAllWorkspaces(true) + captureWin.setFullScreenable(false) + + captureWin.loadFile(`${__static}/plugins/capture/index.html`); + + let { x, y } = screen.getCursorScreenPoint() + if (x >= display.bounds.x && x <= display.bounds.x + display.bounds.width && y >= display.bounds.y && y <= display.bounds.y + display.bounds.height) { + captureWin.focus() + } else { + captureWin.blur() + } + + captureWin.once('ready-to-show', () => captureWin.show()); + return captureWin + }); + }; + + let getWindow = () => captureWins; + + let useCapture = () => { + globalShortcut.register('Esc', () => { + if (captureWins) { + captureWins.forEach(win => win.close()) + captureWins = [] + } + }); + + globalShortcut.register('CmdOrCtrl+Shift+S', init) + + ipcMain.on('capture-screen', (e, { type = 'start', screenId, winId, x, y } = {}) => { + if (type === 'start') { + init() + } else if (type === 'complete') { + if (captureWins) { + captureWins.forEach(win => win.close()) + captureWins = [] + } + // nothing + } else if (type === 'select') { + captureWins.forEach(win => win.webContents.send('capture-screen', { type: 'select', screenId })) + } else if (type === 'getAllDisplays') { + const { screen } = require('electron'); + let displays = screen.getAllDisplays(); + const currentScreen = displays.filter(d => d.bounds.x === x && d.bounds.y === y)[0]; + e.sender.send('getAllDisplays', { + screen: { + scaleFactor: currentScreen.scaleFactor, + id: currentScreen.id, + bounds: currentScreen.bounds, + }, + winId, + }); + } + }); + } + + return { + init: init, + getWindow: getWindow, + useCapture, + }; +}; diff --git a/src/main/browsers/index.js b/src/main/browsers/index.js index 092a8a0..d2d059d 100644 --- a/src/main/browsers/index.js +++ b/src/main/browsers/index.js @@ -1,4 +1,5 @@ module.exports = () => ({ picker: require("./picker")(), separator: require("./separate")(), + capture: require("./capture")(), }); diff --git a/src/main/common/common.js b/src/main/common/common.js index 15a6dc3..edb72b2 100644 --- a/src/main/common/common.js +++ b/src/main/common/common.js @@ -45,10 +45,6 @@ export default function init(mainWindow) { }); ipcMain.on('init-shortcut', (event) => { - globalShortcut.register('Esc', () => { - mainWindow.show(); - event.sender.send('init-rubick'); - }); globalShortcut.register('ctrl+d', () => { event.sender.send('new-window'); }); diff --git a/src/main/index.js b/src/main/index.js index a29bd62..a1353bd 100644 --- a/src/main/index.js +++ b/src/main/index.js @@ -2,6 +2,7 @@ import { app, BrowserWindow, protocol } from 'electron' import '../renderer/store' import init from './common/common'; import createTray from './tray'; +const {capture} = require("./browsers")(); /** * Set `__static` path to static files in production * https://simulatedgreg.gitbooks.io/electron-vue/content/en/using-static-assets.html @@ -19,6 +20,7 @@ function createWindow () { /** * Initial window options */ + capture.useCapture() mainWindow = new BrowserWindow({ height: 60, useContentSize: true, diff --git a/src/renderer/assets/api/config.js b/src/renderer/assets/api/config.js index a0693f7..ae43039 100644 --- a/src/renderer/assets/api/config.js +++ b/src/renderer/assets/api/config.js @@ -1,4 +1,4 @@ export default { - development: 'http://localhost:7001', + development: 'http://rubick-server.qa.91jkys.com', production: 'http://rubick-server.qa.91jkys.com', }; diff --git a/src/renderer/assets/common/constans.js b/src/renderer/assets/common/constans.js index 598994e..2bcf52a 100644 --- a/src/renderer/assets/common/constans.js +++ b/src/renderer/assets/common/constans.js @@ -5,7 +5,7 @@ const PRE_ITEM_HEIGHT = 60; const SYSTEM_PLUGINS = [ { "pluginName": "rubick 帮助文档", - "logo": "logo.png", + "logo": "https://static.91jkys.com/activity/img/4eb6f2848b064f569c28fdf8495d5ec7.png", "features": [ { "code": "help", @@ -17,7 +17,7 @@ const SYSTEM_PLUGINS = [ }, { "pluginName": "屏幕颜色拾取", - "logo": "logo.png", + "logo": "https://static.91jkys.com/activity/img/6a1b4b8a17da45d680ea30b53a91aca8.png", "features": [ { "code": "pick", @@ -26,6 +26,18 @@ const SYSTEM_PLUGINS = [ }, ], "tag": 'rubick-color', + }, + { + "pluginName": "截屏", + "logo": "https://static.91jkys.com/activity/img/b34d30b426f24eb2b77bf434b8493495.png", + "features": [ + { + "code": "shortCut", + "explain": "rubick 屏幕截取", + "cmds": [ "截屏", "shortCut" ] + }, + ], + "tag": 'rubick-screen-short-cut', } ] diff --git a/src/renderer/assets/common/system.js b/src/renderer/assets/common/system.js index 3479aae..e276bd5 100644 --- a/src/renderer/assets/common/system.js +++ b/src/renderer/assets/common/system.js @@ -9,5 +9,10 @@ export default { pick() { ipcRenderer.send('start-picker') } + }, + 'rubick-screen-short-cut': { + shortCut() { + ipcRenderer.send('capture-screen', {type: 'start'}) + } } } diff --git a/src/renderer/assets/common/utils.js b/src/renderer/assets/common/utils.js index 7e87739..3a7155e 100644 --- a/src/renderer/assets/common/utils.js +++ b/src/renderer/assets/common/utils.js @@ -4,6 +4,7 @@ import path from 'path'; import fs from 'fs'; import process from 'child_process'; import Store from 'electron-store'; +import downloadFile from 'download'; const store = new Store(); @@ -44,6 +45,21 @@ function mkdirFolder(name) { }); } +async function downloadZip(downloadRepoUrl, name) { + const plugin_path = path.join(__static, './plugins'); + const targetUrl = downloadRepoUrl ? downloadRepoUrl : `https://github.com/clouDr-f2e/${name}/archive/refs/heads/master.zip`; + if (!(await existOrNot(plugin_path))) { + await mkdirFolder(plugin_path); + } + // 基础模版所在目录,如果是初始化,则是模板名称,否则是项目名称 + const temp_dest = `${plugin_path}/${name}-master`; + // 下载模板 + if (await existOrNot(temp_dest)) { + await process.execSync(`rm -rf ${temp_dest}`); + } + await downloadFile(targetUrl, `${__static}/plugins`,{extract: true}) +} + function downloadFunc(downloadRepoUrl, name) { const targetGit = downloadRepoUrl ? downloadRepoUrl : `github:clouDr-f2e/${name}`; const plugin_path = path.join(__static, './plugins'); @@ -82,7 +98,6 @@ const sysFile = { }, getUserPlugins() { try { - console.log(store.get('user-plugins').devPlugins) return store.get('user-plugins').devPlugins; } catch (e) { return [] @@ -92,6 +107,7 @@ const sysFile = { store.delete('user-plugins'); } } +sysFile.removeAllPlugins() function mergePlugins(plugins) { return [ @@ -137,4 +153,5 @@ export { sysFile, mergePlugins, find, + downloadZip, } diff --git a/src/renderer/store/modules/main.js b/src/renderer/store/modules/main.js index 860c7b4..8f18600 100644 --- a/src/renderer/store/modules/main.js +++ b/src/renderer/store/modules/main.js @@ -7,6 +7,7 @@ import { sysFile, mergePlugins, find, + downloadZip, } from '../../assets/common/utils'; import systemMethod from '../../assets/common/system'; import fs from "fs"; @@ -179,7 +180,7 @@ const actions = { ...cmds.map((cmd) => ({ name: cmd, value: 'plugin', - icon: 'image://' + path.join(plugin.sourceFile, `../${plugin.logo}`), + icon: plugin.sourceFile ? 'image://' + path.join(plugin.sourceFile, `../${plugin.logo}`) : plugin.logo, desc: fe.explain, type: plugin.type, click: (router) => { @@ -199,8 +200,8 @@ const actions = { }); }, async downloadPlugin({commit}, payload) { - await downloadFunc(payload.gitUrl, payload.name); - const fileUrl = find(path.join(__static, `plugins/${payload.name}`)); + await downloadZip(payload.gitUrl, payload.name); + const fileUrl = find(path.join(__static, `plugins/${payload.name}-master`)); // 复制文件 const config = JSON.parse(fs.readFileSync(`${fileUrl}/plugin.json`, 'utf-8')); const pluginConfig = { @@ -221,7 +222,7 @@ const actions = { icon: 'image://' + path.join(plugin.sourceFile, `../${plugin.logo}`), }, searchValue: '', - showMain: true, + showMain: true }); ipcRenderer.send('changeWindowSize-rubick', { height: getWindowHeight(), diff --git a/static/plugins/capture/assets/audio/capture.mp3 b/static/plugins/capture/assets/audio/capture.mp3 new file mode 100644 index 0000000..2976e2f Binary files /dev/null and b/static/plugins/capture/assets/audio/capture.mp3 differ diff --git a/static/plugins/capture/assets/iconfont/demo.css b/static/plugins/capture/assets/iconfont/demo.css new file mode 100644 index 0000000..3d9cbe7 --- /dev/null +++ b/static/plugins/capture/assets/iconfont/demo.css @@ -0,0 +1,370 @@ +*{margin: 0;padding: 0;list-style: none;} +/* +KISSY CSS Reset +理念:1. reset 的目的不是清除浏览器的默认样式,这仅是部分工作。清除和重置是紧密不可分的。 +2. reset 的目的不是让默认样式在所有浏览器下一致,而是减少默认样式有可能带来的问题。 +3. reset 期望提供一套普适通用的基础样式。但没有银弹,推荐根据具体需求,裁剪和修改后再使用。 +特色:1. 适应中文;2. 基于最新主流浏览器。 +维护:玉伯, 正淳 + */ + +/** 清除内外边距 **/ +body, h1, h2, h3, h4, h5, h6, hr, p, blockquote, /* structural elements 结构元素 */ +dl, dt, dd, ul, ol, li, /* list elements 列表元素 */ +pre, /* text formatting elements 文本格式元素 */ +form, fieldset, legend, button, input, textarea, /* form elements 表单元素 */ +th, td /* table elements 表格元素 */ { + margin: 0; + padding: 0; +} + +/** 设置默认字体 **/ +body, +button, input, select, textarea /* for ie */ { + font: 12px/1.5 tahoma, arial, \5b8b\4f53, sans-serif; +} +h1, h2, h3, h4, h5, h6 { font-size: 100%; } +address, cite, dfn, em, var { font-style: normal; } /* 将斜体扶正 */ +code, kbd, pre, samp { font-family: courier new, courier, monospace; } /* 统一等宽字体 */ +small { font-size: 12px; } /* 小于 12px 的中文很难阅读,让 small 正常化 */ + +/** 重置列表元素 **/ +ul, ol { list-style: none; } + +/** 重置文本格式元素 **/ +a { text-decoration: none; } +a:hover { text-decoration: underline; } + + +/** 重置表单元素 **/ +legend { color: #000; } /* for ie6 */ +fieldset, img { border: 0; } /* img 搭车:让链接里的 img 无边框 */ +button, input, select, textarea { font-size: 100%; } /* 使得表单元素在 ie 下能继承字体大小 */ +/* 注:optgroup 无法扶正 */ + +/** 重置表格元素 **/ +table { border-collapse: collapse; border-spacing: 0; } + +/* 清除浮动 */ +.ks-clear:after, .clear:after { + content: '\20'; + display: block; + height: 0; + clear: both; +} +.ks-clear, .clear { + *zoom: 1; +} + +.main { + padding: 30px 100px; +width: 960px; +margin: 0 auto; +} +.main h1{font-size:36px; color:#333; text-align:left;margin-bottom:30px; border-bottom: 1px solid #eee;} + +.helps{margin-top:40px;} +.helps pre{ + padding:20px; + margin:10px 0; + border:solid 1px #e7e1cd; + background-color: #fffdef; + overflow: auto; +} + +.icon_lists{ + width: 100% !important; + +} + +.icon_lists li{ + float:left; + width: 100px; + height:180px; + text-align: center; + list-style: none !important; +} +.icon_lists .icon{ + font-size: 42px; + line-height: 100px; + margin: 10px 0; + color:#333; + -webkit-transition: font-size 0.25s ease-out 0s; + -moz-transition: font-size 0.25s ease-out 0s; + transition: font-size 0.25s ease-out 0s; + +} +.icon_lists .icon:hover{ + font-size: 100px; +} + + + +.markdown { + color: #666; + font-size: 14px; + line-height: 1.8; +} + +.highlight { + line-height: 1.5; +} + +.markdown img { + vertical-align: middle; + max-width: 100%; +} + +.markdown h1 { + color: #404040; + font-weight: 500; + line-height: 40px; + margin-bottom: 24px; +} + +.markdown h2, +.markdown h3, +.markdown h4, +.markdown h5, +.markdown h6 { + color: #404040; + margin: 1.6em 0 0.6em 0; + font-weight: 500; + clear: both; +} + +.markdown h1 { + font-size: 28px; +} + +.markdown h2 { + font-size: 22px; +} + +.markdown h3 { + font-size: 16px; +} + +.markdown h4 { + font-size: 14px; +} + +.markdown h5 { + font-size: 12px; +} + +.markdown h6 { + font-size: 12px; +} + +.markdown hr { + height: 1px; + border: 0; + background: #e9e9e9; + margin: 16px 0; + clear: both; +} + +.markdown p, +.markdown pre { + margin: 1em 0; +} + +.markdown > p, +.markdown > blockquote, +.markdown > .highlight, +.markdown > ol, +.markdown > ul { + width: 80%; +} + +.markdown ul > li { + list-style: circle; +} + +.markdown > ul li, +.markdown blockquote ul > li { + margin-left: 20px; + padding-left: 4px; +} + +.markdown > ul li p, +.markdown > ol li p { + margin: 0.6em 0; +} + +.markdown ol > li { + list-style: decimal; +} + +.markdown > ol li, +.markdown blockquote ol > li { + margin-left: 20px; + padding-left: 4px; +} + +.markdown code { + margin: 0 3px; + padding: 0 5px; + background: #eee; + border-radius: 3px; +} + +.markdown pre { + border-radius: 6px; + background: #f7f7f7; + padding: 20px; +} + +.markdown pre code { + border: none; + background: #f7f7f7; + margin: 0; +} + +.markdown strong, +.markdown b { + font-weight: 600; +} + +.markdown > table { + border-collapse: collapse; + border-spacing: 0px; + empty-cells: show; + border: 1px solid #e9e9e9; + width: 95%; + margin-bottom: 24px; +} + +.markdown > table th { + white-space: nowrap; + color: #333; + font-weight: 600; + +} + +.markdown > table th, +.markdown > table td { + border: 1px solid #e9e9e9; + padding: 8px 16px; + text-align: left; +} + +.markdown > table th { + background: #F7F7F7; +} + +.markdown blockquote { + font-size: 90%; + color: #999; + border-left: 4px solid #e9e9e9; + padding-left: 0.8em; + margin: 1em 0; + font-style: italic; +} + +.markdown blockquote p { + margin: 0; +} + +.markdown .anchor { + opacity: 0; + transition: opacity 0.3s ease; + margin-left: 8px; +} + +.markdown .waiting { + color: #ccc; +} + +.markdown h1:hover .anchor, +.markdown h2:hover .anchor, +.markdown h3:hover .anchor, +.markdown h4:hover .anchor, +.markdown h5:hover .anchor, +.markdown h6:hover .anchor { + opacity: 1; + display: inline-block; +} + +.markdown > br, +.markdown > p > br { + clear: both; +} + + +.hljs { + display: block; + background: white; + padding: 0.5em; + color: #333333; + overflow-x: auto; +} + +.hljs-comment, +.hljs-meta { + color: #969896; +} + +.hljs-string, +.hljs-variable, +.hljs-template-variable, +.hljs-strong, +.hljs-emphasis, +.hljs-quote { + color: #df5000; +} + +.hljs-keyword, +.hljs-selector-tag, +.hljs-type { + color: #a71d5d; +} + +.hljs-literal, +.hljs-symbol, +.hljs-bullet, +.hljs-attribute { + color: #0086b3; +} + +.hljs-section, +.hljs-name { + color: #63a35c; +} + +.hljs-tag { + color: #333333; +} + +.hljs-title, +.hljs-attr, +.hljs-selector-id, +.hljs-selector-class, +.hljs-selector-attr, +.hljs-selector-pseudo { + color: #795da3; +} + +.hljs-addition { + color: #55a532; + background-color: #eaffea; +} + +.hljs-deletion { + color: #bd2c00; + background-color: #ffecec; +} + +.hljs-link { + text-decoration: underline; +} + +pre{ + background: #fff; +} + + + + + diff --git a/static/plugins/capture/assets/iconfont/demo_fontclass.html b/static/plugins/capture/assets/iconfont/demo_fontclass.html new file mode 100644 index 0000000..09f8816 --- /dev/null +++ b/static/plugins/capture/assets/iconfont/demo_fontclass.html @@ -0,0 +1,64 @@ + + + + + + IconFont + + + + +
+

IconFont 图标

+
    + +
  • + +
    下载
    +
    .icon-xiazai
    +
  • + +
  • + +
    关闭
    +
    .icon-guanbi
    +
  • + +
  • + +
    重置
    +
    .icon-zhongzhi
    +
  • + +
  • + +
    对号
    +
    .icon-duihao
    +
  • + +
+ +

font-class引用

+
+ +

font-class是unicode使用方式的一种变种,主要是解决unicode书写不直观,语意不明确的问题。

+

与unicode使用方式相比,具有如下特点:

+
    +
  • 兼容性良好,支持ie8+,及所有现代浏览器。
  • +
  • 相比于unicode语意明确,书写更直观。可以很容易分辨这个icon是什么。
  • +
  • 因为使用class来定义图标,所以当要替换图标时,只需要修改class里面的unicode引用。
  • +
  • 不过因为本质上还是使用的字体,所以多色图标还是不支持的。
  • +
+

使用步骤如下:

+

第一步:引入项目下面生成的fontclass代码:

+ + +
<link rel="stylesheet" type="text/css" href="./iconfont.css">
+

第二步:挑选相应图标并获取类名,应用于页面:

+
<i class="iconfont icon-xxx"></i>
+
+

"iconfont"是你项目下的font-family。可以通过编辑项目查看,默认是"iconfont"。

+
+
+ + diff --git a/static/plugins/capture/assets/iconfont/demo_symbol.html b/static/plugins/capture/assets/iconfont/demo_symbol.html new file mode 100644 index 0000000..8154297 --- /dev/null +++ b/static/plugins/capture/assets/iconfont/demo_symbol.html @@ -0,0 +1,95 @@ + + + + + + IconFont + + + + + + +
+

IconFont 图标

+
    + +
  • + +
    下载
    +
    #icon-xiazai
    +
  • + +
  • + +
    关闭
    +
    #icon-guanbi
    +
  • + +
  • + +
    重置
    +
    #icon-zhongzhi
    +
  • + +
  • + +
    对号
    +
    #icon-duihao
    +
  • + +
+ + +

symbol引用

+
+ +

这是一种全新的使用方式,应该说这才是未来的主流,也是平台目前推荐的用法。相关介绍可以参考这篇文章 + 这种用法其实是做了一个svg的集合,与另外两种相比具有如下特点:

+
    +
  • 支持多色图标了,不再受单色限制。
  • +
  • 通过一些技巧,支持像字体那样,通过font-size,color来调整样式。
  • +
  • 兼容性较差,支持 ie9+,及现代浏览器。
  • +
  • 浏览器渲染svg的性能一般,还不如png。
  • +
+

使用步骤如下:

+

第一步:引入项目下面生成的symbol代码:

+
<script src="./iconfont.js"></script>
+

第二步:加入通用css代码(引入一次就行):

+
<style type="text/css">
+.icon {
+   width: 1em; height: 1em;
+   vertical-align: -0.15em;
+   fill: currentColor;
+   overflow: hidden;
+}
+</style>
+

第三步:挑选相应图标并获取类名,应用于页面:

+
<svg class="icon" aria-hidden="true">
+  <use xlink:href="#icon-xxx"></use>
+</svg>
+        
+
+ + diff --git a/static/plugins/capture/assets/iconfont/demo_unicode.html b/static/plugins/capture/assets/iconfont/demo_unicode.html new file mode 100644 index 0000000..1a81d12 --- /dev/null +++ b/static/plugins/capture/assets/iconfont/demo_unicode.html @@ -0,0 +1,102 @@ + + + + + + IconFont + + + + + +
+

IconFont 图标

+
    + +
  • + +
    下载
    +
    &#xe627;
    +
  • + +
  • + +
    关闭
    +
    &#xe66c;
    +
  • + +
  • + +
    重置
    +
    &#xe633;
    +
  • + +
  • + +
    对号
    +
    &#xeeda;
    +
  • + +
+

unicode引用

+
+ +

unicode是字体在网页端最原始的应用方式,特点是:

+
    +
  • 兼容性最好,支持ie6+,及所有现代浏览器。
  • +
  • 支持按字体的方式去动态调整图标大小,颜色等等。
  • +
  • 但是因为是字体,所以不支持多色。只能使用平台里单色的图标,就算项目里有多色图标也会自动去色。
  • +
+
+

注意:新版iconfont支持多色图标,这些多色图标在unicode模式下将不能使用,如果有需求建议使用symbol的引用方式

+
+

unicode使用步骤如下:

+

第一步:拷贝项目下面生成的font-face

+
@font-face {
+  font-family: 'iconfont';
+  src: url('iconfont.eot');
+  src: url('iconfont.eot?#iefix') format('embedded-opentype'),
+  url('iconfont.woff') format('woff'),
+  url('iconfont.ttf') format('truetype'),
+  url('iconfont.svg#iconfont') format('svg');
+}
+
+

第二步:定义使用iconfont的样式

+
.iconfont{
+  font-family:"iconfont" !important;
+  font-size:16px;font-style:normal;
+  -webkit-font-smoothing: antialiased;
+  -webkit-text-stroke-width: 0.2px;
+  -moz-osx-font-smoothing: grayscale;
+}
+
+

第三步:挑选相应图标并获取字体编码,应用于页面

+
<i class="iconfont">&#x33;</i>
+ +
+

"iconfont"是你项目下的font-family。可以通过编辑项目查看,默认是"iconfont"。

+
+
+ + + + diff --git a/static/plugins/capture/assets/iconfont/iconfont.css b/static/plugins/capture/assets/iconfont/iconfont.css new file mode 100644 index 0000000..7034fb1 --- /dev/null +++ b/static/plugins/capture/assets/iconfont/iconfont.css @@ -0,0 +1,25 @@ + +@font-face {font-family: "iconfont"; + src: url('iconfont.eot?t=1538684099545'); /* IE9*/ + src: url('iconfont.eot?t=1538684099545#iefix') format('embedded-opentype'), /* IE6-IE8 */ + url('data:application/x-font-woff;charset=utf-8;base64,d09GRgABAAAAAAWQAAsAAAAACCQAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABHU1VCAAABCAAAADMAAABCsP6z7U9TLzIAAAE8AAAARAAAAFY8nVDMY21hcAAAAYAAAABrAAABsu3anlxnbHlmAAAB7AAAAZYAAAG869Cas2hlYWQAAAOEAAAALgAAADYS2G+AaGhlYQAAA7QAAAAcAAAAJAfeA4ZobXR4AAAD0AAAAA4AAAAUFAAAAGxvY2EAAAPgAAAADAAAAAwBEAFgbWF4cAAAA+wAAAAfAAAAIAESAENuYW1lAAAEDAAAAUUAAAJtPlT+fXBvc3QAAAVUAAAAPAAAAE0pDHeHeJxjYGRgYOBikGPQYWB0cfMJYeBgYGGAAJAMY05meiJQDMoDyrGAaQ4gZoOIAgCKIwNPAHicY2BkYWCcwMDKwMHUyXSGgYGhH0IzvmYwYuRgYGBiYGVmwAoC0lxTGByeqb+7xdzwv4EhhrmBoQEozAiSAwDxJgzseJztkbsNgDAMRF8+IBSxBw0dC2SgVIzLAC5ZIdgxBUNw0bPsU+LiAkxAUnYlQzgJmJq6YfiJMvxM1bmwEImyySHtvnqHb/8q6D0/1id9Ybtnfq2j1nfKlp5jacvh2I9IczQ77sshP1MOG7MAeJwdj0FrE1EUhe95z8zLvOnM9GVC0pSZmEybmSKYTdsZRIhKXRgQLfgTpIiLoJtCdZFqf4HQnRsLhazabNxamD/gyoIb/QkK3ehqUu/4Npdzz8c795AkfvKSR0gRZUSIrQgtS/WtJN/eSirVRbs/Qr49RO0eMt75MJWjTJrEymreZEJ+9hq4vVV+vLOBRrgkHmXiJBujZhbj1XM76Oi3JjJ444SW1ufMbxp/kuZC3t2Y+Mb4x8xinB375p2a6U5gT1BU+8X9iW3rjp5Jj0j8v/WpmJNNAVGA1ggpEg8DWF3kyIb4IR7qSOnywgnr4kn5RddDR+xoFYnD8oKHZr8errLBlNhhir8E0XUpL8Uv6rEYQnlQa+18jTtzdRZxknJKq80hI8jTzW/T6VnjtCg+NWf7R3Mp50fZ81t6ZVnovb8vXzzA9f6BH5xNi+L1h8pkZD1Worli71qPd39XedzjvTihZaJBnA6SEdo1ZF0oWApftb347tZ6HgwOdezqxav60jN15fRd5yf+uDd6bnmlBf0D1bBUzQAAeJxjYGRgYADi+Y6Xrsbz23xl4GZhAIHrd6YeRtD//7IwMIO4HAxMIAoAaF8MWwAAeJxjYGRgYG7438AQw8IAAkCSkQEVsAIARwsCbnicY2FgYGBBwwABBAAVAAAAAAAAAFYAggC6AN54nGNgZGBgYGUwZ2BmAAEmIOYCQgaG/2A+AwAOdQFWAHicZY9NTsMwEIVf+gekEqqoYIfkBWIBKP0Rq25YVGr3XXTfpk6bKokjx63UA3AejsAJOALcgDvwSCebNpbH37x5Y08A3OAHHo7fLfeRPVwyO3INF7gXrlN/EG6QX4SbaONVuEX9TdjHM6bCbXRheYPXuGL2hHdhDx18CNdwjU/hOvUv4Qb5W7iJO/wKt9Dx6sI+5l5XuI1HL/bHVi+cXqnlQcWhySKTOb+CmV7vkoWt0uqca1vEJlODoF9JU51pW91T7NdD5yIVWZOqCas6SYzKrdnq0AUb5/JRrxeJHoQm5Vhj/rbGAo5xBYUlDowxQhhkiMro6DtVZvSvsUPCXntWPc3ndFsU1P9zhQEC9M9cU7qy0nk6T4E9XxtSdXQrbsuelDSRXs1JErJCXta2VELqATZlV44RelzRiT8oZ0j/AAlabsgAAAB4nGNgYoAALgbsgJWRiZGZkYWRlZGNga0iM7EqMZMtvTQxLymToyojPy+9KiOTLaU0MyMxn4EBAMN8Cyw=') format('woff'), + url('iconfont.ttf?t=1538684099545') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/ + url('iconfont.svg?t=1538684099545#iconfont') format('svg'); /* iOS 4.1- */ +} + +.iconfont { + font-family:"iconfont" !important; + font-size:16px; + font-style:normal; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.icon-xiazai:before { content: "\e627"; } + +.icon-guanbi:before { content: "\e66c"; } + +.icon-zhongzhi:before { content: "\e633"; } + +.icon-duihao:before { content: "\eeda"; } + diff --git a/static/plugins/capture/assets/iconfont/iconfont.eot b/static/plugins/capture/assets/iconfont/iconfont.eot new file mode 100644 index 0000000..1e71066 Binary files /dev/null and b/static/plugins/capture/assets/iconfont/iconfont.eot differ diff --git a/static/plugins/capture/assets/iconfont/iconfont.js b/static/plugins/capture/assets/iconfont/iconfont.js new file mode 100644 index 0000000..4d8c980 --- /dev/null +++ b/static/plugins/capture/assets/iconfont/iconfont.js @@ -0,0 +1 @@ +(function(window){var svgSprite='';var script=function(){var scripts=document.getElementsByTagName("script");return scripts[scripts.length-1]}();var shouldInjectCss=script.getAttribute("data-injectcss");var ready=function(fn){if(document.addEventListener){if(~["complete","loaded","interactive"].indexOf(document.readyState)){setTimeout(fn,0)}else{var loadFn=function(){document.removeEventListener("DOMContentLoaded",loadFn,false);fn()};document.addEventListener("DOMContentLoaded",loadFn,false)}}else if(document.attachEvent){IEContentLoaded(window,fn)}function IEContentLoaded(w,fn){var d=w.document,done=false,init=function(){if(!done){done=true;fn()}};var polling=function(){try{d.documentElement.doScroll("left")}catch(e){setTimeout(polling,50);return}init()};polling();d.onreadystatechange=function(){if(d.readyState=="complete"){d.onreadystatechange=null;init()}}}};var before=function(el,target){target.parentNode.insertBefore(el,target)};var prepend=function(el,target){if(target.firstChild){before(el,target.firstChild)}else{target.appendChild(el)}};function appendSvg(){var div,svg;div=document.createElement("div");div.innerHTML=svgSprite;svgSprite=null;svg=div.getElementsByTagName("svg")[0];if(svg){svg.setAttribute("aria-hidden","true");svg.style.position="absolute";svg.style.width=0;svg.style.height=0;svg.style.overflow="hidden";prepend(svg,document.body)}}if(shouldInjectCss&&!window.__iconfont__svg__cssinject__){window.__iconfont__svg__cssinject__=true;try{document.write("")}catch(e){console&&console.log(e)}}ready(appendSvg)})(window) \ No newline at end of file diff --git a/static/plugins/capture/assets/iconfont/iconfont.svg b/static/plugins/capture/assets/iconfont/iconfont.svg new file mode 100644 index 0000000..cfebe6b --- /dev/null +++ b/static/plugins/capture/assets/iconfont/iconfont.svg @@ -0,0 +1,38 @@ + + + + + +Created by iconfont + + + + + + + + + + + + + + + + + + + + + + + diff --git a/static/plugins/capture/assets/iconfont/iconfont.ttf b/static/plugins/capture/assets/iconfont/iconfont.ttf new file mode 100644 index 0000000..7d18bc0 Binary files /dev/null and b/static/plugins/capture/assets/iconfont/iconfont.ttf differ diff --git a/static/plugins/capture/assets/iconfont/iconfont.woff b/static/plugins/capture/assets/iconfont/iconfont.woff new file mode 100644 index 0000000..5d9f432 Binary files /dev/null and b/static/plugins/capture/assets/iconfont/iconfont.woff differ diff --git a/static/plugins/capture/capture-editor.js b/static/plugins/capture/capture-editor.js new file mode 100644 index 0000000..357fe6b --- /dev/null +++ b/static/plugins/capture/capture-editor.js @@ -0,0 +1,411 @@ +const Event = require('events') +const { getCurrentScreen } = require('./utils') + +const CREATE_RECT = 1 +const MOVING_RECT = 2 +const RESIZE = 3 + +const ANCHORS = [ + { row: 'x', col: 'y', cursor: 'nwse-resize' }, + { row: '', col: 'y', cursor: 'ns-resize' }, + { row: 'r', col: 'y', cursor: 'nesw-resize' }, + + { row: 'x', col: '', cursor: 'ew-resize' }, + { row: 'r', col: '', cursor: 'ew-resize' }, + + { row: 'x', col: 'b', cursor: 'nesw-resize' }, + { row: '', col: 'b', cursor: 'ns-resize' }, + { row: 'r', col: 'b', cursor: 'nwse-resize' }, +] + +class CaptureEditor extends Event { + + constructor($canvas, $bg, imageSrc) { + super() + this.$canvas = $canvas + this.imageSrc = imageSrc + this.disabled = false + let currentScreen; + + (async () => { + currentScreen = await getCurrentScreen(); + this.scaleFactor = currentScreen.scaleFactor + this.screenWidth = currentScreen.bounds.width + this.screenHeight = currentScreen.bounds.height + this.init().then(() => { + // console.log('init') + }) + })(); + this.$bg = $bg + this.ctx = $canvas.getContext('2d') + + this.onMouseDown = this.onMouseDown.bind(this) + this.onMouseMove = this.onMouseMove.bind(this) + this.onMouseUp = this.onMouseUp.bind(this) + } + + async init() { + this.$bg.style.backgroundImage = `url(${this.imageSrc})` + this.$bg.style.backgroundSize = `${this.screenWidth}px ${this.screenHeight}px` + let canvas = document.createElement('canvas') + let ctx = canvas.getContext('2d') + let img = await new Promise((resolve) => { + let img = new Image() + img.src = this.imageSrc + if (img.complete) { + resolve(img) + } else { + img.onload = () => resolve(img) + } + }) + + canvas.width = img.width + canvas.height = img.height + ctx.drawImage(img, 0, 0) + this.bgCtx = ctx + + document.addEventListener('mousedown', this.onMouseDown) + document.addEventListener('mousemove', this.onMouseMove) + document.addEventListener('mouseup', this.onMouseUp) + } + + onMouseDown(e) { + if (this.disabled) { + return + } + this.mouseDown = true + const { pageX, pageY } = e + if (this.selectRect) { + const { + w, h, x, y, r, b, + } = this.selectRect + if (this.selectAnchorIndex !== -1) { + this.startPoint = { + x: pageX, + y: pageY, + moved: false, + selectRect: { + w, h, x, y, r, b, + }, + rawRect: { + w, h, x, y, r, b, + }, + } + this.action = RESIZE + return + } + this.startPoint = { + x: e.pageX, + y: e.pageY, + moved: false, + } + if (pageX > x && pageX < r && pageY > y && pageY < b) { + this.action = MOVING_RECT + this.startDragRect = { + x: pageX, + y: pageY, + selectRect: { + x, y, w, h, r, b, + }, + } + } else { + this.action = CREATE_RECT + } + } else { + this.action = CREATE_RECT + this.startPoint = { + x: e.pageX, + y: e.pageY, + moved: false, + } + e.stopPropagation() + e.preventDefault() + } + } + + onMouseDrag(e) { + if (this.disabled) { + return + } + e.stopPropagation() + e.preventDefault() + + const { pageX, pageY } = e + let startDragging + let selectRect = this.selectRect + if (!this.startPoint.moved) { + if (Math.abs(this.startPoint.x - pageX) > 10 || Math.abs(this.startPoint.y - pageY) > 10) { + this.startPoint.moved = true + startDragging = true + } + } + if (!this.startPoint.moved) { + return + } + + if (this.action === MOVING_RECT) { + // 移动选区 + if (startDragging) { + this.emit('start-dragging', selectRect) + } + this.emit('dragging', selectRect) + const { w, h } = selectRect + const { x: startX, y: startY } = this.startPoint + let newX = this.startDragRect.selectRect.x + pageX - startX + let newY = this.startDragRect.selectRect.y + pageY - startY + let newR = newX + w + let newB = newY + h + if (newX < 0) { + newX = 0 + newR = w + } else if (newR > this.screenWidth) { + newR = this.screenWidth + newX = newR - w + } + if (newY < 0) { + newY = 0 + newB = h + } else if (newB > this.screenHeight) { + newB = this.screenHeight + newY = newB - h + } + this.selectRect = { + w, + h, + x: newX, + y: newY, + r: newR, + b: newB, + } + this.drawRect() + } else if (this.action === RESIZE) { + this.emit('dragging', selectRect) + let { row, col } = ANCHORS[this.selectAnchorIndex] + if (row) { + this.startPoint.rawRect[row] = this.startPoint.selectRect[row] + pageX - this.startPoint.x + selectRect.x = this.startPoint.rawRect.x + selectRect.r = this.startPoint.rawRect.r + if (selectRect.x > selectRect.r) { + let x = selectRect.r + selectRect.r = selectRect.x + selectRect.x = x + } + selectRect.w = selectRect.r - selectRect.x + this.startPoint.rawRect.w = selectRect.w + } + if (col) { + this.startPoint.rawRect[col] = this.startPoint.selectRect[col] + pageY - this.startPoint.y + selectRect.y = this.startPoint.rawRect.y + selectRect.b = this.startPoint.rawRect.b + + if (selectRect.y > selectRect.b) { + let y = selectRect.b + selectRect.b = selectRect.y + selectRect.y = y + } + selectRect.h = selectRect.b - selectRect.y + this.startPoint.rawRect.h = selectRect.h + } + this.drawRect() + } else { + // 生成选区 + const { pageX, pageY } = e + let x, y, w, h, r, b + if (this.startPoint.x > pageX) { + x = pageX + r = this.startPoint.x + } else { + r = pageX + x = this.startPoint.x + } + if (this.startPoint.y > pageY) { + y = pageY + b = this.startPoint.y + } else { + b = pageY + y = this.startPoint.y + } + w = r - x + h = b - y + + + this.selectRect = { + x, y, w, h, r, b, + } + selectRect = this.selectRect + if (startDragging) { + this.emit('start-dragging', selectRect) + } + this.emit('dragging', selectRect) + this.drawRect(x, y, w, h) + } + + + } + + drawRect() { + if (this.disabled) { + return + } + if (!this.selectRect) { + this.$canvas.style.display = 'none' + return + } + const { + x, y, w, h, + } = this.selectRect + + const scaleFactor = this.scaleFactor + let margin = 7 + let radius = 5 + this.$canvas.style.left = `${x - margin}px` + this.$canvas.style.top = `${y - margin}px` + this.$canvas.style.width = `${w + margin * 2}px` + this.$canvas.style.height = `${h + margin * 2}px` + this.$canvas.style.display = 'block' + this.$canvas.width = (w + margin * 2) * scaleFactor + this.$canvas.height = (h + margin * 2) * scaleFactor + + if (w && h) { + let imageData = this.bgCtx.getImageData(x * scaleFactor, y * scaleFactor, w * scaleFactor, h * scaleFactor) + this.ctx.putImageData(imageData, margin * scaleFactor, margin * scaleFactor) + } + this.ctx.fillStyle = '#ffffff' + this.ctx.strokeStyle = '#67bade' + this.ctx.lineWidth = 2 * this.scaleFactor + + this.ctx.strokeRect(margin * scaleFactor, margin * scaleFactor, w * scaleFactor, h * scaleFactor) + this.drawAnchors(w, h, margin, scaleFactor, radius) + } + + drawAnchors(w, h, margin, scaleFactor, radius) { + if (this.disabled) { + return + } + if (this.mouseDown && this.action === CREATE_RECT) { + this.anchors = null + return + } + this.ctx.beginPath() + let anchors = [ + [0, 0], + [w * this.scaleFactor / 2, 0], + [w * this.scaleFactor, 0], + + [0, h * this.scaleFactor / 2], + [w * this.scaleFactor, h * this.scaleFactor / 2], + + [0, h * this.scaleFactor], + [w * this.scaleFactor / 2, h * this.scaleFactor], + [w * this.scaleFactor, h * this.scaleFactor], + ] + this.anchors = anchors.map(([x, y]) => [this.selectRect.x + x / scaleFactor, this.selectRect.y + y / scaleFactor]) + anchors.forEach(([x, y], i) => { + this.ctx.arc(x + margin * scaleFactor, y + margin * scaleFactor, radius * scaleFactor, 0, 2 * Math.PI) + let next = anchors[(i + 1) % anchors.length] + this.ctx.moveTo(next[0] + margin * scaleFactor + radius * scaleFactor, next[1] + margin * scaleFactor) + }) + this.ctx.closePath() + this.ctx.fill() + this.ctx.stroke() + } + + onMouseMove(e) { + if (this.disabled) { + return + } + if (this.mouseDown) { + this.onMouseDrag(e) + return + } + this.selectAnchorIndex = -1 + if (this.selectRect) { + const { pageX, pageY } = e + const { + x, y, r, b, + } = this.selectRect + let selectAnchor, selectIndex = -1 + if (this.anchors) { + this.anchors.forEach(([x, y], i) => { + if (Math.abs(pageX - x) <= 10 && Math.abs(pageY - y) <= 10) { + selectAnchor = [x, y] + selectIndex = i + } + }) + } + if (selectAnchor) { + this.selectAnchorIndex = selectIndex + document.body.style.cursor = ANCHORS[selectIndex].cursor + this.emit('moving') + return + } + if (pageX > x && pageX < r && pageY > y && pageY < b) { + document.body.style.cursor = 'move' + } else { + document.body.style.cursor = 'auto' + } + this.emit('moving') + } + } + + onMouseUp(e) { + if (this.disabled) { + return + } + if (!this.mouseDown) { + return + } + this.mouseDown = false + e.stopPropagation() + e.preventDefault() + this.emit('mouse-up') + if (!this.startPoint.moved) { + this.emit('end-moving') + return + } + this.emit('end-dragging') + this.drawRect() + this.startPoint = null + } + + getImageUrl() { + const scaleFactor = this.scaleFactor + const { + x, y, w, h, + } = this.selectRect + if (w && h) { + let imageData = this.bgCtx.getImageData(x * scaleFactor, y * scaleFactor, w * scaleFactor, h * scaleFactor) + let canvas = document.createElement('canvas') + canvas.width = w + canvas.height = h + let ctx = canvas.getContext('2d') + ctx.putImageData(imageData, 0, 0) + return canvas.toDataURL() + } + return '' + } + + disable() { + this.disabled = true + } + + enable() { + this.disabled = false + } + + reset() { + this.anchors = null + this.startPoint = null + this.selectRect = null + this.startDragRect = null + this.selectAnchorIndex = -1 + this.drawRect() + this.emit('reset') + } +} + + +exports.CaptureEditor = CaptureEditor +exports.CREATE_RECT = CREATE_RECT +exports.MOVING_RECT = MOVING_RECT +exports.RESIZE = RESIZE diff --git a/static/plugins/capture/capture-renderer.js b/static/plugins/capture/capture-renderer.js new file mode 100644 index 0000000..7766129 --- /dev/null +++ b/static/plugins/capture/capture-renderer.js @@ -0,0 +1,139 @@ +const {ipcRenderer, clipboard, nativeImage, remote} = require('electron') + +const fs = require('fs') +const { getScreenSources } = require('./desktop-capturer') +const { CaptureEditor } = require('./capture-editor') +const { getCurrentScreen } = require('./utils') + +const $canvas = document.getElementById('js-canvas') +const $bg = document.getElementById('js-bg') +const $sizeInfo = document.getElementById('js-size-info') +const $toolbar = document.getElementById('js-toolbar') +const $jsMask= document.getElementById('js-mask') + +const $btnClose = document.getElementById('js-tool-close') +const $btnOk = document.getElementById('js-tool-ok') +const $btnSave = document.getElementById('js-tool-save') +const $btnReset = document.getElementById('js-tool-reset') + +let currentScreen; + +(async () => { + currentScreen = await getCurrentScreen(); +})(); +// 右键取消截屏 +document.body.addEventListener('mousedown', (e) => { + if (e.button === 2) { + window.close() + } +}, true) + +// console.time('capture') +getScreenSources({}, (imgSrc) => { + $jsMask.style.display = 'block'; + let capture = new CaptureEditor($canvas, $bg, imgSrc) + + let onDrag = (selectRect) => { + $toolbar.style.display = 'none' + $sizeInfo.style.display = 'block' + $sizeInfo.innerText = `${selectRect.w} * ${selectRect.h}` + if (selectRect.y > 35) { + $sizeInfo.style.top = `${selectRect.y - 30}px` + } else { + $sizeInfo.style.top = `${selectRect.y + 10}px` + } + $sizeInfo.style.left = `${selectRect.x}px` + } + capture.on('start-dragging', onDrag) + capture.on('dragging', onDrag) + + let onDragEnd = () => { + if (capture.selectRect) { + ipcRenderer.send('capture-screen', { + type: 'select', + screenId: currentScreen.id, + }) + const { + r, b, + } = capture.selectRect + $toolbar.style.display = 'flex' + $toolbar.style.top = `${b + 15}px` + $toolbar.style.right = `${window.screen.width - r}px` + } + } + capture.on('end-dragging', onDragEnd) + + ipcRenderer.on('capture-screen', (e, { type, screenId }) => { + if (type === 'select') { + if (screenId && screenId !== currentScreen.id) { + capture.disable() + } + } + }) + + capture.on('reset', () => { + $toolbar.style.display = 'none' + $sizeInfo.style.display = 'none' + }) + + $btnClose.addEventListener('click', () => { + ipcRenderer.send('capture-screen', { + type: 'complete', + }) + window.close() + }) + + $btnReset.addEventListener('click', () => { + capture.reset() + }) + + let selectCapture = () => { + if (!capture.selectRect) { + return + } + let url = capture.getImageUrl() + remote.getCurrentWindow().hide() + clipboard.writeImage(nativeImage.createFromDataURL(url)) + ipcRenderer.send('capture-screen', { + type: 'complete', + url, + }) + + } + $btnOk.addEventListener('click', selectCapture) + + $btnSave.addEventListener('click', () => { + let url = capture.getImageUrl() + + remote.getCurrentWindow().hide() + remote.dialog.showSaveDialog({ + filters: [{ + name: 'Images', + extensions: ['png', 'jpg', 'gif'], + }], + }).then(({filePath}) => { + if (filePath) { + fs.writeFile(filePath, new Buffer(url.replace('data:image/png;base64,', ''), 'base64'), () => { + ipcRenderer.send('capture-screen', { + type: 'complete' + }) + window.close() + }) + } else { + ipcRenderer.send('capture-screen', { + type: 'complete' + }) + window.close() + } + }) + }) + + window.addEventListener('keypress', (e) => { + if (e.code === 'Enter') { + selectCapture() + } + }) +}) + + + diff --git a/static/plugins/capture/desktop-capturer.js b/static/plugins/capture/desktop-capturer.js new file mode 100644 index 0000000..55ff665 --- /dev/null +++ b/static/plugins/capture/desktop-capturer.js @@ -0,0 +1,17 @@ +const {desktopCapturer} = require('electron'); + +exports.getScreenSources = async ({ types = ['screen'] } = {}, callback) => { + let curScreen = await getCurrentScreen(); + let screenWidth = curScreen.bounds.width + let screenHeight = curScreen.bounds.height + desktopCapturer.getSources({ + types: ['screen'], + thumbnailSize: { + width: screenWidth * curScreen.scaleFactor, + height: screenHeight * curScreen.scaleFactor, + } + }).then((sources) => { + let imgSrc = sources.filter(s => s.id.indexOf(curScreen.id) >= 0)[0].thumbnail.toDataURL() + callback(imgSrc) + }) +} diff --git a/static/plugins/capture/index.html b/static/plugins/capture/index.html new file mode 100644 index 0000000..77aa1f9 --- /dev/null +++ b/static/plugins/capture/index.html @@ -0,0 +1,88 @@ + + + + + + + Document + + + + +
+
+ +
+
+
+
+
+
+
+ + + + diff --git a/static/plugins/capture/logo.png b/static/plugins/capture/logo.png new file mode 100644 index 0000000..50eddd8 Binary files /dev/null and b/static/plugins/capture/logo.png differ diff --git a/static/plugins/capture/utils.js b/static/plugins/capture/utils.js new file mode 100644 index 0000000..4070040 --- /dev/null +++ b/static/plugins/capture/utils.js @@ -0,0 +1,20 @@ +const { remote, ipcRenderer } = require('electron'); + +let currentWindow = remote.getCurrentWindow() + +exports.getCurrentScreen = () => { + let { x, y } = currentWindow.getBounds(); + ipcRenderer.send('capture-screen', { + type: 'getAllDisplays', + winId: currentWindow.id, + x, + y, + }); + return new Promise(resolve => { + ipcRenderer.on('getAllDisplays', (e, { type, winId, screen}) => { + if (winId === currentWindow.id) { + resolve(screen) + } + }) + }) +}