feat: Arrow binding is a preference (#10839)
Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
This commit is contained in:
@@ -119,7 +119,6 @@ import {
|
||||
fixBindingsAfterDeletion,
|
||||
getHoveredElementForBinding,
|
||||
isBindingEnabled,
|
||||
shouldEnableBindingForPointerEvent,
|
||||
updateBoundElements,
|
||||
LinearElementEditor,
|
||||
newElementWith,
|
||||
@@ -319,6 +318,8 @@ import {
|
||||
actionToggleElementLock,
|
||||
actionToggleLinearEditor,
|
||||
actionToggleObjectsSnapMode,
|
||||
actionToggleArrowBinding,
|
||||
actionToggleMidpointSnapping,
|
||||
actionToggleCropEditor,
|
||||
} from "../actions";
|
||||
import { actionWrapTextInContainer } from "../actions/actionBoundText";
|
||||
@@ -2734,7 +2735,9 @@ class App extends React.Component<AppProps, AppState> {
|
||||
|
||||
private onBlur = withBatchedUpdates(() => {
|
||||
isHoldingSpace = false;
|
||||
this.setState({ isBindingEnabled: true });
|
||||
this.setState({
|
||||
isBindingEnabled: this.state.bindingPreference === "enabled",
|
||||
});
|
||||
});
|
||||
|
||||
private onUnload = () => {
|
||||
@@ -4937,13 +4940,15 @@ class App extends React.Component<AppProps, AppState> {
|
||||
return;
|
||||
}
|
||||
|
||||
if (event[KEYS.CTRL_OR_CMD] && this.state.isBindingEnabled) {
|
||||
if (event[KEYS.CTRL_OR_CMD] && !event.repeat) {
|
||||
if (getFeatureFlag("COMPLEX_BINDINGS")) {
|
||||
this.resetDelayedBindMode();
|
||||
}
|
||||
|
||||
flushSync(() => {
|
||||
this.setState({ isBindingEnabled: false });
|
||||
this.setState({
|
||||
isBindingEnabled: this.state.bindingPreference !== "enabled",
|
||||
});
|
||||
});
|
||||
|
||||
maybeHandleArrowPointlikeDrag({ app: this, event });
|
||||
@@ -5217,10 +5222,13 @@ class App extends React.Component<AppProps, AppState> {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!event[KEYS.CTRL_OR_CMD] && !this.state.isBindingEnabled) {
|
||||
flushSync(() => {
|
||||
this.setState({ isBindingEnabled: true });
|
||||
});
|
||||
if (!event[KEYS.CTRL_OR_CMD]) {
|
||||
const preferenceEnabled = this.state.bindingPreference === "enabled";
|
||||
if (this.state.isBindingEnabled !== preferenceEnabled) {
|
||||
flushSync(() => {
|
||||
this.setState({ isBindingEnabled: preferenceEnabled });
|
||||
});
|
||||
}
|
||||
|
||||
maybeHandleArrowPointlikeDrag({ app: this, event });
|
||||
}
|
||||
@@ -7138,6 +7146,14 @@ class App extends React.Component<AppProps, AppState> {
|
||||
private handleCanvasPointerDown = (
|
||||
event: React.PointerEvent<HTMLElement>,
|
||||
) => {
|
||||
// If Ctrl is not held, ensure isBindingEnabled reflects the user preference.
|
||||
if (!event.ctrlKey) {
|
||||
const preferenceEnabled = this.state.bindingPreference === "enabled";
|
||||
if (this.state.isBindingEnabled !== preferenceEnabled) {
|
||||
this.setState({ isBindingEnabled: preferenceEnabled });
|
||||
}
|
||||
}
|
||||
|
||||
const scenePointer = viewportCoordsToSceneCoords(event, this.state);
|
||||
const { x: scenePointerX, y: scenePointerY } = scenePointer;
|
||||
this.lastPointerMoveCoords = {
|
||||
@@ -7358,7 +7374,6 @@ class App extends React.Component<AppProps, AppState> {
|
||||
}
|
||||
|
||||
this.clearSelectionIfNotUsingSelection();
|
||||
this.updateBindingEnabledOnPointerMove(event);
|
||||
|
||||
if (this.handleSelectionOnPointerDown(event, pointerDownState)) {
|
||||
return;
|
||||
@@ -7581,6 +7596,13 @@ class App extends React.Component<AppProps, AppState> {
|
||||
this.removePointer(event);
|
||||
this.lastPointerUpEvent = event;
|
||||
|
||||
if (!event.ctrlKey) {
|
||||
const preferenceEnabled = this.state.bindingPreference === "enabled";
|
||||
if (this.state.isBindingEnabled !== preferenceEnabled) {
|
||||
this.setState({ isBindingEnabled: preferenceEnabled });
|
||||
}
|
||||
}
|
||||
|
||||
const scenePointer = viewportCoordsToSceneCoords(
|
||||
{ clientX: event.clientX, clientY: event.clientY },
|
||||
this.state,
|
||||
@@ -8636,7 +8658,9 @@ class App extends React.Component<AppProps, AppState> {
|
||||
): void => {
|
||||
if (event.ctrlKey) {
|
||||
flushSync(() => {
|
||||
this.setState({ isBindingEnabled: false });
|
||||
this.setState({
|
||||
isBindingEnabled: this.state.bindingPreference !== "enabled",
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -11330,15 +11354,6 @@ class App extends React.Component<AppProps, AppState> {
|
||||
this.addNewImagesToImageCache();
|
||||
}, IMAGE_RENDER_TIMEOUT);
|
||||
|
||||
private updateBindingEnabledOnPointerMove = (
|
||||
event: React.PointerEvent<HTMLElement>,
|
||||
) => {
|
||||
const shouldEnableBinding = shouldEnableBindingForPointerEvent(event);
|
||||
if (this.state.isBindingEnabled !== shouldEnableBinding) {
|
||||
this.setState({ isBindingEnabled: shouldEnableBinding });
|
||||
}
|
||||
};
|
||||
|
||||
private clearSelection(hitElement: ExcalidrawElement | null): void {
|
||||
this.setState((prevState) => ({
|
||||
selectedElementIds: makeNextSelectedElementIds({}, prevState),
|
||||
@@ -12100,6 +12115,8 @@ class App extends React.Component<AppProps, AppState> {
|
||||
CONTEXT_MENU_SEPARATOR,
|
||||
actionToggleGridMode,
|
||||
actionToggleObjectsSnapMode,
|
||||
actionToggleArrowBinding,
|
||||
actionToggleMidpointSnapping,
|
||||
actionToggleZenMode,
|
||||
actionToggleViewMode,
|
||||
actionToggleStats,
|
||||
|
||||
@@ -249,6 +249,7 @@ const getRelevantAppStateProps = (
|
||||
multiElement: appState.multiElement,
|
||||
newElement: appState.newElement,
|
||||
isBindingEnabled: appState.isBindingEnabled,
|
||||
isMidpointSnappingEnabled: appState.isMidpointSnappingEnabled,
|
||||
suggestedBinding: appState.suggestedBinding,
|
||||
isRotating: appState.isRotating,
|
||||
elementsToHighlight: appState.elementsToHighlight,
|
||||
|
||||
@@ -9,7 +9,9 @@ import {
|
||||
actionLoadScene,
|
||||
actionSaveToActiveFile,
|
||||
actionShortcuts,
|
||||
actionToggleArrowBinding,
|
||||
actionToggleGridMode,
|
||||
actionToggleMidpointSnapping,
|
||||
actionToggleObjectsSnapMode,
|
||||
actionToggleSearchMenu,
|
||||
actionToggleStats,
|
||||
@@ -443,6 +445,40 @@ const PreferencesToggleSnapModeItem = () => {
|
||||
);
|
||||
};
|
||||
|
||||
const PreferencesToggleArrowBindingItem = () => {
|
||||
const { t } = useI18n();
|
||||
const actionManager = useExcalidrawActionManager();
|
||||
const appState = useUIAppState();
|
||||
return (
|
||||
<DropdownMenuItemCheckbox
|
||||
checked={appState.bindingPreference === "enabled"}
|
||||
onSelect={(event) => {
|
||||
actionManager.executeAction(actionToggleArrowBinding);
|
||||
event.preventDefault();
|
||||
}}
|
||||
>
|
||||
{t("labels.arrowBinding")}
|
||||
</DropdownMenuItemCheckbox>
|
||||
);
|
||||
};
|
||||
|
||||
const PreferencesToggleMidpointSnappingItem = () => {
|
||||
const { t } = useI18n();
|
||||
const actionManager = useExcalidrawActionManager();
|
||||
const appState = useUIAppState();
|
||||
return (
|
||||
<DropdownMenuItemCheckbox
|
||||
checked={appState.isMidpointSnappingEnabled}
|
||||
onSelect={(event) => {
|
||||
actionManager.executeAction(actionToggleMidpointSnapping);
|
||||
event.preventDefault();
|
||||
}}
|
||||
>
|
||||
{t("labels.midpointSnapping")}
|
||||
</DropdownMenuItemCheckbox>
|
||||
);
|
||||
};
|
||||
|
||||
export const PreferencesToggleGridModeItem = () => {
|
||||
const { t } = useI18n();
|
||||
const actionManager = useExcalidrawActionManager();
|
||||
@@ -538,6 +574,8 @@ export const Preferences = ({
|
||||
<PreferencesToggleZenModeItem />
|
||||
<PreferencesToggleViewModeItem />
|
||||
<PreferencesToggleElementPropertiesItem />
|
||||
<PreferencesToggleArrowBindingItem />
|
||||
<PreferencesToggleMidpointSnappingItem />
|
||||
</>
|
||||
)}
|
||||
{additionalItems}
|
||||
@@ -548,6 +586,8 @@ export const Preferences = ({
|
||||
|
||||
Preferences.ToggleToolLock = PreferencesToggleToolLockItem;
|
||||
Preferences.ToggleSnapMode = PreferencesToggleSnapModeItem;
|
||||
Preferences.ToggleArrowBinding = PreferencesToggleArrowBindingItem;
|
||||
Preferences.ToggleMidpointSnapping = PreferencesToggleMidpointSnappingItem;
|
||||
Preferences.ToggleGridMode = PreferencesToggleGridModeItem;
|
||||
Preferences.ToggleZenMode = PreferencesToggleZenModeItem;
|
||||
Preferences.ToggleViewMode = PreferencesToggleViewModeItem;
|
||||
|
||||
Reference in New Issue
Block a user