Skip to content

Commit 08e2d0b

Browse files
authored
Merge pull request #379 from ethereum/copypastefix
support copy paste for mac in vscode
2 parents b9f483d + 78c6149 commit 08e2d0b

File tree

2 files changed

+72
-15
lines changed

2 files changed

+72
-15
lines changed

packages/engine/vscode/src/lib/webview.ts

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -179,21 +179,39 @@ async function getWebviewContent(url: string, profile: Profile, options: Webview
179179
const vscode = acquireVsCodeApi();
180180
const pframe = document.createElement('iframe')
181181
// forward messages
182-
window.addEventListener('message', event => {
183-
if (event.origin.indexOf('vscode-webview:')>-1) {
184-
// Else extension -> webview
185-
pframe.contentWindow.postMessage(event.data, '${serverUri}');
186-
} else {
187-
// If iframe -> webview
188-
if(event.data.action == 'keydown'){
189-
// incoming keyboard event
190-
if(navigator.platform.toLowerCase().indexOf('mac') === 0)
191-
window.dispatchEvent(new KeyboardEvent('keydown', event.data));
192-
}else{
193-
// forward message to vscode extension
194-
vscode.postMessage(event.data)
182+
183+
window.addEventListener('paste', function (evt) {
184+
pframe.contentWindow.postMessage({action:"paste", data:evt.clipboardData.getData('text/plain')},'${serverUri}');
185+
});
186+
187+
window.addEventListener('copy', function (evt) {
188+
pframe.contentWindow.postMessage({action:"copy"},'${serverUri}');
189+
});
190+
191+
window.addEventListener('message', event => {
192+
if (event.origin.indexOf('vscode-webview:')>-1) {
193+
// Else extension -> webview
194+
pframe.contentWindow.postMessage(event.data, '${serverUri}');
195+
} else {
196+
// If iframe -> webview
197+
if(event.data.action == 'keydown'){
198+
// incoming keyboard event
199+
if(navigator.platform.toLowerCase().indexOf('mac') === 0)
200+
window.dispatchEvent(new KeyboardEvent('keydown', event.data));
201+
}else if(event.data.action == 'copy'){
202+
// put data in clipboard
203+
if(navigator.platform.toLowerCase().indexOf('mac') === 0){
204+
navigator.permissions.query({name: "clipboard-write"}).then(result => {
205+
if (result.state == "granted" || result.state == "prompt") {
206+
navigator.clipboard.writeText(event.data.data)
207+
}
208+
});
209+
}
210+
}else{
211+
// forward message to vscode extension
212+
vscode.postMessage(event.data)
213+
}
195214
}
196-
}
197215
});
198216
199217
pframe.setAttribute('sandbox', 'allow-popups allow-scripts allow-same-origin allow-downloads allow-forms allow-top-navigation')

packages/plugin/webview/src/lib/connector.ts

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import axios from 'axios'
1616
/** Transform camelCase (JS) text into kebab-case (CSS) */
1717
function toKebabCase(text: string) {
1818
return text.replace(/([a-z0-9]|(?=[A-Z]))([A-Z])/g, '$1-$2').toLowerCase();
19-
};
19+
}
2020

2121
declare global {
2222
function acquireTheiaApi(): any;
@@ -60,6 +60,23 @@ export class WebviewConnector implements ClientConnector {
6060
window.addEventListener('message', async (event: MessageEvent) => {
6161
if (!event.source) return
6262
if (!event.data) return
63+
// copy paste events from vscode
64+
if (event.origin.indexOf('vscode-webview:') > -1) {
65+
if (event.data.action && event.data.action === 'paste') {
66+
this.pasteClipBoard(event);
67+
return;
68+
}
69+
if (event.data.action && event.data.action === 'copy') {
70+
const selection = document.getSelection();
71+
const event = {
72+
action: 'copy',
73+
data: selection.toString()
74+
}
75+
window.parent.postMessage(event, '*')
76+
return;
77+
}
78+
}
79+
// plugin messages
6380
if (!isPluginMessage(event.data)) return
6481
// Support for iframe
6582
if (!this.isVscode) {
@@ -78,6 +95,28 @@ export class WebviewConnector implements ClientConnector {
7895
}
7996

8097
// vscode specific, webview iframe requires forwarding of keyboard events & links clicked
98+
pasteClipBoard(event) {
99+
this.insertAtCursor(document.activeElement, event.data.data);
100+
}
101+
102+
insertAtCursor(element:any, value:any) {
103+
const lastValue:any = element.value;
104+
if (element.selectionStart || element.selectionStart == '0') {
105+
element.value = element.value.substring(0, element.selectionStart)
106+
+ value
107+
+ element.value.substring(element.selectionEnd, element.value.length);
108+
} else {
109+
element.value += value;
110+
}
111+
// this takes care of triggering the change on React components
112+
const event:any = new Event('input', { bubbles: true });
113+
event.simulated = true;
114+
const tracker:any = element._valueTracker;
115+
if (tracker) {
116+
tracker.setValue(lastValue);
117+
}
118+
element.dispatchEvent(event);
119+
}
81120
forwardEvents(){
82121
document.addEventListener('keydown', e => {
83122
const obj = {

0 commit comments

Comments
 (0)