mirror of
https://github.com/rubickCenter/rubick
synced 2025-06-07 11:04:11 +08:00
✨ 支持文件检索呼起插件
This commit is contained in:
parent
ced8aa846b
commit
ff118dfe2d
2
package-lock.json
generated
2
package-lock.json
generated
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "rubick",
|
||||
"version": "2.0.0",
|
||||
"version": "2.0.1-beta.3",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "rubick",
|
||||
"version": "2.0.1-beta.3",
|
||||
"version": "2.0.1-beta.4",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"serve": "vue-cli-service serve",
|
||||
|
@ -132,4 +132,6 @@ window.rubick = {
|
||||
shellOpenPath(path) {
|
||||
shell.openPath(path);
|
||||
},
|
||||
|
||||
getLocalId: () => ipcSendSync("getLocalId"),
|
||||
};
|
||||
|
@ -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>
|
2
public/tpl/js/app.6e04bbe2.js
Normal file
2
public/tpl/js/app.6e04bbe2.js
Normal 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
|
1
public/tpl/js/app.6e04bbe2.js.map
Normal file
1
public/tpl/js/app.6e04bbe2.js.map
Normal file
File diff suppressed because one or more lines are too long
@ -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
8
public/tpl/js/chunk-vendors.88fb06db.js
Normal file
8
public/tpl/js/chunk-vendors.88fb06db.js
Normal file
File diff suppressed because one or more lines are too long
1
public/tpl/js/chunk-vendors.88fb06db.js.map
Normal file
1
public/tpl/js/chunk-vendors.88fb06db.js.map
Normal file
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
49
src/common/utils/getCopyFiles.ts
Normal file
49
src/common/utils/getCopyFiles.ts
Normal 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;
|
||||
}
|
@ -10,7 +10,10 @@
|
||||
:searchValue="searchValue"
|
||||
:placeholder="placeholder"
|
||||
:pluginLoading="pluginLoading"
|
||||
:clipboardFile="clipboardFile || []"
|
||||
@choosePlugin="choosePlugin"
|
||||
@focus="searchFocus"
|
||||
@clearClipbord="clearClipboardFile"
|
||||
/>
|
||||
</div>
|
||||
<Result
|
||||
@ -18,6 +21,7 @@
|
||||
:searchValue="searchValue"
|
||||
:currentSelect="currentSelect"
|
||||
:options="options"
|
||||
:clipboardFile="clipboardFile || []"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
@ -41,6 +45,9 @@ const {
|
||||
currentPlugin,
|
||||
placeholder,
|
||||
pluginLoading,
|
||||
searchFocus,
|
||||
clipboardFile,
|
||||
clearClipboardFile,
|
||||
} = createPluginManager();
|
||||
|
||||
initPlugins();
|
||||
@ -57,13 +64,13 @@ getPluginInfo({
|
||||
remote.getGlobal("LOCAL_PLUGINS").addPlugin(res);
|
||||
});
|
||||
|
||||
watch([searchValue], () => {
|
||||
watch([options], () => {
|
||||
currentSelect.value = 0;
|
||||
if (currentPlugin.value.name) return;
|
||||
nextTick(() => {
|
||||
ipcRenderer.sendSync("msg-trigger", {
|
||||
type: "setExpendHeight",
|
||||
data: getWindowHeight(searchValue.value ? options.value : []),
|
||||
data: getWindowHeight(options.value),
|
||||
});
|
||||
});
|
||||
});
|
||||
|
BIN
src/renderer/assets/file.png
Normal file
BIN
src/renderer/assets/file.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.9 KiB |
BIN
src/renderer/assets/folder.png
Normal file
BIN
src/renderer/assets/folder.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.6 KiB |
BIN
src/renderer/assets/link.png
Normal file
BIN
src/renderer/assets/link.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.4 KiB |
@ -1,5 +1,5 @@
|
||||
<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">
|
||||
<template #renderItem="{ item, index }">
|
||||
<a-list-item
|
||||
@ -46,10 +46,12 @@ const props = defineProps({
|
||||
default: 0,
|
||||
},
|
||||
currentPlugin: {},
|
||||
clipboardFile: () => [],
|
||||
});
|
||||
|
||||
const renderTitle = (title) => {
|
||||
if (typeof title !== "string") return;
|
||||
if (!props.searchValue) return title;
|
||||
const result = title.toLowerCase().split(props.searchValue.toLowerCase());
|
||||
if (result && result.length > 1) {
|
||||
return `<div>${result[0]}<span style="color: red">${props.searchValue}</span>${result[1]}</div>`;
|
||||
|
@ -1,6 +1,10 @@
|
||||
<template>
|
||||
<div class="rubick-select">
|
||||
<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
|
||||
id="search"
|
||||
class="main-input"
|
||||
@ -11,6 +15,7 @@
|
||||
:value="searchValue"
|
||||
:placeholder="placeholder || 'Hi, Rubick2'"
|
||||
@keypress.enter="(e) => keydownEvent(e)"
|
||||
@focus="emit('focus')"
|
||||
>
|
||||
<template #suffix>
|
||||
<div class="suffix-tool" >
|
||||
@ -36,15 +41,16 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { defineProps, defineEmits, ref } from "vue";
|
||||
import { defineProps, defineEmits, ref, computed } from "vue";
|
||||
import { ipcRenderer, remote } from "electron";
|
||||
import { LoadingOutlined, MoreOutlined } from "@ant-design/icons-vue";
|
||||
|
||||
const opConfig = remote.getGlobal("OP_CONFIG");
|
||||
const { Menu } = remote;
|
||||
|
||||
const config = ref(opConfig.get());
|
||||
|
||||
const props = defineProps({
|
||||
const props: any = defineProps({
|
||||
searchValue: {
|
||||
type: [String, Number],
|
||||
default: "",
|
||||
@ -55,6 +61,7 @@ const props = defineProps({
|
||||
},
|
||||
currentPlugin: {},
|
||||
pluginLoading: Boolean,
|
||||
clipboardFile: () => [],
|
||||
});
|
||||
|
||||
const changeValue = (e) => {
|
||||
@ -69,11 +76,12 @@ const emit = defineEmits([
|
||||
"openMenu",
|
||||
"changeSelect",
|
||||
"choosePlugin",
|
||||
"focus",
|
||||
]);
|
||||
|
||||
const keydownEvent = (e, index) => {
|
||||
const { ctrlKey, shiftKey, altKey, metaKey } = e;
|
||||
const modifiers = [];
|
||||
const modifiers: Array<string> = [];
|
||||
ctrlKey && modifiers.push("control");
|
||||
shiftKey && modifiers.push("shift");
|
||||
altKey && modifiers.push("alt");
|
||||
@ -98,7 +106,7 @@ const checkNeedInit = (e) => {
|
||||
}
|
||||
};
|
||||
|
||||
const targetSearch = ({ value, type }) => {
|
||||
const targetSearch = ({ value }) => {
|
||||
if (props.currentPlugin.name) {
|
||||
return ipcRenderer.sendSync("msg-trigger", {
|
||||
type: "sendSubInputChangeEvent",
|
||||
@ -109,13 +117,14 @@ const targetSearch = ({ value, type }) => {
|
||||
|
||||
const closeTag = () => {
|
||||
emit("changeSelect", {});
|
||||
emit("clearClipbord");
|
||||
ipcRenderer.send("msg-trigger", {
|
||||
type: "removePlugin",
|
||||
});
|
||||
};
|
||||
|
||||
const showSeparate = () => {
|
||||
let pluginMenu = [
|
||||
let pluginMenu: any = [
|
||||
{
|
||||
label: config.value.perf.common.hideOnBlur ? "钉住" : "自动隐藏",
|
||||
click: changeHideOnBlur,
|
||||
@ -233,5 +242,22 @@ const newWindow = () => {
|
||||
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>
|
||||
|
133
src/renderer/plugins-manager/clipboardWatch.ts
Normal file
133
src/renderer/plugins-manager/clipboardWatch.ts
Normal 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,
|
||||
};
|
||||
};
|
@ -39,7 +39,7 @@ const createPluginManager = (): any => {
|
||||
plugin: JSON.parse(
|
||||
JSON.stringify({
|
||||
...plugin,
|
||||
ext: {
|
||||
ext: plugin.ext || {
|
||||
code: plugin.feature.code,
|
||||
type: plugin.cmd.type || "text",
|
||||
payload: null,
|
||||
@ -54,16 +54,21 @@ const createPluginManager = (): any => {
|
||||
}
|
||||
};
|
||||
|
||||
const { searchValue, onSearch, setSearchValue, placeholder } = searchManager();
|
||||
const { options } = optionsManager({
|
||||
searchValue,
|
||||
appList,
|
||||
openPlugin,
|
||||
currentPlugin: toRefs(state).currentPlugin,
|
||||
});
|
||||
const { searchValue, onSearch, setSearchValue, placeholder } =
|
||||
searchManager();
|
||||
const { options, searchFocus, clipboardFile, clearClipboardFile } =
|
||||
optionsManager({
|
||||
searchValue,
|
||||
appList,
|
||||
openPlugin,
|
||||
currentPlugin: toRefs(state).currentPlugin,
|
||||
});
|
||||
// plugin operation
|
||||
const getPluginInfo = async ({ pluginName, pluginPath }) => {
|
||||
const pluginInfo = await pluginInstance.getAdapterInfo(pluginName, pluginPath);
|
||||
const pluginInfo = await pluginInstance.getAdapterInfo(
|
||||
pluginName,
|
||||
pluginPath
|
||||
);
|
||||
return {
|
||||
...pluginInfo,
|
||||
indexPath: commonConst.dev()
|
||||
@ -115,6 +120,9 @@ const createPluginManager = (): any => {
|
||||
options,
|
||||
searchValue,
|
||||
placeholder,
|
||||
searchFocus,
|
||||
clipboardFile,
|
||||
clearClipboardFile,
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -1,27 +1,44 @@
|
||||
import { ref, toRaw, toRefs, watch } from "vue";
|
||||
import { ref, watch } from "vue";
|
||||
import throttle from "lodash.throttle";
|
||||
import { remote } from "electron";
|
||||
import path from "path";
|
||||
import { PLUGIN_INSTALL_DIR as baseDir } from "@/common/constans/renderer";
|
||||
import commonConst from "@/common/utils/commonConst";
|
||||
import pluginClickEvent from "./pluginClickEvent";
|
||||
import useFocus from "./clipboardWatch";
|
||||
|
||||
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) {
|
||||
return lists.filter((item) => {
|
||||
if (typeof item === "string") {
|
||||
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([]);
|
||||
|
||||
watch(searchValue, () => search(searchValue.value));
|
||||
// search Input operation
|
||||
const search = throttle((value) => {
|
||||
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();
|
||||
let options: any = [];
|
||||
// todo 先搜索 plugin
|
||||
@ -34,34 +51,25 @@ const optionsManager = ({ searchValue, appList, openPlugin, currentPlugin }) =>
|
||||
options = [
|
||||
...options,
|
||||
...cmds.map((cmd) => ({
|
||||
name: cmd,
|
||||
name: cmd.label || cmd,
|
||||
value: "plugin",
|
||||
icon: plugin.logo,
|
||||
desc: fe.explain,
|
||||
type: plugin.pluginType,
|
||||
click: () => {
|
||||
const pluginPath = path.resolve(
|
||||
baseDir,
|
||||
"node_modules",
|
||||
plugin.name
|
||||
);
|
||||
const pluginDist = {
|
||||
...toRaw(plugin),
|
||||
indexPath: `file://${path.join(
|
||||
pluginPath,
|
||||
"./",
|
||||
plugin.main || ""
|
||||
)}`,
|
||||
pluginClickEvent({
|
||||
plugin,
|
||||
fe,
|
||||
cmd,
|
||||
feature: fe,
|
||||
};
|
||||
// 模板文件
|
||||
if (!plugin.main) {
|
||||
pluginDist.tplPath = commonConst.dev()
|
||||
? "http://localhost:8082/#/"
|
||||
: `file://${__static}/tpl/index.html`;
|
||||
}
|
||||
openPlugin(pluginDist);
|
||||
ext: cmd.type
|
||||
? {
|
||||
code: fe.code,
|
||||
type: cmd.type || "text",
|
||||
payload: searchValue.value,
|
||||
}
|
||||
: null,
|
||||
openPlugin,
|
||||
});
|
||||
},
|
||||
})),
|
||||
];
|
||||
@ -104,8 +112,22 @@ const optionsManager = ({ searchValue, appList, openPlugin, currentPlugin }) =>
|
||||
optionsRef.value = options;
|
||||
}, 500);
|
||||
|
||||
const setOptionsRef = (options) => {
|
||||
optionsRef.value = options;
|
||||
};
|
||||
|
||||
const { searchFocus, clipboardFile, clearClipboardFile } = useFocus({
|
||||
currentPlugin,
|
||||
optionsRef,
|
||||
openPlugin,
|
||||
setOptionsRef,
|
||||
});
|
||||
|
||||
return {
|
||||
options: optionsRef,
|
||||
searchFocus,
|
||||
clipboardFile,
|
||||
clearClipboardFile,
|
||||
};
|
||||
};
|
||||
|
||||
|
30
src/renderer/plugins-manager/pluginClickEvent.ts
Normal file
30
src/renderer/plugins-manager/pluginClickEvent.ts
Normal 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);
|
||||
}
|
@ -6,12 +6,12 @@
|
||||
import { useRouter } from "vue-router";
|
||||
|
||||
const router = useRouter();
|
||||
window.rubick.onPluginEnter(({ code }) => {
|
||||
window.rubick.onPluginEnter(({ code, type, payload }) => {
|
||||
const current = window.exports[code];
|
||||
router.push({
|
||||
name: current.mode,
|
||||
params: {
|
||||
code,
|
||||
code, type, payload
|
||||
},
|
||||
});
|
||||
});
|
||||
|
@ -7,7 +7,7 @@
|
||||
v-for="(item, index) in lists"
|
||||
@click="select(item)"
|
||||
>
|
||||
<img class="icon" :src="item.icon" />
|
||||
<img v-if="item.icon" class="icon" :src="item.icon" />
|
||||
<div class="content">
|
||||
<div class="title">{{ item.title }}</div>
|
||||
<div class="desc">{{ decodeURIComponent(item.description) }}</div>
|
||||
@ -18,7 +18,7 @@
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { useRoute } from "vue-router";
|
||||
import { ref, onBeforeUnmount } from "vue";
|
||||
import { ref, onBeforeUnmount, watch } from "vue";
|
||||
const { ipcRenderer } = window.require("electron");
|
||||
|
||||
const route = useRoute();
|
||||
@ -27,14 +27,18 @@ const itemHeight = 60;
|
||||
const itemMaxNum = 10;
|
||||
const defaultHeight = 60;
|
||||
|
||||
const code = route.params.code;
|
||||
const { code, type, payload } = route.params;
|
||||
const current = window.exports[code];
|
||||
window.rubick.setExpendHeight(defaultHeight);
|
||||
|
||||
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({ code: code, type: "", payload: [] }, (lists) => {
|
||||
lists.value = lists;
|
||||
current.args.enter({ code: code, type, payload }, (result) => {
|
||||
lists.value = result;
|
||||
});
|
||||
|
||||
const currentSelect = ref(0);
|
||||
@ -51,8 +55,6 @@ window.rubick.setSubInput(({ text }) => {
|
||||
current.args.search &&
|
||||
current.args.search({ code, type: "", payload: [] }, text, (result) => {
|
||||
lists.value = result || [];
|
||||
const height = lists.value.length > itemMaxNum ? itemMaxNum * itemHeight : itemHeight * lists.value.length
|
||||
window.rubick.setExpendHeight(defaultHeight + height);
|
||||
});
|
||||
}, "搜索");
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user