mirror of
https://github.com/rubickCenter/rubick
synced 2025-06-28 16:42:47 +08:00
ref: 项目基础开发
This commit is contained in:
parent
d9c0f5ed7b
commit
02d9c30bc9
@ -61,6 +61,8 @@
|
||||
"axios": "^0.18.1",
|
||||
"download-git-repo": "^3.0.2",
|
||||
"electron-store": "^8.0.0",
|
||||
"marked": "^2.0.7",
|
||||
"query-string": "^7.0.0",
|
||||
"uuid": "^8.3.2",
|
||||
"vue": "^2.5.16",
|
||||
"vue-electron": "^1.0.6",
|
||||
|
@ -1,11 +0,0 @@
|
||||
import { ipcMain } from 'electron';
|
||||
|
||||
const init = () => {
|
||||
ipcMain.on('msg-trigger', async (event, arg) => {
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
export default () => {
|
||||
init();
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
export const getlocalDataFile = () => {
|
||||
let localDataFile = process.env.HOME;
|
||||
if (!localDataFile) {
|
||||
localDataFile = process.env.LOCALAPPDATA;
|
||||
}
|
||||
return localDataFile;
|
||||
};
|
@ -1,9 +1,16 @@
|
||||
import {app} from 'electron';
|
||||
import {getlocalDataFile, saveData, getData} from './common/utils';
|
||||
import path from "path";
|
||||
|
||||
const appPath = path.join(getlocalDataFile());
|
||||
const dbPath = path.join(appPath, './db.json');
|
||||
|
||||
export default {
|
||||
getPath(arg) {
|
||||
return app.getPath(arg.name);
|
||||
},
|
||||
hideMainWindow(arg, mainWindow) {
|
||||
console.log(111, mainWindow)
|
||||
mainWindow.hide();
|
||||
},
|
||||
showMainWindow(arg, mainWindow) {
|
||||
@ -13,6 +20,87 @@ export default {
|
||||
return arg
|
||||
},
|
||||
setExpendHeight({height}, mainWindow) {
|
||||
console.log(height);
|
||||
mainWindow.setSize(788, height);
|
||||
},
|
||||
db: {
|
||||
put({data}) {
|
||||
data._rev = '';
|
||||
let dbData = getData(dbPath) || [];
|
||||
let target = [];
|
||||
console.log(data, dbData);
|
||||
dbData.some((d, i) => {
|
||||
if (d._id === data._id) {
|
||||
target = [d, i]
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
// 更新
|
||||
if (target[0]) {
|
||||
dbData[target[1]] = data;
|
||||
} else {
|
||||
dbData.push(data);
|
||||
}
|
||||
saveData(dbPath, dbData);
|
||||
return {
|
||||
id: data.id,
|
||||
ok: true,
|
||||
rev: '',
|
||||
}
|
||||
},
|
||||
get({key}) {
|
||||
const dbData = getData(dbPath) || [];
|
||||
|
||||
return dbData.find(d => d._id === key) || {};
|
||||
},
|
||||
remove({key}) {
|
||||
key = typeof key === 'object' ? key.id : key;
|
||||
let dbData = getData(dbPath);
|
||||
let find = false;
|
||||
dbData.some((d, i) => {
|
||||
if (d._id === key) {
|
||||
dbData.splice(i, 1);
|
||||
find = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
if (find) {
|
||||
saveData(dbPath, dbData);
|
||||
return {
|
||||
id: key,
|
||||
ok: true,
|
||||
rev: '',
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
id: key,
|
||||
ok: false,
|
||||
rev: '',
|
||||
}
|
||||
}
|
||||
},
|
||||
bulkDocs({docs}) {
|
||||
const dbData = getData(dbPath);
|
||||
dbData.forEach((d, i) => {
|
||||
const result = docs.find(data => data._id === d._id);
|
||||
if (result) {
|
||||
dbData[i] = result;
|
||||
}
|
||||
});
|
||||
saveData(dbPath, dbData);
|
||||
return docs.map(d => ({
|
||||
id: d.id,
|
||||
success: true,
|
||||
rev: '',
|
||||
}))
|
||||
},
|
||||
allDocs({key}) {
|
||||
const dbData = getData(dbPath);
|
||||
const result = dbData.filter(d => d._id === key);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
import {globalShortcut, ipcMain} from 'electron';
|
||||
import {globalShortcut, ipcMain, BrowserWindow} from 'electron';
|
||||
import {stringify} from 'query-string';
|
||||
import Api from './api';
|
||||
|
||||
export default function init(mainWindow) {
|
||||
@ -15,9 +16,41 @@ export default function init(mainWindow) {
|
||||
});
|
||||
|
||||
ipcMain.on('msg-trigger', async (event, arg) => {
|
||||
const data = Api[arg.type](arg, mainWindow);
|
||||
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 = 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)}`
|
||||
: `file://${__dirname}/index.html/#/plugin?${stringify(opts)}`
|
||||
const win = new BrowserWindow({
|
||||
height: 600,
|
||||
useContentSize: true,
|
||||
width: 788,
|
||||
titleBarStyle: 'hiddenInset',
|
||||
title: '拉比克',
|
||||
webPreferences: {
|
||||
webSecurity: false,
|
||||
enableRemoteModule: true,
|
||||
backgroundThrottling: false,
|
||||
webviewTag: true,
|
||||
nodeIntegration: true // 在网页中集成Node
|
||||
}
|
||||
});
|
||||
win.loadURL(winURL)
|
||||
win.once('ready-to-show', () => win.show());
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
21
src/main/common/utils.js
Normal file
21
src/main/common/utils.js
Normal file
@ -0,0 +1,21 @@
|
||||
import fs from "fs";
|
||||
|
||||
export const getlocalDataFile = () => {
|
||||
let localDataFile = process.env.HOME;
|
||||
if (!localDataFile) {
|
||||
localDataFile = process.env.LOCALAPPDATA;
|
||||
}
|
||||
return localDataFile;
|
||||
};
|
||||
|
||||
export function saveData(path, value) {
|
||||
fs.writeFileSync(path, JSON.stringify(value));
|
||||
}
|
||||
|
||||
export function getData(path, defaultValue) {
|
||||
try {
|
||||
return JSON.parse(fs.readFileSync(path, 'utf8'));
|
||||
} catch (e) {
|
||||
return defaultValue || undefined;
|
||||
}
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
import { app, BrowserWindow } from 'electron'
|
||||
import { app, BrowserWindow, protocol } from 'electron'
|
||||
import '../renderer/store'
|
||||
import eventTracker from '../common/event-tracker';
|
||||
import init from './common';
|
||||
import createTray from './tray';
|
||||
/**
|
||||
@ -27,6 +26,7 @@ function createWindow () {
|
||||
frame: false,
|
||||
title: '拉比克',
|
||||
webPreferences: {
|
||||
webSecurity: false,
|
||||
enableRemoteModule: true,
|
||||
backgroundThrottling: false,
|
||||
webviewTag: true,
|
||||
@ -39,8 +39,15 @@ function createWindow () {
|
||||
mainWindow.on('closed', () => {
|
||||
mainWindow = null
|
||||
});
|
||||
protocol.interceptFileProtocol('file', (req, callback) => {
|
||||
const url = req.url.substr(8);
|
||||
callback(decodeURI(url));
|
||||
}, (error) => {
|
||||
if (error) {
|
||||
console.error('Failed to register protocol');
|
||||
}
|
||||
});
|
||||
init(mainWindow);
|
||||
eventTracker();
|
||||
}
|
||||
|
||||
app.on('ready', () => {
|
||||
|
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<a-layout id="components-layout-demo-custom-trigger">
|
||||
<div class="rubick-select">
|
||||
<a-layout id="components-layout">
|
||||
<div v-if="!searchType" class="rubick-select">
|
||||
<div class="tag-container" v-if="selected">
|
||||
<a-tag
|
||||
:key="selected.key"
|
||||
@ -14,17 +14,18 @@
|
||||
</div>
|
||||
<a-input
|
||||
id="search"
|
||||
placeholder="Hi, Rubick"
|
||||
:placeholder="subPlaceHolder && selected && selected.key === 'plugin-container' ? subPlaceHolder : 'Hi, Rubick'"
|
||||
class="main-input"
|
||||
@change="onSearch"
|
||||
:value="searchValue"
|
||||
:maxLength="selected ? 0 : 1000"
|
||||
:maxLength="selected && selected.key !== 'plugin-container' ? 0 : 1000"
|
||||
>
|
||||
<a-icon class="icon-tool" type="tool" slot="suffix" @click="() => {
|
||||
showMainUI();
|
||||
changePath({key: 'market'})
|
||||
}"/>
|
||||
}
|
||||
<div @click="goMenu" class="suffix-tool" slot="suffix">
|
||||
<a-icon v-show="selected && selected.key === 'plugin-container'" class="icon-more" type="more" />
|
||||
<img class="icon-tool" v-if="selected && selected.icon" :src="selected.icon" />
|
||||
<a-icon class="icon-tool" v-else type="tool"/>
|
||||
</div>
|
||||
|
||||
</a-input>
|
||||
<div class="options" v-show="showOptions">
|
||||
<a-list item-layout="horizontal" :data-source="options">
|
||||
@ -35,24 +36,49 @@
|
||||
<span slot="title" >{{ item.name }}</span>
|
||||
<a-avatar
|
||||
slot="avatar"
|
||||
src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png"
|
||||
:src="item.icon"
|
||||
/>
|
||||
</a-list-item-meta>
|
||||
</a-list-item>
|
||||
</a-list>
|
||||
</div>
|
||||
</div>
|
||||
<div class="rubick-select-subMenu" v-else>
|
||||
<div>
|
||||
<img class="icon-tool-sub" v-if="query && query.icon" :src="query.icon" />
|
||||
<a-input
|
||||
:placeholder="subPlaceHolder"
|
||||
class="sub-input"
|
||||
@change="onSearch"
|
||||
:value="searchValue"
|
||||
></a-input>
|
||||
</div>
|
||||
|
||||
<div class="icon-container">
|
||||
<a-icon class="icon" type="info-circle" />
|
||||
<a-icon class="icon" type="setting" />
|
||||
</div>
|
||||
</div>
|
||||
<router-view></router-view>
|
||||
</a-layout>
|
||||
</template>
|
||||
<script>
|
||||
import {mapActions, mapMutations, mapState} from "vuex";
|
||||
import {ipcRenderer} from "electron";
|
||||
import {ipcRenderer, remote} from "electron";
|
||||
import {getWindowHeight} from "./assets/common/utils";
|
||||
|
||||
const {Menu, MenuItem} = remote;
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
searchType: this.$route.query.searchType ? 'subWindow' : '',
|
||||
query: this.$route.query
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
document.getElementById('search').addEventListener('keydown', this.checkNeedInit)
|
||||
const searchNd = document.getElementById('search');
|
||||
searchNd && searchNd.addEventListener('keydown', this.checkNeedInit)
|
||||
},
|
||||
beforeDestroy() {
|
||||
},
|
||||
@ -81,10 +107,52 @@ export default {
|
||||
this.$router.push({
|
||||
path: '/home',
|
||||
});
|
||||
}
|
||||
},
|
||||
goMenu() {
|
||||
if (this.selected && this.selected.key === 'plugin-container') {
|
||||
const pluginMenu = [
|
||||
{
|
||||
label: '分离窗口',
|
||||
click: () => {
|
||||
ipcRenderer.send('new-window', {
|
||||
...this.$route.query,
|
||||
...this.selected
|
||||
});
|
||||
this.closeTag();
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '开发者工具',
|
||||
click: () => {
|
||||
const webview = document.getElementById('webview');
|
||||
webview.openDevTools()
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '当前插件信息',
|
||||
submenu: [
|
||||
{
|
||||
label: '简介',
|
||||
},
|
||||
{
|
||||
label: '功能'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
label: '隐藏插件',
|
||||
},
|
||||
];
|
||||
let menu = Menu.buildFromTemplate(pluginMenu);
|
||||
menu.popup();
|
||||
return;
|
||||
}
|
||||
this.showMainUI();
|
||||
this.changePath({key: 'market'})
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
...mapState('main', ['showMain', 'current', 'options', 'selected', 'searchValue']),
|
||||
...mapState('main', ['showMain', 'current', 'options', 'selected', 'searchValue', 'subPlaceHolder']),
|
||||
showOptions() {
|
||||
// 有选项值,且不在显示主页
|
||||
if (this.options.length && !this.showMain) {
|
||||
@ -99,4 +167,90 @@ export default {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
#components-layout {
|
||||
padding-top: 60px;
|
||||
height: 100vh;
|
||||
overflow: auto;
|
||||
}
|
||||
.rubick-select, .rubick-select-subMenu {
|
||||
display: flex;
|
||||
padding-left: 10px;
|
||||
background: #fff;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
.tag-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: #fff;
|
||||
|
||||
.select-tag {
|
||||
height: 36px;
|
||||
font-size: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
.ant-input:focus {
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.options {
|
||||
position: absolute;
|
||||
top: 62px;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
z-index: 99;
|
||||
.op-item {
|
||||
padding: 0 10px;
|
||||
height: 60px;
|
||||
line-height: 50px;
|
||||
max-height: 500px;
|
||||
overflow: auto;
|
||||
background: #fafafa;
|
||||
}
|
||||
}
|
||||
}
|
||||
.rubick-select-subMenu {
|
||||
-webkit-app-region: drag;
|
||||
background: #eee;
|
||||
height: 50px;
|
||||
padding-left: 200px;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
.icon-tool-sub {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
border-radius: 100%;
|
||||
margin-right: 10px;
|
||||
}
|
||||
.icon-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 20px;
|
||||
color: #999;
|
||||
.icon {
|
||||
margin-right: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
.sub-input {
|
||||
width: 310px;
|
||||
border-radius: 100px;
|
||||
}
|
||||
}
|
||||
.suffix-tool {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.icon-more {
|
||||
font-size: 26px;
|
||||
font-weight: bold;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -1,38 +1,59 @@
|
||||
<template>
|
||||
<div>
|
||||
<webview style="width: 100%;height: 100vh" id="webview" :src="path" :preload="preload"></webview>
|
||||
<webview id="webview" :src="path" :preload="preload"></webview>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import path from 'path';
|
||||
import {ipcRenderer} from 'electron';
|
||||
import {mapMutations, mapState} from 'vuex';
|
||||
|
||||
export default {
|
||||
name: "index.vue",
|
||||
data() {
|
||||
return {
|
||||
path: `File://${this.$route.query.sourceFile}`,
|
||||
preload: `File://${path.join(__static, './preload.js')}`
|
||||
preload: `File://${path.join(__static, './preload.js')}`,
|
||||
webview: null,
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
const webview = document.querySelector('webview');
|
||||
webview.addEventListener('dom-ready', () => {
|
||||
webview.openDevTools();
|
||||
webview.send('onPluginReady', this.$route.query);
|
||||
webview.send('onPluginEnter', this.$route.query)
|
||||
this.webview = document.querySelector('webview');
|
||||
this.webview.addEventListener('dom-ready', () => {
|
||||
this.webview.send('onPluginReady', this.$route.query);
|
||||
this.webview.send('onPluginEnter', this.$route.query);
|
||||
});
|
||||
this.setSubPlaceHolder('Hi, Rubick');
|
||||
this.webview.addEventListener('ipc-message', (event) => {
|
||||
if (event.channel === 'setSubInput') {
|
||||
this.setSubPlaceHolder(event.args[0].placeHolder);
|
||||
}
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
...mapMutations('main', ['setSubPlaceHolder']),
|
||||
},
|
||||
beforeRouteUpdate() {
|
||||
this.path = `File://${this.$route.query.sourceFile}`
|
||||
},
|
||||
beforeDestroy() {
|
||||
const webview = document.querySelector('webview');
|
||||
webview.send('onPluginOut', this.$route.query)
|
||||
webview && webview.send('onPluginOut', this.$route.query)
|
||||
},
|
||||
computed: {
|
||||
...mapState('main', ['searchValue'])
|
||||
},
|
||||
watch: {
|
||||
searchValue() {
|
||||
this.webview.send('msg-back-setSubInput', this.searchValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
<style lang="scss">
|
||||
#webview {
|
||||
width: 100%;
|
||||
height: calc(100vh - 60px);
|
||||
}
|
||||
</style>
|
||||
|
@ -46,47 +46,6 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.rubick-select {
|
||||
display: flex;
|
||||
padding-left: 10px;
|
||||
background: #fff;
|
||||
position: relative;
|
||||
|
||||
.tag-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: #fff;
|
||||
|
||||
.select-tag {
|
||||
height: 36px;
|
||||
font-size: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
.ant-input:focus {
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.options {
|
||||
position: absolute;
|
||||
top: 62px;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
z-index: 99;
|
||||
.op-item {
|
||||
padding: 0 10px;
|
||||
height: 60px;
|
||||
line-height: 50px;
|
||||
max-height: 500px;
|
||||
overflow: auto;
|
||||
background: #fafafa;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.main-input {
|
||||
-webkit-app-region: drag;
|
||||
height: 60px !important;
|
||||
|
@ -27,13 +27,16 @@
|
||||
</div>
|
||||
<a-tabs default-active-key="1">
|
||||
<a-tab-pane key="1" tab="功能关键字">
|
||||
<div class="desc-item" v-for="item in pluginDetail.features">
|
||||
<div>{{item.explain}}</div>
|
||||
<a-tag v-for="cmd in item.cmds">{{cmd}}</a-tag>
|
||||
<div class="detail-container">
|
||||
<div class="desc-item" v-for="item in pluginDetail.features">
|
||||
<div>{{item.explain}}</div>
|
||||
<a-tag @click="openPlugin({cmd, plugin: pluginDetail, feature: item, router: $router})" v-for="cmd in item.cmds">{{cmd}}</a-tag>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="2" tab="详情介绍">
|
||||
Content of Tab Pane 2
|
||||
<div class="detail-container" v-html="readme"></div>
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
</div>
|
||||
@ -45,7 +48,12 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {mapState, mapMutations} from 'vuex';
|
||||
import {mapState, mapMutations, mapActions} from 'vuex';
|
||||
import marked from 'marked';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
const rendererMD = new marked.Renderer();
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
@ -53,7 +61,8 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapMutations('main', ['deleteProdPlugin'])
|
||||
...mapMutations('main', ['deleteProdPlugin']),
|
||||
...mapActions('main', ['openPlugin']),
|
||||
},
|
||||
computed: {
|
||||
...mapState('main', ['devPlugins']),
|
||||
@ -62,6 +71,25 @@ export default {
|
||||
},
|
||||
prodPlugin() {
|
||||
return this.devPlugins.filter(plugin => plugin.type === 'prod')
|
||||
},
|
||||
readme() {
|
||||
marked.setOptions({
|
||||
renderer: rendererMD,
|
||||
gfm: true,
|
||||
tables: true,
|
||||
breaks: false,
|
||||
pedantic: false,
|
||||
sanitize: false,
|
||||
smartLists: true,
|
||||
smartypants: false
|
||||
});
|
||||
try {
|
||||
const mdFile = path.join(this.pluginDetail.sourceFile, '../README.md');
|
||||
return marked(fs.readFileSync(mdFile, 'utf8'));
|
||||
} catch (e) {
|
||||
return '暂无描述信息'
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -70,10 +98,12 @@ export default {
|
||||
<style lang="scss">
|
||||
.dev-container {
|
||||
height: calc(100vh - 110px);
|
||||
overflow: auto;
|
||||
.dev-detail {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
}
|
||||
.plugin-detail {
|
||||
padding: 20px;
|
||||
@ -93,6 +123,10 @@ export default {
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
.detail-container {
|
||||
height: 340px;
|
||||
overflow: auto;
|
||||
}
|
||||
.desc-item {
|
||||
border-bottom: 1px solid #ddd;
|
||||
padding: 10px 0;
|
||||
|
@ -1,4 +1,4 @@
|
||||
import {clipboard, ipcRenderer} from "electron";
|
||||
import {clipboard, ipcRenderer, remote} from "electron";
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import {getWindowHeight, searchKeyValues, downloadFunc, sysFile} from '../../assets/common/utils';
|
||||
import fs from "fs";
|
||||
@ -11,6 +11,7 @@ const state = {
|
||||
current: ['market'],
|
||||
searchValue: '',
|
||||
devPlugins: sysFile.getUserPlugins() || [],
|
||||
subPlaceHolder: '',
|
||||
}
|
||||
|
||||
const mutations = {
|
||||
@ -22,6 +23,9 @@ const mutations = {
|
||||
}
|
||||
});
|
||||
},
|
||||
setSubPlaceHolder(state, payload) {
|
||||
state.subPlaceHolder = payload;
|
||||
},
|
||||
deleteDevPlugin(state, payload) {
|
||||
state.devPlugins = state.devPlugins.filter(plugin => plugin.name !== payload.name);
|
||||
sysFile.savePlugins(state.devPlugins);
|
||||
@ -44,16 +48,18 @@ const mutations = {
|
||||
|
||||
const actions = {
|
||||
showMainUI ({ commit, state }, paylpad) {
|
||||
commit('commonUpdate', {
|
||||
showMain: true,
|
||||
selected: {
|
||||
key: 'market',
|
||||
name: '插件中心'
|
||||
}
|
||||
});
|
||||
ipcRenderer.send('changeWindowSize', {
|
||||
height: getWindowHeight(),
|
||||
});
|
||||
setTimeout(() => {
|
||||
commit('commonUpdate', {
|
||||
showMain: true,
|
||||
selected: {
|
||||
key: 'market',
|
||||
name: '插件中心'
|
||||
}
|
||||
});
|
||||
}, 50);
|
||||
},
|
||||
reloadDevPlugin({ commit }, payload) {
|
||||
const config = JSON.parse(fs.readFileSync(path.join(payload.sourceFile, '../plugin.json'), 'utf-8'));
|
||||
@ -75,11 +81,16 @@ const actions = {
|
||||
})
|
||||
},
|
||||
onSearch ({ commit }, paylpad) {
|
||||
if (state.selected) {
|
||||
if (state.selected && state.selected.key !== 'plugin-container') {
|
||||
commit('commonUpdate', {searchValue: ''});
|
||||
return;
|
||||
}
|
||||
const value = paylpad.target.value;
|
||||
// 在插件界面
|
||||
if(state.selected && state.selected.key === 'plugin-container') {
|
||||
commit('commonUpdate', {searchValue: value})
|
||||
return;
|
||||
}
|
||||
const fileUrl = clipboard.read('public.file-url').replace('file://', '');
|
||||
commit('commonUpdate', {searchValue: value})
|
||||
// 复制文件
|
||||
@ -148,33 +159,15 @@ const actions = {
|
||||
const feature = plugin.features;
|
||||
feature.forEach(fe => {
|
||||
const cmds = searchKeyValues(fe.cmds, value);
|
||||
console.log(plugin);
|
||||
options = [
|
||||
...options,
|
||||
...cmds.map((cmd) => ({
|
||||
name: cmd,
|
||||
value: 'plugin',
|
||||
icon: 'plus-circle',
|
||||
icon: 'file://' + path.join(plugin.sourceFile, `../${plugin.logo}`),
|
||||
desc: fe.explain,
|
||||
click: (router) => {
|
||||
commit('commonUpdate', {
|
||||
selected: {
|
||||
key: cmd,
|
||||
name: cmd
|
||||
},
|
||||
searchValue: '',
|
||||
showMain: true,
|
||||
});
|
||||
ipcRenderer.send('changeWindowSize', {
|
||||
height: getWindowHeight(),
|
||||
});
|
||||
router.push({
|
||||
path: '/plugin',
|
||||
query: {
|
||||
...plugin,
|
||||
detail: JSON.stringify(fe)
|
||||
},
|
||||
})
|
||||
actions.openPlugin({commit}, {cmd, plugin, feature: fe, router});
|
||||
}
|
||||
}))
|
||||
]
|
||||
@ -202,6 +195,27 @@ const actions = {
|
||||
commit('commonUpdate', {
|
||||
devPlugins: [pluginConfig, ...state.devPlugins],
|
||||
});
|
||||
},
|
||||
openPlugin({commit}, {cmd, plugin, feature, router}) {
|
||||
commit('commonUpdate', {
|
||||
selected: {
|
||||
key: 'plugin-container',
|
||||
name: cmd,
|
||||
icon: 'file://' + path.join(plugin.sourceFile, `../${plugin.logo}`),
|
||||
},
|
||||
searchValue: '',
|
||||
showMain: true,
|
||||
});
|
||||
ipcRenderer.send('changeWindowSize', {
|
||||
height: getWindowHeight(),
|
||||
});
|
||||
router.push({
|
||||
path: '/plugin',
|
||||
query: {
|
||||
...plugin,
|
||||
detail: JSON.stringify(feature)
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,9 @@
|
||||
const path = require('path');
|
||||
const filePath = location.href.replace('file://', '');
|
||||
const {ipcRenderer, nativeImage, clipboard} = require('electron');
|
||||
const Store = require('electron-store');
|
||||
const store = new Store();
|
||||
const {ipcRenderer, nativeImage, clipboard, remote} = require('electron');
|
||||
|
||||
const currentWindow = remote.getCurrentWindow();
|
||||
const winId = currentWindow.id;
|
||||
|
||||
function convertImgToBase64(url, callback, outputFormat){
|
||||
var canvas = document.createElement('CANVAS'),
|
||||
@ -56,9 +57,19 @@ window.utools = window.rubick = {
|
||||
ipcRenderer.send('msg-trigger', {
|
||||
type: 'setExpendHeight',
|
||||
height,
|
||||
winId
|
||||
});
|
||||
},
|
||||
setSubInput(onChange, placeHolder, isFocus) {
|
||||
ipcRenderer.sendToHost('setSubInput', {
|
||||
placeHolder, isFocus
|
||||
});
|
||||
ipcRenderer.on(`msg-back-setSubInput`, (e, result) => {
|
||||
onChange({text: result});
|
||||
});
|
||||
},
|
||||
|
||||
setSubInputValue(text) {
|
||||
|
||||
},
|
||||
|
||||
@ -91,14 +102,39 @@ window.utools = window.rubick = {
|
||||
clipboard.writeText(text);
|
||||
},
|
||||
db: {
|
||||
put(key, value) {
|
||||
console.log(key, value);
|
||||
store.set(key, value)
|
||||
put(data) {
|
||||
ipcRenderer.send('msg-trigger', {
|
||||
type: 'db.put',
|
||||
data,
|
||||
});
|
||||
return new Promise((resolve, reject) => {
|
||||
ipcRenderer.once(`msg-back-db.put`, (e, result) => {
|
||||
result ? resolve(result) : reject();
|
||||
});
|
||||
})
|
||||
},
|
||||
get(key) {
|
||||
store.get(key);
|
||||
ipcRenderer.send('msg-trigger', {
|
||||
type: 'db.get',
|
||||
key,
|
||||
});
|
||||
return new Promise((resolve, reject) => {
|
||||
ipcRenderer.once(`msg-back-db.get`, (e, result) => {
|
||||
result ? resolve(result) : reject();
|
||||
});
|
||||
})
|
||||
},
|
||||
remove() {}
|
||||
remove(key) {
|
||||
ipcRenderer.send('msg-trigger', {
|
||||
type: 'db.remove',
|
||||
key,
|
||||
});
|
||||
return new Promise((resolve, reject) => {
|
||||
ipcRenderer.once(`msg-back-db.remove`, (e, result) => {
|
||||
result ? resolve(result) : reject();
|
||||
});
|
||||
})
|
||||
}
|
||||
},
|
||||
isDarkColors() {
|
||||
return false;
|
||||
|
Loading…
x
Reference in New Issue
Block a user