aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStanley Yip <stanley_yip@brown.edu>2019-10-08 18:14:09 -0400
committerStanley Yip <stanley_yip@brown.edu>2019-10-08 18:14:09 -0400
commitb29832a0b75e91f7d53e3820b12d517e6bf3ee94 (patch)
tree6ec887f8207ec00bd8afd5b0a168b72b6e3ca68b
parent5ed2968c5d3e62f06b6355c33d3cb17e9828db26 (diff)
touchable added baseline
-rw-r--r--src/client/util/InteractionUtils.ts2
-rw-r--r--src/client/views/DocComponent.tsx3
-rw-r--r--src/client/views/Touchable.tsx82
-rw-r--r--src/client/views/collections/CollectionBaseView.tsx3
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx122
-rw-r--r--src/client/views/nodes/DocumentView.tsx3
6 files changed, 125 insertions, 90 deletions
diff --git a/src/client/util/InteractionUtils.ts b/src/client/util/InteractionUtils.ts
index f8088825a..63cba4982 100644
--- a/src/client/util/InteractionUtils.ts
+++ b/src/client/util/InteractionUtils.ts
@@ -2,7 +2,7 @@ export namespace InteractionUtils {
export const MOUSE = "mouse";
export const TOUCH = "touch";
- export function IsType(e: PointerEvent, type: PointerTypes): boolean {
+ export function IsType(e: PointerEvent | React.PointerEvent, type: string): boolean {
return e.pointerType === type;
}
diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx
index d6562492f..6d51122d4 100644
--- a/src/client/views/DocComponent.tsx
+++ b/src/client/views/DocComponent.tsx
@@ -1,9 +1,10 @@
import * as React from 'react';
import { Doc } from '../../new_fields/Doc';
import { computed } from 'mobx';
+import { Touchable } from './Touchable';
export function DocComponent<P extends { Document: Doc }, T>(schemaCtor: (doc: Doc) => T) {
- class Component extends React.Component<P> {
+ class Component extends Touchable<P> {
//TODO This might be pretty inefficient if doc isn't observed, because computed doesn't cache then
@computed
get Document(): T {
diff --git a/src/client/views/Touchable.tsx b/src/client/views/Touchable.tsx
new file mode 100644
index 000000000..e9671ab8b
--- /dev/null
+++ b/src/client/views/Touchable.tsx
@@ -0,0 +1,82 @@
+import * as React from 'react';
+import { action } from 'mobx';
+import { InteractionUtils } from '../util/InteractionUtils';
+
+export abstract class Touchable<T> extends React.Component<T> {
+ protected _touchDrag: boolean = false;
+ protected prevPoints: Map<number, React.Touch> = new Map<number, React.Touch>();
+
+ public FirstX: number = 0;
+ public FirstY: number = 0;
+ public SecondX: number = 0;
+ public SecondY: number = 0;
+
+ /**
+ * When a touch even starts, we keep track of each touch that is associated with that event
+ */
+ @action
+ protected onTouchStart = (e: React.TouchEvent): void => {
+ for (let i = 0; i < e.targetTouches.length; i++) {
+ let pt = e.targetTouches.item(i);
+ this.prevPoints.set(pt.identifier, pt);
+ }
+ document.removeEventListener("touchmove", this.onTouch);
+ document.addEventListener("touchmove", this.onTouch);
+ document.removeEventListener("touchend", this.onTouchEnd);
+ document.addEventListener("touchend", this.onTouchEnd);
+ }
+
+ /**
+ * Handle touch move event
+ */
+ @action
+ protected onTouch = (e: TouchEvent): void => {
+ // if we're not actually moving a lot, don't consider it as dragging yet
+ if (!InteractionUtils.IsDragging(this.prevPoints, e.targetTouches, 5) && !this._touchDrag) return;
+ this._touchDrag = true;
+ switch (e.targetTouches.length) {
+ case 1:
+ this.handle1Pointer(e)
+ break;
+ case 2:
+ this.handle2Pointers(e);
+ break;
+ }
+ }
+
+ @action
+ protected onTouchEnd = (e: TouchEvent): void => {
+ this._touchDrag = false;
+ e.stopPropagation();
+
+ // remove all the touches associated with the event
+ for (let i = 0; i < e.targetTouches.length; i++) {
+ let pt = e.targetTouches.item(i);
+ if (pt) {
+ if (this.prevPoints.has(pt.identifier)) {
+ this.prevPoints.delete(pt.identifier);
+ }
+ }
+ }
+
+ if (e.targetTouches.length === 0) {
+ this.prevPoints.clear();
+ }
+ this.cleanUpInteractions();
+ }
+
+ cleanUpInteractions = (): void => {
+ document.removeEventListener("touchmove", this.onTouch);
+ document.removeEventListener("touchend", this.onTouchEnd);
+ }
+
+ handle1Pointer = (e: TouchEvent): any => {
+ e.stopPropagation();
+ e.preventDefault();
+ }
+
+ handle2Pointers = (e: TouchEvent): any => {
+ e.stopPropagation();
+ e.preventDefault();
+ }
+} \ No newline at end of file
diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx
index 38d050e5c..f8988338f 100644
--- a/src/client/views/collections/CollectionBaseView.tsx
+++ b/src/client/views/collections/CollectionBaseView.tsx
@@ -13,6 +13,7 @@ import { FieldViewProps } from '../nodes/FieldView';
import './CollectionBaseView.scss';
import { DateField } from '../../../new_fields/DateField';
import { ImageField } from '../../../new_fields/URLField';
+import { Touchable } from '../Touchable';
export enum CollectionViewType {
Invalid,
@@ -60,7 +61,7 @@ export interface CollectionViewProps extends FieldViewProps {
}
@observer
-export class CollectionBaseView extends React.Component<CollectionViewProps> {
+export class CollectionBaseView extends Touchable<CollectionViewProps> {
@observable private static _safeMode = false;
static InSafeMode() { return this._safeMode; }
static SetSafeMode(safeMode: boolean) { this._safeMode = safeMode; }
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 314ce5cdb..2f9d2606f 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -351,100 +351,50 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
}
}
- private prevPoints: Map<number, React.Touch> = new Map<number, React.Touch>();
- public FirstX: number = 0;
- public FirstY: number = 0;
- public SecondX: number = 0;
- public SecondY: number = 0;
-
- private _touchDrag: boolean = false;
-
- /**
- * When a touch even starts, we keep track of each touch that is associated with that event
- */
- @action
- onTouchStart = (e: React.TouchEvent): void => {
- for (let i = 0; i < e.targetTouches.length; i++) {
- let pt = e.targetTouches.item(i);
- this.prevPoints.set(pt.identifier, pt);
+ handle1Pointer = (e: TouchEvent) => {
+ // panning a workspace
+ if (!e.cancelBubble && this.props.active()) {
+ let pt = e.targetTouches.item(0);
+ if (pt) {
+ this.pan(pt);
+ }
+ e.stopPropagation();
+ e.preventDefault();
}
- document.removeEventListener("touchmove", this.onTouch);
- document.addEventListener("touchmove", this.onTouch);
- document.removeEventListener("touchend", this.onTouchEnd);
- document.addEventListener("touchend", this.onTouchEnd);
}
- /**
- * Handle touch move event
- */
- @action
- onTouch = (e: TouchEvent): void => {
- // if we're not actually moving a lot, don't consider it as dragging yet
- if (!InteractionUtils.IsDragging(this.prevPoints, e.targetTouches, 5) && !this._touchDrag) return;
- this._touchDrag = true;
- switch (e.targetTouches.length) {
- case 1:
- // panning a workspace
- if (!e.cancelBubble && this.props.active()) {
- let pt = e.targetTouches.item(0);
- if (pt) {
- this.pan(pt);
- }
- e.stopPropagation();
- e.preventDefault();
- }
- break;
- case 2:
- // pinch zooming
- if (!e.cancelBubble) {
- let pt1: Touch | null = e.targetTouches.item(0);
- let pt2: Touch | null = e.targetTouches.item(1);
- if (!pt1 || !pt2) return;
-
- if (this.prevPoints.size === 2) {
- let oldPoint1 = this.prevPoints.get(pt1.identifier);
- let oldPoint2 = this.prevPoints.get(pt2.identifier);
- if (oldPoint1 && oldPoint2) {
- let dir = InteractionUtils.Pinching(pt1, pt2, oldPoint1, oldPoint2);
-
- // if zooming, zoom
- if (dir !== 0) {
- let d1 = Math.sqrt(Math.pow(pt1.clientX - oldPoint1.clientX, 2) + Math.pow(pt1.clientY - oldPoint1.clientY, 2));
- let d2 = Math.sqrt(Math.pow(pt2.clientX - oldPoint2.clientX, 2) + Math.pow(pt2.clientY - oldPoint2.clientY, 2));
- let centerX = Math.min(pt1.clientX, pt2.clientX) + Math.abs(pt2.clientX - pt1.clientX) / 2;
- let centerY = Math.min(pt1.clientY, pt2.clientY) + Math.abs(pt2.clientY - pt1.clientY) / 2;
- let delta = dir * (d1 + d2);
- this.zoom(centerX, centerY, delta, 250);
- this.prevPoints.set(pt1.identifier, pt1);
- this.prevPoints.set(pt2.identifier, pt2);
- }
- }
+ handle2Pointers = (e: TouchEvent) => {
+ // pinch zooming
+ if (!e.cancelBubble) {
+ let pt1: Touch | null = e.targetTouches.item(0);
+ let pt2: Touch | null = e.targetTouches.item(1);
+ if (!pt1 || !pt2) return;
+
+ if (this.prevPoints.size === 2) {
+ let oldPoint1 = this.prevPoints.get(pt1.identifier);
+ let oldPoint2 = this.prevPoints.get(pt2.identifier);
+ if (oldPoint1 && oldPoint2) {
+ let dir = InteractionUtils.Pinching(pt1, pt2, oldPoint1, oldPoint2);
+
+ // if zooming, zoom
+ if (dir !== 0) {
+ let d1 = Math.sqrt(Math.pow(pt1.clientX - oldPoint1.clientX, 2) + Math.pow(pt1.clientY - oldPoint1.clientY, 2));
+ let d2 = Math.sqrt(Math.pow(pt2.clientX - oldPoint2.clientX, 2) + Math.pow(pt2.clientY - oldPoint2.clientY, 2));
+ let centerX = Math.min(pt1.clientX, pt2.clientX) + Math.abs(pt2.clientX - pt1.clientX) / 2;
+ let centerY = Math.min(pt1.clientY, pt2.clientY) + Math.abs(pt2.clientY - pt1.clientY) / 2;
+ let delta = dir * (d1 + d2);
+ this.zoom(centerX, centerY, delta, 250);
+ this.prevPoints.set(pt1.identifier, pt1);
+ this.prevPoints.set(pt2.identifier, pt2);
}
}
- e.stopPropagation();
- e.preventDefault();
- break;
- }
- }
-
- @action
- onTouchEnd = (e: TouchEvent): void => {
- this._touchDrag = false;
- e.stopPropagation();
-
- // remove all the touches associated with the event
- for (let i = 0; i < e.targetTouches.length; i++) {
- let pt = e.targetTouches.item(i);
- if (pt) {
- if (this.prevPoints.has(pt.identifier)) {
- this.prevPoints.delete(pt.identifier);
- }
}
}
+ e.stopPropagation();
+ e.preventDefault();
+ }
- if (e.targetTouches.length === 0) {
- this.prevPoints.clear();
- }
+ cleanUpInteractions = () => {
document.removeEventListener("pointermove", this.onPointerMove);
document.removeEventListener("pointerup", this.onPointerUp);
document.removeEventListener("touchmove", this.onTouch);
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 6627b8792..bf90e2d08 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -611,8 +611,9 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
DataDoc={this.props.DataDoc} />);
}
- onTouchStart = (e: React.TouchEvent) => {
+ handle1Pointer = (e: TouchEvent) => {
e.stopPropagation();
+ e.preventDefault();
}
render() {