aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authoryipstanley <stanley_yip@brown.edu>2019-11-16 16:22:42 -0500
committeryipstanley <stanley_yip@brown.edu>2019-11-16 16:22:42 -0500
commite86c44757770c097392fb17726041a4410c16e74 (patch)
treed7010cab595f3d3b609c91741fce35c42d3176f3 /src
parentd9eb5155734241e5c54353fe53168051fbd32c84 (diff)
fixed some bugs with touch, text document are a little buggy?
Diffstat (limited to 'src')
-rw-r--r--src/client/views/InkingCanvas.scss51
-rw-r--r--src/client/views/InkingCanvas.tsx217
-rw-r--r--src/client/views/collections/CollectionStaffView.tsx4
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx9
-rw-r--r--src/client/views/collections/collectionFreeForm/MarqueeView.tsx1
-rw-r--r--src/client/views/nodes/DocumentView.tsx7
6 files changed, 9 insertions, 280 deletions
diff --git a/src/client/views/InkingCanvas.scss b/src/client/views/InkingCanvas.scss
deleted file mode 100644
index 8f32652ed..000000000
--- a/src/client/views/InkingCanvas.scss
+++ /dev/null
@@ -1,51 +0,0 @@
-@import "globalCssVariables";
-
-.inkingCanvas {
- // opacity: 0.99;
- touch-action: none;
-
- .jsx-parser {
- position: absolute;
- width: 100%;
- height: 100%;
- background: inherit;
- //z-index: -1; // allows annotations to appear on videos when screen is full-size & ...
- }
-}
-
-.inkingCanvas-paths-ink,
-.inkingCanvas-paths-markers,
-.inkingCanvas-noSelect,
-.inkingCanvas-canSelect {
- position: absolute;
- top: 0;
- left: 0;
- width: 8192px;
- height: 8192px;
- cursor: "crosshair";
- pointer-events: all;
-}
-
-.inkingCanvas-canSelect,
-.inkingCanvas-noSelect {
- top: -50000px;
- left: -50000px;
- width: 100000px;
- height: 100000px;
-}
-
-.inkingCanvas-noSelect {
- pointer-events: none;
- cursor: "crosshair";
-}
-
-.inkingCanvas-paths-ink,
-.inkingCanvas-paths-markers {
- pointer-events: none;
- z-index: 10000; // overlays ink on top of everything
- cursor: "arrow";
-}
-
-.inkingCanvas-paths-markers {
- mix-blend-mode: multiply;
-} \ No newline at end of file
diff --git a/src/client/views/InkingCanvas.tsx b/src/client/views/InkingCanvas.tsx
deleted file mode 100644
index e5253c377..000000000
--- a/src/client/views/InkingCanvas.tsx
+++ /dev/null
@@ -1,217 +0,0 @@
-import { action, computed, trace, observable, runInAction } from "mobx";
-import { observer } from "mobx-react";
-import { Utils } from "../../Utils";
-import { Transform } from "../util/Transform";
-import "./InkingCanvas.scss";
-import { InkingControl } from "./InkingControl";
-import { InkingStroke } from "./InkingStroke";
-import React = require("react");
-import { UndoManager } from "../util/UndoManager";
-import { PointData, InkField, InkTool } from "../../new_fields/InkField";
-import { Doc } from "../../new_fields/Doc";
-import { Cast, PromiseValue, NumCast } from "../../new_fields/Types";
-import { Touchable } from "./Touchable";
-import { InteractionUtils } from "../util/InteractionUtils";
-
-interface InkCanvasProps {
- getScreenTransform: () => Transform;
- AnnotationDocument: Doc;
- Document: Doc;
- inkFieldKey: string;
- children: () => JSX.Element[];
-}
-
-@observer
-export class InkingCanvas extends Touchable<InkCanvasProps> {
- maxCanvasDim = 8192 / 2; // 1/2 of the maximum canvas dimension for Chrome
- @observable inkMidX: number = 0;
- @observable inkMidY: number = 0;
- private previousState?: Map<string, PointData>;
- private _currentStrokeId: string = "";
- public static IntersectStrokeRect(stroke: PointData, selRect: { left: number, top: number, width: number, height: number }): boolean {
- return stroke.pathData.reduce((inside: boolean, val) => inside ||
- (selRect.left < val.x && selRect.left + selRect.width > val.x &&
- selRect.top < val.y && selRect.top + selRect.height > val.y)
- , false);
- }
- public static StrokeRect(stroke: PointData): { left: number, top: number, right: number, bottom: number } {
- return stroke.pathData.reduce((bounds: { left: number, top: number, right: number, bottom: number }, val) =>
- ({
- left: Math.min(bounds.left, val.x), top: Math.min(bounds.top, val.y),
- right: Math.max(bounds.right, val.x), bottom: Math.max(bounds.bottom, val.y)
- })
- , { left: Number.MAX_VALUE, top: Number.MAX_VALUE, right: -Number.MAX_VALUE, bottom: -Number.MAX_VALUE });
- }
-
- componentDidMount() {
- PromiseValue(Cast(this.props.AnnotationDocument[this.props.inkFieldKey], InkField)).then(ink => runInAction(() => {
- if (ink) {
- let bounds = Array.from(ink.inkData).reduce(([mix, max, miy, may], [id, strokeData]) =>
- strokeData.pathData.reduce(([mix, max, miy, may], p) =>
- [Math.min(mix, p.x), Math.max(max, p.x), Math.min(miy, p.y), Math.max(may, p.y)],
- [mix, max, miy, may]),
- [Number.MAX_VALUE, Number.MIN_VALUE, Number.MAX_VALUE, Number.MIN_VALUE]);
- this.inkMidX = (bounds[0] + bounds[1]) / 2;
- this.inkMidY = (bounds[2] + bounds[3]) / 2;
- }
- }));
- }
-
- @computed
- get inkData(): Map<string, PointData> {
- let map = Cast(this.props.AnnotationDocument[this.props.inkFieldKey], InkField);
- return !map ? new Map : new Map(map.inkData);
- }
-
- set inkData(value: Map<string, PointData>) {
- this.props.AnnotationDocument[this.props.inkFieldKey] = new InkField(value);
- }
-
- @action
- onPointerDown = (e: React.PointerEvent): void => {
- if (e.button !== 0 || e.altKey || e.ctrlKey || InkingControl.Instance.selectedTool === InkTool.None) {
- return;
- }
-
- document.addEventListener("pointermove", this.onPointerMove, true);
- document.addEventListener("pointerup", this.onPointerUp, true);
- e.stopPropagation();
- e.preventDefault();
-
- this.previousState = new Map(this.inkData);
-
- if (InkingControl.Instance.selectedTool !== InkTool.Eraser && InkingControl.Instance.selectedTool !== InkTool.Scrubber) {
- // start the new line, saves a uuid to represent the field of the stroke
- this._currentStrokeId = Utils.GenerateGuid();
- const data = this.inkData;
- data.set(this._currentStrokeId, {
- pathData: [this.relativeCoordinatesForEvent(e.clientX, e.clientY)],
- color: InkingControl.Instance.selectedColor,
- width: InkingControl.Instance.selectedWidth,
- tool: InkingControl.Instance.selectedTool,
- displayTimecode: NumCast(this.props.Document.currentTimecode, -1),
- creationTime: new Date().getTime()
- });
- this.inkData = data;
- }
- }
-
- @action
- handle1PointerMove = (e: TouchEvent) => {
- e.stopPropagation();
- e.preventDefault();
- let pointer = e.targetTouches.item(0);
- if (pointer) {
- this.handleMove(pointer.clientX, pointer.clientY);
- }
- }
-
- handle2PointersMove = () => { }
-
- @action
- onPointerUp = (e: PointerEvent): void => {
- document.removeEventListener("pointermove", this.onPointerMove, true);
- document.removeEventListener("pointerup", this.onPointerUp, true);
- let coord = this.relativeCoordinatesForEvent(e.clientX, e.clientY);
- if (Math.abs(coord.x - this.inkMidX) > 500 || Math.abs(coord.y - this.inkMidY) > 500) {
- this.inkMidX = coord.x;
- this.inkMidY = coord.y;
- }
- e.stopPropagation();
- e.preventDefault();
-
- const batch = UndoManager.StartBatch("One ink stroke");
- const oldState = this.previousState || new Map;
- this.previousState = undefined;
- const newState = new Map(this.inkData);
- UndoManager.AddEvent({
- undo: () => this.inkData = oldState,
- redo: () => this.inkData = newState
- });
- batch.end();
- }
-
- handleMove = (x: number, y: number) => {
- if (InkingControl.Instance.selectedTool !== InkTool.Eraser && InkingControl.Instance.selectedTool !== InkTool.Scrubber) {
- let data = this.inkData; // add points to new line as it is being drawn
- let strokeData = data.get(this._currentStrokeId);
- if (strokeData) {
- strokeData.pathData.push(this.relativeCoordinatesForEvent(x, y));
- data.set(this._currentStrokeId, strokeData);
- }
- this.inkData = data;
- }
- }
-
- @action
- onPointerMove = (e: PointerEvent): void => {
- if (InteractionUtils.IsType(e, InteractionUtils.TOUCH)) {
- return;
- }
- e.stopPropagation();
- e.preventDefault();
- this.handleMove(e.clientX, e.clientY);
- }
-
- relativeCoordinatesForEvent = (ex: number, ey: number): { x: number, y: number } => {
- let [x, y] = this.props.getScreenTransform().transformPoint(ex, ey);
- return { x, y };
- }
-
- @action
- removeLine = (id: string): void => {
- if (!this.previousState) {
- this.previousState = new Map(this.inkData);
- document.addEventListener("pointermove", this.onPointerMove, true);
- document.addEventListener("pointerup", this.onPointerUp, true);
- }
- let data = this.inkData;
- data.delete(id);
- this.inkData = data;
- }
-
- // @computed
- // get drawnPaths() {
- // let curTimecode = NumCast(this.props.Document.currentTimecode, -1);
- // let paths = Array.from(this.inkData).reduce((paths, [id, strokeData]) => {
- // if (strokeData.displayTimecode === -1 || (Math.abs(Math.round(strokeData.displayTimecode) - Math.round(curTimecode)) < 3)) {
- // paths.push(<InkingStroke key={id} id={id}
- // line={strokeData.pathData}
- // count={strokeData.pathData.length}
- // offsetX={this.maxCanvasDim - this.inkMidX}
- // offsetY={this.maxCanvasDim - this.inkMidY}
- // color={strokeData.color}
- // width={strokeData.width}
- // tool={strokeData.tool}
- // creationTime={strokeData.creationTime}
- // deleteCallback={this.removeLine} />);
- // }
- // return paths;
- // }, [] as JSX.Element[]);
- // let markerPaths = paths.filter(path => path.props.tool === InkTool.Highlighter);
- // let penPaths = paths.filter(path => path.props.tool !== InkTool.Highlighter);
- // return [!penPaths.length ? (null) :
- // <svg className={`inkingCanvas-paths-ink`} key="Pens"
- // style={{ left: `${this.inkMidX - this.maxCanvasDim}px`, top: `${this.inkMidY - this.maxCanvasDim}px` }} >
- // {penPaths}
- // </svg>,
- // !markerPaths.length ? (null) :
- // <svg className={`inkingCanvas-paths-markers`} key="Markers"
- // style={{ left: `${this.inkMidX - this.maxCanvasDim}px`, top: `${this.inkMidY - this.maxCanvasDim}px` }}>
- // {markerPaths}
- // </svg>];
- // }
-
- render() {
- let svgCanvasStyle = InkingControl.Instance.selectedTool !== InkTool.None && !this.props.Document.isBackground ? "canSelect" : "noSelect";
- let cursor = svgCanvasStyle === "canSelect" ? (InkingControl.Instance.selectedTool === InkTool.Eraser ||
- InkingControl.Instance.selectedTool === InkTool.Scrubber ? "pointer" : "default") : undefined;
- return (
- <div className="inkingCanvas">
- <div className={`inkingCanvas-${svgCanvasStyle}`} onPointerDown={this.onPointerDown} onTouchStart={this.onTouchStart} style={{ cursor: cursor }} />
- {this.props.children()}
- {/* {this.drawnPaths} */}
- </div >
- );
- }
-} \ No newline at end of file
diff --git a/src/client/views/collections/CollectionStaffView.tsx b/src/client/views/collections/CollectionStaffView.tsx
index 5b1224b96..eea05ea61 100644
--- a/src/client/views/collections/CollectionStaffView.tsx
+++ b/src/client/views/collections/CollectionStaffView.tsx
@@ -1,5 +1,4 @@
import { CollectionSubView } from "./CollectionSubView";
-import { InkingCanvas } from "../InkingCanvas";
import { Transform } from "../../util/Transform";
import React = require("react")
import { computed, action, IReactionDisposer, reaction, runInAction, observable } from "mobx";
@@ -54,9 +53,6 @@ export class CollectionStaffView extends CollectionSubView(doc => doc) {
render() {
return (
<div className="collectionStaffView" ref={this._mainCont}>
- <InkingCanvas getScreenTransform={this.getTransform} Document={this.props.Document} AnnotationDocument={this.fieldExtensionDoc} inkFieldKey={"ink"} >
- {() => []}
- </InkingCanvas>
{this.staves}
{this.addStaffButton}
</div>
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 61d097c62..c7806a097 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -24,7 +24,6 @@ import { undoBatch, UndoManager } from "../../../util/UndoManager";
import { COLLECTION_BORDER_WIDTH } from "../../../views/globalCssVariables.scss";
import { ContextMenu } from "../../ContextMenu";
import { ContextMenuProps } from "../../ContextMenuItem";
-import { InkingCanvas } from "../../InkingCanvas";
import { CollectionFreeFormDocumentView } from "../../nodes/CollectionFreeFormDocumentView";
import { DocumentViewProps } from "../../nodes/DocumentView";
import { FormattedTextBox } from "../../nodes/FormattedTextBox";
@@ -298,8 +297,10 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
if (this._points.length > 1) {
let B = this.svgBounds;
let points = this._points.map(p => ({ x: p.x - B.left, y: p.y - B.top }));
- let inkDoc = Docs.Create.InkDocument(InkingControl.Instance.selectedColor, InkingControl.Instance.selectedTool, parseInt(InkingControl.Instance.selectedWidth), points, { width: B.width, height: B.height, x: B.left, y: B.top });
- this.addDocument(inkDoc);
+ UndoManager.RunInBatch(() => {
+ let inkDoc = Docs.Create.InkDocument(InkingControl.Instance.selectedColor, InkingControl.Instance.selectedTool, parseInt(InkingControl.Instance.selectedWidth), points, { width: B.width, height: B.height, x: B.left, y: B.top });
+ this.addDocument(inkDoc);
+ }, "addink");
this._points = [];
}
@@ -385,7 +386,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
handle1PointerMove = (e: TouchEvent) => {
// panning a workspace
- if (!e.cancelBubble && this.props.active()) {
+ if (!e.cancelBubble && this.props.active() && !SelectionManager.GetIsDragging()) {
let pt = e.targetTouches.item(0);
if (pt) {
this.pan(pt);
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index b5f6f095e..1066f4f8d 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -13,7 +13,6 @@ import { Docs } from "../../../documents/Documents";
import { SelectionManager } from "../../../util/SelectionManager";
import { Transform } from "../../../util/Transform";
import { undoBatch } from "../../../util/UndoManager";
-import { InkingCanvas } from "../../InkingCanvas";
import { PreviewCursor } from "../../PreviewCursor";
import { CollectionViewType } from "../CollectionView";
import { CollectionFreeFormView } from "./CollectionFreeFormView";
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 5b3eea280..6ffa62fe5 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -41,6 +41,7 @@ import { DocumentContentsView } from "./DocumentContentsView";
import "./DocumentView.scss";
import { FormattedTextBox } from './FormattedTextBox';
import React = require("react");
+import { InteractionUtils } from '../../util/InteractionUtils';
library.add(fa.faEdit, fa.faTrash, fa.faShare, fa.faDownload, fa.faExpandArrowsAlt, fa.faCompressArrowsAlt, fa.faLayerGroup, fa.faExternalLinkAlt, fa.faAlignCenter, fa.faCaretSquareRight,
fa.faSquare, fa.faConciergeBell, fa.faWindowRestore, fa.faFolder, fa.faMapPin, fa.faLink, fa.faFingerprint, fa.faCrosshairs, fa.faDesktop, fa.faUnlock, fa.faLock, fa.faLaptopCode, fa.faMale,
@@ -138,7 +139,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
(Math.abs(e.clientX - this._downX) < Utils.DRAG_THRESHOLD && Math.abs(e.clientY - this._downY) < Utils.DRAG_THRESHOLD)) {
e.stopPropagation();
let preventDefault = true;
- if (this._doubleTap && this.props.renderDepth && !this.onClickHandler?.script) { // disable double-click to show full screen for things that have an on click behavior since clicking them twice can be misinterpreted as a double click
+ if (this._doubleTap && this.props.renderDepth && !this.onClickHandler ?.script) { // disable double-click to show full screen for things that have an on click behavior since clicking them twice can be misinterpreted as a double click
let fullScreenAlias = Doc.MakeAlias(this.props.Document);
if (StrCast(fullScreenAlias.layoutKey) !== "layoutCustom" && fullScreenAlias.layoutCustom !== undefined) {
fullScreenAlias.layoutKey = "layoutCustom";
@@ -216,7 +217,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
}
else if (!e.cancelBubble && (SelectionManager.IsSelected(this) || this.props.parentActive() || this.Document.onDragStart || this.Document.onClick) && !this.Document.lockedPosition && !this.Document.inOverlay) {
if (Math.abs(this._downX - e.clientX) > 3 || Math.abs(this._downY - e.clientY) > 3) {
- if (!e.altKey && (!this.topMost || this.Document.onDragStart || this.Document.onClick) && e.buttons === 1) {
+ if (!e.altKey && (!this.topMost || this.Document.onDragStart || this.Document.onClick) && (e.buttons === 1 || InteractionUtils.IsType(e, InteractionUtils.TOUCH))) {
document.removeEventListener("pointermove", this.onPointerMove);
document.removeEventListener("pointerup", this.onPointerUp);
this.startDragging(this._downX, this._downY, this.Document.dropAction ? this.Document.dropAction as any : e.ctrlKey || e.altKey ? "alias" : undefined, this._hitTemplateDrag);
@@ -354,7 +355,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
@undoBatch
@action
setCustomView = (custom: boolean): void => {
- if (this.props.ContainingCollectionView?.props.DataDoc || this.props.ContainingCollectionView?.props.Document.isTemplateDoc) {
+ if (this.props.ContainingCollectionView ?.props.DataDoc || this.props.ContainingCollectionView ?.props.Document.isTemplateDoc) {
Doc.MakeMetadataFieldTemplate(this.props.Document, this.props.ContainingCollectionView.props.Document);
} else {
custom ? DocumentView.makeCustomViewClicked(this.props.Document, this.props.DataDoc) : DocumentView.makeNativeViewClicked(this.props.Document);