瀏覽代碼

Feature: Hint viewer (#666)

* Add Hint viewer

- Add hints for arrows and lines
- Add hints for resizing elements

* Swap priority of multi mode and resize mode in Hint Viewer

* Remove dangling locales from public

* Add shortcut to hide hints

* Change hint texts and show resize hint ONLY during resizing

* Remove hints toggling
Gasim Gasimzada 5 年之前
父節點
當前提交
f70bd0081c
共有 6 個文件被更改,包括 78 次插入0 次删除
  1. 1 0
      src/appState.ts
  2. 6 0
      src/components/HintViewer.css
  3. 55 0
      src/components/HintViewer.tsx
  4. 10 0
      src/index.tsx
  5. 5 0
      src/locales/en.json
  6. 1 0
      src/types.ts

+ 1 - 0
src/appState.ts

@@ -26,6 +26,7 @@ export function getDefaultAppState(): AppState {
     cursorY: 0,
     scrolledOutside: false,
     name: DEFAULT_PROJECT_NAME,
+    isResizing: false,
   };
 }
 

+ 6 - 0
src/components/HintViewer.css

@@ -0,0 +1,6 @@
+.HintViewer {
+  position: absolute;
+  left: 0.5em;
+  bottom: 0.5em;
+  font-size: 0.8rem;
+}

+ 55 - 0
src/components/HintViewer.tsx

@@ -0,0 +1,55 @@
+import React from "react";
+import { t } from "../i18n";
+import { ExcalidrawElement } from "../element/types";
+
+import "./HintViewer.css";
+
+interface Hint {
+  elementType: string;
+  multiMode: boolean;
+  isResizing: boolean;
+  elements: readonly ExcalidrawElement[];
+}
+
+const getHints = ({ elementType, multiMode, isResizing, elements }: Hint) => {
+  if (elementType === "arrow" || elementType === "line") {
+    if (!multiMode) {
+      return t("hints.linearElement");
+    }
+    return t("hints.linearElementMulti");
+  }
+
+  if (isResizing) {
+    const selectedElements = elements.filter(el => el.isSelected);
+    if (
+      selectedElements.length === 1 &&
+      (selectedElements[0].type === "arrow" ||
+        selectedElements[0].type === "line") &&
+      selectedElements[0].points.length > 2
+    ) {
+      return null;
+    }
+    return t("hints.resize");
+  }
+
+  return null;
+};
+
+export const HintViewer = ({
+  elementType,
+  multiMode,
+  isResizing,
+  elements,
+}: Hint) => {
+  const hint = getHints({
+    elementType,
+    multiMode,
+    isResizing,
+    elements,
+  });
+  if (!hint) {
+    return null;
+  }
+
+  return <div className="HintViewer">{hint}</div>;
+};

+ 10 - 0
src/index.tsx

@@ -99,6 +99,7 @@ import { LanguageList } from "./components/LanguageList";
 import { Point } from "roughjs/bin/geometry";
 import { t, languages, setLanguage, getLanguage } from "./i18n";
 import { StoredScenesList } from "./components/StoredScenesList";
+import { HintViewer } from "./components/HintViewer";
 
 let { elements } = createScene();
 const { history } = createHistory();
@@ -1186,6 +1187,7 @@ export class App extends React.Component<any, AppState> {
                 }
 
                 if (isResizingElements && this.state.resizingElement) {
+                  this.setState({ isResizing: true });
                   const el = this.state.resizingElement;
                   const selectedElements = elements.filter(el => el.isSelected);
                   if (selectedElements.length === 1) {
@@ -1541,6 +1543,7 @@ export class App extends React.Component<any, AppState> {
               };
 
               const onMouseUp = (e: MouseEvent) => {
+                this.setState({ isResizing: false });
                 const {
                   draggingElement,
                   resizingElement,
@@ -1805,6 +1808,13 @@ export class App extends React.Component<any, AppState> {
           </canvas>
         </main>
         <footer role="contentinfo">
+          <HintViewer
+            elementType={this.state.elementType}
+            multiMode={this.state.multiElement !== null}
+            isResizing={this.state.isResizing}
+            elements={elements}
+          />
+
           <LanguageList
             onChange={lng => {
               setLanguage(lng);

+ 5 - 0
src/locales/en.json

@@ -77,5 +77,10 @@
     "canvasActions": "Canvas actions",
     "selectedShapeActions": "Selected shape actions",
     "shapes": "Shapes"
+  },
+  "hints": {
+    "linearElement": "Click to start multiple points, drag for single line",
+    "linearElementMulti": "Press Escape or Enter to finish",
+    "resize": "You can constraint proportions by holding SHIFT while resizing"
   }
 }

+ 1 - 0
src/types.ts

@@ -25,4 +25,5 @@ export type AppState = {
   scrolledOutside: boolean;
   name: string;
   selectedId?: string;
+  isResizing: boolean;
 };