From 086391b7e45ed4b3cb29602a776f5812f142fff2 Mon Sep 17 00:00:00 2001
From: Sam Wilkins <abdullah_ahmed@brown.edu>
Date: Wed, 8 May 2019 22:30:46 -0400
Subject: restoration of cursor functionality: cursor field

---
 .../CollectionFreeFormRemoteCursors.tsx            | 66 +++++++++++++---------
 1 file changed, 38 insertions(+), 28 deletions(-)

(limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.tsx')

diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.tsx
index 036745eca..c22f430ac 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.tsx
@@ -1,26 +1,38 @@
 import { computed } from "mobx";
 import { observer } from "mobx-react";
-import { CollectionViewProps, CursorEntry } from "../CollectionSubView";
+import { CollectionViewProps } from "../CollectionSubView";
 import "./CollectionFreeFormView.scss";
 import React = require("react");
 import v5 = require("uuid/v5");
 import { CurrentUserUtils } from "../../../../server/authentication/models/current_user_utils";
+import CursorField from "../../../../new_fields/CursorField";
+import { List } from "../../../../new_fields/List";
+import { Cast } from "../../../../new_fields/Types";
+import { listSpec } from "../../../../new_fields/Schema";
 
 @observer
 export class CollectionFreeFormRemoteCursors extends React.Component<CollectionViewProps> {
-    protected getCursors(): CursorEntry[] {
+
+    protected getCursors(): CursorField[] {
         let doc = this.props.Document;
+
         let id = CurrentUserUtils.id;
-        let cursors = doc.GetList(KeyStore.Cursors, [] as CursorEntry[]);
-        let notMe = cursors.filter(entry => entry.Data[0][0] !== id);
-        return id ? notMe : [];
+        if (!id) {
+            return [];
+        }
+
+        let cursors = Cast(doc.cursors, listSpec(CursorField));
+        if (!cursors) {
+            doc.cursors = cursors = new List<CursorField>();
+        }
+
+        return cursors.filter(cursor => cursor.data.metadata.id !== id);
     }
 
     private crosshairs?: HTMLCanvasElement;
     drawCrosshairs = (backgroundColor: string) => {
         if (this.crosshairs) {
-            let c = this.crosshairs;
-            let ctx = c.getContext('2d');
+            let ctx = this.crosshairs.getContext('2d');
             if (ctx) {
                 ctx.fillStyle = backgroundColor;
                 ctx.fillRect(0, 0, 20, 20);
@@ -49,29 +61,27 @@ export class CollectionFreeFormRemoteCursors extends React.Component<CollectionV
             }
         }
     }
+
     @computed
     get sharedCursors() {
-        return this.getCursors().map(entry => {
-            if (entry.Data.length > 0) {
-                let id = entry.Data[0][0];
-                let email = entry.Data[0][1];
-                let point = entry.Data[1];
-                this.drawCrosshairs("#" + v5(id, v5.URL).substring(0, 6).toUpperCase() + "22");
-                return (
-                    <div key={id} className="collectionFreeFormRemoteCursors-cont"
-                        style={{ transform: `translate(${point[0] - 10}px, ${point[1] - 10}px)` }}
-                    >
-                        <canvas className="collectionFreeFormRemoteCursors-canvas"
-                            ref={(el) => { if (el) this.crosshairs = el; }}
-                            width={20}
-                            height={20}
-                        />
-                        <p className="collectionFreeFormRemoteCursors-symbol">
-                            {email[0].toUpperCase()}
-                        </p>
-                    </div>
-                );
-            }
+        return this.getCursors().map(c => {
+            let m = c.data.metadata;
+            let l = c.data.position;
+            this.drawCrosshairs("#" + v5(m.id, v5.URL).substring(0, 6).toUpperCase() + "22");
+            return (
+                <div key={m.id} className="collectionFreeFormRemoteCursors-cont"
+                    style={{ transform: `translate(${l.x - 10}px, ${l.y - 10}px)` }}
+                >
+                    <canvas className="collectionFreeFormRemoteCursors-canvas"
+                        ref={(el) => { if (el) this.crosshairs = el; }}
+                        width={20}
+                        height={20}
+                    />
+                    <p className="collectionFreeFormRemoteCursors-symbol">
+                        {m.identifier[0].toUpperCase()}
+                    </p>
+                </div>
+            );
         });
     }
 
-- 
cgit v1.2.3-70-g09d2


From cfb7fdb1a7b2db263502677e57ee882a6fe23f13 Mon Sep 17 00:00:00 2001
From: Tyler Schicke <tyler_schicke@brown.edu>
Date: Tue, 21 May 2019 12:29:28 -0400
Subject: Made cursors disappear after 1 second

---
 package.json                                                     | 1 +
 src/client/views/collections/CollectionSubView.tsx               | 6 ++----
 .../collectionFreeForm/CollectionFreeFormRemoteCursors.tsx       | 5 ++++-
 src/new_fields/CursorField.ts                                    | 9 ++++++---
 4 files changed, 13 insertions(+), 8 deletions(-)

(limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.tsx')

diff --git a/package.json b/package.json
index 790535728..aa4abb0a5 100644
--- a/package.json
+++ b/package.json
@@ -126,6 +126,7 @@
         "mobx": "^5.9.0",
         "mobx-react": "^5.3.5",
         "mobx-react-devtools": "^6.1.1",
+        "mobx-utils": "^5.4.0",
         "mongodb": "^3.1.13",
         "mongoose": "^5.4.18",
         "node-sass": "^4.12.0",
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 864fdfa4b..7800b35df 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -16,9 +16,7 @@ import { listSpec } from "../../../new_fields/Schema";
 import { Cast, PromiseValue, FieldValue, ListSpec } from "../../../new_fields/Types";
 import { List } from "../../../new_fields/List";
 import { DocServer } from "../../DocServer";
-import { ObjectField } from "../../../new_fields/ObjectField";
-import CursorField, { CursorPosition, CursorMetadata } from "../../../new_fields/CursorField";
-import { url } from "inspector";
+import CursorField from "../../../new_fields/CursorField";
 
 export interface CollectionViewProps extends FieldViewProps {
     addDocument: (document: Doc, allowDuplicates?: boolean) => boolean;
@@ -72,7 +70,7 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) {
                 if (cursors.length > 0 && (ind = cursors.findIndex(entry => entry.data.metadata.id === id)) > -1) {
                     cursors[ind].setPosition(pos);
                 } else {
-                    let entry = new CursorField({ metadata: { id: id, identifier: email }, position: pos });
+                    let entry = new CursorField({ metadata: { id: id, identifier: email, timestamp: Date.now() }, position: pos });
                     cursors.push(entry);
                 }
             }
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.tsx
index 642118d75..2838b7905 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.tsx
@@ -9,6 +9,7 @@ import CursorField from "../../../../new_fields/CursorField";
 import { List } from "../../../../new_fields/List";
 import { Cast } from "../../../../new_fields/Types";
 import { listSpec } from "../../../../new_fields/Schema";
+import * as mobxUtils from 'mobx-utils';
 
 @observer
 export class CollectionFreeFormRemoteCursors extends React.Component<CollectionViewProps> {
@@ -23,7 +24,9 @@ export class CollectionFreeFormRemoteCursors extends React.Component<CollectionV
 
         let cursors = Cast(doc.cursors, listSpec(CursorField));
 
-        return (cursors || []).filter(cursor => cursor.data.metadata.id !== id);
+        const now = mobxUtils.now();
+        // const now = Date.now();
+        return (cursors || []).filter(cursor => cursor.data.metadata.id !== id && (now - cursor.data.metadata.timestamp) < 1000);
     }
 
     private crosshairs?: HTMLCanvasElement;
diff --git a/src/new_fields/CursorField.ts b/src/new_fields/CursorField.ts
index 1be1ec3e0..fd86031a8 100644
--- a/src/new_fields/CursorField.ts
+++ b/src/new_fields/CursorField.ts
@@ -1,7 +1,7 @@
 import { ObjectField } from "./ObjectField";
 import { observable } from "mobx";
 import { Deserializable } from "../client/util/SerializationHelper";
-import { serializable, createSimpleSchema, object } from "serializr";
+import { serializable, createSimpleSchema, object, date } from "serializr";
 import { OnUpdate, ToScriptString, Copy } from "./FieldSymbols";
 
 export type CursorPosition = {
@@ -11,7 +11,8 @@ export type CursorPosition = {
 
 export type CursorMetadata = {
     id: string,
-    identifier: string
+    identifier: string,
+    timestamp: number
 };
 
 export type CursorData = {
@@ -26,7 +27,8 @@ const PositionSchema = createSimpleSchema({
 
 const MetadataSchema = createSimpleSchema({
     id: true,
-    identifier: true
+    identifier: true,
+    timestamp: true
 });
 
 const CursorSchema = createSimpleSchema({
@@ -47,6 +49,7 @@ export default class CursorField extends ObjectField {
 
     setPosition(position: CursorPosition) {
         this.data.position = position;
+        this.data.metadata.timestamp = Date.now();
         this[OnUpdate]();
     }
 
-- 
cgit v1.2.3-70-g09d2

