diff options
Diffstat (limited to 'src/client/views/nodes/VideoBox.tsx')
-rw-r--r-- | src/client/views/nodes/VideoBox.tsx | 102 |
1 files changed, 52 insertions, 50 deletions
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx index 7a7d4fe37..e00cb8618 100644 --- a/src/client/views/nodes/VideoBox.tsx +++ b/src/client/views/nodes/VideoBox.tsx @@ -3,7 +3,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { action, computed, IReactionDisposer, observable, ObservableMap, reaction, runInAction, untracked } from 'mobx'; import { observer } from 'mobx-react'; import { basename } from 'path'; -import { Doc, HeightSym, WidthSym } from '../../../fields/Doc'; +import { Doc, HeightSym, StrListCast, WidthSym } from '../../../fields/Doc'; import { InkTool } from '../../../fields/InkField'; import { List } from '../../../fields/List'; import { ObjectField } from '../../../fields/ObjectField'; @@ -91,9 +91,9 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp return LinkManager.Links(this.dataDoc); } @computed get heightPercent() { - return NumCast(this.layoutDoc._timelineHeightPercent, 100); + return NumCast(this.layoutDoc._layout_timelineHeightPercent, 100); } // current percent of video relative to VideoBox height - // @computed get rawDuration() { return NumCast(this.dataDoc[this.fieldKey + "-duration"]); } + // @computed get rawDuration() { return NumCast(this.dataDoc[this.fieldKey + "_duration"]); } @observable rawDuration: number = 0; @computed get youtubeVideoId() { @@ -325,14 +325,14 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp y: NumCast(this.layoutDoc.y, 1), _width: 150, _height: 50, - title: (this.layoutDoc._currentTimecode || 0).toString(), + title: (this.layoutDoc._layout_currentTimecode || 0).toString(), onClick: FollowLinkScript(), }); this.props.addDocument?.(b); - DocUtils.MakeLink(b, this.rootDoc, { linkRelationship: 'video snapshot' }); + DocUtils.MakeLink(b, this.rootDoc, { link_relationship: 'video snapshot' }); Networking.PostToServer('/youtubeScreenshot', { id: this.youtubeVideoId, - timecode: this.layoutDoc._currentTimecode, + timecode: this.layoutDoc._layout_currentTimecode, }).then(response => { const resolved = response?.accessPaths?.agnostic?.client; if (resolved) { @@ -345,7 +345,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp const dataUrl = canvas.toDataURL('image/png'); // can also use 'image/png' // if you want to preview the captured image, const retitled = StrCast(this.rootDoc.title).replace(/[ -\.:]/g, ''); - const encodedFilename = encodeURIComponent('snapshot' + retitled + '_' + (this.layoutDoc._currentTimecode || 0).toString().replace(/\./, '_')); + const encodedFilename = encodeURIComponent('snapshot' + retitled + '_' + (this.layoutDoc._layout_currentTimecode || 0).toString().replace(/\./, '_')); const filename = basename(encodedFilename); Utils.convertDataUri(dataUrl, filename).then((returnedFilename: string) => returnedFilename && (cb ?? this.createSnapshotLink)(returnedFilename, downX, downY)); } @@ -354,8 +354,8 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp updateIcon = () => { const makeIcon = (returnedfilename: string) => { this.dataDoc.icon = new ImageField(returnedfilename); - this.dataDoc['icon-nativeWidth'] = this.layoutDoc[WidthSym](); - this.dataDoc['icon-nativeHeight'] = this.layoutDoc[HeightSym](); + this.dataDoc.icon_nativeWidth = this.layoutDoc[WidthSym](); + this.dataDoc.icon_nativeHeight = this.layoutDoc[HeightSym](); }; this.Snapshot(undefined, undefined, makeIcon); }; @@ -373,18 +373,18 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp onClick: FollowLinkScript(), _width: 150, _height: (height / width) * 150, - title: '--snapshot' + NumCast(this.layoutDoc._currentTimecode) + ' image-', + title: '--snapshot' + NumCast(this.layoutDoc._layout_currentTimecode) + ' image-', }); Doc.SetNativeWidth(Doc.GetProto(imageSnapshot), Doc.NativeWidth(this.layoutDoc)); Doc.SetNativeHeight(Doc.GetProto(imageSnapshot), Doc.NativeHeight(this.layoutDoc)); this.props.addDocument?.(imageSnapshot); - const link = DocUtils.MakeLink(imageSnapshot, this.getAnchor(true), { linkRelationship: 'video snapshot' }); - link && (Doc.GetProto(link.anchor2 as Doc).timecodeToHide = NumCast((link.anchor2 as Doc).timecodeToShow) + 3); + const link = DocUtils.MakeLink(imageSnapshot, this.getAnchor(true), { link_relationship: 'video snapshot' }); + link && (Doc.GetProto(link.link_anchor_2 as Doc).timecodeToHide = NumCast((link.link_anchor_2 as Doc).timecodeToShow) + 3); setTimeout(() => downX !== undefined && downY !== undefined && DocumentManager.Instance.getFirstDocumentView(imageSnapshot)?.startDragging(downX, downY, 'move', true)); }; getAnchor = (addAsAnnotation: boolean, pinProps?: PinProps) => { - const timecode = Cast(this.layoutDoc._currentTimecode, 'number', null); + const timecode = Cast(this.layoutDoc._layout_currentTimecode, 'number', null); const marquee = AnchorMenu.Instance.GetAnchor?.(undefined, addAsAnnotation); if (!addAsAnnotation && marquee) marquee.backgroundColor = 'transparent'; const anchor = CollectionStackedTimeline.createAnchor(this.rootDoc, this.dataDoc, this.annotationKey, timecode ? timecode : undefined, undefined, marquee, addAsAnnotation) || this.rootDoc; @@ -402,16 +402,16 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp } if (Number.isFinite(this.player!.duration)) { this.rawDuration = this.player!.duration; - this.dataDoc[this.fieldKey + '-duration'] = this.rawDuration; - } else this.rawDuration = NumCast(this.dataDoc[this.fieldKey + '-duration']); + this.dataDoc[this.fieldKey + '_duration'] = this.rawDuration; + } else this.rawDuration = NumCast(this.dataDoc[this.fieldKey + '_duration']); }); // updates video time @action updateTimecode = () => { - this.player && (this.layoutDoc._currentTimecode = this.player.currentTime); + this.player && (this.layoutDoc._layout_currentTimecode = this.player.currentTime); try { - this._youtubePlayer && (this.layoutDoc._currentTimecode = this._youtubePlayer.getCurrentTime?.()); + this._youtubePlayer && (this.layoutDoc._layout_currentTimecode = this._youtubePlayer.getCurrentTime?.()); } catch (e) { console.log('Video Timecode Exception:', e); } @@ -423,8 +423,8 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp // extracts video thumbnails and saves them as field of doc getVideoThumbnails = () => { - if (this.dataDoc.thumbnails !== undefined) return; - this.dataDoc.thumbnails = new List<string>(); + if (this.dataDoc[this.fieldKey + '_thumbnails'] !== undefined) return; + this.dataDoc[this.fieldKey + '_thumbnails'] = new List<string>(); const thumbnailPromises: Promise<any>[] = []; const video = document.createElement('video'); @@ -442,7 +442,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp if (newTime < video.duration) { video.currentTime = newTime; } else { - Promise.all(thumbnailPromises).then(thumbnails => (this.dataDoc.thumbnails = new List<string>(thumbnails))); + Promise.all(thumbnailPromises).then(thumbnails => (this.dataDoc[this.fieldKey + '_thumbnails'] = new List<string>(thumbnails))); } }; @@ -460,12 +460,12 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp // vref.onfullscreenchange = action((e) => this._fullScreen = vref.webkitDisplayingFullscreen); this._disposers.reactionDisposer?.(); this._disposers.reactionDisposer = reaction( - () => NumCast(this.layoutDoc._currentTimecode), + () => NumCast(this.layoutDoc._layout_currentTimecode), time => !this._playing && (vref.currentTime = time), { fireImmediately: true } ); - (!this.dataDoc.thumbnails || this.dataDoc.thumbnails.length != VideoBox.numThumbnails) && this.getVideoThumbnails(); + (!this.dataDoc[this.fieldKey + '_thumbnails'] || this.dataDoc[this.fieldKey + '_thumbnails'].length != VideoBox.numThumbnails) && this.getVideoThumbnails(); } }; @@ -531,7 +531,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp this.dataDoc.layout = RecordingBox.LayoutString(this.fieldKey); // delete assoicated video data this.dataDoc[this.props.fieldKey] = ''; - this.dataDoc[this.fieldKey + '-duration'] = ''; + this.dataDoc[this.fieldKey + '_duration'] = ''; // delete assoicated presentation data this.dataDoc[this.fieldKey + '-presentation'] = ''; }, @@ -573,7 +573,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp key="video" autoPlay={this._screenCapture} ref={this.setVideoRef} - style={this._fullScreen ? this.fullScreenSize() : this.isCropped ? { width: 'max-content', height: 'max-content', transform: `scale(${1 / NumCast(this.rootDoc._viewScale)})`, transformOrigin: 'top left' } : {}} + style={this._fullScreen ? this.fullScreenSize() : this.isCropped ? { width: 'max-content', height: 'max-content', transform: `scale(${1 / NumCast(this.rootDoc._freeform_scale)})`, transformOrigin: 'top left' } : {}} onCanPlay={this.videoLoad} controls={VideoBox._nativeControls} onPlay={() => this.Play()} @@ -620,8 +620,8 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp this._disposers.reactionDisposer?.(); this._disposers.youtubeReactionDisposer?.(); this._disposers.reactionDisposer = reaction( - () => this.layoutDoc._currentTimecode, - () => !this._playing && this.Seek(NumCast(this.layoutDoc._currentTimecode)) + () => this.layoutDoc._layout_currentTimecode, + () => !this._playing && this.Seek(NumCast(this.layoutDoc._layout_currentTimecode)) ); this._disposers.youtubeReactionDisposer = reaction( () => Doc.ActiveTool === InkTool.None && this.props.isSelected(true) && !SnappingManager.GetIsDragging() && !DocumentDecorations.Instance.Interacting, @@ -677,15 +677,15 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp this._clicking = false; if (this.props.isContentActive()) { // const local = this.props.ScreenToLocalTransform().scale(this.props.scaling?.() || 1).transformPoint(e.clientX, e.clientY); - // this.layoutDoc._timelineHeightPercent = Math.max(0, Math.min(100, local[1] / this.props.PanelHeight() * 100)); + // this.layoutDoc._layout_timelineHeightPercent = Math.max(0, Math.min(100, local[1] / this.props.PanelHeight() * 100)); - this.layoutDoc._timelineHeightPercent = 80; + this.layoutDoc._layout_timelineHeightPercent = 80; } return false; }), emptyFunction, () => { - this.layoutDoc._timelineHeightPercent = this.heightPercent !== 100 ? 100 : VideoBox.heightPercent; + this.layoutDoc._layout_timelineHeightPercent = this.heightPercent !== 100 ? 100 : VideoBox.heightPercent; setTimeout( action(() => (this._clicking = false)), 500 @@ -721,7 +721,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp this._youtubeIframeId = VideoBox._youtubeIframeCounter++; this._youtubeContentCreated = this._forceCreateYouTubeIFrame ? true : true; const classname = 'videoBox-content-YouTube' + (this._fullScreen ? '-fullScreen' : ''); - const start = untracked(() => Math.round(NumCast(this.layoutDoc._currentTimecode))); + const start = untracked(() => Math.round(NumCast(this.layoutDoc._layout_currentTimecode))); return ( <iframe key={this._youtubeIframeId} @@ -740,7 +740,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp @action.bound addDocWithTimecode(doc: Doc | Doc[]): boolean { const docs = doc instanceof Doc ? [doc] : doc; - const curTime = NumCast(this.layoutDoc._currentTimecode); + const curTime = NumCast(this.layoutDoc._layout_currentTimecode); docs.forEach(doc => (doc._timecodeToHide = (doc._timecodeToShow = curTime) + 1)); return this.addDocument(doc); } @@ -859,7 +859,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp // starts marquee selection marqueeDown = (e: React.PointerEvent) => { - if (!e.altKey && e.button === 0 && NumCast(this.layoutDoc._viewScale, 1) === 1 && this.props.isContentActive(true) && ![InkTool.Highlighter, InkTool.Pen].includes(Doc.ActiveTool)) { + if (!e.altKey && e.button === 0 && NumCast(this.layoutDoc._freeform_scale, 1) === 1 && this.props.isContentActive(true) && ![InkTool.Highlighter, InkTool.Pen].includes(Doc.ActiveTool)) { setupMoveUpEvents( this, e, @@ -890,7 +890,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp .scale(this.scaling()) .translate(0, (-this.heightPercent / 100) * this.props.PanelHeight()); - setPlayheadTime = (time: number) => (this.player!.currentTime = this.layoutDoc._currentTimecode = time); + setPlayheadTime = (time: number) => (this.player!.currentTime = this.layoutDoc._layout_currentTimecode = time); timelineHeight = () => (this.props.PanelHeight() * (100 - this.heightPercent)) / 100; @@ -899,7 +899,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp scaling = () => this.props.NativeDimScaling?.() || 1; panelWidth = () => (this.props.PanelWidth() * this.heightPercent) / 100; - panelHeight = () => (this.layoutDoc._fitWidth ? this.panelWidth() / (Doc.NativeAspect(this.rootDoc) || 1) : (this.props.PanelHeight() * this.heightPercent) / 100); + panelHeight = () => (this.layoutDoc._layout_fitWidth ? this.panelWidth() / (Doc.NativeAspect(this.rootDoc) || 1) : (this.props.PanelHeight() * this.heightPercent) / 100); screenToLocalTransform = () => { const offset = (this.props.PanelWidth() - this.panelWidth()) / 2 / this.scaling(); @@ -956,9 +956,11 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp <CollectionStackedTimeline ref={action((r: any) => (this._stackedTimeline = r))} {...this.props} + dataFieldKey={this.fieldKey} fieldKey={this.annotationKey} dictationKey={this.fieldKey + '-dictation'} mediaPath={this.audiopath} + thumbnails={() => StrListCast(this.dataDoc[this.fieldKey + '_thumbnails'])} renderDepth={this.props.renderDepth + 1} startTag={'_timecodeToShow' /* videoStart */} endTag={'_timecodeToHide' /* videoEnd */} @@ -1003,7 +1005,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp const anchy = NumCast(cropping.y); const anchw = NumCast(cropping._width); const anchh = NumCast(cropping._height); - const viewScale = NumCast(this.rootDoc[this.fieldKey + '-nativeWidth']) / anchw; + const viewScale = NumCast(this.rootDoc[this.fieldKey + '_nativeWidth']) / anchw; cropping.title = 'crop: ' + this.rootDoc.title; cropping.x = NumCast(this.rootDoc.x) + NumCast(this.rootDoc._width); cropping.y = NumCast(this.rootDoc.y); @@ -1014,25 +1016,25 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp cropping.onClick = undefined; const croppingProto = Doc.GetProto(cropping); croppingProto.annotationOn = undefined; - croppingProto.isPrototype = true; + croppingProto.isDataDoc = true; croppingProto.proto = Cast(this.rootDoc.proto, Doc, null)?.proto; // set proto of cropping's data doc to be IMAGE_PROTO croppingProto.type = DocumentType.VID; croppingProto.layout = VideoBox.LayoutString('data'); croppingProto.data = ObjectField.MakeCopy(this.rootDoc[this.fieldKey] as ObjectField); - croppingProto['data-nativeWidth'] = anchw; - croppingProto['data-nativeHeight'] = anchh; + croppingProto['data_nativeWidth'] = anchw; + croppingProto['data_nativeHeight'] = anchh; croppingProto.videoCrop = true; - croppingProto.currentTimecode = this.layoutDoc._currentTimecode; - croppingProto.viewScale = viewScale; - croppingProto.viewScaleMin = viewScale; - croppingProto.panX = anchx / viewScale; - croppingProto.panY = anchy / viewScale; - croppingProto.panXMin = anchx / viewScale; - croppingProto.panXMax = anchw / viewScale; - croppingProto.panYMin = anchy / viewScale; - croppingProto.panYMax = anchh / viewScale; + croppingProto.layout_currentTimecode = this.layoutDoc._layout_currentTimecode; + croppingProto.freeform_scale = viewScale; + croppingProto.freeform_scaleMin = viewScale; + croppingProto.freeform_ = anchx / viewScale; + croppingProto.freeform_panY = anchy / viewScale; + croppingProto.freeform_panXMin = anchx / viewScale; + croppingProto.freeform_panXMax = anchw / viewScale; + croppingProto.freeform_panYMin = anchy / viewScale; + croppingProto.freeform_panYMax = anchh / viewScale; if (addCrop) { - DocUtils.MakeLink(region, cropping, { linkRelationship: 'cropped image' }); + DocUtils.MakeLink(region, cropping, { link_relationship: 'cropped image' }); } this.props.bringToFront(cropping); return cropping; @@ -1050,7 +1052,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp style={{ pointerEvents: this.layoutDoc._lockedPosition ? 'none' : undefined, borderRadius, - overflow: this.props.docViewPath?.().slice(-1)[0].fitWidth ? 'auto' : undefined, + overflow: this.props.docViewPath?.().slice(-1)[0].layout_fitWidth ? 'auto' : undefined, }} onWheel={e => { e.stopPropagation(); @@ -1116,7 +1118,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp @computed get UIButtons() { const bounds = this.props.docViewPath().lastElement().getBounds(); const width = (bounds?.right || 0) - (bounds?.left || 0); - const curTime = NumCast(this.layoutDoc._currentTimecode) - (this.timeline?.clipStart || 0); + const curTime = NumCast(this.layoutDoc._layout_currentTimecode) - (this.timeline?.clipStart || 0); return ( <> <div className="videobox-button" title={this._playing ? 'play' : 'pause'} onPointerDown={this.onPlayDown}> |