aboutsummaryrefslogtreecommitdiff
path: root/src/client/views
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views')
-rw-r--r--src/client/views/Main.tsx2
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx37
-rw-r--r--src/client/views/nodes/RecordingBox/RecordingBox.tsx14
-rw-r--r--src/client/views/nodes/RecordingBox/RecordingView.scss18
-rw-r--r--src/client/views/nodes/RecordingBox/RecordingView.tsx41
-rw-r--r--src/client/views/nodes/VideoBox.tsx23
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 {