diff options
| author | Sophie Zhang <sophie_zhang@brown.edu> | 2023-09-18 17:40:01 -0400 |
|---|---|---|
| committer | Sophie Zhang <sophie_zhang@brown.edu> | 2023-09-18 17:40:01 -0400 |
| commit | 013f25f01e729feee5db94900c61f4be4dd46869 (patch) | |
| tree | 765dd5f2e06d6217ca79438e1098cefc8da627bf /src/client/views/nodes/RecordingBox/RecordingBox.tsx | |
| parent | f5e765adff1e7b32250eb503c9724a4ac99117f3 (diff) | |
| parent | 84aa8806a62e2e957e8281d7d492139e3d8225f2 (diff) | |
Merge branch 'master' into sophie-report-manager
Diffstat (limited to 'src/client/views/nodes/RecordingBox/RecordingBox.tsx')
| -rw-r--r-- | src/client/views/nodes/RecordingBox/RecordingBox.tsx | 228 |
1 files changed, 211 insertions, 17 deletions
diff --git a/src/client/views/nodes/RecordingBox/RecordingBox.tsx b/src/client/views/nodes/RecordingBox/RecordingBox.tsx index 04f11a5df..481e43feb 100644 --- a/src/client/views/nodes/RecordingBox/RecordingBox.tsx +++ b/src/client/views/nodes/RecordingBox/RecordingBox.tsx @@ -1,31 +1,38 @@ import { action, observable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; +import { DateField } from '../../../../fields/DateField'; +import { Doc, DocListCast } from '../../../../fields/Doc'; +import { Id } from '../../../../fields/FieldSymbols'; +import { List } from '../../../../fields/List'; +import { BoolCast, DocCast } from '../../../../fields/Types'; import { VideoField } from '../../../../fields/URLField'; import { Upload } from '../../../../server/SharedMediaTypes'; +import { Docs } from '../../../documents/Documents'; +import { DocumentType } from '../../../documents/DocumentTypes'; +import { DocumentManager } from '../../../util/DocumentManager'; +import { DragManager } from '../../../util/DragManager'; +import { ScriptingGlobals } from '../../../util/ScriptingGlobals'; +import { SelectionManager } from '../../../util/SelectionManager'; +import { Presentation } from '../../../util/TrackMovements'; +import { undoBatch } from '../../../util/UndoManager'; +import { CollectionFreeFormView } from '../../collections/collectionFreeForm/CollectionFreeFormView'; import { ViewBoxBaseComponent } from '../../DocComponent'; -import { FieldView } from '../FieldView'; +import { media_state } from '../AudioBox'; +import { FieldView, FieldViewProps } from '../FieldView'; import { VideoBox } from '../VideoBox'; import { RecordingView } from './RecordingView'; -import { DocumentType } from '../../../documents/DocumentTypes'; -import { Presentation } from '../../../util/TrackMovements'; -import { Doc } from '../../../../fields/Doc'; -import { Id } from '../../../../fields/FieldSymbols'; -import { DocCast } from '../../../../fields/Types'; @observer -export class RecordingBox extends ViewBoxBaseComponent() { +export class RecordingBox extends ViewBoxBaseComponent<FieldViewProps>() { public static LayoutString(fieldKey: string) { return FieldView.LayoutString(RecordingBox, fieldKey); } private _ref: React.RefObject<HTMLDivElement> = React.createRef(); - constructor(props: any) { - super(props); - } - componentDidMount() { + this.props.setContentView?.(this); Doc.SetNativeWidth(this.dataDoc, 1280); Doc.SetNativeHeight(this.dataDoc, 720); } @@ -34,9 +41,7 @@ export class RecordingBox extends ViewBoxBaseComponent() { @observable videoDuration: number | undefined = undefined; @action - setVideoDuration = (duration: number) => { - this.videoDuration = duration; - }; + setVideoDuration = (duration: number) => (this.videoDuration = duration); @action setResult = (info: Upload.AccessPathInfo, presentation?: Presentation) => { @@ -46,20 +51,209 @@ export class RecordingBox extends ViewBoxBaseComponent() { this.dataDoc.layout = VideoBox.LayoutString(this.fieldKey); this.dataDoc[this.props.fieldKey] = new VideoField(this.result.accessPaths.client); - this.dataDoc[this.fieldKey + '-recorded'] = true; + this.dataDoc[this.fieldKey + '_recorded'] = true; // stringify the presentation and store it if (presentation?.movements) { const presCopy = { ...presentation }; presCopy.movements = presentation.movements.map(movement => ({ ...movement, doc: movement.doc[Id] })) as any; - this.dataDoc[this.fieldKey + '-presentation'] = JSON.stringify(presCopy); + this.dataDoc[this.fieldKey + '_presentation'] = JSON.stringify(presCopy); } }; + @undoBatch + @action + public static WorkspaceStopRecording() { + const remDoc = RecordingBox.screengrabber?.rootDoc; + if (remDoc) { + //if recordingbox is true; when we press the stop button. changed vals temporarily to see if changes happening + RecordingBox.screengrabber?.Pause?.(); + setTimeout(() => { + RecordingBox.screengrabber?.Finish?.(); + remDoc.overlayX = 70; //was 100 + remDoc.overlayY = 590; + RecordingBox.screengrabber = undefined; + }, 100); + //could break if recording takes too long to turn into videobox. If so, either increase time on setTimeout below or find diff place to do this + setTimeout(() => Doc.RemFromMyOverlay(remDoc), 1000); + Doc.UserDoc().workspaceRecordingState = media_state.Paused; + Doc.AddDocToList(Doc.UserDoc(), 'workspaceRecordings', remDoc); + } + } + + /** + * This method toggles whether or not we are currently using the RecordingBox to record with the topbar button + * @param _readOnly_ + * @returns + */ + @undoBatch + @action + public static WorkspaceStartRecording(value: string) { + const screengrabber = + value === 'Record Workspace' + ? Docs.Create.ScreenshotDocument({ + title: `${new DateField()}-${Doc.ActiveDashboard?.title ?? ''}`, + _width: 205, + _height: 115, + }) + : Docs.Create.WebCamDocument(`${new DateField()}-${Doc.ActiveDashboard?.title ?? ''}`, { + title: `${new DateField()}-${Doc.ActiveDashboard?.title ?? ''}`, + _width: 205, + _height: 115, + }); + screengrabber.overlayX = 70; //was -400 + screengrabber.overlayY = 590; //was 0 + Doc.GetProto(screengrabber)[Doc.LayoutFieldKey(screengrabber) + '_trackScreen'] = true; + Doc.AddToMyOverlay(screengrabber); //just adds doc to overlay + DocumentManager.Instance.AddViewRenderedCb(screengrabber, docView => { + RecordingBox.screengrabber = docView.ComponentView as RecordingBox; + RecordingBox.screengrabber.Record?.(); + }); + Doc.UserDoc().workspaceRecordingState = media_state.Recording; + } + + /** + * This method changes the menu depending on whether or not we are in playback mode + * @param value RecordingBox rootdoc + */ + @undoBatch + @action + public static replayWorkspace(value: Doc) { + Doc.UserDoc().currentRecording = value; + value.overlayX = 70; + value.overlayY = window.innerHeight - 180; + Doc.AddToMyOverlay(value); + DocumentManager.Instance.AddViewRenderedCb(value, docView => { + Doc.UserDoc().currentRecording = docView.rootDoc; + SelectionManager.SelectSchemaViewDoc(value); + RecordingBox.resumeWorkspaceReplaying(value); + }); + } + + /** + * Adds the recording box to the canvas + * @param value current recordingbox + */ + @undoBatch + @action + public static addRecToWorkspace(value: RecordingBox) { + let ffView = Array.from(DocumentManager.Instance.DocumentViews).find(view => view.ComponentView instanceof CollectionFreeFormView); + (ffView?.ComponentView as CollectionFreeFormView).props.addDocument?.(value.rootDoc); + Doc.RemoveDocFromList(Doc.UserDoc(), 'workspaceRecordings', value.rootDoc); + Doc.RemFromMyOverlay(value.rootDoc); + Doc.UserDoc().currentRecording = undefined; + Doc.UserDoc().workspaceReplayingState = undefined; + Doc.UserDoc().workspaceRecordingState = undefined; + } + + @action + public static resumeWorkspaceReplaying(doc: Doc) { + const docView = DocumentManager.Instance.getDocumentView(doc); + if (docView?.ComponentView instanceof VideoBox) { + docView.ComponentView.Play(); + } + Doc.UserDoc().workspaceReplayingState = media_state.Playing; + } + + @action + public static pauseWorkspaceReplaying(doc: Doc) { + const docView = DocumentManager.Instance.getDocumentView(doc); + const videoBox = docView?.ComponentView as VideoBox; + if (videoBox) { + videoBox.Pause(); + } + Doc.UserDoc().workspaceReplayingState = media_state.Paused; + } + + @action + public static stopWorkspaceReplaying(value: Doc) { + Doc.RemFromMyOverlay(value); + Doc.UserDoc().currentRecording = undefined; + Doc.UserDoc().workspaceReplayingState = undefined; + Doc.UserDoc().workspaceRecordingState = undefined; + Doc.RemFromMyOverlay(value); + } + + @undoBatch + @action + public static removeWorkspaceReplaying(value: Doc) { + Doc.RemoveDocFromList(Doc.UserDoc(), 'workspaceRecordings', value); + Doc.RemFromMyOverlay(value); + Doc.UserDoc().currentRecording = undefined; + Doc.UserDoc().workspaceReplayingState = undefined; + Doc.UserDoc().workspaceRecordingState = undefined; + } + + Record: undefined | (() => void); + Pause: undefined | (() => void); + Finish: undefined | (() => void); + getControls = (record: () => void, pause: () => void, finish: () => void) => { + this.Record = record; + this.Pause = pause; + this.Finish = finish; + }; render() { return ( <div className="recordingBox" ref={this._ref}> - {!this.result && <RecordingView setResult={this.setResult} setDuration={this.setVideoDuration} id={DocCast(this.rootDoc.proto)?.[Id] || ''} />} + {!this.result && ( + <RecordingView + forceTrackScreen={BoolCast(this.layoutDoc[this.fieldKey + '_trackScreen'])} + getControls={this.getControls} + setResult={this.setResult} + setDuration={this.setVideoDuration} + id={DocCast(this.rootDoc.proto)?.[Id] || ''} + /> + )} </div> ); } + static screengrabber: RecordingBox | undefined; } + +ScriptingGlobals.add(function stopWorkspaceRecording() { + RecordingBox.WorkspaceStopRecording(); +}); + +ScriptingGlobals.add(function stopWorkspaceReplaying(value: Doc) { + RecordingBox.stopWorkspaceReplaying(value); +}); +ScriptingGlobals.add(function removeWorkspaceReplaying(value: Doc) { + RecordingBox.removeWorkspaceReplaying(value); +}); + +ScriptingGlobals.add(function getCurrentRecording() { + return Doc.UserDoc().currentRecording; +}); +ScriptingGlobals.add(function getWorkspaceRecordings() { + return new List<any>(['Record Workspace', `Record Webcam`, ...DocListCast(Doc.UserDoc().workspaceRecordings)]); +}); +ScriptingGlobals.add(function isWorkspaceRecording() { + return Doc.UserDoc().workspaceRecordingState === media_state.Recording; +}); +ScriptingGlobals.add(function isWorkspaceReplaying() { + return Doc.UserDoc().workspaceReplayingState; +}); +ScriptingGlobals.add(function replayWorkspace(value: Doc | string, _readOnly_: boolean) { + if (_readOnly_) return DocCast(Doc.UserDoc().currentRecording) ?? 'Record Workspace'; + if (typeof value === 'string') RecordingBox.WorkspaceStartRecording(value); + else RecordingBox.replayWorkspace(value); +}); +ScriptingGlobals.add(function pauseWorkspaceReplaying(value: Doc, _readOnly_: boolean) { + RecordingBox.pauseWorkspaceReplaying(value); +}); +ScriptingGlobals.add(function resumeWorkspaceReplaying(value: Doc, _readOnly_: boolean) { + RecordingBox.resumeWorkspaceReplaying(value); +}); + +ScriptingGlobals.add(function startRecordingDrag(value: { doc: Doc | string; e: React.PointerEvent }) { + if (DocCast(value.doc)) { + DragManager.StartDocumentDrag([value.e.target as HTMLElement], new DragManager.DocumentDragData([DocCast(value.doc)], 'embed'), value.e.clientX, value.e.clientY); + value.e.preventDefault(); + return true; + } +}); +ScriptingGlobals.add(function renderDropdown() { + if (!Doc.UserDoc().workspaceRecordings || DocListCast(Doc.UserDoc().workspaceRecordings).length === 0) { + return true; + } + return false; +}); |
