Skip to content

Commit

Permalink
Fix copy paste
Browse files Browse the repository at this point in the history
Switches mime type of clipboard ID to text/plain.
Prevents GLSP handling paste if the active element isn't the SVG element.
Tests whether copy, cut and paste commands are supported in the browser
to enable even paste in an Electron context.

Fixes eclipse-glsp/glsp#249
  • Loading branch information
planger authored and martin-fleck-at committed Jun 14, 2021
1 parent d011231 commit ca6fb1d
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 11 deletions.
45 changes: 38 additions & 7 deletions packages/client/src/features/copy-paste/copy-paste-context-menu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,21 +49,31 @@ export class InvokeCopyPasteActionHandler implements IActionHandler {
handle(action: Action): void {
switch (action.kind) {
case InvokeCopyAction.KIND:
document.execCommand('copy');
if (supportsCopy()) {
document.execCommand('copy');
} else {
this.notifyUserToUseShortcut('copy');
}
break;
case InvokePasteAction.KIND:
// in a browser without additional permission we can't invoke the paste command
// the user needs to invoke it from the browser, so notify the user about it
this.notifyUserToUseShortcut();
if (supportsPaste()) {
document.execCommand('paste');
} else {
this.notifyUserToUseShortcut('paste');
}
break;
case InvokeCutAction.KIND:
document.execCommand('cut');
if (supportsCut()) {
document.execCommand('cut');
} else {
this.notifyUserToUseShortcut('cut');
}
break;
}
}

protected notifyUserToUseShortcut(): void {
const message = 'Please use the browser\'s paste command or shortcut.';
protected notifyUserToUseShortcut(operation: string): void {
const message = `Please use the browser's ${operation} command or shortcut.`;
const timeout = 10000;
const severity = 'WARNING';
this.dispatcher.dispatchAll([
Expand Down Expand Up @@ -105,3 +115,24 @@ export class CopyPasteContextMenuItemProvider implements IContextMenuItemProvide
};
}
}

export function supportsCopy(): boolean {
return isNative() || document.queryCommandSupported('copy');
}

export function supportsCut(): boolean {
return isNative() || document.queryCommandSupported('cut');
}

export function supportsPaste(): boolean {
const isChrome = (userAgent().indexOf('Chrome') >= 0);
return isNative() || (!isChrome && document.queryCommandSupported('paste'));
}

export function isNative(): boolean {
return typeof (window as any).process !== 'undefined';
}

function userAgent(): string {
return typeof navigator !== 'undefined' ? navigator.userAgent : '';
}
16 changes: 12 additions & 4 deletions packages/client/src/features/copy-paste/copy-paste-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ function getClipboardIdFromDataTransfer(dataTransfer: DataTransfer): string | un
return isClipboardId(jsonObject) ? jsonObject.clipboardId : undefined;
}

const CLIPBOARD_DATA_FORMAT = 'application/json';
const CLIPBOARD_DATA_FORMAT = 'text/plain';

@injectable()
export class ServerCopyPasteHandler implements ICopyPasteHandler {
Expand Down Expand Up @@ -126,7 +126,7 @@ export class ServerCopyPasteHandler implements ICopyPasteHandler {
}

handlePaste(event: ClipboardEvent): void {
if (event.clipboardData) {
if (event.clipboardData && this.shouldPaste(event)) {
const clipboardId = getClipboardIdFromDataTransfer(event.clipboardData);
const clipboardData = this.clipboadService.get(clipboardId);
if (clipboardData) {
Expand All @@ -137,8 +137,16 @@ export class ServerCopyPasteHandler implements ICopyPasteHandler {
}

protected shouldCopy(_event: ClipboardEvent): boolean | null {
return this.editorContext.get().selectedElementIds.length > 0 && document.activeElement instanceof SVGElement
&& document.activeElement.parentElement && document.activeElement.parentElement.id === this.viewerOptions.baseDiv;
return this.editorContext.get().selectedElementIds.length > 0 && this.isDiagramActive();
}

protected shouldPaste(_event: ClipboardEvent): boolean | null {
return this.isDiagramActive();
}

private isDiagramActive(): boolean | null {
return document.activeElement instanceof SVGElement
&& document.activeElement.parentElement
&& document.activeElement.parentElement.id === this.viewerOptions.baseDiv;
}
}

0 comments on commit ca6fb1d

Please sign in to comment.