chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 12:24:31 +08:00
commit f732f575ee
272 changed files with 79618 additions and 0 deletions
+8
View File
@@ -0,0 +1,8 @@
export const WINDOW_WIDTH = 800;
export const WINDOW_HEIGHT = 60;
export const WINDOW_PLUGIN_HEIGHT = 600;
export const GUIDE_WIDTH = 800;
export const GUIDE_HEIGHT = 600;
export const WINDOW_MIN_HEIGHT = 60;
+36
View File
@@ -0,0 +1,36 @@
export default {
version: 7,
perf: {
custom: {
theme: 'SPRING',
primaryColor: '#ff4ea4',
errorColor: '#ed6d46',
warningColor: '#e5a84b',
successColor: '#c0d695',
infoColor: '#aa8eeB',
logo: `file://${__static}/logo.png`,
placeholder: '你好,Rubick!请输入插件关键词',
username: 'Rubick',
},
shortCut: {
showAndHidden: 'Option+R',
separate: 'Ctrl+D',
quit: 'Shift+Escape',
capture: 'Ctrl+Shift+A',
},
common: {
start: true,
space: true,
hideOnBlur: true,
autoPast: false,
darkMode: false,
guide: false,
history: true,
lang: 'zh-CN',
},
local: {
search: true,
},
},
global: [],
};
+87
View File
@@ -0,0 +1,87 @@
import { app } from 'electron';
import path from 'path';
const appPath = app.getPath('userData');
const PLUGIN_INSTALL_DIR = path.join(appPath, './rubick-plugins-new');
const DECODE_KEY = {
Backspace: 'Backspace',
Tab: 'Tab',
Enter: 'Enter',
MediaPlayPause: 'MediaPlayPause',
Escape: 'Escape',
Space: 'Space',
PageUp: 'PageUp',
PageDown: 'PageDown',
End: 'End',
Home: 'Home',
ArrowLeft: 'Left',
ArrowUp: 'Up',
ArrowRight: 'Right',
ArrowDown: 'Down',
PrintScreen: 'PrintScreen',
Insert: 'Insert',
Delete: 'Delete',
Digit0: '0',
Digit1: '1',
Digit2: '2',
Digit3: '3',
Digit4: '4',
Digit5: '5',
Digit6: '6',
Digit7: '7',
Digit8: '8',
Digit9: '9',
KeyA: 'A',
KeyB: 'B',
KeyC: 'C',
KeyD: 'D',
KeyE: 'E',
KeyF: 'F',
KeyG: 'G',
KeyH: 'H',
KeyI: 'I',
KeyJ: 'J',
KeyK: 'K',
KeyL: 'L',
KeyM: 'M',
KeyN: 'N',
KeyO: 'O',
KeyP: 'P',
KeyQ: 'Q',
KeyR: 'R',
KeyS: 'S',
KeyT: 'T',
KeyU: 'U',
KeyV: 'V',
KeyW: 'W',
KeyX: 'X',
KeyY: 'Y',
KeyZ: 'Z',
F1: 'F1',
F2: 'F2',
F3: 'F3',
F4: 'F4',
F5: 'F5',
F6: 'F6',
F7: 'F7',
F8: 'F8',
F9: 'F9',
F10: 'F10',
F11: 'F11',
F12: 'F12',
Semicolon: ';',
Equal: '=',
Comma: ',',
Minus: '-',
Period: '.',
Slash: '/',
Backquote: '`',
BracketLeft: '[',
Backslash: '\\',
BracketRight: ']',
Quote: "'",
};
export { PLUGIN_INSTALL_DIR, DECODE_KEY };
+9
View File
@@ -0,0 +1,9 @@
import { app } from '@electron/remote';
import path from 'path';
const appPath = app.getPath('userData');
const PLUGIN_INSTALL_DIR = path.join(appPath, './rubick-plugins-new');
const PLUGIN_HISTORY = 'rubick-plugin-history';
export { PLUGIN_INSTALL_DIR, PLUGIN_HISTORY };
+17
View File
@@ -0,0 +1,17 @@
export default {
linux(): boolean {
return process.platform === 'linux';
},
macOS(): boolean {
return process.platform === 'darwin';
},
windows(): boolean {
return process.platform === 'win32';
},
production(): boolean {
return process.env.NODE_ENV !== 'development';
},
dev(): boolean {
return process.env.NODE_ENV === 'development';
},
};
+46
View File
@@ -0,0 +1,46 @@
import { ipcRenderer } from 'electron';
const useDrag = () => {
let animationId: number;
let mouseX: number;
let mouseY: number;
let clientWidth = 0;
let clientHeight = 0;
let draggable = true;
const onMouseDown = (e) => {
// 右击不移动
if (e.button === 2) return;
draggable = true;
mouseX = e.clientX;
mouseY = e.clientY;
if (Math.abs(document.body.clientWidth - clientWidth) > 5) {
clientWidth = document.body.clientWidth;
}
if (Math.abs(document.body.clientHeight - clientHeight) > 5) {
clientHeight = document.body.clientHeight;
}
document.addEventListener('mouseup', onMouseUp);
animationId = requestAnimationFrame(moveWindow);
};
const onMouseUp = () => {
draggable = false;
document.removeEventListener('mouseup', onMouseUp);
cancelAnimationFrame(animationId);
};
const moveWindow = () => {
ipcRenderer.send('msg-trigger', {
type: 'windowMoving',
data: { mouseX, mouseY, width: clientWidth, height: clientHeight },
});
if (draggable) animationId = requestAnimationFrame(moveWindow);
};
return {
onMouseDown,
};
};
export default useDrag;
+55
View File
@@ -0,0 +1,55 @@
import commonConst from './commonConst';
import { clipboard } from 'electron';
import plist from 'plist';
import fs from 'fs';
import path from 'path';
import ofs from 'original-fs';
export default function getCopyFiles(): Array<any> | null {
let fileInfo;
if (commonConst.macOS()) {
if (!clipboard.has('NSFilenamesPboardType')) return null;
const result = clipboard.read('NSFilenamesPboardType');
if (!result) return null;
try {
fileInfo = plist.parse(result);
} catch (e) {
return null;
}
} else if (process.platform === 'win32') {
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;
const result = clipboard.read('text/uri-list').match(/^file:\/\/\/.*/gm);
if (!result || !result.length) return null;
fileInfo = result.map((e) =>
decodeURIComponent(e).replace(/^file:\/\//, '')
);
}
if (!Array.isArray(fileInfo)) return null;
const target: any = fileInfo
.map((p) => {
if (!fs.existsSync(p)) return false;
let info;
try {
info = ofs.lstatSync(p);
} catch (e) {
return false;
}
return {
isFile: info.isFile(),
isDirectory: info.isDirectory(),
name: path.basename(p) || p,
path: p,
};
})
.filter(Boolean);
return target.length ? target : null;
}
+14
View File
@@ -0,0 +1,14 @@
import path from 'path';
import fs from 'fs';
export default (): string => {
let localDataFile: any = process.env.HOME;
if (!localDataFile) {
localDataFile = process.env.LOCALAPPDATA;
}
const rubickPath = path.join(localDataFile, 'rubick');
if (!fs.existsSync(rubickPath)) {
fs.mkdirSync(rubickPath);
}
return rubickPath;
};
+14
View File
@@ -0,0 +1,14 @@
const WINDOW_MAX_HEIGHT = 620;
const WINDOW_MIN_HEIGHT = 60;
const PRE_ITEM_HEIGHT = 70;
const HISTORY_HEIGHT = 70;
export default (searchList: Array<any>, historyList): number => {
const defaultHeight = historyList.length ? HISTORY_HEIGHT : 0;
if (!searchList) return WINDOW_MAX_HEIGHT + defaultHeight;
if (!searchList.length) return WINDOW_MIN_HEIGHT + defaultHeight;
return searchList.length * PRE_ITEM_HEIGHT + WINDOW_MIN_HEIGHT >
WINDOW_MAX_HEIGHT
? WINDOW_MAX_HEIGHT
: searchList.length * PRE_ITEM_HEIGHT + WINDOW_MIN_HEIGHT;
};
+45
View File
@@ -0,0 +1,45 @@
import path from 'path';
import fs from 'fs';
import getLocalDataFile from './getLocalDataFile';
import defaultConfigForAnyPlatform from '../constans/defaultConfig';
const configPath = path.join(getLocalDataFile(), './rubick-config.json');
global.OP_CONFIG = {
config: null,
getDefaultConfig() {
return defaultConfigForAnyPlatform;
},
get() {
try {
if (!global.OP_CONFIG.config) {
global.OP_CONFIG.config = JSON.parse(
fs.readFileSync(configPath, 'utf8') ||
JSON.stringify(defaultConfigForAnyPlatform)
);
}
// 重置
if (
!global.OP_CONFIG.config.version ||
global.OP_CONFIG.config.version < defaultConfigForAnyPlatform.version
) {
global.OP_CONFIG.config = defaultConfigForAnyPlatform;
fs.writeFileSync(
configPath,
JSON.stringify(defaultConfigForAnyPlatform)
);
}
return global.OP_CONFIG.config;
} catch (e) {
global.OP_CONFIG.config = defaultConfigForAnyPlatform;
return global.OP_CONFIG.config;
}
},
set(value) {
global.OP_CONFIG.config = {
...global.OP_CONFIG.config,
...value,
};
fs.writeFileSync(configPath, JSON.stringify(global.OP_CONFIG.config));
},
};
+120
View File
@@ -0,0 +1,120 @@
import path from 'path';
import fs from 'fs';
import { PluginHandler } from '@/core';
import { PLUGIN_INSTALL_DIR as baseDir } from '@/common/constans/main';
import API from '@/main/common/api';
const configPath = path.join(baseDir, './rubick-local-plugin.json');
let registry;
let pluginInstance;
(async () => {
try {
const res = await API.dbGet({
data: {
id: 'rubick-localhost-config',
},
});
registry = res && res.data.register;
pluginInstance = new PluginHandler({
baseDir,
registry,
});
} catch (e) {
pluginInstance = new PluginHandler({
baseDir,
registry,
});
}
})();
global.LOCAL_PLUGINS = {
PLUGINS: [],
async downloadPlugin(plugin) {
await pluginInstance.install([plugin.name], { isDev: plugin.isDev });
if (plugin.isDev) {
// 获取 dev 插件信息
const pluginPath = path.resolve(baseDir, 'node_modules', plugin.name);
const pluginInfo = JSON.parse(
fs.readFileSync(path.join(pluginPath, './package.json'), 'utf8')
);
plugin = {
...plugin,
...pluginInfo,
};
}
global.LOCAL_PLUGINS.addPlugin(plugin);
return global.LOCAL_PLUGINS.PLUGINS;
},
refreshPlugin(plugin) {
// 获取 dev 插件信息
const pluginPath = path.resolve(baseDir, 'node_modules', plugin.name);
const pluginInfo = JSON.parse(
fs.readFileSync(path.join(pluginPath, './package.json'), 'utf8')
);
plugin = {
...plugin,
...pluginInfo,
};
// 刷新
let currentPlugins = global.LOCAL_PLUGINS.getLocalPlugins();
currentPlugins = currentPlugins.map((p) => {
if (p.name === plugin.name) {
return plugin;
}
return p;
});
// 存入
global.LOCAL_PLUGINS.PLUGINS = currentPlugins;
fs.writeFileSync(configPath, JSON.stringify(currentPlugins));
return global.LOCAL_PLUGINS.PLUGINS;
},
getLocalPlugins() {
try {
if (!global.LOCAL_PLUGINS.PLUGINS.length) {
global.LOCAL_PLUGINS.PLUGINS = JSON.parse(
fs.readFileSync(configPath, 'utf-8')
);
}
return global.LOCAL_PLUGINS.PLUGINS;
} catch (e) {
global.LOCAL_PLUGINS.PLUGINS = [];
return global.LOCAL_PLUGINS.PLUGINS;
}
},
addPlugin(plugin) {
let has = false;
const currentPlugins = global.LOCAL_PLUGINS.getLocalPlugins();
currentPlugins.some((p) => {
has = p.name === plugin.name;
return has;
});
if (!has) {
currentPlugins.unshift(plugin);
global.LOCAL_PLUGINS.PLUGINS = currentPlugins;
fs.writeFileSync(configPath, JSON.stringify(currentPlugins));
}
},
updatePlugin(plugin) {
global.LOCAL_PLUGINS.PLUGINS = global.LOCAL_PLUGINS.PLUGINS.map(
(origin) => {
if (origin.name === plugin.name) {
return plugin;
}
return origin;
}
);
fs.writeFileSync(configPath, JSON.stringify(global.LOCAL_PLUGINS.PLUGINS));
},
async deletePlugin(plugin) {
await pluginInstance.uninstall([plugin.name], { isDev: plugin.isDev });
global.LOCAL_PLUGINS.PLUGINS = global.LOCAL_PLUGINS.PLUGINS.filter(
(p) => plugin.name !== p.name
);
fs.writeFileSync(configPath, JSON.stringify(global.LOCAL_PLUGINS.PLUGINS));
return global.LOCAL_PLUGINS.PLUGINS;
},
};
+40
View File
@@ -0,0 +1,40 @@
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
export default function throttle(func, wait, options?: any): () => void {
let context, args, result;
let timeout = null;
let previous = 0;
if (!options) options = {};
const later = function () {
previous = options.leading === false ? 0 : Date.now();
timeout = null;
result = func.apply(context, args);
if (!timeout) context = args = null;
};
return () => {
const now = Date.now();
if (!previous && options.leading === false) previous = now;
// 计算剩余时间
const remaining = wait - (now - previous);
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
context = this;
// eslint-disable-next-line prefer-rest-params
args = arguments;
if (remaining <= 0 || remaining > wait) {
if (timeout) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
clearTimeout(timeout);
timeout = null;
}
previous = now;
result = func.apply(context, args);
if (!timeout) context = args = null;
} else if (!timeout && options.trailing !== false) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
timeout = setTimeout(later, remaining);
}
return result;
};
}