diff --git a/package.json b/package.json
index 0acf7a2..da443a3 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "rubick",
- "version": "3.2.1",
+ "version": "3.2.2",
"author": "muwoo <2424880409@qq.com>",
"private": true,
"scripts": {
diff --git a/public/installer.nsh b/public/installer.nsh
new file mode 100644
index 0000000..2a19881
--- /dev/null
+++ b/public/installer.nsh
@@ -0,0 +1,13 @@
+!macro customInstall
+ SetRegView 64
+ WriteRegStr HKCR "*\shell\rubick" "" "open w&ith rubick search"
+ WriteRegStr HKCR "*\shell\rubick" "Icon" "$INSTDIR\rubick.exe"
+ WriteRegStr HKCR "*\shell\rubick\command" "" '"$INSTDIR\rubick.exe" "search" "%1"'
+ SetRegView 32
+ WriteRegStr HKCR "*\shell\rubick" "" "open w&ith rubick search"
+ WriteRegStr HKCR "*\shell\rubick" "Icon" "$INSTDIR\rubick.exe"
+ WriteRegStr HKCR "*\shell\rubick\command" "" '"$INSTDIR\rubick.exe" "search" "%1"'
+!macroend
+!macro customUninstall
+ DeleteRegKey HKCR "*\shell\rubick"
+!macroend
\ No newline at end of file
diff --git a/public/rubick.workflow/Contents/Info.plist b/public/rubick.workflow/Contents/Info.plist
new file mode 100644
index 0000000..5b64c83
--- /dev/null
+++ b/public/rubick.workflow/Contents/Info.plist
@@ -0,0 +1,31 @@
+
+
+
+
+ NSServices
+
+
+ NSBackgroundColorName
+ background
+ NSIconName
+ NSTouchBarSend
+ NSMenuItem
+
+ default
+ rubick 打开
+
+ NSMessage
+ runWorkflowAsService
+ NSRequiredContext
+
+ NSApplicationIdentifier
+ com.apple.finder
+
+ NSSendFileTypes
+
+ public.item
+
+
+
+
+
diff --git a/public/rubick.workflow/Contents/QuickLook/Thumbnail.png b/public/rubick.workflow/Contents/QuickLook/Thumbnail.png
new file mode 100644
index 0000000..80e2b14
Binary files /dev/null and b/public/rubick.workflow/Contents/QuickLook/Thumbnail.png differ
diff --git a/public/rubick.workflow/Contents/document.wflow b/public/rubick.workflow/Contents/document.wflow
new file mode 100644
index 0000000..5478453
--- /dev/null
+++ b/public/rubick.workflow/Contents/document.wflow
@@ -0,0 +1,228 @@
+
+
+
+
+ AMApplicationBuild
+ 512
+ AMApplicationVersion
+ 2.10
+ AMDocumentVersion
+ 2
+ actions
+
+
+ action
+
+ AMAccepts
+
+ Container
+ List
+ Optional
+
+ Types
+
+ com.apple.cocoa.string
+
+
+ AMActionVersion
+ 2.0.3
+ AMApplication
+
+ 自动操作
+
+ AMParameterProperties
+
+ COMMAND_STRING
+
+ CheckedForUserDefaultShell
+
+ inputMethod
+
+ shell
+
+ source
+
+
+ AMProvides
+
+ Container
+ List
+ Types
+
+ com.apple.cocoa.string
+
+
+ ActionBundlePath
+ /System/Library/Automator/Run Shell Script.action
+ ActionName
+ 运行Shell脚本
+ ActionParameters
+
+ COMMAND_STRING
+ /Applications/rubick.app/Contents/MacOS/rubick search "$@" > /dev/null 2>&1 &
+ CheckedForUserDefaultShell
+
+ inputMethod
+ 0
+ shell
+ /bin/bash
+ source
+
+
+ BundleIdentifier
+ com.apple.RunShellScript
+ CFBundleVersion
+ 2.0.3
+ CanShowSelectedItemsWhenRun
+
+ CanShowWhenRun
+
+ Category
+
+ AMCategoryUtilities
+
+ Class Name
+ RunShellScriptAction
+ InputUUID
+ 7E11290E-3E3F-4D65-988B-3E2A8B597EEF
+ Keywords
+
+ Shell
+ 脚本
+ 命令
+ 运行
+ Unix
+
+ OutputUUID
+ 475C56B3-F23A-4D39-BB41-4B00F76B096B
+ UUID
+ BBBABDAB-D65B-41BF-B1EB-03ACA5AF4714
+ UnlocalizedApplications
+
+ Automator
+
+ arguments
+
+ 0
+
+ default value
+ 0
+ name
+ inputMethod
+ required
+ 0
+ type
+ 0
+ uuid
+ 0
+
+ 1
+
+ default value
+
+ name
+ CheckedForUserDefaultShell
+ required
+ 0
+ type
+ 0
+ uuid
+ 1
+
+ 2
+
+ default value
+
+ name
+ source
+ required
+ 0
+ type
+ 0
+ uuid
+ 2
+
+ 3
+
+ default value
+
+ name
+ COMMAND_STRING
+ required
+ 0
+ type
+ 0
+ uuid
+ 3
+
+ 4
+
+ default value
+ /bin/sh
+ name
+ shell
+ required
+ 0
+ type
+ 0
+ uuid
+ 4
+
+
+ conversionLabel
+ 0
+ isViewVisible
+ 1
+ location
+ 309.000000:305.000000
+ nibPath
+ /System/Library/Automator/Run Shell Script.action/Contents/Resources/Base.lproj/main.nib
+
+ isViewVisible
+ 1
+
+
+ connectors
+
+ workflowMetaData
+
+ applicationBundleID
+ com.apple.finder
+ applicationBundleIDsByPath
+
+ /System/Library/CoreServices/Finder.app
+ com.apple.finder
+
+ applicationPath
+ /System/Library/CoreServices/Finder.app
+ applicationPaths
+
+ /System/Library/CoreServices/Finder.app
+
+ inputTypeIdentifier
+ com.apple.Automator.fileSystemObject
+ outputTypeIdentifier
+ com.apple.Automator.nothing
+ presentationMode
+ 15
+ processesInput
+
+ serviceApplicationBundleID
+ com.apple.finder
+ serviceApplicationPath
+ /System/Library/CoreServices/Finder.app
+ serviceInputTypeIdentifier
+ com.apple.Automator.fileSystemObject
+ serviceOutputTypeIdentifier
+ com.apple.Automator.nothing
+ serviceProcessesInput
+
+ systemImageName
+ NSTouchBarSend
+ useAutomaticInputType
+
+ workflowTypeIdentifier
+ com.apple.Automator.servicesMenu
+
+
+
diff --git a/src/main/common/getSearchFiles.ts b/src/main/common/getSearchFiles.ts
new file mode 100644
index 0000000..221cf22
--- /dev/null
+++ b/src/main/common/getSearchFiles.ts
@@ -0,0 +1,84 @@
+import path from 'path';
+import fs from 'fs-extra';
+import os from 'os';
+
+const getSearchFiles = (argv = process.argv, cwd = process.cwd()) => {
+ const files = argv.slice(2); // 过滤['rubick.exe', 'search']这两个参数,直接获取需要上传的图片路径
+ let result: any = [];
+ if (files.length > 0) {
+ // 如果图片列表不为空
+ result = files
+ .map((item) => {
+ if (path.isAbsolute(item)) {
+ // 如果是绝对路径
+ return {
+ path: item,
+ };
+ } else {
+ const tempPath = path.join(cwd, item); // 如果是相对路径,就拼接
+ if (fs.existsSync(tempPath)) {
+ // 判断文件是否存在
+ return {
+ path: tempPath,
+ };
+ } else {
+ return null;
+ }
+ }
+ })
+ .filter((item) => item !== null); // 排除为null的路径
+ }
+ return result; // 返回结果
+};
+
+const putFileToRubick = (webContents, files) => {
+ webContents.executeJavaScript(`window.searchFocus(${JSON.stringify(files)})`);
+};
+
+const copyFileOutsideOfElectronAsar = function (
+ sourceInAsarArchive,
+ destOutsideAsarArchive
+) {
+ if (fs.existsSync(sourceInAsarArchive)) {
+ // file will be copied
+ if (fs.statSync(sourceInAsarArchive).isFile()) {
+ const file = destOutsideAsarArchive;
+ const dir = path.dirname(file);
+ if (!fs.existsSync(dir)) {
+ fs.mkdirSync(dir, { recursive: true });
+ }
+
+ fs.writeFileSync(file, fs.readFileSync(sourceInAsarArchive));
+ }
+
+ // dir is browsed
+ else if (fs.statSync(sourceInAsarArchive).isDirectory()) {
+ fs.readdirSync(sourceInAsarArchive).forEach(function (fileOrFolderName) {
+ copyFileOutsideOfElectronAsar(
+ sourceInAsarArchive + '/' + fileOrFolderName,
+ destOutsideAsarArchive + '/' + fileOrFolderName
+ );
+ });
+ }
+ }
+};
+
+const macBeforeOpen = () => {
+ const dest = `${os.homedir}/Library/Services/rubick.workflow`;
+ if (fs.existsSync(dest)) {
+ // 判断是否存在
+ return true;
+ } else {
+ // 如果不存在就复制过去
+ try {
+ copyFileOutsideOfElectronAsar(
+ path.join(__static, 'rubick.workflow'),
+ dest
+ );
+ } catch (e) {
+ console.log(e);
+ }
+ }
+};
+
+export { getSearchFiles, putFileToRubick, macBeforeOpen };
diff --git a/src/main/index.ts b/src/main/index.ts
index 0bde5a3..4e300c0 100644
--- a/src/main/index.ts
+++ b/src/main/index.ts
@@ -13,6 +13,11 @@ import API from './common/api';
import createTray from './common/tray';
import registerHotKey from './common/registerHotKey';
import localConfig from './common/initLocalConfig';
+import {
+ getSearchFiles,
+ putFileToRubick,
+ macBeforeOpen,
+} from './common/getSearchFiles';
import '../common/utils/localPlugin';
@@ -41,6 +46,7 @@ class App {
beforeReady() {
// 系统托盘
if (commonConst.macOS()) {
+ macBeforeOpen();
if (commonConst.production() && !app.isInApplicationsFolder()) {
app.moveToApplicationsFolder();
} else {
@@ -83,14 +89,20 @@ class App {
}
onRunning() {
- app.on('second-instance', () => {
- // 当运行第二个实例时,将会聚焦到myWindow这个窗口
+ app.on('second-instance', (event, commandLine, workingDirectory) => {
+ const files = getSearchFiles(commandLine, workingDirectory);
const win = this.windowCreator.getWindow();
+ // 当运行第二个实例时,将会聚焦到myWindow这个窗口
+ // 如果有文件列表作为参数,说明是命令行启动
if (win) {
if (win.isMinimized()) {
win.restore();
}
win.focus();
+ if (files.length > 0) {
+ win.show();
+ putFileToRubick(win.webContents, files);
+ }
}
});
app.on('activate', () => {
diff --git a/src/renderer/components/search.vue b/src/renderer/components/search.vue
index 62aa420..cf57b0f 100644
--- a/src/renderer/components/search.vue
+++ b/src/renderer/components/search.vue
@@ -59,7 +59,7 @@ import { LoadingOutlined, MoreOutlined } from '@ant-design/icons-vue';
const remote = window.require('@electron/remote');
import localConfig from '../confOp';
-const { Menu } = remote;
+const { Menu, app } = remote;
const config: any = ref(localConfig.getConfig());
@@ -232,9 +232,14 @@ const changeHideOnBlur = () => {
const getIcon = () => {
if (props.clipboardFile[0].dataUrl) return props.clipboardFile[0].dataUrl;
- return props.clipboardFile[0].isFile
- ? require('../assets/file.png')
- : require('../assets/folder.png');
+ try {
+ return ipcRenderer.sendSync('msg-trigger', {
+ type: 'getFileIcon',
+ data: { path: props.clipboardFile[0].path },
+ });
+ } catch (e) {
+ return require('../assets/file.png');
+ }
};
const newWindow = () => {
diff --git a/src/renderer/plugins-manager/clipboardWatch.ts b/src/renderer/plugins-manager/clipboardWatch.ts
index 2f91524..b101866 100644
--- a/src/renderer/plugins-manager/clipboardWatch.ts
+++ b/src/renderer/plugins-manager/clipboardWatch.ts
@@ -8,13 +8,13 @@ import { ref } from 'vue';
export default ({ currentPlugin, optionsRef, openPlugin, setOptionsRef }) => {
const clipboardFile: any = ref([]);
- const searchFocus = () => {
+ const searchFocus = (files) => {
const config: any = localConfig.getConfig();
// 未开启自动粘贴
if (!config.perf.common.autoPast) return;
if (currentPlugin.value.name) return;
- const fileList = getCopyFiles();
+ const fileList = files || getCopyFiles();
// 拷贝的是文件
if (fileList) {
window.setSubInputValue({ value: '' });
@@ -43,78 +43,79 @@ export default ({ currentPlugin, optionsRef, openPlugin, setOptionsRef }) => {
}
// 再正则插件
- localPlugins.forEach((plugin) => {
- const feature = plugin.features;
- // 系统插件无 features 的情况,不需要再搜索
- if (!feature) return;
- feature.forEach((fe) => {
- const ext = path.extname(fileList[0].path);
- fe.cmds.forEach((cmd) => {
- const regImg = /\.(png|jpg|gif|jpeg|webp)$/;
- if (
- cmd.type === 'img' &&
- regImg.test(ext) &&
- fileList.length === 1
- ) {
- const option = {
- name: cmd.label,
- value: 'plugin',
- icon: plugin.logo,
- desc: fe.explain,
- type: plugin.pluginType,
- click: () => {
- pluginClickEvent({
- plugin,
- fe,
- cmd,
- ext: {
- code: fe.code,
- type: cmd.type || 'text',
- payload: nativeImage
- .createFromPath(fileList[0].path)
- .toDataURL(),
- },
- openPlugin,
- option,
- });
- clearClipboardFile();
- },
- };
- options.push(option);
- }
- // 如果是文件,且符合文件正则类型
- if (
- fileList.length > 1 ||
- (cmd.type === 'file' && new RegExp(cmd.match).test(ext))
- ) {
- const option = {
- name: cmd,
- value: 'plugin',
- icon: plugin.logo,
- desc: fe.explain,
- type: plugin.pluginType,
- click: () => {
- pluginClickEvent({
- plugin,
- fe,
- cmd,
- option,
- ext: {
- code: fe.code,
- type: cmd.type || 'text',
- payload: fileList,
- },
- openPlugin,
- });
- clearClipboardFile();
- },
- };
- options.push(option);
- }
+ if (fileList.length === 1) {
+ localPlugins.forEach((plugin) => {
+ const feature = plugin.features;
+ // 系统插件无 features 的情况,不需要再搜索
+ if (!feature) return;
+ feature.forEach((fe) => {
+ const ext = path.extname(fileList[0].path);
+ fe.cmds.forEach((cmd) => {
+ const regImg = /\.(png|jpg|gif|jpeg|webp)$/;
+ if (
+ cmd.type === 'img' &&
+ regImg.test(ext) &&
+ fileList.length === 1
+ ) {
+ const option = {
+ name: cmd.label,
+ value: 'plugin',
+ icon: plugin.logo,
+ desc: fe.explain,
+ type: plugin.pluginType,
+ click: () => {
+ pluginClickEvent({
+ plugin,
+ fe,
+ cmd,
+ ext: {
+ code: fe.code,
+ type: cmd.type || 'text',
+ payload: nativeImage
+ .createFromPath(fileList[0].path)
+ .toDataURL(),
+ },
+ openPlugin,
+ option,
+ });
+ clearClipboardFile();
+ },
+ };
+ options.push(option);
+ }
+ // 如果是文件,且符合文件正则类型
+ if (
+ fileList.length > 1 ||
+ (cmd.type === 'file' && new RegExp(cmd.match).test(ext))
+ ) {
+ const option = {
+ name: cmd,
+ value: 'plugin',
+ icon: plugin.logo,
+ desc: fe.explain,
+ type: plugin.pluginType,
+ click: () => {
+ pluginClickEvent({
+ plugin,
+ fe,
+ cmd,
+ option,
+ ext: {
+ code: fe.code,
+ type: cmd.type || 'text',
+ payload: fileList,
+ },
+ openPlugin,
+ });
+ clearClipboardFile();
+ },
+ };
+ options.push(option);
+ }
+ });
});
});
- });
-
+ }
setOptionsRef(options);
clipboard.clear();
return;
diff --git a/src/renderer/plugins-manager/options.ts b/src/renderer/plugins-manager/options.ts
index 1c6dceb..04e9eb7 100644
--- a/src/renderer/plugins-manager/options.ts
+++ b/src/renderer/plugins-manager/options.ts
@@ -156,6 +156,8 @@ const optionsManager = ({
setOptionsRef,
});
+ window.searchFocus = searchFocus;
+
return {
options: optionsRef,
searchFocus,
diff --git a/src/renderer/shims-vue.d.ts b/src/renderer/shims-vue.d.ts
index 37b95bf..497ddb1 100644
--- a/src/renderer/shims-vue.d.ts
+++ b/src/renderer/shims-vue.d.ts
@@ -26,4 +26,5 @@ interface Window {
setCurrentPlugin: (plugin: any) => void;
pluginLoaded: () => void;
getMainInputInfo: () => any;
+ searchFocus: (args: any) => any;
}
diff --git a/vue.config.js b/vue.config.js
index 4a90ef7..23f5ebb 100644
--- a/vue.config.js
+++ b/vue.config.js
@@ -32,7 +32,7 @@ module.exports = {
],
// Use this to change the entry point of your app's render process. default src/[main|index].[js|ts]
builderOptions: {
- productName: 'rubick2',
+ productName: 'rubick',
appId: 'com.muwoo.rubick',
compression: 'maximum',
directories: {
@@ -67,7 +67,13 @@ module.exports = {
},
mac: {
icon: 'public/icons/icon.icns',
- target: ['dmg', 'zip'],
+ target: [
+ {
+ target: 'dmg',
+ arch: ['x64', 'arm64'],
+ },
+ ],
+ artifactName: 'rubick-${version}-${arch}.dmg',
gatekeeperAssess: false,
entitlementsInherit: './release/entitlements.mac.plist',
entitlements: './release/entitlements.mac.plist',
@@ -79,11 +85,19 @@ module.exports = {
},
win: {
icon: 'public/icons/icon.ico',
- target: 'nsis',
+ artifactName: 'rubick-Setup-${version}-${arch}.exe',
+ target: [
+ {
+ target: 'nsis',
+ arch: ['x64', 'ia32'],
+ },
+ ],
},
nsis: {
+ shortcutName: 'rubick',
oneClick: false,
allowToChangeInstallationDirectory: true,
+ include: 'public/installer.nsh',
},
linux: {
icon: 'public/icons/',