import { action, makeObservable, 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 { DocumentType } from '../../../documents/DocumentTypes'; import { Docs } from '../../../documents/Documents'; import { DocumentManager } from '../../../util/DocumentManager'; import { DragManager, dropActionType } from '../../../util/DragManager'; import { ScriptingGlobals } from '../../../util/ScriptingGlobals'; import { Presentation } from '../../../util/TrackMovements'; import { undoBatch } from '../../../util/UndoManager'; import { ViewBoxBaseComponent } from '../../DocComponent'; import { CollectionFreeFormView } from '../../collections/collectionFreeForm/CollectionFreeFormView'; import { media_state } from '../AudioBox'; import { FieldView, FieldViewProps } from '../FieldView'; import { VideoBox } from '../VideoBox'; import { RecordingView } from './RecordingView'; import { DocData } from '../../../../fields/DocSymbols'; @observer export class RecordingBox extends ViewBoxBaseComponent() { public static LayoutString(fieldKey: string) { return FieldView.LayoutString(RecordingBox, fieldKey); } private _ref: React.RefObject = React.createRef(); constructor(props: FieldViewProps) { super(props); makeObservable(this); } componentDidMount() { this._props.setContentViewBox?.(this); Doc.SetNativeWidth(this.dataDoc, 1280); Doc.SetNativeHeight(this.dataDoc, 720); } @observable result: Upload.AccessPathInfo | undefined = undefined; @observable videoDuration: number | undefined = undefined; @action setVideoDuration = (duration: number) => (this.videoDuration = duration); @action setResult = (info: Upload.AccessPathInfo, presentation?: Presentation) => { this.result = info; this.dataDoc.type = DocumentType.VID; this.dataDoc[this.fieldKey + '_duration'] = this.videoDuration; this.dataDoc.layout = VideoBox.LayoutString(this.fieldKey); this.dataDoc[this._props.fieldKey] = new VideoField(this.result.accessPaths.client); 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); } }; @undoBatch public static WorkspaceStopRecording() { const remDoc = RecordingBox.screengrabber?.Document; 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 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 screengrabber[DocData][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 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.Document; docView.select(false); RecordingBox.resumeWorkspaceReplaying(value); }); } /** * Adds the recording box to the canvas * @param value current recordingbox */ @undoBatch 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.Document); Doc.RemoveDocFromList(Doc.UserDoc(), 'workspaceRecordings', value.Document); Doc.RemFromMyOverlay(value.Document); Doc.UserDoc().currentRecording = undefined; Doc.UserDoc().workspaceReplayingState = undefined; Doc.UserDoc().workspaceRecordingState = undefined; } 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; } 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; } public static stopWorkspaceReplaying(value: Doc) { Doc.RemFromMyOverlay(value); Doc.UserDoc().currentRecording = undefined; Doc.UserDoc().workspaceReplayingState = undefined; Doc.UserDoc().workspaceRecordingState = undefined; Doc.RemFromMyOverlay(value); } @undoBatch 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 (
{!this.result && ( )}
); } 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(['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)], dropActionType.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; });