Compare commits
85 Commits
7e66b3f3e9
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0d39d2b9ce | ||
|
|
a05860bc6a | ||
|
|
3b4ca0e289 | ||
|
|
b75188fdb8 | ||
|
|
bf3ae7c9ba | ||
|
|
b7b16e2f3e | ||
|
|
3fec3665b6 | ||
|
|
b7587a454f | ||
|
|
f5f3f030ce | ||
|
|
0bddb33fde | ||
|
|
9005d070aa | ||
|
|
9adfa84cab | ||
|
|
15c160e45d | ||
|
|
6bf613042a | ||
|
|
04fe2e03a6 | ||
|
|
6c0d34fc4f | ||
|
|
3fa9bb0384 | ||
|
|
791115901a | ||
|
|
a879ed6555 | ||
|
|
28b58e7976 | ||
|
|
dc54b25f84 | ||
|
|
fc51a383bf | ||
|
|
a546bc0d59 | ||
|
|
c732e448c3 | ||
|
|
fbc7da0606 | ||
|
|
6315ec12ae | ||
|
|
3ba8250d7c | ||
|
|
706aa84374 | ||
|
|
f70bf3983e | ||
|
|
47359308fc | ||
|
|
3f03e5578e | ||
|
|
7cabbe26f5 | ||
|
|
5c048c6341 | ||
|
|
e90a30c8a4 | ||
|
|
599538db76 | ||
|
|
e9c41b6bdb | ||
|
|
1e7a8209b7 | ||
|
|
481cd44ab3 | ||
|
|
d41caa742b | ||
|
|
69218a728b | ||
|
|
73cef1512c | ||
|
|
986ad42ed7 | ||
|
|
42aec3403a | ||
|
|
8c15dba68d | ||
|
|
37647de7a8 | ||
|
|
1b2c9b3577 | ||
|
|
7cb832829d | ||
|
|
02da06c450 | ||
|
|
e613fc19d4 | ||
|
|
c7807aeb3f | ||
|
|
9813573679 | ||
|
|
61ec18f0dc | ||
|
|
5ca1ba1271 | ||
|
|
8c3186afef | ||
|
|
de0e9ed8f2 | ||
|
|
ef85084730 | ||
|
|
b4b7c81b60 | ||
|
|
4b79cce2f4 | ||
|
|
ae10dac5f7 | ||
|
|
1e0babe22d | ||
|
|
5ec18caa72 | ||
|
|
b7d8932291 | ||
|
|
5608a147f7 | ||
|
|
132fb94289 | ||
|
|
bb1a74b3b9 | ||
|
|
bf9da854c7 | ||
|
|
a2c5bcc90c | ||
|
|
b9f4333c01 | ||
|
|
bbeddb3fe6 | ||
|
|
4a2ca33e02 | ||
|
|
0578c7c7eb | ||
|
|
ef34452a4f | ||
|
|
286d9da8d1 | ||
|
|
6b9d5182bf | ||
|
|
2053491782 | ||
|
|
e128d01b81 | ||
|
|
c3bc0bdb9e | ||
|
|
f1f4e62177 | ||
|
|
c07d4bae55 | ||
|
|
c78dd9c4b6 | ||
|
|
2dd4ed10cc | ||
|
|
70ce3dd037 | ||
|
|
a0644c0ccf | ||
|
|
583e9934fa | ||
|
|
472879f9b2 |
4
.github/workflows/main.yml
vendored
@@ -23,7 +23,7 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
os: [macos-11, windows-2019, ubuntu-latest]
|
os: [macos-latest, windows-2022, ubuntu-latest]
|
||||||
|
|
||||||
# create steps
|
# create steps
|
||||||
steps:
|
steps:
|
||||||
@@ -52,7 +52,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
yarn
|
yarn
|
||||||
yarn global add xvfb-maybe
|
yarn global add xvfb-maybe
|
||||||
yarn global add @vue/cli
|
yarn global add @vue/cli@4.5.0 --frozen-lockfile --ignore-engines
|
||||||
- name: Build feature
|
- name: Build feature
|
||||||
run: |
|
run: |
|
||||||
cd ./feature
|
cd ./feature
|
||||||
|
|||||||
2
.npmrc
@@ -1 +1 @@
|
|||||||
electron_mirror=https://npm.taobao.org/mirrors/electron/
|
electron_mirror=https://npmmirror.com/mirrors/electron/
|
||||||
|
|||||||
41
README.md
@@ -1,36 +1,22 @@
|
|||||||
English | [简体中文](./README.zh-CN.md)
|
English | [简体中文](./README.zh-CN.md)
|
||||||
|
|
||||||
|
|
||||||
<div align= "center">
|
<div align= "center">
|
||||||
<img align="center" width=200 src="https://user-images.githubusercontent.com/21073039/128333805-73e086f0-5523-46a3-a096-cba80b904c46.png" />
|
<img align="center" width=200 src="./public/logo.png" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div align="center">
|
||||||
<div align= "center">
|
<h1>Rubick</h1>
|
||||||
<h1>Rubick</h1>
|
<img alt="downloads" src="https://img.shields.io/github/downloads/rubickCenter/rubick/total" />
|
||||||
|
<a href="https://github.com/rubickCenter/rubick/releases"><img alt="latest release" src="https://img.shields.io/github/package-json/v/rubickCenter/rubick" /></a>
|
||||||
<img alt="release" src="https://img.shields.io/github/downloads/rubickCenter/rubick/total" />
|
<a href="https://github.com/rubickCenter/rubick/actions"><img alt="github action building" src="https://img.shields.io/github/actions/workflow/status/rubickCenter/rubick/main.yml" /></a>
|
||||||
<a href="https://github.com/rubickCenter/rubick/releases">
|
<a href="https://github.com/rubickCenter/rubick/blob/master/LICENSE"><img alt="license" src="https://img.shields.io/github/license/rubickCenter/rubick" /></a>
|
||||||
<img alt="release" src="https://img.shields.io/github/package-json/v/rubickCenter/rubick" />
|
<a href="https://github.com/rubickCenter/rubick/stargazers"><img alt="github stars" src="https://img.shields.io/github/stars/rubickCenter/rubick?style=social" /></a>
|
||||||
</a>
|
<a href="https://gitee.com/monkeyWang/rubick"><img alt="gitee mirror" src="https://img.shields.io/badge/Gitee--yellow.svg?style=social&logo=data:image/svg+xml;base64,PHN2ZyB0PSIxNTc0ODM3MTM4ODM3IiBjbGFzcz0iaWNvbiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHAtaWQ9IjE3NzAiICAgICB3aWR0aD0iMTYiIGhlaWdodD0iMTYiPiAgICA8cGF0aCBkPSJNODkxIDQyOC44SDQ2NS44Yy0yMC40IDAtMzcgMTYuNS0zNyAzN3Y5Mi40YzAgMjAuNCAxNi41IDM3IDM3IDM3aDI1OC45YzIwLjQgMCAzNyAxNi42IDM3IDM3djE4LjRjMCA2MS4zLTQ5LjcgMTEwLjktMTEwLjkgMTEwLjlIMjk5LjRjLTIwLjQgMC0zNy0xNi42LTM3LTM3VjM3My4yYzAtNjEuMyA0OS43LTExMC45IDExMC45LTExMC45aDUxNy42YzIwLjQgMCAzNy0xNi41IDM3LTM3bDAuMS05Mi4zYzAtMjAuNC0xNi41LTM3LTM3LTM3SDM3My4zQzIyMC4yIDk2IDk2IDIyMC4yIDk2IDM3My4zVjg5MWMwIDIwLjQgMTYuNiAzNyAzNyAzN2g1NDUuNEM4MTYuMiA5MjggOTI4IDgxNi4zIDkyOCA2NzguNFY0NjUuOGMwLTIwLjQtMTYuNi0zNy0zNy0zN3oiICAgICAgICAgIGZpbGw9IiNkODFlMDYiIHAtaWQ9IjE3NzEiPjwvcGF0aD48L3N2Zz4=" /></a>
|
||||||
<a href="https://github.com/rubickCenter/rubick/actions">
|
|
||||||
<img alt=building src=https://img.shields.io/github/actions/workflow/status/rubickCenter/rubick/main.yml>
|
|
||||||
</a>
|
|
||||||
<a href="https://github.com/rubickCenter/rubick/blob/master/LICENSE">
|
|
||||||
<img alt="npm" src="https://img.shields.io/github/license/rubickCenter/rubick" />
|
|
||||||
</a>
|
|
||||||
<a href="https://github.com/rubickCenter/rubick/stargazers">
|
|
||||||
<img alt="star" src="https://img.shields.io/github/stars/rubickCenter/rubick?style=social">
|
|
||||||
</a>
|
|
||||||
<a href="https://gitee.com/monkeyWang/rubick">
|
|
||||||
<img alt="码云" src="https://img.shields.io/badge/Gitee--yellow.svg?style=social&logo=data:image/svg+xml;base64,PHN2ZyB0PSIxNTc0ODM3MTM4ODM3IiBjbGFzcz0iaWNvbiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHAtaWQ9IjE3NzAiICAgICB3aWR0aD0iMTYiIGhlaWdodD0iMTYiPiAgICA8cGF0aCBkPSJNODkxIDQyOC44SDQ2NS44Yy0yMC40IDAtMzcgMTYuNS0zNyAzN3Y5Mi40YzAgMjAuNCAxNi41IDM3IDM3IDM3aDI1OC45YzIwLjQgMCAzNyAxNi42IDM3IDM3djE4LjRjMCA2MS4zLTQ5LjcgMTEwLjktMTEwLjkgMTEwLjlIMjk5LjRjLTIwLjQgMC0zNy0xNi42LTM3LTM3VjM3My4yYzAtNjEuMyA0OS43LTExMC45IDExMC45LTExMC45aDUxNy42YzIwLjQgMCAzNy0xNi41IDM3LTM3bDAuMS05Mi4zYzAtMjAuNC0xNi41LTM3LTM3LTM3SDM3My4zQzIyMC4yIDk2IDk2IDIyMC4yIDk2IDM3My4zVjg5MWMwIDIwLjQgMTYuNiAzNyAzNyAzN2g1NDUuNEM4MTYuMiA5MjggOTI4IDgxNi4zIDkyOCA2NzguNFY0NjUuOGMwLTIwLjQtMTYuNi0zNy0zNy0zN3oiICAgICAgICAgIGZpbGw9IiNkODFlMDYiIHAtaWQ9IjE3NzEiPjwvcGF0aD48L3N2Zz4="/>
|
|
||||||
</a>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div align= "center">
|
<div align= "center">
|
||||||
<img align="center" src="https://picx.zhimg.com/80/v2-f8fe09ef125dac5fdcbef3fe00f92b21_720w.png" />
|
<img align="center" src="https://picx.zhimg.com/80/v2-f8fe09ef125dac5fdcbef3fe00f92b21_720w.png" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
Open-source plugin-based desktop efficiency toolbox. The plugins are installed and uninstalled based on npm, which is very lightweight. The plugin data supports webdav multi-terminal synchronization, which is very secure. It supports internal network deployment and can be customized for further development, which is very flexible.
|
Open-source plugin-based desktop efficiency toolbox. The plugins are installed and uninstalled based on npm, which is very lightweight. The plugin data supports webdav multi-terminal synchronization, which is very secure. It supports internal network deployment and can be customized for further development, which is very flexible.
|
||||||
|
|
||||||
## Get Rubick
|
## Get Rubick
|
||||||
@@ -104,11 +90,20 @@ If the project is helpful to you, you can buy me a cup of coffee as a reward!
|
|||||||
<img width="180" src="https://picx.zhimg.com/80/v2-3160247d6099053405e6cd2cb6afb5e5_720w.png">
|
<img width="180" src="https://picx.zhimg.com/80/v2-3160247d6099053405e6cd2cb6afb5e5_720w.png">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
## 友情链接
|
||||||
|
|
||||||
|
<a href="https://pro.kuaitu.cc/" target="_blank">
|
||||||
|
<img width="100" src="https://github.com/user-attachments/assets/6127488e-466b-4e71-98ab-00fb3c76553e" />
|
||||||
|
</a>
|
||||||
|
|
||||||
|
|
||||||
## Feedback
|
## Feedback
|
||||||
Those who are interested in this project or want to exchange and learn can scan the QR code and add the following WeChat, with the comment rubick, to help us grow better.
|
Those who are interested in this project or want to exchange and learn can scan the QR code and add the following WeChat, with the comment rubick, to help us grow better.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
<a href="https://hellogithub.com/repository/0a3e2484b44e481e9dcf1850e45193cd" target="_blank"><img src="https://api.hellogithub.com/v1/widgets/recommend.svg?rid=0a3e2484b44e481e9dcf1850e45193cd&claim_uid=vXGwjpmYNsBex0C" alt="Featured|HelloGitHub" style="width: 250px; height: 54px;" width="250" height="54" /></a>
|
||||||
|
|
||||||
## Contribute
|
## Contribute
|
||||||
This project exists thanks to all the people who contribute. [[Contribute](https://github.com/rubickCenter/rubick/graphs/contributors)]. <a href="https://github.com/rubickCenter/rubick/graphs/contributors"><img src="https://opencollective.com/rubick/contributors.svg?width=890&button=false" /></a>
|
This project exists thanks to all the people who contribute. [[Contribute](https://github.com/rubickCenter/rubick/graphs/contributors)]. <a href="https://github.com/rubickCenter/rubick/graphs/contributors"><img src="https://opencollective.com/rubick/contributors.svg?width=890&button=false" /></a>
|
||||||
|
|
||||||
|
|||||||
@@ -2,29 +2,17 @@
|
|||||||
|
|
||||||
|
|
||||||
<div align= "center">
|
<div align= "center">
|
||||||
<img align="center" width=200 src="https://user-images.githubusercontent.com/21073039/128333805-73e086f0-5523-46a3-a096-cba80b904c46.png" />
|
<img align="center" width=200 src="./public/logo.png" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div align="center">
|
||||||
<div align= "center">
|
<h1>Rubick</h1>
|
||||||
<h1>Rubick</h1>
|
<img alt="累计下载数" src="https://img.shields.io/github/downloads/rubickCenter/rubick/total" />
|
||||||
|
<a href="https://github.com/rubickCenter/rubick/releases"><img alt="最新发布版本" src="https://img.shields.io/github/package-json/v/rubickCenter/rubick" /></a>
|
||||||
<img alt="release" src="https://img.shields.io/github/downloads/rubickCenter/rubick/total" />
|
<a href="https://github.com/rubickCenter/rubick/actions"><img alt="github action 构建" src="https://img.shields.io/github/actions/workflow/status/rubickCenter/rubick/main.yml" /></a>
|
||||||
<a href="https://github.com/rubickCenter/rubick/releases">
|
<a href="https://github.com/rubickCenter/rubick/blob/master/LICENSE"><img alt="许可证" src="https://img.shields.io/github/license/rubickCenter/rubick" /></a>
|
||||||
<img alt="release" src="https://img.shields.io/github/package-json/v/rubickCenter/rubick" />
|
<a href="https://github.com/rubickCenter/rubick/stargazers"><img alt="github 收藏数" src="https://img.shields.io/github/stars/rubickCenter/rubick?style=social" /></a>
|
||||||
</a>
|
<a href="https://gitee.com/monkeyWang/rubick"><img alt="gitee 镜像源" src="https://img.shields.io/badge/Gitee--yellow.svg?style=social&logo=data:image/svg+xml;base64,PHN2ZyB0PSIxNTc0ODM3MTM4ODM3IiBjbGFzcz0iaWNvbiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHAtaWQ9IjE3NzAiICAgICB3aWR0aD0iMTYiIGhlaWdodD0iMTYiPiAgICA8cGF0aCBkPSJNODkxIDQyOC44SDQ2NS44Yy0yMC40IDAtMzcgMTYuNS0zNyAzN3Y5Mi40YzAgMjAuNCAxNi41IDM3IDM3IDM3aDI1OC45YzIwLjQgMCAzNyAxNi42IDM3IDM3djE4LjRjMCA2MS4zLTQ5LjcgMTEwLjktMTEwLjkgMTEwLjlIMjk5LjRjLTIwLjQgMC0zNy0xNi42LTM3LTM3VjM3My4yYzAtNjEuMyA0OS43LTExMC45IDExMC45LTExMC45aDUxNy42YzIwLjQgMCAzNy0xNi41IDM3LTM3bDAuMS05Mi4zYzAtMjAuNC0xNi41LTM3LTM3LTM3SDM3My4zQzIyMC4yIDk2IDk2IDIyMC4yIDk2IDM3My4zVjg5MWMwIDIwLjQgMTYuNiAzNyAzNyAzN2g1NDUuNEM4MTYuMiA5MjggOTI4IDgxNi4zIDkyOCA2NzguNFY0NjUuOGMwLTIwLjQtMTYuNi0zNy0zNy0zN3oiICAgICAgICAgIGZpbGw9IiNkODFlMDYiIHAtaWQ9IjE3NzEiPjwvcGF0aD48L3N2Zz4=" /></a>
|
||||||
<a href="https://github.com/rubickCenter/rubick/actions">
|
|
||||||
<img alt=building src=https://img.shields.io/github/workflow/status/rubickCenter/rubick/Build>
|
|
||||||
</a>
|
|
||||||
<a href="https://github.com/rubickCenter/rubick/blob/master/LICENSE">
|
|
||||||
<img alt="npm" src="https://img.shields.io/github/license/rubickCenter/rubick" />
|
|
||||||
</a>
|
|
||||||
<a href="https://github.com/rubickCenter/rubick/stargazers">
|
|
||||||
<img alt="star" src="https://img.shields.io/github/stars/rubickCenter/rubick?style=social">
|
|
||||||
</a>
|
|
||||||
<a href="https://gitee.com/monkeyWang/rubick">
|
|
||||||
<img alt="码云" src="https://img.shields.io/badge/Gitee--yellow.svg?style=social&logo=data:image/svg+xml;base64,PHN2ZyB0PSIxNTc0ODM3MTM4ODM3IiBjbGFzcz0iaWNvbiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHAtaWQ9IjE3NzAiICAgICB3aWR0aD0iMTYiIGhlaWdodD0iMTYiPiAgICA8cGF0aCBkPSJNODkxIDQyOC44SDQ2NS44Yy0yMC40IDAtMzcgMTYuNS0zNyAzN3Y5Mi40YzAgMjAuNCAxNi41IDM3IDM3IDM3aDI1OC45YzIwLjQgMCAzNyAxNi42IDM3IDM3djE4LjRjMCA2MS4zLTQ5LjcgMTEwLjktMTEwLjkgMTEwLjlIMjk5LjRjLTIwLjQgMC0zNy0xNi42LTM3LTM3VjM3My4yYzAtNjEuMyA0OS43LTExMC45IDExMC45LTExMC45aDUxNy42YzIwLjQgMCAzNy0xNi41IDM3LTM3bDAuMS05Mi4zYzAtMjAuNC0xNi41LTM3LTM3LTM3SDM3My4zQzIyMC4yIDk2IDk2IDIyMC4yIDk2IDM3My4zVjg5MWMwIDIwLjQgMTYuNiAzNyAzNyAzN2g1NDUuNEM4MTYuMiA5MjggOTI4IDgxNi4zIDkyOCA2NzguNFY0NjUuOGMwLTIwLjQtMTYuNi0zNy0zNy0zN3oiICAgICAgICAgIGZpbGw9IiNkODFlMDYiIHAtaWQ9IjE3NzEiPjwvcGF0aD48L3N2Zz4="/>
|
|
||||||
</a>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div align= "center">
|
<div align= "center">
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 15 KiB |
@@ -5864,7 +5864,7 @@ lodash.memoize@^4.1.2:
|
|||||||
|
|
||||||
lodash.throttle@^4.1.1:
|
lodash.throttle@^4.1.1:
|
||||||
version "4.1.1"
|
version "4.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4"
|
resolved "https://registry.npmmirror.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4"
|
||||||
integrity sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==
|
integrity sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==
|
||||||
|
|
||||||
lodash.transform@^4.6.0:
|
lodash.transform@^4.6.0:
|
||||||
|
|||||||
@@ -42,7 +42,7 @@
|
|||||||
"eslint-plugin-prettier": "^3.3.1",
|
"eslint-plugin-prettier": "^3.3.1",
|
||||||
"eslint-plugin-vue": "^7.0.0",
|
"eslint-plugin-vue": "^7.0.0",
|
||||||
"less": "^4.1.3",
|
"less": "^4.1.3",
|
||||||
"less-loader": "5.0.0",
|
"less-loader": "^6.2.0",
|
||||||
"prettier": "^2.2.1",
|
"prettier": "^2.2.1",
|
||||||
"typescript": "~4.1.5"
|
"typescript": "~4.1.5"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"pluginName": "系统菜单",
|
"pluginName": "系统菜单",
|
||||||
"description": "系统菜单",
|
"description": "系统菜单",
|
||||||
"main": "index.html",
|
"main": "index.html",
|
||||||
"logo": "https://pic1.zhimg.com/80/v2-c09780808301668a82e6646cb42f0806_720w.png",
|
"logo": "https://pic1.zhimg.com/80/v2-29152fe716010751db835adf591421f8_720w.png",
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"preload":"preload.js",
|
"preload":"preload.js",
|
||||||
"pluginType": "ui",
|
"pluginType": "ui",
|
||||||
|
|||||||
@@ -8,37 +8,37 @@
|
|||||||
>
|
>
|
||||||
<a-menu-item key="finder">
|
<a-menu-item key="finder">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<StarOutlined style="font-size: 18px;" />
|
<StarOutlined style="font-size: 16px" />
|
||||||
</template>
|
</template>
|
||||||
{{ $t('feature.market.explore') }}
|
{{ $t('feature.market.explore') }}
|
||||||
</a-menu-item>
|
</a-menu-item>
|
||||||
<a-menu-item key="worker">
|
<a-menu-item key="worker">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<SendOutlined style="transform: rotate(-45deg); font-size: 18px;" />
|
<SendOutlined style="transform: rotate(-45deg); font-size: 16px" />
|
||||||
</template>
|
</template>
|
||||||
{{ $t('feature.market.efficiency') }}
|
{{ $t('feature.market.efficiency') }}
|
||||||
</a-menu-item>
|
</a-menu-item>
|
||||||
<a-menu-item key="tools">
|
<a-menu-item key="tools">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<SearchOutlined style="font-size: 18px;" />
|
<SearchOutlined style="font-size: 16px" />
|
||||||
</template>
|
</template>
|
||||||
{{ $t('feature.market.searchTool') }}
|
{{ $t('feature.market.searchTool') }}
|
||||||
</a-menu-item>
|
</a-menu-item>
|
||||||
<a-menu-item key="image">
|
<a-menu-item key="image">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<FileImageOutlined style="font-size: 18px;" />
|
<FileImageOutlined style="font-size: 16px" />
|
||||||
</template>
|
</template>
|
||||||
{{ $t('feature.market.imageTool') }}
|
{{ $t('feature.market.imageTool') }}
|
||||||
</a-menu-item>
|
</a-menu-item>
|
||||||
<a-menu-item key="devPlugin">
|
<a-menu-item key="devPlugin">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<CodeOutlined style="font-size: 18px;" />
|
<CodeOutlined style="font-size: 16px" />
|
||||||
</template>
|
</template>
|
||||||
{{ $t('feature.market.developTool') }}
|
{{ $t('feature.market.developTool') }}
|
||||||
</a-menu-item>
|
</a-menu-item>
|
||||||
<a-menu-item key="system">
|
<a-menu-item key="system">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<DatabaseOutlined style="font-size: 18px;" />
|
<DatabaseOutlined style="font-size: 16px" />
|
||||||
</template>
|
</template>
|
||||||
{{ $t('feature.market.systemTool') }}
|
{{ $t('feature.market.systemTool') }}
|
||||||
</a-menu-item>
|
</a-menu-item>
|
||||||
@@ -72,7 +72,21 @@
|
|||||||
</a-sub-menu>
|
</a-sub-menu>
|
||||||
</a-menu>
|
</a-menu>
|
||||||
</div>
|
</div>
|
||||||
<div :class="['finder', 'result', 'devPlugin', 'image', 'tools', 'worker', 'system'].includes(active[0]) ? 'container' : 'more'">
|
<div
|
||||||
|
:class="
|
||||||
|
[
|
||||||
|
'finder',
|
||||||
|
'result',
|
||||||
|
'devPlugin',
|
||||||
|
'image',
|
||||||
|
'tools',
|
||||||
|
'worker',
|
||||||
|
'system',
|
||||||
|
].includes(active[0])
|
||||||
|
? 'container'
|
||||||
|
: 'more'
|
||||||
|
"
|
||||||
|
>
|
||||||
<keep-alive>
|
<keep-alive>
|
||||||
<router-view />
|
<router-view />
|
||||||
</keep-alive>
|
</keep-alive>
|
||||||
@@ -103,14 +117,14 @@ const active = computed(() => store.state.active);
|
|||||||
const { perf } = localConfig.getConfig();
|
const { perf } = localConfig.getConfig();
|
||||||
|
|
||||||
const changeMenu = (key: any) => {
|
const changeMenu = (key: any) => {
|
||||||
store.commit('commonUpdate', {active: [key]})
|
store.commit('commonUpdate', { active: [key] });
|
||||||
router.push(key);
|
router.push(key);
|
||||||
};
|
};
|
||||||
|
|
||||||
window.rubick.onPluginEnter(({ code }: { code: string }) => {
|
window.rubick.onPluginEnter(({ code }: { code: string }) => {
|
||||||
code = code === '已安装插件' ? 'installed' : code;
|
code = code === '已安装插件' ? 'installed' : code;
|
||||||
changeMenu(code);
|
changeMenu(code);
|
||||||
store.commit('commonUpdate', {active: [code]})
|
store.commit('commonUpdate', { active: [code] });
|
||||||
});
|
});
|
||||||
|
|
||||||
window.rubick.setSubInput((e: any) => {
|
window.rubick.setSubInput((e: any) => {
|
||||||
@@ -129,7 +143,7 @@ window.rubick.setSubInput((e: any) => {
|
|||||||
store.commit('setSearchValue', e.text);
|
store.commit('setSearchValue', e.text);
|
||||||
router.push('result');
|
router.push('result');
|
||||||
} else {
|
} else {
|
||||||
store.commit('commonUpdate', {active: ['finder']})
|
store.commit('commonUpdate', { active: ['finder'] });
|
||||||
router.push('finder');
|
router.push('finder');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -144,13 +158,16 @@ init();
|
|||||||
background: var(--color-body-bg2) !important;
|
background: var(--color-body-bg2) !important;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
border-right: none;
|
border-right: none;
|
||||||
.ant-menu-item, .ant-menu-submenu, .ant-menu-submenu-arrow {
|
.ant-menu-item,
|
||||||
|
.ant-menu-submenu,
|
||||||
|
.ant-menu-submenu-arrow {
|
||||||
color: var(--color-text-content);
|
color: var(--color-text-content);
|
||||||
&:active {
|
&:active {
|
||||||
background: none;
|
background: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.ant-menu-item-selected, .ant-menu-submenu-selected {
|
.ant-menu-item-selected,
|
||||||
|
.ant-menu-submenu-selected {
|
||||||
background-color: var(--color-list-hover);
|
background-color: var(--color-list-hover);
|
||||||
color: var(--ant-primary-color);
|
color: var(--ant-primary-color);
|
||||||
.ant-menu-submenu-arrow {
|
.ant-menu-submenu-arrow {
|
||||||
@@ -203,9 +220,12 @@ init();
|
|||||||
background: var(--color-body-bg2);
|
background: var(--color-body-bg2);
|
||||||
}
|
}
|
||||||
.left-menu {
|
.left-menu {
|
||||||
padding: 24px 16px;
|
padding: 16px;
|
||||||
position: relative;
|
position: relative;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
|
:deep(.ant-menu) {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
:deep(.ant-menu-item) {
|
:deep(.ant-menu-item) {
|
||||||
padding-left: 12px !important;
|
padding-left: 12px !important;
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -219,7 +239,14 @@ init();
|
|||||||
}
|
}
|
||||||
:deep(.user-info) {
|
:deep(.user-info) {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 32px;
|
bottom: 16px;
|
||||||
|
width: calc(100% - 32px);
|
||||||
|
.ant-menu-submenu-title {
|
||||||
|
padding: 0 32px 0 8px;
|
||||||
|
.ant-menu-title-content {
|
||||||
|
margin-left: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
:deep(.ant-avatar) {
|
:deep(.ant-avatar) {
|
||||||
background: transparent;
|
background: transparent;
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 17 KiB |
@@ -1,6 +1,6 @@
|
|||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
|
||||||
let baseURL = 'https://gitcode.net/rubickcenter/rubick-database/-/raw/master';
|
let baseURL = 'https://gitee.com/monkeyWang/rubickdatabase/raw/master';
|
||||||
let access_token = '';
|
let access_token = '';
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -14,7 +14,7 @@ try {
|
|||||||
const instance = axios.create({
|
const instance = axios.create({
|
||||||
timeout: 4000,
|
timeout: 4000,
|
||||||
baseURL:
|
baseURL:
|
||||||
baseURL || 'https://gitcode.net/rubickcenter/rubick-database/-/raw/master',
|
baseURL || 'https://gitee.com/monkeyWang/rubickdatabase/raw/master',
|
||||||
});
|
});
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@@ -23,9 +23,10 @@ export default {
|
|||||||
if (access_token) {
|
if (access_token) {
|
||||||
targetPath = `${encodeURIComponent(
|
targetPath = `${encodeURIComponent(
|
||||||
targetPath
|
targetPath
|
||||||
)}/raw?access_token=${access_token}&ref=master`;
|
)}?access_token=${access_token}&ref=master`;
|
||||||
}
|
}
|
||||||
const res = await instance.get(targetPath);
|
const res = await instance.get(targetPath);
|
||||||
|
console.log('total plugsin', res);
|
||||||
return res.data;
|
return res.data;
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -34,7 +35,7 @@ export default {
|
|||||||
if (access_token) {
|
if (access_token) {
|
||||||
targetPath = `${encodeURIComponent(
|
targetPath = `${encodeURIComponent(
|
||||||
targetPath
|
targetPath
|
||||||
)}/raw?access_token=${access_token}&ref=master`;
|
)}?access_token=${access_token}&ref=master`;
|
||||||
}
|
}
|
||||||
const res = await instance.get(targetPath);
|
const res = await instance.get(targetPath);
|
||||||
return res.data;
|
return res.data;
|
||||||
@@ -45,7 +46,7 @@ export default {
|
|||||||
if (access_token) {
|
if (access_token) {
|
||||||
targetPath = `${encodeURIComponent(
|
targetPath = `${encodeURIComponent(
|
||||||
targetPath
|
targetPath
|
||||||
)}/raw?access_token=${access_token}&ref=master`;
|
)}?access_token=${access_token}&ref=master`;
|
||||||
}
|
}
|
||||||
const res = await instance.get(targetPath);
|
const res = await instance.get(targetPath);
|
||||||
return res.data;
|
return res.data;
|
||||||
@@ -55,7 +56,7 @@ export default {
|
|||||||
if (access_token) {
|
if (access_token) {
|
||||||
targetPath = `${encodeURIComponent(
|
targetPath = `${encodeURIComponent(
|
||||||
targetPath
|
targetPath
|
||||||
)}/raw?access_token=${access_token}&ref=master`;
|
)}?access_token=${access_token}&ref=master`;
|
||||||
}
|
}
|
||||||
const res = await instance.get(targetPath);
|
const res = await instance.get(targetPath);
|
||||||
return res.data;
|
return res.data;
|
||||||
@@ -71,7 +72,7 @@ export default {
|
|||||||
if (access_token) {
|
if (access_token) {
|
||||||
targetPath = `${encodeURIComponent(
|
targetPath = `${encodeURIComponent(
|
||||||
targetPath
|
targetPath
|
||||||
)}/raw?access_token=${access_token}&ref=master`;
|
)}?access_token=${access_token}&ref=master`;
|
||||||
}
|
}
|
||||||
const res = await instance.get(targetPath);
|
const res = await instance.get(targetPath);
|
||||||
return res.data;
|
return res.data;
|
||||||
@@ -81,7 +82,7 @@ export default {
|
|||||||
if (access_token) {
|
if (access_token) {
|
||||||
targetPath = `${encodeURIComponent(
|
targetPath = `${encodeURIComponent(
|
||||||
targetPath
|
targetPath
|
||||||
)}/raw?access_token=${access_token}&ref=master`;
|
)}?access_token=${access_token}&ref=master`;
|
||||||
}
|
}
|
||||||
const res = await instance.get(targetPath);
|
const res = await instance.get(targetPath);
|
||||||
return res.data;
|
return res.data;
|
||||||
@@ -91,7 +92,7 @@ export default {
|
|||||||
if (access_token) {
|
if (access_token) {
|
||||||
targetPath = `${encodeURIComponent(
|
targetPath = `${encodeURIComponent(
|
||||||
targetPath
|
targetPath
|
||||||
)}/raw?access_token=${access_token}&ref=master`;
|
)}?access_token=${access_token}&ref=master`;
|
||||||
}
|
}
|
||||||
const res = await instance.get(targetPath);
|
const res = await instance.get(targetPath);
|
||||||
return res.data;
|
return res.data;
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ export default {
|
|||||||
changeLang: 'Change Language',
|
changeLang: 'Change Language',
|
||||||
cn: '简体中文',
|
cn: '简体中文',
|
||||||
en: 'English',
|
en: 'English',
|
||||||
|
history: 'keywords search history',
|
||||||
},
|
},
|
||||||
global: {
|
global: {
|
||||||
title: 'Global Shortcut Key',
|
title: 'Global Shortcut Key',
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ export default {
|
|||||||
changeLang: '切换语言',
|
changeLang: '切换语言',
|
||||||
cn: '简体中文',
|
cn: '简体中文',
|
||||||
en: 'English',
|
en: 'English',
|
||||||
|
history: '关键词搜索记录',
|
||||||
},
|
},
|
||||||
global: {
|
global: {
|
||||||
title: '全局快捷键',
|
title: '全局快捷键',
|
||||||
|
|||||||
@@ -31,9 +31,9 @@ const searchValue = computed(() => store.state.searchValue);
|
|||||||
|
|
||||||
const result = computed(() => {
|
const result = computed(() => {
|
||||||
if (searchValue.value.trim().length > 0) {
|
if (searchValue.value.trim().length > 0) {
|
||||||
const pattern = new RegExp(searchValue.value);
|
const pattern = new RegExp(searchValue.value.toLowerCase());
|
||||||
return totalPlugins.value.filter((plugin) => {
|
return totalPlugins.value.filter((plugin) => {
|
||||||
if (plugin.pluginName.match(pattern)) {
|
if (plugin.pluginName.toLowerCase().match(pattern)) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -119,6 +119,16 @@
|
|||||||
:un-checked-children="$t('feature.settings.basic.off')"
|
:un-checked-children="$t('feature.settings.basic.off')"
|
||||||
></a-switch>
|
></a-switch>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="settings-item-li">
|
||||||
|
<div class="label">
|
||||||
|
{{ $t('feature.settings.basic.history') }}
|
||||||
|
</div>
|
||||||
|
<a-switch
|
||||||
|
v-model:checked="common.history"
|
||||||
|
:checked-children="$t('feature.settings.basic.on')"
|
||||||
|
:un-checked-children="$t('feature.settings.basic.off')"
|
||||||
|
></a-switch>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="setting-item">
|
<div class="setting-item">
|
||||||
<div class="title">{{ $t('feature.settings.basic.theme') }}</div>
|
<div class="title">{{ $t('feature.settings.basic.theme') }}</div>
|
||||||
@@ -264,12 +274,16 @@ const state = reactive({
|
|||||||
custom: {},
|
custom: {},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 添加lastKeyPressTime变量来跟踪按键时间
|
||||||
|
const lastKeyPressTime = ref(0);
|
||||||
|
const DOUBLE_CLICK_THRESHOLD = 300; // 双击时间阈值(毫秒)
|
||||||
|
|
||||||
const isWindows = window?.rubick?.isWindows();
|
const isWindows = window?.rubick?.isWindows();
|
||||||
const tipText = computed(() => {
|
const tipText = computed(() => {
|
||||||
const optionKeyName = isWindows ? 'Alt' : 'Option、Command';
|
const optionKeyName = isWindows ? 'Alt' : 'Option、Command';
|
||||||
return t('feature.settings.global.addShortcutKeyTips', {
|
return t('feature.settings.global.addShortcutKeyTips', {
|
||||||
optionKeyName: optionKeyName,
|
optionKeyName: optionKeyName,
|
||||||
});
|
}) + `此外你也可以双击修饰键如(Ctrl+Ctrl)`;
|
||||||
});
|
});
|
||||||
|
|
||||||
const currentSelect = ref(['userInfo']);
|
const currentSelect = ref(['userInfo']);
|
||||||
@@ -283,14 +297,15 @@ state.local = perf.local;
|
|||||||
state.global = defaultGlobal;
|
state.global = defaultGlobal;
|
||||||
|
|
||||||
const setConfig = debounce(() => {
|
const setConfig = debounce(() => {
|
||||||
|
const { perf } = localConfig.getConfig();
|
||||||
localConfig.setConfig(
|
localConfig.setConfig(
|
||||||
JSON.parse(
|
JSON.parse(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
perf: {
|
perf: {
|
||||||
|
...perf,
|
||||||
shortCut: state.shortCut,
|
shortCut: state.shortCut,
|
||||||
common: state.common,
|
common: state.common,
|
||||||
local: state.local,
|
local: state.local,
|
||||||
custom: state.custom,
|
|
||||||
},
|
},
|
||||||
global: state.global,
|
global: state.global,
|
||||||
})
|
})
|
||||||
@@ -303,33 +318,60 @@ watch(state, setConfig);
|
|||||||
|
|
||||||
const changeShortCut = (e, key) => {
|
const changeShortCut = (e, key) => {
|
||||||
let compose = '';
|
let compose = '';
|
||||||
// 添加是否包含功能键的判断
|
const currentTime = Date.now();
|
||||||
let incluFuncKeys = false;
|
const isDoubleClick = currentTime - lastKeyPressTime.value < DOUBLE_CLICK_THRESHOLD;
|
||||||
|
lastKeyPressTime.value = currentTime;
|
||||||
|
|
||||||
|
// 处理 F1-F12 功能键
|
||||||
|
if (e.keyCode >= 112 && e.keyCode <= 123) {
|
||||||
|
state.shortCut[key] = keycodes[e.keyCode].toUpperCase();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理双击功能键的情况
|
||||||
|
if (isDoubleClick) {
|
||||||
|
if (e.keyCode === 17) { // Ctrl
|
||||||
|
state.shortCut[key] = 'Ctrl+Ctrl';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (e.keyCode === 18) { // Alt
|
||||||
|
state.shortCut[key] = 'Option+Option';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (e.keyCode === 16) { // Shift
|
||||||
|
state.shortCut[key] = 'Shift+Shift';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (e.keyCode === 93) { // Command
|
||||||
|
state.shortCut[key] = 'Command+Command';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理功能键+普通键的组合
|
||||||
|
let hasModifierKey = false;
|
||||||
|
|
||||||
if (e.ctrlKey && e.keyCode !== 17) {
|
if (e.ctrlKey && e.keyCode !== 17) {
|
||||||
compose += '+Ctrl';
|
compose += '+Ctrl';
|
||||||
incluFuncKeys = true;
|
hasModifierKey = true;
|
||||||
}
|
}
|
||||||
if (e.shiftKey && e.keyCode !== 16) {
|
if (e.shiftKey && e.keyCode !== 16) {
|
||||||
compose += '+Shift';
|
compose += '+Shift';
|
||||||
incluFuncKeys = true;
|
hasModifierKey = true;
|
||||||
}
|
}
|
||||||
if (e.altKey && e.keyCode !== 18) {
|
if (e.altKey && e.keyCode !== 18) {
|
||||||
compose += '+Option';
|
compose += '+Option';
|
||||||
incluFuncKeys = true;
|
hasModifierKey = true;
|
||||||
}
|
}
|
||||||
if (e.metaKey && e.keyCode !== 93) {
|
if (e.metaKey && e.keyCode !== 93) {
|
||||||
compose += '+Command';
|
compose += '+Command';
|
||||||
incluFuncKeys = true;
|
hasModifierKey = true;
|
||||||
}
|
}
|
||||||
compose += '+' + keycodes[e.keyCode].toUpperCase();
|
|
||||||
compose = compose.substring(1);
|
// 只有当有修饰键时才添加普通键
|
||||||
if (
|
if (hasModifierKey) {
|
||||||
incluFuncKeys &&
|
compose += '+' + keycodes[e.keyCode].toUpperCase();
|
||||||
e.keyCode !== 16 &&
|
compose = compose.substring(1);
|
||||||
e.keyCode !== 17 &&
|
|
||||||
e.keyCode !== 18 &&
|
|
||||||
e.keyCode !== 93
|
|
||||||
) {
|
|
||||||
state.shortCut[key] = compose;
|
state.shortCut[key] = compose;
|
||||||
} else {
|
} else {
|
||||||
// 不做处理
|
// 不做处理
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
name="register"
|
name="register"
|
||||||
>
|
>
|
||||||
<a-input
|
<a-input
|
||||||
placeholder="https://registry.npm.taobao.org"
|
placeholder="https://registry.npmmirror.com"
|
||||||
v-model:value="formState.register"
|
v-model:value="formState.register"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
@@ -27,7 +27,7 @@
|
|||||||
name="database"
|
name="database"
|
||||||
>
|
>
|
||||||
<a-input
|
<a-input
|
||||||
placeholder="https://gitcode.net/rubickcenter/rubick-database/-/raw/master"
|
placeholder="https://gitee.com/monkeyWang/rubickdatabase/raw/master"
|
||||||
v-model:value="formState.database"
|
v-model:value="formState.database"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
@@ -54,8 +54,8 @@ import { message } from 'ant-design-vue';
|
|||||||
let _rev: any;
|
let _rev: any;
|
||||||
|
|
||||||
let defaultConfig = {
|
let defaultConfig = {
|
||||||
register: 'https://registry.npm.taobao.org',
|
register: 'https://registry.npmmirror.com',
|
||||||
database: 'https://gitcode.net/rubickcenter/rubick-database/-/raw/master',
|
database: 'https://gitee.com/monkeyWang/rubickdatabase/raw/master',
|
||||||
access_token: '',
|
access_token: '',
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -81,7 +81,7 @@ const layout = {
|
|||||||
const resetForm = () => {
|
const resetForm = () => {
|
||||||
formState.value = {
|
formState.value = {
|
||||||
register: 'https://registry.npmmirror.com',
|
register: 'https://registry.npmmirror.com',
|
||||||
database: 'https://gitcode.net/rubickcenter/rubick-database/-/raw/master',
|
database: 'https://gitee.com/monkeyWang/rubickdatabase/raw/master',
|
||||||
access_token: '',
|
access_token: '',
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -64,6 +64,8 @@ const theme = ref(perf.custom.theme);
|
|||||||
state.custom = perf.custom || {};
|
state.custom = perf.custom || {};
|
||||||
|
|
||||||
const setConfig = debounce(() => {
|
const setConfig = debounce(() => {
|
||||||
|
const { perf } = localConfig.getConfig();
|
||||||
|
|
||||||
localConfig.setConfig(
|
localConfig.setConfig(
|
||||||
JSON.parse(
|
JSON.parse(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
|
|||||||
@@ -7,7 +7,9 @@ module.exports = {
|
|||||||
// 向预处理器 Loader 传递配置选项
|
// 向预处理器 Loader 传递配置选项
|
||||||
less: {
|
less: {
|
||||||
// 配置less(其他样式解析用法一致)
|
// 配置less(其他样式解析用法一致)
|
||||||
javascriptEnabled: true, // 设置为true
|
lessOptions: {
|
||||||
|
javascriptEnabled: true, // 设置为true
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "rubick",
|
"name": "rubick",
|
||||||
"version": "4.1.7",
|
"version": "4.3.7",
|
||||||
"author": "muwoo <2424880409@qq.com>",
|
"author": "muwoo <2424880409@qq.com>",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@@ -39,6 +39,7 @@
|
|||||||
"pouchdb-load": "^1.4.6",
|
"pouchdb-load": "^1.4.6",
|
||||||
"pouchdb-replication-stream": "^1.2.9",
|
"pouchdb-replication-stream": "^1.2.9",
|
||||||
"simple-plist": "0.2.1",
|
"simple-plist": "0.2.1",
|
||||||
|
"uiohook-napi": "^1.5.4",
|
||||||
"vue": "^3.0.0",
|
"vue": "^3.0.0",
|
||||||
"vue-router": "^4.0.0-0",
|
"vue-router": "^4.0.0-0",
|
||||||
"vuex": "^4.0.0-0",
|
"vuex": "^4.0.0-0",
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"pluginName": "系统菜单",
|
"pluginName": "系统菜单",
|
||||||
"description": "系统菜单",
|
"description": "系统菜单",
|
||||||
"main": "index.html",
|
"main": "index.html",
|
||||||
"logo": "https://pic1.zhimg.com/80/v2-c09780808301668a82e6646cb42f0806_720w.png",
|
"logo": "https://pic1.zhimg.com/80/v2-29152fe716010751db835adf591421f8_720w.png",
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"preload":"preload.js",
|
"preload":"preload.js",
|
||||||
"pluginType": "ui",
|
"pluginType": "ui",
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 131 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 3.2 KiB |
BIN
public/icons/iconTemplate@2x.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
public/icons/shield@2x.png
Normal file
|
After Width: | Height: | Size: 828 B |
BIN
public/logo.png
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 131 KiB |
@@ -39,6 +39,12 @@ window.rubick = {
|
|||||||
openPlugin(plugin) {
|
openPlugin(plugin) {
|
||||||
ipcSendSync('loadPlugin', plugin);
|
ipcSendSync('loadPlugin', plugin);
|
||||||
},
|
},
|
||||||
|
onShow(cb) {
|
||||||
|
typeof cb === 'function' && (window.rubick.hooks.onShow = cb);
|
||||||
|
},
|
||||||
|
onHide(cb) {
|
||||||
|
typeof cb === 'function' && (window.rubick.hooks.onHide = cb);
|
||||||
|
},
|
||||||
// 窗口交互
|
// 窗口交互
|
||||||
hideMainWindow() {
|
hideMainWindow() {
|
||||||
ipcSendSync('hideMainWindow');
|
ipcSendSync('hideMainWindow');
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
export default {
|
export default {
|
||||||
version: 4,
|
version: 7,
|
||||||
perf: {
|
perf: {
|
||||||
custom: {
|
custom: {
|
||||||
theme: 'SPRING',
|
theme: 'SPRING',
|
||||||
@@ -25,6 +25,7 @@ export default {
|
|||||||
autoPast: false,
|
autoPast: false,
|
||||||
darkMode: false,
|
darkMode: false,
|
||||||
guide: false,
|
guide: false,
|
||||||
|
history: true,
|
||||||
lang: 'zh-CN',
|
lang: 'zh-CN',
|
||||||
},
|
},
|
||||||
local: {
|
local: {
|
||||||
|
|||||||
@@ -4,6 +4,6 @@ import path from 'path';
|
|||||||
const appPath = app.getPath('userData');
|
const appPath = app.getPath('userData');
|
||||||
|
|
||||||
const PLUGIN_INSTALL_DIR = path.join(appPath, './rubick-plugins-new');
|
const PLUGIN_INSTALL_DIR = path.join(appPath, './rubick-plugins-new');
|
||||||
const PLUGIN_HISTORY = 'rubick-local-start-app';
|
const PLUGIN_HISTORY = 'rubick-plugin-history';
|
||||||
|
|
||||||
export { PLUGIN_INSTALL_DIR, PLUGIN_HISTORY };
|
export { PLUGIN_INSTALL_DIR, PLUGIN_HISTORY };
|
||||||
|
|||||||
@@ -32,63 +32,6 @@ const getIconFile = (appFileInput) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// const sortIcons = (icons) => {
|
|
||||||
// const aWins = -1;
|
|
||||||
// const bWins = 1;
|
|
||||||
// const catWins = 0;
|
|
||||||
// return icons.sort((a, b) => {
|
|
||||||
// const aSize = parseInt(a.match(/(\d+)x\1/)[1], 10);
|
|
||||||
// const bSize = parseInt(b.match(/(\d+)x\1/)[1], 10);
|
|
||||||
// if (aSize === bSize) {
|
|
||||||
// if (a.indexOf('@2x') > -1) return aWins;
|
|
||||||
// if (b.indexOf('@2x') > -1) return bWins;
|
|
||||||
// return catWins;
|
|
||||||
// }
|
|
||||||
// if (aSize > bSize) return aWins;
|
|
||||||
// if (aSize < bSize) return bWins;
|
|
||||||
// return catWins;
|
|
||||||
// });
|
|
||||||
// };
|
|
||||||
|
|
||||||
// const icnsToPng = (iconFile, pngFileOutput) => {
|
|
||||||
// const outputDir = pngFileOutput.split('.')[0] + '.iconset'
|
|
||||||
// return new Promise((resolve, reject) => {
|
|
||||||
// exec(`iconutil --convert iconset '${iconFile}' --output '${outputDir}'`, (error) => {
|
|
||||||
// if (error) return reject(error)
|
|
||||||
// fs.readdir(outputDir, (error, files) => {
|
|
||||||
// if (error) {
|
|
||||||
// return resolve(tiffToPng(iconFile, pngFileOutput))
|
|
||||||
// }
|
|
||||||
// const realIcons = files.map((file) => {
|
|
||||||
// return path.join(outputDir, file)
|
|
||||||
// })
|
|
||||||
// const biggestIcon = sortIcons(realIcons).find(Boolean)
|
|
||||||
// fs.rename(biggestIcon, pngFileOutput, (error) => {
|
|
||||||
// error ? reject(error) : resolve(realIcons.filter((file) => {
|
|
||||||
// return file !== biggestIcon
|
|
||||||
// }))
|
|
||||||
// })
|
|
||||||
// })
|
|
||||||
// })
|
|
||||||
// }).then((files) => {
|
|
||||||
// // Cleanup temp icons
|
|
||||||
// return Promise.all(files.map((file) => {
|
|
||||||
// return new Promise((resolve, reject) => {
|
|
||||||
// fs.unlink(file, (error) => {
|
|
||||||
// error ? reject(error) : resolve()
|
|
||||||
// })
|
|
||||||
// })
|
|
||||||
// }))
|
|
||||||
// }).then(() => {
|
|
||||||
// // Cleanup temp directory
|
|
||||||
// return new Promise((resolve, reject) => {
|
|
||||||
// fs.rmdir(outputDir, (error) => {
|
|
||||||
// error ? reject(error) : resolve()
|
|
||||||
// })
|
|
||||||
// })
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
|
|
||||||
const tiffToPng = (iconFile, pngFileOutput) => {
|
const tiffToPng = (iconFile, pngFileOutput) => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
exec(
|
exec(
|
||||||
|
|||||||
@@ -1,23 +1,23 @@
|
|||||||
import { spawn } from "child_process";
|
import { spawn } from 'child_process';
|
||||||
import plist from "plist";
|
import plist from 'plist';
|
||||||
|
|
||||||
export default function getApps(resolve, reject, filterByAppName = false) {
|
export default function getApps(resolve, reject, filterByAppName = false) {
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
let resultBuffer = new Buffer.from([]);
|
let resultBuffer = new Buffer.from([]);
|
||||||
|
|
||||||
const profileInstalledApps = spawn("/usr/sbin/system_profiler", [
|
const profileInstalledApps = spawn('/usr/sbin/system_profiler', [
|
||||||
"-xml",
|
'-xml',
|
||||||
"-detailLevel",
|
'-detailLevel',
|
||||||
"mini",
|
'mini',
|
||||||
"SPApplicationsDataType",
|
'SPApplicationsDataType',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
profileInstalledApps.stdout.on("data", (chunckBuffer) => {
|
profileInstalledApps.stdout.on('data', (chunckBuffer) => {
|
||||||
resultBuffer = Buffer.concat([resultBuffer, chunckBuffer]);
|
resultBuffer = Buffer.concat([resultBuffer, chunckBuffer]);
|
||||||
});
|
});
|
||||||
|
|
||||||
profileInstalledApps.on("exit", (exitCode) => {
|
profileInstalledApps.on('exit', (exitCode) => {
|
||||||
if (exitCode !== 0) {
|
if (exitCode !== 0) {
|
||||||
reject([]);
|
reject([]);
|
||||||
return;
|
return;
|
||||||
@@ -37,7 +37,7 @@ export default function getApps(resolve, reject, filterByAppName = false) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
profileInstalledApps.on("error", (err) => {
|
profileInstalledApps.on('error', (err) => {
|
||||||
reject(err);
|
reject(err);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,11 +7,10 @@ import path from 'path';
|
|||||||
import got from 'got';
|
import got from 'got';
|
||||||
import fixPath from 'fix-path';
|
import fixPath from 'fix-path';
|
||||||
|
|
||||||
|
import spawn from 'cross-spawn';
|
||||||
import { ipcRenderer } from 'electron';
|
import { ipcRenderer } from 'electron';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
|
||||||
import npm from 'npm';
|
|
||||||
|
|
||||||
fixPath();
|
fixPath();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -37,12 +36,19 @@ class AdapterHandler {
|
|||||||
fs.mkdirsSync(options.baseDir);
|
fs.mkdirsSync(options.baseDir);
|
||||||
fs.writeFileSync(
|
fs.writeFileSync(
|
||||||
`${options.baseDir}/package.json`,
|
`${options.baseDir}/package.json`,
|
||||||
'{"dependencies":{}}'
|
// '{"dependencies":{}}'
|
||||||
|
// fix 插件安装时node版本问题
|
||||||
|
JSON.stringify({
|
||||||
|
dependencies: {},
|
||||||
|
volta: {
|
||||||
|
node: '16.19.1',
|
||||||
|
},
|
||||||
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
this.baseDir = options.baseDir;
|
this.baseDir = options.baseDir;
|
||||||
|
|
||||||
let register = options.registry || 'https://registry.npmmirror.com/';
|
let register = options.registry || 'https://registry.npmmirror.com';
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const dbdata = ipcRenderer.sendSync('msg-trigger', {
|
const dbdata = ipcRenderer.sendSync('msg-trigger', {
|
||||||
@@ -61,7 +67,7 @@ class AdapterHandler {
|
|||||||
const packageJSON = JSON.parse(
|
const packageJSON = JSON.parse(
|
||||||
fs.readFileSync(`${this.baseDir}/package.json`, 'utf-8')
|
fs.readFileSync(`${this.baseDir}/package.json`, 'utf-8')
|
||||||
);
|
);
|
||||||
const registryUrl = `https://registry.npm.taobao.org/${name}`;
|
const registryUrl = `https://registry.npmmirror.com/${name}`;
|
||||||
|
|
||||||
// 从npm源中获取依赖包的最新版本
|
// 从npm源中获取依赖包的最新版本
|
||||||
try {
|
try {
|
||||||
@@ -158,67 +164,44 @@ class AdapterHandler {
|
|||||||
*/
|
*/
|
||||||
private async execCommand(cmd: string, modules: string[]): Promise<string> {
|
private async execCommand(cmd: string, modules: string[]): Promise<string> {
|
||||||
return new Promise((resolve: any, reject: any) => {
|
return new Promise((resolve: any, reject: any) => {
|
||||||
const module =
|
let args: string[] = [cmd].concat(
|
||||||
cmd !== 'uninstall' && cmd !== 'link'
|
cmd !== 'uninstall' && cmd !== 'link'
|
||||||
? modules.map((m) => `${m}@latest`)
|
? modules.map((m) => `${m}@latest`)
|
||||||
: modules;
|
: modules
|
||||||
const config: any = {
|
);
|
||||||
prefix: this.baseDir,
|
|
||||||
save: true,
|
|
||||||
cache: path.join(this.baseDir, 'cache'),
|
|
||||||
};
|
|
||||||
if (cmd !== 'link') {
|
if (cmd !== 'link') {
|
||||||
config.registry = this.registry;
|
args = args
|
||||||
|
.concat('--color=always')
|
||||||
|
.concat('--save')
|
||||||
|
.concat(`--registry=${this.registry}`);
|
||||||
}
|
}
|
||||||
npm.load(config, function (err) {
|
|
||||||
npm.commands[cmd](module, function (er, data) {
|
|
||||||
if (!err) {
|
|
||||||
console.log(data);
|
|
||||||
resolve({ code: -1, data });
|
|
||||||
} else {
|
|
||||||
reject({ code: -1, data: err });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
npm.on('log', function (message) {
|
const npm = spawn('npm', args, {
|
||||||
// log installation progress
|
cwd: this.baseDir,
|
||||||
console.log(message);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// if (cmd !== 'link') {
|
console.log(args);
|
||||||
// args = args
|
|
||||||
// .concat('--color=always')
|
|
||||||
// .concat('--save')
|
|
||||||
// .concat(`--registry=${this.registry}`);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// const npm = spawn('npm', args, {
|
let output = '';
|
||||||
// cwd: this.baseDir,
|
npm.stdout
|
||||||
// });
|
.on('data', (data: string) => {
|
||||||
//
|
output += data; // 获取输出日志
|
||||||
// console.log(args);
|
})
|
||||||
//
|
.pipe(process.stdout);
|
||||||
// let output = '';
|
|
||||||
// npm.stdout
|
npm.stderr
|
||||||
// .on('data', (data: string) => {
|
.on('data', (data: string) => {
|
||||||
// output += data; // 获取输出日志
|
output += data; // 获取报错日志
|
||||||
// })
|
})
|
||||||
// .pipe(process.stdout);
|
.pipe(process.stderr);
|
||||||
//
|
|
||||||
// npm.stderr
|
npm.on('close', (code: number) => {
|
||||||
// .on('data', (data: string) => {
|
if (!code) {
|
||||||
// output += data; // 获取报错日志
|
resolve({ code: 0, data: output }); // 如果没有报错就输出正常日志
|
||||||
// })
|
} else {
|
||||||
// .pipe(process.stderr);
|
reject({ code: code, data: output }); // 如果报错就输出报错日志
|
||||||
//
|
}
|
||||||
// npm.on('close', (code: number) => {
|
});
|
||||||
// if (!code) {
|
|
||||||
// resolve({ code: 0, data: output }); // 如果没有报错就输出正常日志
|
|
||||||
// } else {
|
|
||||||
// reject({ code: code, data: output }); // 如果报错就输出报错日志
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ export default () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
win.on('show', () => {
|
win.on('show', () => {
|
||||||
|
// 触发主窗口的 onShow hook
|
||||||
win.webContents.executeJavaScript(
|
win.webContents.executeJavaScript(
|
||||||
`window.rubick && window.rubick.hooks && typeof window.rubick.hooks.onShow === "function" && window.rubick.hooks.onShow()`
|
`window.rubick && window.rubick.hooks && typeof window.rubick.hooks.onShow === "function" && window.rubick.hooks.onShow()`
|
||||||
);
|
);
|
||||||
@@ -67,6 +68,7 @@ export default () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
win.on('hide', () => {
|
win.on('hide', () => {
|
||||||
|
// 触发主窗口的 onHide hook
|
||||||
win.webContents.executeJavaScript(
|
win.webContents.executeJavaScript(
|
||||||
`window.rubick && window.rubick.hooks && typeof window.rubick.hooks.onHide === "function" && window.rubick.hooks.onHide()`
|
`window.rubick && window.rubick.hooks && typeof window.rubick.hooks.onHide === "function" && window.rubick.hooks.onHide()`
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ export default () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const init = (plugin, window: BrowserWindow) => {
|
const init = (plugin, window: BrowserWindow) => {
|
||||||
if (view === null || view === undefined) {
|
if (view === null || view === undefined || view.inDetach) {
|
||||||
createView(plugin, window);
|
createView(plugin, window);
|
||||||
// if (viewInstance.getView(plugin.name) && !commonConst.dev()) {
|
// if (viewInstance.getView(plugin.name) && !commonConst.dev()) {
|
||||||
// view = viewInstance.getView(plugin.name).view;
|
// view = viewInstance.getView(plugin.name).view;
|
||||||
@@ -175,31 +175,44 @@ export default () => {
|
|||||||
|
|
||||||
const removeView = (window: BrowserWindow) => {
|
const removeView = (window: BrowserWindow) => {
|
||||||
if (!view) return;
|
if (!view) return;
|
||||||
window.removeBrowserView(view);
|
|
||||||
if (!view.inDetach) {
|
|
||||||
window.setBrowserView(null);
|
|
||||||
view.webContents?.destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
// window.setSize(800, 60);
|
|
||||||
executeHooks('PluginOut', null);
|
executeHooks('PluginOut', null);
|
||||||
window.webContents?.executeJavaScript(`window.initRubick()`);
|
// 先记住这次要移除的视图,防止后面异步代码里全局引用被换掉
|
||||||
view = undefined;
|
const snapshotView = view;
|
||||||
|
setTimeout(() => {
|
||||||
|
// 获取当前视图,判断是否已经换成了新视图
|
||||||
|
const currentView = window.getBrowserView?.();
|
||||||
|
window.removeBrowserView(snapshotView);
|
||||||
|
|
||||||
|
// 主窗口的插件视图仍然挂着旧实例时,需要还原主窗口 UI
|
||||||
|
if (!snapshotView.inDetach) {
|
||||||
|
// 如果窗口还挂着旧视图,说明还没换掉,需要把主窗口恢复到初始状态
|
||||||
|
if (currentView === snapshotView) {
|
||||||
|
window.setBrowserView(null);
|
||||||
|
if (view === snapshotView) {
|
||||||
|
window.webContents?.executeJavaScript(`window.initRubick()`);
|
||||||
|
view = undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
snapshotView.webContents?.destroy();
|
||||||
|
}
|
||||||
|
// 分离窗口只需释放全局引用,视图由分离窗口继续管理
|
||||||
|
else if (view === snapshotView) {
|
||||||
|
view = undefined;
|
||||||
|
}
|
||||||
|
}, 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getView = () => view;
|
const getView = () => view;
|
||||||
|
|
||||||
const executeHooks = (hook, data) => {
|
const executeHooks = (hook, data) => {
|
||||||
setTimeout(() => {
|
if (!view) return;
|
||||||
if (!view) return;
|
const evalJs = `if(window.rubick && window.rubick.hooks && typeof window.rubick.hooks.on${hook} === 'function' ) {
|
||||||
const evalJs = `if(window.rubick && window.rubick.hooks && typeof window.rubick.hooks.on${hook} === 'function' ) {
|
|
||||||
try {
|
try {
|
||||||
window.rubick.hooks.on${hook}(${data ? JSON.stringify(data) : ''});
|
window.rubick.hooks.on${hook}(${data ? JSON.stringify(data) : ''});
|
||||||
} catch(e) {}
|
} catch(e) {}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
view.webContents?.executeJavaScript(evalJs);
|
view.webContents?.executeJavaScript(evalJs);
|
||||||
}, 300);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -27,6 +27,30 @@ import DBInstance from './db';
|
|||||||
import getWinPosition from './getWinPosition';
|
import getWinPosition from './getWinPosition';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import commonConst from '@/common/utils/commonConst';
|
import commonConst from '@/common/utils/commonConst';
|
||||||
|
import { copyFilesToWindowsClipboard } from './windowsClipboard';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sanitize input files 剪贴板文件合法性校验
|
||||||
|
* @param input
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
const sanitizeInputFiles = (input: unknown): string[] => {
|
||||||
|
const candidates = Array.isArray(input)
|
||||||
|
? input
|
||||||
|
: typeof input === 'string'
|
||||||
|
? [input]
|
||||||
|
: [];
|
||||||
|
return candidates
|
||||||
|
.map((filePath) => (typeof filePath === 'string' ? filePath.trim() : ''))
|
||||||
|
.filter((filePath) => {
|
||||||
|
if (!filePath) return false;
|
||||||
|
try {
|
||||||
|
return fs.existsSync(filePath);
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const runnerInstance = runner();
|
const runnerInstance = runner();
|
||||||
const detachInstance = detach();
|
const detachInstance = detach();
|
||||||
@@ -44,6 +68,20 @@ class API extends DBInstance {
|
|||||||
mainWindow.webContents.on('before-input-event', (event, input) =>
|
mainWindow.webContents.on('before-input-event', (event, input) =>
|
||||||
this.__EscapeKeyDown(event, input, mainWindow)
|
this.__EscapeKeyDown(event, input, mainWindow)
|
||||||
);
|
);
|
||||||
|
// 设置主窗口的 show/hide 事件监听
|
||||||
|
this.setupMainWindowHooks(mainWindow);
|
||||||
|
}
|
||||||
|
|
||||||
|
private setupMainWindowHooks(mainWindow: BrowserWindow) {
|
||||||
|
mainWindow.on('show', () => {
|
||||||
|
// 触发插件的 onShow hook
|
||||||
|
runnerInstance.executeHooks('Show', null);
|
||||||
|
});
|
||||||
|
|
||||||
|
mainWindow.on('hide', () => {
|
||||||
|
// 触发插件的 onHide hook
|
||||||
|
runnerInstance.executeHooks('Hide', null);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public getCurrentWindow = (window, e) => {
|
public getCurrentWindow = (window, e) => {
|
||||||
@@ -128,8 +166,8 @@ class API extends DBInstance {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public removePlugin(e, window) {
|
public removePlugin(e, window) {
|
||||||
this.currentPlugin = null;
|
|
||||||
runnerInstance.removeView(window);
|
runnerInstance.removeView(window);
|
||||||
|
this.currentPlugin = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public openPluginDevTools() {
|
public openPluginDevTools() {
|
||||||
@@ -139,6 +177,7 @@ class API extends DBInstance {
|
|||||||
public hideMainWindow(arg, window) {
|
public hideMainWindow(arg, window) {
|
||||||
window.hide();
|
window.hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
public showMainWindow(arg, window) {
|
public showMainWindow(arg, window) {
|
||||||
window.show();
|
window.show();
|
||||||
}
|
}
|
||||||
@@ -156,6 +195,15 @@ class API extends DBInstance {
|
|||||||
if (!originWindow) return;
|
if (!originWindow) return;
|
||||||
const targetHeight = height;
|
const targetHeight = height;
|
||||||
originWindow.setSize(originWindow.getSize()[0], targetHeight);
|
originWindow.setSize(originWindow.getSize()[0], targetHeight);
|
||||||
|
const screenPoint = screen.getCursorScreenPoint();
|
||||||
|
const display = screen.getDisplayNearestPoint(screenPoint);
|
||||||
|
const position =
|
||||||
|
originWindow.getPosition()[1] + targetHeight > display.bounds.height
|
||||||
|
? height - 60
|
||||||
|
: 0;
|
||||||
|
originWindow.webContents.executeJavaScript(
|
||||||
|
`window.setPosition && typeof window.setPosition === "function" && window.setPosition(${position})`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public setSubInput({ data }, window, e) {
|
public setSubInput({ data }, window, e) {
|
||||||
@@ -201,11 +249,10 @@ class API extends DBInstance {
|
|||||||
if (!Notification.isSupported()) return;
|
if (!Notification.isSupported()) return;
|
||||||
'string' != typeof body && (body = String(body));
|
'string' != typeof body && (body = String(body));
|
||||||
const plugin = this.currentPlugin;
|
const plugin = this.currentPlugin;
|
||||||
if (!plugin) return;
|
|
||||||
const notify = new Notification({
|
const notify = new Notification({
|
||||||
title: plugin.pluginName,
|
title: plugin ? plugin.pluginName : null,
|
||||||
body,
|
body,
|
||||||
icon: plugin.logo,
|
icon: plugin ? plugin.logo : null,
|
||||||
});
|
});
|
||||||
notify.show();
|
notify.show();
|
||||||
}
|
}
|
||||||
@@ -221,13 +268,28 @@ class API extends DBInstance {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public copyFile({ data }) {
|
public copyFile({ data }) {
|
||||||
if (data.file && fs.existsSync(data.file)) {
|
const targetFiles = sanitizeInputFiles(data?.file);
|
||||||
clipboard.writeBuffer(
|
|
||||||
'NSFilenamesPboardType',
|
if (!targetFiles.length) {
|
||||||
Buffer.from(plist.build([data.file]))
|
return false;
|
||||||
);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (process.platform === 'darwin') {
|
||||||
|
try {
|
||||||
|
clipboard.writeBuffer(
|
||||||
|
'NSFilenamesPboardType',
|
||||||
|
Buffer.from(plist.build(targetFiles))
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (process.platform === 'win32') {
|
||||||
|
return copyFilesToWindowsClipboard(targetFiles);
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -326,6 +388,7 @@ class API extends DBInstance {
|
|||||||
shell.showItemInFolder(data.path);
|
shell.showItemInFolder(data.path);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getFileIcon({ data }) {
|
public async getFileIcon({ data }) {
|
||||||
const nativeImage = await app.getFileIcon(data.path, { size: 'normal' });
|
const nativeImage = await app.getFileIcon(data.path, { size: 'normal' });
|
||||||
return nativeImage.toDataURL();
|
return nativeImage.toDataURL();
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import {
|
|||||||
import screenCapture from '@/core/screen-capture';
|
import screenCapture from '@/core/screen-capture';
|
||||||
import localConfig from '@/main/common/initLocalConfig';
|
import localConfig from '@/main/common/initLocalConfig';
|
||||||
import winPosition from './getWinPosition';
|
import winPosition from './getWinPosition';
|
||||||
|
import { uIOhook, UiohookKey } from 'uiohook-napi';
|
||||||
|
|
||||||
const registerHotKey = (mainWindow: BrowserWindow): void => {
|
const registerHotKey = (mainWindow: BrowserWindow): void => {
|
||||||
// 设置开机启动
|
// 设置开机启动
|
||||||
@@ -57,27 +58,43 @@ const registerHotKey = (mainWindow: BrowserWindow): void => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 显示主窗口
|
||||||
|
function mainWindowPopUp() {
|
||||||
|
const currentShow = mainWindow.isVisible() && mainWindow.isFocused();
|
||||||
|
if (currentShow) return mainWindow.hide();
|
||||||
|
const { x: wx, y: wy } = winPosition.getPosition();
|
||||||
|
mainWindow.setAlwaysOnTop(false);
|
||||||
|
mainWindow.setVisibleOnAllWorkspaces(true, { visibleOnFullScreen: true });
|
||||||
|
mainWindow.focus();
|
||||||
|
mainWindow.setVisibleOnAllWorkspaces(false, {
|
||||||
|
visibleOnFullScreen: true,
|
||||||
|
});
|
||||||
|
mainWindow.setPosition(wx, wy);
|
||||||
|
mainWindow.show();
|
||||||
|
}
|
||||||
|
|
||||||
const init = async () => {
|
const init = async () => {
|
||||||
await setAutoLogin();
|
await setAutoLogin();
|
||||||
await setDarkMode();
|
await setDarkMode();
|
||||||
await setTheme();
|
await setTheme();
|
||||||
const config = await localConfig.getConfig();
|
const config = await localConfig.getConfig();
|
||||||
globalShortcut.unregisterAll();
|
globalShortcut.unregisterAll();
|
||||||
// 注册偏好快捷键
|
|
||||||
globalShortcut.register(config.perf.shortCut.showAndHidden, () => {
|
|
||||||
const currentShow = mainWindow.isVisible() && mainWindow.isFocused();
|
|
||||||
if (currentShow) return mainWindow.hide();
|
|
||||||
const { x: wx, y: wy } = winPosition.getPosition();
|
|
||||||
mainWindow.setAlwaysOnTop(false);
|
|
||||||
mainWindow.setVisibleOnAllWorkspaces(true, { visibleOnFullScreen: true });
|
|
||||||
mainWindow.focus();
|
|
||||||
mainWindow.setVisibleOnAllWorkspaces(false, {
|
|
||||||
visibleOnFullScreen: true,
|
|
||||||
});
|
|
||||||
mainWindow.setPosition(wx, wy);
|
|
||||||
mainWindow.show();
|
|
||||||
});
|
|
||||||
|
|
||||||
|
// 注册偏好快捷键
|
||||||
|
// 处理显示/隐藏快捷键的注册
|
||||||
|
const doublePressShortcuts = ['Ctrl+Ctrl', 'Option+Option', 'Shift+Shift', 'Command+Command'];
|
||||||
|
const isDoublePressShortcut = doublePressShortcuts.includes(config.perf.shortCut.showAndHidden);
|
||||||
|
|
||||||
|
if (isDoublePressShortcut) {
|
||||||
|
// 双击快捷键(如 Ctrl+Ctrl)详见 uIOhookRegister 函数实现
|
||||||
|
} else {
|
||||||
|
// 注册普通快捷键(如 Ctrl+Space、F8 等)
|
||||||
|
globalShortcut.register(config.perf.shortCut.showAndHidden, () => {
|
||||||
|
mainWindowPopUp();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 截图快捷键
|
||||||
globalShortcut.register(config.perf.shortCut.capture, () => {
|
globalShortcut.register(config.perf.shortCut.capture, () => {
|
||||||
screenCapture(mainWindow, (data) => {
|
screenCapture(mainWindow, (data) => {
|
||||||
data &&
|
data &&
|
||||||
@@ -93,6 +110,17 @@ const registerHotKey = (mainWindow: BrowserWindow): void => {
|
|||||||
// mainWindow.show();
|
// mainWindow.show();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 添加局部快捷键监听
|
||||||
|
mainWindow.webContents.on('before-input-event', (event, input) => {
|
||||||
|
if (input.key.toLowerCase() === 'w'
|
||||||
|
&& (input.control || input.meta) && !input.alt && !input.shift) {
|
||||||
|
event.preventDefault();
|
||||||
|
if (mainWindow && !mainWindow.isDestroyed()) {
|
||||||
|
mainWindow.hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// 注册自定义全局快捷键
|
// 注册自定义全局快捷键
|
||||||
config.global.forEach((sc) => {
|
config.global.forEach((sc) => {
|
||||||
if (!sc.key || !sc.value) return;
|
if (!sc.key || !sc.value) return;
|
||||||
@@ -101,9 +129,48 @@ const registerHotKey = (mainWindow: BrowserWindow): void => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
uIOhookRegister(mainWindowPopUp);
|
||||||
init();
|
init();
|
||||||
ipcMain.on('re-register', () => {
|
ipcMain.on('re-register', () => {
|
||||||
init();
|
init();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
export default registerHotKey;
|
export default registerHotKey;
|
||||||
|
|
||||||
|
function uIOhookRegister(callback: () => void) {
|
||||||
|
let lastModifierPress = Date.now();
|
||||||
|
uIOhook.on('keydown', async (uio_event) => {
|
||||||
|
const config = await localConfig.getConfig(); // 此处还有优化空间
|
||||||
|
|
||||||
|
if (
|
||||||
|
![
|
||||||
|
'Ctrl+Ctrl',
|
||||||
|
'Option+Option',
|
||||||
|
'Shift+Shift',
|
||||||
|
'Command+Command',
|
||||||
|
].includes(config.perf.shortCut.showAndHidden)
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 双击快捷键,如 Ctrl+Ctrl
|
||||||
|
const modifers = config.perf.shortCut.showAndHidden.split('+');
|
||||||
|
const showAndHiddenKeyStr = modifers.pop(); // Ctrl
|
||||||
|
const keyStr2uioKeyCode = {
|
||||||
|
Ctrl: UiohookKey.Ctrl,
|
||||||
|
Shift: UiohookKey.Shift,
|
||||||
|
Option: UiohookKey.Alt,
|
||||||
|
Command: UiohookKey.Comma,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (uio_event.keycode === keyStr2uioKeyCode[showAndHiddenKeyStr]) {
|
||||||
|
const currentTime = Date.now();
|
||||||
|
if (currentTime - lastModifierPress < 300) {
|
||||||
|
callback(); // 调用 mainWindowPopUp
|
||||||
|
}
|
||||||
|
lastModifierPress = currentTime;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
uIOhook.start();
|
||||||
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ function createTray(window: BrowserWindow): Promise<Tray> {
|
|||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
let icon;
|
let icon;
|
||||||
if (commonConst.macOS()) {
|
if (commonConst.macOS()) {
|
||||||
icon = './icons/icon@3x.png';
|
icon = './icons/iconTemplate@2x.png';
|
||||||
} else if (commonConst.windows()) {
|
} else if (commonConst.windows()) {
|
||||||
icon =
|
icon =
|
||||||
parseInt(os.release()) < 10
|
parseInt(os.release()) < 10
|
||||||
|
|||||||
133
src/main/common/windowsClipboard.ts
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
import { clipboard } from 'electron';
|
||||||
|
import path from 'path';
|
||||||
|
|
||||||
|
// 仅在 Windows 平台辅助操作剪贴板多文件格式。
|
||||||
|
type ClipboardExModule = typeof import('electron-clipboard-ex');
|
||||||
|
|
||||||
|
const DROPFILES_HEADER_SIZE = 20;
|
||||||
|
|
||||||
|
let clipboardExModule: ClipboardExModule | null = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Windows 平台专用:尝试加载第三方库 electron-clipboard-ex。
|
||||||
|
* 这个库能够调用系统底层接口写入“文件复制”数据,成功率更高。
|
||||||
|
* 其他系统无需加载它,因此这里做了“按需加载”的处理。
|
||||||
|
*/
|
||||||
|
const ensureClipboardEx = (): ClipboardExModule | null => {
|
||||||
|
if (process.platform !== 'win32') return null;
|
||||||
|
if (clipboardExModule) return clipboardExModule;
|
||||||
|
try {
|
||||||
|
// eslint-disable-next-line global-require, @typescript-eslint/no-var-requires
|
||||||
|
clipboardExModule = require('electron-clipboard-ex');
|
||||||
|
} catch {
|
||||||
|
clipboardExModule = null;
|
||||||
|
}
|
||||||
|
return clipboardExModule;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 把一组文件路径变成 Windows 规定的文本格式。
|
||||||
|
* 要求:每个路径之间用单个空字符分隔,最后再额外放两个空字符,表示列表结束。
|
||||||
|
* Windows 资源管理器会按这个格式解析我们复制到剪贴板的文件。
|
||||||
|
*/
|
||||||
|
const buildWindowsFileListPayload = (files: string[]): Buffer =>
|
||||||
|
Buffer.from(`${files.join('\0')}\0\0`, 'utf16le');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造 CF_HDROP 专用的二进制数据。
|
||||||
|
* 这是 Windows 复制文件时的底层格式,前 20 字节是固定的结构头,
|
||||||
|
* 后面紧跟着具体的文件路径(由 buildWindowsFileListPayload 生成)。
|
||||||
|
* 只要把这个内容写入剪贴板,任何支持粘贴文件的程序都能理解。
|
||||||
|
*/
|
||||||
|
const buildWindowsFileDropBuffer = (files: string[]): Buffer => {
|
||||||
|
const payload = buildWindowsFileListPayload(files);
|
||||||
|
const header = Buffer.alloc(DROPFILES_HEADER_SIZE);
|
||||||
|
header.writeUInt32LE(DROPFILES_HEADER_SIZE, 0);
|
||||||
|
header.writeInt32LE(0, 4);
|
||||||
|
header.writeInt32LE(0, 8);
|
||||||
|
header.writeUInt32LE(0, 12);
|
||||||
|
header.writeUInt32LE(1, 16);
|
||||||
|
|
||||||
|
const result = Buffer.alloc(header.length + payload.length);
|
||||||
|
for (let i = 0; i < header.length; i += 1) {
|
||||||
|
result[i] = header[i];
|
||||||
|
}
|
||||||
|
for (let i = 0; i < payload.length; i += 1) {
|
||||||
|
result[header.length + i] = payload[i];
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 复制/移动/创建快捷方式 等不同操作在 Windows 中对应不同的“意图”值。
|
||||||
|
* Preferred DropEffect 告诉系统:当前剪贴板数据应该以何种方式处理。
|
||||||
|
* 我们默认写入“copy”,相当于普通的复制粘贴。
|
||||||
|
*/
|
||||||
|
const buildDropEffectBuffer = (effect: 'copy' | 'move' | 'link' = 'copy') => {
|
||||||
|
const effectMap = {
|
||||||
|
copy: 1,
|
||||||
|
move: 2,
|
||||||
|
link: 4,
|
||||||
|
} as const;
|
||||||
|
const buffer = Buffer.alloc(4);
|
||||||
|
buffer.writeUInt32LE(effectMap[effect], 0);
|
||||||
|
return buffer;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 直接使用 Electron 内置 API 写入多种剪贴板格式。
|
||||||
|
* 步骤:
|
||||||
|
* 1. 写入二进制的 CF_HDROP(含头部与路径列表)
|
||||||
|
* 2. 写入纯文本形式的 FileNameW(备选格式)
|
||||||
|
* 3. 写入 Preferred DropEffect(告诉系统“这是复制”)
|
||||||
|
* 全部成功后,读取一次 CF_HDROP 的长度,确认剪贴板里确实有内容。
|
||||||
|
*/
|
||||||
|
const writeWindowsBuffers = (files: string[]): boolean => {
|
||||||
|
try {
|
||||||
|
clipboard.writeBuffer('CF_HDROP', buildWindowsFileDropBuffer(files));
|
||||||
|
clipboard.writeBuffer('FileNameW', buildWindowsFileListPayload(files));
|
||||||
|
clipboard.writeBuffer('Preferred DropEffect', buildDropEffectBuffer('copy'));
|
||||||
|
return clipboard.readBuffer('CF_HDROP').length > 0;
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 如果项目中安装了 electron-clipboard-ex,我们优先使用它。
|
||||||
|
* 理由:该库通过原生方式与系统交互,兼容性往往优于 Electron 的 JS 层写入。
|
||||||
|
* 调用成功后,必要时读回文件列表做一次数量校验,确保复制的文件数量正确。
|
||||||
|
*/
|
||||||
|
const writeWithClipboardEx = (files: string[]): boolean => {
|
||||||
|
const clipboardEx = ensureClipboardEx();
|
||||||
|
if (!clipboardEx) return false;
|
||||||
|
try {
|
||||||
|
clipboardEx.writeFilePaths(files);
|
||||||
|
if (typeof clipboardEx.readFilePaths === 'function') {
|
||||||
|
const result = clipboardEx.readFilePaths();
|
||||||
|
return Array.isArray(result) && result.length === files.length;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 对外暴露的唯一入口。
|
||||||
|
* 1. 先把所有路径换成 Windows 可识别的标准形式(path.normalize)。
|
||||||
|
* 2. 尝试使用 electron-clipboard-ex 写入,如果成功就结束。
|
||||||
|
* 3. 若第三方库不可用或失败,再退回 Electron 原生写入流程。
|
||||||
|
* 这一层屏蔽了所有细节,外部调用者只需传入字符串数组即可。
|
||||||
|
*/
|
||||||
|
export const copyFilesToWindowsClipboard = (files: string[]): boolean => {
|
||||||
|
const normalizedFiles = files
|
||||||
|
.map((filePath) => path.normalize(filePath))
|
||||||
|
.filter(Boolean);
|
||||||
|
if (!normalizedFiles.length) return false;
|
||||||
|
if (writeWithClipboardEx(normalizedFiles)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return writeWindowsBuffers(normalizedFiles);
|
||||||
|
};
|
||||||
|
|
||||||
@@ -1,8 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div
|
<div id="components-layout" @mousedown="onMouseDown">
|
||||||
id="components-layout"
|
|
||||||
@mousedown="onMouseDown"
|
|
||||||
>
|
|
||||||
<Search
|
<Search
|
||||||
:currentPlugin="currentPlugin"
|
:currentPlugin="currentPlugin"
|
||||||
@changeCurrent="changeIndex"
|
@changeCurrent="changeIndex"
|
||||||
@@ -35,6 +32,7 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { watch, ref, toRaw } from 'vue';
|
import { watch, ref, toRaw } from 'vue';
|
||||||
|
import { exec } from 'child_process';
|
||||||
import Result from './components/result.vue';
|
import Result from './components/result.vue';
|
||||||
import Search from './components/search.vue';
|
import Search from './components/search.vue';
|
||||||
import getWindowHeight from '../common/utils/getWindowHeight';
|
import getWindowHeight from '../common/utils/getWindowHeight';
|
||||||
@@ -43,6 +41,7 @@ import useDrag from '../common/utils/dragWindow';
|
|||||||
import { getGlobal } from '@electron/remote';
|
import { getGlobal } from '@electron/remote';
|
||||||
import { PLUGIN_HISTORY } from '@/common/constans/renderer';
|
import { PLUGIN_HISTORY } from '@/common/constans/renderer';
|
||||||
import { message } from 'ant-design-vue';
|
import { message } from 'ant-design-vue';
|
||||||
|
import localConfig from './confOp';
|
||||||
|
|
||||||
const { onMouseDown } = useDrag();
|
const { onMouseDown } = useDrag();
|
||||||
const remote = window.require('@electron/remote');
|
const remote = window.require('@electron/remote');
|
||||||
@@ -73,6 +72,8 @@ initPlugins();
|
|||||||
const currentSelect = ref(0);
|
const currentSelect = ref(0);
|
||||||
const menuPluginInfo: any = ref({});
|
const menuPluginInfo: any = ref({});
|
||||||
|
|
||||||
|
const config: any = ref(localConfig.getConfig());
|
||||||
|
|
||||||
getPluginInfo({
|
getPluginInfo({
|
||||||
pluginName: 'feature',
|
pluginName: 'feature',
|
||||||
// eslint-disable-next-line no-undef
|
// eslint-disable-next-line no-undef
|
||||||
@@ -90,7 +91,9 @@ watch(
|
|||||||
window.rubick.setExpendHeight(
|
window.rubick.setExpendHeight(
|
||||||
getWindowHeight(
|
getWindowHeight(
|
||||||
options.value,
|
options.value,
|
||||||
pluginLoading.value ? [] : pluginHistory.value
|
pluginLoading.value || !config.value.perf.common.history
|
||||||
|
? []
|
||||||
|
: pluginHistory.value
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@@ -100,26 +103,15 @@ watch(
|
|||||||
);
|
);
|
||||||
|
|
||||||
const changeIndex = (index) => {
|
const changeIndex = (index) => {
|
||||||
if (!options.value.length) {
|
const len = options.value.length || pluginHistory.value.length;
|
||||||
if (!pluginHistory.value.length) return;
|
if (!len) return;
|
||||||
if (
|
if (currentSelect.value + index > len - 1) {
|
||||||
currentSelect.value + index > pluginHistory.value.length - 1 ||
|
|
||||||
currentSelect.value + index < 0
|
|
||||||
) {
|
|
||||||
currentSelect.value = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
currentSelect.value = currentSelect.value + index;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
currentSelect.value + index > options.value.length - 1 ||
|
|
||||||
currentSelect.value + index < 0
|
|
||||||
) {
|
|
||||||
currentSelect.value = 0;
|
currentSelect.value = 0;
|
||||||
return;
|
} else if (currentSelect.value + index < 0) {
|
||||||
|
currentSelect.value = len - 1;
|
||||||
|
} else {
|
||||||
|
currentSelect.value = currentSelect.value + index;
|
||||||
}
|
}
|
||||||
currentSelect.value = currentSelect.value + index;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const openMenu = (ext) => {
|
const openMenu = (ext) => {
|
||||||
@@ -142,6 +134,12 @@ const choosePlugin = (plugin) => {
|
|||||||
const localPlugins = getGlobal('LOCAL_PLUGINS').getLocalPlugins();
|
const localPlugins = getGlobal('LOCAL_PLUGINS').getLocalPlugins();
|
||||||
const currentChoose = plugin || pluginHistory.value[currentSelect.value];
|
const currentChoose = plugin || pluginHistory.value[currentSelect.value];
|
||||||
let hasRemove = true;
|
let hasRemove = true;
|
||||||
|
if (currentChoose.pluginType === 'app') {
|
||||||
|
hasRemove = false;
|
||||||
|
changePluginHistory(currentChoose);
|
||||||
|
exec(currentChoose.action);
|
||||||
|
return;
|
||||||
|
}
|
||||||
localPlugins.find((plugin) => {
|
localPlugins.find((plugin) => {
|
||||||
if (plugin.name === currentChoose.originName) {
|
if (plugin.name === currentChoose.originName) {
|
||||||
hasRemove = false;
|
hasRemove = false;
|
||||||
@@ -151,7 +149,9 @@ const choosePlugin = (plugin) => {
|
|||||||
});
|
});
|
||||||
if (hasRemove) {
|
if (hasRemove) {
|
||||||
const result = window.rubick.db.get(PLUGIN_HISTORY) || {};
|
const result = window.rubick.db.get(PLUGIN_HISTORY) || {};
|
||||||
const history = result.data.filter(item => item.originName !== currentChoose.originName);
|
const history = result.data.filter(
|
||||||
|
(item) => item.originName !== currentChoose.originName
|
||||||
|
);
|
||||||
setPluginHistory(history);
|
setPluginHistory(history);
|
||||||
return message.warning('插件已被卸载!');
|
return message.warning('插件已被卸载!');
|
||||||
}
|
}
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 17 KiB |
@@ -2,7 +2,12 @@
|
|||||||
<div v-show="!currentPlugin.name" class="options">
|
<div v-show="!currentPlugin.name" class="options">
|
||||||
<div
|
<div
|
||||||
class="history-plugins"
|
class="history-plugins"
|
||||||
v-if="!options.length || !(searchValue || !!clipboardFile.length)"
|
v-if="
|
||||||
|
!options.length &&
|
||||||
|
!searchValue &&
|
||||||
|
!clipboardFile.length &&
|
||||||
|
config.perf.common.history
|
||||||
|
"
|
||||||
>
|
>
|
||||||
<a-row>
|
<a-row>
|
||||||
<a-col
|
<a-col
|
||||||
@@ -44,12 +49,16 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import {defineEmits, defineProps, reactive, toRaw, watch} from 'vue';
|
import { defineEmits, defineProps, reactive, ref, toRaw, watch } from 'vue';
|
||||||
|
import localConfig from '../confOp';
|
||||||
|
|
||||||
const path = window.require('path');
|
const path = window.require('path');
|
||||||
const remote = window.require('@electron/remote');
|
const remote = window.require('@electron/remote');
|
||||||
|
|
||||||
declare const __static: string;
|
declare const __static: string;
|
||||||
|
|
||||||
|
const config: any = ref(localConfig.getConfig());
|
||||||
|
|
||||||
const props: any = defineProps({
|
const props: any = defineProps({
|
||||||
searchValue: {
|
searchValue: {
|
||||||
type: [String, Number],
|
type: [String, Number],
|
||||||
|
|||||||
@@ -25,6 +25,8 @@
|
|||||||
ref="mainInput"
|
ref="mainInput"
|
||||||
class="main-input"
|
class="main-input"
|
||||||
@input="(e) => changeValue(e)"
|
@input="(e) => changeValue(e)"
|
||||||
|
@keydown.left="(e) => keydownEvent(e, 'left')"
|
||||||
|
@keydown.right="(e) => keydownEvent(e, 'right')"
|
||||||
@keydown.down="(e) => keydownEvent(e, 'down')"
|
@keydown.down="(e) => keydownEvent(e, 'down')"
|
||||||
@keydown.tab="(e) => keydownEvent(e, 'down')"
|
@keydown.tab="(e) => keydownEvent(e, 'down')"
|
||||||
@keydown.up="(e) => keydownEvent(e, 'up')"
|
@keydown.up="(e) => keydownEvent(e, 'up')"
|
||||||
@@ -41,10 +43,7 @@
|
|||||||
>
|
>
|
||||||
<template #suffix>
|
<template #suffix>
|
||||||
<div class="suffix-tool">
|
<div class="suffix-tool">
|
||||||
<MoreOutlined
|
<MoreOutlined @click="showSeparate()" class="icon-more" />
|
||||||
@click="showSeparate()"
|
|
||||||
class="icon-more"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</a-input>
|
</a-input>
|
||||||
@@ -96,6 +95,7 @@ const emit = defineEmits([
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
const keydownEvent = (e, key: string) => {
|
const keydownEvent = (e, key: string) => {
|
||||||
|
key !== 'space' && e.preventDefault();
|
||||||
const { ctrlKey, shiftKey, altKey, metaKey } = e;
|
const { ctrlKey, shiftKey, altKey, metaKey } = e;
|
||||||
const modifiers: Array<string> = [];
|
const modifiers: Array<string> = [];
|
||||||
ctrlKey && modifiers.push('control');
|
ctrlKey && modifiers.push('control');
|
||||||
@@ -119,12 +119,19 @@ const keydownEvent = (e, key: string) => {
|
|||||||
case 'down':
|
case 'down':
|
||||||
emit('changeCurrent', 1);
|
emit('changeCurrent', 1);
|
||||||
break;
|
break;
|
||||||
|
case 'left':
|
||||||
|
emit('changeCurrent', -1);
|
||||||
|
break;
|
||||||
|
case 'right':
|
||||||
|
emit('changeCurrent', 1);
|
||||||
|
break;
|
||||||
case 'enter':
|
case 'enter':
|
||||||
if (runPluginDisable) return;
|
if (runPluginDisable) return;
|
||||||
emit('choosePlugin');
|
emit('choosePlugin');
|
||||||
break;
|
break;
|
||||||
case 'space':
|
case 'space':
|
||||||
if (runPluginDisable || !config.value.perf.common.space) return;
|
if (runPluginDisable || !config.value.perf.common.space) return;
|
||||||
|
e.preventDefault();
|
||||||
emit('choosePlugin');
|
emit('choosePlugin');
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ const createPluginManager = (): any => {
|
|||||||
const initLocalStartPlugin = () => {
|
const initLocalStartPlugin = () => {
|
||||||
const result = ipcRenderer.sendSync('msg-trigger', {
|
const result = ipcRenderer.sendSync('msg-trigger', {
|
||||||
type: 'dbGet',
|
type: 'dbGet',
|
||||||
data: { id: PLUGIN_HISTORY },
|
data: { id: 'rubick-local-start-app' },
|
||||||
});
|
});
|
||||||
if (result && result.value) {
|
if (result && result.value) {
|
||||||
appList.value.push(...result.value);
|
appList.value.push(...result.value);
|
||||||
@@ -77,6 +77,10 @@ const createPluginManager = (): any => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const openPlugin = async (plugin, option) => {
|
const openPlugin = async (plugin, option) => {
|
||||||
|
ipcRenderer.send('msg-trigger', {
|
||||||
|
type: 'removePlugin',
|
||||||
|
});
|
||||||
|
window.initRubick();
|
||||||
if (plugin.pluginType === 'ui' || plugin.pluginType === 'system') {
|
if (plugin.pluginType === 'ui' || plugin.pluginType === 'system') {
|
||||||
if (state.currentPlugin && state.currentPlugin.name === plugin.name) {
|
if (state.currentPlugin && state.currentPlugin.name === plugin.name) {
|
||||||
window.rubick.showMainWindow();
|
window.rubick.showMainWindow();
|
||||||
@@ -103,7 +107,6 @@ const createPluginManager = (): any => {
|
|||||||
message.error('启动应用出错,请确保启动应用存在!');
|
message.error('启动应用出错,请确保启动应用存在!');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
window.initRubick();
|
|
||||||
changePluginHistory({
|
changePluginHistory({
|
||||||
...plugin,
|
...plugin,
|
||||||
...option,
|
...option,
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import useFocus from './clipboardWatch';
|
|||||||
|
|
||||||
function formatReg(regStr) {
|
function formatReg(regStr) {
|
||||||
const flags = regStr.replace(/.*\/([gimy]*)$/, '$1');
|
const flags = regStr.replace(/.*\/([gimy]*)$/, '$1');
|
||||||
const pattern = flags.replace(new RegExp('^/(.*?)/' + flags + '$'), '$1');
|
const pattern = regStr.replace(new RegExp('^/(.*?)/' + flags + '$'), '$1');
|
||||||
return new RegExp(pattern, flags);
|
return new RegExp(pattern, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -102,7 +102,9 @@ module.exports = {
|
|||||||
include: 'public/installer.nsh',
|
include: 'public/installer.nsh',
|
||||||
},
|
},
|
||||||
linux: {
|
linux: {
|
||||||
icon: 'build/icons/',
|
icon: 'public/icons/',
|
||||||
|
publish: ['github'],
|
||||||
|
target: 'deb',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||