适配Linux Gnome的复制plugin.json文件的功能。修复粘贴plugin.json受定时器影响不跳出按钮、搜索栏为空时退格路由报错两个Bug

This commit is contained in:
tcsnzh 2021-09-20 23:37:13 +08:00
parent 9d3e7fc4a5
commit db12d66ff7
3 changed files with 285 additions and 202 deletions

View File

@ -126,6 +126,7 @@ import {
searchKeyValues,
fileLists,
} from "./assets/common/utils";
import { commonConst } from "../main/common/utils";
const opConfig = remote.getGlobal("opConfig");
const { Menu, MenuItem } = remote;
@ -217,7 +218,7 @@ export default {
...mapMutations("main", ["commonUpdate"]),
shouldPaste(e) {
let filePath = "";
if (process.platform === "win32") {
if (commonConst.windows()) {
const rawFilePath = clipboard.read("FileNameW");
filePath = rawFilePath.replace(
new RegExp(String.fromCharCode(0), "g"),
@ -226,11 +227,46 @@ export default {
if (filePath.indexOf("plugin.json") >= 0) {
this.search({
filePath,
disableDebounce: true,
});
}
} else if (commonConst.linux()) {
const text = clipboard.readText("selection");
// gnome
//
// x-special/nautilus-clipboard
// copy
// file:///home/admin/dir/plugin.json
const splitLF = text.split(" ");
let pathUrl;
if (
splitLF.length == 3 &&
splitLF[0] === "x-special/nautilus-clipboard" &&
splitLF[1] === "copy" &&
(pathUrl = splitLF[2]).startsWith("file://") &&
pathUrl.indexOf("plugin.json") >= 0
) {
filePath = pathUrl.slice(7);
this.search({
filePath,
disableDebounce: true,
});
}
//
}
},
/**
* @param {Object} v 搜索配置对象
* 若v.disableDebounce为true则不会触发防抖动保护
* 该值的作用是让search()方法被多个监听器同时调用时在某些情况下无视其他监听器的防抖动保护
* 其他属性 v.valuev.filePath 参见 src/renderer/store/modules/main.js的onSearch函数
*/
search(v) {
console.log("search was called , param v is :", v);
if (!v.disableDebounce) {
this.onSearch(v);
return;
}
if (!this.searchFn) {
this.searchFn = debounce(this.onSearch, 200);
}
@ -297,9 +333,13 @@ export default {
ipcRenderer.send("changeWindowSize-rubick", {
height: getWindowHeight([]),
});
if (this.$router.history.current.fullPath !== "/home") {
// if
// (退)
this.$router.push({
path: "/home",
});
}
},
newWindow() {
ipcRenderer.send("new-window", {

View File

@ -9,7 +9,12 @@
>
<a-icon type="left-circle" />
</div>
<div slot="nextArrow" slot-scope="props" class="custom-slick-arrow" style="right: 10px">
<div
slot="nextArrow"
slot-scope="props"
class="custom-slick-arrow"
style="right: 10px"
>
<a-icon type="right-circle" />
</div>
<div v-for="banner in bannerList">
@ -18,22 +23,33 @@
</a-carousel>
<a-divider v-if="bannerList && !!bannerList.length"></a-divider>
<h2>插件</h2>
<a-list item-layout="horizontal" style="width: 100%" :grid="{ gutter: 16, column: 2 }" :data-source="pluginList">
<a-list
item-layout="horizontal"
style="width: 100%"
:grid="{ gutter: 16, column: 2 }"
:data-source="pluginList"
>
<a-list-item slot="renderItem" slot-scope="item, index">
<a-button v-if="showButton(item)" :loading="loading[index]" type="link" slot="actions" @click="download(index, item)">
<a-icon v-show="!loading[index]" style="font-size: 20px;" type="cloud-download" />
<a-button
v-if="showButton(item)"
:loading="loading[index]"
type="link"
slot="actions"
@click="download(index, item)"
>
<a-icon
v-show="!loading[index]"
style="font-size: 20px;"
type="cloud-download"
/>
</a-button>
<a-list-item-meta
@click="showPannel(item, index)"
:description="item.description"
>
<div slot="title">{{ item.pluginName }}</div>
<a-avatar
slot="avatar"
:src="item.logo"
/>
<a-avatar slot="avatar" :src="item.logo" />
</a-list-item-meta>
</a-list-item>
</a-list>
@ -70,8 +86,8 @@
</template>
<script>
import api from '../../../assets/api';
import {mapActions, mapState} from 'vuex';
import api from "../../../assets/api";
import { mapActions, mapState } from "vuex";
import marked from "marked";
import { shell } from "electron";
const rendererMD = new marked.Renderer();
@ -83,8 +99,8 @@ export default {
loading: {},
bannerList: [],
show: false,
currentSelect: {}
}
currentSelect: {},
};
},
async created() {
const [result, bannerRes] = await Promise.all([
@ -93,7 +109,7 @@ export default {
]);
this.pluginList = result.result;
this.bannerList = bannerRes.result;
console.log(bannerRes)
console.log(bannerRes);
},
methods: {
@ -108,7 +124,9 @@ export default {
this.$set(this.loading, index, false);
},
showButton(item) {
return !this.devPlugins.filter(plugin => (plugin.name === item.name && plugin.type === 'prod')).length;
return !this.devPlugins.filter(
(plugin) => plugin.name === item.name && plugin.type === "prod"
).length;
},
showPannel(item, index) {
this.show = true;
@ -117,13 +135,13 @@ export default {
},
jumpTo(link) {
if (link) {
shell.openExternal(link)
shell.openExternal(link);
}
},
...mapActions('main', ['downloadPlugin'])
...mapActions("main", ["downloadPlugin"]),
},
computed: {
...mapState('main', ['devPlugins']),
...mapState("main", ["devPlugins"]),
readme() {
marked.setOptions({
renderer: rendererMD,
@ -133,17 +151,16 @@ export default {
pedantic: false,
sanitize: false,
smartLists: true,
smartypants: false
smartypants: false,
});
try {
return marked(this.currentSelect.detail);
} catch (e) {
return '暂无描述信息'
}
}
}
return "暂无描述信息";
}
},
},
};
</script>
<style lang="less">
@ -178,7 +195,7 @@ export default {
}
}
.market {
height: calc(~'100vh - 110px');
height: calc(~"100vh - 110px");
background: #fff;
padding: 20px;
box-sizing: border-box;
@ -221,5 +238,4 @@ export default {
white-space: nowrap;
}
}
</style>

View File

@ -1,5 +1,5 @@
import { clipboard, ipcRenderer, remote } from 'electron';
import { v4 as uuidv4 } from 'uuid';
import { clipboard, ipcRenderer, remote } from "electron";
import { v4 as uuidv4 } from "uuid";
import {
getWindowHeight,
searchKeyValues,
@ -7,34 +7,34 @@ import {
mergePlugins,
find,
downloadZip,
fileLists
} from '../../assets/common/utils';
import systemMethod from '../../assets/common/system';
import fs from 'fs';
import path from 'path';
import { execSync } from 'child_process';
fileLists,
} from "../../assets/common/utils";
import systemMethod from "../../assets/common/system";
import fs from "fs";
import path from "path";
import { execSync } from "child_process";
const state = {
selected: null,
options: [],
showMain: false,
current: ['market'],
searchValue: '',
current: ["market"],
searchValue: "",
devPlugins: mergePlugins(sysFile.getUserPlugins() || []),
subPlaceHolder: '',
subPlaceHolder: "",
pluginLoading: true,
pluginInfo: (() => {
try {
return window.pluginInfo || {};
} catch (e) {}
})()
})(),
};
const mutations = {
commonUpdate(state, payload) {
Object.keys(payload).forEach((key) => {
state[key] = payload[key];
if (key === 'devPlugins') {
if (key === "devPlugins") {
sysFile.savePlugins(payload[key]);
}
});
@ -43,11 +43,15 @@ const mutations = {
state.subPlaceHolder = payload;
},
deleteDevPlugin(state, payload) {
state.devPlugins = state.devPlugins.filter((plugin) => plugin.name !== payload.name);
state.devPlugins = state.devPlugins.filter(
(plugin) => plugin.name !== payload.name
);
sysFile.savePlugins(state.devPlugins);
},
deleteProdPlugin(state, payload) {
state.devPlugins = state.devPlugins.filter((plugin) => plugin.id !== payload.id);
state.devPlugins = state.devPlugins.filter(
(plugin) => plugin.id !== payload.id
);
sysFile.savePlugins(state.devPlugins);
// todo 删除 static 目录下的对应插件
},
@ -59,124 +63,136 @@ const mutations = {
});
state.devPlugins = [...state.devPlugins];
sysFile.savePlugins(state.devPlugins);
}
},
};
const actions = {
showMainUI({ commit, state }, paylpad) {
ipcRenderer.send('changeWindowSize-rubick', {
height: getWindowHeight()
ipcRenderer.send("changeWindowSize-rubick", {
height: getWindowHeight(),
});
setTimeout(() => {
commit('commonUpdate', {
commit("commonUpdate", {
showMain: true,
selected: {
key: 'market',
name: '插件中心'
}
key: "market",
name: "插件中心",
},
});
}, 50);
},
reloadDevPlugin({ commit }, payload) {
const config = JSON.parse(fs.readFileSync(path.join(payload.sourceFile, '../plugin.json'), 'utf-8'));
const config = JSON.parse(
fs.readFileSync(path.join(payload.sourceFile, "../plugin.json"), "utf-8")
);
const pluginConfig = {
...config,
sourceFile: path.join(payload.sourceFile, `../${config.main}`)
sourceFile: path.join(payload.sourceFile, `../${config.main}`),
};
const devPlugins = [...state.devPlugins];
commit('commonUpdate', {
commit("commonUpdate", {
devPlugins: devPlugins.map((plugin) => {
if (plugin.name === payload.name) {
return {
...plugin,
...pluginConfig
...pluginConfig,
};
}
return plugin;
})
}),
});
},
async onSearch({ commit }, paylpad) {
if (state.selected && state.selected.key !== 'plugin-container') {
commit('commonUpdate', { searchValue: '' });
/**
* @param {Object} payload payload.filePath为配置文件的绝对路径payload.value为搜索栏文字值
*/
async onSearch({ commit }, payload) {
if (state.selected && state.selected.key !== "plugin-container") {
commit("commonUpdate", { searchValue: "" });
return;
}
const value = paylpad.value;
const value = payload.value;
// 在插件界面不触发其他功能
if ((state.selected && state.selected.key === 'plugin-container') || paylpad.searchType === 'subWindow') {
commit('commonUpdate', { searchValue: value });
if (
(state.selected && state.selected.key === "plugin-container") ||
payload.searchType === "subWindow"
) {
commit("commonUpdate", { searchValue: value });
return;
}
const fileUrl = paylpad.filePath || clipboard.read('public.file-url').replace('file://', '');
commit('commonUpdate', { searchValue: value });
const fileUrl =
payload.filePath ||
clipboard.read("public.file-url").replace("file://", "");
commit("commonUpdate", { searchValue: value });
// 复制文件
if (paylpad.filePath || (fileUrl && value === 'plugin.json')) {
const config = JSON.parse(fs.readFileSync(fileUrl, 'utf-8'));
if (payload.filePath || (fileUrl && value === "plugin.json")) {
const config = JSON.parse(fs.readFileSync(fileUrl, "utf-8"));
const pluginConfig = {
...config,
sourceFile: path.join(fileUrl, `../${config.main || 'index.html'}`),
sourceFile: path.join(fileUrl, `../${config.main || "index.html"}`),
id: uuidv4(),
type: 'dev',
icon: 'image://' + path.join(fileUrl, `../${config.logo}`),
type: "dev",
icon: "image://" + path.join(fileUrl, `../${config.logo}`),
subType: (() => {
if (config.main) {
return '';
return "";
}
return 'template';
})()
return "template";
})(),
};
commit('commonUpdate', {
commit("commonUpdate", {
selected: {
key: 'plugin',
name: 'plugin.json'
key: "plugin",
name: "plugin.json",
},
searchValue: '',
searchValue: "",
options: [
{
name: '新建rubick开发插件',
value: 'new-plugin',
icon: 'https://static.91jkys.com/activity/img/b37ff555c748489f88f3adac15b76f18.png',
desc: '新建rubick开发插件',
name: "新建rubick开发插件",
value: "new-plugin",
icon:
"https://static.91jkys.com/activity/img/b37ff555c748489f88f3adac15b76f18.png",
desc: "新建rubick开发插件",
click: (router) => {
commit('commonUpdate', {
commit("commonUpdate", {
showMain: true,
devPlugins: [pluginConfig, ...state.devPlugins],
selected: {
key: 'plugin',
name: '新建rubick开发插件'
key: "plugin",
name: "新建rubick开发插件",
},
current: ['dev']
current: ["dev"],
});
ipcRenderer.send('changeWindowSize-rubick', {
height: getWindowHeight()
ipcRenderer.send("changeWindowSize-rubick", {
height: getWindowHeight(),
});
router.push('/home/dev');
}
router.push("/home/dev");
},
},
{
name: '复制路径',
desc: '复制路径',
value: 'copy-path',
icon: 'https://static.91jkys.com/activity/img/ac0d4df0247345b9a84c8cd7ea3dd696.png',
name: "复制路径",
desc: "复制路径",
value: "copy-path",
icon:
"https://static.91jkys.com/activity/img/ac0d4df0247345b9a84c8cd7ea3dd696.png",
click: () => {
clipboard.writeText(fileUrl);
commit('commonUpdate', {
commit("commonUpdate", {
showMain: false,
selected: null,
options: []
options: [],
});
ipcRenderer.send('changeWindowSize-rubick', {
height: getWindowHeight([])
ipcRenderer.send("changeWindowSize-rubick", {
height: getWindowHeight([]),
});
remote.Notification('Rubick 通知', { body: '复制成功' });
}
}
]
remote.Notification("Rubick 通知", { body: "复制成功" });
},
},
],
});
// 调整窗口大小
ipcRenderer.send('changeWindowSize-rubick', {
height: getWindowHeight(state.options)
ipcRenderer.send("changeWindowSize-rubick", {
height: getWindowHeight(state.options),
});
return;
}
@ -187,7 +203,7 @@ const actions = {
if (value) {
state.devPlugins.forEach((plugin) => {
// dev 插件未开启
if (plugin.type === 'dev' && !plugin.status) return;
if (plugin.type === "dev" && !plugin.status) return;
const feature = plugin.features;
feature.forEach((fe) => {
const cmds = searchKeyValues(fe.cmds, value);
@ -195,14 +211,19 @@ const actions = {
...options,
...cmds.map((cmd) => ({
name: cmd,
value: 'plugin',
icon: plugin.sourceFile ? 'image://' + path.join(plugin.sourceFile, `../${plugin.logo}`) : plugin.logo,
value: "plugin",
icon: plugin.sourceFile
? "image://" + path.join(plugin.sourceFile, `../${plugin.logo}`)
: plugin.logo,
desc: fe.explain,
type: plugin.type,
click: (router) => {
actions.openPlugin({ commit }, { cmd, plugin, feature: fe, router });
}
}))
actions.openPlugin(
{ commit },
{ cmd, plugin, feature: fe, router }
);
},
})),
];
});
});
@ -215,8 +236,12 @@ const actions = {
if (!descMap.get(plugin)) {
descMap.set(plugin, true);
let has = false;
plugin.keyWords.some(keyWord => {
if (keyWord.toLocaleUpperCase().indexOf(value.toLocaleUpperCase()) >= 0) {
plugin.keyWords.some((keyWord) => {
if (
keyWord
.toLocaleUpperCase()
.indexOf(value.toLocaleUpperCase()) >= 0
) {
has = keyWord;
plugin.name = keyWord;
return true;
@ -233,17 +258,17 @@ const actions = {
actions.openPlugin({ commit }, { plugin });
};
return plugin;
})
}),
];
descMap = null;
}
commit('commonUpdate', {
options
commit("commonUpdate", {
options,
});
ipcRenderer.send('changeWindowSize-rubick', {
height: getWindowHeight(state.options)
ipcRenderer.send("changeWindowSize-rubick", {
height: getWindowHeight(state.options),
});
},
async downloadPlugin({ commit }, payload) {
@ -251,88 +276,90 @@ const actions = {
const fileUrl = find(distUrl);
// 复制文件
const config = JSON.parse(fs.readFileSync(`${fileUrl}/plugin.json`, 'utf-8'));
const config = JSON.parse(
fs.readFileSync(`${fileUrl}/plugin.json`, "utf-8")
);
const pluginConfig = {
...config,
id: uuidv4(),
sourceFile: `${fileUrl}/${config.main}`,
type: 'prod',
type: "prod",
icon: payload.logo,
subType: (() => {
if (config.main) {
return '';
return "";
}
return 'template';
})()
return "template";
})(),
};
commit('commonUpdate', {
devPlugins: [pluginConfig, ...state.devPlugins]
commit("commonUpdate", {
devPlugins: [pluginConfig, ...state.devPlugins],
});
},
openPlugin({ commit }, { cmd, plugin, feature, router, payload }) {
if (plugin.type === 'app') {
if (plugin.type === "app") {
execSync(plugin.action);
commit('commonUpdate', {
commit("commonUpdate", {
selected: null,
showMain: false,
options: [],
searchValue: ''
searchValue: "",
});
ipcRenderer.send('changeWindowSize-rubick', {
height: getWindowHeight([])
ipcRenderer.send("changeWindowSize-rubick", {
height: getWindowHeight([]),
});
return;
}
commit('commonUpdate', {
commit("commonUpdate", {
selected: {
key: 'plugin-container',
key: "plugin-container",
name: cmd.label ? cmd.label : cmd,
icon: 'image://' + path.join(plugin.sourceFile, `../${plugin.logo}`)
icon: "image://" + path.join(plugin.sourceFile, `../${plugin.logo}`),
},
searchValue: '',
showMain: true
searchValue: "",
showMain: true,
});
ipcRenderer.send('changeWindowSize-rubick', {
height: getWindowHeight()
ipcRenderer.send("changeWindowSize-rubick", {
height: getWindowHeight(),
});
if (plugin.type === 'system') {
if (plugin.type === "system") {
systemMethod[plugin.tag][feature.code]();
commit('commonUpdate', {
commit("commonUpdate", {
selected: null,
showMain: false,
options: []
options: [],
});
ipcRenderer.send('changeWindowSize-rubick', {
height: getWindowHeight([])
ipcRenderer.send("changeWindowSize-rubick", {
height: getWindowHeight([]),
});
router.push({
path: '/home'
path: "/home",
});
return;
}
commit('commonUpdate', {
commit("commonUpdate", {
pluginInfo: {
cmd,
...plugin,
detail: feature,
payload
}
payload,
},
});
router.push({
path: '/plugin',
path: "/plugin",
query: {
...plugin,
_modify: Date.now(),
detail: JSON.stringify(feature)
}
detail: JSON.stringify(feature),
},
});
}
},
};
export default {
namespaced: true,
state,
mutations,
actions
actions,
};