improve clipboard handling (#596)

* improve clipboard handling

* fix regression of not defocusing tool icons
This commit is contained in:
David Luzar 2020-01-27 22:14:35 +01:00 committed by GitHub
parent de68561df5
commit 26048ee469
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 38 additions and 21 deletions

View File

@ -37,7 +37,7 @@ export class ActionManager implements ActionsManagerInterface {
action => action.keyTest && action.keyTest(event, elements, appState),
);
if (data.length === 0) return {};
if (data.length === 0) return null;
event.preventDefault();
return data[0].perform(elements, appState, null);

View File

@ -45,7 +45,7 @@ export interface ActionsManagerInterface {
event: KeyboardEvent,
elements: readonly ExcalidrawElement[],
appState: AppState,
) => ActionResult | {};
) => ActionResult | null;
getContextMenuItems: (
elements: readonly ExcalidrawElement[],
appState: AppState,

View File

@ -307,11 +307,15 @@ export class App extends React.Component<any, AppState> {
}
if (isInputLike(event.target)) return;
const data = this.actionManager.handleKeyDown(event, elements, this.state);
this.syncActionResult(data);
const actionResult = this.actionManager.handleKeyDown(
event,
elements,
this.state,
);
if (data.elements !== undefined || data.appState !== undefined) {
return;
if (actionResult) {
this.syncActionResult(actionResult);
if (actionResult) return;
}
const shape = findShapeByKey(event.key);
@ -371,18 +375,20 @@ export class App extends React.Component<any, AppState> {
private removeWheelEventListener: (() => void) | undefined;
private copyToClipboard = () => {
if (navigator.clipboard) {
const text = JSON.stringify(
elements
.filter(element => element.isSelected)
.map(({ shape, ...el }) => el),
);
const text = JSON.stringify(
elements
.filter(element => element.isSelected)
.map(({ shape, ...el }) => el),
);
if ("clipboard" in navigator && "writeText" in navigator.clipboard) {
navigator.clipboard.writeText(text);
} else {
document.execCommand("copy");
}
};
private pasteFromClipboard = () => {
if (navigator.clipboard) {
if ("clipboard" in navigator && "readText" in navigator.clipboard) {
navigator.clipboard
.readText()
.then(text => this.addElementsFromPaste(text));
@ -790,9 +796,9 @@ export class App extends React.Component<any, AppState> {
// fixes mousemove causing selection of UI texts #32
e.preventDefault();
// Preventing the event above disables default behavior
// of defocusing potentially focused input, which is what we want
// when clicking inside the canvas.
if (isInputLike(document.activeElement)) {
// of defocusing potentially focused element, which is what we
// want when clicking inside the canvas.
if (document.activeElement instanceof HTMLElement) {
document.activeElement.blur();
}

View File

@ -14,14 +14,25 @@ export function capitalizeString(str: string) {
return str.charAt(0).toUpperCase() + str.slice(1);
}
export function isToolIcon(
target: Element | EventTarget | null,
): target is HTMLElement {
return target instanceof HTMLElement && target.className.includes("ToolIcon");
}
export function isInputLike(
target: Element | EventTarget | null,
): target is HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement {
): target is
| HTMLInputElement
| HTMLTextAreaElement
| HTMLSelectElement
| HTMLDivElement {
return (
(target instanceof HTMLElement && target.dataset.type === "wysiwyg") ||
target instanceof HTMLInputElement ||
target instanceof HTMLTextAreaElement ||
target instanceof HTMLSelectElement
((target instanceof HTMLElement && target.dataset.type === "wysiwyg") ||
target instanceof HTMLInputElement ||
target instanceof HTMLTextAreaElement ||
target instanceof HTMLSelectElement) &&
!isToolIcon(target)
);
}