Skip to content

Commit 3731bfe

Browse files
committed
Added copy/paste context menu to inputs and code/pre blocks
1 parent 0e36b51 commit 3731bfe

6 files changed

Lines changed: 75 additions & 2 deletions

File tree

src-electron/ipcListeners.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ipcMain, dialog, App, BrowserWindow } from 'electron';
1+
import { ipcMain, dialog, App, BrowserWindow, Menu, MenuItem } from 'electron';
22
import electronUpdater from 'electron-updater';
33
import os from 'os';
44
import { fileURLToPath } from 'url';
@@ -75,3 +75,19 @@ ipcMain.on('get-statics-directory', (event) => {
7575
const __dirname = path.dirname(__filename);
7676
event.returnValue = __dirname;
7777
});
78+
79+
ipcMain.on('electron:showContextMenu', (event, options: any) => {
80+
const templateItems: MenuItem[] = [];
81+
templateItems.push(new MenuItem({
82+
label: 'Copy',
83+
role: 'copy'
84+
}));
85+
if (!options.readonly) {
86+
templateItems.push(new MenuItem({
87+
label: 'Paste',
88+
role: 'paste'
89+
}));
90+
}
91+
const menu = Menu.buildFromTemplate(templateItems);
92+
menu.popup();
93+
})

src-electron/preload/electron-preload.ts renamed to src-electron/preload/electron-ipc-preload.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,7 @@ export async function selectFileDialog(options: any) {
3030
export function copyToClipboard(value: string) {
3131
ipcRenderer.sendSync('electron:clipboard:copyText', value);
3232
}
33+
34+
export function showContextMenu(options: any) {
35+
ipcRenderer.send('electron:showContextMenu', options);
36+
}

src-electron/preload/expose-preload.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import * as buffer from './node-buffer';
66
import * as os from './node-os';
77
import * as zip from './zip-preload';
88
import * as appGlobals from "./app-preload-globals";
9-
import * as electron from "./electron-preload";
9+
import * as electron from "./electron-ipc-preload";
1010

1111
contextBridge.exposeInMainWorld('node', {
1212
path: path,

src/App.vue

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ import { NodeFsImplementation } from './providers/node/fs/NodeFsImplementation';
5252
import { useRouter } from 'vue-router';
5353
import { ProtocolProviderImplementation } from './providers/generic/protocol/ProtocolProviderImplementation';
5454
import { provideProtocolImplementation } from './providers/generic/protocol/ProtocolProvider';
55+
import contextMenu from './providers/node/context_menu/context_menu';
5556
5657
const store = baseStore;
5758
const router = useRouter();
@@ -142,6 +143,23 @@ onMounted(async () => {
142143
143144
watchEffect(() => {
144145
document.documentElement.classList.toggle('html--dark', quasar.dark.isActive);
146+
});
147+
148+
document.addEventListener('contextmenu', e => {
149+
if (e.target) {
150+
const target = e.target as HTMLElement;
151+
switch (true) {
152+
case target instanceof HTMLInputElement: {
153+
contextMenu.showContextMenu({ readonly: false });
154+
break;
155+
}
156+
case ['code', 'pre'].includes(target.tagName.toLowerCase()): {
157+
contextMenu.showContextMenu({ readonly: true });
158+
break;
159+
}
160+
default: { break; }
161+
}
162+
}
145163
})
146164
</script>
147165

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { ContextMenuProcessProvider } from './context_menu';
2+
3+
let execIdentifier = 0;
4+
5+
export const ContextMenuProcessImplementation: ContextMenuProcessProvider = {
6+
showContextMenu: (options) => window.electron.showContextMenu(options),
7+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { ContextMenuProcessImplementation } from './ContextMenuImplementation';
2+
3+
export type ContextMenuOptions = {
4+
readonly: boolean
5+
}
6+
7+
export type ContextMenuProcessProvider = {
8+
showContextMenu: (options: ContextMenuOptions) => Promise<void>;
9+
}
10+
11+
let implementation: () => ContextMenuProcessProvider;
12+
13+
function getImplementation(): ContextMenuProcessProvider {
14+
if (!implementation) {
15+
return ContextMenuProcessImplementation;
16+
}
17+
return implementation();
18+
}
19+
20+
export function provideContextMenuImplementation(provider: () => ContextMenuProcessProvider) {
21+
implementation = provider;
22+
}
23+
24+
const contextMenu: ContextMenuProcessProvider = {
25+
showContextMenu: (options) => getImplementation().showContextMenu(options),
26+
};
27+
28+
export default contextMenu;

0 commit comments

Comments
 (0)