From 3cca58612cde96a3082ca8e190fe2166d531d556 Mon Sep 17 00:00:00 2001 From: Fawn Date: Tue, 14 Jan 2020 17:40:50 -0500 Subject: drawn strokes get added to mobile ink collection --- src/mobile/MobileInterface.scss | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 src/mobile/MobileInterface.scss (limited to 'src/mobile/MobileInterface.scss') diff --git a/src/mobile/MobileInterface.scss b/src/mobile/MobileInterface.scss new file mode 100644 index 000000000..e4cc919a5 --- /dev/null +++ b/src/mobile/MobileInterface.scss @@ -0,0 +1,7 @@ +.mobileInterface-topButtons { + position: absolute; + display: flex; + justify-content: space-between; + width: 100%; + z-index: 9999; +} \ No newline at end of file -- cgit v1.2.3-70-g09d2 From ecf0f5b8f426db9e66c05e759f61294811b15fca Mon Sep 17 00:00:00 2001 From: vellichora Date: Sat, 1 Feb 2020 14:56:19 -0500 Subject: mobile ink overlay is draggable from desktop --- src/client/DocServer.ts | 19 ++- src/client/util/InteractionUtils.ts | 165 ------------------- src/client/util/InteractionUtils.tsx | 182 +++++++++++++++++++++ src/client/views/GestureOverlay.scss | 4 - src/client/views/GestureOverlay.tsx | 25 +-- src/client/views/InkingStroke.tsx | 17 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 1 - src/client/views/nodes/DocumentView.tsx | 1 + src/mobile/MobileInkOverlay.scss | 38 +++++ src/mobile/MobileInkOverlay.tsx | 91 +++++++++-- src/mobile/MobileInterface.scss | 2 +- src/mobile/MobileInterface.tsx | 90 ++++++---- src/server/Message.ts | 14 +- src/server/Websocket/Websocket.ts | 8 +- 14 files changed, 393 insertions(+), 264 deletions(-) delete mode 100644 src/client/util/InteractionUtils.ts create mode 100644 src/client/util/InteractionUtils.tsx create mode 100644 src/mobile/MobileInkOverlay.scss (limited to 'src/mobile/MobileInterface.scss') diff --git a/src/client/DocServer.ts b/src/client/DocServer.ts index a1cb42df2..b20cd3521 100644 --- a/src/client/DocServer.ts +++ b/src/client/DocServer.ts @@ -1,5 +1,5 @@ import * as OpenSocket from 'socket.io-client'; -import { MessageStore, YoutubeQueryTypes, GestureContent, MobileInkBoxContent } from "./../server/Message"; +import { MessageStore, YoutubeQueryTypes, GestureContent, MobileInkOverlayContent, UpdateMobileInkOverlayPosition } from "./../server/Message"; import { Opt, Doc } from '../new_fields/Doc'; import { Utils, emptyFunction } from '../Utils'; import { SerializationHelper } from './util/SerializationHelper'; @@ -72,9 +72,13 @@ export namespace DocServer { Utils.Emit(_socket, MessageStore.GesturePoints, content); } - export function dispatchBoxTrigger(content: MobileInkBoxContent) { + export function dispatchOverlayTrigger(content: MobileInkOverlayContent) { // _socket.emit("dispatchBoxTrigger"); - Utils.Emit(_socket, MessageStore.MobileInkBoxTrigger, content); + Utils.Emit(_socket, MessageStore.MobileInkOverlayTrigger, content); + } + + export function dispatchOverlayPositionUpdate(content: UpdateMobileInkOverlayPosition) { + Utils.Emit(_socket, MessageStore.UpdateMobileInkOverlayPosition, content); } } @@ -100,13 +104,18 @@ export namespace DocServer { Utils.AddServerHandler(_socket, MessageStore.ConnectionTerminated, () => { alert("Your connection to the server has been terminated."); }); + + // mobile ink overlay socket events to communicate between mobile view and desktop view _socket.addEventListener("receiveGesturePoints", (content: GestureContent) => { MobileInkOverlay.Instance.drawStroke(content); }); - _socket.addEventListener("receiveBoxTrigger", (content: MobileInkBoxContent) => { - GestureOverlay.Instance.enableMobileInkBox(content); + _socket.addEventListener("receiveOverlayTrigger", (content: MobileInkOverlayContent) => { + GestureOverlay.Instance.enableMobileInkOverlay(content); MobileInkOverlay.Instance.initMobileInkOverlay(content); }); + _socket.addEventListener("updateMobileOverlayPosition", (content: UpdateMobileInkOverlayPosition) => { + MobileInkOverlay.Instance.updatePosition(content); + }); } function errorFunc(): never { diff --git a/src/client/util/InteractionUtils.ts b/src/client/util/InteractionUtils.ts deleted file mode 100644 index 76b43da3c..000000000 --- a/src/client/util/InteractionUtils.ts +++ /dev/null @@ -1,165 +0,0 @@ -export namespace InteractionUtils { - export const MOUSETYPE = "mouse"; - export const TOUCHTYPE = "touch"; - export const PENTYPE = "pen"; - export const ERASERTYPE = "eraser"; - - const POINTER_PEN_BUTTON = -1; - const REACT_POINTER_PEN_BUTTON = 0; - const ERASER_BUTTON = 5; - - export function GetMyTargetTouches(e: TouchEvent | React.TouchEvent, prevPoints: Map, ignorePen: boolean): React.Touch[] { - const myTouches = new Array(); - for (let i = 0; i < e.targetTouches.length; i++) { - const pt: any = e.targetTouches.item(i); - if (pt && prevPoints.has(pt.identifier)) { - if (ignorePen || (pt.radiusX > 1 && pt.radiusY > 1)) { - myTouches.push(pt); - } - } - } - return myTouches; - } - - export function IsType(e: PointerEvent | React.PointerEvent, type: string): boolean { - switch (type) { - // pen and eraser are both pointer type 'pen', but pen is button 0 and eraser is button 5. -syip2 - case PENTYPE: - return e.pointerType === PENTYPE && (e.button === -1 || e.button === 0); - case ERASERTYPE: - return e.pointerType === PENTYPE && e.button === (e instanceof PointerEvent ? ERASER_BUTTON : ERASER_BUTTON); - default: - return e.pointerType === type; - } - } - - export function TwoPointEuclidist(pt1: React.Touch, pt2: React.Touch): number { - return Math.sqrt(Math.pow(pt1.clientX - pt2.clientX, 2) + Math.pow(pt1.clientY - pt2.clientY, 2)); - } - - /** - * Returns the centroid of an n-arbitrary long list of points (takes the average the x and y components of each point) - * @param pts - n-arbitrary long list of points - */ - export function CenterPoint(pts: React.Touch[]): { X: number, Y: number } { - const centerX = pts.map(pt => pt.clientX).reduce((a, b) => a + b, 0) / pts.length; - const centerY = pts.map(pt => pt.clientY).reduce((a, b) => a + b, 0) / pts.length; - return { X: centerX, Y: centerY }; - } - - /** - * Returns -1 if pinching out, 0 if not pinching, and 1 if pinching in - * @param pt1 - new point that corresponds to oldPoint1 - * @param pt2 - new point that corresponds to oldPoint2 - * @param oldPoint1 - previous point 1 - * @param oldPoint2 - previous point 2 - */ - export function Pinching(pt1: React.Touch, pt2: React.Touch, oldPoint1: React.Touch, oldPoint2: React.Touch): number { - const threshold = 4; - const oldDist = TwoPointEuclidist(oldPoint1, oldPoint2); - const newDist = TwoPointEuclidist(pt1, pt2); - - /** if they have the same sign, then we are either pinching in or out. - * threshold it by 10 (it has to be pinching by at least threshold to be a valid pinch) - * so that it can still pan without freaking out - */ - if (Math.sign(oldDist) === Math.sign(newDist) && Math.abs(oldDist - newDist) > threshold) { - return Math.sign(oldDist - newDist); - } - return 0; - } - - /** - * Returns -1 if pinning and pinching out, 0 if not pinning, and 1 if pinching in - * @param pt1 - new point that corresponds to oldPoint1 - * @param pt2 - new point that corresponds to oldPoint2 - * @param oldPoint1 - previous point 1 - * @param oldPoint2 - previous point 2 - */ - export function Pinning(pt1: React.Touch, pt2: React.Touch, oldPoint1: React.Touch, oldPoint2: React.Touch): number { - const threshold = 4; - - const pt1Dist = TwoPointEuclidist(oldPoint1, pt1); - const pt2Dist = TwoPointEuclidist(oldPoint2, pt2); - - const pinching = Pinching(pt1, pt2, oldPoint1, oldPoint2); - - if (pinching !== 0) { - if ((pt1Dist < threshold && pt2Dist > threshold) || (pt1Dist > threshold && pt2Dist < threshold)) { - return pinching; - } - } - return 0; - } - - export function IsDragging(oldTouches: Map, newTouches: React.Touch[], leniency: number): boolean { - for (const touch of newTouches) { - if (touch) { - const oldTouch = oldTouches.get(touch.identifier); - if (oldTouch) { - if (TwoPointEuclidist(touch, oldTouch) >= leniency) { - return true; - } - } - } - } - return false; - } - - // These might not be very useful anymore, but I'll leave them here for now -syip2 - { - - - /** - * Returns the type of Touch Interaction from a list of points. - * Also returns any data that is associated with a Touch Interaction - * @param pts - List of points - */ - // export function InterpretPointers(pts: React.Touch[]): { type: Opt, data?: any } { - // const leniency = 200; - // switch (pts.length) { - // case 1: - // return { type: OneFinger }; - // case 2: - // return { type: TwoSeperateFingers }; - // case 3: - // let pt1 = pts[0]; - // let pt2 = pts[1]; - // let pt3 = pts[2]; - // if (pt1 && pt2 && pt3) { - // let dist12 = TwoPointEuclidist(pt1, pt2); - // let dist23 = TwoPointEuclidist(pt2, pt3); - // let dist13 = TwoPointEuclidist(pt1, pt3); - // console.log(`distances: ${dist12}, ${dist23}, ${dist13}`); - // let dist12close = dist12 < leniency; - // let dist23close = dist23 < leniency; - // let dist13close = dist13 < leniency; - // let xor2313 = dist23close ? !dist13close : dist13close; - // let xor = dist12close ? !xor2313 : xor2313; - // // three input xor because javascript doesn't have logical xor's - // if (xor) { - // let points: number[] = []; - // let min = Math.min(dist12, dist23, dist13); - // switch (min) { - // case dist12: - // points = [0, 1, 2]; - // break; - // case dist23: - // points = [1, 2, 0]; - // break; - // case dist13: - // points = [0, 2, 1]; - // break; - // } - // return { type: TwoToOneFingers, data: points }; - // } - // else { - // return { type: ThreeSeperateFingers, data: null }; - // } - // } - // default: - // return { type: undefined }; - // } - // } - } -} \ No newline at end of file diff --git a/src/client/util/InteractionUtils.tsx b/src/client/util/InteractionUtils.tsx new file mode 100644 index 000000000..34c7cfa74 --- /dev/null +++ b/src/client/util/InteractionUtils.tsx @@ -0,0 +1,182 @@ +import React = require("react"); + +export namespace InteractionUtils { + export const MOUSETYPE = "mouse"; + export const TOUCHTYPE = "touch"; + export const PENTYPE = "pen"; + export const ERASERTYPE = "eraser"; + + const POINTER_PEN_BUTTON = -1; + const REACT_POINTER_PEN_BUTTON = 0; + const ERASER_BUTTON = 5; + + export function GetMyTargetTouches(e: TouchEvent | React.TouchEvent, prevPoints: Map, ignorePen: boolean): React.Touch[] { + const myTouches = new Array(); + for (let i = 0; i < e.targetTouches.length; i++) { + const pt: any = e.targetTouches.item(i); + if (pt && prevPoints.has(pt.identifier)) { + if (ignorePen || (pt.radiusX > 1 && pt.radiusY > 1)) { + myTouches.push(pt); + } + } + } + return myTouches; + } + + // TODO: find a way to reference this function from InkingStroke instead of copy pastign here. copied bc of weird error when on mobile view + export function CreatePolyline(points: { X: number, Y: number }[], left: number, top: number, color: string, width: number) { + const pts = points.reduce((acc: string, pt: { X: number, Y: number }) => acc + `${pt.X - left},${pt.Y - top} `, ""); + return ( + + ); + } + + export function IsType(e: PointerEvent | React.PointerEvent, type: string): boolean { + switch (type) { + // pen and eraser are both pointer type 'pen', but pen is button 0 and eraser is button 5. -syip2 + case PENTYPE: + return e.pointerType === PENTYPE && (e.button === -1 || e.button === 0); + case ERASERTYPE: + return e.pointerType === PENTYPE && e.button === (e instanceof PointerEvent ? ERASER_BUTTON : ERASER_BUTTON); + default: + return e.pointerType === type; + } + } + + export function TwoPointEuclidist(pt1: React.Touch, pt2: React.Touch): number { + return Math.sqrt(Math.pow(pt1.clientX - pt2.clientX, 2) + Math.pow(pt1.clientY - pt2.clientY, 2)); + } + + /** + * Returns the centroid of an n-arbitrary long list of points (takes the average the x and y components of each point) + * @param pts - n-arbitrary long list of points + */ + export function CenterPoint(pts: React.Touch[]): { X: number, Y: number } { + const centerX = pts.map(pt => pt.clientX).reduce((a, b) => a + b, 0) / pts.length; + const centerY = pts.map(pt => pt.clientY).reduce((a, b) => a + b, 0) / pts.length; + return { X: centerX, Y: centerY }; + } + + /** + * Returns -1 if pinching out, 0 if not pinching, and 1 if pinching in + * @param pt1 - new point that corresponds to oldPoint1 + * @param pt2 - new point that corresponds to oldPoint2 + * @param oldPoint1 - previous point 1 + * @param oldPoint2 - previous point 2 + */ + export function Pinching(pt1: React.Touch, pt2: React.Touch, oldPoint1: React.Touch, oldPoint2: React.Touch): number { + const threshold = 4; + const oldDist = TwoPointEuclidist(oldPoint1, oldPoint2); + const newDist = TwoPointEuclidist(pt1, pt2); + + /** if they have the same sign, then we are either pinching in or out. + * threshold it by 10 (it has to be pinching by at least threshold to be a valid pinch) + * so that it can still pan without freaking out + */ + if (Math.sign(oldDist) === Math.sign(newDist) && Math.abs(oldDist - newDist) > threshold) { + return Math.sign(oldDist - newDist); + } + return 0; + } + + /** + * Returns -1 if pinning and pinching out, 0 if not pinning, and 1 if pinching in + * @param pt1 - new point that corresponds to oldPoint1 + * @param pt2 - new point that corresponds to oldPoint2 + * @param oldPoint1 - previous point 1 + * @param oldPoint2 - previous point 2 + */ + export function Pinning(pt1: React.Touch, pt2: React.Touch, oldPoint1: React.Touch, oldPoint2: React.Touch): number { + const threshold = 4; + + const pt1Dist = TwoPointEuclidist(oldPoint1, pt1); + const pt2Dist = TwoPointEuclidist(oldPoint2, pt2); + + const pinching = Pinching(pt1, pt2, oldPoint1, oldPoint2); + + if (pinching !== 0) { + if ((pt1Dist < threshold && pt2Dist > threshold) || (pt1Dist > threshold && pt2Dist < threshold)) { + return pinching; + } + } + return 0; + } + + export function IsDragging(oldTouches: Map, newTouches: React.Touch[], leniency: number): boolean { + for (const touch of newTouches) { + if (touch) { + const oldTouch = oldTouches.get(touch.identifier); + if (oldTouch) { + if (TwoPointEuclidist(touch, oldTouch) >= leniency) { + return true; + } + } + } + } + return false; + } + + // These might not be very useful anymore, but I'll leave them here for now -syip2 + { + + + /** + * Returns the type of Touch Interaction from a list of points. + * Also returns any data that is associated with a Touch Interaction + * @param pts - List of points + */ + // export function InterpretPointers(pts: React.Touch[]): { type: Opt, data?: any } { + // const leniency = 200; + // switch (pts.length) { + // case 1: + // return { type: OneFinger }; + // case 2: + // return { type: TwoSeperateFingers }; + // case 3: + // let pt1 = pts[0]; + // let pt2 = pts[1]; + // let pt3 = pts[2]; + // if (pt1 && pt2 && pt3) { + // let dist12 = TwoPointEuclidist(pt1, pt2); + // let dist23 = TwoPointEuclidist(pt2, pt3); + // let dist13 = TwoPointEuclidist(pt1, pt3); + // console.log(`distances: ${dist12}, ${dist23}, ${dist13}`); + // let dist12close = dist12 < leniency; + // let dist23close = dist23 < leniency; + // let dist13close = dist13 < leniency; + // let xor2313 = dist23close ? !dist13close : dist13close; + // let xor = dist12close ? !xor2313 : xor2313; + // // three input xor because javascript doesn't have logical xor's + // if (xor) { + // let points: number[] = []; + // let min = Math.min(dist12, dist23, dist13); + // switch (min) { + // case dist12: + // points = [0, 1, 2]; + // break; + // case dist23: + // points = [1, 2, 0]; + // break; + // case dist13: + // points = [0, 2, 1]; + // break; + // } + // return { type: TwoToOneFingers, data: points }; + // } + // else { + // return { type: ThreeSeperateFingers, data: null }; + // } + // } + // default: + // return { type: undefined }; + // } + // } + } +} \ No newline at end of file diff --git a/src/client/views/GestureOverlay.scss b/src/client/views/GestureOverlay.scss index 2996b7073..31601efd4 100644 --- a/src/client/views/GestureOverlay.scss +++ b/src/client/views/GestureOverlay.scss @@ -5,8 +5,4 @@ top: 0; left: 0; touch-action: none; -} - -.mobileInkOverlay { - border: 5px dashed red; } \ No newline at end of file diff --git a/src/client/views/GestureOverlay.tsx b/src/client/views/GestureOverlay.tsx index 81284b543..a01a86b53 100644 --- a/src/client/views/GestureOverlay.tsx +++ b/src/client/views/GestureOverlay.tsx @@ -19,7 +19,7 @@ import Palette from "./Palette"; import MobileInterface from "../../mobile/MobileInterface"; import { MainView } from "./MainView"; import { DocServer } from "../DocServer"; -import { GestureContent, MobileInkBoxContent } from "../../server/Message"; +import { GestureContent, MobileInkOverlayContent } from "../../server/Message"; import { Point } from "../northstar/model/idea/idea"; import MobileInkOverlay from "../../mobile/MobileInkOverlay"; @@ -217,21 +217,6 @@ export default class GestureOverlay extends Touchable { return { right: right, left: left, bottom: bottom, top: top, width: right - left, height: bottom - top }; } - // TODO: find a way to reference this function from InkingStroke instead of copy pastign here. copied bc of weird error when on mobile view - CreatePolyline(points: { X: number, Y: number }[], left: number, top: number, color?: string, width?: number) { - const pts = points.reduce((acc: string, pt: { X: number, Y: number }) => acc + `${pt.X - left},${pt.Y - top} `, ""); - return ( - - ); - } - @computed get currentStroke() { if (this._points.length <= 1) { return (null); @@ -241,23 +226,23 @@ export default class GestureOverlay extends Touchable { return ( - {this.CreatePolyline(this._points, B.left, B.top, this.Color, this.Width)} + {InteractionUtils.CreatePolyline(this._points, B.left, B.top, this.Color, this.Width)} ); } @action - enableMobileInkBox = (content: MobileInkBoxContent) => { - this.showMobileInkOverlay = content.enableBox; + enableMobileInkOverlay = (content: MobileInkOverlayContent) => { + this.showMobileInkOverlay = content.enableOverlay; } render() { return (
+ {this.showMobileInkOverlay ? : <>} {this.currentStroke} {this.props.children} {this._palette} - {this.showMobileInkOverlay ? : <>}
); } } diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx index 8b346d5d9..aca507147 100644 --- a/src/client/views/InkingStroke.tsx +++ b/src/client/views/InkingStroke.tsx @@ -10,24 +10,11 @@ import "./InkingStroke.scss"; import { FieldView, FieldViewProps } from "./nodes/FieldView"; import React = require("react"); import { TraceMobx } from "../../new_fields/util"; +import { InteractionUtils } from "../util/InteractionUtils"; type InkDocument = makeInterface<[typeof documentSchema]>; const InkDocument = makeInterface(documentSchema); -export function CreatePolyline(points: { X: number, Y: number }[], left: number, top: number, color?: string, width?: number) { - const pts = points.reduce((acc: string, pt: { X: number, Y: number }) => acc + `${pt.X - left},${pt.Y - top} `, ""); - return ( - - ); -} - @observer export class InkingStroke extends DocExtendableComponent(InkDocument) { public static LayoutString(fieldStr: string) { return FieldView.LayoutString(InkingStroke, fieldStr); } @@ -44,7 +31,7 @@ export class InkingStroke extends DocExtendableComponent(Docu if (!(InteractionUtils.IsType(e, InteractionUtils.MOUSETYPE) || InkingControl.Instance.selectedTool === InkTool.Highlighter || InkingControl.Instance.selectedTool === InkTool.Pen)) { if (!InteractionUtils.IsType(e, InteractionUtils.PENTYPE)) { e.stopPropagation(); + // TODO: check here for panning/inking } return; } diff --git a/src/mobile/MobileInkOverlay.scss b/src/mobile/MobileInkOverlay.scss new file mode 100644 index 000000000..2e45d0441 --- /dev/null +++ b/src/mobile/MobileInkOverlay.scss @@ -0,0 +1,38 @@ +.mobileInkOverlay { + border: 5px dashed red; +} + +.mobileInkOverlay-border { + background-color: rgba(0, 255, 0, .4); + position: absolute; + pointer-events: auto; + cursor: pointer; + + &.top { + width: calc(100% + 20px); + height: 10px; + top: -10px; + left: -10px; + } + + &.left { + width: 10px; + height: calc(100% + 20px); + top: -10px; + left: -10px; + } + + &.right { + width: 10px; + height: calc(100% + 20px); + top: -10px; + right: -10px; + } + + &.bottom { + width: calc(100% + 20px); + height: 10px; + bottom: -10px; + left: -10px; + } +} \ No newline at end of file diff --git a/src/mobile/MobileInkOverlay.tsx b/src/mobile/MobileInkOverlay.tsx index 71dd20c51..5efc7b83a 100644 --- a/src/mobile/MobileInkOverlay.tsx +++ b/src/mobile/MobileInkOverlay.tsx @@ -1,8 +1,9 @@ import React = require('react'); import { observer } from "mobx-react"; -import { MobileInkBoxContent, GestureContent } from "../server/Message"; +import { MobileInkOverlayContent, GestureContent, UpdateMobileInkOverlayPosition } from "../server/Message"; import { observable, action } from "mobx"; import { GestureUtils } from "../pen-gestures/GestureUtils"; +import "./MobileInkOverlay.scss"; @observer @@ -15,6 +16,11 @@ export default class MobileInkOverlay extends React.Component { @observable private _x: number = -300; @observable private _y: number = -300; + @observable private _offsetX: number = 0; + @observable private _offsetY: number = 0; + @observable private _isDragging: boolean = false; + private _mainCont: React.RefObject = React.createRef(); + constructor(props: Readonly<{}>) { super(props); MobileInkOverlay.Instance = this; @@ -28,18 +34,27 @@ export default class MobileInkOverlay extends React.Component { } @action - initMobileInkOverlay(content: MobileInkBoxContent) { + initMobileInkOverlay(content: MobileInkOverlayContent) { const { width, height } = content; const scaledSize = this.initialSize(width ? width : 0, height ? height : 0); - this._width = scaledSize.width; - this._height = scaledSize.height; - this._scale = scaledSize.scale; + this._width = scaledSize.width * .5; + this._height = scaledSize.height * .5; + this._scale = .5; //scaledSize.scale; this._x = 300; // TODO: center on screen this._y = 25; // TODO: center on screen } + @action + updatePosition(content: UpdateMobileInkOverlayPosition) { + const { dx, dy, dsize } = content; + console.log(dx, dy, dsize); + } + drawStroke = (content: GestureContent) => { + // TODO: figure out why strokes drawn in corner of mobile interface dont get inserted + const { points, bounds } = content; + console.log("received points", points, bounds); const B = { right: (bounds.right * this._scale) + this._x, @@ -65,16 +80,66 @@ export default class MobileInkOverlay extends React.Component { ); } + @action + dragStart = (e: React.PointerEvent) => { + console.log("pointer down"); + document.removeEventListener("pointermove", this.dragging); + document.removeEventListener("pointerup", this.dragEnd); + document.addEventListener("pointermove", this.dragging); + document.addEventListener("pointerup", this.dragEnd); + + this._isDragging = true; + this._offsetX = e.pageX - this._mainCont.current!.getBoundingClientRect().left; + this._offsetY = e.pageY - this._mainCont.current!.getBoundingClientRect().top; + + e.preventDefault(); + e.stopPropagation(); + } + + @action + dragging = (e: PointerEvent) => { + const x = e.pageX - this._offsetX; + const y = e.pageY - this._offsetY; + + // TODO: don't allow drag over library? + this._x = Math.min(Math.max(x, 0), window.innerWidth - this._width); + this._y = Math.min(Math.max(y, 0), window.innerHeight - this._height); + + e.preventDefault(); + e.stopPropagation(); + } + + @action + dragEnd = (e: PointerEvent) => { + document.removeEventListener("pointermove", this.dragging); + document.removeEventListener("pointerup", this.dragEnd); + + this._isDragging = false; + + e.preventDefault(); + e.stopPropagation(); + } + render() { + return ( -
+
+
+
+
+
+
); } } \ No newline at end of file diff --git a/src/mobile/MobileInterface.scss b/src/mobile/MobileInterface.scss index e4cc919a5..8abe5a40d 100644 --- a/src/mobile/MobileInterface.scss +++ b/src/mobile/MobileInterface.scss @@ -1,4 +1,4 @@ -.mobileInterface-topButtons { +.mobileInterface-inkInterfaceButtons { position: absolute; display: flex; justify-content: space-between; diff --git a/src/mobile/MobileInterface.tsx b/src/mobile/MobileInterface.tsx index 4840ea374..b191b3afb 100644 --- a/src/mobile/MobileInterface.tsx +++ b/src/mobile/MobileInterface.tsx @@ -10,7 +10,7 @@ import { DocumentView } from '../client/views/nodes/DocumentView'; import { emptyPath, emptyFunction, returnFalse, returnOne, returnEmptyString, returnTrue } from '../Utils'; import { Transform } from '../client/util/Transform'; import { library } from '@fortawesome/fontawesome-svg-core'; -import { faPenNib, faHighlighter, faEraser, faMousePointer, faBreadSlice, faTrash, faCheck } from '@fortawesome/free-solid-svg-icons'; +import { faPenNib, faHighlighter, faEraser, faMousePointer, faBreadSlice, faTrash, faCheck, faLongArrowAltLeft } from '@fortawesome/free-solid-svg-icons'; import { Scripting } from '../client/util/Scripting'; import { CollectionFreeFormView } from '../client/views/collections/collectionFreeForm/CollectionFreeFormView'; import GestureOverlay from '../client/views/GestureOverlay'; @@ -23,7 +23,7 @@ import { DateField } from '../new_fields/DateField'; import { GestureUtils } from '../pen-gestures/GestureUtils'; import { DocServer } from '../client/DocServer'; -library.add(faTrash, faCheck); +library.add(faLongArrowAltLeft); @observer export default class MobileInterface extends React.Component { @@ -68,8 +68,8 @@ export default class MobileInterface extends React.Component { InkingControl.Instance.switchTool(InkTool.Pen); this.drawingInk = true; - DocServer.Mobile.dispatchBoxTrigger({ - enableBox: true, + DocServer.Mobile.dispatchOverlayTrigger({ + enableOverlay: true, width: window.innerWidth, height: window.innerHeight }); @@ -112,12 +112,12 @@ export default class MobileInterface extends React.Component { return "hello"; } - onClick = (e: React.MouseEvent) => { + onBack = (e: React.MouseEvent) => { this.switchCurrentView("main"); InkingControl.Instance.switchTool(InkTool.None); // TODO: switch to previous tool - DocServer.Mobile.dispatchBoxTrigger({ - enableBox: false, + DocServer.Mobile.dispatchOverlayTrigger({ + enableOverlay: false, width: window.innerWidth, height: window.innerHeight }); @@ -126,37 +126,61 @@ export default class MobileInterface extends React.Component { this.drawingInk = false; } + shiftLeft = (e: React.MouseEvent) => { + DocServer.Mobile.dispatchOverlayPositionUpdate({ + dx: -10 + }); + } + + shiftRight = (e: React.MouseEvent) => { + DocServer.Mobile.dispatchOverlayPositionUpdate({ + dx: 10 + }); + } + @computed get inkContent() { + // TODO: support panning and zooming + // TODO: handle moving of ink strokes if (this.mainContainer) { return ( - -
- - +
+
+
+ +
+
+ +
+
+ + +
- window.innerHeight} - PanelWidth={() => window.innerWidth} - focus={emptyFunction} - isSelected={returnFalse} - select={emptyFunction} - active={returnFalse} - ContentScaling={returnOne} - whenActiveChanged={returnFalse} - ScreenToLocalTransform={Transform.Identity} - ruleProvider={undefined} - renderDepth={0} - ContainingCollectionView={undefined} - ContainingCollectionDoc={undefined}> - - + + window.innerHeight} + PanelWidth={() => window.innerWidth} + focus={emptyFunction} + isSelected={returnFalse} + select={emptyFunction} + active={returnFalse} + ContentScaling={returnOne} + whenActiveChanged={returnFalse} + ScreenToLocalTransform={Transform.Identity} + ruleProvider={undefined} + renderDepth={0} + ContainingCollectionView={undefined} + ContainingCollectionDoc={undefined}> + + +
); } } diff --git a/src/server/Message.ts b/src/server/Message.ts index 1958286df..064a19653 100644 --- a/src/server/Message.ts +++ b/src/server/Message.ts @@ -50,12 +50,18 @@ export interface GestureContent { readonly color?: string; } -export interface MobileInkBoxContent { - readonly enableBox: boolean; +export interface MobileInkOverlayContent { + readonly enableOverlay: boolean; readonly width?: number; readonly height?: number; } +export interface UpdateMobileInkOverlayPosition { + readonly dx?: number; + readonly dy?: number; + readonly dsize?: number; +} + export namespace MessageStore { export const Foo = new Message("Foo"); export const Bar = new Message("Bar"); @@ -65,8 +71,10 @@ export namespace MessageStore { export const GetDocument = new Message("Get Document"); export const DeleteAll = new Message("Delete All"); export const ConnectionTerminated = new Message("Connection Terminated"); + export const GesturePoints = new Message("Gesture Points"); - export const MobileInkBoxTrigger = new Message("Trigger Mobile Ink Box"); + export const MobileInkOverlayTrigger = new Message("Trigger Mobile Ink Overlay"); + export const UpdateMobileInkOverlayPosition = new Message("Update Mobile Ink Overlay Position"); export const GetRefField = new Message("Get Ref Field"); export const GetRefFields = new Message("Get Ref Fields"); diff --git a/src/server/Websocket/Websocket.ts b/src/server/Websocket/Websocket.ts index 16e34bdfc..fe253400c 100644 --- a/src/server/Websocket/Websocket.ts +++ b/src/server/Websocket/Websocket.ts @@ -1,5 +1,5 @@ import { Utils } from "../../Utils"; -import { MessageStore, Transferable, Types, Diff, YoutubeQueryInput, YoutubeQueryTypes, GestureContent, MobileInkBoxContent } from "../Message"; +import { MessageStore, Transferable, Types, Diff, YoutubeQueryInput, YoutubeQueryTypes, GestureContent, MobileInkOverlayContent } from "../Message"; import { Client } from "../Client"; import { Socket } from "socket.io"; import { Database } from "../database"; @@ -55,7 +55,7 @@ export namespace WebSocket { Utils.AddServerHandler(socket, MessageStore.DeleteField, id => DeleteField(socket, id)); Utils.AddServerHandler(socket, MessageStore.DeleteFields, ids => DeleteFields(socket, ids)); Utils.AddServerHandler(socket, MessageStore.GesturePoints, content => processGesturePoints(socket, content)); - Utils.AddServerHandler(socket, MessageStore.MobileInkBoxTrigger, content => processBoxTrigger(socket, content)); + Utils.AddServerHandler(socket, MessageStore.MobileInkOverlayTrigger, content => processOverlayTrigger(socket, content)); Utils.AddServerHandlerCallback(socket, MessageStore.GetRefField, GetRefField); Utils.AddServerHandlerCallback(socket, MessageStore.GetRefFields, GetRefFields); @@ -74,8 +74,8 @@ export namespace WebSocket { socket.broadcast.emit("receiveGesturePoints", content); } - function processBoxTrigger(socket: Socket, content: MobileInkBoxContent) { - socket.broadcast.emit("receiveBoxTrigger", content); + function processOverlayTrigger(socket: Socket, content: MobileInkOverlayContent) { + socket.broadcast.emit("receiveOverlayTrigger", content); } function HandleYoutubeQuery([query, callback]: [YoutubeQueryInput, (result?: any[]) => void]) { -- cgit v1.2.3-70-g09d2 From e8fcbbf57b2a2f443d9c280ce10558cf9d51c632 Mon Sep 17 00:00:00 2001 From: vellichora Date: Sun, 9 Feb 2020 17:11:24 -0500 Subject: can upload collection from mobile to desktop --- src/client/DocServer.ts | 9 +- src/client/util/DragManager.ts | 2 +- .../collections/CollectionMasonryViewFieldRow.tsx | 1 + .../views/collections/CollectionStackingView.tsx | 2 + .../CollectionStackingViewFieldColumn.tsx | 1 + src/client/views/collections/CollectionSubView.tsx | 2 +- src/client/views/collections/CollectionView.tsx | 2 +- .../views/collections/CollectionViewChromes.tsx | 1 + src/mobile/ImageUpload.tsx | 1 + src/mobile/MobileInkOverlay.tsx | 53 +++++++- src/mobile/MobileInterface.scss | 8 ++ src/mobile/MobileInterface.tsx | 150 ++++++++++++--------- src/server/ApiManagers/UploadManager.ts | 1 + src/server/Message.ts | 6 + src/server/Websocket/Websocket.ts | 7 +- .../authentication/models/current_user_utils.ts | 21 +-- src/server/server_Initialization.ts | 24 ++-- 17 files changed, 195 insertions(+), 96 deletions(-) (limited to 'src/mobile/MobileInterface.scss') diff --git a/src/client/DocServer.ts b/src/client/DocServer.ts index c03764471..e09251855 100644 --- a/src/client/DocServer.ts +++ b/src/client/DocServer.ts @@ -1,5 +1,5 @@ import * as OpenSocket from 'socket.io-client'; -import { MessageStore, YoutubeQueryTypes, GestureContent, MobileInkOverlayContent, UpdateMobileInkOverlayPositionContent } from "./../server/Message"; +import { MessageStore, YoutubeQueryTypes, GestureContent, MobileInkOverlayContent, UpdateMobileInkOverlayPositionContent, MobileDocumentUploadContent } from "./../server/Message"; import { Opt, Doc } from '../new_fields/Doc'; import { Utils, emptyFunction } from '../Utils'; import { SerializationHelper } from './util/SerializationHelper'; @@ -81,6 +81,10 @@ export namespace DocServer { Utils.Emit(_socket, MessageStore.UpdateMobileInkOverlayPosition, content); } + export function dispatchMobileDocumentUpload(content: MobileDocumentUploadContent) { + Utils.Emit(_socket, MessageStore.MobileDocumentUpload, content); + } + } export function init(protocol: string, hostname: string, port: number, identifier: string) { @@ -116,6 +120,9 @@ export namespace DocServer { _socket.addEventListener("receiveUpdateOverlayPosition", (content: UpdateMobileInkOverlayPositionContent) => { MobileInkOverlay.Instance.updatePosition(content); }); + _socket.addEventListener("receiveMobileDocumentUpload", (content: MobileDocumentUploadContent) => { + MobileInkOverlay.Instance.uploadDocument(content); + }); } function errorFunc(): never { diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index df2f5fe3c..0bb8b531d 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -179,7 +179,7 @@ export namespace DragManager { ); } element.dataset.canDrop = "true"; - const handler = (e: Event) => dropFunc(e, (e as CustomEvent).detail); + const handler = (e: Event) => { console.log("drop target reveied docs"); dropFunc(e, (e as CustomEvent).detail); }; element.addEventListener("dashOnDrop", handler); return () => { element.removeEventListener("dashOnDrop", handler); diff --git a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx index 80752303c..26e0cc35a 100644 --- a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx +++ b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx @@ -73,6 +73,7 @@ export class CollectionMasonryViewFieldRow extends React.Component { + console.log("masronry row drop"); this._createAliasSelected = false; if (de.complete.docDragData) { (this.props.parent.Document.dropConverter instanceof ScriptField) && diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 992820fc7..83c90810e 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -240,6 +240,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { @undoBatch @action drop = (e: Event, de: DragManager.DropEvent) => { + console.log("DROP STACKIN G2"); const where = [de.x, de.y]; let targInd = -1; let plusOne = 0; @@ -270,6 +271,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { @undoBatch @action onDrop = async (e: React.DragEvent): Promise => { + console.log("DROP STACKING"); const where = [e.clientX, e.clientY]; let targInd = -1; this._docXfs.map((cd, i) => { diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx index 39b4e4e1d..65c4b3195 100644 --- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx +++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx @@ -57,6 +57,7 @@ export class CollectionStackingViewFieldColumn extends React.Component { + console.log("column drop stacking"); this._createAliasSelected = false; if (de.complete.docDragData) { const key = StrCast(this.props.parent.props.Document.sectionFilter); diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index e94f24f2c..b35af2314 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -6,7 +6,7 @@ import { Id } from "../../../new_fields/FieldSymbols"; import { List } from "../../../new_fields/List"; import { listSpec } from "../../../new_fields/Schema"; import { ScriptField } from "../../../new_fields/ScriptField"; -import { Cast } from "../../../new_fields/Types"; +import { Cast, StrCast } from "../../../new_fields/Types"; import { CurrentUserUtils } from "../../../server/authentication/models/current_user_utils"; import { Utils } from "../../../Utils"; import { DocServer } from "../../DocServer"; diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 88023783b..1d399e26f 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -138,7 +138,7 @@ export class CollectionView extends Touchable { let index = value.reduce((p, v, i) => (v instanceof Doc && v === doc) ? i : p, -1); index = index !== -1 ? index : value.reduce((p, v, i) => (v instanceof Doc && Doc.AreProtosEqual(v, doc)) ? i : p, -1); - ContextMenu.Instance.clearItems(); + ContextMenu.Instance && ContextMenu.Instance.clearItems(); if (index !== -1) { value.splice(index, 1); return true; diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx index a870b6043..01dc21f95 100644 --- a/src/client/views/collections/CollectionViewChromes.tsx +++ b/src/client/views/collections/CollectionViewChromes.tsx @@ -231,6 +231,7 @@ export class CollectionViewBaseChrome extends React.Component { + console.log("toggle collapse"); this.props.CollectionView.props.Document.chromeStatus = this.props.CollectionView.props.Document.chromeStatus === "enabled" ? "collapsed" : "enabled"; if (this.props.collapse) { this.props.collapse(this.props.CollectionView.props.Document.chromeStatus !== "enabled"); diff --git a/src/mobile/ImageUpload.tsx b/src/mobile/ImageUpload.tsx index 3304e8e22..10bd78075 100644 --- a/src/mobile/ImageUpload.tsx +++ b/src/mobile/ImageUpload.tsx @@ -47,6 +47,7 @@ class Uploader extends React.Component { const upload = window.location.origin + "/upload"; this.status = "uploading image"; + console.log("uploading image", formData); const res = await fetch(upload, { method: 'POST', body: formData diff --git a/src/mobile/MobileInkOverlay.tsx b/src/mobile/MobileInkOverlay.tsx index 6b65aa436..ed4cca5b9 100644 --- a/src/mobile/MobileInkOverlay.tsx +++ b/src/mobile/MobileInkOverlay.tsx @@ -1,9 +1,13 @@ import React = require('react'); import { observer } from "mobx-react"; -import { MobileInkOverlayContent, GestureContent, UpdateMobileInkOverlayPositionContent } from "../server/Message"; +import { MobileInkOverlayContent, GestureContent, UpdateMobileInkOverlayPositionContent, MobileDocumentUploadContent } from "../server/Message"; import { observable, action } from "mobx"; import { GestureUtils } from "../pen-gestures/GestureUtils"; import "./MobileInkOverlay.scss"; +import { StrCast } from '../new_fields/Types'; +import { DragManager } from "../client/util/DragManager"; +import { DocServer } from '../client/DocServer'; +import { Doc } from '../new_fields/Doc'; @observer @@ -67,7 +71,7 @@ export default class MobileInkOverlay extends React.Component { height: bounds.height * this._scale, }; - const target = document.elementFromPoint(points[0].X, points[0].Y); + const target = document.elementFromPoint(this._x + 10, this._y + 10); target?.dispatchEvent( new CustomEvent("dashOnGesture", { @@ -82,6 +86,43 @@ export default class MobileInkOverlay extends React.Component { ); } + uploadDocument = async (content: MobileDocumentUploadContent) => { + const { docId } = content; + console.log("receive upload document id", docId); + const doc = await DocServer.GetRefField(docId); + + if (doc && doc instanceof Doc) { + console.log("parsed upload document into doc", StrCast(doc.proto!.title)); + + const target = document.elementFromPoint(this._x + 10, this._y + 10); + console.log("the target is", target); + + const dragData = new DragManager.DocumentDragData([doc]); + const complete = new DragManager.DragCompleteEvent(false, dragData); + console.log("the drag data is", dragData); + + if (target) { + target.dispatchEvent( + new CustomEvent("dashOnDrop", + { + bubbles: true, + detail: { + x: this._x, + y: this._y, + complete: complete, + altKey: false, + metaKey: false, + ctrlKey: false + } + } + ) + ); + } else { + alert("TARGET IS UNDEFINED"); + } + } + } + @action dragStart = (e: React.PointerEvent) => { document.removeEventListener("pointermove", this.dragging); @@ -132,15 +173,17 @@ export default class MobileInkOverlay extends React.Component { transform: `translate(${this._x}px, ${this._y}px)`, zIndex: 30000, pointerEvents: "none", - borderStyle: this._isDragging ? "solid" : "dashed" - }} + borderStyle: this._isDragging ? "solid" : "dashed", + backgroundColor: "rgba(255, 0, 0, 0.3)" + } + } ref={this._mainCont} >
-
+ ); } } \ No newline at end of file diff --git a/src/mobile/MobileInterface.scss b/src/mobile/MobileInterface.scss index 8abe5a40d..8b0ebcd53 100644 --- a/src/mobile/MobileInterface.scss +++ b/src/mobile/MobileInterface.scss @@ -1,7 +1,15 @@ .mobileInterface-inkInterfaceButtons { position: absolute; + top: -50px; display: flex; justify-content: space-between; width: 100%; z-index: 9999; + height: 50px; +} + +.mobileInterface-container { + height: calc(100% - 50px); + margin-top: 50px; + position: relative; } \ No newline at end of file diff --git a/src/mobile/MobileInterface.tsx b/src/mobile/MobileInterface.tsx index 665d9a168..a1ef0a5d1 100644 --- a/src/mobile/MobileInterface.tsx +++ b/src/mobile/MobileInterface.tsx @@ -22,6 +22,18 @@ import { SelectionManager } from '../client/util/SelectionManager'; import { DateField } from '../new_fields/DateField'; import { GestureUtils } from '../pen-gestures/GestureUtils'; import { DocServer } from '../client/DocServer'; +import { DocumentDecorations } from '../client/views/DocumentDecorations'; +import { OverlayView } from '../client/views/OverlayView'; +import { DictationOverlay } from '../client/views/DictationOverlay'; +import SharingManager from '../client/util/SharingManager'; +import { PreviewCursor } from '../client/views/PreviewCursor'; +import { ContextMenu } from '../client/views/ContextMenu'; +import { RadialMenu } from '../client/views/nodes/RadialMenu'; +import PDFMenu from '../client/views/pdf/PDFMenu'; +import MarqueeOptionsMenu from '../client/views/collections/collectionFreeForm/MarqueeOptionsMenu'; +import GoogleAuthenticationManager from '../client/apis/GoogleAuthenticationManager'; +import { listSpec } from '../new_fields/Schema'; +import { Id } from '../new_fields/FieldSymbols'; library.add(faLongArrowAltLeft); @@ -31,7 +43,7 @@ export default class MobileInterface extends React.Component { @computed private get userDoc() { return CurrentUserUtils.UserDocument; } @computed private get mainContainer() { return this.userDoc ? FieldValue(Cast(this.userDoc.activeMobile, Doc)) : CurrentUserUtils.GuestMobile; } // @observable private currentView: "main" | "ink" | "upload" = "main"; - private mainDoc: Doc = CurrentUserUtils.setupMobileDoc(this.userDoc); + private mainDoc: any = CurrentUserUtils.setupMobileDoc(this.userDoc); @observable private renderView?: () => JSX.Element; // private inkDoc?: Doc; @@ -49,7 +61,6 @@ export default class MobileInterface extends React.Component { library.add(...[faPenNib, faHighlighter, faEraser, faMousePointer]); if (this.userDoc && !this.mainContainer) { - // const doc = CurrentUserUtils.setupMobileDoc(this.userDoc); this.userDoc.activeMobile = this.mainDoc; } } @@ -76,48 +87,22 @@ export default class MobileInterface extends React.Component { }); } - // @action - // switchCurrentView = (view: "main" | "ink" | "upload") => { - // this.currentView = view; - - // if (this.userDoc) { - // switch (view) { - // case "main": { - // // const doc = CurrentUserUtils.setupMobileDoc(this.userDoc); - // this.userDoc.activeMobile = this.mainDoc; - // break; - // } - // case "ink": { - // this.inkDoc = CurrentUserUtils.setupMobileInkingDoc(this.userDoc); - // this.userDoc.activeMobile = this.inkDoc; - // InkingControl.Instance.switchTool(InkTool.Pen); - // this.drawingInk = true; - - // DocServer.Mobile.dispatchOverlayTrigger({ - // enableOverlay: true, - // width: window.innerWidth, - // height: window.innerHeight - // }); - - // break; - // } - // case "upload": { - // this.uploadDoc = CurrentUserUtils.setupMobileUploadDoc(this.userDoc); - // this.userDoc.activeMobile = this.uploadDoc; - - // } - // } - // } - // } + onSwitchUpload = () => { + DocServer.Mobile.dispatchOverlayTrigger({ + enableOverlay: true, + width: 100, + height: 100 + }); + } renderDefaultContent = () => { - console.log("rendering default content"); + console.log("rendering default content", this.mainContainer); if (this.mainContainer) { return { console.log("want to add doc to default content", StrCast(doc.title)); return false; }} addDocTab={returnFalse} pinToPres={emptyFunction} removeDocument={undefined} @@ -192,42 +177,54 @@ export default class MobileInterface extends React.Component { - - window.innerHeight} - PanelWidth={() => window.innerWidth} - focus={emptyFunction} - isSelected={returnFalse} - select={emptyFunction} - active={returnFalse} - ContentScaling={returnOne} - whenActiveChanged={returnFalse} - ScreenToLocalTransform={Transform.Identity} - ruleProvider={undefined} - renderDepth={0} - ContainingCollectionView={undefined} - ContainingCollectionDoc={undefined}> - - + window.innerHeight} + PanelWidth={() => window.innerWidth} + focus={emptyFunction} + isSelected={returnFalse} + select={emptyFunction} + active={returnFalse} + ContentScaling={returnOne} + whenActiveChanged={returnFalse} + ScreenToLocalTransform={Transform.Identity} + ruleProvider={undefined} + renderDepth={0} + ContainingCollectionView={undefined} + ContainingCollectionDoc={undefined}> + ); } } - upload = () => { + upload = async (e: React.MouseEvent) => { + if (this.mainContainer) { + const data = Cast(this.mainContainer.data, listSpec(Doc)); + if (data) { + const uploadDoc = await data[1]; // TODO: ensure this is the collection to upload + console.log("UPLOADING DOCUMENT FROM MOBILE", uploadDoc[Id], StrCast(uploadDoc.proto!.title)); + if (uploadDoc) { + DocServer.Mobile.dispatchMobileDocumentUpload({ + docId: uploadDoc[Id] + }); + } + } + } + e.stopPropagation(); + e.preventDefault(); } renderUploadContent() { if (this.mainContainer) { return ( -
+
@@ -240,7 +237,7 @@ export default class MobileInterface extends React.Component { Document={this.mainContainer} DataDoc={undefined} LibraryPath={emptyPath} - addDocument={returnFalse} + addDocument={(doc: Doc) => { console.log("want to add doc", StrCast(doc.title)); return false; }} addDocTab={returnFalse} pinToPres={emptyFunction} removeDocument={undefined} @@ -266,13 +263,35 @@ export default class MobileInterface extends React.Component { } } + onDragOver = (e: React.DragEvent) => { + e.preventDefault(); + e.stopPropagation(); + } + render() { // const content = this.currentView === "main" ? this.mainContent : // this.currentView === "ink" ? this.inkContent : // this.currentView === "upload" ? this.uploadContent : <>; return ( -
- {this.renderView ? this.renderView() : this.renderDefaultContent()} +
+ {/* + + {this.renderView ? this.renderView() : this.renderDefaultContent()} + */} + + {/* + + */} + + + {this.renderView ? this.renderView() : this.renderDefaultContent()} + + + {/* */} + + {/* + + */}
); } @@ -281,5 +300,6 @@ export default class MobileInterface extends React.Component { Scripting.addGlobal(function switchMobileView(doc: (userDoc: Doc) => Doc, renderView?: () => JSX.Element, onSwitch?: () => void) { return MobileInterface.Instance.switchCurrentView(doc, renderView, onSwitch); }); Scripting.addGlobal(function onSwitchMobileInking() { return MobileInterface.Instance.onSwitchInking(); }); Scripting.addGlobal(function renderMobileInking() { return MobileInterface.Instance.renderInkingContent(); }); +Scripting.addGlobal(function onSwitchMobileUpload() { return MobileInterface.Instance.onSwitchUpload(); }); Scripting.addGlobal(function renderMobileUpload() { return MobileInterface.Instance.renderUploadContent(); }); diff --git a/src/server/ApiManagers/UploadManager.ts b/src/server/ApiManagers/UploadManager.ts index 74f45ae62..e76d9b7a2 100644 --- a/src/server/ApiManagers/UploadManager.ts +++ b/src/server/ApiManagers/UploadManager.ts @@ -42,6 +42,7 @@ export default class UploadManager extends ApiManager { method: Method.POST, subscription: "/upload", secureHandler: async ({ req, res }) => { + console.log("/upload register"); const form = new formidable.IncomingForm(); form.uploadDir = pathToDirectory(Directory.parsed_files); form.keepExtensions = true; diff --git a/src/server/Message.ts b/src/server/Message.ts index 236df3f3c..c23a2f0a8 100644 --- a/src/server/Message.ts +++ b/src/server/Message.ts @@ -1,5 +1,6 @@ import { Utils } from "../Utils"; import { Point } from "../pen-gestures/ndollar"; +import { Doc } from "../new_fields/Doc"; export class Message { private _name: string; @@ -62,6 +63,10 @@ export interface UpdateMobileInkOverlayPositionContent { readonly dsize?: number; } +export interface MobileDocumentUploadContent { + readonly docId: string; +} + export namespace MessageStore { export const Foo = new Message("Foo"); export const Bar = new Message("Bar"); @@ -75,6 +80,7 @@ export namespace MessageStore { export const GesturePoints = new Message("Gesture Points"); export const MobileInkOverlayTrigger = new Message("Trigger Mobile Ink Overlay"); export const UpdateMobileInkOverlayPosition = new Message("Update Mobile Ink Overlay Position"); + export const MobileDocumentUpload = new Message("Upload Document From Mobile"); export const GetRefField = new Message("Get Ref Field"); export const GetRefFields = new Message("Get Ref Fields"); diff --git a/src/server/Websocket/Websocket.ts b/src/server/Websocket/Websocket.ts index 77816c897..798bdae67 100644 --- a/src/server/Websocket/Websocket.ts +++ b/src/server/Websocket/Websocket.ts @@ -1,5 +1,5 @@ import { Utils } from "../../Utils"; -import { MessageStore, Transferable, Types, Diff, YoutubeQueryInput, YoutubeQueryTypes, GestureContent, MobileInkOverlayContent, UpdateMobileInkOverlayPositionContent } from "../Message"; +import { MessageStore, Transferable, Types, Diff, YoutubeQueryInput, YoutubeQueryTypes, GestureContent, MobileInkOverlayContent, UpdateMobileInkOverlayPositionContent, MobileDocumentUploadContent } from "../Message"; import { Client } from "../Client"; import { Socket } from "socket.io"; import { Database } from "../database"; @@ -57,6 +57,7 @@ export namespace WebSocket { Utils.AddServerHandler(socket, MessageStore.GesturePoints, content => processGesturePoints(socket, content)); Utils.AddServerHandler(socket, MessageStore.MobileInkOverlayTrigger, content => processOverlayTrigger(socket, content)); Utils.AddServerHandler(socket, MessageStore.UpdateMobileInkOverlayPosition, content => processUpdateOverlayPosition(socket, content)); + Utils.AddServerHandler(socket, MessageStore.MobileDocumentUpload, content => processMobileDocumentUpload(socket, content)); Utils.AddServerHandlerCallback(socket, MessageStore.GetRefField, GetRefField); Utils.AddServerHandlerCallback(socket, MessageStore.GetRefFields, GetRefFields); @@ -83,6 +84,10 @@ export namespace WebSocket { socket.broadcast.emit("receiveUpdateOverlayPosition", content); } + function processMobileDocumentUpload(socket: Socket, content: MobileDocumentUploadContent) { + socket.broadcast.emit("receiveMobileDocumentUpload", content); + } + function HandleYoutubeQuery([query, callback]: [YoutubeQueryInput, (result?: any[]) => void]) { const { ProjectCredentials } = GoogleCredentialsLoader; switch (query.type) { diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index 817cf40b1..3e5953ac1 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -103,7 +103,7 @@ export class CurrentUserUtils { { title: "use scrubber", icon: "eraser", click: 'activateScrubber(this.activePen.pen = sameDocs(this.activePen.pen, this) ? undefined : this);', ischecked: `sameDocs(this.activePen.pen, this)`, backgroundColor: "green", activePen: doc }, { title: "use drag", icon: "mouse-pointer", click: 'deactivateInk();this.activePen.pen = this;', ischecked: `sameDocs(this.activePen.pen, this)`, backgroundColor: "white", activePen: doc }, { title: "draw", icon: "pen-nib", click: 'switchMobileView(setupMobileInkingDoc, renderMobileInking, onSwitchMobileInking);', ischecked: `sameDocs(this.activePen.pen, this)`, backgroundColor: "red", activePen: doc }, - { title: "upload", icon: "upload", click: 'switchMobileView(setupMobileUploadDoc, renderMobileUpload);', backgroundColor: "orange" }, + { title: "upload", icon: "upload", click: 'switchMobileView(setupMobileUploadDoc, renderMobileUpload, onSwitchMobileUpload);', backgroundColor: "orange" }, { title: "upload", icon: "upload", click: 'uploadImageMobile();', backgroundColor: "cyan" }, ]; return docProtoData.filter(d => !buttons || !buttons.includes(d.title)).map(data => Docs.Create.FontIconDocument({ @@ -138,7 +138,9 @@ export class CurrentUserUtils { } static setupMobileDoc(userDoc: Doc) { - return userDoc.activeMoble ?? Docs.Create.MasonryDocument(CurrentUserUtils.setupMobileButtons(userDoc), { + const webDoc = Docs.Create.WebDocument("https://wikipedia.com", { title: "Mobile Upload Web", chromeStatus: "enabled" }); + + return userDoc.activeMoble ?? Docs.Create.MasonryDocument([webDoc, ...CurrentUserUtils.setupMobileButtons(userDoc)], { columnWidth: 100, ignoreClick: true, lockedPosition: true, chromeStatus: "disabled", title: "buttons", autoHeight: true, yMargin: 5 }); } @@ -148,13 +150,14 @@ export class CurrentUserUtils { } static setupMobileUploadDoc(userDoc: Doc) { - console.log("setup mobile upload", window.innerWidth, window.innerHeight); - const webDoc = Docs.Create.WebDocument("https://wikipedia.com", { title: "Mobile Upload Web", chromeStatus: "enabled" }); - const uploadDoc = Docs.Create.StackingDocument([], { title: "Mobile Upload", backgroundColor: "pink" }); - return Docs.Create.StackingDocument([webDoc, uploadDoc], { - title: "Mobile Upload", backgroundColor: "white", - columnWidth: window.innerWidth, ignoreClick: true, lockedPosition: true, chromeStatus: "disabled", autoHeight: true, yMargin: 5, - width: window.innerWidth, height: window.innerHeight + const webDoc = Docs.Create.WebDocument("https://yahoo.com", { title: "Upload Images From the Web", chromeStatus: "enabled" }); + const uploadDoc = Docs.Create.StackingDocument([], { title: "Mobile Upload Collection", backgroundColor: "pink" }); + console.log("window size", window.innerWidth, window.innerHeight); + // return Docs.Create.StackingDocument([webDoc, uploadDoc], { + // columnWidth: window.innerWidth, //ignoreClick: true, lockedPosition: true, chromeStatus: "disabled", title: "Mobile Upload", autoHeight: true, yMargin: 5 + // }); + return Docs.Create.StackingDocument([webDoc, uploadDoc], {//...CurrentUserUtils.setupMobileButtons(userDoc)], { + columnWidth: 100, lockedPosition: true, chromeStatus: "disabled", title: "Upload", autoHeight: true, yMargin: 30 }); } diff --git a/src/server/server_Initialization.ts b/src/server/server_Initialization.ts index cbe070293..5f1ecc733 100644 --- a/src/server/server_Initialization.ts +++ b/src/server/server_Initialization.ts @@ -42,18 +42,18 @@ export default async function InitializeServer(routeSetter: RouteSetter) { } }; app.use(cors(corsOptions)); - app.use("*", ({ user, originalUrl }, res, next) => { - if (user && !originalUrl.includes("Heartbeat")) { - const userEmail = (user as any).email; - if (userEmail) { - timeMap[userEmail] = Date.now(); - } - } - if (!user && originalUrl === "/") { - return res.redirect("/login"); - } - next(); - }); + // app.use("*", ({ user, originalUrl }, res, next) => { + // if (user && !originalUrl.includes("Heartbeat")) { + // const userEmail = (user as any).email; + // if (userEmail) { + // timeMap[userEmail] = Date.now(); + // } + // } + // if (!user && originalUrl === "/") { + // return res.redirect("/login"); + // } + // next(); + // }); app.use(wdm(compiler, { publicPath: config.output.publicPath })); app.use(whm(compiler)); -- cgit v1.2.3-70-g09d2 From 74ca8ac01e32faa8adab54ddfd806fe46cda03ec Mon Sep 17 00:00:00 2001 From: Hannah Date: Tue, 11 Feb 2020 06:22:04 -0500 Subject: refined upload interaction --- src/client/util/DragManager.ts | 21 ++-- src/client/views/nodes/WebBox.scss | 15 +++ src/client/views/nodes/WebBox.tsx | 130 ++++++++++----------- src/mobile/ImageUpload.tsx | 2 - src/mobile/MobileInkOverlay.scss | 4 +- src/mobile/MobileInkOverlay.tsx | 35 +++--- src/mobile/MobileInterface.scss | 7 +- src/mobile/MobileInterface.tsx | 42 ++++--- src/server/Message.ts | 2 +- .../authentication/models/current_user_utils.ts | 25 ++-- 10 files changed, 146 insertions(+), 137 deletions(-) (limited to 'src/mobile/MobileInterface.scss') diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 745540ff9..702c10910 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -195,7 +195,7 @@ export namespace DragManager { dragData.userDropAction === "alias" || (!dragData.userDropAction && dragData.dropAction === "alias") ? Doc.MakeAlias(d) : dragData.userDropAction === "copy" || (!dragData.userDropAction && dragData.dropAction === "copy") ? Doc.MakeCopy(d, true) : d) ); - e.docDragData?.droppedDocuments.forEach((drop: Doc, i: number) => + e.docDragData ?.droppedDocuments.forEach((drop: Doc, i: number) => Cast(dragData.draggedDocuments[i].removeDropProperties, listSpec("string"), []).map(prop => drop[prop] = undefined)); }; dragData.draggedDocuments.map(d => d.dragFactory); // does this help? trying to make sure the dragFactory Doc is loaded @@ -288,6 +288,7 @@ export namespace DragManager { if (!ele.parentNode) dragDiv.appendChild(ele); const dragElement = ele.parentNode === dragDiv ? ele : ele.cloneNode(true) as HTMLElement; const rect = ele.getBoundingClientRect(); + console.log("boudning", rect); const scaleX = rect.width / ele.offsetWidth, scaleY = rect.height / ele.offsetHeight; xs.push(rect.left); @@ -305,7 +306,7 @@ export namespace DragManager { dragElement.style.transformOrigin = "0 0"; dragElement.style.borderRadius = getComputedStyle(ele).borderRadius; dragElement.style.zIndex = globalCssVariables.contextMenuZindex;// "1000"; - dragElement.style.transform = `translate(${rect.left + (options?.offsetX || 0)}px, ${rect.top + (options?.offsetY || 0)}px) scale(${scaleX}, ${scaleY})`; + dragElement.style.transform = `translate(${rect.left + (options ?.offsetX || 0)}px, ${rect.top + (options ?.offsetY || 0)}px) scale(${scaleX}, ${scaleY})`; dragElement.style.width = `${rect.width / scaleX}px`; dragElement.style.height = `${rect.height / scaleY}px`; @@ -334,8 +335,8 @@ export namespace DragManager { return dragElement; }); - const hideSource = options?.hideSource ? true : false; - eles.map(ele => ele.parentElement && ele.parentElement?.className === dragData.dragDivName ? (ele.parentElement.hidden = hideSource) : (ele.hidden = hideSource)); + const hideSource = options ?.hideSource ? true : false; + eles.map(ele => ele.parentElement && ele.parentElement ?.className === dragData.dragDivName ? (ele.parentElement.hidden = hideSource) : (ele.hidden = hideSource)); let lastX = downX; let lastY = downY; @@ -346,7 +347,7 @@ export namespace DragManager { } if (e.shiftKey && CollectionDockingView.Instance) { AbortDrag(); - finishDrag?.(new DragCompleteEvent(true, dragData)); + finishDrag ?.(new DragCompleteEvent(true, dragData)); CollectionDockingView.Instance.StartOtherDrag({ pageX: e.pageX, pageY: e.pageY, @@ -360,13 +361,13 @@ export namespace DragManager { lastX = e.pageX; lastY = e.pageY; dragElements.map((dragElement, i) => (dragElement.style.transform = - `translate(${(xs[i] += moveX) + (options?.offsetX || 0)}px, ${(ys[i] += moveY) + (options?.offsetY || 0)}px) scale(${scaleXs[i]}, ${scaleYs[i]})`) + `translate(${(xs[i] += moveX) + (options ?.offsetX || 0)}px, ${(ys[i] += moveY) + (options ?.offsetY || 0)}px) scale(${scaleXs[i]}, ${scaleYs[i]})`) ); }; const hideDragShowOriginalElements = () => { dragElements.map(dragElement => dragElement.parentNode === dragDiv && dragDiv.removeChild(dragElement)); - eles.map(ele => ele.parentElement && ele.parentElement?.className === dragData.dragDivName ? (ele.parentElement.hidden = false) : (ele.hidden = false)); + eles.map(ele => ele.parentElement && ele.parentElement ?.className === dragData.dragDivName ? (ele.parentElement.hidden = false) : (ele.hidden = false)); }; const endDrag = () => { document.removeEventListener("pointermove", moveHandler, true); @@ -376,14 +377,14 @@ export namespace DragManager { AbortDrag = () => { hideDragShowOriginalElements(); SelectionManager.SetIsDragging(false); - options?.dragComplete?.(new DragCompleteEvent(true, dragData)); + options ?.dragComplete ?.(new DragCompleteEvent(true, dragData)); endDrag(); }; const upHandler = (e: PointerEvent) => { hideDragShowOriginalElements(); dispatchDrag(eles, e, dragData, options, finishDrag); SelectionManager.SetIsDragging(false); - options?.dragComplete?.(new DragCompleteEvent(false, dragData)); + options ?.dragComplete ?.(new DragCompleteEvent(false, dragData)); endDrag(); }; document.addEventListener("pointermove", moveHandler, true); @@ -404,7 +405,7 @@ export namespace DragManager { }); if (target) { const complete = new DragCompleteEvent(false, dragData); - finishDrag?.(complete); + finishDrag ?.(complete); target.dispatchEvent( new CustomEvent("dashOnDrop", { diff --git a/src/client/views/nodes/WebBox.scss b/src/client/views/nodes/WebBox.scss index fbe9bf063..226103a53 100644 --- a/src/client/views/nodes/WebBox.scss +++ b/src/client/views/nodes/WebBox.scss @@ -90,4 +90,19 @@ width: 100%; margin-right: 10px; height: 100%; +} + +.touch-iframe-overlay { + width: 100%; + height: 100%; + position: absolute; + pointer-events: all; + + .indicator { + position: absolute; + + &.active { + background-color: rgba(0, 0, 0, 0.1); + } + } } \ No newline at end of file diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index c405dd9d4..ee5bf6f2f 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -39,6 +39,7 @@ export class WebBox extends DocAnnotatableComponent private _longPressSecondsHack?: NodeJS.Timeout; private _iframeRef = React.createRef(); + private _iframeIndicatorRef = React.createRef(); private _iframeDragRef = React.createRef(); @observable private _pressX: number = 0; @observable private _pressY: number = 0; @@ -63,39 +64,6 @@ export class WebBox extends DocAnnotatableComponent componentDidMount() { document.addEventListener("pointerup", this.onLongPressUp); document.addEventListener("pointermove", this.onLongPressMove); - // this._iframeRef.current?.contentWindow?.document.addEventListener("mousedown", (event: MouseEvent) => { - // console.log("clicked inside the iframe?"); - // }); - // const iframe = document.getElementById(this.props.Document.proto![Id]); - // if (iframe) { - // iframe.addEventListener('pointerdown', function (event) { - // const B = iframe.getBoundingClientRect(); - // const e = new CustomEvent('pointerdown', { bubbles: true, cancelable: false }); - // // e.clientX = e.clientX + B?.left; - // // e.clientY = e.clientY + B?.top; - // console.log("custom event pointer down"); - // iframe.dispatchEvent(e); - // }) - // } - // if (this._iframeRef.current) { - // console.log("resetting iframes events"); - // const self = this; - // this._iframeRef.current.addEventListener('pointermove', function (event) { - // const B = self._iframeRef.current?.getBoundingClientRect(); - // const e = new CustomEvent('pointermove', { bubbles: true, cancelable: false }); - // // e.clientX = e.clientX + B?.left; - // // e.clientY = e.clientY + B?.top; - // self._iframeRef.current?.dispatchEvent(e); - // }); - // this._iframeRef.current.addEventListener('pointerdown', function (event) { - // const B = self._iframeRef.current?.getBoundingClientRect(); - // const e = new CustomEvent('pointerdown', { bubbles: true, cancelable: false }); - // // e.clientX = e.clientX + B?.left; - // // e.clientY = e.clientY + B?.top; - // console.log("custom event pointer down"); - // self._iframeRef.current?.dispatchEvent(e); - // }) - // } } componentWillUnmount() { @@ -217,59 +185,75 @@ export class WebBox extends DocAnnotatableComponent } } - // TODO: make this actually a long press onLongPressDown = (e: React.PointerEvent) => { - - console.log("press down", e.clientX, e.clientX); this._pressX = e.clientX; this._pressY = e.clientY; - this._longPressSecondsHack = setTimeout(() => { - console.log("start the drag!!"); - const B = this._iframeRef.current?.getBoundingClientRect(); - const iframeDoc = this._iframeRef.current?.contentDocument; + + // find the pressed element in the iframe (currently only works if its an img) + let pressedElement: HTMLElement | undefined; + let pressedBound: ClientRect | undefined; + if (this._iframeRef.current) { + const B = this._iframeRef.current.getBoundingClientRect(); + const iframeDoc = this._iframeRef.current.contentDocument; if (B && iframeDoc) { - console.log("frame doc", iframeDoc); - console.log("get point", this._pressX, B.left, this._pressY, B.top); + // TODO: this only works when scale = 1 const element = iframeDoc.elementFromPoint(this._pressX - B.left, this._pressY - B.top); - console.log("found element", element); - if (element) { - e.stopPropagation(); - e.preventDefault(); - const clone = element.cloneNode(true) as HTMLElement; - - if (clone.nodeName === "IMG") { - const src = clone.getAttribute("src"); // TODO: may not always work - - if (src) { - const doc = Docs.Create.ImageDocument(src, { width: 300 }); - ImageUtils.ExtractExif(doc); - - console.log("start image drag", this._pressX, this._pressY, doc); - // document.dispatchEvent() - const dragData = new DragManager.DocumentDragData([doc]); - DragManager.StartDocumentDrag([clone], dragData, this._pressX, this._pressY); - } + if (element && element.nodeName === "IMG") { + pressedBound = element.getBoundingClientRect(); + pressedElement = element.cloneNode(true) as HTMLElement; + } + } + } + + // mark the pressed element + if (pressedElement && pressedBound) { + console.log("clones b", pressedElement.getBoundingClientRect(), pressedBound); + if (this._iframeIndicatorRef.current) { + this._iframeIndicatorRef.current.style.top = pressedBound.top + "px"; + this._iframeIndicatorRef.current.style.left = pressedBound.left + "px"; + this._iframeIndicatorRef.current.style.width = pressedBound.width + "px"; + this._iframeIndicatorRef.current.style.height = pressedBound.height + "px"; + this._iframeIndicatorRef.current.classList.add("active"); + } + } + + // start dragging the pressed element if long pressed + this._longPressSecondsHack = setTimeout(() => { + if (pressedElement && pressedBound) { + e.stopPropagation(); + e.preventDefault(); + if (pressedElement.nodeName === "IMG") { + const src = pressedElement.getAttribute("src"); // TODO: may not always work + if (src) { + const doc = Docs.Create.ImageDocument(src, { width: 300 }); + ImageUtils.ExtractExif(doc); + + // add clone to div so that dragging ghost is placed properly + if (this._iframeDragRef.current) this._iframeDragRef.current.appendChild(pressedElement); + + const dragData = new DragManager.DocumentDragData([doc]); + DragManager.StartDocumentDrag([pressedElement], dragData, this._pressX, this._pressY, { hideSource: true }); } } } }, 1500); - // e.stopPropagation(); - // e.preventDefault(); } onLongPressMove = (e: PointerEvent) => { - this._pressX = e.clientX; - this._pressY = e.clientY; + // this._pressX = e.clientX; + // this._pressY = e.clientY; } onLongPressUp = (e: PointerEvent) => { - console.log("press up"); if (this._longPressSecondsHack) { clearTimeout(this._longPressSecondsHack); - console.log("long press cancelled"); } - // e.stopPropagation(); - // e.preventDefault(); + if (this._iframeIndicatorRef.current) { + this._iframeIndicatorRef.current.classList.remove("active"); + } + if (this._iframeDragRef.current) { + while (this._iframeDragRef.current.firstChild) this._iframeDragRef.current.removeChild(this._iframeDragRef.current.firstChild); + } } @@ -300,9 +284,13 @@ export class WebBox extends DocAnnotatableComponent
{content}
-
- {!frozen ? (null) :
} - {/* onPointerDown={(e) => { this.onPrePointer(e); this.onLongPressDown(e) }} onPointerMove={this.onPrePointer} onPointerUp={(e) => { this.onPrePointer(e); }} />} */} + {!frozen ? (null) : +
+
+
+
+
+
} ); } render() { diff --git a/src/mobile/ImageUpload.tsx b/src/mobile/ImageUpload.tsx index 10bd78075..42dfd4e51 100644 --- a/src/mobile/ImageUpload.tsx +++ b/src/mobile/ImageUpload.tsx @@ -106,8 +106,6 @@ class Uploader extends React.Component { } -// Scripting.addGlobal(function uploadImageMobile() { return Uploader.onClick(); }); - // DocServer.init(window.location.protocol, window.location.hostname, 4321, "image upload"); (async () => { diff --git a/src/mobile/MobileInkOverlay.scss b/src/mobile/MobileInkOverlay.scss index 2e45d0441..0b4484519 100644 --- a/src/mobile/MobileInkOverlay.scss +++ b/src/mobile/MobileInkOverlay.scss @@ -1,10 +1,10 @@ .mobileInkOverlay { border: 5px dashed red; + background-color: rgba(0, 0, 0, .05); } .mobileInkOverlay-border { - background-color: rgba(0, 255, 0, .4); - position: absolute; + // background-color: rgba(0, 255, 0, .4); position: absolute; pointer-events: auto; cursor: pointer; diff --git a/src/mobile/MobileInkOverlay.tsx b/src/mobile/MobileInkOverlay.tsx index 9f810424a..db6cf21b4 100644 --- a/src/mobile/MobileInkOverlay.tsx +++ b/src/mobile/MobileInkOverlay.tsx @@ -20,6 +20,7 @@ export default class MobileInkOverlay extends React.Component { @observable private _height: number = 0; @observable private _x: number = -300; @observable private _y: number = -300; + @observable private _text: string = ""; @observable private _offsetX: number = 0; @observable private _offsetY: number = 0; @@ -32,21 +33,25 @@ export default class MobileInkOverlay extends React.Component { } initialSize(mobileWidth: number, mobileHeight: number) { - const maxWidth = window.innerWidth - 30; // TODO: may not be window ?? figure out how to not include library ???? + const maxWidth = window.innerWidth - 30; const maxHeight = window.innerHeight - 30; // -30 for padding - const scale = Math.min(maxWidth / mobileWidth, maxHeight / mobileHeight); - return { width: mobileWidth * scale, height: mobileHeight * scale, scale: scale }; + if (mobileWidth > maxWidth || mobileHeight > maxHeight) { + const scale = Math.min(maxWidth / mobileWidth, maxHeight / mobileHeight); + return { width: mobileWidth * scale, height: mobileHeight * scale, scale: scale }; + } + return { width: mobileWidth, height: mobileHeight, scale: 1 }; } @action initMobileInkOverlay(content: MobileInkOverlayContent) { - const { width, height } = content; + const { width, height, text } = content; const scaledSize = this.initialSize(width ? width : 0, height ? height : 0); this._width = scaledSize.width; this._height = scaledSize.height; - this._scale = scaledSize.scale; //scaledSize.scale; + this._scale = scaledSize.scale; this._x = 300; // TODO: center on screen this._y = 25; // TODO: center on screen + this._text = text ? text : ""; } @action @@ -73,7 +78,7 @@ export default class MobileInkOverlay extends React.Component { }; const target = document.elementFromPoint(this._x + 10, this._y + 10); - target?.dispatchEvent( + target ?.dispatchEvent( new CustomEvent("dashOnGesture", { bubbles: true, @@ -88,25 +93,13 @@ export default class MobileInkOverlay extends React.Component { } uploadDocument = async (content: MobileDocumentUploadContent) => { - const { docId, asCollection } = content; - console.log("receive upload document id", docId); + const { docId } = content; const doc = await DocServer.GetRefField(docId); if (doc && doc instanceof Doc) { - console.log("parsed upload document into doc", StrCast(doc.proto!.title)); - const target = document.elementFromPoint(this._x + 10, this._y + 10); - console.log("the target is", target); - - let uploadDocs = [doc]; - if (!asCollection) { - const children = await DocListCastAsync(doc.data); - console.log("uploading children", children); - uploadDocs = children ? children : []; - } - const dragData = new DragManager.DocumentDragData(uploadDocs); + const dragData = new DragManager.DocumentDragData([doc]); const complete = new DragManager.DragCompleteEvent(false, dragData); - console.log("the drag data is", dragData); if (target) { target.dispatchEvent( @@ -181,11 +174,11 @@ export default class MobileInkOverlay extends React.Component { zIndex: 30000, pointerEvents: "none", borderStyle: this._isDragging ? "solid" : "dashed", - backgroundColor: "rgba(255, 0, 0, 0.3)" } } ref={this._mainCont} > +

{this._text}

diff --git a/src/mobile/MobileInterface.scss b/src/mobile/MobileInterface.scss index 8b0ebcd53..8083e5760 100644 --- a/src/mobile/MobileInterface.scss +++ b/src/mobile/MobileInterface.scss @@ -1,15 +1,18 @@ .mobileInterface-inkInterfaceButtons { position: absolute; - top: -50px; + top: 0px; display: flex; justify-content: space-between; width: 100%; z-index: 9999; height: 50px; + + .mobileInterface-button { + height: 100%; + } } .mobileInterface-container { height: calc(100% - 50px); - margin-top: 50px; position: relative; } \ No newline at end of file diff --git a/src/mobile/MobileInterface.tsx b/src/mobile/MobileInterface.tsx index e21258c62..a3b956a15 100644 --- a/src/mobile/MobileInterface.tsx +++ b/src/mobile/MobileInterface.tsx @@ -34,6 +34,7 @@ import MarqueeOptionsMenu from '../client/views/collections/collectionFreeForm/M import GoogleAuthenticationManager from '../client/apis/GoogleAuthenticationManager'; import { listSpec } from '../new_fields/Schema'; import { Id } from '../new_fields/FieldSymbols'; +import { DocumentManager } from '../client/util/DocumentManager'; library.add(faLongArrowAltLeft); @@ -73,7 +74,6 @@ export default class MobileInterface extends React.Component { onSwitch && onSwitch(); this.renderView = renderView; - console.log("switching current view", renderView); } onSwitchInking = () => { @@ -87,22 +87,37 @@ export default class MobileInterface extends React.Component { }); } - onSwitchUpload = () => { + onSwitchUpload = async () => { + let width = 300; + let height = 300; + + // get width and height of the collection doc + if (this.mainContainer) { + const data = Cast(this.mainContainer.data, listSpec(Doc)); + if (data) { + const collectionDoc = await data[1]; // this should be the collection doc since the positions should be locked + const docView = DocumentManager.Instance.getDocumentView(collectionDoc); + if (docView) { + width = docView.nativeWidth ? docView.nativeWidth : 300; + height = docView.nativeHeight ? docView.nativeHeight : 300; + } + } + } DocServer.Mobile.dispatchOverlayTrigger({ enableOverlay: true, - width: 100, - height: 100 + width: width, + height: height, + text: "Documents uploaded from mobile will show here", }); } renderDefaultContent = () => { - console.log("rendering default content", this.mainContainer); if (this.mainContainer) { return { console.log("want to add doc to default content", StrCast(doc.title)); return false; }} + addDocument={returnFalse} addDocTab={returnFalse} pinToPres={emptyFunction} removeDocument={undefined} @@ -142,7 +157,6 @@ export default class MobileInterface extends React.Component { } shiftLeft = (e: React.MouseEvent) => { - console.log("shift left!"); DocServer.Mobile.dispatchOverlayPositionUpdate({ dx: -10 }); @@ -203,17 +217,16 @@ export default class MobileInterface extends React.Component { } } - upload = async (e: React.MouseEvent, asCollection: boolean) => { + upload = async (e: React.MouseEvent) => { if (this.mainContainer) { const data = Cast(this.mainContainer.data, listSpec(Doc)); if (data) { - const uploadDoc = await data[1]; // TODO: ensure this is the collection to upload - - console.log("UPLOADING DOCUMENT FROM MOBILE", uploadDoc[Id], StrCast(uploadDoc.proto!.title)); + const collectionDoc = await data[1]; // this should be the collection doc since the positions should be locked + const children = Cast(collectionDoc.data, listSpec(Doc), []); + const uploadDoc = children.length === 1 ? await children[0] : collectionDoc; if (uploadDoc) { DocServer.Mobile.dispatchMobileDocumentUpload({ docId: uploadDoc[Id], - asCollection: asCollection }); } } @@ -231,15 +244,14 @@ export default class MobileInterface extends React.Component {
- - +
{ console.log("want to add doc", StrCast(doc.title)); return false; }} + addDocument={returnFalse} addDocTab={returnFalse} pinToPres={emptyFunction} removeDocument={undefined} diff --git a/src/server/Message.ts b/src/server/Message.ts index 6dac37a46..b7bf2e81e 100644 --- a/src/server/Message.ts +++ b/src/server/Message.ts @@ -55,6 +55,7 @@ export interface MobileInkOverlayContent { readonly enableOverlay: boolean; readonly width?: number; readonly height?: number; + readonly text?: string; } export interface UpdateMobileInkOverlayPositionContent { @@ -65,7 +66,6 @@ export interface UpdateMobileInkOverlayPositionContent { export interface MobileDocumentUploadContent { readonly docId: string; - readonly asCollection: boolean; } export namespace MessageStore { diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index 3e5953ac1..491685e18 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -102,9 +102,9 @@ export class CurrentUserUtils { { title: "use eraser", icon: "eraser", click: 'activateEraser(this.activePen.pen = sameDocs(this.activePen.pen, this) ? undefined : this);', ischecked: `sameDocs(this.activePen.pen, this)`, backgroundColor: "pink", activePen: doc }, { title: "use scrubber", icon: "eraser", click: 'activateScrubber(this.activePen.pen = sameDocs(this.activePen.pen, this) ? undefined : this);', ischecked: `sameDocs(this.activePen.pen, this)`, backgroundColor: "green", activePen: doc }, { title: "use drag", icon: "mouse-pointer", click: 'deactivateInk();this.activePen.pen = this;', ischecked: `sameDocs(this.activePen.pen, this)`, backgroundColor: "white", activePen: doc }, - { title: "draw", icon: "pen-nib", click: 'switchMobileView(setupMobileInkingDoc, renderMobileInking, onSwitchMobileInking);', ischecked: `sameDocs(this.activePen.pen, this)`, backgroundColor: "red", activePen: doc }, + // { title: "draw", icon: "pen-nib", click: 'switchMobileView(setupMobileInkingDoc, renderMobileInking, onSwitchMobileInking);', ischecked: `sameDocs(this.activePen.pen, this)`, backgroundColor: "red", activePen: doc }, { title: "upload", icon: "upload", click: 'switchMobileView(setupMobileUploadDoc, renderMobileUpload, onSwitchMobileUpload);', backgroundColor: "orange" }, - { title: "upload", icon: "upload", click: 'uploadImageMobile();', backgroundColor: "cyan" }, + // { title: "upload", icon: "upload", click: 'uploadImageMobile();', backgroundColor: "cyan" }, ]; return docProtoData.filter(d => !buttons || !buttons.includes(d.title)).map(data => Docs.Create.FontIconDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, dropAction: data.click ? "copy" : undefined, title: data.title, icon: data.icon, ignoreClick: data.ignoreClick, @@ -138,9 +138,7 @@ export class CurrentUserUtils { } static setupMobileDoc(userDoc: Doc) { - const webDoc = Docs.Create.WebDocument("https://wikipedia.com", { title: "Mobile Upload Web", chromeStatus: "enabled" }); - - return userDoc.activeMoble ?? Docs.Create.MasonryDocument([webDoc, ...CurrentUserUtils.setupMobileButtons(userDoc)], { + return userDoc.activeMoble ?? Docs.Create.MasonryDocument(CurrentUserUtils.setupMobileButtons(userDoc), { columnWidth: 100, ignoreClick: true, lockedPosition: true, chromeStatus: "disabled", title: "buttons", autoHeight: true, yMargin: 5 }); } @@ -150,14 +148,15 @@ export class CurrentUserUtils { } static setupMobileUploadDoc(userDoc: Doc) { - const webDoc = Docs.Create.WebDocument("https://yahoo.com", { title: "Upload Images From the Web", chromeStatus: "enabled" }); - const uploadDoc = Docs.Create.StackingDocument([], { title: "Mobile Upload Collection", backgroundColor: "pink" }); - console.log("window size", window.innerWidth, window.innerHeight); - // return Docs.Create.StackingDocument([webDoc, uploadDoc], { - // columnWidth: window.innerWidth, //ignoreClick: true, lockedPosition: true, chromeStatus: "disabled", title: "Mobile Upload", autoHeight: true, yMargin: 5 - // }); - return Docs.Create.StackingDocument([webDoc, uploadDoc], {//...CurrentUserUtils.setupMobileButtons(userDoc)], { - columnWidth: 100, lockedPosition: true, chromeStatus: "disabled", title: "Upload", autoHeight: true, yMargin: 30 + const webDoc = Docs.Create.WebDocument("https://www.britannica.com/animal/cat", { + title: "Upload Images From the Web", chromeStatus: "enabled", lockedPosition: true + }); + const uploadDoc = Docs.Create.StackingDocument([], { + title: "Mobile Upload Collection", backgroundColor: "white", lockedPosition: true + }); + console.log(window.innerWidth, screen.width, window.devicePixelRatio); + return Docs.Create.StackingDocument([webDoc, uploadDoc], { + columnWidth: screen.width - 10, lockedPosition: true, chromeStatus: "disabled", title: "Upload", autoHeight: true, yMargin: 80, backgroundColor: "lightgray" }); } -- cgit v1.2.3-70-g09d2 From 864cba561db8e26240b093da7ab524e76c8823d1 Mon Sep 17 00:00:00 2001 From: andrewdkim Date: Tue, 11 Feb 2020 22:47:23 -0500 Subject: small fixes for mobile remote upload --- package-lock.json | 41 ++++++++++++++++------ src/client/views/nodes/WebBox.tsx | 12 +++++-- src/mobile/MobileInkOverlay.scss | 5 +-- src/mobile/MobileInterface.scss | 2 +- src/mobile/MobileInterface.tsx | 8 +++-- src/server/DashSession/DashSessionAgent.ts | 21 ++++++----- .../authentication/models/current_user_utils.ts | 3 +- src/server/index.ts | 2 +- 8 files changed, 63 insertions(+), 31 deletions(-) (limited to 'src/mobile/MobileInterface.scss') diff --git a/package-lock.json b/package-lock.json index 5492f7dbf..1741b50dc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5682,7 +5682,8 @@ }, "ansi-regex": { "version": "2.1.1", - "bundled": true + "bundled": true, + "optional": true }, "aproba": { "version": "1.2.0", @@ -5700,11 +5701,13 @@ }, "balanced-match": { "version": "1.0.0", - "bundled": true + "bundled": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -5717,15 +5720,18 @@ }, "code-point-at": { "version": "1.1.0", - "bundled": true + "bundled": true, + "optional": true }, "concat-map": { "version": "0.0.1", - "bundled": true + "bundled": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", - "bundled": true + "bundled": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -5828,7 +5834,8 @@ }, "inherits": { "version": "2.0.4", - "bundled": true + "bundled": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -5838,6 +5845,7 @@ "is-fullwidth-code-point": { "version": "1.0.0", "bundled": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -5850,17 +5858,20 @@ "minimatch": { "version": "3.0.4", "bundled": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } }, "minimist": { "version": "0.0.8", - "bundled": true + "bundled": true, + "optional": true }, "minipass": { "version": "2.9.0", "bundled": true, + "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -5877,6 +5888,7 @@ "mkdirp": { "version": "0.5.1", "bundled": true, + "optional": true, "requires": { "minimist": "0.0.8" } @@ -5957,7 +5969,8 @@ }, "number-is-nan": { "version": "1.0.1", - "bundled": true + "bundled": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -5967,6 +5980,7 @@ "once": { "version": "1.4.0", "bundled": true, + "optional": true, "requires": { "wrappy": "1" } @@ -6042,7 +6056,8 @@ }, "safe-buffer": { "version": "5.1.2", - "bundled": true + "bundled": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -6072,6 +6087,7 @@ "string-width": { "version": "1.0.2", "bundled": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -6089,6 +6105,7 @@ "strip-ansi": { "version": "3.0.1", "bundled": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -6127,11 +6144,13 @@ }, "wrappy": { "version": "1.0.2", - "bundled": true + "bundled": true, + "optional": true }, "yallist": { "version": "3.1.1", - "bundled": true + "bundled": true, + "optional": true } } }, diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index d486253b8..6cae4e878 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -193,9 +193,17 @@ export class WebBox extends DocAnnotatableComponent const B = this._iframeRef.current.getBoundingClientRect(); const iframeDoc = this._iframeRef.current.contentDocument; if (B && iframeDoc) { - // TODO: this only works when scale = 1 + // check if there is selected text + const selectedText = iframeDoc.getSelection(); + if (selectedText && selectedText.toString.length > -1) { + + } + console.log("selectedText", selectedText ? selectedText.toString() : ""); + + // TODO: this only works when scale = 1 as it is currently only inteded for mobile upload const element = iframeDoc.elementFromPoint(this._pressX - B.left, this._pressY - B.top); - if (element && element.nodeName === "IMG") { + console.log("found element", element, element && element.nodeName); + if (element && element.nodeName) {//} === "IMG") { pressedBound = element.getBoundingClientRect(); pressedElement = element.cloneNode(true) as HTMLElement; } diff --git a/src/mobile/MobileInkOverlay.scss b/src/mobile/MobileInkOverlay.scss index 0b4484519..b9c1fb146 100644 --- a/src/mobile/MobileInkOverlay.scss +++ b/src/mobile/MobileInkOverlay.scss @@ -1,10 +1,11 @@ .mobileInkOverlay { - border: 5px dashed red; + border: 10px dashed red; background-color: rgba(0, 0, 0, .05); } .mobileInkOverlay-border { - // background-color: rgba(0, 255, 0, .4); position: absolute; + // background-color: rgba(0, 255, 0, .4); + position: absolute; pointer-events: auto; cursor: pointer; diff --git a/src/mobile/MobileInterface.scss b/src/mobile/MobileInterface.scss index 8083e5760..d0849dbc7 100644 --- a/src/mobile/MobileInterface.scss +++ b/src/mobile/MobileInterface.scss @@ -13,6 +13,6 @@ } .mobileInterface-container { - height: calc(100% - 50px); + height: 100%; position: relative; } \ No newline at end of file diff --git a/src/mobile/MobileInterface.tsx b/src/mobile/MobileInterface.tsx index 07ee611ee..83410b99d 100644 --- a/src/mobile/MobileInterface.tsx +++ b/src/mobile/MobileInterface.tsx @@ -3,7 +3,7 @@ import { observer } from 'mobx-react'; import { computed, action, observable } from 'mobx'; import { CurrentUserUtils } from '../server/authentication/models/current_user_utils'; import { FieldValue, Cast, StrCast } from '../new_fields/Types'; -import { Doc } from '../new_fields/Doc'; +import { Doc, DocListCast } from '../new_fields/Doc'; import { Docs } from '../client/documents/Documents'; import { CollectionView } from '../client/views/collections/CollectionView'; import { DocumentView } from '../client/views/nodes/DocumentView'; @@ -220,8 +220,10 @@ export default class MobileInterface extends React.Component { const data = Cast(this.mainContainer.data, listSpec(Doc)); if (data) { const collectionDoc = await data[1]; // this should be the collection doc since the positions should be locked - const children = Cast(collectionDoc.data, listSpec(Doc), []); - const uploadDoc = children.length === 1 ? await children[0] : collectionDoc; + const children = DocListCast(collectionDoc.data); + const uploadDoc = children.length === 1 ? children[0] : Docs.Create.StackingDocument(children, { + title: "Mobile Upload Collection", backgroundColor: "white", lockedPosition: true, _width: 300, _height: 300 + }); if (uploadDoc) { DocServer.Mobile.dispatchMobileDocumentUpload({ docId: uploadDoc[Id], diff --git a/src/server/DashSession/DashSessionAgent.ts b/src/server/DashSession/DashSessionAgent.ts index c55e01243..44f77c049 100644 --- a/src/server/DashSession/DashSessionAgent.ts +++ b/src/server/DashSession/DashSessionAgent.ts @@ -25,15 +25,18 @@ export class DashSessionAgent extends AppliedSessionAgent { * The core method invoked when the single master thread is initialized. * Installs event hooks, repl commands and additional IPC listeners. */ - protected async initializeMonitor(monitor: Monitor, sessionKey: string): Promise { - await this.dispatchSessionPassword(sessionKey); - monitor.addReplCommand("pull", [], () => monitor.exec("git pull")); - monitor.addReplCommand("solr", [/start|stop|index/], this.executeSolrCommand); - monitor.addReplCommand("backup", [], this.backup); - monitor.addReplCommand("debug", [/\S+\@\S+/], async ([to]) => this.dispatchZippedDebugBackup(to)); - monitor.on("backup", this.backup); - monitor.on("debug", async ({ to }) => this.dispatchZippedDebugBackup(to)); - monitor.coreHooks.onCrashDetected(this.dispatchCrashReport); + // protected async initializeMonitor(monitor: Monitor, sessionKey: string): Promise { + protected async initializeMonitor(monitor: Monitor): Promise { + + // await this.dispatchSessionPassword(sessionKey); + // monitor.addReplCommand("pull", [], () => monitor.exec("git pull")); + // monitor.addReplCommand("solr", [/start|stop|index/], this.executeSolrCommand); + // monitor.addReplCommand("backup", [], this.backup); + // monitor.addReplCommand("debug", [/\S+\@\S+/], async ([to]) => this.dispatchZippedDebugBackup(to)); + // monitor.on("backup", this.backup); + // monitor.on("debug", async ({ to }) => this.dispatchZippedDebugBackup(to)); + // monitor.coreHooks.onCrashDetected(this.dispatchCrashReport); + return ""; } /** diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index aa9f3649e..6c916689a 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -161,9 +161,8 @@ export class CurrentUserUtils { const uploadDoc = Docs.Create.StackingDocument([], { title: "Mobile Upload Collection", backgroundColor: "white", lockedPosition: true }); - console.log(window.innerWidth, screen.width, window.devicePixelRatio); return Docs.Create.StackingDocument([webDoc, uploadDoc], { - columnWidth: screen.width - 10, lockedPosition: true, _chromeStatus: "disabled", title: "Upload", _autoHeight: true, _yMargin: 80, backgroundColor: "lightgray" + _width: screen.width, lockedPosition: true, _chromeStatus: "disabled", title: "Upload", _autoHeight: true, _yMargin: 80, backgroundColor: "lightgray" }); } diff --git a/src/server/index.ts b/src/server/index.ts index 313a2f0e2..55ba71dba 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -141,7 +141,7 @@ export async function launchServer() { * So, the 'else' clause is exactly what we've always run when executing npm start. */ if (process.env.RELEASE) { - (sessionAgent = new DashSessionAgent()).launch(); + // (sessionAgent = new DashSessionAgent()).launch(); } else { launchServer(); } -- cgit v1.2.3-70-g09d2