feat: 支持文本模板,系统命令

This commit is contained in:
muwoo 2021-06-10 20:54:28 +08:00
parent 31e7e17cc9
commit 31d57fc404
29 changed files with 377 additions and 205 deletions

View File

@ -1,9 +0,0 @@
const notice = require('./operators/notice');
const network = require('./operators/network');
const common = require('./operators/common');
window.rubick = {
notice,
network,
common,
}

View File

@ -1,7 +0,0 @@
const { shell } = require('electron');
module.exports = {
openInBrowser(url) {
shell.openExternal(url);
}
}

View File

@ -1,71 +0,0 @@
const {ipcRenderer} = require("electron");
const AnyProxy = require('anyproxy');
const options = {
port: 8001,
webInterface: {
enable: true,
webPort: 8002
},
forceProxyHttps: false,
wsIntercept: false, // 不开启websocket代理
silent: true
};
class Network {
constructor() {
this.mockList = [];
this.proxyServer = null;
}
initNetwork(op, {
beforeSendRequest,
beforeSendResponse,
success,
}) {
if (op === 'start') {
if (!this.proxyServer || !this.proxyServer.recorder) {
const _this = this;
options.rule = {
*beforeSendRequest(requestDetail) {
if (beforeSendRequest) {
return beforeSendRequest(requestDetail);
}
return requestDetail
},
*beforeSendResponse (requestDetail, responseDetail) {
if (beforeSendResponse) {
return beforeSendResponse(requestDetail, responseDetail);
}
return responseDetail;
}
};
this.proxyServer = new AnyProxy.ProxyServer(options);
this.proxyServer.once('ready', () => {
console.log('启动完成');
success && success(this.proxyServer);
});
}
this.proxyServer.start();
} else {
AnyProxy.utils.systemProxyMgr.disableGlobalProxy('http');
AnyProxy.utils.systemProxyMgr.disableGlobalProxy('https');
this.proxyServer.close();
success && success();
}
}
getIPAddress() {
const interfaces = require('os').networkInterfaces();
for (const devName in interfaces) {
const iface = interfaces[devName];
for (let i = 0; i < iface.length; i++) {
const alias = iface[i];
if (alias.family === 'IPv4' && alias.address !== '127.0.0.1' && !alias.internal) {
return alias.address;
}
}
}
}
}
module.exports = new Network();

View File

@ -1,11 +0,0 @@
module.exports = {
system({title, body}, cb) {
const myNotification = new Notification(title, {
body
});
myNotification.onclick = () => {
cb();
}
}
}

View File

@ -14,7 +14,8 @@
"pack": "npm run pack:main && npm run pack:renderer", "pack": "npm run pack:main && npm run pack:renderer",
"pack:main": "cross-env NODE_ENV=production webpack --progress --colors --config .electron-vue/webpack.main.config.js", "pack:main": "cross-env NODE_ENV=production webpack --progress --colors --config .electron-vue/webpack.main.config.js",
"pack:renderer": "cross-env NODE_ENV=production webpack --progress --colors --config .electron-vue/webpack.renderer.config.js", "pack:renderer": "cross-env NODE_ENV=production webpack --progress --colors --config .electron-vue/webpack.renderer.config.js",
"postinstall": "" "postinstall": "",
"rebuild": " ./node_modules/.bin/electron-rebuild"
}, },
"build": { "build": {
"asar": false, "asar": false,
@ -59,12 +60,16 @@
"ant-design-vue": "^1.7.5", "ant-design-vue": "^1.7.5",
"anyproxy": "^4.1.3", "anyproxy": "^4.1.3",
"axios": "^0.18.1", "axios": "^0.18.1",
"chokidar": "^3.5.1",
"download-git-repo": "^3.0.2", "download-git-repo": "^3.0.2",
"electron-store": "^8.0.0", "electron-store": "^8.0.0",
"marked": "^2.0.7", "marked": "^2.0.7",
"node-fetch": "^2.6.1", "node-fetch": "^2.6.1",
"osx-mouse": "git+https://github.com/Toinane/osx-mouse.git",
"puppeteer-core": "^10.0.0", "puppeteer-core": "^10.0.0",
"puppeteer-in-electron": "^3.0.3",
"query-string": "^7.0.0", "query-string": "^7.0.0",
"robotjs": "git+ssh://git@github.com/Toinane/robotjs.git",
"uuid": "^8.3.2", "uuid": "^8.3.2",
"vue": "^2.5.16", "vue": "^2.5.16",
"vue-electron": "^1.0.6", "vue-electron": "^1.0.6",
@ -92,15 +97,16 @@
"electron-builder": "22.10.5", "electron-builder": "22.10.5",
"electron-debug": "^1.5.0", "electron-debug": "^1.5.0",
"electron-devtools-installer": "^2.2.4", "electron-devtools-installer": "^2.2.4",
"electron-rebuild": "^2.3.5",
"file-loader": "^1.1.11", "file-loader": "^1.1.11",
"html-webpack-plugin": "^3.2.0", "html-webpack-plugin": "^3.2.0",
"less": "^4.1.1",
"less-loader": "^5.0.0",
"listr": "^0.14.3", "listr": "^0.14.3",
"mini-css-extract-plugin": "0.4.0", "mini-css-extract-plugin": "0.4.0",
"multispinner": "^0.2.1", "multispinner": "^0.2.1",
"node-loader": "^0.6.0", "node-loader": "^0.6.0",
"node-sass": "^4.9.2",
"react": "^17.0.2", "react": "^17.0.2",
"sass-loader": "^7.0.3",
"style-loader": "^0.21.0", "style-loader": "^0.21.0",
"url-loader": "^1.0.1", "url-loader": "^1.0.1",
"vue-html-loader": "^1.2.4", "vue-html-loader": "^1.2.4",

View File

@ -0,0 +1,4 @@
module.exports = () => ({
picker: require("./picker")(),
separator: require("./separate")(),
});

View File

@ -0,0 +1,42 @@
const { BrowserWindow, nativeImage } = require("electron");
module.exports = () => {
let win;
let init = () => {
if (win === null || win === undefined) {
createWindow();
}
};
let createWindow = () => {
win = new BrowserWindow({
frame: false,
autoHideMenuBar: true,
width: 100,
height: 100,
transparent: true,
alwaysOnTop: true,
resizable: false,
focusable: true,
hasShadow: false,
// icon: nativeImage.createFromPath(`${dirname}/build/icon.png`),
webPreferences: {
nodeIntegration: true,
devTools: false,
},
});
win.loadURL(`file://${__static}/plugins/picker/index.html`);
win.on("closed", () => {
win = undefined;
});
};
let getWindow = () => win;
return {
init: init,
getWindow: getWindow,
};
};

View File

@ -0,0 +1,46 @@
const {stringify} = require('query-string');
const { BrowserWindow, nativeImage } = require("electron");
module.exports = () => {
let win;
let init = (opts) => {
createWindow(opts);
};
let createWindow = (opts) => {
const winURL = process.env.NODE_ENV === 'development'
? `http://localhost:9080/#/plugin?${stringify(opts)}`
: `${__dirname}/index.html`
win = new BrowserWindow({
height: 600,
useContentSize: true,
width: 800,
titleBarStyle: 'hiddenInset',
title: '拉比克',
show: false,
webPreferences: {
webSecurity: false,
enableRemoteModule: true,
backgroundThrottling: false,
webviewTag: true,
nodeIntegration: true // 在网页中集成Node
}
});
process.env.NODE_ENV === 'development' ? win.loadURL(winURL) : win.loadFile(winURL, {
hash: `#/plugin?${stringify(opts)}`,
});
win.once('ready-to-show', () => win.show());
win.on("closed", () => {
win = undefined;
});
};
let getWindow = () => win;
return {
init: init,
getWindow: getWindow,
};
};

View File

@ -1,71 +0,0 @@
import {globalShortcut, ipcMain, BrowserWindow} from 'electron';
import {stringify} from 'query-string';
import Api from './api';
import path from 'path';
export default function init(mainWindow) {
ipcMain.on('changeWindowSize', (event, arg) => {
mainWindow.setSize(arg.width || 788, arg.height);
});
mainWindow.on('blur', () => {
// mainWindow.hide();
});
globalShortcut.register('Alt+R', () => {
mainWindow.show();
});
ipcMain.on('init-shortcut', (event) => {
globalShortcut.register('Esc', () => {
mainWindow.show();
event.sender.send('init-rubick');
});
globalShortcut.register('ctrl+d', () => {
event.sender.send('new-window');
});
})
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);
});
ipcMain.on('new-window', (event, arg) => {
const opts = {
...arg,
searchType: 'subWindow',
}
const winURL = process.env.NODE_ENV === 'development'
? `http://localhost:9080/#/plugin?${stringify(opts)}`
: `${__dirname}/index.html`
const win = new BrowserWindow({
height: 600,
useContentSize: true,
width: 788,
titleBarStyle: 'hiddenInset',
title: '拉比克',
show: false,
webPreferences: {
webSecurity: false,
enableRemoteModule: true,
backgroundThrottling: false,
webviewTag: true,
nodeIntegration: true // 在网页中集成Node
}
});
process.env.NODE_ENV === 'development' ? win.loadURL(winURL) : win.loadFile(winURL, {
hash: `#/plugin?${stringify(opts)}`,
});
win.once('ready-to-show', () => win.show());
})
}

View File

@ -1,5 +1,5 @@
import {app, BrowserWindow} from 'electron'; import {app, BrowserWindow} from 'electron';
import {getlocalDataFile, saveData, getData} from './common/utils'; import {getlocalDataFile, saveData, getData} from './utils';
import path from "path"; import path from "path";
const puppeteer = require("puppeteer-core"); const puppeteer = require("puppeteer-core");

112
src/main/common/common.js Normal file
View File

@ -0,0 +1,112 @@
import {
globalShortcut,
ipcMain,
BrowserWindow,
clipboard,
Notification,
} from 'electron';
import Api from './api';
import robot from 'robotjs';
const browsers = require("../browsers")();
const mouseEvents = require("osx-mouse");
const {picker, separator} = browsers;
let closePicker = (newColor) => {
if (picker.getWindow()) {
ipcMain.removeListener("closePicker", closePicker);
ipcMain.removeListener("pickerRequested", (event) => {});
picker.getWindow().close();
}
};
export default function init(mainWindow) {
const mouseTrack = mouseEvents();
let down_time = 0;
mouseTrack.on('right-down', () => {
down_time = Date.now();
})
mouseTrack.on('right-up', () => {
if ((Date.now() - down_time) > 1000) {
new Notification({ title: 'Rubick 通知', body: '长按了' }).show();
}
});
ipcMain.on('changeWindowSize-rubick', (event, arg) => {
mainWindow.setSize(arg.width || 788, arg.height);
});
mainWindow.on('blur', () => {
// mainWindow.hide();
});
globalShortcut.register('Alt+R', () => {
mainWindow.show();
});
ipcMain.on('init-shortcut', (event) => {
globalShortcut.register('Esc', () => {
mainWindow.show();
event.sender.send('init-rubick');
});
globalShortcut.register('ctrl+d', () => {
event.sender.send('new-window');
});
})
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);
window.webContents.send(`msg-back-${arg.type}`, data);
});
ipcMain.on('new-window', (event, arg) => {
const opts = {
...arg,
searchType: 'subWindow',
}
separator.init(opts);
});
ipcMain.on('start-picker', () => {
const mouseTrack = mouseEvents();
picker.init();
picker.getWindow().on("close", () => {
mouseTrack.destroy();
});
mouseTrack.on('move', (x, y) => {
if (!picker.getWindow()) return;
let color = "#" + robot.getPixelColor(parseInt(x), parseInt(y));
picker.getWindow().setPosition(parseInt(x) - 50, parseInt(y) - 50);
picker.getWindow().webContents.send("updatePicker", color);
})
mouseTrack.on("left-up", (x, y) => {
const color = "#" + robot.getPixelColor(parseInt(x), parseInt(y));
clipboard.writeText("#" + robot.getPixelColor(parseInt(x), parseInt(y)));
new Notification({ title: 'Rubick 通知', body: `${color} 已保存到剪切板` }).show();
closePicker();
});
let pos = robot.getMousePos();
picker
.getWindow()
.setPosition(parseInt(pos.x) - 50, parseInt(pos.y) - 50);
picker
.getWindow()
.webContents.send(
"updatePicker",
robot.getPixelColor(pos.x, pos.y)
);
ipcMain.on("closePicker", closePicker);
mouseTrack.on("right-up", closePicker);
})
}

View File

@ -1,6 +1,6 @@
import { app, BrowserWindow, protocol } from 'electron' import { app, BrowserWindow, protocol } from 'electron'
import '../renderer/store' import '../renderer/store'
import init from './common'; import init from './common/common';
import createTray from './tray'; import createTray from './tray';
/** /**
* Set `__static` path to static files in production * Set `__static` path to static files in production

View File

@ -16,7 +16,7 @@
id="search" id="search"
:placeholder="subPlaceHolder && selected && selected.key === 'plugin-container' ? subPlaceHolder : 'Hi, Rubick'" :placeholder="subPlaceHolder && selected && selected.key === 'plugin-container' ? subPlaceHolder : 'Hi, Rubick'"
class="main-input" class="main-input"
@change="onSearch" @change="e => onSearch({value: e.target.value})"
:value="searchValue" :value="searchValue"
:maxLength="selected && selected.key !== 'plugin-container' ? 0 : 1000" :maxLength="selected && selected.key !== 'plugin-container' ? 0 : 1000"
> >
@ -49,7 +49,7 @@
<a-input <a-input
:placeholder="subPlaceHolder" :placeholder="subPlaceHolder"
class="sub-input" class="sub-input"
@change="onSearch" @change="(e) => onSearch({value: e.target.value, searchType: $route.query.searchType})"
:value="searchValue" :value="searchValue"
></a-input> ></a-input>
</div> </div>
@ -84,8 +84,6 @@ export default {
const searchNd = document.getElementById('search'); const searchNd = document.getElementById('search');
searchNd && searchNd.addEventListener('keydown', this.checkNeedInit) searchNd && searchNd.addEventListener('keydown', this.checkNeedInit)
}, },
beforeDestroy() {
},
methods: { methods: {
...mapActions('main', ['onSearch', 'showMainUI']), ...mapActions('main', ['onSearch', 'showMainUI']),
...mapMutations('main', ['commonUpdate']), ...mapMutations('main', ['commonUpdate']),
@ -104,8 +102,9 @@ export default {
this.commonUpdate({ this.commonUpdate({
selected: null, selected: null,
showMain: false, showMain: false,
options: [],
}); });
ipcRenderer.send('changeWindowSize', { ipcRenderer.send('changeWindowSize-rubick', {
height: getWindowHeight([]), height: getWindowHeight([]),
}); });
this.$router.push({ this.$router.push({
@ -167,7 +166,7 @@ export default {
} }
}; };
</script> </script>
<style lang="scss"> <style lang="less">
* { * {
margin: 0; margin: 0;
padding: 0; padding: 0;

View File

@ -2,8 +2,36 @@ const WINDOW_MAX_HEIGHT = 600;
const WINDOW_MIN_HEIGHT = 60; const WINDOW_MIN_HEIGHT = 60;
const PRE_ITEM_HEIGHT = 60; const PRE_ITEM_HEIGHT = 60;
const SYSTEM_PLUGINS = [
{
"pluginName": "rubick 帮助文档",
"logo": "logo.png",
"features": [
{
"code": "help",
"explain": "rubick 帮助文档",
"cmds": [ "Help", "帮助" ]
},
],
"tag": 'rubick-help',
},
{
"pluginName": "屏幕颜色拾取",
"logo": "logo.png",
"features": [
{
"code": "pick",
"explain": "rubick 帮助文档",
"cmds": [ "取色", "拾色", 'Pick color' ]
},
],
"tag": 'rubick-color',
}
]
export { export {
WINDOW_MAX_HEIGHT, WINDOW_MAX_HEIGHT,
WINDOW_MIN_HEIGHT, WINDOW_MIN_HEIGHT,
PRE_ITEM_HEIGHT, PRE_ITEM_HEIGHT,
SYSTEM_PLUGINS,
} }

View File

@ -0,0 +1,13 @@
import {shell, ipcRenderer} from 'electron';
export default {
'rubick-help': {
help() {
shell.openExternal('https://u.tools/docs/guide/about-uTools.html')
}
},
'rubick-color': {
pick() {
ipcRenderer.send('start-picker')
}
}
}

View File

@ -1,4 +1,4 @@
import {WINDOW_MAX_HEIGHT, WINDOW_MIN_HEIGHT, PRE_ITEM_HEIGHT} from './constans'; import {WINDOW_MAX_HEIGHT, WINDOW_MIN_HEIGHT, PRE_ITEM_HEIGHT, SYSTEM_PLUGINS} from './constans';
import download from 'download-git-repo'; import download from 'download-git-repo';
import path from 'path'; import path from 'path';
import fs from 'fs'; import fs from 'fs';
@ -14,7 +14,6 @@ function getWindowHeight(searchList) {
} }
function searchKeyValues(lists, value){ function searchKeyValues(lists, value){
console.log(lists);
return lists.filter(item => item.indexOf(value) >= 0) return lists.filter(item => item.indexOf(value) >= 0)
} }
@ -90,9 +89,24 @@ const sysFile = {
} }
} }
function mergePlugins(plugins) {
return [
...plugins,
...SYSTEM_PLUGINS.map(plugin => {
return {
...plugin,
status: true,
sourceFile: '',
type: 'system',
}
}),
]
}
export { export {
getWindowHeight, getWindowHeight,
searchKeyValues, searchKeyValues,
downloadFunc, downloadFunc,
sysFile, sysFile,
mergePlugins,
} }

View File

@ -46,7 +46,7 @@ export default {
}, },
} }
</script> </script>
<style lang="scss"> <style lang="less">
.fava-btn { .fava-btn {
cursor: pointer; cursor: pointer;
&:hover { &:hover {

View File

@ -10,6 +10,10 @@
<script> <script>
import path from 'path'; import path from 'path';
import {mapMutations, mapState} from 'vuex'; import {mapMutations, mapState} from 'vuex';
import {remote} from "electron";
const currentWindow = remote.getCurrentWindow();
const winId = currentWindow.id;
export default { export default {
name: "index.vue", name: "index.vue",
@ -20,7 +24,7 @@ export default {
webview: null, webview: null,
query: this.$route.query, query: this.$route.query,
config: {}, config: {},
templatePath: `File://${path.join(__static, './doc-tpl.html')}?code=${JSON.parse(this.$route.query.detail).code}&targetFile=${encodeURIComponent(this.$route.query.sourceFile)}`, templatePath: `File://${path.join(__static, './plugins/doc/doc-tpl.html')}?code=${JSON.parse(this.$route.query.detail).code}&targetFile=${encodeURIComponent(this.$route.query.sourceFile)}`,
} }
}, },
mounted() { mounted() {
@ -90,9 +94,9 @@ export default {
} }
</script> </script>
<style lang="scss"> <style lang="less">
#webview { #webview {
width: 100%; width: 100%;
height: calc(100vh - 60px); height: calc(~'100vh - 60px');
} }
</style> </style>

View File

@ -45,7 +45,7 @@ export default {
} }
</script> </script>
<style lang="scss"> <style lang="less">
.main-input { .main-input {
-webkit-app-region: drag; -webkit-app-region: drag;
height: 60px !important; height: 60px !important;

View File

@ -110,9 +110,9 @@ export default {
} }
</script> </script>
<style lang="scss"> <style lang="less">
.dev-container { .dev-container {
height: calc(100vh - 110px); height: calc(~'100vh - 110px');
.dev-detail { .dev-detail {
display: flex; display: flex;
align-items: flex-start; align-items: flex-start;

View File

@ -74,9 +74,9 @@ export default {
} }
</script> </script>
<style lang="scss"> <style lang="less">
.market { .market {
height: calc(100vh - 110px); height: calc(~'100vh - 110px');
background: #fff; background: #fff;
padding: 20px; padding: 20px;
box-sizing: border-box; box-sizing: border-box;

View File

@ -95,9 +95,9 @@ export default {
} }
</script> </script>
<style lang="scss"> <style lang="less">
.dev-container { .dev-container {
height: calc(100vh - 110px); height: calc(~'100vh - 110px');
overflow: auto; overflow: auto;
.dev-detail { .dev-detail {
display: flex; display: flex;

View File

@ -1,6 +1,13 @@
import {clipboard, ipcRenderer, remote} from "electron"; import {clipboard, ipcRenderer, remote} from "electron";
import { v4 as uuidv4 } from 'uuid'; import { v4 as uuidv4 } from 'uuid';
import {getWindowHeight, searchKeyValues, downloadFunc, sysFile} from '../../assets/common/utils'; import {
getWindowHeight,
searchKeyValues,
downloadFunc,
sysFile,
mergePlugins,
} from '../../assets/common/utils';
import systemMethod from '../../assets/common/system';
import fs from "fs"; import fs from "fs";
import path from 'path'; import path from 'path';
@ -10,7 +17,7 @@ const state = {
showMain: false, showMain: false,
current: ['market'], current: ['market'],
searchValue: '', searchValue: '',
devPlugins: sysFile.getUserPlugins() || [], devPlugins: mergePlugins(sysFile.getUserPlugins() || []),
subPlaceHolder: '', subPlaceHolder: '',
} }
@ -48,7 +55,7 @@ const mutations = {
const actions = { const actions = {
showMainUI ({ commit, state }, paylpad) { showMainUI ({ commit, state }, paylpad) {
ipcRenderer.send('changeWindowSize', { ipcRenderer.send('changeWindowSize-rubick', {
height: getWindowHeight(), height: getWindowHeight(),
}); });
setTimeout(() => { setTimeout(() => {
@ -85,9 +92,9 @@ const actions = {
commit('commonUpdate', {searchValue: ''}); commit('commonUpdate', {searchValue: ''});
return; return;
} }
const value = paylpad.target.value; const value = paylpad.value;
// 在插件界面 // 在插件界面
if(state.selected && state.selected.key === 'plugin-container') { if((state.selected && state.selected.key === 'plugin-container') || paylpad.searchType === 'subWindow') {
commit('commonUpdate', {searchValue: value}) commit('commonUpdate', {searchValue: value})
return; return;
} }
@ -131,7 +138,7 @@ const actions = {
}, },
current: ['dev'], current: ['dev'],
}); });
ipcRenderer.send('changeWindowSize', { ipcRenderer.send('changeWindowSize-rubick', {
height: getWindowHeight(), height: getWindowHeight(),
}); });
router.push('/home/dev') router.push('/home/dev')
@ -149,7 +156,7 @@ const actions = {
] ]
}); });
// 调整窗口大小 // 调整窗口大小
ipcRenderer.send('changeWindowSize', { ipcRenderer.send('changeWindowSize-rubick', {
height: getWindowHeight(state.options), height: getWindowHeight(state.options),
}); });
return return
@ -184,7 +191,7 @@ const actions = {
commit('commonUpdate', { commit('commonUpdate', {
options options
}); });
ipcRenderer.send('changeWindowSize', { ipcRenderer.send('changeWindowSize-rubick', {
height: getWindowHeight(state.options), height: getWindowHeight(state.options),
}); });
}, },
@ -212,9 +219,24 @@ const actions = {
searchValue: '', searchValue: '',
showMain: true, showMain: true,
}); });
ipcRenderer.send('changeWindowSize', { ipcRenderer.send('changeWindowSize-rubick', {
height: getWindowHeight(), height: getWindowHeight(),
}); });
if (plugin.type === 'system') {
systemMethod[plugin.tag][feature.code]()
commit('commonUpdate', {
selected: null,
showMain: false,
options: [],
});
ipcRenderer.send('changeWindowSize-rubick', {
height: getWindowHeight([]),
});
router.push({
path: '/home',
});
return;
}
router.push({ router.push({
path: '/plugin', path: '/plugin',
query: { query: {

View File

@ -2,7 +2,6 @@ import doc from './doc.js';
function getQueryVariable(variable) { function getQueryVariable(variable) {
var query = window.location.search.substring(1); var query = window.location.search.substring(1);
var vars = query.split("&"); var vars = query.split("&");
console.log(vars);
for (var i=0;i<vars.length;i++) { for (var i=0;i<vars.length;i++) {
var pair = vars[i].split("="); var pair = vars[i].split("=");
if(pair[0] == variable){return pair[1];} if(pair[0] == variable){return pair[1];}
@ -15,10 +14,10 @@ const routes = [
] ]
const router = new VueRouter({ const router = new VueRouter({
routes // (缩写) 相当于 routes: routes routes
}) })
const app = new Vue({ new Vue({
el: '#app', el: '#app',
data: { data: {
config: window.exports, config: window.exports,

View File

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Picker</title>
<link rel="stylesheet" href="./picker.css" />
<script defer src="./picker.js"></script>
</head>
<body>
<section id="picker"></section>
</body>
</html>

View File

@ -0,0 +1,17 @@
* {
margin: 0;
padding: 0;
}
body {
background: transparent;
cursor: crosshair;
overflow: hidden;
}
#picker {
width: 100px;
height: 100px;
border-radius: 120px;
box-sizing: border-box;
}

View File

@ -0,0 +1,23 @@
const { ipcRenderer } = require("electron");
document.querySelector(
"#picker"
).style.border = `10px solid rgba(200, 200, 200, 0.3)`;
document.addEventListener(
"DOMContentLoaded",
() => ipcRenderer.send("pickerRequested"),
false
);
document.addEventListener(
"keydown",
(event) => {
if (event.key === "Escape") ipcRenderer.send("closePicker");
},
false
);
ipcRenderer.on("updatePicker", (event, color) => {
document.querySelector("#picker").style.border = `10px solid ${color}`;
});