From 3be42131bc08024f06e0daec8d09e45bf3f1ddab Mon Sep 17 00:00:00 2001 From: bob Date: Mon, 13 May 2019 16:21:28 -0400 Subject: a bunch of fixes to schemas, marquees, and an experimental feature to set a document's data with linking UI --- src/client/views/nodes/PDFBox.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/client/views/nodes/PDFBox.tsx') diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index cb27b3f1b..ff8737192 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -1,5 +1,5 @@ import * as htmlToImage from "html-to-image"; -import { action, computed, IReactionDisposer, observable, reaction, Reaction, trace } from 'mobx'; +import { action, computed, IReactionDisposer, observable, reaction, Reaction, trace, runInAction } from 'mobx'; import { observer } from "mobx-react"; import 'react-image-lightbox/style.css'; import Measure from "react-measure"; @@ -223,7 +223,7 @@ export class PDFBox extends DocComponent(PdfDocumen document.addEventListener("pointerup", this.onPointerUp); } if (this.props.isSelected() && e.buttons === 2) { - this._alt = true; + runInAction(() => this._alt = true); document.removeEventListener("pointerup", this.onPointerUp); document.addEventListener("pointerup", this.onPointerUp); } -- cgit v1.2.3-70-g09d2 From a96b2d61fe05eacaaad793f2d9e19c3d99708137 Mon Sep 17 00:00:00 2001 From: bob Date: Tue, 14 May 2019 10:03:03 -0400 Subject: added non-working mp4 youtube video streamer --- src/client/views/nodes/PDFBox.tsx | 35 ++++++++-------------------- src/client/views/nodes/VideoBox.tsx | 46 +++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 25 deletions(-) (limited to 'src/client/views/nodes/PDFBox.tsx') diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index ff8737192..6cbf066ca 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -53,8 +53,10 @@ export class PDFBox extends DocComponent(PdfDocumen public static LayoutString() { return FieldView.LayoutString(PDFBox); } private _mainDiv = React.createRef(); + private renderHeight = 2400; @observable private _renderAsSvg = true; + @observable private _alt = false; private _reactionDisposer: Opt; @@ -65,8 +67,8 @@ export class PDFBox extends DocComponent(PdfDocumen @observable private _interactive: boolean = false; @observable private _loaded: boolean = false; - @computed private get curPage() { return FieldValue(this.Document.curPage, 1); } - @computed private get thumbnailPage() { return Cast(this.props.Document.thumbnailPage, "number", -1); } + @computed private get curPage() { return NumCast(this.Document.curPage, 1); } + @computed private get thumbnailPage() { return NumCast(this.props.Document.thumbnailPage, -1); } componentDidMount() { this._reactionDisposer = reaction( @@ -162,10 +164,8 @@ export class PDFBox extends DocComponent(PdfDocumen let index: any; this._pageInfo.divs.forEach((obj: any) => { obj.spans.forEach((element: any) => { - if (element === span) { - if (!index) { - index = this._pageInfo.divs.indexOf(obj); - } + if (element === span && !index) { + index = this._pageInfo.divs.indexOf(obj); } }); }); @@ -243,7 +243,6 @@ export class PDFBox extends DocComponent(PdfDocumen } - @action saveThumbnail = () => { this._renderAsSvg = false; @@ -284,20 +283,16 @@ export class PDFBox extends DocComponent(PdfDocumen this.props.Document.nativeHeight = nativeHeight; } } - renderHeight = 2400; @computed get pdfPage() { return ; } @computed get pdfContent() { - let page = this.curPage; - const renderHeight = 2400; let pdfUrl = Cast(this.props.Document[this.props.fieldKey], PdfField); if (!pdfUrl) { return

No pdf url to render

; } - let xf = FieldValue(this.Document.nativeHeight, 0) / renderHeight; let body = NumCast(this.props.Document.nativeHeight) ? this.pdfPage : @@ -307,6 +302,7 @@ export class PDFBox extends DocComponent(PdfDocumen } ; + let xf = NumCast(this.Document.nativeHeight) / this.renderHeight; return
{body} @@ -339,22 +335,11 @@ export class PDFBox extends DocComponent(PdfDocumen } return (null); } - @observable _alt = false; - @action - onKeyDown = (e: React.KeyboardEvent) => { - if (e.key === "Alt") { - this._alt = true; - } - } - @action - onKeyUp = (e: React.KeyboardEvent) => { - if (e.key === "Alt") { - this._alt = false; - } - } + @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" : ""); + let classname = "pdfBox-cont"; // + (this.props.isSelected() && !InkingControl.Instance.selectedTool && !this._alt ? "-interactive" : ""); return (
{this.pdfRenderer} diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx index 97c5d8818..740d4cc1b 100644 --- a/src/client/views/nodes/VideoBox.tsx +++ b/src/client/views/nodes/VideoBox.tsx @@ -1,6 +1,7 @@ import React = require("react"); 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 { DocComponent } from "../DocComponent"; @@ -12,6 +13,8 @@ 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"; type VideoDocument = makeInterface<[typeof positionSchema, typeof pageSchema]>; const VideoDocument = makeInterface(positionSchema, pageSchema); @@ -63,11 +66,54 @@ export class VideoBox extends DocComponent(VideoD ; } + getMp4ForVideo(videoId: string = "JN5beCVArMs") { + return new Promise(async (resolve, reject) => { + const videoInfoRequestConfig = { + headers: { + connection: 'keep-alive', + "user-agent": 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:43.0) Gecko/20100101 Firefox/46.0', + }, + + } + try { + let responseSchema: any = {}; + const videoInfoResponse = await rp.get(DocServer.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'); + const subString = dataHtml.substring(start, end) + const subJson = JSON.parse(subString); + const stringSub = subJson.args.player_response; + const stringSubJson = JSON.parse(stringSub); + const adaptiveFormats = stringSubJson.streamingData.adaptiveFormats; + const videoDetails = stringSubJson.videoDetails + responseSchema["adaptiveFormats"] = adaptiveFormats; + responseSchema["videoDetails"] = videoDetails; + resolve(responseSchema) + } + catch (err) { + console.log(` + --- Youtube --- + Function: getMp4ForVideo + Error: `, err) + reject(err) + } + }) + } + + render() { let field = Cast(this.Document[this.props.fieldKey], VideoField); if (!field) { return
Loading
; } + + // this.getMp4ForVideo().then((mp4) => { + // console.log(mp4); + // }).catch(e => { + // console.log("") + // }); + // // let content = this.videoContent(field.url.href); return NumCast(this.props.Document.nativeHeight) ? content : -- cgit v1.2.3-70-g09d2 From 0b677567dce5673bc45f08704485901801c90646 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik 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/nodes/PDFBox.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 => { + 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 { @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 { - 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 ([
- {"" + Math.round(this._currentTimecode)} - {" " + Math.round((this._currentTimecode - Math.trunc(this._currentTimecode)) * 100)} + {"" + Math.round(curTime)} + {" " + Math.round((curTime - Math.trunc(curTime)) * 100)}
,
- {this._playTimer ? "\"" : ">"} + {this._videoBox && this._videoBox.Playing ? "\"" : ">"}
,
F @@ -37,37 +36,21 @@ export class CollectionVideoView extends React.Component { ]); } - @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 { @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 { } } - 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 { } render() { + trace(); return ( {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 { 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(PdfDocumen @observable private _renderAsSvg = true; @observable private _alt = false; - private _reactionDisposer: Opt; + 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(PdfDocumen } componentWillUnmount() { - if (this._reactionDisposer) { - this._reactionDisposer(); - } + if (this._reactionDisposer) this._reactionDisposer(); } /** @@ -338,7 +336,6 @@ export class PDFBox extends DocComponent(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 (
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(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(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