Skip to content

Commit fb1a360

Browse files
committed
Added copy/paste context menu to inputs and code/pre blocks
1 parent 4cb61fb commit fb1a360

File tree

7 files changed

+77
-5
lines changed

7 files changed

+77
-5
lines changed

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 } from 'electron';
1+
import { ipcMain, dialog, Menu, MenuItem } from 'electron';
22
import electronUpdater from 'electron-updater';
33
import os from 'os';
44
import {fileURLToPath} from "url";
@@ -80,3 +80,19 @@ ipcMain.on('get-statics-directory', (event) => {
8080
const __dirname = path.dirname(__filename);
8181
event.returnValue = __dirname;
8282
})
83+
84+
ipcMain.on('electron:showContextMenu', (event, options: any) => {
85+
const templateItems: MenuItem[] = [];
86+
templateItems.push(new MenuItem({
87+
label: 'Copy',
88+
role: 'copy'
89+
}));
90+
if (!options.readonly) {
91+
templateItems.push(new MenuItem({
92+
label: 'Paste',
93+
role: 'paste'
94+
}));
95+
}
96+
const menu = Menu.buildFromTemplate(templateItems);
97+
menu.popup();
98+
})

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
@@ -38,3 +38,7 @@ export async function selectFileDialog(options: any) {
3838
export function copyToClipboard(value: string) {
3939
ipcRenderer.sendSync('electron:clipboard:copyText', value);
4040
}
41+
42+
export function showContextMenu(options: any) {
43+
ipcRenderer.send('electron:showContextMenu', options);
44+
}

src-electron/preload/expose-preload.ts

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

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

src/App.vue

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ import FileUtils from './utils/FileUtils';
2929
import LinkProvider from './providers/components/LinkProvider';
3030
import LinkImpl from './r2mm/component_override/LinkImpl';
3131
import FsProvider from './providers/generic/file/FsProvider';
32-
import NodeFs from './providers/generic/file/NodeFs';
3332
import { DataFolderProvider } from './providers/ror2/system/DataFolderProvider';
3433
import { DataFolderProviderImpl } from './r2mm/system/DataFolderProviderImpl';
3534
import InteractionProvider from './providers/ror2/system/InteractionProvider';
@@ -48,8 +47,9 @@ import { provideStoreImplementation } from './providers/generic/store/StoreProvi
4847
import baseStore from './store';
4948
import { getCurrentInstance, onMounted, ref, watchEffect } from 'vue';
5049
import { useUtilityComposable } from './components/composables/UtilityComposable';
51-
import { Dark, useQuasar } from 'quasar';
50+
import { useQuasar } from 'quasar';
5251
import { NodeFsImplementation } from 'src/providers/node/fs/NodeFsImplementation';
52+
import contextMenu from 'src/providers/node/context_menu/context_menu';
5353
5454
const store = baseStore;
5555
provideStoreImplementation(() => store);
@@ -139,6 +139,23 @@ onMounted(async () => {
139139
140140
watchEffect(() => {
141141
document.documentElement.classList.toggle('html--dark', quasar.dark.isActive);
142+
});
143+
144+
document.addEventListener('contextmenu', e => {
145+
if (e.target) {
146+
const target = e.target as HTMLElement;
147+
switch (true) {
148+
case target instanceof HTMLInputElement: {
149+
contextMenu.showContextMenu({ readonly: false });
150+
break;
151+
}
152+
case ['code', 'pre'].includes(target.tagName.toLowerCase()): {
153+
contextMenu.showContextMenu({ readonly: true });
154+
break;
155+
}
156+
default: { break; }
157+
}
158+
}
142159
})
143160
</script>
144161

src/providers/node/child_process/child_process.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { NodeChildProcessImplementation } from 'src/providers/node/child_process/ChildProcessImplementation';
1+
import { NodeChildProcessImplementation } from './ChildProcessImplementation';
22

33
export type NodeChildProcessProvider = {
44
execSync: (path: string, options?: any) => string;
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)