From 7da76d2538ebde21d7a878b5096d5a673e5d6375 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Fri, 10 May 2019 23:01:08 -0400
Subject: added summary screen grab icon as a template view of a text document.
  converted Cast(...ListSpec(Doc)) pattern to DocListCast

---
 src/client/views/collections/CollectionBaseView.tsx | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

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

diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx
index 2b1f7bb37..645296d27 100644
--- a/src/client/views/collections/CollectionBaseView.tsx
+++ b/src/client/views/collections/CollectionBaseView.tsx
@@ -4,7 +4,7 @@ import * as React from 'react';
 import { ContextMenu } from '../ContextMenu';
 import { FieldViewProps } from '../nodes/FieldView';
 import { Cast, FieldValue, PromiseValue, NumCast } from '../../../new_fields/Types';
-import { Doc, FieldResult, Opt } from '../../../new_fields/Doc';
+import { Doc, FieldResult, Opt, DocListCast } from '../../../new_fields/Doc';
 import { listSpec } from '../../../new_fields/Schema';
 import { List } from '../../../new_fields/List';
 import { Id } from '../../../new_fields/RefField';
@@ -63,13 +63,13 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
         if (!(documentToAdd instanceof Doc)) {
             return false;
         }
-        let data = Cast(documentToAdd.data, listSpec(Doc), []).filter(d => d).map(d => d as Doc);
-        for (const doc of data.filter(d => d instanceof Document)) {
+        let data = DocListCast(documentToAdd.data);
+        for (const doc of data) {
             if (this.createsCycle(doc, containerDocument)) {
                 return true;
             }
         }
-        let annots = Cast(documentToAdd.annotations, listSpec(Doc), []).filter(d => d).map(d => d as Doc);
+        let annots = DocListCast(documentToAdd.annotations);
         for (const annot of annots) {
             if (this.createsCycle(annot, containerDocument)) {
                 return true;
-- 
cgit v1.2.3-70-g09d2


From 0b677567dce5673bc45f08704485901801c90646 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Tue, 14 May 2019 22:46:08 -0400
Subject: fixed following links to video frames

---
 src/client/util/DocumentManager.ts                 | 12 ++---
 .../views/collections/CollectionBaseView.tsx       |  2 +-
 .../views/collections/CollectionSchemaView.scss    |  2 +-
 .../views/collections/CollectionVideoView.tsx      | 51 +++++++--------------
 src/client/views/collections/CollectionView.tsx    |  2 -
 src/client/views/nodes/KeyValuePair.scss           |  2 +-
 src/client/views/nodes/PDFBox.tsx                  |  7 +--
 src/client/views/nodes/VideoBox.scss               |  6 ++-
 src/client/views/nodes/VideoBox.tsx                | 53 ++++++++++++++++++----
 9 files changed, 76 insertions(+), 61 deletions(-)

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

diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index 49c5d8c19..51f5fbe9f 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -111,19 +111,19 @@ export class DocumentManager {
 
     @undoBatch
     public jumpToDocument = async (doc: Doc): Promise<void> => {
+        const page = NumCast(doc.page, undefined);
+        const contextDoc = await Cast(doc.annotationOn, Doc);
+        if (contextDoc) {
+            const curPage = NumCast(contextDoc.curPage, page);
+            if (page !== curPage) contextDoc.curPage = page;
+        }
         let docView = DocumentManager.Instance.getDocumentView(doc);
         if (docView) {
             docView.props.focus(docView.props.Document);
         } else {
-            const contextDoc = await Cast(doc.annotationOn, Doc);
             if (!contextDoc) {
                 CollectionDockingView.Instance.AddRightSplit(Doc.MakeDelegate(doc));
             } else {
-                const page = NumCast(doc.page, undefined);
-                const curPage = NumCast(contextDoc.curPage, undefined);
-                if (page !== curPage) {
-                    contextDoc.curPage = page;
-                }
                 let contextView = DocumentManager.Instance.getDocumentView(contextDoc);
                 if (contextView) {
                     contextDoc.panTransformType = "Ease";
diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx
index 645296d27..31bdf213e 100644
--- a/src/client/views/collections/CollectionBaseView.tsx
+++ b/src/client/views/collections/CollectionBaseView.tsx
@@ -87,7 +87,7 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
     @action.bound
     addDocument(doc: Doc, allowDuplicates: boolean = false): boolean {
         let props = this.props;
-        var curPage = Cast(props.Document.curPage, "number", -1);
+        var curPage = NumCast(props.Document.curPage, -1);
         Doc.SetOnPrototype(doc, "page", curPage);
         if (curPage >= 0) {
             Doc.SetOnPrototype(doc, "annotationOn", props.Document);
diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss
index b9ed99155..5e9d2ac67 100644
--- a/src/client/views/collections/CollectionSchemaView.scss
+++ b/src/client/views/collections/CollectionSchemaView.scss
@@ -127,7 +127,7 @@
                 max-width: 100%;
                 height: 100%;
             }
-            .videobox-cont {
+            .videoBox-cont {
                 object-fit: contain;
                 width: auto;
                 height: 100%;
diff --git a/src/client/views/collections/CollectionVideoView.tsx b/src/client/views/collections/CollectionVideoView.tsx
index cb3fd1ba4..16121bb1b 100644
--- a/src/client/views/collections/CollectionVideoView.tsx
+++ b/src/client/views/collections/CollectionVideoView.tsx
@@ -9,27 +9,26 @@ import { FieldView, FieldViewProps } from "../nodes/FieldView";
 import { emptyFunction } from "../../../Utils";
 import { Id } from "../../../new_fields/RefField";
 import { VideoBox } from "../nodes/VideoBox";
+import { NumCast } from "../../../new_fields/Types";
 
 
 @observer
 export class CollectionVideoView extends React.Component<FieldViewProps> {
-    private _videoBox: VideoBox | undefined = undefined;
-    @observable _playTimer?: NodeJS.Timeout = undefined;
-
-    @observable _currentTimecode: number = 0;
+    private _videoBox?: VideoBox;
 
     public static LayoutString(fieldKey: string = "data") {
         return FieldView.LayoutString(CollectionVideoView, fieldKey);
     }
     private get uIButtons() {
         let scaling = Math.min(1.8, this.props.ScreenToLocalTransform().Scale);
+        let curTime = NumCast(this.props.Document.curPage);
         return ([
             <div className="collectionVideoView-time" key="time" onPointerDown={this.onResetDown} style={{ transform: `scale(${scaling}, ${scaling})` }}>
-                <span>{"" + Math.round(this._currentTimecode)}</span>
-                <span style={{ fontSize: 8 }}>{" " + Math.round((this._currentTimecode - Math.trunc(this._currentTimecode)) * 100)}</span>
+                <span>{"" + Math.round(curTime)}</span>
+                <span style={{ fontSize: 8 }}>{" " + Math.round((curTime - Math.trunc(curTime)) * 100)}</span>
             </div>,
             <div className="collectionVideoView-play" key="play" onPointerDown={this.onPlayDown} style={{ transform: `scale(${scaling}, ${scaling})` }}>
-                {this._playTimer ? "\"" : ">"}
+                {this._videoBox && this._videoBox.Playing ? "\"" : ">"}
             </div>,
             <div className="collectionVideoView-full" key="full" onPointerDown={this.onFullDown} style={{ transform: `scale(${scaling}, ${scaling})` }}>
                 F
@@ -37,37 +36,21 @@ export class CollectionVideoView extends React.Component<FieldViewProps> {
         ]);
     }
 
-    @action
-    updateTimecode = () => {
-        if (this._videoBox && this._videoBox.player) {
-            this._currentTimecode = this._videoBox.player.currentTime;
-            this.props.Document.curPage = Math.round(this._currentTimecode);
-        }
-    }
-
-    componentDidMount() { this.updateTimecode(); }
-
-    componentWillUnmount() { if (this._playTimer) clearInterval(this._playTimer); }
-
     @action
     onPlayDown = () => {
         if (this._videoBox && this._videoBox.player) {
-            if (this._videoBox.player.paused) {
-                this._videoBox.player.play();
-                if (!this._playTimer) this._playTimer = setInterval(this.updateTimecode, 1000);
+            if (this._videoBox.Playing) {
+                this._videoBox.Pause();
             } else {
-                this._videoBox.player.pause();
-                if (this._playTimer) clearInterval(this._playTimer);
-                this._playTimer = undefined;
-
+                this._videoBox.Play();
             }
         }
     }
 
     @action
     onFullDown = (e: React.PointerEvent) => {
-        if (this._videoBox && this._videoBox.player) {
-            this._videoBox.player.requestFullscreen();
+        if (this._videoBox) {
+            this._videoBox.FullScreen();
             e.stopPropagation();
             e.preventDefault();
         }
@@ -75,12 +58,9 @@ export class CollectionVideoView extends React.Component<FieldViewProps> {
 
     @action
     onResetDown = () => {
-        if (this._videoBox && this._videoBox.player) {
-            this._videoBox.player.pause();
-            this._videoBox.player.currentTime = 0;
-            if (this._playTimer) clearInterval(this._playTimer);
-            this._playTimer = undefined;
-            this.updateTimecode();
+        if (this._videoBox) {
+            this._videoBox.Pause();
+            this.props.Document.curPage = 0;
         }
     }
 
@@ -90,7 +70,7 @@ export class CollectionVideoView extends React.Component<FieldViewProps> {
         }
     }
 
-    setVideoBox = (player: VideoBox) => { this._videoBox = player; };
+    setVideoBox = (videoBox: VideoBox) => { this._videoBox = videoBox; };
 
     private subView = (_type: CollectionViewType, renderProps: CollectionRenderProps) => {
         let props = { ...this.props, ...renderProps };
@@ -101,6 +81,7 @@ export class CollectionVideoView extends React.Component<FieldViewProps> {
     }
 
     render() {
+        trace();
         return (
             <CollectionBaseView {...this.props} className="collectionVideoView-cont" onContextMenu={this.onContextMenu}>
                 {this.subView}
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 8c1442d38..55fd2a284 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -9,9 +9,7 @@ import { ContextMenu } from '../ContextMenu';
 import { CurrentUserUtils } from '../../../server/authentication/models/current_user_utils';
 import { observer } from 'mobx-react';
 import { undoBatch } from '../../util/UndoManager';
-import { trace } from 'mobx';
 import { Id } from '../../../new_fields/RefField';
-import { Main } from '../Main';
 
 @observer
 export class CollectionView extends React.Component<FieldViewProps> {
diff --git a/src/client/views/nodes/KeyValuePair.scss b/src/client/views/nodes/KeyValuePair.scss
index 4f305dc91..a1c5d5537 100644
--- a/src/client/views/nodes/KeyValuePair.scss
+++ b/src/client/views/nodes/KeyValuePair.scss
@@ -30,7 +30,7 @@
         max-height: 36px;
         width: auto;
     }
-    .videobox-cont{
+    .videoBox-cont{
         width: auto; 
         max-height: 36px; 
     }
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index 6cbf066ca..14fe2df80 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -58,7 +58,7 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
     @observable private _renderAsSvg = true;
     @observable private _alt = false;
 
-    private _reactionDisposer: Opt<IReactionDisposer>;
+    private _reactionDisposer?: IReactionDisposer;
 
     @observable private _perPageInfo: Object[] = []; //stores pageInfo
     @observable private _pageInfo: any = { area: [], divs: [], anno: [] }; //divs is array of objects linked to anno
@@ -84,9 +84,7 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
     }
 
     componentWillUnmount() {
-        if (this._reactionDisposer) {
-            this._reactionDisposer();
-        }
+        if (this._reactionDisposer) this._reactionDisposer();
     }
 
     /**
@@ -338,7 +336,6 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
     @action onKeyDown = (e: React.KeyboardEvent) => e.key === "Alt" && (this._alt = true);
     @action onKeyUp = (e: React.KeyboardEvent) => e.key === "Alt" && (this._alt = false);
     render() {
-        trace();
         let classname = "pdfBox-cont"; // + (this.props.isSelected() && !InkingControl.Instance.selectedTool && !this._alt ? "-interactive" : "");
         return (
             <div className={classname} tabIndex={0} ref={this._mainDiv} onPointerDown={this.onPointerDown} onKeyDown={this.onKeyDown} onKeyUp={this.onKeyUp} >
diff --git a/src/client/views/nodes/VideoBox.scss b/src/client/views/nodes/VideoBox.scss
index 76bbeb37c..35db64cf4 100644
--- a/src/client/views/nodes/VideoBox.scss
+++ b/src/client/views/nodes/VideoBox.scss
@@ -1,4 +1,8 @@
-.videobox-cont{
+.videoBox-cont, .videoBox-cont-fullScreen{
     width: 100%; 
     height: Auto; 
+}
+
+.videoBox-cont-fullScreen {
+    pointer-events: all;
 }
\ No newline at end of file
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index 740d4cc1b..96dc884c8 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -3,16 +3,15 @@ import { observer } from "mobx-react";
 import { FieldView, FieldViewProps } from './FieldView';
 import * as rp from "request-promise";
 import "./VideoBox.scss";
-import { action, computed, trace } from "mobx";
+import { action, IReactionDisposer, reaction, observable } from "mobx";
 import { DocComponent } from "../DocComponent";
 import { positionSchema } from "./DocumentView";
 import { makeInterface } from "../../../new_fields/Schema";
 import { pageSchema } from "./ImageBox";
-import { Cast, FieldValue, NumCast, ToConstructor, ListSpec } from "../../../new_fields/Types";
+import { Cast, FieldValue, NumCast } from "../../../new_fields/Types";
 import { VideoField } from "../../../new_fields/URLField";
 import Measure from "react-measure";
 import "./VideoBox.scss";
-import { Field, FieldResult, Opt } from "../../../new_fields/Doc";
 import { RouteStore } from "../../../server/RouteStore";
 import { DocServer } from "../../DocServer";
 
@@ -21,10 +20,12 @@ const VideoDocument = makeInterface(positionSchema, pageSchema);
 
 @observer
 export class VideoBox extends DocComponent<FieldViewProps, VideoDocument>(VideoDocument) {
-
+    private _reactionDisposer?: IReactionDisposer;
     private _videoRef: HTMLVideoElement | null = null;
     private _loaded: boolean = false;
-    private get initialTimecode() { return FieldValue(this.Document.curPage, -1); }
+    @observable _playTimer?: NodeJS.Timeout = undefined;
+    @observable _fullScreen = false;
+    @observable public Playing: boolean = false;
     public static LayoutString() { return FieldView.LayoutString(VideoBox); }
 
     public get player(): HTMLVideoElement | undefined {
@@ -48,19 +49,50 @@ 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, 1000);
+    }
+
+    @action public Pause() {
+        this.Playing = false;
+        if (this.player) this.player.pause();
+        if (this._playTimer) {
+            clearInterval(this._playTimer);
+            this._playTimer = undefined;
+        }
+    }
+
+    @action public FullScreen() {
+        this._fullScreen = true;
+        this.player && this.player.requestFullscreen();
+    }
+
+    @action
+    updateTimecode = () => this.player && (this.props.Document.curPage = this.player.currentTime);
+
     componentDidMount() {
         if (this.props.setVideoBox) this.props.setVideoBox(this);
     }
+    componentWillUnmount() {
+        this.Pause();
+        if (this._reactionDisposer) this._reactionDisposer();
+    }
 
     @action
     setVideoRef = (vref: HTMLVideoElement | null) => {
         this._videoRef = vref;
-        if (this.initialTimecode >= 0 && vref) {
-            vref.currentTime = this.initialTimecode;
+        if (vref) {
+            vref.onfullscreenchange = action((e) => this._fullScreen = vref.webkitDisplayingFullscreen);
+            if (this._reactionDisposer) this._reactionDisposer();
+            this._reactionDisposer = reaction(() => this.props.Document.curPage, () =>
+                vref.currentTime = NumCast(this.props.Document.curPage, 0), { fireImmediately: true });
         }
     }
     videoContent(path: string) {
-        return <video className="videobox-cont" ref={this.setVideoRef}>
+        let style = "videoBox-cont" + (this._fullScreen ? "-fullScreen" : "");
+        return <video className={`${style}`} ref={this.setVideoRef} onPointerDown={this.onPointerDown}>
             <source src={path} type="video/mp4" />
             Not supported.
         </video>;
@@ -100,7 +132,10 @@ export class VideoBox extends DocComponent<FieldViewProps, VideoDocument>(VideoD
             }
         })
     }
-
+    onPointerDown = (e: React.PointerEvent) => {
+        e.preventDefault();
+        e.stopPropagation();
+    }
 
     render() {
         let field = Cast(this.Document[this.props.fieldKey], VideoField);
-- 
cgit v1.2.3-70-g09d2

