aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/VideoBox.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/nodes/VideoBox.tsx')
-rw-r--r--src/client/views/nodes/VideoBox.tsx233
1 files changed, 113 insertions, 120 deletions
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index 1dfa55c64..9cf929679 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -3,17 +3,18 @@ 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 * as rp from 'request-promise';
-import { Doc, DocListCast, 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';
import { Cast, NumCast, StrCast } from '../../../fields/Types';
import { AudioField, ImageField, VideoField } from '../../../fields/URLField';
-import { emptyFunction, formatTime, OmitKeys, returnEmptyString, returnFalse, returnOne, setupMoveUpEvents, Utils } from '../../../Utils';
+import { emptyFunction, formatTime, returnEmptyString, returnFalse, returnOne, returnZero, setupMoveUpEvents, Utils } from '../../../Utils';
import { Docs, DocUtils } from '../../documents/Documents';
import { DocumentType } from '../../documents/DocumentTypes';
import { Networking } from '../../Network';
import { DocumentManager } from '../../util/DocumentManager';
+import { LinkManager } from '../../util/LinkManager';
import { ReplayMovements } from '../../util/ReplayMovements';
import { SelectionManager } from '../../util/SelectionManager';
import { SnappingManager } from '../../util/SnappingManager';
@@ -27,11 +28,13 @@ import { DocumentDecorations } from '../DocumentDecorations';
import { MarqueeAnnotator } from '../MarqueeAnnotator';
import { AnchorMenu } from '../pdf/AnchorMenu';
import { StyleProp } from '../StyleProvider';
+import { OpenWhere } from './DocumentView';
import { FieldView, FieldViewProps } from './FieldView';
import { RecordingBox } from './RecordingBox';
+import { PinProps, PresBox } from './trails';
import './VideoBox.scss';
-import { ObjectField } from '../../../fields/ObjectField';
-import { DocFocusOptions, OpenWhere } from './DocumentView';
+import { ScriptField } from '../../../fields/ScriptField';
+import { FollowLinkScript } from '../../util/LinkFollower';
const path = require('path');
/**
@@ -51,30 +54,6 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
public static LayoutString(fieldKey: string) {
return FieldView.LayoutString(VideoBox, fieldKey);
}
- /**
- * Uploads an image buffer to the server and stores with specified filename. by default the image
- * is stored at multiple resolutions each retrieved by using the filename appended with _o, _s, _m, _l (indicating original, small, medium, or large)
- * @param imageUri the bytes of the image
- * @param returnedFilename the base filename to store the image on the server
- * @param nosuffix optionally suppress creating multiple resolution images
- */
- public static async convertDataUri(imageUri: string, returnedFilename: string, nosuffix = false, replaceRootFilename?: string) {
- try {
- const posting = Utils.prepend('/uploadURI');
- const returnedUri = await rp.post(posting, {
- body: {
- uri: imageUri,
- name: returnedFilename,
- nosuffix,
- replaceRootFilename,
- },
- json: true,
- });
- return returnedUri;
- } catch (e) {
- console.log('VideoBox :' + e);
- }
- }
static _youtubeIframeCounter: number = 0;
static heightPercent = 80; // height of video relative to videoBox when timeline is open
@@ -109,12 +88,12 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
@observable _scrubbing: boolean = false;
@computed get links() {
- return DocListCast(this.dataDoc.links);
+ 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() {
@@ -242,10 +221,20 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
}
}
+ _keepCurrentlyPlaying = false; // flag to prevent document when paused from being removed from global 'currentlyPlaying' list
+ IsPlaying = () => this._playing;
+ TogglePause = () => {
+ if (!this._playing) this.Play();
+ else {
+ this._keepCurrentlyPlaying = true;
+ this.pause();
+ setTimeout(() => (this._keepCurrentlyPlaying = false));
+ }
+ };
+
// pauses video
- @action public Pause = (update: boolean = true) => {
+ @action public pause = (update: boolean = true) => {
this._playing = false;
- this.removeCurrentlyPlaying();
try {
update && this.player?.pause();
update && this._audioPlayer?.pause();
@@ -263,6 +252,10 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
}
this._playRegionTimer = undefined;
};
+ @action Pause = (update: boolean = true) => {
+ this.pause(update);
+ !this._keepCurrentlyPlaying && this.removeCurrentlyPlaying();
+ };
// toggles video full screen
@action public FullScreen = () => {
@@ -332,19 +325,19 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
y: NumCast(this.layoutDoc.y, 1),
_width: 150,
_height: 50,
- title: (this.layoutDoc._currentTimecode || 0).toString(),
- _isLinkButton: true,
+ title: (this.layoutDoc._layout_currentTimecode || 0).toString(),
+ onClick: FollowLinkScript(),
});
this.props.addDocument?.(b);
- DocUtils.MakeLink({ doc: b }, { doc: this.rootDoc }, '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) {
this.props.removeDocument?.(b);
- this.createRealSummaryLink(resolved);
+ this.createSnapshotLink(resolved);
}
});
} else {
@@ -352,51 +345,51 @@ 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);
- VideoBox.convertDataUri(dataUrl, filename).then((returnedFilename: string) => returnedFilename && (cb ?? this.createRealSummaryLink)(returnedFilename, downX, downY));
+ Utils.convertDataUri(dataUrl, filename).then((returnedFilename: string) => returnedFilename && (cb ?? this.createSnapshotLink)(returnedFilename, downX, downY));
}
};
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);
};
// creates link for snapshot
- createRealSummaryLink = (imagePath: string, downX?: number, downY?: number) => {
+ createSnapshotLink = (imagePath: string, downX?: number, downY?: number) => {
const url = !imagePath.startsWith('/') ? Utils.CorsProxy(imagePath) : imagePath;
const width = NumCast(this.layoutDoc._width) || 1;
const height = NumCast(this.layoutDoc._height);
- const imageSummary = Docs.Create.ImageDocument(url, {
+ const imageSnapshot = Docs.Create.ImageDocument(url, {
_nativeWidth: Doc.NativeWidth(this.layoutDoc),
_nativeHeight: Doc.NativeHeight(this.layoutDoc),
x: NumCast(this.layoutDoc.x) + width,
y: NumCast(this.layoutDoc.y),
- _isLinkButton: true,
+ 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(imageSummary), Doc.NativeWidth(this.layoutDoc));
- Doc.SetNativeHeight(Doc.GetProto(imageSummary), Doc.NativeHeight(this.layoutDoc));
- this.props.addDocument?.(imageSummary);
- const link = DocUtils.MakeLink({ doc: imageSummary }, { doc: this.getAnchor(true) }, 'video snapshot');
- link && (Doc.GetProto(link.anchor2 as Doc).timecodeToHide = NumCast((link.anchor2 as Doc).timecodeToShow) + 3);
- setTimeout(() => downX !== undefined && downY !== undefined && DocumentManager.Instance.getFirstDocumentView(imageSummary)?.startDragging(downX, downY, 'move', true));
+ 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), { 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) => {
- const timecode = Cast(this.layoutDoc._currentTimecode, 'number', null);
+ getAnchor = (addAsAnnotation: boolean, pinProps?: PinProps) => {
+ const timecode = Cast(this.layoutDoc._layout_currentTimecode, 'number', null);
const marquee = AnchorMenu.Instance.GetAnchor?.(undefined, addAsAnnotation);
- return (
- CollectionStackedTimeline.createAnchor(this.rootDoc, this.dataDoc, this.annotationKey, '_timecodeToShow' /* videoStart */, '_timecodeToHide' /* videoEnd */, timecode ? timecode : undefined, undefined, marquee, addAsAnnotation) ||
- this.rootDoc
- );
+ if (!addAsAnnotation && marquee) marquee.backgroundColor = 'transparent';
+ const anchor = CollectionStackedTimeline.createAnchor(this.rootDoc, this.dataDoc, this.annotationKey, timecode ? timecode : undefined, undefined, marquee, addAsAnnotation) || this.rootDoc;
+ PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), temporal: true } }, this.rootDoc);
+ return anchor;
};
// sets video info on load
@@ -409,25 +402,29 @@ 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);
}
};
+ // getView = async (doc: Doc) => {
+ // return new Promise<Opt<DocumentView>>(res => DocumentManager.Instance.AddViewRenderedCb(doc, dv => res(dv)));
+ // };
+
// 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');
@@ -440,12 +437,12 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
canvas.getContext('2d')?.drawImage(video, 0, 0, video.videoWidth, video.videoHeight, 0, 0, 100, 100);
const retitled = StrCast(this.rootDoc.title).replace(/[ -\.:]/g, '');
const encodedFilename = encodeURIComponent('thumbnail' + retitled + '_' + video.currentTime.toString().replace(/\./, '_'));
- thumbnailPromises?.push(VideoBox.convertDataUri(canvas.toDataURL(), basename(encodedFilename), true));
+ thumbnailPromises?.push(Utils.convertDataUri(canvas.toDataURL(), basename(encodedFilename), true));
const newTime = video.currentTime + video.duration / (VideoBox.numThumbnails - 1);
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)));
}
};
@@ -463,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();
}
};
@@ -534,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'] = '';
},
@@ -576,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()}
@@ -623,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,
@@ -680,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
@@ -699,23 +696,24 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
);
};
- // removes video from currently playing display
+ // removes from currently playing display
@action
removeCurrentlyPlaying = () => {
- if (CollectionStackedTimeline.CurrentlyPlaying) {
- const index = CollectionStackedTimeline.CurrentlyPlaying.indexOf(this.layoutDoc);
+ const docView = this.props.DocumentView?.();
+ if (CollectionStackedTimeline.CurrentlyPlaying && docView) {
+ const index = CollectionStackedTimeline.CurrentlyPlaying.indexOf(docView);
index !== -1 && CollectionStackedTimeline.CurrentlyPlaying.splice(index, 1);
}
};
-
- // adds video to currently playing display
+ // adds doc to currently playing display
@action
addCurrentlyPlaying = () => {
+ const docView = this.props.DocumentView?.();
if (!CollectionStackedTimeline.CurrentlyPlaying) {
CollectionStackedTimeline.CurrentlyPlaying = [];
}
- if (CollectionStackedTimeline.CurrentlyPlaying.indexOf(this.layoutDoc) === -1) {
- CollectionStackedTimeline.CurrentlyPlaying.push(this.layoutDoc);
+ if (docView && CollectionStackedTimeline.CurrentlyPlaying.indexOf(docView) === -1) {
+ CollectionStackedTimeline.CurrentlyPlaying.push(docView);
}
};
@@ -723,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}
@@ -742,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);
}
@@ -861,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,
@@ -872,7 +870,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
}),
returnFalse,
() => MarqueeAnnotator.clearAnnotations(this._savedAnnotations),
- false
+ false, false
);
}
};
@@ -892,18 +890,16 @@ 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;
playing = () => this._playing;
- contentFunc = () => [this.youtubeVideoId ? this.youtubeContent : this.content];
-
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();
@@ -953,14 +949,6 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
);
};
- scrollFocus = (doc: Doc, options: DocFocusOptions) => {
- if (doc !== this.rootDoc) {
- const showTime = Cast(doc._timecodeToShow, 'number', null);
- showTime !== undefined && setTimeout(() => this.Seek(showTime), 100);
- return 0.1;
- }
- };
-
// renders CollectionStackedTimeline
@computed get renderTimeline() {
return (
@@ -968,14 +956,15 @@ 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 */}
bringToFront={emptyFunction}
- CollectionView={undefined}
playFrom={this.playFrom}
setTime={this.setPlayheadTime}
playing={this.playing}
@@ -1016,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);
@@ -1024,28 +1013,28 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
cropping._height = anchh * (this.props.NativeDimScaling?.() || 1);
cropping.timecodeToHide = undefined;
cropping.timecodeToShow = undefined;
- cropping.isLinkButton = undefined;
+ 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_scale_min = viewScale;
+ croppingProto.freeform_ = anchx / viewScale;
+ croppingProto.freeform_panY = anchy / viewScale;
+ croppingProto.freeform_panX_min = anchx / viewScale;
+ croppingProto.freeform_panX_max = anchw / viewScale;
+ croppingProto.freeform_panY_min = anchy / viewScale;
+ croppingProto.freeform_panY_max = anchh / viewScale;
if (addCrop) {
- DocUtils.MakeLink({ doc: region }, { doc: cropping }, 'cropped image', '');
+ DocUtils.MakeLink(region, cropping, { link_relationship: 'cropped image' });
}
this.props.bringToFront(cropping);
return cropping;
@@ -1063,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();
@@ -1080,23 +1069,27 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
left: (this.props.PanelWidth() - this.panelWidth()) / 2,
}}>
<CollectionFreeFormView
- {...OmitKeys(this.props, ['NativeWidth', 'NativeHeight', 'setContentView']).omit}
+ {...this.props}
+ setContentView={emptyFunction}
+ NativeWidth={returnZero}
+ NativeHeight={returnZero}
renderDepth={this.props.renderDepth + 1}
fieldKey={this.annotationKey}
- CollectionView={undefined}
isAnnotationOverlay={true}
annotationLayerHostsContent={true}
PanelWidth={this.panelWidth}
PanelHeight={this.panelHeight}
+ isAnyChildContentActive={returnFalse}
ScreenToLocalTransform={this.screenToLocalTransform}
docFilters={this.timelineDocFilter}
select={emptyFunction}
+ focus={emptyFunction}
NativeDimScaling={returnOne}
whenChildContentsActiveChanged={this.whenChildContentsActiveChanged}
removeDocument={this.removeDocument}
moveDocument={this.moveDocument}
addDocument={this.addDocWithTimecode}>
- {this.contentFunc}
+ {this.youtubeVideoId ? this.youtubeContent : this.content}
</CollectionFreeFormView>
</div>
{this.annotationLayer}
@@ -1126,7 +1119,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}>