feat: make clipboard more robust and reintroduce contextmenu actions (#7198)

This commit is contained in:
David Luzar 2023-10-28 21:29:28 +02:00 committed by GitHub
parent ec2de7205f
commit ea677d4581
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 611 additions and 193 deletions

View file

@ -1275,6 +1275,12 @@ class App extends React.Component<AppProps, AppState> {
top={this.state.contextMenu.top}
left={this.state.contextMenu.left}
actionManager={this.actionManager}
onClose={(callback) => {
this.setState({ contextMenu: null }, () => {
this.focusContainer();
callback?.();
});
}}
/>
)}
<StaticCanvas
@ -2110,7 +2116,7 @@ class App extends React.Component<AppProps, AppState> {
if (!isExcalidrawActive || isWritableElement(event.target)) {
return;
}
this.cutAll();
this.actionManager.executeAction(actionCut, "keyboard", event);
event.preventDefault();
event.stopPropagation();
});
@ -2122,19 +2128,11 @@ class App extends React.Component<AppProps, AppState> {
if (!isExcalidrawActive || isWritableElement(event.target)) {
return;
}
this.copyAll();
this.actionManager.executeAction(actionCopy, "keyboard", event);
event.preventDefault();
event.stopPropagation();
});
private cutAll = () => {
this.actionManager.executeAction(actionCut, "keyboard");
};
private copyAll = () => {
this.actionManager.executeAction(actionCopy, "keyboard");
};
private static resetTapTwice() {
didTapTwice = false;
}
@ -2195,8 +2193,8 @@ class App extends React.Component<AppProps, AppState> {
};
public pasteFromClipboard = withBatchedUpdates(
async (event: ClipboardEvent | null) => {
const isPlainPaste = !!(IS_PLAIN_PASTE && event);
async (event: ClipboardEvent) => {
const isPlainPaste = !!IS_PLAIN_PASTE;
// #686
const target = document.activeElement;

View file

@ -9,11 +9,7 @@ import {
} from "../actions/shortcuts";
import { Action } from "../actions/types";
import { ActionManager } from "../actions/manager";
import {
useExcalidrawAppState,
useExcalidrawElements,
useExcalidrawSetAppState,
} from "./App";
import { useExcalidrawAppState, useExcalidrawElements } from "./App";
import React from "react";
export type ContextMenuItem = typeof CONTEXT_MENU_SEPARATOR | Action;
@ -25,14 +21,14 @@ type ContextMenuProps = {
items: ContextMenuItems;
top: number;
left: number;
onClose: (callback?: () => void) => void;
};
export const CONTEXT_MENU_SEPARATOR = "separator";
export const ContextMenu = React.memo(
({ actionManager, items, top, left }: ContextMenuProps) => {
({ actionManager, items, top, left, onClose }: ContextMenuProps) => {
const appState = useExcalidrawAppState();
const setAppState = useExcalidrawSetAppState();
const elements = useExcalidrawElements();
const filteredItems = items.reduce((acc: ContextMenuItem[], item) => {
@ -54,7 +50,9 @@ export const ContextMenu = React.memo(
return (
<Popover
onCloseRequest={() => setAppState({ contextMenu: null })}
onCloseRequest={() => {
onClose();
}}
top={top}
left={left}
fitInViewport={true}
@ -102,7 +100,7 @@ export const ContextMenu = React.memo(
// we need update state before executing the action in case
// the action uses the appState it's being passed (that still
// contains a defined contextMenu) to return the next state.
setAppState({ contextMenu: null }, () => {
onClose(() => {
actionManager.executeAction(item, "contextMenu");
});
}}