preface

In order to further improve the development efficiency, we recently developed an open source toolkit based on Electron, which is comparable to UTools. Not only is the toolkit open source, but the most important thing is that you can use all the open source plug-ins in the UTools ecosystem! This is a huge power and means that all the plugins in the UTools ecosystem can be used in Rubick without differentiation.

In order to improve the user’s efficiency, we try to implement some excellent designs in UTools, such as super panel. This feature allows you to quickly invoke the UTools plug-in capabilities with the mouse without having to open the application. For example, if we upload pictures, as long as we install the Graph Bed plug-in, then when the mouse select a picture on the desktop, you can quickly call out the menu option of uploading pictures, convenient and easy. Let’s see how to achieve it.

Code warehouse

Rubick github

Function screenshot:

Long press right under folder to build

Long right-click after selecting the file

Long right-click after selecting the text

Realize the principle of

Gets the selected copy

To achieve the core of the function is to read the current user selected copy or file, according to the current selected content for different function display. But the core problem is how to implement fetching the currently selected content. After thinking about this problem for a long time, I feel that the only way to get the selected copy is to use Ctrl + C or Command + C to copy to the clipboard first, and then use Electron clipboard to get the current clipboard content. But instead of copying and holding down, uTools simply selects text or holds down a file and then calls up the super panel. So be sure to get the currently selected content before right-clicking the long press.

If you do that, you might actually have no solution, because you thought that way before, you would have no solution. The correct idea is to hold down the selected content before fetching it. It doesn’t look like it’s all lost, but it makes a world of difference:

  1. Get selected first: This requires us to listen for native system selected events, butelectronThe capability is not provided and we cannot listen for system selection events.
  2. Right-click first, then get the content. The advantage of this is that right-click first allows you to listen for mouse right-click events, which is easier than selecting events.

So the idea is to listen for long right-click events first:

// macos const mouseEvents = require("osx-mouse"); const mouseTrack = mouseEvents(); // let down_time = 0; // Let isPress = false; On ('right-down', () => {isPress = true; down_time = Date.now(); Async () {if (isPress) {const CopyResult = await getSelectedText(); }, 500); }) mouseTrack.on('right-up', () => { isPress = false; });

The next step is to implement fetching the selected content. To get the selected content, there is a nice operation, which is:

  1. throughclipboardFirst, get the content of the current shear plate, and enter A
  2. throughrobot.jsTo call the systemcommand + corctrl + c
  3. throughclipboardFirst, get the content of the current shear plate, and enter B
  4. Write A to the shear board and return B

The purpose of saving clipboard content first is that we secretly help the user to perform the copy action. After reading the user’s selected content, we need to reply to the user’s previous clipboard content. Now let’s look at a simple implementation:

Const getSselected = () => {return new Promise((resolve) => {const lastText = clipboard.readText('clipboard'); const platform = process.platform; If (platform === 'Darwin ') {robot.keyTap('c', 'command'); } else { robot.keyTap('c', 'control'); = > {} setTimeout () / / read the clipboard contents const text = clipboard. ReadText (' clipboard ') | | 'const fileUrl = clipboard.read('public.file-url'); // Restore clipboard contents clipboard.writetext (lastText); resolve({ text, fileUrl }) }, 300); })}

Notifies the super panel window of what is currently selected

With the selected content retrieved, the next step is to create BrowserWindow for the super panel:

const { BrowserWindow, ipcMain, app } = require("electron"); module.exports = () => { let win; let init = (mainWindow) => { if (win === null || win === undefined) { createWindow(); }}; let createWindow = () => { win = new BrowserWindow({ frame: false, autoHideMenuBar: true, width: 250, height: 50, show: false, alwaysOnTop: true, webPreferences: { webSecurity: false, enableRemoteModule: true, backgroundThrottling: false, nodeIntegration: true, devTools: false, }, }); win.loadURL(`file://${__static}/plugins/superPanel/index.html`); win.once('ready-to-show', () => win.show()); win.on("closed", () => { win = undefined; }); }; let getWindow = () => win; return { init: init, getWindow: getWindow, }; };

Then notify the superPanel to display the content:

win.webContents.send('trigger-super-panel', { ... copyResult, optionPlugin: optionPlugin.plugins, });

Super panel click action

Next to achieve the super panel click operation, this is relatively simple, directly on the code:

1. Open the Terminal

const { spawn } = require ('child_process');

spawn('open', [ '-a', 'Terminal', fileUrl ]);

2. Create a new file

Remote. Dialog. ShowSaveDialog ({title: "please select a filename to save, buttonLabel:" save ", defaultPath: fileUrl.replace('file://', ''), showsTagField: false, nameFieldLabel: '', }).then(result => { fs.writeFileSync(result.filePath, ''); });

3. Copy paths

clipboard.writeText(fileUrl.replace('file://', ''))

The last

In this post, we’ll show you how to implement a super panel like UTools, but that’s far from the whole of UTools. In the next post, we’ll show you how to implement the rest of UTools. Feel free to issue any questions you have about Rubick and we’ll give you feedback.

In addition, if think design implementation approach is useful to you, and welcome to a Star:https://github.com/clouDr-f2e/rubick