From d2c9550f23c4e5654822ac01b973bb965e3f6dec Mon Sep 17 00:00:00 2001
From: Sam Wilkins <samuel_wilkins@brown.edu>
Date: Fri, 14 Jun 2019 20:49:12 -0400
Subject: cleaned up Docs namespace and thoroughly documented
 DocServer.GetRefFields

---
 src/client/views/collections/CollectionVideoView.tsx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

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

diff --git a/src/client/views/collections/CollectionVideoView.tsx b/src/client/views/collections/CollectionVideoView.tsx
index 7853544d5..bd5cd5450 100644
--- a/src/client/views/collections/CollectionVideoView.tsx
+++ b/src/client/views/collections/CollectionVideoView.tsx
@@ -98,7 +98,7 @@ export class CollectionVideoView extends React.Component<FieldViewProps> {
                 SearchBox.convertDataUri(dataUrl, filename).then((returnedFilename) => {
                     if (returnedFilename) {
                         let url = DocServer.prepend(returnedFilename);
-                        let imageSummary = Docs.ImageDocument(url, {
+                        let imageSummary = Docs.Create.ImageDocument(url, {
                             x: NumCast(this.props.Document.x) + width, y: NumCast(this.props.Document.y),
                             width: 150, height: height / width * 150, title: "--snapshot" + NumCast(this.props.Document.curPage) + " image-"
                         });
-- 
cgit v1.2.3-70-g09d2


From de0304b2966ebdede9d9db8c510e19020046115c Mon Sep 17 00:00:00 2001
From: Sam Wilkins <samuel_wilkins@brown.edu>
Date: Mon, 17 Jun 2019 13:38:15 -0400
Subject: peripheral renaming fixes

---
 src/client/documents/Documents.ts                              |  4 ++--
 src/client/util/History.ts                                     |  6 +++---
 src/client/util/SearchUtil.ts                                  |  4 ++--
 src/client/util/TooltipTextMenu.tsx                            |  8 ++++----
 src/client/views/MainView.tsx                                  | 10 +++++-----
 src/client/views/SearchBox.tsx                                 |  6 +++---
 src/client/views/collections/CollectionDockingView.tsx         | 10 +++++-----
 src/client/views/collections/CollectionSubView.tsx             |  8 ++++----
 src/client/views/collections/CollectionVideoView.tsx           |  2 +-
 src/client/views/collections/DockedFrameRenderer.tsx           |  2 +-
 .../collections/collectionFreeForm/CollectionFreeFormView.tsx  |  4 ++--
 .../views/collections/collectionFreeForm/MarqueeView.tsx       |  2 +-
 src/client/views/nodes/DocumentView.tsx                        |  2 +-
 src/client/views/nodes/FormattedTextBox.tsx                    |  6 +++---
 src/client/views/nodes/PDFBox.tsx                              |  2 +-
 src/client/views/nodes/VideoBox.tsx                            |  2 +-
 src/debug/Viewer.tsx                                           |  2 +-
 src/mobile/ImageUpload.tsx                                     |  4 ++--
 src/new_fields/Proxy.ts                                        |  2 +-
 src/server/authentication/models/current_user_utils.ts         |  6 +++---
 20 files changed, 46 insertions(+), 46 deletions(-)

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

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index b10954636..758291b9b 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -98,7 +98,7 @@ export namespace Docs {
             // non-guid string ids for each document prototype
             let protoIds = [textProtoId, histoProtoId, collProtoId, imageProtoId, webProtoId, kvpProtoId, videoProtoId, audioProtoId, pdfProtoId, iconProtoId]
             // fetch the actual prototype documents from the server
-            let actualProtos = await DocServer.GetRefFields(protoIds);
+            let actualProtos = await DocServer.getRefFields(protoIds);
 
             // initialize prototype documents
             textProto = actualProtos[textProtoId] as Doc || CreateTextProto();
@@ -363,7 +363,7 @@ export namespace Docs {
                 CurrentUserUtils.AddNorthstarSchema(schema, schemaDoc);
                 const docs = schemaDocuments;
                 CurrentUserUtils.GetAllNorthstarColumnAttributes(schema).map(attr => {
-                    DocServer.GetRefField(attr.displayName! + ".alias").then(action((field: Opt<Field>) => {
+                    DocServer.getRefField(attr.displayName! + ".alias").then(action((field: Opt<Field>) => {
                         if (field instanceof Doc) {
                             docs.push(field);
                         } else {
diff --git a/src/client/util/History.ts b/src/client/util/History.ts
index 545ea8629..94bfcbe09 100644
--- a/src/client/util/History.ts
+++ b/src/client/util/History.ts
@@ -88,7 +88,7 @@ export namespace HistoryUtil {
     }
 
     export function createUrl(params: ParsedUrl): string {
-        let baseUrl = DocServer.prepend(`/${params.type}`);
+        let baseUrl = DocServer.Util.prepend(`/${params.type}`);
         switch (params.type) {
             case "doc":
                 const initializers = encodeURIComponent(JSON.stringify(params.initializers));
@@ -103,7 +103,7 @@ export namespace HistoryUtil {
     }
 
     export async function initDoc(id: string, initializer: DocInitializerList) {
-        const doc = await DocServer.GetRefField(id);
+        const doc = await DocServer.getRefField(id);
         if (!(doc instanceof Doc)) {
             return;
         }
@@ -111,7 +111,7 @@ export namespace HistoryUtil {
     }
 
     async function onDocUrl(url: DocUrl) {
-        const field = await DocServer.GetRefField(url.docId);
+        const field = await DocServer.getRefField(url.docId);
         await Promise.all(Object.keys(url.initializers).map(id => initDoc(id, url.initializers[id])));
         if (field instanceof Doc) {
             MainView.Instance.openWorkspace(field, true);
diff --git a/src/client/util/SearchUtil.ts b/src/client/util/SearchUtil.ts
index 28ec8ca14..9dd9acbb7 100644
--- a/src/client/util/SearchUtil.ts
+++ b/src/client/util/SearchUtil.ts
@@ -7,13 +7,13 @@ export namespace SearchUtil {
     export function Search(query: string, returnDocs: true): Promise<Doc[]>;
     export function Search(query: string, returnDocs: false): Promise<string[]>;
     export async function Search(query: string, returnDocs: boolean) {
-        const ids = JSON.parse(await rp.get(DocServer.prepend("/search"), {
+        const ids = JSON.parse(await rp.get(DocServer.Util.prepend("/search"), {
             qs: { query }
         }));
         if (!returnDocs) {
             return ids;
         }
-        const docMap = await DocServer.GetRefFields(ids);
+        const docMap = await DocServer.getRefFields(ids);
         return ids.map((id: string) => docMap[id]).filter((doc: any) => doc instanceof Doc);
     }
 
diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx
index fa2483db5..36219a99e 100644
--- a/src/client/util/TooltipTextMenu.tsx
+++ b/src/client/util/TooltipTextMenu.tsx
@@ -187,9 +187,9 @@ export class TooltipTextMenu {
                 let link = node && node.marks.find(m => m.type.name === "link");
                 if (link) {
                     let href: string = link.attrs.href;
-                    if (href.indexOf(DocServer.prepend("/doc/")) === 0) {
-                        let docid = href.replace(DocServer.prepend("/doc/"), "");
-                        DocServer.GetRefField(docid).then(action((f: Opt<Field>) => {
+                    if (href.indexOf(DocServer.Util.prepend("/doc/")) === 0) {
+                        let docid = href.replace(DocServer.Util.prepend("/doc/"), "");
+                        DocServer.getRefField(docid).then(action((f: Opt<Field>) => {
                             if (f instanceof Doc) {
                                 if (DocumentManager.Instance.getDocumentView(f)) {
                                     DocumentManager.Instance.getDocumentView(f)!.props.focus(f);
@@ -218,7 +218,7 @@ export class TooltipTextMenu {
                         handlers: {
                             dragComplete: action(() => {
                                 let m = dragData.droppedDocuments;
-                                this.makeLink(DocServer.prepend("/doc/" + m[0][Id]));
+                                this.makeLink(DocServer.Util.prepend("/doc/" + m[0][Id]));
                             }),
                         },
                         hideSource: false
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 984db0426..734961b56 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -76,11 +76,11 @@ export class MainView extends React.Component {
         // causes errors to be generated when modifying an observable outside of an action
         configure({ enforceActions: "observed" });
         if (window.location.search.includes("readonly")) {
-            DocServer.makeReadOnly();
+            DocServer.Util.makeReadOnly();
         }
         if (window.location.search.includes("safe")) {
             if (!window.location.search.includes("nro")) {
-                DocServer.makeReadOnly();
+                DocServer.Util.makeReadOnly();
             }
             CollectionBaseView.SetSafeMode(true);
         }
@@ -141,7 +141,7 @@ export class MainView extends React.Component {
                 this.createNewWorkspace();
             }
         } else {
-            DocServer.GetRefField(CurrentUserUtils.MainDocId).then(field =>
+            DocServer.getRefField(CurrentUserUtils.MainDocId).then(field =>
                 field instanceof Doc ? this.openWorkspace(field) :
                     this.createNewWorkspace(CurrentUserUtils.MainDocId));
         }
@@ -294,7 +294,7 @@ export class MainView extends React.Component {
         let logoutRef = React.createRef<HTMLDivElement>();
 
         return [
-            <button className="clear-db-button" key="clear-db" onClick={e => e.shiftKey && e.altKey && DocServer.DeleteDatabase()}>Clear Database</button>,
+            <button className="clear-db-button" key="clear-db" onClick={e => e.shiftKey && e.altKey && DocServer.Util.deleteDatabase()}>Clear Database</button>,
             <div id="toolbar" key="toolbar">
                 <div ref={notifsRef}>
                     <button className="toolbar-button round-button" title="Notifs"
@@ -312,7 +312,7 @@ export class MainView extends React.Component {
             </div >,
             this.isSearchVisible ? <div className="main-searchDiv" key="search" style={{ top: '34px', right: '1px', position: 'absolute' }} > <SearchBox /> </div> : null,
             <div className="main-buttonDiv" key="logout" style={{ bottom: '0px', right: '1px', position: 'absolute' }} ref={logoutRef}>
-                <button onClick={() => request.get(DocServer.prepend(RouteStore.logout), emptyFunction)}>Log Out</button></div>
+                <button onClick={() => request.get(DocServer.Util.prepend(RouteStore.logout), emptyFunction)}>Log Out</button></div>
         ];
 
     }
diff --git a/src/client/views/SearchBox.tsx b/src/client/views/SearchBox.tsx
index 7164d98a4..973715876 100644
--- a/src/client/views/SearchBox.tsx
+++ b/src/client/views/SearchBox.tsx
@@ -56,13 +56,13 @@ export class SearchBox extends React.Component {
 
     @action
     getResults = async (query: string) => {
-        let response = await rp.get(DocServer.prepend('/search'), {
+        let response = await rp.get(DocServer.Util.prepend('/search'), {
             qs: {
                 query
             }
         });
         let res: string[] = JSON.parse(response);
-        const fields = await DocServer.GetRefFields(res);
+        const fields = await DocServer.getRefFields(res);
         const docs: Doc[] = [];
         for (const id of res) {
             const field = fields[id];
@@ -74,7 +74,7 @@ export class SearchBox extends React.Component {
     }
     public static async convertDataUri(imageUri: string, returnedFilename: string) {
         try {
-            let posting = DocServer.prepend(RouteStore.dataUriToImage);
+            let posting = DocServer.Util.prepend(RouteStore.dataUriToImage);
             const returnedUri = await rp.post(posting, {
                 body: {
                     uri: imageUri,
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index e2bcb10ec..4f5837590 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -306,7 +306,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
             let y = e.clientY;
             let docid = (e.target as any).DashDocId;
             let tab = (e.target as any).parentElement as HTMLElement;
-            DocServer.GetRefField(docid).then(action(async (sourceDoc: Opt<Field>) =>
+            DocServer.getRefField(docid).then(action(async (sourceDoc: Opt<Field>) =>
                 (sourceDoc instanceof Doc) && DragLinksAsDocuments(tab, x, y, sourceDoc)));
         } else
             if ((className === "lm_title" || className === "lm_tab lm_active") && !e.shiftKey) {
@@ -320,7 +320,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
                 if (glTab && glTab.contentItem && glTab.contentItem.parent) {
                     glTab.contentItem.parent.setActiveContentItem(glTab.contentItem);
                 }
-                DocServer.GetRefField(docid).then(action((f: Opt<Field>) => {
+                DocServer.getRefField(docid).then(action((f: Opt<Field>) => {
                     if (f instanceof Doc) {
                         DragManager.StartDocumentDrag([tab], new DragManager.DocumentDragData([f]), x, y,
                             {
@@ -372,7 +372,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
             if (tab.contentItem.config.fixed) {
                 tab.contentItem.parent.config.fixed = true;
             }
-            DocServer.GetRefField(tab.contentItem.config.props.documentId).then(async doc => {
+            DocServer.getRefField(tab.contentItem.config.props.documentId).then(async doc => {
                 if (doc instanceof Doc) {
                     let counter: any = this.htmlToElement(`<span class="messageCounter">0</div>`);
                     tab.element.append(counter);
@@ -409,7 +409,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
                 if (tab.reactionDisposer) {
                     tab.reactionDisposer();
                 }
-                let doc = await DocServer.GetRefField(tab.contentItem.config.props.documentId);
+                let doc = await DocServer.getRefField(tab.contentItem.config.props.documentId);
                 if (doc instanceof Doc) {
                     let theDoc = doc;
                     CollectionDockingView.TopLevel._removedDocs.push(theDoc);
@@ -434,7 +434,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
                 //if (confirm('really close this?')) {
                 stack.remove();
                 stack.contentItems.map(async (contentItem: any) => {
-                    let doc = await DocServer.GetRefField(contentItem.config.props.documentId);
+                    let doc = await DocServer.getRefField(contentItem.config.props.documentId);
                     if (doc instanceof Doc) {
                         let theDoc = doc;
                         CollectionDockingView.TopLevel._removedDocs.push(theDoc);
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 440a2410b..36e276d13 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -133,7 +133,7 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) {
                 if (path.includes(window.location.hostname)) {
                     let s = path.split('/');
                     let id = s[s.length - 1];
-                    DocServer.GetRefField(id).then(field => {
+                    DocServer.getRefField(id).then(field => {
                         if (field instanceof Doc) {
                             let alias = Doc.MakeAlias(field);
                             alias.x = options.x || 0;
@@ -170,8 +170,8 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) {
             if (html && html.indexOf(document.location.origin)) { // prosemirror text containing link to dash document
                 let start = html.indexOf(window.location.origin);
                 let path = html.substr(start, html.length - start);
-                let docid = path.substr(0, path.indexOf("\">")).replace(DocServer.prepend("/doc/"), "").split("?")[0];
-                DocServer.GetRefField(docid).then(f => (f instanceof Doc) && this.props.addDocument(f, false));
+                let docid = path.substr(0, path.indexOf("\">")).replace(DocServer.Util.prepend("/doc/"), "").split("?")[0];
+                DocServer.getRefField(docid).then(f => (f instanceof Doc) && this.props.addDocument(f, false));
                 return;
             }
             if (html && html.indexOf("<img") !== 0 && !html.startsWith("<a")) {
@@ -194,7 +194,7 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) {
                 if (item.kind === "string" && item.type.indexOf("uri") !== -1) {
                     let str: string;
                     let prom = new Promise<string>(resolve => e.dataTransfer.items[i].getAsString(resolve))
-                        .then(action((s: string) => rp.head(DocServer.prepend(RouteStore.corsProxy + "/" + (str = s)))))
+                        .then(action((s: string) => rp.head(DocServer.Util.prepend(RouteStore.corsProxy + "/" + (str = s)))))
                         .then(result => {
                             let type = result["content-type"];
                             if (type) {
diff --git a/src/client/views/collections/CollectionVideoView.tsx b/src/client/views/collections/CollectionVideoView.tsx
index bd5cd5450..ccbac9915 100644
--- a/src/client/views/collections/CollectionVideoView.tsx
+++ b/src/client/views/collections/CollectionVideoView.tsx
@@ -97,7 +97,7 @@ export class CollectionVideoView extends React.Component<FieldViewProps> {
                 let filename = encodeURIComponent("snapshot" + this.props.Document.title + "_" + this.props.Document.curPage).replace(/\./g, "");
                 SearchBox.convertDataUri(dataUrl, filename).then((returnedFilename) => {
                     if (returnedFilename) {
-                        let url = DocServer.prepend(returnedFilename);
+                        let url = DocServer.Util.prepend(returnedFilename);
                         let imageSummary = Docs.Create.ImageDocument(url, {
                             x: NumCast(this.props.Document.x) + width, y: NumCast(this.props.Document.y),
                             width: 150, height: height / width * 150, title: "--snapshot" + NumCast(this.props.Document.curPage) + " image-"
diff --git a/src/client/views/collections/DockedFrameRenderer.tsx b/src/client/views/collections/DockedFrameRenderer.tsx
index 25d4b2a49..1e7c5661b 100644
--- a/src/client/views/collections/DockedFrameRenderer.tsx
+++ b/src/client/views/collections/DockedFrameRenderer.tsx
@@ -42,7 +42,7 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
     }
     constructor(props: any) {
         super(props);
-        DocServer.GetRefField(this.props.documentId).then(action((f: Opt<Field>) => this._document = f as Doc));
+        DocServer.getRefField(this.props.documentId).then(action((f: Opt<Field>) => this._document = f as Doc));
     }
 
     nativeWidth = () => NumCast(this._document!.nativeWidth, this._panelWidth);
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 9d19df540..cd613e6ab 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -235,8 +235,8 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
             e.preventDefault();
             let start = html.indexOf(window.location.origin);
             let path = html.substr(start, html.length - start);
-            let docid = path.substr(0, path.indexOf("\">")).replace(DocServer.prepend("/doc/"), "").split("?")[0];
-            DocServer.GetRefField(docid).then(f => {
+            let docid = path.substr(0, path.indexOf("\">")).replace(DocServer.Util.prepend("/doc/"), "").split("?")[0];
+            DocServer.getRefField(docid).then(f => {
                 if (f instanceof Doc) {
                     f.x = pt[0];
                     f.y = pt[1];
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index cd386abfa..07a58ed64 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -306,7 +306,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
                     let summary = Docs.Create.TextDocument({ x: bounds.left, y: bounds.top, width: 300, height: 100, backgroundColor: "#e2ad32" /* yellow */, title: "-summary-" });
                     SearchBox.convertDataUri(dataUrl, "icon" + summary[Id] + "_image").then((returnedFilename) => {
                         if (returnedFilename) {
-                            let url = DocServer.prepend(returnedFilename);
+                            let url = DocServer.Util.prepend(returnedFilename);
                             let imageSummary = Docs.Create.ImageDocument(url, {
                                 x: bounds.left, y: bounds.top + 100 / zoomBasis,
                                 width: 150, height: bounds.height / bounds.width * 150, title: "-summary image-"
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 16e40000d..fdcb20e9a 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -422,7 +422,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
             }, icon: "search"
         });
         cm.addItem({ description: "Center View", event: () => this.props.focus(this.props.Document), icon: "crosshairs" });
-        cm.addItem({ description: "Copy URL", event: () => Utils.CopyText(DocServer.prepend("/doc/" + this.props.Document[Id])), icon: "link" });
+        cm.addItem({ description: "Copy URL", event: () => Utils.CopyText(DocServer.Util.prepend("/doc/" + this.props.Document[Id])), icon: "link" });
         cm.addItem({ description: "Copy ID", event: () => Utils.CopyText(this.props.Document[Id]), icon: "fingerprint" });
         cm.addItem({ description: "Delete", event: this.deleteClicked, icon: "trash" });
         if (!this.topMost) {
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index d00a4b928..6a14a04f7 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -237,9 +237,9 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
                 href = parent.childNodes[0].href;
             }
             if (href) {
-                if (href.indexOf(DocServer.prepend("/doc/")) === 0) {
-                    let docid = href.replace(DocServer.prepend("/doc/"), "").split("?")[0];
-                    DocServer.GetRefField(docid).then(f => {
+                if (href.indexOf(DocServer.Util.prepend("/doc/")) === 0) {
+                    let docid = href.replace(DocServer.Util.prepend("/doc/"), "").split("?")[0];
+                    DocServer.getRefField(docid).then(f => {
                         (f instanceof Doc) && DocumentManager.Instance.jumpToDocument(f, ctrlKey, document => this.props.addDocTab(document, "inTab"))
                     });
                 }
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index aa29a7170..df9e49b64 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -257,7 +257,7 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
                 .then(action((dataUrl: string) => {
                     SearchBox.convertDataUri(dataUrl, "icon" + this.Document[Id] + "_" + this.curPage).then((returnedFilename) => {
                         if (returnedFilename) {
-                            let url = DocServer.prepend(returnedFilename);
+                            let url = DocServer.Util.prepend(returnedFilename);
                             this.props.Document.thumbnail = new ImageField(new URL(url));
                         }
                         runInAction(() => this._renderAsSvg = true);
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index 35ecf12f6..9ab607e91 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -97,7 +97,7 @@ export class VideoBox extends DocComponent<FieldViewProps, VideoDocument>(VideoD
             };
             try {
                 let responseSchema: any = {};
-                const videoInfoResponse = await rp.get(DocServer.prepend(RouteStore.corsProxy + "/" + `https://www.youtube.com/watch?v=${videoId}`), videoInfoRequestConfig);
+                const videoInfoResponse = await rp.get(DocServer.Util.prepend(RouteStore.corsProxy + "/" + `https://www.youtube.com/watch?v=${videoId}`), videoInfoRequestConfig);
                 const dataHtml = videoInfoResponse;
                 const start = dataHtml.indexOf('ytplayer.config = ') + 18;
                 const end = dataHtml.indexOf(';ytplayer.load');
diff --git a/src/debug/Viewer.tsx b/src/debug/Viewer.tsx
index b22300d0b..753149756 100644
--- a/src/debug/Viewer.tsx
+++ b/src/debug/Viewer.tsx
@@ -146,7 +146,7 @@ class Viewer extends React.Component {
     @action
     onKeyPress = (e: React.KeyboardEvent<HTMLDivElement>) => {
         if (e.key === "Enter") {
-            DocServer.GetRefField(this.idToAdd).then(action((field: any) => {
+            DocServer.getRefField(this.idToAdd).then(action((field: any) => {
                 if (field !== undefined) {
                     this.fields.push(field);
                 }
diff --git a/src/mobile/ImageUpload.tsx b/src/mobile/ImageUpload.tsx
index a8f94b746..df597e0a9 100644
--- a/src/mobile/ImageUpload.tsx
+++ b/src/mobile/ImageUpload.tsx
@@ -57,11 +57,11 @@ class Uploader extends React.Component {
 
                         this.status = "getting user document";
 
-                        const res = await rp.get(DocServer.prepend(RouteStore.getUserDocumentId));
+                        const res = await rp.get(DocServer.Util.prepend(RouteStore.getUserDocumentId));
                         if (!res) {
                             throw new Error("No user id returned");
                         }
-                        const field = await DocServer.GetRefField(res);
+                        const field = await DocServer.getRefField(res);
                         let pending: Opt<Doc>;
                         if (field instanceof Doc) {
                             pending = await Cast(field.optionalRightCollection, Doc);
diff --git a/src/new_fields/Proxy.ts b/src/new_fields/Proxy.ts
index 130ec066e..230e4ab8b 100644
--- a/src/new_fields/Proxy.ts
+++ b/src/new_fields/Proxy.ts
@@ -57,7 +57,7 @@ export class ProxyField<T extends RefField> extends ObjectField {
             return undefined;
         }
         if (!this.promise) {
-            this.promise = DocServer.GetRefField(this.fieldId).then(action((field: any) => {
+            this.promise = DocServer.getRefField(this.fieldId).then(action((field: any) => {
                 this.promise = undefined;
                 this.cache = field;
                 if (field === undefined) this.failed = true;
diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts
index 169be3b99..95c20d2db 100644
--- a/src/server/authentication/models/current_user_utils.ts
+++ b/src/server/authentication/models/current_user_utils.ts
@@ -40,7 +40,7 @@ export class CurrentUserUtils {
     }
 
     public static async loadCurrentUser(): Promise<any> {
-        let userPromise = rp.get(DocServer.prepend(RouteStore.getCurrUser)).then(response => {
+        let userPromise = rp.get(DocServer.Util.prepend(RouteStore.getCurrUser)).then(response => {
             if (response) {
                 let obj = JSON.parse(response);
                 CurrentUserUtils.curr_id = obj.id as string;
@@ -49,9 +49,9 @@ export class CurrentUserUtils {
                 throw new Error("There should be a user! Why does Dash think there isn't one?");
             }
         });
-        let userDocPromise = await rp.get(DocServer.prepend(RouteStore.getUserDocumentId)).then(id => {
+        let userDocPromise = await rp.get(DocServer.Util.prepend(RouteStore.getUserDocumentId)).then(id => {
             if (id) {
-                return DocServer.GetRefField(id).then(field =>
+                return DocServer.getRefField(id).then(field =>
                     runInAction(() => this.user_document = field instanceof Doc ? field : this.createUserDocument(id)));
             } else {
                 throw new Error("There should be a user id! Why does Dash think there isn't one?");
-- 
cgit v1.2.3-70-g09d2


From 0058f56fda4e9e6a70ec7c23e1c141927715f9c1 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Thu, 11 Jul 2019 00:38:37 -0400
Subject: trying to make everything work the same way

---
 src/client/documents/Documents.ts                  |  8 +++---
 src/client/util/LinkManager.ts                     |  4 +--
 src/client/util/TooltipTextMenu.tsx                |  2 +-
 .../views/collections/CollectionBaseView.tsx       | 19 ++++++++++---
 src/client/views/collections/CollectionPDFView.tsx |  4 +--
 .../views/collections/CollectionStackingView.tsx   | 10 +++----
 src/client/views/collections/CollectionSubView.tsx | 10 ++++---
 .../views/collections/CollectionTreeView.tsx       |  2 +-
 .../views/collections/CollectionVideoView.tsx      |  4 +--
 src/client/views/collections/CollectionView.tsx    |  2 +-
 .../collectionFreeForm/CollectionFreeFormView.scss |  4 +--
 .../collectionFreeForm/CollectionFreeFormView.tsx  | 33 +++++++++++-----------
 src/client/views/nodes/DocumentView.tsx            |  2 +-
 src/client/views/nodes/FieldView.tsx               |  4 +--
 src/client/views/nodes/FormattedTextBox.tsx        |  3 +-
 src/client/views/pdf/PDFViewer.tsx                 |  2 +-
 src/new_fields/Doc.ts                              |  2 +-
 17 files changed, 64 insertions(+), 51 deletions(-)

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

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index d1c9feb32..46255b5d5 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -174,7 +174,7 @@ export namespace Docs {
     }
 
     function CreateImagePrototype(): Doc {
-        let imageProto = setupPrototypeOptions(imageProtoId, "IMAGE_PROTO", CollectionView.LayoutString("annotations"),
+        let imageProto = setupPrototypeOptions(imageProtoId, "IMAGE_PROTO", CollectionView.LayoutString("data", "annotations"),
             { x: 0, y: 0, nativeWidth: 600, width: 300, backgroundLayout: ImageBox.LayoutString(), curPage: 0, type: DocTypes.IMG });
         return imageProto;
     }
@@ -185,7 +185,7 @@ export namespace Docs {
     }
 
     function CreateHistogramPrototype(): Doc {
-        let histoProto = setupPrototypeOptions(histoProtoId, "HISTO PROTO", CollectionView.LayoutString("annotations"),
+        let histoProto = setupPrototypeOptions(histoProtoId, "HISTO PROTO", CollectionView.LayoutString("data"),
             { x: 0, y: 0, width: 300, height: 300, backgroundColor: "black", backgroundLayout: HistogramBox.LayoutString(), type: DocTypes.HIST });
         return histoProto;
     }
@@ -200,7 +200,7 @@ export namespace Docs {
         return textProto;
     }
     function CreatePdfPrototype(): Doc {
-        let pdfProto = setupPrototypeOptions(pdfProtoId, "PDF_PROTO", CollectionPDFView.LayoutString("annotations"),
+        let pdfProto = setupPrototypeOptions(pdfProtoId, "PDF_PROTO", CollectionPDFView.LayoutString("data", "annotations"),
             { x: 0, y: 0, width: 300, height: 300, backgroundLayout: PDFBox.LayoutString(), curPage: 1, type: DocTypes.PDF });
         return pdfProto;
     }
@@ -221,7 +221,7 @@ export namespace Docs {
         return kvpProto;
     }
     function CreateVideoPrototype(): Doc {
-        let videoProto = setupPrototypeOptions(videoProtoId, "VIDEO_PROTO", CollectionVideoView.LayoutString("annotations"),
+        let videoProto = setupPrototypeOptions(videoProtoId, "VIDEO_PROTO", CollectionVideoView.LayoutString("data", "annotations"),
             { x: 0, y: 0, nativeWidth: 600, width: 300, backgroundLayout: VideoBox.LayoutString(), curPage: 0, type: DocTypes.VID });
         return videoProto;
     }
diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts
index 944bc532f..d6ea6013b 100644
--- a/src/client/util/LinkManager.ts
+++ b/src/client/util/LinkManager.ts
@@ -234,9 +234,9 @@ export class LinkManager {
     //TODO This should also await the return value of the anchor so we don't filter out promises
     public getOppositeAnchor(linkDoc: Doc, anchor: Doc): Doc {
         if (Doc.AreProtosEqual(anchor, Cast(linkDoc.anchor1, Doc, null))) {
-            return Cast(linkDoc.anchor2, Doc, null)!;
+            return Cast(linkDoc.anchor2, Doc, null);
         } else {
-            return Cast(linkDoc.anchor1, Doc, null)!;
+            return Cast(linkDoc.anchor1, Doc, null);
         }
     }
 }
\ No newline at end of file
diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx
index cb7ed976a..4fcc16ddd 100644
--- a/src/client/util/TooltipTextMenu.tsx
+++ b/src/client/util/TooltipTextMenu.tsx
@@ -448,7 +448,7 @@ export class TooltipTextMenu {
                     let node = state.doc.nodeAt(from);
                     node && node.marks.map(m => {
                         m.type === markType && (curLink = m.attrs.href);
-                    })
+                    });
                     //toggleMark(markType)(state, dispatch);
                     //return true;
                 }
diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx
index e4f9b5058..079a44b88 100644
--- a/src/client/views/collections/CollectionBaseView.tsx
+++ b/src/client/views/collections/CollectionBaseView.tsx
@@ -74,21 +74,27 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
         this.props.whenActiveChanged(isActive);
     }
 
+    public get isAnnotationOverlay() { return this.props.fieldKey === "annotations" || this.props.fieldExt === "annotations"; }
+    @computed get extensionDoc() { return Doc.resolvedFieldDataDoc(this.props.DataDoc ? this.props.DataDoc : this.props.Document, this.props.fieldKey, this.isAnnotationOverlay ? "dummy" : ""); }
+
     @action.bound
     addDocument(doc: Doc, allowDuplicates: boolean = false): boolean {
+        let self = this;
         var curPage = NumCast(this.props.Document.curPage, -1);
         Doc.GetProto(doc).page = curPage;
         if (curPage >= 0) {
             Doc.GetProto(doc).annotationOn = this.props.Document;
         }
         allowDuplicates = true;
-        const value = Cast(this.dataDoc[this.dataField], listSpec(Doc));
+        let targetDataDoc = this.props.fieldExt || this.props.Document.isTemplate ? this.extensionDoc : this.props.Document;
+        let targetField = (this.props.fieldExt || this.props.Document.isTemplate) && this.props.fieldExt ? this.props.fieldExt : this.props.fieldKey;
+        const value = Cast(targetDataDoc[targetField], listSpec(Doc));
         if (value !== undefined) {
             if (allowDuplicates || !value.some(v => v instanceof Doc && v[Id] === doc[Id])) {
                 value.push(doc);
             }
         } else {
-            Doc.GetProto(this.dataDoc)[this.dataField] = new List([doc]);
+            Doc.GetProto(targetDataDoc)[targetField] = new List([doc]);
         }
         return true;
     }
@@ -98,7 +104,9 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
         let docView = DocumentManager.Instance.getDocumentView(doc, this.props.ContainingCollectionView);
         docView && SelectionManager.DeselectDoc(docView);
         //TODO This won't create the field if it doesn't already exist
-        const value = Cast(this.dataDoc[this.dataField], listSpec(Doc), []);
+        let targetDataDoc = this.props.fieldExt || this.props.Document.isTemplate ? this.extensionDoc : this.props.Document;
+        let targetField = (this.props.fieldExt || this.props.Document.isTemplate) && this.props.fieldExt ? this.props.fieldExt : this.props.fieldKey;
+        let value = Cast(targetDataDoc[targetField], listSpec(Doc), []);
         let index = value.reduce((p, v, i) => (v instanceof Doc && v[Id] === doc[Id]) ? i : p, -1);
         PromiseValue(Cast(doc.annotationOn, Doc)).then(annotationOn =>
             annotationOn === this.dataDoc.Document && (doc.annotationOn = undefined)
@@ -116,7 +124,10 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
 
     @action.bound
     moveDocument(doc: Doc, targetCollection: Doc, addDocument: (doc: Doc) => boolean): boolean {
-        if (Doc.AreProtosEqual(this.dataDoc, targetCollection)) {
+        let self = this;
+        let targetDataDoc = this.props.fieldExt || this.props.Document.isTemplate ? this.extensionDoc : this.props.Document;
+        if (Doc.AreProtosEqual(targetDataDoc, targetCollection)) {
+            //if (Doc.AreProtosEqual(this.extensionDoc, targetCollection)) {
             return true;
         }
         if (this.removeDocument(doc)) {
diff --git a/src/client/views/collections/CollectionPDFView.tsx b/src/client/views/collections/CollectionPDFView.tsx
index 31a73ab36..c97443785 100644
--- a/src/client/views/collections/CollectionPDFView.tsx
+++ b/src/client/views/collections/CollectionPDFView.tsx
@@ -47,8 +47,8 @@ export class CollectionPDFView extends React.Component<FieldViewProps> {
         this._reactionDisposer && this._reactionDisposer();
     }
 
-    public static LayoutString(fieldKey: string = "data") {
-        return FieldView.LayoutString(CollectionPDFView, fieldKey);
+    public static LayoutString(fieldKey: string = "data", fieldExt: string = "annotations") {
+        return FieldView.LayoutString(CollectionPDFView, fieldKey, fieldExt);
     }
     @observable _inThumb = false;
 
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index 372891923..9266fc8fd 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -50,11 +50,11 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
     }
 
     overlays = (doc: Doc) => {
-        return doc.type === DocTypes.IMG ? { title: "title", caption: "caption" } : {}
+        return doc.type === DocTypes.IMG ? { title: "title", caption: "caption" } : {};
     }
 
     getDisplayDoc(layoutDoc: Doc, d: Doc, dxf: () => Transform) {
-        let dataDoc = d !== this.props.DataDoc ? this.props.DataDoc : undefined
+        let dataDoc = d !== this.props.DataDoc ? this.props.DataDoc : undefined;
         let width = () => d.nativeWidth ? Math.min(layoutDoc[WidthSym](), this.columnWidth) : this.columnWidth;
         let height = () => this.getDocHeight(layoutDoc);
         let finalDxf = () => dxf().scale(this.columnWidth / layoutDoc[WidthSym]());
@@ -75,7 +75,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
             addDocTab={this.props.addDocTab}
             setPreviewScript={emptyFunction}
             previewScript={undefined}>
-        </CollectionSchemaPreview>
+        </CollectionSchemaPreview>;
     }
     getDocHeight(d: Doc) {
         let nw = NumCast(d.nativeWidth);
@@ -176,7 +176,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
                 if (where[0] > pos[0] && where[0] < pos1[0] && where[1] > pos[1] && where[1] < pos1[1]) {
                     targInd = i;
                 }
-            })
+            });
         }
         if (super.drop(e, de)) {
             let newDoc = de.data.droppedDocuments[0];
@@ -202,7 +202,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
             if (where[0] > pos[0] && where[0] < pos1[0] && where[1] > pos[1] && where[1] < pos1[1]) {
                 targInd = i;
             }
-        })
+        });
         super.onDrop(e, {}, () => {
             if (targInd !== -1) {
                 let newDoc = this.childDocs[this.childDocs.length - 1];
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 496f7e461..e72e69330 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -46,18 +46,20 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) {
             this.createDropTarget(ele);
         }
 
-        @computed get extensionDoc() { return Doc.resolvedFieldDataDoc(BoolCast(this.props.Document.isTemplate) && this.props.DataDoc ? this.props.DataDoc : this.props.Document, this.props.fieldKey, this.props.fieldExt); }
+        public get isAnnotationOverlay() { return this.props.fieldKey === "annotations" || this.props.fieldExt === "annotations"; }
+        @computed get extensionDoc() { return Doc.resolvedFieldDataDoc(BoolCast(this.props.Document.isTemplate) && this.props.DataDoc ? this.props.DataDoc : this.props.Document, this.props.fieldKey, this.isAnnotationOverlay ? "dummy" : ""); }
+
 
         get childDocs() {
             let self = this;
             //TODO tfs: This might not be what we want?
             //This linter error can't be fixed because of how js arguments work, so don't switch this to filter(FieldValue)
-            return DocListCast((BoolCast(this.props.Document.isTemplate) ? this.extensionDoc : this.props.Document)[this.props.fieldExt ? this.props.fieldExt : this.props.fieldKey]);
+            return DocListCast(this.extensionDoc[this.props.fieldExt ? this.props.fieldExt : this.props.fieldKey]);
         }
         get childDocList() {
             //TODO tfs: This might not be what we want?
             //This linter error can't be fixed because of how js arguments work, so don't switch this to filter(FieldValue)
-            return Cast((BoolCast(this.props.Document.isTemplate) ? this.extensionDoc : this.props.Document)[this.props.fieldExt ? this.props.fieldExt : this.props.fieldKey], listSpec(Doc));
+            return Cast(this.extensionDoc[this.props.fieldExt ? this.props.fieldExt : this.props.fieldKey], listSpec(Doc));
         }
 
         @action
@@ -102,7 +104,7 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) {
                 } else if (de.data.moveDocument) {
                     let movedDocs = de.data.options === this.props.Document[Id] ? de.data.draggedDocuments : de.data.droppedDocuments;
                     added = movedDocs.reduce((added: boolean, d) =>
-                        de.data.moveDocument(d, this.props.DataDoc ? this.props.DataDoc : this.props.Document, this.props.addDocument) || added, false);
+                        de.data.moveDocument(d, /*this.props.DataDoc ? this.props.DataDoc :*/ this.props.Document, this.props.addDocument) || added, false);
                 } else {
                     added = de.data.droppedDocuments.reduce((added: boolean, d) => this.props.addDocument(d) || added, false);
                 }
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 3674a743a..1280d515c 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -75,7 +75,7 @@ class TreeView extends React.Component<TreeViewProps> {
     @computed get fieldKey() {
         let keys = Array.from(Object.keys(this.resolvedDataDoc));  // bcz: Argh -- make untracked to avoid this rerunning whenever 'libraryBrush' is set
         if (this.resolvedDataDoc.proto instanceof Doc) {
-            let arr = Array.from(Object.keys(this.resolvedDataDoc.proto!));// bcz: Argh -- make untracked to avoid this rerunning whenever 'libraryBrush' is set
+            let arr = Array.from(Object.keys(this.resolvedDataDoc.proto));// bcz: Argh -- make untracked to avoid this rerunning whenever 'libraryBrush' is set
             keys.push(...arr);
             while (keys.indexOf("proto") !== -1) keys.splice(keys.indexOf("proto"), 1);
         }
diff --git a/src/client/views/collections/CollectionVideoView.tsx b/src/client/views/collections/CollectionVideoView.tsx
index 1984965ba..16287a658 100644
--- a/src/client/views/collections/CollectionVideoView.tsx
+++ b/src/client/views/collections/CollectionVideoView.tsx
@@ -21,8 +21,8 @@ import { Docs, DocUtils } from "../../documents/Documents";
 export class CollectionVideoView extends React.Component<FieldViewProps> {
     private _videoBox?: VideoBox;
 
-    public static LayoutString(fieldKey: string = "data") {
-        return FieldView.LayoutString(CollectionVideoView, fieldKey);
+    public static LayoutString(fieldKey: string = "data", fieldExt: string = "annotations") {
+        return FieldView.LayoutString(CollectionVideoView, fieldKey, fieldExt);
     }
     private get uIButtons() {
         let scaling = Math.min(1.8, this.props.ScreenToLocalTransform().Scale);
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index e500e5c70..e69696390 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -27,7 +27,7 @@ library.add(faThList);
 
 @observer
 export class CollectionView extends React.Component<FieldViewProps> {
-    public static LayoutString(fieldStr: string = "data") { return FieldView.LayoutString(CollectionView, fieldStr); }
+    public static LayoutString(fieldStr: string = "data", fieldExt: string = "") { return FieldView.LayoutString(CollectionView, fieldStr, fieldExt); }
 
     private SubView = (type: CollectionViewType, renderProps: CollectionRenderProps) => {
         let props = { ...this.props, ...renderProps };
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
index ccf261c95..51cfa77b1 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
@@ -38,7 +38,7 @@
     // }
     box-shadow: $intermediate-color 0.2vw 0.2vw 0.8vw;
     border: 0px solid $light-color-secondary;
-    border-radius: $border-radius;
+    border-radius: inherit;
     box-sizing: border-box;
     position: absolute;
 
@@ -71,7 +71,7 @@
 
     opacity: 0.99;
     border: 0px solid transparent;
-    border-radius: $border-radius;
+    border-radius: inherit;
     box-sizing: border-box;
     position:absolute;
     z-index: -1;
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 2c9b6b6a9..c931c74bc 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -54,7 +54,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
 
     @computed get nativeWidth() { return this.Document.nativeWidth || 0; }
     @computed get nativeHeight() { return this.Document.nativeHeight || 0; }
-    public get isAnnotationOverlay() { return this.props.fieldKey === "annotations" || this.props.fieldExt === "annotations"; }
+    public get isAnnotationOverlay() { return this.props.fieldExt === "annotations"; }
     private get borderWidth() { return this.isAnnotationOverlay ? 0 : COLLECTION_BORDER_WIDTH; }
     private panX = () => this.props.fitToBox ? this.props.fitToBox()[0] : this.Document.panX || 0;
     private panY = () => this.props.fitToBox ? this.props.fitToBox()[1] : this.Document.panY || 0;
@@ -86,6 +86,9 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
         });
     }
 
+    @computed get extensionDoc() { return Doc.resolvedFieldDataDoc(BoolCast(this.props.Document.isTemplate) && this.props.DataDoc ? this.props.DataDoc : this.props.Document, this.props.fieldKey, this.isAnnotationOverlay ? "dummy" : ""); }
+
+
     @undoBatch
     @action
     drop = (e: Event, de: DragManager.DropEvent) => {
@@ -93,10 +96,9 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
             if (de.data instanceof DragManager.DocumentDragData) {
                 if (de.data.droppedDocuments.length) {
                     let dragDoc = de.data.droppedDocuments[0];
-                    let zoom = NumCast(dragDoc.zoomBasis, 1);
                     let [xp, yp] = this.getTransform().transformPoint(de.x, de.y);
-                    let x = xp - de.data.xOffset / zoom;
-                    let y = yp - de.data.yOffset / zoom;
+                    let x = xp - de.data.xOffset;
+                    let y = yp - de.data.yOffset;
                     let dropX = NumCast(de.data.droppedDocuments[0].x);
                     let dropY = NumCast(de.data.droppedDocuments[0].y);
                     de.data.droppedDocuments.forEach(d => {
@@ -117,10 +119,9 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
             else if (de.data instanceof DragManager.AnnotationDragData) {
                 if (de.data.dropDocument) {
                     let dragDoc = de.data.dropDocument;
-                    let zoom = NumCast(dragDoc.zoomBasis, 1);
                     let [xp, yp] = this.getTransform().transformPoint(de.x, de.y);
-                    let x = xp - de.data.xOffset / zoom;
-                    let y = yp - de.data.yOffset / zoom;
+                    let x = xp - de.data.xOffset;
+                    let y = yp - de.data.yOffset;
                     let dropX = NumCast(de.data.dropDocument.x);
                     let dropY = NumCast(de.data.dropDocument.y);
                     dragDoc.x = x + NumCast(dragDoc.x) - dropX;
@@ -159,14 +160,14 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
             if (!this.isAnnotationOverlay) {
                 PDFMenu.Instance.fadeOut(true);
                 let minx = docs.length ? NumCast(docs[0].x) : 0;
-                let maxx = docs.length ? NumCast(docs[0].width) / NumCast(docs[0].zoomBasis, 1) + minx : minx;
+                let maxx = docs.length ? NumCast(docs[0].width) + minx : minx;
                 let miny = docs.length ? NumCast(docs[0].y) : 0;
-                let maxy = docs.length ? NumCast(docs[0].height) / NumCast(docs[0].zoomBasis, 1) + miny : miny;
+                let maxy = docs.length ? NumCast(docs[0].height) + miny : miny;
                 let ranges = docs.filter(doc => doc).reduce((range, doc) => {
                     let x = NumCast(doc.x);
-                    let xe = x + NumCast(doc.width) / NumCast(doc.zoomBasis, 1);
+                    let xe = x + NumCast(doc.width);
                     let y = NumCast(doc.y);
-                    let ye = y + NumCast(doc.height) / NumCast(doc.zoomBasis, 1);
+                    let ye = y + NumCast(doc.height);
                     return [[range[0][0] > x ? x : range[0][0], range[0][1] < xe ? xe : range[0][1]],
                     [range[1][0] > y ? y : range[1][0], range[1][1] < ye ? ye : range[1][1]]];
                 }, [[minx, maxx], [miny, maxy]]);
@@ -299,8 +300,8 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
             }
         }
         SelectionManager.DeselectAll();
-        const newPanX = NumCast(doc.x) + NumCast(doc.width) / NumCast(doc.zoomBasis, 1) / 2;
-        const newPanY = NumCast(doc.y) + NumCast(doc.height) / NumCast(doc.zoomBasis, 1) / 2;
+        const newPanX = NumCast(doc.x) + NumCast(doc.width) / 2;
+        const newPanY = NumCast(doc.y) + NumCast(doc.height) / 2;
         const newState = HistoryUtil.getState();
         newState.initializers[id] = { panX: newPanX, panY: newPanY };
         HistoryUtil.pushState(newState);
@@ -501,19 +502,17 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
         const containerName = `collectionfreeformview${this.isAnnotationOverlay ? "-overlay" : "-container"}`;
         const easing = () => this.props.Document.panTransformType === "Ease";
 
-        if (this.props.fieldExt) Doc.UpdateDocumentExtensionForField(this.props.DataDoc ? this.props.DataDoc : this.props.Document, this.props.fieldKey);
+        Doc.UpdateDocumentExtensionForField(this.props.DataDoc ? this.props.DataDoc : this.props.Document, this.props.fieldKey);
         return (
             <div className={containerName} ref={this.createDropTarget} onWheel={this.onPointerWheel}
-                style={{ borderRadius: "inherit" }}
                 onPointerDown={this.onPointerDown} onPointerMove={this.onCursorMove} onDrop={this.onDrop.bind(this)} onDragOver={this.onDragOver} onContextMenu={this.onContextMenu}>
                 <MarqueeView container={this} activeDocuments={this.getActiveDocuments} selectDocuments={this.selectDocuments} isSelected={this.props.isSelected}
                     addDocument={this.addDocument} removeDocument={this.props.removeDocument} addLiveTextDocument={this.addLiveTextBox}
                     getContainerTransform={this.getContainerTransform} getTransform={this.getTransform}>
                     <CollectionFreeFormViewPannableContents centeringShiftX={this.centeringShiftX} centeringShiftY={this.centeringShiftY}
                         easing={easing} zoomScaling={this.zoomScaling} panX={this.panX} panY={this.panY}>
-
                         <CollectionFreeFormLinksView {...this.props} key="freeformLinks">
-                            <InkingCanvas getScreenTransform={this.getTransform} Document={this.extensionDoc} inkFieldKey={this.props.fieldExt ? "ink" : this.props.fieldKey + "_ink"} >
+                            <InkingCanvas getScreenTransform={this.getTransform} Document={this.extensionDoc} inkFieldKey={"ink"} >
                                 {this.childViews}
                             </InkingCanvas>
                         </CollectionFreeFormLinksView>
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 6f3adb6b5..613cbf98e 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -530,7 +530,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
                 this.props.addDocument && this.props.addDocument(coll);
                 this.props.removeDocument && this.props.removeDocument(this.props.Document);
             }, icon: "window-restore"
-        })
+        });
         cm.addItem({
             description: "Find aliases", event: async () => {
                 const aliases = await SearchUtil.GetAliasesOfDocument(this.props.Document);
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index c5fc6c65a..abd0d9e12 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -55,8 +55,8 @@ export interface FieldViewProps {
 
 @observer
 export class FieldView extends React.Component<FieldViewProps> {
-    public static LayoutString(fieldType: { name: string }, fieldStr: string = "data") {
-        return `<${fieldType.name} {...props} fieldKey={"${fieldStr}"} />`;
+    public static LayoutString(fieldType: { name: string }, fieldStr: string = "data", fieldExt: string = "") {
+        return `<${fieldType.name} {...props} fieldKey={"${fieldStr}"} fieldExt={"${fieldExt}"} />`;
     }
 
     @computed
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 5475aa2b2..084fd4c96 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -232,9 +232,10 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
                 return field ? field.Data : `{"doc":{"type":"doc","content":[]},"selection":{"type":"text","anchor":0,"head":0}}`;
             },
             field2 => {
-                if (StrCast(this.props.Document.layout).indexOf("\"" + this.props.fieldKey + "\"") !== -1) // bcz: UGH!  why is this needed... something is happening out of order.  test with making a collection, then adding a text note and converting that to a template field.
+                if (StrCast(this.props.Document.layout).indexOf("\"" + this.props.fieldKey + "\"") !== -1) { // bcz: UGH!  why is this needed... something is happening out of order.  test with making a collection, then adding a text note and converting that to a template field.
                     this._editorView && !this._applyingChange &&
                         this._editorView.updateState(EditorState.fromJSON(config, JSON.parse(field2)));
+                }
             }
         );
 
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index 8af29110f..8bba05850 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -588,7 +588,7 @@ export class Viewer extends React.Component<IViewerProps> {
             }
             return true;
         });
-        this.Index = Math.min(this.Index + 1, filtered.length - 1)
+        this.Index = Math.min(this.Index + 1, filtered.length - 1);
     }
 
     nextResult = () => {
diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts
index 3d46243e0..cc0dc71dd 100644
--- a/src/new_fields/Doc.ts
+++ b/src/new_fields/Doc.ts
@@ -372,7 +372,7 @@ export namespace Doc {
         }
         let layout = StrCast(fieldLayoutDoc.layout).replace(/fieldKey={"[^"]*"}/, `fieldKey={"${metaKey}"}`);
         if (backgroundLayout) {
-            layout = StrCast(fieldLayoutDoc.layout).replace(/fieldKey={"annotations"}/, `fieldKey={"${metaKey}"} fieldExt={"annotations"}`);
+            layout = StrCast(fieldLayoutDoc.layout).replace(/fieldKey={"[^"]*"}/, `fieldKey={"${metaKey}"} fieldExt={"annotations"}`);
             backgroundLayout = backgroundLayout.replace(/fieldKey={"[^"]*"}/, `fieldKey={"${metaKey}"}`);
         }
         let nw = Cast(fieldTemplate.nativeWidth, "number");
-- 
cgit v1.2.3-70-g09d2


From 0c4fe96495ea73c16dcf189b09dbceb44943b8ba Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Fri, 12 Jul 2019 18:06:34 -0400
Subject: enabled youtube play controls.  fixed youtube video playing .

---
 src/client/views/collections/CollectionSubView.tsx |  4 +-
 .../views/collections/CollectionVideoView.tsx      |  2 +-
 src/client/views/nodes/VideoBox.tsx                | 65 +++++++++++-----------
 3 files changed, 34 insertions(+), 37 deletions(-)

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

diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index b2c3fb7d0..71f1908f0 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -197,7 +197,7 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) {
                         .then(result => {
                             let type = result["content-type"];
                             if (type) {
-                                Docs.Get.DocumentFromType(type, str, { ...options, width: 300, nativeWidth: 300 })
+                                Docs.Get.DocumentFromType(type, str, { ...options, width: 300, nativeWidth: type.indexOf("video") !== -1 ? 600 : 300 })
                                     .then(doc => doc && this.props.addDocument(doc, false));
                             }
                         });
@@ -218,7 +218,7 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) {
                         body: formData
                     }).then(async (res: Response) => {
                         (await res.json()).map(action((file: any) => {
-                            let full = { ...options, nativeWidth: 300, width: 300, title: dropFileName };
+                            let full = { ...options, nativeWidth: type.indexOf("video") !== -1 ? 600 : 300, width: 300, title: dropFileName };
                             let path = DocServer.prepend(file);
                             Docs.Get.DocumentFromType(type, path, full).then(doc => doc && this.props.addDocument(doc));
                         }));
diff --git a/src/client/views/collections/CollectionVideoView.tsx b/src/client/views/collections/CollectionVideoView.tsx
index 2b6c272aa..8d519ff2b 100644
--- a/src/client/views/collections/CollectionVideoView.tsx
+++ b/src/client/views/collections/CollectionVideoView.tsx
@@ -43,7 +43,7 @@ export class CollectionVideoView extends React.Component<FieldViewProps> {
 
     @action
     onPlayDown = () => {
-        if (this._videoBox && this._videoBox.player) {
+        if (this._videoBox) {
             if (this._videoBox.Playing) {
                 this._videoBox.Pause();
             } else {
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index 9ee4d7942..1b9138cfd 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -47,16 +47,31 @@ export class VideoBox extends DocComponent<FieldViewProps, VideoDocument>(VideoD
 
     @action public Play() {
         this.Playing = true;
-        if (this.player) this.player.play();
-        if (!this._playTimer) this._playTimer = setInterval(this.updateTimecode, 500);
+        if (this.player) {
+            this.player.play();
+            if (!this._playTimer) this._playTimer = setInterval(this.updateTimecode, 500);
+        } else if (this._youtubePlayer) {
+            this._youtubePlayer.playVideo();
+            if (!this._playTimer) this._playTimer = setInterval(this.updateYoutubeTimecode, 1000);
+        }
     }
 
     @action public Pause() {
         this.Playing = false;
-        if (this.player) this.player.pause();
-        if (this._playTimer) {
-            clearInterval(this._playTimer);
-            this._playTimer = undefined;
+        if (this.player) {
+            this.player.pause();
+            if (this._playTimer) {
+                clearInterval(this._playTimer);
+                this._playTimer = undefined;
+            }
+        } else if (this._youtubePlayer) {
+            // let interactive = InkingControl.Instance.selectedTool || !this.props.isSelected() ? "" : "-interactive";
+            // this._youtubePlayer.getIframe().style.pointerEvents = interactive ? "all" : "none";
+            this._youtubePlayer.pauseVideo();
+            if (this._playTimer) {
+                clearInterval(this._playTimer);
+                this._playTimer = undefined;
+            }
         }
     }
 
@@ -91,39 +106,24 @@ export class VideoBox extends DocComponent<FieldViewProps, VideoDocument>(VideoD
                 height: `${NumCast(this.props.Document.height)}`,
                 width: `${NumCast(this.props.Document.width)}`,
                 videoId: videoid.toString(),
-                playerVars: { 'controls': 0 },
+                playerVars: { 'controls': VideoBox._showControls ? 1 : 0 },
                 events: {
-                    //'onReady': this.onPlayerReady,
+                    'onStateChange': this.onPlayerStateChange,
                 }
             });
             // let iframe = $(document.getElementById(`${videoid}-player`)!);
             // iframe.on("load", function () {
             //     iframe.contents().find("head")
             //         .append($("<style type='text/css'>  .ytp-pause-overlay, .ytp-scroll-min { opacity : 0 !important; }  </style>"));
-            // });
-            reaction(() => this.props.isSelected(), (sel) => {
-                if (sel) {
-                    this._youtubePlayer.playVideo();
-                    if (!this._playTimer) this._playTimer = setInterval(this.updateYoutubeTimecode, 1000);
-                } else {
-                    let iframe = $(document.getElementById(`${videoid}-player`)!);
-                    //  .ytp-pause-overlay, .ytp-scroll-min { opacity : 0 !important; }
-                    //     $('iframe').load( function() {
-                    //     $('iframe').contents().find("head")
-                    //       .append($("<style type='text/css'>  .my-class{display:none;}  </style>"));
-                    // });
-                    //this._youtubePlayer.cueVideoById(videoid, this._youtubePlayer.getCurrentTime());
-                    this._youtubePlayer.pauseVideo();
-                    if (this._playTimer) {
-                        clearInterval(this._playTimer);
-                        this._playTimer = undefined;
-                    }
-                }
-            });
+            // })
         }
+    }
 
-
+    @action
+    onPlayerStateChange = (event: any) => {
+        this.Playing = event.data == YT.PlayerState.PLAYING;
     }
+
     componentWillUnmount() {
         this.Pause();
         if (this._reactionDisposer) this._reactionDisposer();
@@ -141,10 +141,6 @@ export class VideoBox extends DocComponent<FieldViewProps, VideoDocument>(VideoD
         }
     }
 
-
-    onPointerDown = (e: React.PointerEvent) => {
-    }
-
     @observable static _showControls: boolean = false;
 
     specificContextMenu = (e: React.MouseEvent): void => {
@@ -162,10 +158,11 @@ export class VideoBox extends DocComponent<FieldViewProps, VideoDocument>(VideoD
         let style = "videoBox-cont" + (this._fullScreen ? "-fullScreen" : interactive);
         let videoid = field && field.url.href.indexOf("youtube") !== -1 ? ((arr: string[]) => arr[arr.length - 1])(field.url.href.split("/")) : "";
 
+        if (this._youtubePlayer) this._youtubePlayer.getIframe().style.pointerEvents = interactive ? "all" : "none";
         return !field ? <div>Loading</div> :
             videoid ?
                 <div id={`${videoid}-player`} className={`${style}`} style={{ height: "100%" }} /> :
-                <video className={`${style}`} ref={this.setVideoRef} onCanPlay={this.videoLoad} onPointerDown={this.onPointerDown} onContextMenu={this.specificContextMenu} controls={VideoBox._showControls}>
+                <video className={`${style}`} ref={this.setVideoRef} onCanPlay={this.videoLoad} onContextMenu={this.specificContextMenu} controls={VideoBox._showControls}>
                     <source src={field.url.href} type="video/mp4" />
                     Not supported.
                 </video>;
-- 
cgit v1.2.3-70-g09d2


From d75d951a863103568f93ab9b04259d07b9668b47 Mon Sep 17 00:00:00 2001
From: Tyler Schicke <tyler_schicke@brown.edu>
Date: Fri, 12 Jul 2019 19:25:20 -0400
Subject: Various small changes/fixes

---
 src/client/views/MainView.tsx                        | 8 +++++---
 src/client/views/collections/CollectionVideoView.tsx | 2 +-
 src/client/views/nodes/VideoBox.tsx                  | 6 ++++--
 src/client/views/search/SearchItem.tsx               | 2 +-
 4 files changed, 11 insertions(+), 7 deletions(-)

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

diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index f0e11a480..614b9cce7 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -1,5 +1,5 @@
 import { IconName, library } from '@fortawesome/fontawesome-svg-core';
-import { faArrowDown, faArrowUp, faClone, faCheck, faCommentAlt, faCut, faExclamation, faFilePdf, faFilm, faFont, faGlobeAsia, faPortrait, faMusic, faObjectGroup, faPenNib, faRedoAlt, faTable, faThumbtack, faTree, faUndoAlt } from '@fortawesome/free-solid-svg-icons';
+import { faArrowDown, faArrowUp, faClone, faCheck, faCommentAlt, faCut, faExclamation, faFilePdf, faFilm, faFont, faGlobeAsia, faPortrait, faMusic, faObjectGroup, faPenNib, faRedoAlt, faTable, faThumbtack, faTree, faUndoAlt, faCat } from '@fortawesome/free-solid-svg-icons';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { action, computed, configure, observable, runInAction, reaction, trace } from 'mobx';
 import { observer } from 'mobx-react';
@@ -38,6 +38,7 @@ import { PresentationView } from './presentationview/PresentationView';
 import { PreviewCursor } from './PreviewCursor';
 import { FilterBox } from './search/FilterBox';
 import { CollectionTreeView } from './collections/CollectionTreeView';
+import { ClientUtils } from '../util/ClientUtils';
 
 @observer
 export class MainView extends React.Component {
@@ -111,6 +112,7 @@ export class MainView extends React.Component {
         library.add(faFont);
         library.add(faExclamation);
         library.add(faPortrait);
+        library.add(faCat);
         library.add(faFilePdf);
         library.add(faObjectGroup);
         library.add(faTable);
@@ -378,11 +380,11 @@ export class MainView extends React.Component {
         let addImportCollectionNode = action(() => Docs.Create.DirectoryImportDocument({ title: "Directory Import", width: 400, height: 400 }));
 
         let btns: [React.RefObject<HTMLDivElement>, IconName, string, () => Doc][] = [
-            [React.createRef<HTMLDivElement>(), "portrait", "Add Cat Image", addImageNode],
             [React.createRef<HTMLDivElement>(), "object-group", "Add Collection", addColNode],
             // [React.createRef<HTMLDivElement>(), "clone", "Add Docking Frame", addDockingNode],
             [React.createRef<HTMLDivElement>(), "arrow-up", "Import Directory", addImportCollectionNode],
         ];
+        if (!ClientUtils.RELEASE) btns.unshift([React.createRef<HTMLDivElement>(), "cat", "Add Cat Image", addImageNode]);
 
         return < div id="add-nodes-menu" style={{ left: this.flyoutWidth + 5 }} >
             <input type="checkbox" id="add-menu-toggle" ref={this.addMenuToggle} />
@@ -399,7 +401,7 @@ export class MainView extends React.Component {
                                 <FontAwesomeIcon icon={btn[1]} size="sm" />
                             </button>
                         </div></li>)}
-                    <li key="undoTest"><button className="add-button round-button" onClick={() => UndoManager.PrintBatches()}><FontAwesomeIcon icon="exclamation" size="sm" /></button></li>
+                    <li key="undoTest"><button className="add-button round-button" title="Click if undo isn't working" onClick={() => UndoManager.TraceOpenBatches()}><FontAwesomeIcon icon="exclamation" size="sm" /></button></li>
                     <li key="color"><button className="add-button round-button" title="Select Color" onClick={() => this.toggleColorPicker()}><div className="toolbar-color-button" style={{ backgroundColor: InkingControl.Instance.selectedColor }} >
                         <div className="toolbar-color-picker" onClick={this.onColorClick} style={this._colorPickerDisplay ? { color: "black", display: "block" } : { color: "black", display: "none" }}>
                             <SketchPicker color={InkingControl.Instance.selectedColor} onChange={InkingControl.Instance.switchColor} />
diff --git a/src/client/views/collections/CollectionVideoView.tsx b/src/client/views/collections/CollectionVideoView.tsx
index 2b6c272aa..39fe3edd1 100644
--- a/src/client/views/collections/CollectionVideoView.tsx
+++ b/src/client/views/collections/CollectionVideoView.tsx
@@ -27,7 +27,7 @@ export class CollectionVideoView extends React.Component<FieldViewProps> {
     private get uIButtons() {
         let scaling = Math.min(1.8, this.props.ScreenToLocalTransform().Scale);
         let curTime = NumCast(this.props.Document.curPage);
-        return ([
+        return (VideoBox._showControls ? [] : [
             <div className="collectionVideoView-time" key="time" onPointerDown={this.onResetDown} style={{ transform: `scale(${scaling}, ${scaling})` }}>
                 <span>{"" + Math.round(curTime)}</span>
                 <span style={{ fontSize: 8 }}>{" " + Math.round((curTime - Math.trunc(curTime)) * 100)}</span>
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index 9ee4d7942..fa1e4d273 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -145,7 +145,7 @@ export class VideoBox extends DocComponent<FieldViewProps, VideoDocument>(VideoD
     onPointerDown = (e: React.PointerEvent) => {
     }
 
-    @observable static _showControls: boolean = false;
+    @observable static _showControls: boolean;
 
     specificContextMenu = (e: React.MouseEvent): void => {
         let field = Cast(this.Document[this.props.fieldKey], VideoField);
@@ -170,4 +170,6 @@ export class VideoBox extends DocComponent<FieldViewProps, VideoDocument>(VideoD
                     Not supported.
                 </video>;
     }
-}
\ No newline at end of file
+}
+
+VideoBox._showControls = true;
\ No newline at end of file
diff --git a/src/client/views/search/SearchItem.tsx b/src/client/views/search/SearchItem.tsx
index f6f5b19f7..cd7e31b20 100644
--- a/src/client/views/search/SearchItem.tsx
+++ b/src/client/views/search/SearchItem.tsx
@@ -241,7 +241,7 @@ export class SearchItem extends React.Component<SearchItemProps> {
                     onClick={this.onClick} onPointerDown={this.pointerDown} >
                     <div className="main-search-info">
                         <div title="Drag as document" onPointerDown={this.onPointerDown}> <FontAwesomeIcon icon="file" size="lg" /> </div>
-                        <div className="search-title" id="result" >{this.props.doc.title}</div>
+                        <div className="search-title" id="result" >{StrCast(this.props.doc.title)}</div>
                         <div className="search-info" style={{ width: this._useIcons ? "15%" : "400px" }}>
                             <div className={`icon-${this._useIcons ? "icons" : "live"}`}>
                                 <div className="search-type" >{this.DocumentIcon}</div>
-- 
cgit v1.2.3-70-g09d2


From bbfc935958b88c7ecaeb9a1e06a255cac958ec4c Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Tue, 16 Jul 2019 11:58:16 -0400
Subject: added extendsDoc to extension doc's  fixed folllowing links to video
 locations.  fixed aspects of youtube integration.

---
 .../views/collections/CollectionVideoView.tsx      |  4 +--
 .../collections/collectionFreeForm/MarqueeView.tsx |  2 +-
 src/client/views/nodes/LinkMenuItem.tsx            |  5 +--
 src/client/views/nodes/VideoBox.tsx                | 42 +++++++++-------------
 src/new_fields/Doc.ts                              |  6 +++-
 5 files changed, 27 insertions(+), 32 deletions(-)

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

diff --git a/src/client/views/collections/CollectionVideoView.tsx b/src/client/views/collections/CollectionVideoView.tsx
index f731c4cef..faf507496 100644
--- a/src/client/views/collections/CollectionVideoView.tsx
+++ b/src/client/views/collections/CollectionVideoView.tsx
@@ -88,14 +88,14 @@ export class CollectionVideoView extends React.Component<FieldViewProps> {
                 canvas.width = 640;
                 canvas.height = 640 * NumCast(this.props.Document.nativeHeight) / NumCast(this.props.Document.nativeWidth);
                 var ctx = canvas.getContext('2d');//draw image to canvas. scale to target dimensions
-                ctx && ctx.drawImage(this._videoBox!.player!, 0, 0, canvas.width, canvas.height);
+                this._videoBox!.player && ctx && ctx.drawImage(this._videoBox!.player!, 0, 0, canvas.width, canvas.height);
 
                 //convert to desired file format
                 var dataUrl = canvas.toDataURL('image/png'); // can also use 'image/png'
                 // if you want to preview the captured image,
 
                 let filename = encodeURIComponent("snapshot" + this.props.Document.title + "_" + this.props.Document.curPage).replace(/\./g, "");
-                SearchBox.convertDataUri(dataUrl, filename).then((returnedFilename) => {
+                SearchBox.convertDataUri(dataUrl, filename).then(returnedFilename => {
                     if (returnedFilename) {
                         let url = DocServer.prepend(returnedFilename);
                         let imageSummary = Docs.Create.ImageDocument(url, {
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index a4a6881f8..b765517a2 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -147,7 +147,6 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
         PreviewCursor.Visible = false;
         this.cleanupInteractions(true);
         if (e.button === 2 || (e.button === 0 && e.altKey)) {
-            if (!this.props.container.props.active()) this.props.selectDocuments([this.props.container.props.Document]);
             document.addEventListener("pointermove", this.onPointerMove, true);
             document.addEventListener("pointerup", this.onPointerUp, true);
             document.addEventListener("keydown", this.marqueeCommand, true);
@@ -181,6 +180,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
 
     @action
     onPointerUp = (e: PointerEvent): void => {
+        if (!this.props.container.props.active()) this.props.selectDocuments([this.props.container.props.Document]);
         // console.log("pointer up!");
         if (this._visible) {
             // console.log("visible");
diff --git a/src/client/views/nodes/LinkMenuItem.tsx b/src/client/views/nodes/LinkMenuItem.tsx
index 9728671c0..6a18a4e7b 100644
--- a/src/client/views/nodes/LinkMenuItem.tsx
+++ b/src/client/views/nodes/LinkMenuItem.tsx
@@ -7,7 +7,7 @@ import { undoBatch } from "../../util/UndoManager";
 import './LinkMenu.scss';
 import React = require("react");
 import { Doc } from '../../../new_fields/Doc';
-import { StrCast, Cast, BoolCast, FieldValue } from '../../../new_fields/Types';
+import { StrCast, Cast, BoolCast, FieldValue, NumCast } from '../../../new_fields/Types';
 import { observable, action } from 'mobx';
 import { LinkManager } from '../../util/LinkManager';
 import { DragLinkAsDocument } from '../../util/DragManager';
@@ -38,7 +38,8 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
             jumpToDoc = pdfDoc;
         }
         if (DocumentManager.Instance.getDocumentView(jumpToDoc)) {
-            DocumentManager.Instance.jumpToDocument(jumpToDoc, e.altKey);
+            let self = this;
+            DocumentManager.Instance.jumpToDocument(jumpToDoc, e.altKey, undefined, undefined, NumCast((this.props.destinationDoc === self.props.linkDoc.anchor2 ? self.props.linkDoc.anchor2Page : self.props.linkDoc.anchor1Page)));
         } else {
             CollectionDockingView.Instance.AddRightSplit(jumpToDoc, undefined);
         }
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index 85e56ca7b..3ade3396e 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -1,5 +1,5 @@
 import React = require("react");
-import { action, IReactionDisposer, observable, reaction, trace, computed, runInAction } from "mobx";
+import { action, IReactionDisposer, observable, reaction, trace, computed, runInAction, untracked } from "mobx";
 import { observer } from "mobx-react";
 import { makeInterface } from "../../../new_fields/Schema";
 import { Cast, FieldValue, NumCast } from "../../../new_fields/Types";
@@ -14,7 +14,6 @@ import { pageSchema } from "./ImageBox";
 import "./VideoBox.scss";
 import { InkTool } from "../../../new_fields/InkField";
 import { DocumentDecorations } from "../DocumentDecorations";
-import { addHiddenFinalProp } from "mobx/lib/internal";
 
 type VideoDocument = makeInterface<[typeof positionSchema, typeof pageSchema]>;
 const VideoDocument = makeInterface(positionSchema, pageSchema);
@@ -53,18 +52,21 @@ export class VideoBox extends DocComponent<FieldViewProps, VideoDocument>(VideoD
     @action public Play = (update: boolean = true) => {
         this.Playing = true;
         update && this.player && this.player.play();
+        console.log("PLAYING = " + update);
         update && this._youtubePlayer && this._youtubePlayer.playVideo();
         !this._playTimer && (this._playTimer = setInterval(this.updateTimecode, 500));
         this.updateTimecode();
     }
 
     @action public Seek(time: number) {
+        console.log("Seeking " + time);
         //if (this._youtubePlayer && this._youtubePlayer.getPlayerState() === 5) return;
-        this._youtubePlayer && !this.Playing && this._youtubePlayer.seekTo(time);
+        this._youtubePlayer && this._youtubePlayer.seekTo(Math.round(time), true);
     }
 
     @action public Pause = (update: boolean = true) => {
         this.Playing = false;
+        console.log("PAUSING = " + update);
         update && this.player && this.player.pause();
         update && this._youtubePlayer && this._youtubePlayer.pauseVideo();
         this._playTimer && clearInterval(this._playTimer);
@@ -122,6 +124,8 @@ export class VideoBox extends DocComponent<FieldViewProps, VideoDocument>(VideoD
         if (field) {
             let subitems: ContextMenuProps[] = [];
             subitems.push({ description: "Toggle Show Controls", event: action(() => VideoBox._showControls = !VideoBox._showControls), icon: "expand-arrows-alt" });
+            subitems.push({ description: "GOTO 3", event: action(() => this.Seek(3)), icon: "expand-arrows-alt" });
+            subitems.push({ description: "PLAY", event: action(() => this.Play()), icon: "expand-arrows-alt" });
             ContextMenu.Instance.addItem({ description: "Video Funcs...", subitems: subitems });
         }
     }
@@ -151,38 +155,22 @@ export class VideoBox extends DocComponent<FieldViewProps, VideoDocument>(VideoD
         else this._youtubeContentCreated = false;
 
         let iframe = e.target;
-        let startupTimecode = NumCast(this.Document.curPage);
         let onYoutubePlayerStateChange = (event: any) => runInAction(() => {
-            if (event.data !== YT.PlayerState.UNSTARTED && event.data !== YT.PlayerState.BUFFERING) {
-                // if (startupTimecode !== -1) {
-                //     startupTimecode = -1;
-                //     if (event.data === YT.PlayerState.PLAYING) this.Pause();
-                // }
-                if (event.data == YT.PlayerState.PLAYING && !this.Playing) this.Play(false);
-                if (event.data == YT.PlayerState.PAUSED && this.Playing) this.Pause(false);
-            }
+            console.log("Event  " + event.data);
+            if (event.data == YT.PlayerState.PLAYING && !this.Playing) this.Play(false);
+            if (event.data == YT.PlayerState.PAUSED && this.Playing) this.Pause(false);
         });
         let onYoutubePlayerReady = (event: any) => {
+            console.log("READY!");
             this._reactionDisposer && this._reactionDisposer();
             this._youtubeReactionDisposer && this._youtubeReactionDisposer();
-            this._reactionDisposer = reaction(() => this.props.Document.curPage, () => this.Seek(this.Document.curPage || 0));
+            this._reactionDisposer = reaction(() => this.props.Document.curPage, () => !this.Playing && this.Seek(this.Document.curPage || 0));
             this._youtubeReactionDisposer = reaction(() => [this.props.isSelected(), DocumentDecorations.Instance.Interacting, InkingControl.Instance.selectedTool], () => {
                 let interactive = InkingControl.Instance.selectedTool === InkTool.None && this.props.isSelected() && !DocumentDecorations.Instance.Interacting;
                 iframe.style.pointerEvents = interactive ? "all" : "none";
             }, { fireImmediately: true });
-            // if (startupTimecode) {
-            //     this.Playing = false;
-            //     this.Seek(startupTimecode);
-            // }
         }
         this._youtubePlayer = new YT.Player(`${this.youtubeVideoId + this._youtubeIframeId}-player`, {
-            playerVars: {
-                rel: 0,
-                start: NumCast(this.props.Document.curPage),
-                fs: 1,
-                modestbranding: 1, // Modest
-                controls: VideoBox._showControls ? 1 : 0// YT.Controls.ShowLoadPlayer : YT.Controls.Hide
-            },
             events: {
                 'onReady': onYoutubePlayerReady,
                 'onStateChange': onYoutubePlayerStateChange,
@@ -195,9 +183,11 @@ export class VideoBox extends DocComponent<FieldViewProps, VideoDocument>(VideoD
         this._youtubeIframeId = VideoBox._youtubeIframeCounter++;
         this._youtubeContentCreated = this._forceCreateYouTubeIFrame ? true : true;
         let style = "videoBox-content-YouTube" + (this._fullScreen ? "-fullScreen" : "");
-        return <iframe key={this._youtubeIframeId} id={`${this.youtubeVideoId + this._youtubeIframeId.toString()}-player`}
+        let start = untracked(() => Math.round(NumCast(this.props.Document.curPage)));
+        return <iframe key={this._youtubeIframeId} id={`${this.youtubeVideoId + this._youtubeIframeId}-player`}
             onLoad={this.youtubeIframeLoaded} className={`${style}`} width="640" height="390"
-            src={`https://www.youtube.com/embed/${this.youtubeVideoId}?enablejsapi=1&fs=1&rel=0&start=32&controls=0`} />
+            src={`https://www.youtube.com/embed/${this.youtubeVideoId}?enablejsapi=1&rel=0&showinfo=1&autoplay=1&start=${start}&modestbranding=1&controls=${VideoBox._showControls ? 1 : 0}`}
+        ></iframe>;
     }
 
     render() {
diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts
index c5f9e7adf..0d9fa540f 100644
--- a/src/new_fields/Doc.ts
+++ b/src/new_fields/Doc.ts
@@ -312,16 +312,20 @@ export namespace Doc {
     }
 
     export function UpdateDocumentExtensionForField(doc: Doc, fieldKey: string) {
-        if (doc[fieldKey + "_ext"] === undefined) {
+        let extensionDoc = doc[fieldKey + "_ext"];
+        if (extensionDoc === undefined) {
             setTimeout(() => {
                 let docExtensionForField = new Doc(doc[Id] + fieldKey, true);
                 docExtensionForField.title = "Extension of " + doc.title + "'s field:" + fieldKey;
+                docExtensionForField.extendsDoc = doc;
                 let proto: Doc | undefined = doc;
                 while (proto && !Doc.IsPrototype(proto)) {
                     proto = proto.proto;
                 }
                 (proto ? proto : doc)[fieldKey + "_ext"] = docExtensionForField;
             }, 0);
+        } else if (extensionDoc instanceof Doc && extensionDoc.extendsDoc === undefined) {
+            setTimeout(() => (extensionDoc as Doc).extendsDoc = doc, 0);
         }
     }
     export function MakeAlias(doc: Doc) {
-- 
cgit v1.2.3-70-g09d2


From 7f6666500f157c5884377d714137426cf05e7569 Mon Sep 17 00:00:00 2001
From: Tyler Schicke <tyler_schicke@brown.edu>
Date: Tue, 16 Jul 2019 13:40:20 -0400
Subject: Changed search to display extension documents as the extended
 documents

---
 src/client/documents/Documents.ts                    |  2 +-
 src/client/views/InkingControl.tsx                   |  4 ++--
 src/client/views/collections/CollectionVideoView.tsx |  2 +-
 src/client/views/search/SearchBox.tsx                | 13 ++++++++-----
 4 files changed, 12 insertions(+), 9 deletions(-)

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

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 177810444..5bbfe1c49 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -235,7 +235,7 @@ export namespace Docs {
             let title = prototypeId.toUpperCase().replace(upper, `_${upper}`);
             // synthesize the default options, the type and title from computed values and
             // whatever options pertain to this specific prototype
-            let options = { title: title, type: type, ...defaultOptions, ...(template.options || {}) };
+            let options = { title: title, type: type, baseProto: true, ...defaultOptions, ...(template.options || {}) };
             let primary = layout.view.LayoutString();
             let collectionView = layout.collectionView;
             if (collectionView) {
diff --git a/src/client/views/InkingControl.tsx b/src/client/views/InkingControl.tsx
index 1910e409b..c7f7bdb66 100644
--- a/src/client/views/InkingControl.tsx
+++ b/src/client/views/InkingControl.tsx
@@ -1,5 +1,5 @@
 import { observable, action, computed, runInAction } from "mobx";
-import { ColorState } from 'react-color';
+import { ColorResult } from 'react-color';
 import React = require("react");
 import { observer } from "mobx-react";
 import "./InkingControl.scss";
@@ -41,7 +41,7 @@ export class InkingControl extends React.Component {
     }
 
     @undoBatch
-    switchColor = action((color: ColorState): void => {
+    switchColor = action((color: ColorResult): void => {
         this._selectedColor = color.hex + (color.rgb.a !== undefined ? this.decimalToHexString(Math.round(color.rgb.a * 255)) : "ff");
         if (InkingControl.Instance.selectedTool === InkTool.None) {
             if (MainOverlayTextBox.Instance.SetColor(color.hex)) return;
diff --git a/src/client/views/collections/CollectionVideoView.tsx b/src/client/views/collections/CollectionVideoView.tsx
index faf507496..096e7e9d1 100644
--- a/src/client/views/collections/CollectionVideoView.tsx
+++ b/src/client/views/collections/CollectionVideoView.tsx
@@ -88,7 +88,7 @@ export class CollectionVideoView extends React.Component<FieldViewProps> {
                 canvas.width = 640;
                 canvas.height = 640 * NumCast(this.props.Document.nativeHeight) / NumCast(this.props.Document.nativeWidth);
                 var ctx = canvas.getContext('2d');//draw image to canvas. scale to target dimensions
-                this._videoBox!.player && ctx && ctx.drawImage(this._videoBox!.player!, 0, 0, canvas.width, canvas.height);
+                this._videoBox!.player && ctx && ctx.drawImage(this._videoBox!.player, 0, 0, canvas.width, canvas.height);
 
                 //convert to desired file format
                 var dataUrl = canvas.toDataURL('image/png'); // can also use 'image/png'
diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx
index ec778b346..dc76d1ff4 100644
--- a/src/client/views/search/SearchBox.tsx
+++ b/src/client/views/search/SearchBox.tsx
@@ -6,7 +6,7 @@ import "./FilterBox.scss";
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { SetupDrag } from '../../util/DragManager';
 import { Docs } from '../../documents/Documents';
-import { NumCast } from '../../../new_fields/Types';
+import { NumCast, Cast } from '../../../new_fields/Types';
 import { Doc } from '../../../new_fields/Doc';
 import { SearchItem } from './SearchItem';
 import { DocServer } from '../../DocServer';
@@ -118,7 +118,7 @@ export class SearchBox extends React.Component {
 
     private get filterQuery() {
         const types = FilterBox.Instance.filterTypes;
-        return "proto_i:*" + (types ? ` AND (${types.map(type => `({!join from=id to=proto_i}type_t:"${type}" AND NOT type_t:*) OR type_t:"${type}"`).join(" ")})` : "");
+        return "NOT baseProto_b:true" + (types ? ` AND (${types.map(type => `({!join from=id to=proto_i}type_t:"${type}" AND NOT type_t:*) OR type_t:"${type}"`).join(" ")})` : "");
     }
 
 
@@ -129,15 +129,18 @@ export class SearchBox extends React.Component {
         }
         this.lockPromise = new Promise(async res => {
             while (this._results.length <= this._endIndex && (this._numTotalResults === -1 || this._maxSearchIndex < this._numTotalResults)) {
-                this._curRequest = SearchUtil.Search(query, this.filterQuery, true, this._maxSearchIndex, 10).then(action((res: SearchUtil.DocSearchResult) => {
+                this._curRequest = SearchUtil.Search(query, this.filterQuery, true, this._maxSearchIndex, 10).then(action(async (res: SearchUtil.DocSearchResult) => {
 
                     // happens at the beginning
                     if (res.numFound !== this._numTotalResults && this._numTotalResults === -1) {
                         this._numTotalResults = res.numFound;
                     }
 
-                    let filteredDocs = FilterBox.Instance.filterDocsByType(res.docs);
-                    this._results.push(...filteredDocs);
+                    const docs = await Promise.all(res.docs.map(doc => Cast(doc.extendsDoc, Doc, doc as any)));
+                    let filteredDocs = FilterBox.Instance.filterDocsByType(docs);
+                    runInAction(() => {
+                        this._results.push(...filteredDocs);
+                    });
 
                     this._curRequest = undefined;
                 }));
-- 
cgit v1.2.3-70-g09d2


From bef7fc20fecf4056a4f8ff47ff593b2df5e329af Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Tue, 16 Jul 2019 14:53:25 -0400
Subject: cleaned up and conquered video boxes.

---
 src/client/views/SearchBox.tsx                     | 45 +++---------
 src/client/views/collections/CollectionSubView.tsx |  4 +-
 .../views/collections/CollectionVideoView.tsx      | 65 ++----------------
 src/client/views/nodes/VideoBox.tsx                | 79 ++++++++++++++++++----
 4 files changed, 86 insertions(+), 107 deletions(-)

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

diff --git a/src/client/views/SearchBox.tsx b/src/client/views/SearchBox.tsx
index 6995e3c7d..8fb43021a 100644
--- a/src/client/views/SearchBox.tsx
+++ b/src/client/views/SearchBox.tsx
@@ -1,27 +1,18 @@
-import * as React from 'react';
-import { observer } from 'mobx-react';
-import { observable, action, runInAction } from 'mobx';
-import { Utils } from '../../Utils';
-import { MessageStore } from '../../server/Message';
-import "./SearchBox.scss";
-import { faSearch, faObjectGroup } from '@fortawesome/free-solid-svg-icons';
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { library } from '@fortawesome/fontawesome-svg-core';
-// const app = express();
-// import * as express from 'express';
-import { Search } from '../../server/Search';
+import { faObjectGroup, faSearch } from '@fortawesome/free-solid-svg-icons';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { action, observable, runInAction } from 'mobx';
+import { observer } from 'mobx-react';
+import * as React from 'react';
 import * as rp from 'request-promise';
-import { SearchItem } from './search/SearchItem';
-import { isString } from 'util';
-import { constant } from 'async';
-import { DocServer } from '../DocServer';
 import { Doc } from '../../new_fields/Doc';
 import { Id } from '../../new_fields/FieldSymbols';
-import { DocumentManager } from '../util/DocumentManager';
-import { SetupDrag } from '../util/DragManager';
-import { Docs } from '../documents/Documents';
-import { RouteStore } from '../../server/RouteStore';
 import { NumCast } from '../../new_fields/Types';
+import { DocServer } from '../DocServer';
+import { Docs } from '../documents/Documents';
+import { SetupDrag } from '../util/DragManager';
+import { SearchItem } from './search/SearchItem';
+import "./SearchBox.scss";
 
 library.add(faSearch);
 library.add(faObjectGroup);
@@ -72,22 +63,6 @@ export class SearchBox extends React.Component {
         }
         return docs;
     }
-    public static async convertDataUri(imageUri: string, returnedFilename: string) {
-        try {
-            let posting = DocServer.prepend(RouteStore.dataUriToImage);
-            const returnedUri = await rp.post(posting, {
-                body: {
-                    uri: imageUri,
-                    name: returnedFilename
-                },
-                json: true,
-            });
-            return returnedUri;
-
-        } catch (e) {
-            console.log(e);
-        }
-    }
 
     @action
     handleClickFilter = (e: Event): void => {
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 71f1908f0..8e8d5708b 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -179,8 +179,8 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) {
                 }
             }
             if (text && text.indexOf("www.youtube.com/watch") !== -1) {
-                const url = text.replace("youtube.com/watch?v=", "youtube.com/embed/");// + "?enablejsapi=1";
-                this.props.addDocument(Docs.Create.VideoDocument(url, { ...options, width: 400, height: 315 }));
+                const url = text.replace("youtube.com/watch?v=", "youtube.com/embed/");
+                this.props.addDocument(Docs.Create.VideoDocument(url, { ...options, title: url, width: 400, height: 315 }));
                 return;
             }
 
diff --git a/src/client/views/collections/CollectionVideoView.tsx b/src/client/views/collections/CollectionVideoView.tsx
index 096e7e9d1..d7d5773ba 100644
--- a/src/client/views/collections/CollectionVideoView.tsx
+++ b/src/client/views/collections/CollectionVideoView.tsx
@@ -1,20 +1,12 @@
-import { action, observable, trace } from "mobx";
-import * as htmlToImage from "html-to-image";
+import { action } from "mobx";
 import { observer } from "mobx-react";
-import { ContextMenu } from "../ContextMenu";
-import { CollectionViewType, CollectionBaseView, CollectionRenderProps } from "./CollectionBaseView";
-import React = require("react");
-import "./CollectionVideoView.scss";
-import { CollectionFreeFormView } from "./collectionFreeForm/CollectionFreeFormView";
+import { NumCast } from "../../../new_fields/Types";
 import { FieldView, FieldViewProps } from "../nodes/FieldView";
-import { emptyFunction, Utils } from "../../../Utils";
-import { Id } from "../../../new_fields/FieldSymbols";
 import { VideoBox } from "../nodes/VideoBox";
-import { NumCast, Cast, StrCast } from "../../../new_fields/Types";
-import { VideoField } from "../../../new_fields/URLField";
-import { SearchBox } from "../search/SearchBox";
-import { DocServer } from "../../DocServer";
-import { Docs, DocUtils } from "../../documents/Documents";
+import { CollectionBaseView, CollectionRenderProps, CollectionViewType } from "./CollectionBaseView";
+import { CollectionFreeFormView } from "./collectionFreeForm/CollectionFreeFormView";
+import "./CollectionVideoView.scss";
+import React = require("react");
 
 
 @observer
@@ -68,49 +60,6 @@ export class CollectionVideoView extends React.Component<FieldViewProps> {
             this.props.Document.curPage = 0;
         }
     }
-
-    onContextMenu = (e: React.MouseEvent): void => {
-        if (!e.isPropagationStopped() && this.props.Document[Id] !== "mainDoc") { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7
-        }
-
-        let field = Cast(this.props.Document[this.props.fieldKey], VideoField);
-        if (field) {
-            let url = field.url.href;
-            ContextMenu.Instance.addItem({
-                description: "Copy path", event: () => { Utils.CopyText(url); }, icon: "expand-arrows-alt"
-            });
-        }
-        let width = NumCast(this.props.Document.width);
-        let height = NumCast(this.props.Document.height);
-        ContextMenu.Instance.addItem({
-            description: "Take Snapshot", event: async () => {
-                var canvas = document.createElement('canvas');
-                canvas.width = 640;
-                canvas.height = 640 * NumCast(this.props.Document.nativeHeight) / NumCast(this.props.Document.nativeWidth);
-                var ctx = canvas.getContext('2d');//draw image to canvas. scale to target dimensions
-                this._videoBox!.player && ctx && ctx.drawImage(this._videoBox!.player, 0, 0, canvas.width, canvas.height);
-
-                //convert to desired file format
-                var dataUrl = canvas.toDataURL('image/png'); // can also use 'image/png'
-                // if you want to preview the captured image,
-
-                let filename = encodeURIComponent("snapshot" + this.props.Document.title + "_" + this.props.Document.curPage).replace(/\./g, "");
-                SearchBox.convertDataUri(dataUrl, filename).then(returnedFilename => {
-                    if (returnedFilename) {
-                        let url = DocServer.prepend(returnedFilename);
-                        let imageSummary = Docs.Create.ImageDocument(url, {
-                            x: NumCast(this.props.Document.x) + width, y: NumCast(this.props.Document.y),
-                            width: 150, height: height / width * 150, title: "--snapshot" + NumCast(this.props.Document.curPage) + " image-"
-                        });
-                        this.props.addDocument && this.props.addDocument(imageSummary, false);
-                        DocUtils.MakeLink(imageSummary, this.props.Document);
-                    }
-                });
-            },
-            icon: "expand-arrows-alt"
-        });
-    }
-
     setVideoBox = (videoBox: VideoBox) => { this._videoBox = videoBox; };
 
     private subView = (_type: CollectionViewType, renderProps: CollectionRenderProps) => {
@@ -123,7 +72,7 @@ export class CollectionVideoView extends React.Component<FieldViewProps> {
 
     render() {
         return (
-            <CollectionBaseView {...this.props} className="collectionVideoView-cont" onContextMenu={this.onContextMenu}>
+            <CollectionBaseView {...this.props} className="collectionVideoView-cont" >
                 {this.subView}
             </CollectionBaseView>);
     }
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index 972e6875d..9806b10b5 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -1,19 +1,24 @@
 import React = require("react");
-import { action, IReactionDisposer, observable, reaction, trace, computed, runInAction, untracked } from "mobx";
+import { action, computed, IReactionDisposer, observable, reaction, runInAction, untracked } from "mobx";
 import { observer } from "mobx-react";
+import * as rp from 'request-promise';
+import { InkTool } from "../../../new_fields/InkField";
 import { makeInterface } from "../../../new_fields/Schema";
 import { Cast, FieldValue, NumCast } from "../../../new_fields/Types";
 import { VideoField } from "../../../new_fields/URLField";
+import { RouteStore } from "../../../server/RouteStore";
+import { Utils } from "../../../Utils";
+import { DocServer } from "../../DocServer";
+import { Docs, DocUtils } from "../../documents/Documents";
 import { ContextMenu } from "../ContextMenu";
 import { ContextMenuProps } from "../ContextMenuItem";
 import { DocComponent } from "../DocComponent";
+import { DocumentDecorations } from "../DocumentDecorations";
 import { InkingControl } from "../InkingControl";
 import { positionSchema } from "./DocumentView";
 import { FieldView, FieldViewProps } from './FieldView';
 import { pageSchema } from "./ImageBox";
 import "./VideoBox.scss";
-import { InkTool } from "../../../new_fields/InkField";
-import { DocumentDecorations } from "../DocumentDecorations";
 
 type VideoDocument = makeInterface<[typeof positionSchema, typeof pageSchema]>;
 const VideoDocument = makeInterface(positionSchema, pageSchema);
@@ -52,21 +57,17 @@ export class VideoBox extends DocComponent<FieldViewProps, VideoDocument>(VideoD
     @action public Play = (update: boolean = true) => {
         this.Playing = true;
         update && this.player && this.player.play();
-        console.log("PLAYING = " + update);
         update && this._youtubePlayer && this._youtubePlayer.playVideo();
         !this._playTimer && (this._playTimer = setInterval(this.updateTimecode, 500));
         this.updateTimecode();
     }
 
     @action public Seek(time: number) {
-        console.log("Seeking " + time);
-        //if (this._youtubePlayer && this._youtubePlayer.getPlayerState() === 5) return;
         this._youtubePlayer && this._youtubePlayer.seekTo(Math.round(time), true);
     }
 
     @action public Pause = (update: boolean = true) => {
         this.Playing = false;
-        console.log("PAUSING = " + update);
         update && this.player && this.player.pause();
         update && this._youtubePlayer && this._youtubePlayer.pauseVideo();
         this._playTimer && clearInterval(this._playTimer);
@@ -119,13 +120,62 @@ export class VideoBox extends DocComponent<FieldViewProps, VideoDocument>(VideoD
         }
     }
 
+    public static async convertDataUri(imageUri: string, returnedFilename: string) {
+        try {
+            let posting = DocServer.prepend(RouteStore.dataUriToImage);
+            const returnedUri = await rp.post(posting, {
+                body: {
+                    uri: imageUri,
+                    name: returnedFilename
+                },
+                json: true,
+            });
+            return returnedUri;
+
+        } catch (e) {
+            console.log(e);
+        }
+    }
     specificContextMenu = (e: React.MouseEvent): void => {
         let field = Cast(this.Document[this.props.fieldKey], VideoField);
         if (field) {
+            let url = field.url.href;
             let subitems: ContextMenuProps[] = [];
+            subitems.push({ description: "Copy path", event: () => { Utils.CopyText(url); }, icon: "expand-arrows-alt" });
             subitems.push({ description: "Toggle Show Controls", event: action(() => VideoBox._showControls = !VideoBox._showControls), icon: "expand-arrows-alt" });
-            subitems.push({ description: "GOTO 3", event: action(() => this.Seek(3)), icon: "expand-arrows-alt" });
-            subitems.push({ description: "PLAY", event: action(() => this.Play()), icon: "expand-arrows-alt" });
+            let width = NumCast(this.props.Document.width);
+            let height = NumCast(this.props.Document.height);
+            subitems.push({
+                description: "Take Snapshot", event: async () => {
+                    var canvas = document.createElement('canvas');
+                    canvas.width = 640;
+                    canvas.height = 640 * NumCast(this.props.Document.nativeHeight) / NumCast(this.props.Document.nativeWidth);
+                    var ctx = canvas.getContext('2d');//draw image to canvas. scale to target dimensions
+                    if (ctx) {
+                        ctx.rect(0, 0, canvas.width, canvas.height);
+                        ctx.fillStyle = "blue";
+                        ctx.fill();
+                        this._videoRef && ctx.drawImage(this._videoRef, 0, 0, canvas.width, canvas.height);
+                    }
+
+                    //convert to desired file format
+                    var dataUrl = canvas.toDataURL('image/png'); // can also use 'image/png'
+                    // if you want to preview the captured image,
+                    let filename = encodeURIComponent("snapshot" + this.props.Document.title + "_" + this.props.Document.curPage).replace(/\./g, "");
+                    VideoBox.convertDataUri(dataUrl, filename).then(returnedFilename => {
+                        if (returnedFilename) {
+                            let url = DocServer.prepend(returnedFilename);
+                            let imageSummary = Docs.Create.ImageDocument(url, {
+                                x: NumCast(this.props.Document.x) + width, y: NumCast(this.props.Document.y),
+                                width: 150, height: height / width * 150, title: "--snapshot" + NumCast(this.props.Document.curPage) + " image-"
+                            });
+                            this.props.ContainingCollectionView && this.props.ContainingCollectionView.props.addDocument && this.props.ContainingCollectionView.props.addDocument(imageSummary, false);
+                            DocUtils.MakeLink(imageSummary, this.props.Document);
+                        }
+                    });
+                },
+                icon: "expand-arrows-alt"
+            });
             ContextMenu.Instance.addItem({ description: "Video Funcs...", subitems: subitems });
         }
     }
@@ -155,13 +205,18 @@ export class VideoBox extends DocComponent<FieldViewProps, VideoDocument>(VideoD
         else this._youtubeContentCreated = false;
 
         let iframe = e.target;
+        let started = true;
         let onYoutubePlayerStateChange = (event: any) => runInAction(() => {
-            console.log("Event  " + event.data);
+            if (started && event.data === YT.PlayerState.PLAYING) {
+                started = false;
+                this._youtubePlayer.unMute();
+                this.Pause();
+                return;
+            }
             if (event.data === YT.PlayerState.PLAYING && !this.Playing) this.Play(false);
             if (event.data === YT.PlayerState.PAUSED && this.Playing) this.Pause(false);
         });
         let onYoutubePlayerReady = (event: any) => {
-            console.log("READY!");
             this._reactionDisposer && this._reactionDisposer();
             this._youtubeReactionDisposer && this._youtubeReactionDisposer();
             this._reactionDisposer = reaction(() => this.props.Document.curPage, () => !this.Playing && this.Seek(this.Document.curPage || 0));
@@ -186,7 +241,7 @@ export class VideoBox extends DocComponent<FieldViewProps, VideoDocument>(VideoD
         let start = untracked(() => Math.round(NumCast(this.props.Document.curPage)));
         return <iframe key={this._youtubeIframeId} id={`${this.youtubeVideoId + this._youtubeIframeId}-player`}
             onLoad={this.youtubeIframeLoaded} className={`${style}`} width="640" height="390"
-            src={`https://www.youtube.com/embed/${this.youtubeVideoId}?enablejsapi=1&rel=0&showinfo=1&autoplay=1&start=${start}&modestbranding=1&controls=${VideoBox._showControls ? 1 : 0}`}
+            src={`https://www.youtube.com/embed/${this.youtubeVideoId}?enablejsapi=1&rel=0&showinfo=1&autoplay=1&mute=1&start=${start}&modestbranding=1&controls=${VideoBox._showControls ? 1 : 0}`}
         ></iframe>;
     }
 
-- 
cgit v1.2.3-70-g09d2


From c351d0d4f6f4e8492cade7d3056e516178f4a138 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Mon, 22 Jul 2019 17:08:25 -0400
Subject: fixed seeking for html video player element

---
 .../views/collections/CollectionVideoView.tsx      | 40 +++++++++++++++++-----
 src/client/views/nodes/VideoBox.tsx                |  1 +
 2 files changed, 33 insertions(+), 8 deletions(-)

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

diff --git a/src/client/views/collections/CollectionVideoView.tsx b/src/client/views/collections/CollectionVideoView.tsx
index d7d5773ba..31a8a93e0 100644
--- a/src/client/views/collections/CollectionVideoView.tsx
+++ b/src/client/views/collections/CollectionVideoView.tsx
@@ -7,6 +7,8 @@ import { CollectionBaseView, CollectionRenderProps, CollectionViewType } from ".
 import { CollectionFreeFormView } from "./collectionFreeForm/CollectionFreeFormView";
 import "./CollectionVideoView.scss";
 import React = require("react");
+import { InkingControl } from "../InkingControl";
+import { InkTool } from "../../../new_fields/InkField";
 
 
 @observer
@@ -19,18 +21,19 @@ export class CollectionVideoView extends React.Component<FieldViewProps> {
     private get uIButtons() {
         let scaling = Math.min(1.8, this.props.ScreenToLocalTransform().Scale);
         let curTime = NumCast(this.props.Document.curPage);
-        return (VideoBox._showControls ? [] : [
-            <div className="collectionVideoView-time" key="time" onPointerDown={this.onResetDown} style={{ transform: `scale(${scaling}, ${scaling})` }}>
-                <span>{"" + Math.round(curTime)}</span>
-                <span style={{ fontSize: 8 }}>{" " + Math.round((curTime - Math.trunc(curTime)) * 100)}</span>
-            </div>,
+        return ([<div className="collectionVideoView-time" key="time" onPointerDown={this.onResetDown} style={{ transform: `scale(${scaling}, ${scaling})` }}>
+            <span>{"" + Math.round(curTime)}</span>
+            <span style={{ fontSize: 8 }}>{" " + Math.round((curTime - Math.trunc(curTime)) * 100)}</span>
+        </div>,
+        VideoBox._showControls ? (null) : [
             <div className="collectionVideoView-play" key="play" onPointerDown={this.onPlayDown} style={{ transform: `scale(${scaling}, ${scaling})` }}>
                 {this._videoBox && this._videoBox.Playing ? "\"" : ">"}
             </div>,
             <div className="collectionVideoView-full" key="full" onPointerDown={this.onFullDown} style={{ transform: `scale(${scaling}, ${scaling})` }}>
                 F
                 </div>
-        ]);
+
+        ]]);
     }
 
     @action
@@ -53,12 +56,33 @@ export class CollectionVideoView extends React.Component<FieldViewProps> {
         }
     }
 
+    _isclick = 0;
     @action
-    onResetDown = () => {
+    onResetDown = (e: React.PointerEvent) => {
         if (this._videoBox) {
             this._videoBox.Pause();
-            this.props.Document.curPage = 0;
+            e.stopPropagation();
+            this._isclick = 0;
+            document.addEventListener("pointermove", this.onPointerMove, true);
+            document.addEventListener("pointerup", this.onPointerUp, true);
+            InkingControl.Instance.switchTool(InkTool.Eraser);
+        }
+    }
+
+    @action
+    onPointerMove = (e: PointerEvent) => {
+        this._isclick += Math.abs(e.movementX) + Math.abs(e.movementY);
+        if (this._videoBox) {
+            this._videoBox.Seek(Math.max(0, NumCast(this.props.Document.curPage, 0) + Math.sign(e.movementX) * 0.0333));
         }
+        e.stopImmediatePropagation();
+    }
+    @action
+    onPointerUp = (e: PointerEvent) => {
+        document.removeEventListener("pointermove", this.onPointerMove, true);
+        document.removeEventListener("pointerup", this.onPointerUp, true);
+        InkingControl.Instance.switchTool(InkTool.None);
+        this._isclick < 10 && (this.props.Document.curPage = 0);
     }
     setVideoBox = (videoBox: VideoBox) => { this._videoBox = videoBox; };
 
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index 83ad2a3b3..5624d41a9 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -65,6 +65,7 @@ export class VideoBox extends DocComponent<FieldViewProps, VideoDocument>(VideoD
 
     @action public Seek(time: number) {
         this._youtubePlayer && this._youtubePlayer.seekTo(Math.round(time), true);
+        this.player && (this.player.currentTime = time);
     }
 
     @action public Pause = (update: boolean = true) => {
-- 
cgit v1.2.3-70-g09d2

