diff options
Diffstat (limited to 'src/client/views')
| -rw-r--r-- | src/client/views/Main.tsx | 2 | ||||
| -rw-r--r-- | src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx | 37 | ||||
| -rw-r--r-- | src/client/views/nodes/RecordingBox/RecordingBox.tsx | 14 | ||||
| -rw-r--r-- | src/client/views/nodes/RecordingBox/RecordingView.scss | 18 | ||||
| -rw-r--r-- | src/client/views/nodes/RecordingBox/RecordingView.tsx | 41 | ||||
| -rw-r--r-- | src/client/views/nodes/VideoBox.tsx | 23 |
6 files changed, 79 insertions, 56 deletions
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx index 8560ccb29..517fe097c 100644 --- a/src/client/views/Main.tsx +++ b/src/client/views/Main.tsx @@ -8,6 +8,7 @@ import { AssignAllExtensions } from "../../extensions/General/Extensions"; import { Docs } from "../documents/Documents"; import { CurrentUserUtils } from "../util/CurrentUserUtils"; import { LinkManager } from "../util/LinkManager"; +import { RecordingApi } from "../util/RecordingApi"; import { CollectionView } from "./collections/CollectionView"; import { MainView } from "./MainView"; @@ -36,5 +37,6 @@ AssignAllExtensions(); const expires = "expires=" + d.toUTCString(); document.cookie = `loadtime=${loading};${expires};path=/`; new LinkManager(); + new RecordingApi; ReactDOM.render(<MainView />, document.getElementById('root')); })();
\ No newline at end of file diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index edc872a40..aa2e0c417 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -54,6 +54,7 @@ import "./CollectionFreeFormView.scss"; import { MarqueeView } from "./MarqueeView"; import React = require("react"); import e = require("connect-flash"); +import { RecordingApi } from "../../../util/RecordingApi"; export const panZoomSchema = createSchema({ _panX: "number", @@ -121,8 +122,6 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection @observable _keyframeEditing = false; @observable ChildDrag: DocumentView | undefined; // child document view being dragged. needed to update drop areas of groups when a group item is dragged. - @observable storedMovements: object[] = []; // stores the movement if in recoding mode - @computed get views() { return this._layoutElements.filter(ele => ele.bounds && !ele.bounds.z).map(ele => ele.ele); } @computed get backgroundEvents() { return this.props.layerProvider?.(this.layoutDoc) === false && SnappingManager.GetIsDragging(); } @computed get backgroundActive() { return this.props.layerProvider?.(this.layoutDoc) === false && this.props.isContentActive(); } @@ -964,36 +963,16 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection } } - - followMovements = (): void => { - // need the first for subtraction - let first = null; - - this.storedMovements.forEach(movement => { - if (first === null) first = movement.time; - - // set the pan to what was stored - setTimeout(() => { - this.Document._panX = movement.panX; - this.Document._panY = movement.panY; - }, movement.time - first) - }) - - // for now, clear the movements - this.storedMovements = [] - } - @action setPan(panX: number, panY: number, panTime: number = 0, clamp: boolean = false) { - // if not presenting, just retrace the movements + // set the current respective FFview to the tab being panned. + Doc.UserDoc()?.presentationMode === 'recording' && RecordingApi.Instance.setRecordingFFView(this); + // TODO: make this based off the specific recording FFView + Doc.UserDoc()?.presentationMode === 'none' && RecordingApi.Instance.setPlayFFView(this); if (Doc.UserDoc()?.presentationMode === 'watching') { - this.followMovements() - return; - } - - if (Doc.UserDoc()?.presentationMode === 'recording') { - // store as many movments as possible - this.storedMovements.push({time: new Date().getTime(), panX, panY}) + RecordingApi.Instance.pauseVideoAndMovements(); + Doc.UserDoc().presentationMode = 'none'; + // RecordingApi.Instance.pauseMovements() } if (!this.isAnnotationOverlay && clamp) { diff --git a/src/client/views/nodes/RecordingBox/RecordingBox.tsx b/src/client/views/nodes/RecordingBox/RecordingBox.tsx index a49cbbea5..d00f05759 100644 --- a/src/client/views/nodes/RecordingBox/RecordingBox.tsx +++ b/src/client/views/nodes/RecordingBox/RecordingBox.tsx @@ -1,7 +1,7 @@ import { action, observable } from "mobx"; import { observer } from "mobx-react"; import * as React from "react"; -import { AudioField, VideoField } from "../../../../fields/URLField"; +import { VideoField } from "../../../../fields/URLField"; import { Upload } from "../../../../server/SharedMediaTypes"; import { ViewBoxBaseComponent } from "../../DocComponent"; import { FieldView } from "../FieldView"; @@ -9,6 +9,8 @@ import { VideoBox } from "../VideoBox"; import { RecordingView } from './RecordingView'; import { DocumentType } from "../../../documents/DocumentTypes"; +import { RecordingApi } from "../../../util/RecordingApi"; + @observer export class RecordingBox extends ViewBoxBaseComponent() { @@ -31,18 +33,20 @@ export class RecordingBox extends ViewBoxBaseComponent() { @action setResult = (info: Upload.FileInformation) => { - console.log("Setting result to " + info) + // console.log("Setting result to " + info) this.result = info - console.log(this.result.accessPaths.agnostic.client) + // console.log(this.result.accessPaths.agnostic.client) this.dataDoc.type = DocumentType.VID; - console.log(this.videoDuration) + // console.log(this.videoDuration) this.dataDoc[this.fieldKey + "-duration"] = this.videoDuration; // this.layoutDoc.layout = VideoBox.LayoutString(this.fieldKey); this.dataDoc.layout = VideoBox.LayoutString(this.fieldKey); // this.dataDoc.nativeWidth = this.dataDoc.nativeHeight = undefined; // this.layoutDoc._fitWidth = undefined; - this.dataDoc[this.props.fieldKey] = new VideoField(this.result.accessPaths.agnostic.client); + this.dataDoc[this.props.fieldKey] = new VideoField(this.result.accessPaths.agnostic.client); + // stringify the presenation and store it + this.dataDoc[this.fieldKey + "-presentation"] = JSON.stringify(RecordingApi.Instance.clear()); } render() { diff --git a/src/client/views/nodes/RecordingBox/RecordingView.scss b/src/client/views/nodes/RecordingBox/RecordingView.scss index 0c153c9c8..c55af5952 100644 --- a/src/client/views/nodes/RecordingBox/RecordingView.scss +++ b/src/client/views/nodes/RecordingBox/RecordingView.scss @@ -1,9 +1,11 @@ video { - flex: 100%; + // flex: 100%; width: 100%; // min-height: 400px; - height: auto; - display: block; + //height: auto; + height: 100%; + //display: block; + object-fit: cover; background-color: black; } @@ -14,18 +16,20 @@ button { .recording-container { height: 100%; width: 100%; - display: flex; + // display: flex; pointer-events: all; + background-color: grey; } .video-wrapper { - max-width: 600px; - max-width: 700px; + // max-width: 600px; + // max-width: 700px; position: relative; display: flex; justify-content: center; - overflow: hidden; + // overflow: hidden; border-radius: 10px; + margin: 0; } .video-wrapper:hover .controls { diff --git a/src/client/views/nodes/RecordingBox/RecordingView.tsx b/src/client/views/nodes/RecordingBox/RecordingView.tsx index e5f6deca2..0a8294dcf 100644 --- a/src/client/views/nodes/RecordingBox/RecordingView.tsx +++ b/src/client/views/nodes/RecordingBox/RecordingView.tsx @@ -8,6 +8,8 @@ import { IconContext } from "react-icons"; import { Networking } from '../../../Network'; import { Upload } from '../../../../server/SharedMediaTypes'; +import { RecordingApi } from '../../../util/RecordingApi'; + enum RecordingStatus { Recording, @@ -43,18 +45,23 @@ export function RecordingView(props: IRecordingViewProps) { const audioRecorder = useRef<MediaRecorder | null>(null); const videoElementRef = useRef<HTMLVideoElement | null>(null); - const [finished, setFinished] = useState<Boolean>(false) + const [finished, setFinished] = useState<Boolean>(false) const DEFAULT_MEDIA_CONSTRAINTS = { - video: true, - audio: true, - // audio: { - // echoCancellation: true, - // noiseSuppression: true, - // sampleRate: 44100 - // } + // video: true, + // audio: true + video: { + width: 1280, + height: 720, + }, + // audio: true, + audio: { + echoCancellation: true, + noiseSuppression: true, + sampleRate: 44100 + } } useEffect(() => { @@ -150,7 +157,9 @@ export function RecordingView(props: IRecordingViewProps) { // } videoRecorder.current.onstart = (event: any) => { - setRecording(true); + setRecording(true); + // RecordingApi.Instance.clear(); + RecordingApi.Instance.start(); } videoRecorder.current.onstop = () => { @@ -163,7 +172,8 @@ export function RecordingView(props: IRecordingViewProps) { // reset the temporary chunks videoChunks = [] setRecording(false); - setFinished(true); + setFinished(true); + RecordingApi.Instance.pause(); } // recording paused @@ -173,12 +183,14 @@ export function RecordingView(props: IRecordingViewProps) { // reset the temporary chunks videoChunks = [] - setRecording(false); + setRecording(false); + RecordingApi.Instance.pause(); } videoRecorder.current.onresume = async (event: any) => { await startShowingStream(); - setRecording(true); + setRecording(true); + RecordingApi.Instance.resume(); } videoRecorder.current.start(200) @@ -244,7 +256,7 @@ export function RecordingView(props: IRecordingViewProps) { return toTwoDigit(minutes) + " : " + toTwoDigit(seconds); } - return ( + return ( <div className="recording-container"> <div className="video-wrapper"> <video id="video" @@ -293,8 +305,7 @@ export function RecordingView(props: IRecordingViewProps) { <i className="bx bxs-volume-mute"></i> )} </button> */} - </div> - + </div> </div> </div>) }
\ No newline at end of file diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx index b424225e7..8aecc2483 100644 --- a/src/client/views/nodes/VideoBox.tsx +++ b/src/client/views/nodes/VideoBox.tsx @@ -28,6 +28,7 @@ import { AnchorMenu } from "../pdf/AnchorMenu"; import { StyleProp } from "../StyleProvider"; import { FieldView, FieldViewProps } from './FieldView'; import "./VideoBox.scss"; +import { RecordingApi } from "../../util/RecordingApi"; const path = require('path'); @@ -117,6 +118,12 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp return field?.url.href ?? vfield?.url.href ?? ""; } + // returns the presentation data if it exists, null otherwise + @computed get presentation() { + const data = this.dataDoc[this.fieldKey + '-presentation']; + return data ? JSON.parse(data) : null; + } + @computed private get timeline() { return this._stackedTimeline; } private get transition() { return this._clicking ? "left 0.5s, width 0.5s, height 0.5s" : ""; } // css transition for hiding/showing timeline @@ -147,6 +154,17 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp // plays video @action public Play = (update: boolean = true) => { + if (Doc.UserDoc().presentationMode === 'watching' && !this._playing) { + console.log('VideoBox : Play : presentation mode', this._playing); + return; + } + + // if presentation isn't null, call followmovements on the recording api + if (this.presentation) { + const err = RecordingApi.Instance.playMovements(this.presentation, this.player?.currentTime || 0, this); + err && console.log(err) + } + this._playing = true; const eleTime = this.player?.currentTime || 0; if (this.timeline) { @@ -184,6 +202,11 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp // pauses video @action public Pause = (update: boolean = true) => { + if (this.presentation) { + const err = RecordingApi.Instance.pauseMovements(); + err && console.log(err); + } + this._playing = false; this.removeCurrentlyPlaying(); try { |
