支持文件检索呼起插件

This commit is contained in:
muwoo 2021-12-20 18:33:00 +08:00
parent ced8aa846b
commit ff118dfe2d
25 changed files with 351 additions and 70 deletions

2
package-lock.json generated
View File

@ -1,6 +1,6 @@
{ {
"name": "rubick", "name": "rubick",
"version": "2.0.0", "version": "2.0.1-beta.3",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {

View File

@ -1,6 +1,6 @@
{ {
"name": "rubick", "name": "rubick",
"version": "2.0.1-beta.3", "version": "2.0.1-beta.4",
"private": true, "private": true,
"scripts": { "scripts": {
"serve": "vue-cli-service serve", "serve": "vue-cli-service serve",

View File

@ -132,4 +132,6 @@ window.rubick = {
shellOpenPath(path) { shellOpenPath(path) {
shell.openPath(path); shell.openPath(path);
}, },
getLocalId: () => ipcSendSync("getLocalId"),
}; };

View File

@ -1 +1 @@
<!DOCTYPE html><html lang=""><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="favicon.ico"><title>tpl</title><link href="css/app.f5fd5a5f.css" rel="preload" as="style"><link href="js/app.845a0078.js" rel="preload" as="script"><link href="js/chunk-vendors.d5af439e.js" rel="preload" as="script"><link href="css/app.f5fd5a5f.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but tpl doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script src="js/chunk-vendors.d5af439e.js"></script><script src="js/app.845a0078.js"></script></body></html> <!DOCTYPE html><html lang=""><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="favicon.ico"><title>tpl</title><link href="css/app.f5fd5a5f.css" rel="preload" as="style"><link href="js/app.6e04bbe2.js" rel="preload" as="script"><link href="js/chunk-vendors.88fb06db.js" rel="preload" as="script"><link href="css/app.f5fd5a5f.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but tpl doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script src="js/chunk-vendors.88fb06db.js"></script><script src="js/app.6e04bbe2.js"></script></body></html>

View File

@ -0,0 +1,2 @@
(function(e){function t(t){for(var r,a,u=t[0],i=t[1],l=t[2],d=0,p=[];d<u.length;d++)a=u[d],Object.prototype.hasOwnProperty.call(c,a)&&c[a]&&p.push(c[a][0]),c[a]=0;for(r in i)Object.prototype.hasOwnProperty.call(i,r)&&(e[r]=i[r]);s&&s(t);while(p.length)p.shift()();return o.push.apply(o,l||[]),n()}function n(){for(var e,t=0;t<o.length;t++){for(var n=o[t],r=!0,u=1;u<n.length;u++){var i=n[u];0!==c[i]&&(r=!1)}r&&(o.splice(t--,1),e=a(a.s=n[0]))}return e}var r={},c={app:0},o=[];function a(t){if(r[t])return r[t].exports;var n=r[t]={i:t,l:!1,exports:{}};return e[t].call(n.exports,n,n.exports,a),n.l=!0,n.exports}a.m=e,a.c=r,a.d=function(e,t,n){a.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},a.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},a.t=function(e,t){if(1&t&&(e=a(e)),8&t)return e;if(4&t&&"object"===typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(a.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)a.d(n,r,function(t){return e[t]}.bind(null,r));return n},a.n=function(e){var t=e&&e.__esModule?function(){return e["default"]}:function(){return e};return a.d(t,"a",t),t},a.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},a.p="";var u=window["webpackJsonp"]=window["webpackJsonp"]||[],i=u.push.bind(u);u.push=t,u=u.slice();for(var l=0;l<u.length;l++)t(u[l]);var s=i;o.push([0,"chunk-vendors"]),n()})({0:function(e,t,n){e.exports=n("cd49")},"2fb6":function(e,t,n){},3809:function(e,t,n){"use strict";n("2fb6")},"3ac0":function(e,t,n){},cd49:function(e,t,n){"use strict";n.r(t);n("e260"),n("e6cf"),n("cca6"),n("a79d");var r=n("7a23"),c=n("6c02"),o={setup:function(e){var t=Object(c["d"])();return window.rubick.onPluginEnter((function(e){var n=e.code,r=e.type,c=e.payload,o=window.exports[n];t.push({name:o.mode,params:{code:n,type:r,payload:c}})})),function(e,t){var n=Object(r["w"])("router-view");return Object(r["r"])(),Object(r["d"])(n)}}};n("da18");const a=o;var u=a,i=(n("ac1f"),n("841c"),n("a4d3"),n("e01a"),{class:"list-container"}),l={class:"options"},s=["onClick"],d=["src"],p={class:"content"},f={class:"title"},v={class:"desc"},b=Object(r["h"])({setup:function(e){var t=window.require("electron"),n=t.ipcRenderer,o=Object(c["c"])(),a=60,u=10,b=60,O=o.params,j=O.code,y=O.type,w=O.payload,h=window.exports[j];window.rubick.setExpendHeight(b);var g=Object(r["u"])([]);Object(r["B"])([g],(function(){var e=g.value.length>u?u*a:a*g.value.length;window.rubick.setExpendHeight(b+e)})),h.args.enter&&h.args.enter({code:j,type:y,payload:w},(function(e){g.value=e}));var m=Object(r["u"])(0);n.on("changeCurrent",(function(e,t){m.value+t>g.value.length-1||g.value+t<0||(m.value=m.value+t)})),window.rubick.setSubInput((function(e){var t=e.text;h.args.search&&h.args.search({code:j,type:"",payload:[]},t,(function(e){g.value=e||[]}))}),"搜索");var k=function(e){h.args.select&&h.args.select({code:j,type:"",payload:[]},e)},x=function(e){if("Enter"===e.code)return k(g.value[m.value]);var t=0;"ArrowDown"===e.code&&(t=1),"ArrowUp"===e.code&&(t=-1),g.value.length&&(m.value+t>g.value.length-1||m.value+t<0||(m.value=m.value+t))};return window.addEventListener("keydown",x),Object(r["o"])((function(){window.removeEventListener("keydown",x)})),function(e,t){return Object(r["r"])(),Object(r["f"])("div",i,[Object(r["C"])(Object(r["g"])("div",l,[(Object(r["r"])(!0),Object(r["f"])(r["a"],null,Object(r["v"])(g.value,(function(e,t){return Object(r["r"])(),Object(r["f"])("div",{key:t,class:Object(r["m"])(m.value===t?"active op-item":"op-item"),onClick:function(t){return k(e)}},[e.icon?(Object(r["r"])(),Object(r["f"])("img",{key:0,class:"icon",src:e.icon},null,8,d)):Object(r["e"])("",!0),Object(r["g"])("div",p,[Object(r["g"])("div",f,Object(r["y"])(e.title),1),Object(r["g"])("div",v,Object(r["y"])(decodeURIComponent(e.description)),1)])],10,s)})),128))],512),[[r["A"],!!(g.value||[]).length]])])}}});n("3809");const O=b;var j=O,y={class:"home"};function w(e,t){return Object(r["r"])(),Object(r["f"])("div",y)}var h=n("6b0d"),g=n.n(h);const m={},k=g()(m,[["render",w]]);var x=k,P=[{path:"/list",name:"list",component:j},{path:"/doc",name:"doc",component:x}],E=Object(c["a"])({history:Object(c["b"])(),routes:P}),S=E,_=n("5502"),C=Object(_["a"])({state:{},mutations:{},actions:{},modules:{}});Object(r["c"])(u).use(C).use(S).mount("#app")},da18:function(e,t,n){"use strict";n("3ac0")}});
//# sourceMappingURL=app.6e04bbe2.js.map

File diff suppressed because one or more lines are too long

View File

@ -1,2 +0,0 @@
(function(e){function t(t){for(var r,u,a=t[0],i=t[1],l=t[2],d=0,p=[];d<a.length;d++)u=a[d],Object.prototype.hasOwnProperty.call(c,u)&&c[u]&&p.push(c[u][0]),c[u]=0;for(r in i)Object.prototype.hasOwnProperty.call(i,r)&&(e[r]=i[r]);s&&s(t);while(p.length)p.shift()();return o.push.apply(o,l||[]),n()}function n(){for(var e,t=0;t<o.length;t++){for(var n=o[t],r=!0,a=1;a<n.length;a++){var i=n[a];0!==c[i]&&(r=!1)}r&&(o.splice(t--,1),e=u(u.s=n[0]))}return e}var r={},c={app:0},o=[];function u(t){if(r[t])return r[t].exports;var n=r[t]={i:t,l:!1,exports:{}};return e[t].call(n.exports,n,n.exports,u),n.l=!0,n.exports}u.m=e,u.c=r,u.d=function(e,t,n){u.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},u.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},u.t=function(e,t){if(1&t&&(e=u(e)),8&t)return e;if(4&t&&"object"===typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(u.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)u.d(n,r,function(t){return e[t]}.bind(null,r));return n},u.n=function(e){var t=e&&e.__esModule?function(){return e["default"]}:function(){return e};return u.d(t,"a",t),t},u.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},u.p="";var a=window["webpackJsonp"]=window["webpackJsonp"]||[],i=a.push.bind(a);a.push=t,a=a.slice();for(var l=0;l<a.length;l++)t(a[l]);var s=i;o.push([0,"chunk-vendors"]),n()})({0:function(e,t,n){e.exports=n("cd49")},2874:function(e,t,n){},"2f93":function(e,t,n){"use strict";n("4016")},4016:function(e,t,n){},5490:function(e,t,n){"use strict";n("2874")},cd49:function(e,t,n){"use strict";n.r(t);n("e260"),n("e6cf"),n("cca6"),n("a79d");var r=n("7a23"),c=n("6c02"),o={setup:function(e){var t=Object(c["d"])();return window.rubick.onPluginEnter((function(e){var n=e.code,r=window.exports[n];t.push({name:r.mode,params:{code:n}})})),function(e,t){var n=Object(r["v"])("router-view");return Object(r["q"])(),Object(r["d"])(n)}}};n("5490");const u=o;var a=u,i=(n("ac1f"),n("841c"),n("a4d3"),n("e01a"),{class:"list-container"}),l={class:"options"},s=["onClick"],d=["src"],p={class:"content"},f={class:"title"},v={class:"desc"},b=Object(r["g"])({setup:function(e){var t=window.require("electron"),n=t.ipcRenderer,o=Object(c["c"])(),u=60,a=10,b=60,O=o.params.code,j=window.exports[O];window.rubick.setExpendHeight(b);var w=Object(r["t"])([]);j.args.enter&&j.args.enter({code:O,type:"",payload:[]},(function(e){e.value=e}));var h=Object(r["t"])(0);n.on("changeCurrent",(function(e,t){h.value+t>w.value.length-1||w.value+t<0||(h.value=h.value+t)})),window.rubick.setSubInput((function(e){var t=e.text;j.args.search&&j.args.search({code:O,type:"",payload:[]},t,(function(e){w.value=e||[];var t=w.value.length>a?a*u:u*w.value.length;window.rubick.setExpendHeight(b+t)}))}),"搜索");var g=function(e){j.args.select&&j.args.select({code:O,type:"",payload:[]},e)},y=function(e){if("Enter"===e.code)return g(w.value[h.value]);var t=0;"ArrowDown"===e.code&&(t=1),"ArrowUp"===e.code&&(t=-1),w.value.length&&(h.value+t>w.value.length-1||h.value+t<0||(h.value=h.value+t))};return window.addEventListener("keydown",y),Object(r["n"])((function(){window.removeEventListener("keydown",y)})),function(e,t){return Object(r["q"])(),Object(r["e"])("div",i,[Object(r["B"])(Object(r["f"])("div",l,[(Object(r["q"])(!0),Object(r["e"])(r["a"],null,Object(r["u"])(w.value,(function(e,t){return Object(r["q"])(),Object(r["e"])("div",{key:t,class:Object(r["l"])(h.value===t?"active op-item":"op-item"),onClick:function(t){return g(e)}},[Object(r["f"])("img",{class:"icon",src:e.icon},null,8,d),Object(r["f"])("div",p,[Object(r["f"])("div",f,Object(r["x"])(e.title),1),Object(r["f"])("div",v,Object(r["x"])(decodeURIComponent(e.description)),1)])],10,s)})),128))],512),[[r["z"],!!(w.value||[]).length]])])}}});n("2f93");const O=b;var j=O,w={class:"home"};function h(e,t){return Object(r["q"])(),Object(r["e"])("div",w)}var g=n("6b0d"),y=n.n(g);const m={},x=y()(m,[["render",h]]);var k=x,P=[{path:"/list",name:"list",component:j},{path:"/doc",name:"doc",component:k}],q=Object(c["a"])({history:Object(c["b"])(),routes:P}),E=q,S=n("5502"),_=Object(S["a"])({state:{},mutations:{},actions:{},modules:{}});Object(r["c"])(a).use(_).use(E).mount("#app")}});
//# sourceMappingURL=app.845a0078.js.map

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,49 @@
import commonConst from "./commonConst";
import { clipboard, remote } from "electron";
import plist from "plist";
import fs from "fs";
import path from "path";
import ofs from "original-fs";
export default function getCopyFiles(): Array<any> | null {
let fileInfo;
if (commonConst.macOS()) {
if (!clipboard.has("NSFilenamesPboardType")) return null;
const result = clipboard.read("NSFilenamesPboardType");
if (!result) return null;
try {
fileInfo = plist.parse(result);
} catch (e) {
return null;
}
} else if (commonConst.windows()) {
// todo
} else {
if (!commonConst.linux()) return null;
if (!clipboard.has("text/uri-list")) return null;
const result = clipboard.read("text/uri-list").match(/^file:\/\/\/.*/gm);
if (!result || !result.length) return null;
fileInfo = result.map((e) =>
decodeURIComponent(e).replace(/^file:\/\//, "")
);
}
if (!Array.isArray(fileInfo)) return null;
const target: any = fileInfo
.map((p) => {
if (!fs.existsSync(p)) return false;
let info;
try {
info = ofs.lstatSync(p);
} catch (e) {
return false;
}
return {
isFile: info.isFile(),
isDirectory: info.isDirectory(),
name: path.basename(p) || p,
path: p,
};
})
.filter(Boolean);
return target.length ? target : null;
}

View File

@ -10,7 +10,10 @@
:searchValue="searchValue" :searchValue="searchValue"
:placeholder="placeholder" :placeholder="placeholder"
:pluginLoading="pluginLoading" :pluginLoading="pluginLoading"
:clipboardFile="clipboardFile || []"
@choosePlugin="choosePlugin" @choosePlugin="choosePlugin"
@focus="searchFocus"
@clearClipbord="clearClipboardFile"
/> />
</div> </div>
<Result <Result
@ -18,6 +21,7 @@
:searchValue="searchValue" :searchValue="searchValue"
:currentSelect="currentSelect" :currentSelect="currentSelect"
:options="options" :options="options"
:clipboardFile="clipboardFile || []"
/> />
</div> </div>
</template> </template>
@ -41,6 +45,9 @@ const {
currentPlugin, currentPlugin,
placeholder, placeholder,
pluginLoading, pluginLoading,
searchFocus,
clipboardFile,
clearClipboardFile,
} = createPluginManager(); } = createPluginManager();
initPlugins(); initPlugins();
@ -57,13 +64,13 @@ getPluginInfo({
remote.getGlobal("LOCAL_PLUGINS").addPlugin(res); remote.getGlobal("LOCAL_PLUGINS").addPlugin(res);
}); });
watch([searchValue], () => { watch([options], () => {
currentSelect.value = 0; currentSelect.value = 0;
if (currentPlugin.value.name) return; if (currentPlugin.value.name) return;
nextTick(() => { nextTick(() => {
ipcRenderer.sendSync("msg-trigger", { ipcRenderer.sendSync("msg-trigger", {
type: "setExpendHeight", type: "setExpendHeight",
data: getWindowHeight(searchValue.value ? options.value : []), data: getWindowHeight(options.value),
}); });
}); });
}); });

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

@ -1,5 +1,5 @@
<template> <template>
<div v-show="!!options.length && searchValue && !currentPlugin.name" class="options" ref="scrollDom"> <div v-show="!!options.length && (searchValue || !!clipboardFile.length) && !currentPlugin.name" class="options" ref="scrollDom">
<a-list item-layout="horizontal" :dataSource="options"> <a-list item-layout="horizontal" :dataSource="options">
<template #renderItem="{ item, index }"> <template #renderItem="{ item, index }">
<a-list-item <a-list-item
@ -46,10 +46,12 @@ const props = defineProps({
default: 0, default: 0,
}, },
currentPlugin: {}, currentPlugin: {},
clipboardFile: () => [],
}); });
const renderTitle = (title) => { const renderTitle = (title) => {
if (typeof title !== "string") return; if (typeof title !== "string") return;
if (!props.searchValue) return title;
const result = title.toLowerCase().split(props.searchValue.toLowerCase()); const result = title.toLowerCase().split(props.searchValue.toLowerCase());
if (result && result.length > 1) { if (result && result.length > 1) {
return `<div>${result[0]}<span style="color: red">${props.searchValue}</span>${result[1]}</div>`; return `<div>${result[0]}<span style="color: red">${props.searchValue}</span>${result[1]}</div>`;

View File

@ -1,6 +1,10 @@
<template> <template>
<div class="rubick-select"> <div class="rubick-select">
<div class="select-tag" v-show="currentPlugin.cmd">{{ currentPlugin.cmd }}</div> <div class="select-tag" v-show="currentPlugin.cmd">{{ currentPlugin.cmd }}</div>
<div class="clipboard-tag" v-if="!!clipboardFile.length">
<img :src="clipboardFile[0].isFile ? require('../assets/file.png') : require('../assets/folder.png')" />
{{ clipboardFile[0].name }}
</div>
<a-input <a-input
id="search" id="search"
class="main-input" class="main-input"
@ -11,6 +15,7 @@
:value="searchValue" :value="searchValue"
:placeholder="placeholder || 'Hi, Rubick2'" :placeholder="placeholder || 'Hi, Rubick2'"
@keypress.enter="(e) => keydownEvent(e)" @keypress.enter="(e) => keydownEvent(e)"
@focus="emit('focus')"
> >
<template #suffix> <template #suffix>
<div class="suffix-tool" > <div class="suffix-tool" >
@ -36,15 +41,16 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { defineProps, defineEmits, ref } from "vue"; import { defineProps, defineEmits, ref, computed } from "vue";
import { ipcRenderer, remote } from "electron"; import { ipcRenderer, remote } from "electron";
import { LoadingOutlined, MoreOutlined } from "@ant-design/icons-vue"; import { LoadingOutlined, MoreOutlined } from "@ant-design/icons-vue";
const opConfig = remote.getGlobal("OP_CONFIG"); const opConfig = remote.getGlobal("OP_CONFIG");
const { Menu } = remote; const { Menu } = remote;
const config = ref(opConfig.get()); const config = ref(opConfig.get());
const props = defineProps({ const props: any = defineProps({
searchValue: { searchValue: {
type: [String, Number], type: [String, Number],
default: "", default: "",
@ -55,6 +61,7 @@ const props = defineProps({
}, },
currentPlugin: {}, currentPlugin: {},
pluginLoading: Boolean, pluginLoading: Boolean,
clipboardFile: () => [],
}); });
const changeValue = (e) => { const changeValue = (e) => {
@ -69,11 +76,12 @@ const emit = defineEmits([
"openMenu", "openMenu",
"changeSelect", "changeSelect",
"choosePlugin", "choosePlugin",
"focus",
]); ]);
const keydownEvent = (e, index) => { const keydownEvent = (e, index) => {
const { ctrlKey, shiftKey, altKey, metaKey } = e; const { ctrlKey, shiftKey, altKey, metaKey } = e;
const modifiers = []; const modifiers: Array<string> = [];
ctrlKey && modifiers.push("control"); ctrlKey && modifiers.push("control");
shiftKey && modifiers.push("shift"); shiftKey && modifiers.push("shift");
altKey && modifiers.push("alt"); altKey && modifiers.push("alt");
@ -98,7 +106,7 @@ const checkNeedInit = (e) => {
} }
}; };
const targetSearch = ({ value, type }) => { const targetSearch = ({ value }) => {
if (props.currentPlugin.name) { if (props.currentPlugin.name) {
return ipcRenderer.sendSync("msg-trigger", { return ipcRenderer.sendSync("msg-trigger", {
type: "sendSubInputChangeEvent", type: "sendSubInputChangeEvent",
@ -109,13 +117,14 @@ const targetSearch = ({ value, type }) => {
const closeTag = () => { const closeTag = () => {
emit("changeSelect", {}); emit("changeSelect", {});
emit("clearClipbord");
ipcRenderer.send("msg-trigger", { ipcRenderer.send("msg-trigger", {
type: "removePlugin", type: "removePlugin",
}); });
}; };
const showSeparate = () => { const showSeparate = () => {
let pluginMenu = [ let pluginMenu: any = [
{ {
label: config.value.perf.common.hideOnBlur ? "钉住" : "自动隐藏", label: config.value.perf.common.hideOnBlur ? "钉住" : "自动隐藏",
click: changeHideOnBlur, click: changeHideOnBlur,
@ -233,5 +242,22 @@ const newWindow = () => {
left: 0; left: 0;
} }
} }
.clipboard-tag {
white-space: pre;
user-select: none;
font-size: 16px;
height: 32px;
position: relative;
align-items: center;
display: flex;
border: 1px solid #e6e6e6;
padding: 0 8px;
margin-right: 12px;
img {
width: 24px;
height: 24px;
margin-right: 6px;
}
}
} }
</style> </style>

View File

@ -0,0 +1,133 @@
import getCopyFiles from "@/common/utils/getCopyFiles";
import { clipboard, nativeImage, remote, ipcRenderer } from "electron";
import path from "path";
import pluginClickEvent from "./pluginClickEvent";
import { ref } from "vue";
export default ({
currentPlugin,
optionsRef,
openPlugin,
setOptionsRef,
}) => {
const clipboardFile: any = ref([]);
const searchFocus = () => {
if (currentPlugin.value.name) return;
const fileList = getCopyFiles();
// 拷贝的是文件
if (fileList) {
window.setSubInputValue({ value: "" });
clipboardFile.value = fileList;
const localPlugins = remote.getGlobal("LOCAL_PLUGINS").getLocalPlugins();
const options: any = [
{
name: "复制路径",
value: "plugin",
icon: require("../assets/link.png"),
desc: "复制路径到剪切板",
click: () => {
clipboard.writeText(fileList.map(file => file.path).join(","));
ipcRenderer.send("msg-trigger", { type: "hideMainWindow" });
},
},
];
// 判断复制的文件类型是否一直
const commonLen = fileList.filter(
(file) => path.extname(fileList[0].path) === path.extname(file.path)
).length;
// 复制路径
if (commonLen !== fileList.length) {
setOptionsRef(options);
return;
}
// 再正则插件
localPlugins.forEach((plugin) => {
const feature = plugin.features;
// 系统插件无 features 的情况,不需要再搜索
if (!feature) return;
feature.forEach((fe) => {
const ext = path.extname(fileList[0].path);
fe.cmds.forEach((cmd) => {
const regImg = /\.(png|jpg|gif|jpeg|webp)$/;
if (cmd.type === "img" && regImg.test(ext) && fileList.length === 1) {
options.push({
name: cmd.label,
value: "plugin",
icon: plugin.logo,
desc: fe.explain,
type: plugin.pluginType,
click: () => {
pluginClickEvent({
plugin,
fe,
cmd,
ext: {
code: fe.code,
type: cmd.type || "text",
payload: nativeImage.createFromPath(fileList[0].path).toDataURL(),
},
openPlugin,
});
clearClipboardFile();
},
});
}
// 如果是文件,且符合文件正则类型
if (
fileList.length > 1 ||
(cmd.type === "file" && new RegExp(cmd.match).test(ext))
) {
options.push({
name: cmd,
value: "plugin",
icon: plugin.logo,
desc: fe.explain,
type: plugin.pluginType,
click: () => {
pluginClickEvent({
plugin,
fe,
cmd,
ext: {
code: fe.code,
type: cmd.type || "text",
payload: fileList,
},
openPlugin,
});
clearClipboardFile();
},
});
}
});
});
});
setOptionsRef(options);
clipboard.clear();
return;
}
const clipboardType = clipboard.availableFormats();
if (!clipboardType.length) return;
if ("text/plain" === clipboardType[0]) {
const contentText = clipboard.readText();
if (contentText.trim()) {
clearClipboardFile();
window.setSubInputValue({ value: contentText });
}
}
clipboard.clear();
};
const clearClipboardFile = () => {
clipboardFile.value = [];
optionsRef.value = [];
};
return {
searchFocus,
clipboardFile,
clearClipboardFile,
};
};

View File

@ -39,7 +39,7 @@ const createPluginManager = (): any => {
plugin: JSON.parse( plugin: JSON.parse(
JSON.stringify({ JSON.stringify({
...plugin, ...plugin,
ext: { ext: plugin.ext || {
code: plugin.feature.code, code: plugin.feature.code,
type: plugin.cmd.type || "text", type: plugin.cmd.type || "text",
payload: null, payload: null,
@ -54,16 +54,21 @@ const createPluginManager = (): any => {
} }
}; };
const { searchValue, onSearch, setSearchValue, placeholder } = searchManager(); const { searchValue, onSearch, setSearchValue, placeholder } =
const { options } = optionsManager({ searchManager();
searchValue, const { options, searchFocus, clipboardFile, clearClipboardFile } =
appList, optionsManager({
openPlugin, searchValue,
currentPlugin: toRefs(state).currentPlugin, appList,
}); openPlugin,
currentPlugin: toRefs(state).currentPlugin,
});
// plugin operation // plugin operation
const getPluginInfo = async ({ pluginName, pluginPath }) => { const getPluginInfo = async ({ pluginName, pluginPath }) => {
const pluginInfo = await pluginInstance.getAdapterInfo(pluginName, pluginPath); const pluginInfo = await pluginInstance.getAdapterInfo(
pluginName,
pluginPath
);
return { return {
...pluginInfo, ...pluginInfo,
indexPath: commonConst.dev() indexPath: commonConst.dev()
@ -115,6 +120,9 @@ const createPluginManager = (): any => {
options, options,
searchValue, searchValue,
placeholder, placeholder,
searchFocus,
clipboardFile,
clearClipboardFile,
}; };
}; };

View File

@ -1,27 +1,44 @@
import { ref, toRaw, toRefs, watch } from "vue"; import { ref, watch } from "vue";
import throttle from "lodash.throttle"; import throttle from "lodash.throttle";
import { remote } from "electron"; import { remote } from "electron";
import path from "path"; import pluginClickEvent from "./pluginClickEvent";
import { PLUGIN_INSTALL_DIR as baseDir } from "@/common/constans/renderer"; import useFocus from "./clipboardWatch";
import commonConst from "@/common/utils/commonConst";
function formatReg(regStr) {
const flags = regStr.replace(/.*\/([gimy]*)$/, "$1");
const pattern = flags.replace(new RegExp("^/(.*?)/" + flags + "$"), "$1");
return new RegExp(pattern, flags);
}
function searchKeyValues(lists, value) { function searchKeyValues(lists, value) {
return lists.filter((item) => { return lists.filter((item) => {
if (typeof item === "string") { if (typeof item === "string") {
return item.toLowerCase().indexOf(value.toLowerCase()) >= 0; return item.toLowerCase().indexOf(value.toLowerCase()) >= 0;
} }
return item.type.toLowerCase().indexOf(value.toLowerCase()) >= 0; if (item.type === "regex") {
return formatReg(item.match).test(value);
}
return false;
}); });
} }
const optionsManager = ({ searchValue, appList, openPlugin, currentPlugin }) => { const optionsManager = ({
searchValue,
appList,
openPlugin,
currentPlugin,
}) => {
const optionsRef = ref([]); const optionsRef = ref([]);
watch(searchValue, () => search(searchValue.value)); watch(searchValue, () => search(searchValue.value));
// search Input operation // search Input operation
const search = throttle((value) => { const search = throttle((value) => {
if (currentPlugin.value.name) return; if (currentPlugin.value.name) return;
if (!value) return; if (clipboardFile.value.length) return;
if (!value) {
optionsRef.value = [];
return;
}
const localPlugins = remote.getGlobal("LOCAL_PLUGINS").getLocalPlugins(); const localPlugins = remote.getGlobal("LOCAL_PLUGINS").getLocalPlugins();
let options: any = []; let options: any = [];
// todo 先搜索 plugin // todo 先搜索 plugin
@ -34,34 +51,25 @@ const optionsManager = ({ searchValue, appList, openPlugin, currentPlugin }) =>
options = [ options = [
...options, ...options,
...cmds.map((cmd) => ({ ...cmds.map((cmd) => ({
name: cmd, name: cmd.label || cmd,
value: "plugin", value: "plugin",
icon: plugin.logo, icon: plugin.logo,
desc: fe.explain, desc: fe.explain,
type: plugin.pluginType, type: plugin.pluginType,
click: () => { click: () => {
const pluginPath = path.resolve( pluginClickEvent({
baseDir, plugin,
"node_modules", fe,
plugin.name
);
const pluginDist = {
...toRaw(plugin),
indexPath: `file://${path.join(
pluginPath,
"./",
plugin.main || ""
)}`,
cmd, cmd,
feature: fe, ext: cmd.type
}; ? {
// 模板文件 code: fe.code,
if (!plugin.main) { type: cmd.type || "text",
pluginDist.tplPath = commonConst.dev() payload: searchValue.value,
? "http://localhost:8082/#/" }
: `file://${__static}/tpl/index.html`; : null,
} openPlugin,
openPlugin(pluginDist); });
}, },
})), })),
]; ];
@ -104,8 +112,22 @@ const optionsManager = ({ searchValue, appList, openPlugin, currentPlugin }) =>
optionsRef.value = options; optionsRef.value = options;
}, 500); }, 500);
const setOptionsRef = (options) => {
optionsRef.value = options;
};
const { searchFocus, clipboardFile, clearClipboardFile } = useFocus({
currentPlugin,
optionsRef,
openPlugin,
setOptionsRef,
});
return { return {
options: optionsRef, options: optionsRef,
searchFocus,
clipboardFile,
clearClipboardFile,
}; };
}; };

View File

@ -0,0 +1,30 @@
import { PLUGIN_INSTALL_DIR as baseDir } from "@/common/constans/renderer";
import path from "path";
import { toRaw } from "vue";
import commonConst from "@/common/utils/commonConst";
export default function pluginClickEvent({ plugin, fe, cmd, ext, openPlugin }) {
const pluginPath = path.resolve(
baseDir,
"node_modules",
plugin.name
);
const pluginDist = {
...toRaw(plugin),
indexPath: `file://${path.join(
pluginPath,
"./",
plugin.main || ""
)}`,
cmd: cmd.label || cmd,
feature: fe,
ext,
};
// 模板文件
if (!plugin.main) {
pluginDist.tplPath = commonConst.dev()
? "http://localhost:8082/#/"
: `file://${__static}/tpl/index.html`;
}
openPlugin(pluginDist);
}

View File

@ -6,12 +6,12 @@
import { useRouter } from "vue-router"; import { useRouter } from "vue-router";
const router = useRouter(); const router = useRouter();
window.rubick.onPluginEnter(({ code }) => { window.rubick.onPluginEnter(({ code, type, payload }) => {
const current = window.exports[code]; const current = window.exports[code];
router.push({ router.push({
name: current.mode, name: current.mode,
params: { params: {
code, code, type, payload
}, },
}); });
}); });

View File

@ -7,7 +7,7 @@
v-for="(item, index) in lists" v-for="(item, index) in lists"
@click="select(item)" @click="select(item)"
> >
<img class="icon" :src="item.icon" /> <img v-if="item.icon" class="icon" :src="item.icon" />
<div class="content"> <div class="content">
<div class="title">{{ item.title }}</div> <div class="title">{{ item.title }}</div>
<div class="desc">{{ decodeURIComponent(item.description) }}</div> <div class="desc">{{ decodeURIComponent(item.description) }}</div>
@ -18,7 +18,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { useRoute } from "vue-router"; import { useRoute } from "vue-router";
import { ref, onBeforeUnmount } from "vue"; import { ref, onBeforeUnmount, watch } from "vue";
const { ipcRenderer } = window.require("electron"); const { ipcRenderer } = window.require("electron");
const route = useRoute(); const route = useRoute();
@ -27,14 +27,18 @@ const itemHeight = 60;
const itemMaxNum = 10; const itemMaxNum = 10;
const defaultHeight = 60; const defaultHeight = 60;
const code = route.params.code; const { code, type, payload } = route.params;
const current = window.exports[code]; const current = window.exports[code];
window.rubick.setExpendHeight(defaultHeight); window.rubick.setExpendHeight(defaultHeight);
const lists = ref([]); const lists = ref([]);
watch([lists], () => {
const height = lists.value.length > itemMaxNum ? itemMaxNum * itemHeight : itemHeight * lists.value.length
window.rubick.setExpendHeight(defaultHeight + height);
});
current.args.enter && current.args.enter &&
current.args.enter({ code: code, type: "", payload: [] }, (lists) => { current.args.enter({ code: code, type, payload }, (result) => {
lists.value = lists; lists.value = result;
}); });
const currentSelect = ref(0); const currentSelect = ref(0);
@ -51,8 +55,6 @@ window.rubick.setSubInput(({ text }) => {
current.args.search && current.args.search &&
current.args.search({ code, type: "", payload: [] }, text, (result) => { current.args.search({ code, type: "", payload: [] }, text, (result) => {
lists.value = result || []; lists.value = result || [];
const height = lists.value.length > itemMaxNum ? itemMaxNum * itemHeight : itemHeight * lists.value.length
window.rubick.setExpendHeight(defaultHeight + height);
}); });
}, "搜索"); }, "搜索");