mirror of
https://github.com/rubickCenter/rubick
synced 2025-06-08 03:24:12 +08:00
parent
a7a85a7c62
commit
bde5377282
@ -22,11 +22,11 @@
|
|||||||
<template #renderItem="{ item }">
|
<template #renderItem="{ item }">
|
||||||
<a-list-item>
|
<a-list-item>
|
||||||
<template #actions>
|
<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)">
|
@click="() => downloadPlugin(item.plugin)">
|
||||||
<CloudDownloadOutlined style="font-size: 18px;"/>
|
<CloudDownloadOutlined style="font-size: 18px;"/>
|
||||||
</a>
|
</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;"/>
|
<LoadingOutlined style="font-size: 18px;"/>
|
||||||
</a>
|
</a>
|
||||||
<a key="list-loadmore-edit" @click="() => showKeys(item)">
|
<a key="list-loadmore-edit" @click="() => showKeys(item)">
|
||||||
@ -36,11 +36,11 @@
|
|||||||
<a-list-item-meta :description="`${item.keys.length} 份文档`">
|
<a-list-item-meta :description="`${item.keys.length} 份文档`">
|
||||||
<template #title>
|
<template #title>
|
||||||
<div>
|
<div>
|
||||||
<span>{{ item.plugin.pluginName }}</span>
|
<span>{{ item.plugin?.pluginName }}</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #avatar>
|
<template #avatar>
|
||||||
<a-avatar shape="square" :src="item.plugin.logo"/>
|
<a-avatar shape="square" :src="item.plugin?.logo"/>
|
||||||
</template>
|
</template>
|
||||||
</a-list-item-meta>
|
</a-list-item-meta>
|
||||||
</a-list-item>
|
</a-list-item>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "rubick",
|
"name": "rubick",
|
||||||
"version": "4.0.4",
|
"version": "4.0.5",
|
||||||
"author": "muwoo <2424880409@qq.com>",
|
"author": "muwoo <2424880409@qq.com>",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@ -69,7 +69,7 @@
|
|||||||
"less-loader": "^5.0.0",
|
"less-loader": "^5.0.0",
|
||||||
"prettier": "^2.8.4",
|
"prettier": "^2.8.4",
|
||||||
"typescript": "~4.1.5",
|
"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"
|
"worker-plugin": "^5.0.1"
|
||||||
},
|
},
|
||||||
"resolutions": {
|
"resolutions": {
|
||||||
|
@ -85,6 +85,10 @@ window.rubick = {
|
|||||||
remove: (doc) => ipcSendSync('dbRemove', { doc }),
|
remove: (doc) => ipcSendSync('dbRemove', { doc }),
|
||||||
bulkDocs: (docs) => ipcSendSync('dbBulkDocs', { docs }),
|
bulkDocs: (docs) => ipcSendSync('dbBulkDocs', { docs }),
|
||||||
allDocs: (key) => ipcSendSync('dbAllDocs', { key }),
|
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: {
|
dbStorage: {
|
||||||
setItem: (key, value) => {
|
setItem: (key, value) => {
|
||||||
|
@ -204,4 +204,38 @@ export default class DB {
|
|||||||
this.pouchDB = syncDb.pouchDB;
|
this.pouchDB = syncDb.pouchDB;
|
||||||
await webdavClient.createReadStream(this.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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,8 +11,8 @@ type WebDavOptions = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
type DBInstance = {
|
type DBInstance = {
|
||||||
loadIt: (stream: unknown) => void;
|
loadIt: (stream: unknown, options?: any) => void;
|
||||||
dump: (stream: unknown) => void;
|
dump: (stream: unknown, options?: any) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default class WebDav {
|
export default class WebDav {
|
||||||
@ -54,7 +54,12 @@ export default class WebDav {
|
|||||||
}).show();
|
}).show();
|
||||||
}
|
}
|
||||||
const ws = new MemoryStream();
|
const ws = new MemoryStream();
|
||||||
dbInstance.dump(ws);
|
dbInstance.dump(ws, {
|
||||||
|
filter: (doc) => {
|
||||||
|
// attachment 文档导出有问题,
|
||||||
|
return !doc._attachments;
|
||||||
|
},
|
||||||
|
});
|
||||||
ws.pipe(
|
ws.pipe(
|
||||||
this.client.createWriteStream(this.cloudPath, {}, () => {
|
this.client.createWriteStream(this.cloudPath, {}, () => {
|
||||||
new Notification({
|
new Notification({
|
||||||
|
@ -157,13 +157,17 @@ 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 args: string[] = [cmd]
|
let args: string[] = [cmd].concat(
|
||||||
.concat(
|
cmd !== 'uninstall' && cmd !== 'link'
|
||||||
cmd !== 'uninstall' ? modules.map((m) => `${m}@latest`) : modules
|
? modules.map((m) => `${m}@latest`)
|
||||||
)
|
: modules
|
||||||
.concat('--color=always')
|
);
|
||||||
.concat('--save')
|
if (cmd !== 'link') {
|
||||||
.concat(`--registry=${this.registry}`);
|
args = args
|
||||||
|
.concat('--color=always')
|
||||||
|
.concat('--save')
|
||||||
|
.concat(`--registry=${this.registry}`);
|
||||||
|
}
|
||||||
|
|
||||||
const npm = spawn('npm', args, {
|
const npm = spawn('npm', args, {
|
||||||
cwd: this.baseDir,
|
cwd: this.baseDir,
|
||||||
|
@ -73,23 +73,31 @@ export default () => {
|
|||||||
|
|
||||||
const init = (plugin, window: BrowserWindow) => {
|
const init = (plugin, window: BrowserWindow) => {
|
||||||
if (view === null || view === undefined) {
|
if (view === null || view === undefined) {
|
||||||
if (viewInstance.getView(plugin.name) && !commonConst.dev()) {
|
createView(plugin, window);
|
||||||
view = viewInstance.getView(plugin.name).view;
|
// if (viewInstance.getView(plugin.name) && !commonConst.dev()) {
|
||||||
window.setBrowserView(view);
|
// view = viewInstance.getView(plugin.name).view;
|
||||||
view.inited = true;
|
// window.setBrowserView(view);
|
||||||
viewReadyFn(window, plugin);
|
// view.inited = true;
|
||||||
} else {
|
// viewReadyFn(window, plugin);
|
||||||
createView(plugin, window);
|
// } else {
|
||||||
viewInstance.addView(plugin.name, view);
|
// createView(plugin, window);
|
||||||
}
|
// viewInstance.addView(plugin.name, view);
|
||||||
|
// }
|
||||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||||
require('@electron/remote/main').enable(view.webContents);
|
require('@electron/remote/main').enable(view.webContents);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const createView = (plugin, window: BrowserWindow) => {
|
const createView = (plugin, window: BrowserWindow) => {
|
||||||
const { tplPath, indexPath, development, name, main, pluginSetting, ext } =
|
const {
|
||||||
plugin;
|
tplPath,
|
||||||
|
indexPath,
|
||||||
|
development,
|
||||||
|
name,
|
||||||
|
main = 'index.html',
|
||||||
|
pluginSetting,
|
||||||
|
ext,
|
||||||
|
} = plugin;
|
||||||
let pluginIndexPath = tplPath || indexPath;
|
let pluginIndexPath = tplPath || indexPath;
|
||||||
let preloadPath;
|
let preloadPath;
|
||||||
let darkMode;
|
let darkMode;
|
||||||
@ -160,7 +168,7 @@ export default () => {
|
|||||||
window.removeBrowserView(view);
|
window.removeBrowserView(view);
|
||||||
window.setSize(800, 60);
|
window.setSize(800, 60);
|
||||||
executeHooks('PluginOut', null);
|
executeHooks('PluginOut', null);
|
||||||
window.webContents.executeJavaScript(`window.initRubick()`);
|
window.webContents?.executeJavaScript(`window.initRubick()`);
|
||||||
view = undefined;
|
view = undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -174,7 +182,7 @@ export default () => {
|
|||||||
} catch(e) {}
|
} catch(e) {}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
view.webContents.executeJavaScript(evalJs);
|
view.webContents?.executeJavaScript(evalJs);
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -14,13 +14,18 @@ import { screenCapture } from '@/core';
|
|||||||
import plist from 'plist';
|
import plist from 'plist';
|
||||||
import ks from 'node-key-sender';
|
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 getCopyFiles from '@/common/utils/getCopyFiles';
|
||||||
|
import common from '@/common/utils/commonConst';
|
||||||
|
|
||||||
import mainInstance from '../index';
|
import mainInstance from '../index';
|
||||||
import { runner, detach } from '../browsers';
|
import { runner, detach } from '../browsers';
|
||||||
import DBInstance from './db';
|
import DBInstance from './db';
|
||||||
import getWinPosition from './getWinPosition';
|
import getWinPosition from './getWinPosition';
|
||||||
|
import path from 'path';
|
||||||
|
|
||||||
const runnerInstance = runner();
|
const runnerInstance = runner();
|
||||||
const detachInstance = detach();
|
const detachInstance = detach();
|
||||||
@ -77,8 +82,29 @@ class API extends DBInstance {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public openPlugin({ data: plugin }, window) {
|
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);
|
window.setSize(window.getSize()[0], 60);
|
||||||
this.removePlugin(null, window);
|
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);
|
runnerInstance.init(plugin, window);
|
||||||
this.currentPlugin = plugin;
|
this.currentPlugin = plugin;
|
||||||
window.webContents.executeJavaScript(
|
window.webContents.executeJavaScript(
|
||||||
|
@ -54,4 +54,20 @@ export default class DBInstance {
|
|||||||
public dbImport({ data }) {
|
public dbImport({ data }) {
|
||||||
return dbInstance.importDb(data.target);
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
27
src/main/common/getLatestVersion.ts
Normal file
27
src/main/common/getLatestVersion.ts
Normal 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;
|
||||||
|
};
|
@ -1,96 +1,45 @@
|
|||||||
import { dialog } from 'electron';
|
import { dialog, shell } from 'electron';
|
||||||
import { autoUpdater } from 'electron-updater';
|
|
||||||
import pkg from '../../../package.json';
|
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 {
|
const checkVersion = async () => {
|
||||||
private lastestVersion: string;
|
const res: string = await getLatestVersion();
|
||||||
private currentVersion: string;
|
if (res !== '') {
|
||||||
private releaseNotes: string;
|
const latest = res;
|
||||||
private isUpdate: boolean;
|
const result = compareVersion2Update(version, latest);
|
||||||
|
if (result) {
|
||||||
constructor() {
|
dialog
|
||||||
this.lastestVersion = '';
|
.showMessageBox({
|
||||||
this.currentVersion = pkg.version;
|
type: 'info',
|
||||||
this.releaseNotes = '';
|
title: 'Rubick 更新提示',
|
||||||
this.isUpdate = false;
|
buttons: ['Yes', 'No'],
|
||||||
autoUpdater.autoDownload = false;
|
message: `发现新版本 v${latest},是否更新?`,
|
||||||
autoUpdater.autoInstallOnAppQuit = false;
|
})
|
||||||
|
.then((res) => {
|
||||||
|
if (res.response === 0) {
|
||||||
|
// if selected yes
|
||||||
|
shell.openExternal(downloadUrl);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
checkForMacAndWindows() {
|
// if true -> update else return false
|
||||||
let sendUpdateMsg = false;
|
const compareVersion2Update = (current: string, latest: string) => {
|
||||||
autoUpdater.removeAllListeners();
|
try {
|
||||||
// update-available 会触发多次,限制只通知一次
|
if (latest.includes('beta')) {
|
||||||
autoUpdater.checkForUpdates();
|
return false;
|
||||||
|
}
|
||||||
autoUpdater.on('download-progress', ({ percent }) => {
|
return lt(current, latest);
|
||||||
console.log('下载进度', percent);
|
} catch (e) {
|
||||||
// if (percent < 50) {
|
return false;
|
||||||
// }
|
|
||||||
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;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
checkUpdate(): void {
|
export default checkVersion;
|
||||||
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();
|
|
||||||
|
@ -22,6 +22,7 @@ import {
|
|||||||
import '../common/utils/localPlugin';
|
import '../common/utils/localPlugin';
|
||||||
|
|
||||||
import registerySystemPlugin from './common/registerySystemPlugin';
|
import registerySystemPlugin from './common/registerySystemPlugin';
|
||||||
|
import checkVersion from './common/versionHandler';
|
||||||
|
|
||||||
class App {
|
class App {
|
||||||
public windowCreator: { init: () => void; getWindow: () => BrowserWindow };
|
public windowCreator: { init: () => void; getWindow: () => BrowserWindow };
|
||||||
@ -62,6 +63,7 @@ class App {
|
|||||||
}
|
}
|
||||||
onReady() {
|
onReady() {
|
||||||
const readyFunction = async () => {
|
const readyFunction = async () => {
|
||||||
|
checkVersion();
|
||||||
await localConfig.init();
|
await localConfig.init();
|
||||||
const config = await localConfig.getConfig();
|
const config = await localConfig.getConfig();
|
||||||
if (!config.perf.common.guide) {
|
if (!config.perf.common.guide) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user