mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-09-26 02:40:07 +02:00
alternatvie: keep lasso drag to only mobile
This commit is contained in:
@@ -25,6 +25,18 @@ export const isIOS =
|
|||||||
export const isBrave = () =>
|
export const isBrave = () =>
|
||||||
(navigator as any).brave?.isBrave?.name === "isBrave";
|
(navigator as any).brave?.isBrave?.name === "isBrave";
|
||||||
|
|
||||||
|
// Mobile user agent detection
|
||||||
|
export const isMobileUA =
|
||||||
|
/android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(
|
||||||
|
navigator.userAgent.toLowerCase(),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Mobile platform detection
|
||||||
|
export const isMobilePlatform =
|
||||||
|
/android|ios|iphone|ipad|ipod|blackberry|windows phone/i.test(
|
||||||
|
navigator.platform.toLowerCase(),
|
||||||
|
);
|
||||||
|
|
||||||
export const supportsResizeObserver =
|
export const supportsResizeObserver =
|
||||||
typeof window !== "undefined" && "ResizeObserver" in window;
|
typeof window !== "undefined" && "ResizeObserver" in window;
|
||||||
|
|
||||||
|
@@ -100,6 +100,8 @@ import {
|
|||||||
randomInteger,
|
randomInteger,
|
||||||
CLASSES,
|
CLASSES,
|
||||||
Emitter,
|
Emitter,
|
||||||
|
isMobileUA,
|
||||||
|
isMobilePlatform,
|
||||||
} from "@excalidraw/common";
|
} from "@excalidraw/common";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -2386,6 +2388,19 @@ class App extends React.Component<AppProps, AppState> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private isMobileOrTablet = (): boolean => {
|
||||||
|
// Touch + pointer accuracy
|
||||||
|
const hasTouch = "ontouchstart" in window || navigator.maxTouchPoints > 0;
|
||||||
|
const hasCoarsePointer = window.matchMedia("(pointer: coarse)").matches;
|
||||||
|
const isTouchMobile = hasTouch && hasCoarsePointer;
|
||||||
|
|
||||||
|
// At least two indicators should be true
|
||||||
|
const indicators = [isMobileUA, isTouchMobile, isMobilePlatform];
|
||||||
|
const hasMultipleIndicators = indicators.filter(Boolean).length >= 2;
|
||||||
|
|
||||||
|
return hasMultipleIndicators;
|
||||||
|
};
|
||||||
|
|
||||||
private isMobileBreakpoint = (width: number, height: number) => {
|
private isMobileBreakpoint = (width: number, height: number) => {
|
||||||
return (
|
return (
|
||||||
width < MQ_MAX_WIDTH_PORTRAIT ||
|
width < MQ_MAX_WIDTH_PORTRAIT ||
|
||||||
@@ -6013,7 +6028,7 @@ class App extends React.Component<AppProps, AppState> {
|
|||||||
if (
|
if (
|
||||||
hasDeselectedButton ||
|
hasDeselectedButton ||
|
||||||
(this.state.activeTool.type !== "selection" &&
|
(this.state.activeTool.type !== "selection" &&
|
||||||
this.state.activeTool.type !== "lasso" &&
|
(this.state.activeTool.type !== "lasso" || !this.isMobileOrTablet()) &&
|
||||||
this.state.activeTool.type !== "text" &&
|
this.state.activeTool.type !== "text" &&
|
||||||
this.state.activeTool.type !== "eraser")
|
this.state.activeTool.type !== "eraser")
|
||||||
) {
|
) {
|
||||||
@@ -6187,7 +6202,7 @@ class App extends React.Component<AppProps, AppState> {
|
|||||||
) {
|
) {
|
||||||
if (
|
if (
|
||||||
this.state.activeTool.type !== "lasso" ||
|
this.state.activeTool.type !== "lasso" ||
|
||||||
selectedElements.length > 0
|
(selectedElements.length > 0 && this.isMobileOrTablet())
|
||||||
) {
|
) {
|
||||||
setCursor(this.interactiveCanvas, CURSOR_TYPE.MOVE);
|
setCursor(this.interactiveCanvas, CURSOR_TYPE.MOVE);
|
||||||
}
|
}
|
||||||
@@ -6301,7 +6316,8 @@ class App extends React.Component<AppProps, AppState> {
|
|||||||
) {
|
) {
|
||||||
if (
|
if (
|
||||||
this.state.activeTool.type !== "lasso" ||
|
this.state.activeTool.type !== "lasso" ||
|
||||||
Object.keys(this.state.selectedElementIds).length > 0
|
(Object.keys(this.state.selectedElementIds).length > 0 &&
|
||||||
|
this.isMobileOrTablet())
|
||||||
) {
|
) {
|
||||||
setCursor(this.interactiveCanvas, CURSOR_TYPE.MOVE);
|
setCursor(this.interactiveCanvas, CURSOR_TYPE.MOVE);
|
||||||
}
|
}
|
||||||
@@ -6315,7 +6331,8 @@ class App extends React.Component<AppProps, AppState> {
|
|||||||
) {
|
) {
|
||||||
if (
|
if (
|
||||||
this.state.activeTool.type !== "lasso" ||
|
this.state.activeTool.type !== "lasso" ||
|
||||||
Object.keys(this.state.selectedElementIds).length > 0
|
(Object.keys(this.state.selectedElementIds).length > 0 &&
|
||||||
|
this.isMobileOrTablet())
|
||||||
) {
|
) {
|
||||||
setCursor(this.interactiveCanvas, CURSOR_TYPE.MOVE);
|
setCursor(this.interactiveCanvas, CURSOR_TYPE.MOVE);
|
||||||
}
|
}
|
||||||
@@ -6583,13 +6600,16 @@ class App extends React.Component<AppProps, AppState> {
|
|||||||
const hitSelectedElement =
|
const hitSelectedElement =
|
||||||
pointerDownState.hit.element &&
|
pointerDownState.hit.element &&
|
||||||
this.isASelectedElement(pointerDownState.hit.element);
|
this.isASelectedElement(pointerDownState.hit.element);
|
||||||
|
const isMobileOrTablet = this.isMobileOrTablet();
|
||||||
|
|
||||||
// Start a new lasso ONLY if we're not interacting with an existing
|
// On PCs, we always want to start a new lasso path even when we're hitting some elements
|
||||||
|
// Otherwise, start a new lasso ONLY if we're not interacting with an existing
|
||||||
// selection (move/resize/rotate).
|
// selection (move/resize/rotate).
|
||||||
if (
|
if (
|
||||||
!pointerDownState.hit.hasHitCommonBoundingBoxOfSelectedElements &&
|
!isMobileOrTablet ||
|
||||||
|
(!pointerDownState.hit.hasHitCommonBoundingBoxOfSelectedElements &&
|
||||||
!pointerDownState.resize.handleType &&
|
!pointerDownState.resize.handleType &&
|
||||||
!hitSelectedElement
|
!hitSelectedElement)
|
||||||
) {
|
) {
|
||||||
this.lassoTrail.startPath(
|
this.lassoTrail.startPath(
|
||||||
pointerDownState.origin.x,
|
pointerDownState.origin.x,
|
||||||
@@ -6598,8 +6618,13 @@ class App extends React.Component<AppProps, AppState> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// For lasso tool, if we hit an element, select it immediately like normal selection
|
// When mobile & tablet, for lasso tool
|
||||||
if (pointerDownState.hit.element && !hitSelectedElement) {
|
// if we hit an element, select it immediately like normal selection
|
||||||
|
if (
|
||||||
|
isMobileOrTablet &&
|
||||||
|
pointerDownState.hit.element &&
|
||||||
|
!hitSelectedElement
|
||||||
|
) {
|
||||||
this.setState((prevState) => {
|
this.setState((prevState) => {
|
||||||
const nextSelectedElementIds: { [id: string]: true } = {
|
const nextSelectedElementIds: { [id: string]: true } = {
|
||||||
...prevState.selectedElementIds,
|
...prevState.selectedElementIds,
|
||||||
@@ -7141,7 +7166,7 @@ class App extends React.Component<AppProps, AppState> {
|
|||||||
): boolean => {
|
): boolean => {
|
||||||
if (
|
if (
|
||||||
this.state.activeTool.type === "selection" ||
|
this.state.activeTool.type === "selection" ||
|
||||||
this.state.activeTool.type === "lasso"
|
(this.state.activeTool.type === "lasso" && this.isMobileOrTablet())
|
||||||
) {
|
) {
|
||||||
const elements = this.scene.getNonDeletedElements();
|
const elements = this.scene.getNonDeletedElements();
|
||||||
const elementsMap = this.scene.getNonDeletedElementsMap();
|
const elementsMap = this.scene.getNonDeletedElementsMap();
|
||||||
@@ -8387,7 +8412,8 @@ class App extends React.Component<AppProps, AppState> {
|
|||||||
(hasHitASelectedElement ||
|
(hasHitASelectedElement ||
|
||||||
pointerDownState.hit.hasHitCommonBoundingBoxOfSelectedElements ||
|
pointerDownState.hit.hasHitCommonBoundingBoxOfSelectedElements ||
|
||||||
(this.state.activeTool.type === "lasso" &&
|
(this.state.activeTool.type === "lasso" &&
|
||||||
pointerDownState.hit.element)) &&
|
pointerDownState.hit.element &&
|
||||||
|
this.isMobileOrTablet())) &&
|
||||||
!isSelectingPointsInLineEditor &&
|
!isSelectingPointsInLineEditor &&
|
||||||
(this.state.activeTool.type !== "lasso" ||
|
(this.state.activeTool.type !== "lasso" ||
|
||||||
pointerDownState.hit.hasHitCommonBoundingBoxOfSelectedElements ||
|
pointerDownState.hit.hasHitCommonBoundingBoxOfSelectedElements ||
|
||||||
@@ -8437,7 +8463,9 @@ class App extends React.Component<AppProps, AppState> {
|
|||||||
selectedElements.length > 0 &&
|
selectedElements.length > 0 &&
|
||||||
!pointerDownState.withCmdOrCtrl &&
|
!pointerDownState.withCmdOrCtrl &&
|
||||||
!this.state.editingTextElement &&
|
!this.state.editingTextElement &&
|
||||||
this.state.activeEmbeddable?.state !== "active"
|
this.state.activeEmbeddable?.state !== "active" &&
|
||||||
|
// for lasso tool, only allow dragging on mobile or tablet devices
|
||||||
|
(this.state.activeTool.type !== "lasso" || this.isMobileOrTablet())
|
||||||
) {
|
) {
|
||||||
const dragOffset = {
|
const dragOffset = {
|
||||||
x: pointerCoords.x - pointerDownState.drag.origin.x,
|
x: pointerCoords.x - pointerDownState.drag.origin.x,
|
||||||
|
Reference in New Issue
Block a user