Compare commits

...

19 Commits

Author SHA1 Message Date
木偶
404cb4fcb5 Merge pull request #267 from lumozx/master
fix: 多端数据同步下,列表适配暗黑模式
2023-10-20 15:50:43 +08:00
muwoo
5553170c5a 🐛 修复分离窗口后主程序失去响应的bug 2023-10-20 15:33:41 +08:00
lumozx
d8fabc6b4c fix: 暗黑模式下,点击刷新插件,插件名称输入框暗黑模式失效的问题 2023-10-20 12:12:10 +08:00
lumozx
88e4e325f3 fix: 选择器和输入框适配暗黑模式 2023-10-20 12:09:46 +08:00
muwoo
c0aaae08ee 🐛 修复 linux CI 2023-10-20 11:45:46 +08:00
muwoo
35598159a6 🐛 修复 linux CI 2023-10-20 11:45:36 +08:00
muwoo
2a1a332fbb ♻️ 修改 onPluginEnter 执行时机. 2023-10-20 11:23:57 +08:00
lumozx
6d105e0f56 fix: drawer与model暗黑适配 2023-10-20 11:01:21 +08:00
lumozx
d2acdeaad6 fix: 列表页暗黑适配 2023-10-20 10:27:56 +08:00
lumozx
54ad4ef7b2 Merge branch 'rubickCenter:master' into master 2023-10-19 21:33:15 +08:00
muwoo
7fb299d270 🐛 修复 #268 2023-10-19 15:24:13 +08:00
lumozx
606cb8bb22 fix: 多端数据同步下,列表适配暗黑模式 2023-10-18 12:44:49 +08:00
muwoo
142387d684 🐛 修复CI 2023-10-18 11:25:58 +08:00
muwoo
77127b55b0 Merge remote-tracking branch 'origin/master'
# Conflicts:
#	src/main/index.ts
2023-10-18 11:03:10 +08:00
muwoo
bde5377282 🐛 修复 #264
 支持 db.postAttachment 和 db.getAttachment
♻️ 重构版本更新机制
2023-10-18 11:02:14 +08:00
木偶
d48f8638ed Merge pull request #262 from lumozx/master
优化引导页UI,修复部分文案错误
2023-10-16 21:49:08 +08:00
lumozx
9c92e0f5fa fix: 引导样式
1、margin-left太宽导致出现滚动条
2、aligin-items -> align-items
3、按钮优化鼠标手势
2023-10-16 16:30:10 +08:00
lumozx
af11f46518 fix: LICENSE非md文件 2023-10-16 16:26:51 +08:00
lumozx
d4a4a168cd fix: registerySystemPlugin -> registerSystemPlugin 2023-10-16 16:26:18 +08:00
26 changed files with 295 additions and 147 deletions

View File

@@ -94,4 +94,4 @@ This project exists thanks to all the people who contribute. [[Contribute](https
![image](https://user-images.githubusercontent.com/21073039/127327603-9796f246-ee4b-4950-a69d-ce3205ec9569.png)
## License
This project is licensed under the MIT License - see the [LICENSE.md](https://github.com/rubickCenter/rubick/blob/master/LICENSE) file for details.
This project is licensed under the MIT License - see the [LICENSE](https://github.com/rubickCenter/rubick/blob/master/LICENSE) file for details.

View File

@@ -94,5 +94,5 @@ This project exists thanks to all the people who contribute. [[Contribute](https
![image](https://user-images.githubusercontent.com/21073039/127327603-9796f246-ee4b-4950-a69d-ce3205ec9569.png)
## License
This project is licensed under the MIT License - see the [LICENSE.md](https://github.com/rubickCenter/rubick/blob/master/LICENSE) file for details.
This project is licensed under the MIT License - see the [LICENSE](https://github.com/rubickCenter/rubick/blob/master/LICENSE) file for details.

View File

@@ -15,6 +15,8 @@
--color-input-hover: #fff;
// 边框
--color-border-light: #f0f0f0;
// 输入框附带icon
--color-action-color: rgba(0, 0, 0, 0.25);;
}
.dark {
@@ -29,4 +31,6 @@
--color-input-hover: #444d;
// 边框
--color-border-light: #444d;
// 输入框附带icon
--color-action-color: #ffffff4d;
}

View File

@@ -103,7 +103,7 @@ const wrapperCol = { span: 14 };
color: var(--color-text-content);
}
:deep(.ant-input) {
background: var(--color-input-hover);
background: var(--color-input-hover) !important;
color: var(--color-text-content);
}
}

View File

@@ -6,7 +6,7 @@
<ExportOutlined />
</template>
</a-button>
<a-button @click="importData" danger size="small" style="margin-right: 10px;">
<a-button @click="importData" danger size="small" style="margin-right: 10px; background-color: var(--color-input-hover)">
导入数据
<template #icon>
<ImportOutlined />
@@ -22,25 +22,30 @@
<template #renderItem="{ item }">
<a-list-item>
<template #actions>
<a v-if="!item.plugin.isdownload && !item.plugin.isloading" key="list-loadmore-edit"
<a v-if="!item.plugin?.isdownload && !item.plugin?.isloading" key="list-loadmore-edit"
@click="() => downloadPlugin(item.plugin)">
<CloudDownloadOutlined style="font-size: 18px;"/>
</a>
<a v-if="item.plugin.isloading" key="list-loadmore-edit">
<a v-if="item.plugin?.isloading" key="list-loadmore-edit">
<LoadingOutlined style="font-size: 18px;"/>
</a>
<a key="list-loadmore-edit" @click="() => showKeys(item)">
<DatabaseOutlined style="font-size: 18px;"/>
</a>
</template>
<a-list-item-meta :description="`${item.keys.length} 份文档`">
<a-list-item-meta>
<template #title>
<div>
<span>{{ item.plugin.pluginName }}</span>
<div style="color: var(--color-text-content)">
<span>{{ item.plugin?.pluginName }}</span>
</div>
</template>
<template #avatar>
<a-avatar shape="square" :src="item.plugin.logo"/>
<a-avatar shape="square" :src="item.plugin?.logo"/>
</template>
<template #description>
<div style="color: var(--color-text-desc)">
<span>{{ item.keys.length }} 份文档</span>
</div>
</template>
</a-list-item-meta>
</a-list-item>
@@ -52,6 +57,7 @@
:closable="false"
:title="currentSelect.plugin.pluginName"
placement="right"
class="exportDrawer"
>
<p
class="key-item"
@@ -64,7 +70,12 @@
</a-drawer>
<a-modal
centered
bodyStyle="max-height: 500px; overflow: auto"
:bodyStyle="{
maxHeight: '500px',
overflow: 'auto',
backgroundColor: 'var(--color-body-bg)',
color: 'var(--color-text-primary)'
}"
:footer="null"
:closable="false"
v-model:visible="show"
@@ -75,6 +86,7 @@
v-model:visible="showSetting"
title="webdav 账户配置"
:footer="null"
class="webdavModel"
>
<a-alert v-if="formState.suport === 'jianguo'" style="margin-bottom: 20px;" type="info" show-icon>
<template #message>
@@ -255,7 +267,7 @@ const downloadPlugin = async (plugin) => {
.export-header {
width: 100%;
height: 40px;
border-bottom: 1px solid #eee;
border-bottom: 1px solid var(--color-border-light);
text-align: right;
}
.key-item {
@@ -265,4 +277,44 @@ const downloadPlugin = async (plugin) => {
color: var(--ant-primary-color);
}
}
.exportDrawer{
.ant-drawer-header{
background-color: var(--color-body-bg);
border-bottom: 1px solid var(--color-border-light);
.ant-drawer-title{
color: var(--color-text-primary);
}
}
.ant-drawer-body{
background-color: var(--color-body-bg);
color: var(--color-text-content)
}
}
.webdavModel{
.ant-modal-close-x{
color: var(--color-text-content);
}
.ant-modal-header{
background-color: var(--color-body-bg);
border-bottom: 1px solid var(--color-border-light);
.ant-modal-title{
color: var(--color-text-primary);
}
}
.ant-form-item-label>label {
color: var(--color-text-content);
}
.ant-modal-body {
background-color: var(--color-body-bg);
.ant-input,
.ant-input-password,
.ant-select-selector {
background: var(--color-input-hover) !important;
color: var(--color-text-content);
}
.ant-input-password-icon, .ant-select-arrow {
color: var(--color-action-color);
}
}
}
</style>

View File

@@ -512,6 +512,13 @@ const changeLanguage = (value) => {
background: var(--color-list-hover);
}
}
.ant-select-selector {
background: var(--color-input-hover) !important;
color: var(--color-text-content);
}
.ant-input-password-icon, .ant-select-arrow {
color: var(--color-action-color);
}
}
}
}

View File

@@ -102,11 +102,11 @@ const netStep = () => {
}
.info {
padding-top: 42px;
margin-left: 178px;
margin-left: 84px;
box-sizing: border-box;
width: 100%;
text-align: left;
position: relative;
align-self: flex-start;
color: @text-color;
.top-icon {
position: absolute;
@@ -147,9 +147,11 @@ const netStep = () => {
background: @primary-color;
color: #fff;
display: flex;
aligin-items: center;
align-items: center;
justify-content: center;
border-radius: 4px;
cursor: pointer;
user-select: none;
}
}

View File

@@ -1,6 +1,6 @@
{
"name": "rubick",
"version": "4.0.4",
"version": "4.0.8",
"author": "muwoo <2424880409@qq.com>",
"private": true,
"scripts": {
@@ -14,7 +14,7 @@
"postinstall": "electron-builder install-app-deps",
"postuninstall": "electron-builder install-app-deps"
},
"main": "background.js",
"main": "index.js",
"optionalDependencies": {
"electron-clipboard-ex": "^1.3.3"
},
@@ -69,7 +69,7 @@
"less-loader": "^5.0.0",
"prettier": "^2.8.4",
"typescript": "~4.1.5",
"vue-cli-plugin-electron-builder": "~2.1.1",
"vue-cli-plugin-electron-builder": "3.0.0-alpha.4",
"worker-plugin": "^5.0.1"
},
"resolutions": {

View File

@@ -0,0 +1 @@
*{margin:0;padding:0}.guide-container .step0{padding:28px;padding-top:36px;box-sizing:border-box;display:flex;flex-direction:column;width:100vw;height:100vh}.guide-container .title{font-size:28px;font-weight:600;color:#574777}.guide-container .down-line{line-height:24px;color:#ff4ea4}.guide-container .desc{padding-top:10px;box-sizing:border-box;font-size:24px}.guide-container .img-container{flex:1;display:flex;flex-direction:column;justify-content:center;align-items:center}.guide-container .img{width:680px}.guide-container .info{padding-top:42px;margin-left:84px;box-sizing:border-box;text-align:left;position:relative;align-self:flex-start;color:#574777}.guide-container .info .top-icon{position:absolute;left:0;top:0;-webkit-user-select:none;-moz-user-select:none;user-select:none;width:1em;height:1em;display:inline-block;fill:currentcolor;flex-shrink:0;transition:fill .2s cubic-bezier(.4,0,.2,1) 0ms;font-size:1.5rem}.footer{position:fixed;bottom:0;left:0;width:100%;justify-content:space-between;padding:20px;box-sizing:border-box}.footer,.footer .step{display:flex;align-items:center}.footer .step-num{margin-right:20px}.footer .button{width:100px;height:40px;line-height:40px;background:#ff4ea4;color:#fff;display:flex;align-items:center;justify-content:center;border-radius:4px;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;user-select:none}.step4 .img{width:300px}.step1 .img{width:550px}

View File

@@ -1 +0,0 @@
*{margin:0;padding:0}.guide-container .step0{padding:28px;padding-top:36px;box-sizing:border-box;display:flex;flex-direction:column;width:100vw;height:100vh}.guide-container .title{font-size:28px;font-weight:600;color:#574777}.guide-container .down-line{line-height:24px;color:#ff4ea4}.guide-container .desc{padding-top:10px;box-sizing:border-box;font-size:24px}.guide-container .img-container{flex:1;display:flex;flex-direction:column;justify-content:center;align-items:center}.guide-container .img{width:680px}.guide-container .info{padding-top:42px;margin-left:178px;box-sizing:border-box;width:100%;text-align:left;position:relative;color:#574777}.guide-container .info .top-icon{position:absolute;left:0;top:0;-webkit-user-select:none;-moz-user-select:none;user-select:none;width:1em;height:1em;display:inline-block;fill:currentcolor;flex-shrink:0;transition:fill .2s cubic-bezier(.4,0,.2,1) 0ms;font-size:1.5rem}.footer{position:fixed;bottom:0;left:0;width:100%;justify-content:space-between;padding:20px;box-sizing:border-box}.footer,.footer .step{display:flex;align-items:center}.footer .step-num{margin-right:20px}.footer .button{width:100px;height:40px;line-height:40px;background:#ff4ea4;color:#fff;display:flex;aligin-items:center;justify-content:center;border-radius:4px}.step4 .img{width:300px}.step1 .img{width:550px}

View File

@@ -1 +1 @@
<!doctype html><html lang=""><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="favicon.ico"><title>rubick 桌面端开源工具箱</title><script defer="defer" src="js/chunk-vendors.c1874e13.js"></script><script defer="defer" src="js/app.b3377163.js"></script><link href="css/app.8c142cf3.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but guide doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div></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>rubick 桌面端开源工具箱</title><script defer="defer" src="js/chunk-vendors.c1874e13.js"></script><script defer="defer" src="js/app.c403c1a5.js"></script><link href="css/app.5b19f647.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but guide doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div></body></html>

View File

@@ -1 +1 @@
(function(){"use strict";var i={544:function(i,n,s){var e=s(963),t=s(252),c=s(577),a=s.p+"img/img.02a1c5f1.png",r=s.p+"img/img_1.097595c9.png",l=s.p+"img/img_2.cd4c34db.png",o=s.p+"img/img_3.1ad5b474.png",u=s(262);const d={class:"guide-container"},v={class:"step0"},p=(0,t._)("div",{class:"title"},"您好,我叫 Rubick",-1),f=(0,t._)("div",{class:"desc"},[(0,t.Uk)("快捷键 "),(0,t._)("span",{class:"down-line"},"Alt + R"),(0,t.Uk)(" 可以快速打开我")],-1),g=(0,t._)("div",{class:"img-container"},[(0,t._)("img",{class:"img",src:a}),(0,t._)("div",{class:"info"},[(0,t._)("svg",{class:"top-icon",focusable:"false","aria-hidden":"true",viewBox:"0 0 24 24","data-testid":"NorthIcon"},[(0,t._)("path",{d:"m5 9 1.41 1.41L11 5.83V22h2V5.83l4.59 4.59L19 9l-7-7-7 7z"})]),(0,t.Uk)(" 点击 logo 进入插件市场 ")])],-1),m=[p,f,g],w={class:"step0 step1"},_=(0,t.uE)('<div class="title">选择需要的插件安装</div><div class="desc">基于 <span class="down-line">npm</span> 的插件包管理,像小程序一样,用完即走</div><div class="img-container"><img class="img" src="'+r+'"></div>',3),h=[_],b={class:"step0"},y=(0,t.uE)('<div class="title"><span class="down-line">关键字</span>搜索应用和插件</div><div class="desc">搜索框内输入关键字可以搜索安装的应用和插件</div><div class="img-container"><img class="img" src="'+l+'"></div>',3),O=[y],k={class:"step0 step1"},j=(0,t.uE)('<div class="title">完全开源免费,支持内网部署</div><div class="desc">进入插件市场的 <span class="down-line">账户与设置</span> 菜单,进行内网部署设置</div><div class="img-container"><img class="img" src="'+o+'"></div>',3),x=[j],F={class:"footer"},E=(0,t._)("div",null,null,-1),z={class:"step"},C={class:"step-num"};var R={__name:"App",setup(i){const n=(0,u.iH)(0),{ipcRenderer:s}=window.require("electron"),a=()=>{if(n.value>=3)return s.send("guide:service",{type:"close"});n.value=n.value+1};return(i,s)=>((0,t.wg)(),(0,t.iD)("div",d,[(0,t.wy)((0,t._)("div",v,m,512),[[e.F8,0===n.value]]),(0,t.wy)((0,t._)("div",w,h,512),[[e.F8,1===n.value]]),(0,t.wy)((0,t._)("div",b,O,512),[[e.F8,2===n.value]]),(0,t.wy)((0,t._)("div",k,x,512),[[e.F8,3===n.value]]),(0,t._)("div",F,[E,(0,t._)("div",z,[(0,t._)("span",C,(0,c.zw)(n.value+1)+" / 4",1),(0,t._)("div",{class:"button",onClick:a},(0,c.zw)(n.value+1===4?"完成":"下一步"),1)])])]))}};const U=R;var A=U;(0,e.ri)(A).mount("#app")}},n={};function s(e){var t=n[e];if(void 0!==t)return t.exports;var c=n[e]={exports:{}};return i[e](c,c.exports,s),c.exports}s.m=i,function(){var i=[];s.O=function(n,e,t,c){if(!e){var a=1/0;for(u=0;u<i.length;u++){e=i[u][0],t=i[u][1],c=i[u][2];for(var r=!0,l=0;l<e.length;l++)(!1&c||a>=c)&&Object.keys(s.O).every((function(i){return s.O[i](e[l])}))?e.splice(l--,1):(r=!1,c<a&&(a=c));if(r){i.splice(u--,1);var o=t();void 0!==o&&(n=o)}}return n}c=c||0;for(var u=i.length;u>0&&i[u-1][2]>c;u--)i[u]=i[u-1];i[u]=[e,t,c]}}(),function(){s.d=function(i,n){for(var e in n)s.o(n,e)&&!s.o(i,e)&&Object.defineProperty(i,e,{enumerable:!0,get:n[e]})}}(),function(){s.g=function(){if("object"===typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(i){if("object"===typeof window)return window}}()}(),function(){s.o=function(i,n){return Object.prototype.hasOwnProperty.call(i,n)}}(),function(){s.p=""}(),function(){var i={143:0};s.O.j=function(n){return 0===i[n]};var n=function(n,e){var t,c,a=e[0],r=e[1],l=e[2],o=0;if(a.some((function(n){return 0!==i[n]}))){for(t in r)s.o(r,t)&&(s.m[t]=r[t]);if(l)var u=l(s)}for(n&&n(e);o<a.length;o++)c=a[o],s.o(i,c)&&i[c]&&i[c][0](),i[c]=0;return s.O(u)},e=self["webpackChunkguide"]=self["webpackChunkguide"]||[];e.forEach(n.bind(null,0)),e.push=n.bind(null,e.push.bind(e))}();var e=s.O(void 0,[998],(function(){return s(544)}));e=s.O(e)})();
(function(){"use strict";var i={141:function(i,n,s){var e=s(963),t=s(252),c=s(577),a=s.p+"img/img.02a1c5f1.png",r=s.p+"img/img_1.097595c9.png",l=s.p+"img/img_2.cd4c34db.png",o=s.p+"img/img_3.1ad5b474.png",u=s(262);const d={class:"guide-container"},v={class:"step0"},p=(0,t._)("div",{class:"title"},"您好,我叫 Rubick",-1),f=(0,t._)("div",{class:"desc"},[(0,t.Uk)("快捷键 "),(0,t._)("span",{class:"down-line"},"Alt + R"),(0,t.Uk)(" 可以快速打开我")],-1),g=(0,t._)("div",{class:"img-container"},[(0,t._)("img",{class:"img",src:a}),(0,t._)("div",{class:"info"},[(0,t._)("svg",{class:"top-icon",focusable:"false","aria-hidden":"true",viewBox:"0 0 24 24","data-testid":"NorthIcon"},[(0,t._)("path",{d:"m5 9 1.41 1.41L11 5.83V22h2V5.83l4.59 4.59L19 9l-7-7-7 7z"})]),(0,t.Uk)(" 点击 logo 进入插件市场 ")])],-1),m=[p,f,g],w={class:"step0 step1"},_=(0,t.uE)('<div class="title">选择需要的插件安装</div><div class="desc">基于 <span class="down-line">npm</span> 的插件包管理,像小程序一样,用完即走</div><div class="img-container"><img class="img" src="'+r+'"></div>',3),h=[_],b={class:"step0"},y=(0,t.uE)('<div class="title"><span class="down-line">关键字</span>搜索应用和插件</div><div class="desc">搜索框内输入关键字可以搜索安装的应用和插件</div><div class="img-container"><img class="img" src="'+l+'"></div>',3),O=[y],k={class:"step0 step1"},j=(0,t.uE)('<div class="title">完全开源免费,支持内网部署</div><div class="desc">进入插件市场的 <span class="down-line">账户与设置</span> 菜单,进行内网部署设置</div><div class="img-container"><img class="img" src="'+o+'"></div>',3),x=[j],F={class:"footer"},E=(0,t._)("div",null,null,-1),z={class:"step"},C={class:"step-num"};var R={__name:"App",setup(i){const n=(0,u.iH)(0),{ipcRenderer:s}=window.require("electron"),a=()=>{if(n.value>=3)return s.send("guide:service",{type:"close"});n.value=n.value+1};return(i,s)=>((0,t.wg)(),(0,t.iD)("div",d,[(0,t.wy)((0,t._)("div",v,m,512),[[e.F8,0===n.value]]),(0,t.wy)((0,t._)("div",w,h,512),[[e.F8,1===n.value]]),(0,t.wy)((0,t._)("div",b,O,512),[[e.F8,2===n.value]]),(0,t.wy)((0,t._)("div",k,x,512),[[e.F8,3===n.value]]),(0,t._)("div",F,[E,(0,t._)("div",z,[(0,t._)("span",C,(0,c.zw)(n.value+1)+" / 4",1),(0,t._)("div",{class:"button",onClick:a},(0,c.zw)(n.value+1===4?"完成":"下一步"),1)])])]))}};const U=R;var A=U;(0,e.ri)(A).mount("#app")}},n={};function s(e){var t=n[e];if(void 0!==t)return t.exports;var c=n[e]={exports:{}};return i[e](c,c.exports,s),c.exports}s.m=i,function(){var i=[];s.O=function(n,e,t,c){if(!e){var a=1/0;for(u=0;u<i.length;u++){e=i[u][0],t=i[u][1],c=i[u][2];for(var r=!0,l=0;l<e.length;l++)(!1&c||a>=c)&&Object.keys(s.O).every((function(i){return s.O[i](e[l])}))?e.splice(l--,1):(r=!1,c<a&&(a=c));if(r){i.splice(u--,1);var o=t();void 0!==o&&(n=o)}}return n}c=c||0;for(var u=i.length;u>0&&i[u-1][2]>c;u--)i[u]=i[u-1];i[u]=[e,t,c]}}(),function(){s.d=function(i,n){for(var e in n)s.o(n,e)&&!s.o(i,e)&&Object.defineProperty(i,e,{enumerable:!0,get:n[e]})}}(),function(){s.g=function(){if("object"===typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(i){if("object"===typeof window)return window}}()}(),function(){s.o=function(i,n){return Object.prototype.hasOwnProperty.call(i,n)}}(),function(){s.p=""}(),function(){var i={143:0};s.O.j=function(n){return 0===i[n]};var n=function(n,e){var t,c,a=e[0],r=e[1],l=e[2],o=0;if(a.some((function(n){return 0!==i[n]}))){for(t in r)s.o(r,t)&&(s.m[t]=r[t]);if(l)var u=l(s)}for(n&&n(e);o<a.length;o++)c=a[o],s.o(i,c)&&i[c]&&i[c][0](),i[c]=0;return s.O(u)},e=self["webpackChunkguide"]=self["webpackChunkguide"]||[];e.forEach(n.bind(null,0)),e.push=n.bind(null,e.push.bind(e))}();var e=s.O(void 0,[998],(function(){return s(141)}));e=s.O(e)})();

View File

@@ -85,6 +85,10 @@ window.rubick = {
remove: (doc) => ipcSendSync('dbRemove', { doc }),
bulkDocs: (docs) => ipcSendSync('dbBulkDocs', { docs }),
allDocs: (key) => ipcSendSync('dbAllDocs', { key }),
postAttachment: (docId, attachment, type) =>
ipcSendSync('dbPostAttachment', { docId, attachment, type }),
getAttachment: (docId) => ipcSendSync('dbGetAttachment', { docId }),
getAttachmentType: (docId) => ipcSendSync('dbGetAttachmentType', { docId }),
},
dbStorage: {
setItem: (key, value) => {

View File

@@ -17,10 +17,13 @@ export default function getCopyFiles(): Array<any> | null {
return null;
}
} else if (process.platform === 'win32') {
/* eslint-disable */
const clipboardEx = require('electron-clipboard-ex');
fileInfo = clipboardEx.readFilePaths();
// todo
try {
/* eslint-disable */
const clipboardEx = require('electron-clipboard-ex');
fileInfo = clipboardEx.readFilePaths();
} catch (e) {
// todo
}
} else {
if (!commonConst.linux()) return null;
if (!clipboard.has('text/uri-list')) return null;

View File

@@ -204,4 +204,38 @@ export default class DB {
this.pouchDB = syncDb.pouchDB;
await webdavClient.createReadStream(this.pouchDB);
}
public async postAttachment(
name: string,
docId: string,
attachment: Buffer | Uint8Array,
type: string
) {
const buffer = Buffer.from(attachment);
if (buffer.byteLength > this.docAttachmentMaxByteLength)
return this.errorInfo(
'exception',
'attachment data up to ' +
this.docAttachmentMaxByteLength / 1024 / 1024 +
'M'
);
try {
const result = await this.pouchDB.put({
_id: this.getDocId(name, docId),
_attachments: { 0: { data: buffer, content_type: type } },
});
result.id = this.replaceDocId(name, result.id);
return result;
} catch (e) {
return this.errorInfo(e.name, e.message);
}
}
async getAttachment(name: string, docId: string, len = '0') {
try {
return await this.pouchDB.getAttachment(this.getDocId(name, docId), len);
} catch (e) {
return null;
}
}
}

View File

@@ -11,8 +11,8 @@ type WebDavOptions = {
};
type DBInstance = {
loadIt: (stream: unknown) => void;
dump: (stream: unknown) => void;
loadIt: (stream: unknown, options?: any) => void;
dump: (stream: unknown, options?: any) => void;
};
export default class WebDav {
@@ -54,7 +54,12 @@ export default class WebDav {
}).show();
}
const ws = new MemoryStream();
dbInstance.dump(ws);
dbInstance.dump(ws, {
filter: (doc) => {
// attachment 文档导出有问题,
return !doc._attachments;
},
});
ws.pipe(
this.client.createWriteStream(this.cloudPath, {}, () => {
new Notification({

View File

@@ -157,13 +157,17 @@ class AdapterHandler {
*/
private async execCommand(cmd: string, modules: string[]): Promise<string> {
return new Promise((resolve: any, reject: any) => {
const args: string[] = [cmd]
.concat(
cmd !== 'uninstall' ? modules.map((m) => `${m}@latest`) : modules
)
.concat('--color=always')
.concat('--save')
.concat(`--registry=${this.registry}`);
let args: string[] = [cmd].concat(
cmd !== 'uninstall' && cmd !== 'link'
? modules.map((m) => `${m}@latest`)
: modules
);
if (cmd !== 'link') {
args = args
.concat('--color=always')
.concat('--save')
.concat(`--registry=${this.registry}`);
}
const npm = spawn('npm', args, {
cwd: this.baseDir,

View File

@@ -73,23 +73,31 @@ export default () => {
const init = (plugin, window: BrowserWindow) => {
if (view === null || view === undefined) {
if (viewInstance.getView(plugin.name) && !commonConst.dev()) {
view = viewInstance.getView(plugin.name).view;
window.setBrowserView(view);
view.inited = true;
viewReadyFn(window, plugin);
} else {
createView(plugin, window);
viewInstance.addView(plugin.name, view);
}
createView(plugin, window);
// if (viewInstance.getView(plugin.name) && !commonConst.dev()) {
// view = viewInstance.getView(plugin.name).view;
// window.setBrowserView(view);
// view.inited = true;
// viewReadyFn(window, plugin);
// } else {
// createView(plugin, window);
// viewInstance.addView(plugin.name, view);
// }
// eslint-disable-next-line @typescript-eslint/no-var-requires
require('@electron/remote/main').enable(view.webContents);
}
};
const createView = (plugin, window: BrowserWindow) => {
const { tplPath, indexPath, development, name, main, pluginSetting, ext } =
plugin;
const {
tplPath,
indexPath,
development,
name,
main = 'index.html',
pluginSetting,
ext,
} = plugin;
let pluginIndexPath = tplPath || indexPath;
let preloadPath;
let darkMode;
@@ -160,21 +168,23 @@ export default () => {
window.removeBrowserView(view);
window.setSize(800, 60);
executeHooks('PluginOut', null);
window.webContents.executeJavaScript(`window.initRubick()`);
window.webContents?.executeJavaScript(`window.initRubick()`);
view = undefined;
};
const getView = () => view;
const executeHooks = (hook, data) => {
if (!view) return;
const evalJs = `if(window.rubick && window.rubick.hooks && typeof window.rubick.hooks.on${hook} === 'function' ) {
try {
setTimeout(() => {
if (!view) return;
const evalJs = `if(window.rubick && window.rubick.hooks && typeof window.rubick.hooks.on${hook} === 'function' ) {
try {
window.rubick.hooks.on${hook}(${data ? JSON.stringify(data) : ''});
} catch(e) {}
} catch(e) {}
}
`;
view.webContents.executeJavaScript(evalJs);
view.webContents?.executeJavaScript(evalJs);
}, 300);
};
return {

View File

@@ -14,13 +14,18 @@ import { screenCapture } from '@/core';
import plist from 'plist';
import ks from 'node-key-sender';
import { DECODE_KEY } from '@/common/constans/main';
import {
DECODE_KEY,
PLUGIN_INSTALL_DIR as baseDir,
} from '@/common/constans/main';
import getCopyFiles from '@/common/utils/getCopyFiles';
import common from '@/common/utils/commonConst';
import mainInstance from '../index';
import { runner, detach } from '../browsers';
import DBInstance from './db';
import getWinPosition from './getWinPosition';
import path from 'path';
const runnerInstance = runner();
const detachInstance = detach();
@@ -77,8 +82,29 @@ class API extends DBInstance {
}
public openPlugin({ data: plugin }, window) {
if (plugin.platform && !plugin.platform.includes(process.platform)) {
return new Notification({
title: `插件不支持当前 ${process.platform} 系统`,
body: `插件仅支持 ${plugin.platform.join(',')}`,
icon: plugin.logo,
}).show();
}
window.setSize(window.getSize()[0], 60);
this.removePlugin(null, window);
// 模板文件
if (!plugin.main) {
plugin.tplPath = common.dev()
? 'http://localhost:8083/#/'
: `file://${__static}/tpl/index.html`;
}
if (!plugin.indexPath) {
const pluginPath = path.resolve(baseDir, 'node_modules', plugin.name);
plugin.indexPath = `file://${path.join(
pluginPath,
'./',
plugin.main || ''
)}`;
}
runnerInstance.init(plugin, window);
this.currentPlugin = plugin;
window.webContents.executeJavaScript(
@@ -196,7 +222,7 @@ class API extends DBInstance {
}
public getFeatures() {
return this.currentPlugin.features;
return this.currentPlugin?.features;
}
public setFeature({ data }, window) {

View File

@@ -54,4 +54,20 @@ export default class DBInstance {
public dbImport({ data }) {
return dbInstance.importDb(data.target);
}
public dbPostAttachment({ data }) {
const { docId, attachment, type } = data;
return dbInstance.postAttachment(this.DBKEY, docId, attachment, type);
}
public dbGetAttachment({ data }) {
return dbInstance.getAttachment(this.DBKEY, data.docId);
}
public async dbGetAttachmentType({ data }) {
const res: any = await this.dbGet(data.docId);
if (!res || !res._attachments) return null;
const result = res._attachments[0];
return result ? result.content_type : null;
}
}

View File

@@ -0,0 +1,27 @@
// for referer policy, we can't use it in renderer
import axios from 'axios';
const RELEASE_URL = 'https://api.github.com/repos/rubickCenter/rubick/releases';
export const getLatestVersion = async (isCheckBetaUpdate = false) => {
let res = '';
try {
res = await axios
.get(RELEASE_URL, {
headers: {
Referer: 'https://github.com',
},
})
.then((r) => {
const list = r.data;
if (isCheckBetaUpdate) {
const betaList = list.filter((item) => item.name.includes('beta'));
return betaList[0].name;
}
const normalList = list.filter((item) => !item.name.includes('beta'));
return normalList[0].name;
});
} catch (err) {
console.log(err);
}
return res;
};

View File

@@ -1,96 +1,45 @@
import { dialog } from 'electron';
import { autoUpdater } from 'electron-updater';
import { dialog, shell } from 'electron';
import pkg from '../../../package.json';
import { main } from '../browsers';
import { lt } from 'semver';
import { getLatestVersion } from './getLatestVersion';
const version = pkg.version;
const downloadUrl = 'https://github.com/rubickCenter/rubick/releases/latest';
class VersionHandler {
private lastestVersion: string;
private currentVersion: string;
private releaseNotes: string;
private isUpdate: boolean;
constructor() {
this.lastestVersion = '';
this.currentVersion = pkg.version;
this.releaseNotes = '';
this.isUpdate = false;
autoUpdater.autoDownload = false;
autoUpdater.autoInstallOnAppQuit = false;
const checkVersion = async () => {
const res: string = await getLatestVersion();
if (res !== '') {
const latest = res;
const result = compareVersion2Update(version, latest);
if (result) {
dialog
.showMessageBox({
type: 'info',
title: 'Rubick 更新提示',
buttons: ['Yes', 'No'],
message: `发现新版本 v${latest},是否更新?`,
})
.then((res) => {
if (res.response === 0) {
// if selected yes
shell.openExternal(downloadUrl);
}
});
}
} else {
return false;
}
};
checkForMacAndWindows() {
let sendUpdateMsg = false;
autoUpdater.removeAllListeners();
// update-available 会触发多次,限制只通知一次
autoUpdater.checkForUpdates();
autoUpdater.on('download-progress', ({ percent }) => {
console.log('下载进度', percent);
// if (percent < 50) {
// }
this.isUpdate = true;
});
autoUpdater.on('update-available', (info) => {
if (sendUpdateMsg) return;
const { version, releaseName = 'normal', releaseNotes } = info;
this.lastestVersion = version;
sendUpdateMsg = true;
autoUpdater.on('update-downloaded', () => {
console.log('下载完成');
this.isUpdate = false;
if (releaseName === 'major') {
autoUpdater.quitAndInstall(true, true);
}
const mainWindow = main().getWindow();
dialog
.showMessageBox(mainWindow, {
title: '版本更新',
message: `发现新版本${this.lastestVersion},是否更新\n\n${releaseNotes}`,
type: 'info',
buttons: ['稍后提示', '立即更新'],
})
.then(({ response }) => {
console.log(response);
if (response === 1) {
this.update();
}
});
});
// 自动下载安装包
if (!this.isUpdate) {
autoUpdater.downloadUpdate();
console.log('download');
}
});
autoUpdater.on('update-not-available', (info) => {
if (sendUpdateMsg) return;
sendUpdateMsg = true;
});
autoUpdater.on('error', () => {
this.isUpdate = false;
});
// if true -> update else return false
const compareVersion2Update = (current: string, latest: string) => {
try {
if (latest.includes('beta')) {
return false;
}
return lt(current, latest);
} catch (e) {
return false;
}
};
checkUpdate(): void {
this.checkForMacAndWindows();
}
update() {
let sendUpdateMsg = false;
this.checkUpdate();
autoUpdater.on('update-downloaded', () => {
if (sendUpdateMsg) return;
sendUpdateMsg = true;
this.isUpdate = false;
autoUpdater.quitAndInstall(true, true);
// App.quit();
});
}
}
export default new VersionHandler();
export default checkVersion;

View File

@@ -21,7 +21,8 @@ import {
import '../common/utils/localPlugin';
import registerySystemPlugin from './common/registerySystemPlugin';
import checkVersion from './common/versionHandler';
import registerSystemPlugin from './common/registerSystemPlugin';
class App {
public windowCreator: { init: () => void; getWindow: () => BrowserWindow };
@@ -36,7 +37,7 @@ class App {
if (!gotTheLock) {
app.quit();
} else {
this.systemPlugins = registerySystemPlugin();
this.systemPlugins = registerSystemPlugin();
this.beforeReady();
this.onReady();
this.onRunning();
@@ -62,6 +63,7 @@ class App {
}
onReady() {
const readyFunction = async () => {
checkVersion();
await localConfig.init();
const config = await localConfig.getConfig();
if (!config.perf.common.guide) {

View File

@@ -14,7 +14,7 @@
:key="index"
>
<a-avatar style="width: 28px; height: 28px;" :src="item.icon" />
<div class="name ellpise">{{item.pluginName || item._name || item.name}}</div>
<div class="name ellpise">{{item.cmd || item.pluginName || item._name || item.name}}</div>
</a-col>
</a-row>
</div>

View File

@@ -70,6 +70,9 @@ const createPluginManager = (): any => {
const openPlugin = async (plugin, option) => {
if (plugin.pluginType === 'ui' || plugin.pluginType === 'system') {
if (state.currentPlugin && state.currentPlugin.name === plugin.name) {
ipcRenderer.sendSync('msg-trigger', {
type: 'showMainWindow',
});
return;
}
await loadPlugin(plugin);