aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/views/nodes/ScreenshotBox.scss2
-rw-r--r--src/client/views/nodes/ScreenshotBox.tsx101
2 files changed, 38 insertions, 65 deletions
diff --git a/src/client/views/nodes/ScreenshotBox.scss b/src/client/views/nodes/ScreenshotBox.scss
index 141960f60..ab54cf526 100644
--- a/src/client/views/nodes/ScreenshotBox.scss
+++ b/src/client/views/nodes/ScreenshotBox.scss
@@ -26,7 +26,7 @@
position: absolute;
right: 25;
top: 0;
- width:50;
+ width:25;
height: 25;
.screenshotBox-snapshot{
color : white;
diff --git a/src/client/views/nodes/ScreenshotBox.tsx b/src/client/views/nodes/ScreenshotBox.tsx
index bed6566a6..999ccf5f6 100644
--- a/src/client/views/nodes/ScreenshotBox.tsx
+++ b/src/client/views/nodes/ScreenshotBox.tsx
@@ -1,6 +1,6 @@
import React = require("react");
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-import { action, computed, IReactionDisposer, observable } from "mobx";
+import { action, computed, observable } from "mobx";
import { observer } from "mobx-react";
import { DateField } from "../../../fields/DateField";
import { Doc, WidthSym } from "../../../fields/Doc";
@@ -16,17 +16,13 @@ import { DocUtils } from "../../documents/Documents";
import { DocumentType } from "../../documents/DocumentTypes";
import { Networking } from "../../Network";
import { CurrentUserUtils } from "../../util/CurrentUserUtils";
-import { DocumentManager } from "../../util/DocumentManager";
import { CollectionFreeFormView } from "../collections/collectionFreeForm/CollectionFreeFormView";
import { CollectionStackedTimeline } from "../collections/CollectionStackedTimeline";
import { ContextMenu } from "../ContextMenu";
-import { ContextMenuProps } from "../ContextMenuItem";
import { ViewBoxAnnotatableComponent } from "../DocComponent";
-import { DocumentView } from "./DocumentView";
import { FieldView, FieldViewProps } from './FieldView';
import "./ScreenshotBox.scss";
import { VideoBox } from "./VideoBox";
-const path = require('path');
declare class MediaRecorder {
constructor(e: any, options?: any); // whatever MediaRecorder has
}
@@ -36,27 +32,22 @@ const ScreenshotDocument = makeInterface(documentSchema);
@observer
export class ScreenshotBox extends ViewBoxAnnotatableComponent<FieldViewProps, ScreenshotDocument>(ScreenshotDocument) {
- private _reactionDisposer?: IReactionDisposer;
- private _videoRef: HTMLVideoElement | null = null;
- private _vchunks: any;
- private _achunks: any;
- private _vrecorder: any;
- private _arecorder: any;
- private _dictation: Doc | undefined;
- private _dictationView: DocumentView | undefined;
public static LayoutString(fieldKey: string) { return FieldView.LayoutString(ScreenshotBox, fieldKey); }
+ private _videoRef = React.createRef<HTMLVideoElement>();
+ private _audioRec: any;
+ private _videoRec: any;
+ @observable _screenCapture = false;
@computed get recordingStart() { return Cast(this.dataDoc[this.props.fieldKey + "-recordingStart"], DateField)?.date.getTime(); }
-
getAnchor = () => {
- const startTime = Cast(this.layoutDoc._currentTimecode, "number", null) || (this._vrecorder ? (Date.now() - (this.recordingStart || 0)) / 1000 : undefined);
- return CollectionStackedTimeline.createAnchor(this.rootDoc, this.dataDoc, this.annotationKey, "_timecodeToShow" /* audioStart */, "_timecodeToHide" /* audioEnd */,
+ const startTime = Cast(this.layoutDoc._currentTimecode, "number", null) || (this._videoRec ? (Date.now() - (this.recordingStart || 0)) / 1000 : undefined);
+ return CollectionStackedTimeline.createAnchor(this.rootDoc, this.dataDoc, this.annotationKey, "_timecodeToShow", "_timecodeToHide",
startTime, startTime === undefined ? undefined : startTime + 3)
|| this.rootDoc;
}
videoLoad = () => {
- const aspect = this._videoRef!.videoWidth / this._videoRef!.videoHeight;
+ const aspect = this._videoRef.current!.videoWidth / this._videoRef.current!.videoHeight;
const nativeWidth = Doc.NativeWidth(this.layoutDoc);
const nativeHeight = Doc.NativeHeight(this.layoutDoc);
if (!nativeWidth || !nativeHeight) {
@@ -67,28 +58,19 @@ export class ScreenshotBox extends ViewBoxAnnotatableComponent<FieldViewProps, S
}
componentWillUnmount() {
- this._reactionDisposer?.();
const ind = DocUtils.ActiveRecordings.indexOf(this);
ind !== -1 && (DocUtils.ActiveRecordings.splice(ind, 1));
}
- @action
- setVideoRef = (vref: HTMLVideoElement | null) => this._videoRef = vref;
-
- @observable _screenCapture = false;
specificContextMenu = (e: React.MouseEvent): void => {
- const field = Cast(this.dataDoc[this.fieldKey], VideoField);
- if (field) {
- const subitems: ContextMenuProps[] = [];
- subitems.push({ description: "Screen Capture", event: this.toggleRecording, icon: "expand-arrows-alt" });
- ContextMenu.Instance.addItem({ description: "Options...", subitems: subitems, icon: "video" });
- }
+ const subitems = [{ description: "Screen Capture", event: this.toggleRecording, icon: "expand-arrows-alt" as any }];
+ ContextMenu.Instance.addItem({ description: "Options...", subitems, icon: "video" });
}
@computed get content() {
const interactive = CurrentUserUtils.SelectedTool !== InkTool.None || !this.props.isSelected() ? "" : "-interactive";
- const style = "videoBox-content" + interactive;
- return <video className={`${style}`} key="video" autoPlay={this._screenCapture} ref={this.setVideoRef}
+ return <video className={"videoBox-content" + interactive} key="video" ref={this._videoRef}
+ autoPlay={this._screenCapture}
style={{ width: this._screenCapture ? "100%" : undefined, height: this._screenCapture ? "100%" : undefined }}
onCanPlay={this.videoLoad}
controls={true}
@@ -101,40 +83,38 @@ export class ScreenshotBox extends ViewBoxAnnotatableComponent<FieldViewProps, S
toggleRecording = action(async () => {
this._screenCapture = !this._screenCapture;
if (this._screenCapture) {
- this._arecorder = new MediaRecorder(await navigator.mediaDevices.getUserMedia({ audio: true }));
- this._achunks = [];
- this._arecorder.ondataavailable = (e: any) => this._achunks.push(e.data);
- this._arecorder.onstop = async (e: any) => {
- const [{ result }] = await Networking.UploadFilesToServer(this._achunks);
+ this._audioRec = new MediaRecorder(await navigator.mediaDevices.getUserMedia({ audio: true }));
+ const aud_chunks: any = [];
+ this._audioRec.ondataavailable = (e: any) => aud_chunks.push(e.data);
+ this._audioRec.onstop = async (e: any) => {
+ const [{ result }] = await Networking.UploadFilesToServer(aud_chunks);
if (!(result instanceof Error)) {
this.dataDoc[this.props.fieldKey + "-audio"] = new AudioField(Utils.prepend(result.accessPaths.agnostic.client));
}
};
- const vstream = await (navigator.mediaDevices as any).getDisplayMedia({ video: true });
- this._videoRef!.srcObject = vstream;
- this._vrecorder = new MediaRecorder(vstream);
- this._vchunks = [];
- this._vrecorder.onstart = action(() => this.dataDoc[this.props.fieldKey + "-recordingStart"] = new DateField(new Date()));
- this._vrecorder.ondataavailable = (e: any) => this._vchunks.push(e.data);
- this._vrecorder.onstop = async (e: any) => {
- const file = new File(this._vchunks, `${this.rootDoc[Id]}.mkv`, { type: this._vchunks[0].type, lastModified: Date.now() });
+ this._videoRef.current!.srcObject = await (navigator.mediaDevices as any).getDisplayMedia({ video: true });
+ this._videoRec = new MediaRecorder(this._videoRef.current!.srcObject);
+ const vid_chunks: any = [];
+ this._videoRec.onstart = () => this.dataDoc[this.props.fieldKey + "-recordingStart"] = new DateField(new Date());
+ this._videoRec.ondataavailable = (e: any) => vid_chunks.push(e.data);
+ this._videoRec.onstop = async (e: any) => {
+ const file = new File(vid_chunks, `${this.rootDoc[Id]}.mkv`, { type: vid_chunks[0].type, lastModified: Date.now() });
const [{ result }] = await Networking.UploadFilesToServer(file);
this.dataDoc[this.fieldKey + "-duration"] = (new Date().getTime() - this.recordingStart!) / 1000;
- if (!(result instanceof Error)) {
+ if (!(result instanceof Error)) { // convert this screenshotBox into normal videoBox
this.dataDoc.type = DocumentType.VID;
this.layoutDoc.layout = VideoBox.LayoutString(this.fieldKey);
this.dataDoc[this.props.fieldKey] = new VideoField(Utils.prepend(result.accessPaths.agnostic.client));
} else alert("video conversion failed");
};
- this._dictation = this.setupDictation();
- setTimeout(() => this._dictationView = DocumentManager.Instance.getDocumentView(this._dictation!));
- this._arecorder.start();
- this._vrecorder.start();
+ this.setupDictation();
+ this._audioRec.start();
+ this._videoRec.start();
this.dataDoc.mediaState = "recording";
DocUtils.ActiveRecordings.push(this);
} else {
- this._arecorder.stop();
- this._vrecorder.stop();
+ this._audioRec.stop();
+ this._videoRec.stop();
this.dataDoc.mediaState = "paused";
const ind = DocUtils.ActiveRecordings.indexOf(this);
ind !== -1 && (DocUtils.ActiveRecordings.splice(ind, 1));
@@ -150,21 +130,10 @@ export class ScreenshotBox extends ViewBoxAnnotatableComponent<FieldViewProps, S
dictationTextProto.recordingStart = ComputedField.MakeFunction(`self.recordingSource["${this.props.fieldKey}-recordingStart"]`);
dictationTextProto.mediaState = ComputedField.MakeFunction("self.recordingSource.mediaState");
this.props.addDocument?.(dictationText) || this.props.addDocTab(dictationText, "add:bottom");
- return dictationText;
}
-
- private get uIButtons() {
- return (<div className="screenshotBox-uiButtons">
- <div className="screenshotBox-recorder" key="snap" onPointerDown={this.toggleRecording} >
- <FontAwesomeIcon icon="file" size="lg" />
- </div>
- </div>);
- }
-
contentFunc = () => [this.content];
render() {
- return (<div className="videoBox" onContextMenu={this.specificContextMenu}
- style={{ width: `${100}%`, height: `${100}%` }} >
+ return <div className="videoBox" onContextMenu={this.specificContextMenu} style={{ width: "100%", height: "100%" }} >
<div className="videoBox-viewer" >
<CollectionFreeFormView {...OmitKeys(this.props, ["NativeWidth", "NativeHeight"]).omit}
PanelHeight={this.props.PanelHeight}
@@ -186,7 +155,11 @@ export class ScreenshotBox extends ViewBoxAnnotatableComponent<FieldViewProps, S
{this.contentFunc}
</CollectionFreeFormView>
</div>
- {this.props.isSelected() ? this.uIButtons : (null)}
- </div >);
+ {!this.props.isSelected() ? (null) : <div className="screenshotBox-uiButtons">
+ <div className="screenshotBox-recorder" key="snap" onPointerDown={this.toggleRecording} >
+ <FontAwesomeIcon icon="file" size="lg" />
+ </div>
+ </div>}
+ </div >;
}
} \ No newline at end of file