Panayiotis Lipiridis 4 tahun lalu
induk
melakukan
1d7c5705b2

+ 2 - 1
src/actions/actionCanvas.tsx

@@ -18,6 +18,7 @@ import { getNewZoom } from "../scene/zoom";
 import { centerScrollOn } from "../scene/scroll";
 import { centerScrollOn } from "../scene/scroll";
 import { EVENT_ACTION, EVENT_CHANGE, trackEvent } from "../analytics";
 import { EVENT_ACTION, EVENT_CHANGE, trackEvent } from "../analytics";
 import colors from "../colors";
 import colors from "../colors";
+import { GRID_SIZE } from "../constants";
 
 
 export const actionChangeViewBackgroundColor = register({
 export const actionChangeViewBackgroundColor = register({
   name: "changeViewBackgroundColor",
   name: "changeViewBackgroundColor",
@@ -64,7 +65,7 @@ export const actionClearCanvas = register({
         elementLocked: appState.elementLocked,
         elementLocked: appState.elementLocked,
         exportBackground: appState.exportBackground,
         exportBackground: appState.exportBackground,
         exportEmbedScene: appState.exportEmbedScene,
         exportEmbedScene: appState.exportEmbedScene,
-        gridSize: appState.gridSize,
+        gridSize: appState.gridSize || GRID_SIZE,
         shouldAddWatermark: appState.shouldAddWatermark,
         shouldAddWatermark: appState.shouldAddWatermark,
         showStats: appState.showStats,
         showStats: appState.showStats,
       },
       },

+ 131 - 145
src/components/App.tsx

@@ -1,181 +1,167 @@
+import { Point, simplify } from "points-on-curve";
 import React from "react";
 import React from "react";
-
-import rough from "roughjs/bin/rough";
 import { RoughCanvas } from "roughjs/bin/canvas";
 import { RoughCanvas } from "roughjs/bin/canvas";
-import { simplify, Point } from "points-on-curve";
-
-import {
-  newElement,
-  newTextElement,
-  duplicateElement,
-  isInvisiblySmallElement,
-  isTextElement,
-  textWysiwyg,
-  getCommonBounds,
-  getCursorForResizingElement,
-  getPerfectElementSize,
-  getNormalizedDimensions,
-  newLinearElement,
-  transformElements,
-  getElementWithTransformHandleType,
-  getResizeOffsetXY,
-  getResizeArrowDirection,
-  getTransformHandleTypeFromCoords,
-  isNonDeletedElement,
-  updateTextElement,
-  dragSelectedElements,
-  getDragOffsetXY,
-  dragNewElement,
-  hitTest,
-  isHittingElementBoundingBoxWithoutHittingElement,
-  getNonDeletedElements,
-} from "../element";
-import {
-  getElementsWithinSelection,
-  isOverScrollBars,
-  getElementsAtPosition,
-  getElementContainingPosition,
-  getNormalizedZoom,
-  getSelectedElements,
-  isSomeElementSelected,
-  calculateScrollCenter,
-} from "../scene";
-import { loadFromBlob, exportCanvas } from "../data";
-
-import { renderScene } from "../renderer";
-import {
-  AppState,
-  GestureEvent,
-  Gesture,
-  ExcalidrawProps,
-  SceneData,
-} from "../types";
-import {
-  ExcalidrawElement,
-  ExcalidrawTextElement,
-  NonDeleted,
-  ExcalidrawGenericElement,
-  ExcalidrawLinearElement,
-  ExcalidrawBindableElement,
-} from "../element/types";
-
-import { distance2d, isPathALoop, getGridPoint } from "../math";
-
-import {
-  isWritableElement,
-  isInputLike,
-  isToolIcon,
-  debounce,
-  distance,
-  resetCursor,
-  viewportCoordsToSceneCoords,
-  sceneCoordsToViewportCoords,
-  setCursorForShape,
-  tupleToCoors,
-  ResolvablePromise,
-  resolvablePromise,
-  withBatchedUpdates,
-} from "../utils";
-import {
-  KEYS,
-  isArrowKey,
-  getResizeCenterPointKey,
-  getResizeWithSidesSameLengthKey,
-  getRotateWithDiscreteAngleKey,
-  CODES,
-} from "../keys";
-
-import { findShapeByKey } from "../shapes";
-import { createHistory, SceneHistory } from "../history";
-
-import ContextMenu from "./ContextMenu";
-
-import { ActionManager } from "../actions/manager";
+import rough from "roughjs/bin/rough";
 import "../actions";
 import "../actions";
+import { actionDeleteSelected, actionFinalize } from "../actions";
+import { createRedoAction, createUndoAction } from "../actions/actionHistory";
+import { ActionManager } from "../actions/manager";
 import { actions } from "../actions/register";
 import { actions } from "../actions/register";
-
 import { ActionResult } from "../actions/types";
 import { ActionResult } from "../actions/types";
+import {
+  EVENT_DIALOG,
+  EVENT_LIBRARY,
+  EVENT_SHAPE,
+  trackEvent,
+} from "../analytics";
 import { getDefaultAppState } from "../appState";
 import { getDefaultAppState } from "../appState";
-import { t, getLanguage } from "../i18n";
-
+import { renderSpreadsheet } from "../charts";
 import {
 import {
   copyToClipboard,
   copyToClipboard,
   parseClipboard,
   parseClipboard,
   probablySupportsClipboardBlob,
   probablySupportsClipboardBlob,
   probablySupportsClipboardWriteText,
   probablySupportsClipboardWriteText,
 } from "../clipboard";
 } from "../clipboard";
-import { normalizeScroll } from "../scene";
-import { getCenter, getDistance } from "../gesture";
-import { createUndoAction, createRedoAction } from "../actions/actionHistory";
-
 import {
 import {
+  APP_NAME,
+  CANVAS_ONLY_ACTIONS,
   CURSOR_TYPE,
   CURSOR_TYPE,
+  DEFAULT_VERTICAL_ALIGN,
+  DRAGGING_THRESHOLD,
   ELEMENT_SHIFT_TRANSLATE_AMOUNT,
   ELEMENT_SHIFT_TRANSLATE_AMOUNT,
   ELEMENT_TRANSLATE_AMOUNT,
   ELEMENT_TRANSLATE_AMOUNT,
-  POINTER_BUTTON,
-  DRAGGING_THRESHOLD,
-  TEXT_TO_CENTER_SNAP_THRESHOLD,
-  LINE_CONFIRM_THRESHOLD,
-  EVENT,
   ENV,
   ENV,
-  CANVAS_ONLY_ACTIONS,
-  DEFAULT_VERTICAL_ALIGN,
-  GRID_SIZE,
+  EVENT,
+  LINE_CONFIRM_THRESHOLD,
   MIME_TYPES,
   MIME_TYPES,
+  POINTER_BUTTON,
   TAP_TWICE_TIMEOUT,
   TAP_TWICE_TIMEOUT,
+  TEXT_TO_CENTER_SNAP_THRESHOLD,
   TOUCH_CTX_MENU_TIMEOUT,
   TOUCH_CTX_MENU_TIMEOUT,
-  APP_NAME,
 } from "../constants";
 } from "../constants";
-
-import LayerUI from "./LayerUI";
-import { ScrollBars, SceneState } from "../scene/types";
+import { exportCanvas, loadFromBlob } from "../data";
+import { isValidLibrary } from "../data/json";
+import { Library } from "../data/library";
+import { restore } from "../data/restore";
+import {
+  dragNewElement,
+  dragSelectedElements,
+  duplicateElement,
+  getCommonBounds,
+  getCursorForResizingElement,
+  getDragOffsetXY,
+  getElementWithTransformHandleType,
+  getNonDeletedElements,
+  getNormalizedDimensions,
+  getPerfectElementSize,
+  getResizeArrowDirection,
+  getResizeOffsetXY,
+  getTransformHandleTypeFromCoords,
+  hitTest,
+  isHittingElementBoundingBoxWithoutHittingElement,
+  isInvisiblySmallElement,
+  isNonDeletedElement,
+  isTextElement,
+  newElement,
+  newLinearElement,
+  newTextElement,
+  textWysiwyg,
+  transformElements,
+  updateTextElement,
+} from "../element";
+import {
+  bindOrUnbindSelectedElements,
+  fixBindingsAfterDeletion,
+  fixBindingsAfterDuplication,
+  getEligibleElementsForBinding,
+  getHoveredElementForBinding,
+  isBindingEnabled,
+  isLinearElementSimpleAndAlreadyBound,
+  maybeBindLinearElement,
+  shouldEnableBindingForPointerEvent,
+  unbindLinearElements,
+  updateBoundElements,
+} from "../element/binding";
+import { LinearElementEditor } from "../element/linearElementEditor";
 import { mutateElement } from "../element/mutateElement";
 import { mutateElement } from "../element/mutateElement";
-import { invalidateShapeForElement } from "../renderer/renderElement";
+import { deepCopyElement } from "../element/newElement";
+import { MaybeTransformHandleType } from "../element/transformHandles";
 import {
 import {
-  isLinearElement,
-  isLinearElementType,
   isBindingElement,
   isBindingElement,
   isBindingElementType,
   isBindingElementType,
+  isLinearElement,
+  isLinearElementType,
 } from "../element/typeChecks";
 } from "../element/typeChecks";
-import { actionFinalize, actionDeleteSelected } from "../actions";
-
-import { LinearElementEditor } from "../element/linearElementEditor";
 import {
 import {
+  ExcalidrawBindableElement,
+  ExcalidrawElement,
+  ExcalidrawGenericElement,
+  ExcalidrawLinearElement,
+  ExcalidrawTextElement,
+  NonDeleted,
+} from "../element/types";
+import { getCenter, getDistance } from "../gesture";
+import {
+  editGroupForSelectedElement,
+  getElementsInGroup,
+  getSelectedGroupIdForElement,
   getSelectedGroupIds,
   getSelectedGroupIds,
+  isElementInGroup,
   isSelectedViaGroup,
   isSelectedViaGroup,
   selectGroupsForSelectedElements,
   selectGroupsForSelectedElements,
-  isElementInGroup,
-  getSelectedGroupIdForElement,
-  getElementsInGroup,
-  editGroupForSelectedElement,
 } from "../groups";
 } from "../groups";
-import { Library } from "../data/library";
-import Scene from "../scene/Scene";
+import { createHistory, SceneHistory } from "../history";
+import { getLanguage, t } from "../i18n";
 import {
 import {
-  getHoveredElementForBinding,
-  maybeBindLinearElement,
-  getEligibleElementsForBinding,
-  bindOrUnbindSelectedElements,
-  unbindLinearElements,
-  fixBindingsAfterDuplication,
-  fixBindingsAfterDeletion,
-  isLinearElementSimpleAndAlreadyBound,
-  isBindingEnabled,
-  updateBoundElements,
-  shouldEnableBindingForPointerEvent,
-} from "../element/binding";
-import { MaybeTransformHandleType } from "../element/transformHandles";
-import { deepCopyElement } from "../element/newElement";
-import { renderSpreadsheet } from "../charts";
-import { isValidLibrary } from "../data/json";
+  CODES,
+  getResizeCenterPointKey,
+  getResizeWithSidesSameLengthKey,
+  getRotateWithDiscreteAngleKey,
+  isArrowKey,
+  KEYS,
+} from "../keys";
+import { distance2d, getGridPoint, isPathALoop } from "../math";
+import { renderScene } from "../renderer";
+import { invalidateShapeForElement } from "../renderer/renderElement";
+import {
+  calculateScrollCenter,
+  getElementContainingPosition,
+  getElementsAtPosition,
+  getElementsWithinSelection,
+  getNormalizedZoom,
+  getSelectedElements,
+  isOverScrollBars,
+  isSomeElementSelected,
+  normalizeScroll,
+} from "../scene";
+import Scene from "../scene/Scene";
+import { SceneState, ScrollBars } from "../scene/types";
 import { getNewZoom } from "../scene/zoom";
 import { getNewZoom } from "../scene/zoom";
-import { restore } from "../data/restore";
+import { findShapeByKey } from "../shapes";
 import {
 import {
-  EVENT_DIALOG,
-  EVENT_LIBRARY,
-  EVENT_SHAPE,
-  trackEvent,
-} from "../analytics";
+  AppState,
+  ExcalidrawProps,
+  Gesture,
+  GestureEvent,
+  SceneData,
+} from "../types";
+import {
+  debounce,
+  distance,
+  isInputLike,
+  isToolIcon,
+  isWritableElement,
+  resetCursor,
+  ResolvablePromise,
+  resolvablePromise,
+  sceneCoordsToViewportCoords,
+  setCursorForShape,
+  tupleToCoors,
+  viewportCoordsToSceneCoords,
+  withBatchedUpdates,
+} from "../utils";
+import ContextMenu from "./ContextMenu";
+import LayerUI from "./LayerUI";
 import { Stats } from "./Stats";
 import { Stats } from "./Stats";
 
 
 const { history } = createHistory();
 const { history } = createHistory();
@@ -3662,7 +3648,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
             CANVAS_ONLY_ACTIONS.includes(action.name),
             CANVAS_ONLY_ACTIONS.includes(action.name),
           ),
           ),
           {
           {
-            checked: this.state.gridSize !== null,
+            checked: this.state.showGrid,
             shortcutName: "gridMode",
             shortcutName: "gridMode",
             label: t("labels.gridMode"),
             label: t("labels.gridMode"),
             action: this.toggleGridMode,
             action: this.toggleGridMode,

+ 0 - 68
src/components/SlidableInput.tsx

@@ -1,68 +0,0 @@
-import React, { CSSProperties, useEffect, useState } from "react";
-import classes from "./SlidableInput.module.css";
-import { throttle } from "./utils/throttle";
-
-interface SlidableInputProps {
-  value: number;
-  prefix?: string;
-  suffix?: string;
-  minValue?: number;
-  maxValue?: number;
-  style?: CSSProperties;
-  onChange?: (value: number) => void;
-}
-
-export const SlidableInput: React.FC<SlidableInputProps> = ({
-  value,
-  style,
-  prefix,
-  suffix,
-  onChange,
-  minValue,
-  maxValue,
-}) => {
-  const [isLocked, setIsLocked] = useState<boolean>(true);
-  const previousX = React.useRef(0);
-
-  useEffect(() => {
-    const onMouseMoveHandler = throttle((event: MouseEvent) => {
-      if (isLocked) return;
-
-      const nextX = event.screenX;
-      if (nextX === previousX.current) return;
-      const nextValue = value + (nextX > previousX.current ? 1 : -1);
-
-      onChange &&
-        nextValue <= (maxValue || Infinity) &&
-        nextValue >= (typeof minValue === "number" ? minValue : -Infinity) &&
-        onChange(nextValue);
-
-      previousX.current = nextX;
-    }, 250) as EventListenerOrEventListenerObject;
-
-    window.addEventListener("mousemove", onMouseMoveHandler);
-
-    return () => {
-      window.removeEventListener("mousemove", onMouseMoveHandler);
-    };
-    // eslint-disable-next-line react-hooks/exhaustive-deps
-  }, [isLocked, value]);
-
-  const onMouseDown = () => setIsLocked(false);
-
-  useEffect(() => {
-    const onMouseUp = () => setIsLocked(true);
-    window.addEventListener("mouseup", onMouseUp);
-    return () => {
-      window.removeEventListener("mouseup", onMouseUp);
-    };
-  }, []);
-
-  return (
-    <span className={classes.input} style={style} onMouseDown={onMouseDown}>
-      {prefix}
-      {value}
-      {suffix}
-    </span>
-  );
-};

+ 17 - 14
src/components/Stats.tsx

@@ -12,7 +12,6 @@ import { AppState } from "../types";
 import { debounce, nFormatter } from "../utils";
 import { debounce, nFormatter } from "../utils";
 import { close } from "./icons";
 import { close } from "./icons";
 import { Island } from "./Island";
 import { Island } from "./Island";
-import { SlidableInput } from "./SlidableInput";
 import "./Stats.scss";
 import "./Stats.scss";
 
 
 type StorageSizes = { scene: number; total: number };
 type StorageSizes = { scene: number; total: number };
@@ -158,19 +157,23 @@ export const Stats = (props: {
                 </td>
                 </td>
               </tr>
               </tr>
             )}
             )}
-
-            <tr>
-              <th colSpan={2}>{"Misc"}</th>
-            </tr>
-            <tr>
-              <td>{"Grid size"}</td>
-              <td>
-                <SlidableInput
-                  value={props.appState.gridSize || 8}
-                  minValue={8}
-                />
-              </td>
-            </tr>
+            {props.appState.showGrid && (
+              <>
+                <tr>
+                  <th colSpan={2}>{"Misc"}</th>
+                </tr>
+                <tr
+                  onClick={() => {
+                    // TODO: better way to update the gridSize and re-render the scene
+                    props.appState.gridSize =
+                      ((props.appState.gridSize - 5) % 50) + 10;
+                  }}
+                >
+                  <td>{"Grid size"}</td>
+                  <td>{props.appState.gridSize}</td>
+                </tr>
+              </>
+            )}
           </tbody>
           </tbody>
         </table>
         </table>
       </Island>
       </Island>

+ 0 - 14
src/components/utils/throttle.ts

@@ -1,14 +0,0 @@
-export const throttle = (func: Function, limit: number): Function => {
-  let inThrottle: boolean;
-
-  return function (this: any): any {
-    const args = arguments;
-    const context = this;
-
-    if (!inThrottle) {
-      inThrottle = true;
-      func.apply(context, args);
-      setTimeout(() => (inThrottle = false), limit);
-    }
-  };
-};

+ 1 - 1
src/renderer/renderScene.ts

@@ -233,7 +233,7 @@ export const renderScene = (
   context.scale(sceneState.zoom.value, sceneState.zoom.value);
   context.scale(sceneState.zoom.value, sceneState.zoom.value);
 
 
   // Grid
   // Grid
-  if (renderGrid && appState.gridSize) {
+  if (renderGrid && appState.showGrid) {
     strokeGrid(
     strokeGrid(
       context,
       context,
       appState.gridSize,
       appState.gridSize,