diff options
| author | bobzel <zzzman@gmail.com> | 2021-09-24 22:31:22 -0400 |
|---|---|---|
| committer | bobzel <zzzman@gmail.com> | 2021-09-24 22:31:22 -0400 |
| commit | 6bcf4ae5f3953ba10ba1fba6c7d2246514a90eed (patch) | |
| tree | 859bb94c62c70a5c731376afe4aae5573036c8f7 /src/client/views/collections | |
| parent | cbf22b4ccaab14a7c8cb62137ea09b58a001e13a (diff) | |
refactored trim stuff out of audiobox into collectionstackedtimeline so that videobox can reuse trimming
Diffstat (limited to 'src/client/views/collections')
| -rw-r--r-- | src/client/views/collections/CollectionStackedTimeline.tsx | 193 |
1 files changed, 86 insertions, 107 deletions
diff --git a/src/client/views/collections/CollectionStackedTimeline.tsx b/src/client/views/collections/CollectionStackedTimeline.tsx index 43f78cf78..48014921a 100644 --- a/src/client/views/collections/CollectionStackedTimeline.tsx +++ b/src/client/views/collections/CollectionStackedTimeline.tsx @@ -61,24 +61,21 @@ export type CollectionStackedTimelineProps = { mediaPath: string; dictationKey: string; rawDuration: number; - trimming: boolean; - clipStart: number; - clipEnd: number; - clipDuration: number; - trimStart: () => number; - trimEnd: () => number; - trimDuration: () => number; - setStartTrim: (newStart: number) => void; - setEndTrim: (newEnd: number) => void; + fieldKey: string; }; +export enum TrimScope { + All = 2, + Clip = 1, + None = 0, +} + @observer export class CollectionStackedTimeline extends CollectionSubView< PanZoomDocument, CollectionStackedTimelineProps >(PanZoomDocument) { - @observable static SelectingRegion: CollectionStackedTimeline | undefined = - undefined; + @observable static SelectingRegion: CollectionStackedTimeline | undefined; static RangeScript: ScriptField; static LabelScript: ScriptField; static RangePlayScript: ScriptField; @@ -87,37 +84,43 @@ export class CollectionStackedTimeline extends CollectionSubView< private _timeline: HTMLDivElement | null = null; private _markerStart: number = 0; @observable _markerEnd: number = 0; + @observable _trimming: number = TrimScope.None; + @observable _trimStart: number = 0; + @observable _trimEnd: number = 0; - get minLength() { - const rect = this._timeline?.getBoundingClientRect(); - if (rect) { - return 0.05 * this.clipDuration; - } - return 0; - } + get minTrimLength() { return this._timeline?.getBoundingClientRect() ? 0.05 * this.clipDuration : 0; } + @computed get trimStart() { return this.IsTrimming !== TrimScope.None ? this._trimStart : this.clipStart; } + @computed get trimDuration() { return this.trimEnd - this.trimStart; } + @computed get trimEnd() { return this.IsTrimming !== TrimScope.None ? this._trimEnd : this.clipEnd; } - get trimStart() { - return this.props.trimStart(); - } + @computed get clipStart() { return this.IsTrimming === TrimScope.All ? 0 : NumCast(this.layoutDoc.clipStart); } + @computed get clipDuration() { return this.clipEnd - this.clipStart; } + @computed get clipEnd() { return this.IsTrimming === TrimScope.All ? this.props.rawDuration : NumCast(this.layoutDoc.clipEnd, this.props.rawDuration); } - get trimEnd() { - return this.props.trimEnd(); - } + @computed get currentTime() { return NumCast(this.layoutDoc._currentTimecode); } - get clipDuration() { - return this.props.clipDuration; - } + public get IsTrimming() { return this._trimming; } - @computed get currentTime() { - return NumCast(this.layoutDoc._currentTimecode); + @action + public StartTrimming(scope: TrimScope) { + this._trimStart = this.clipStart; + this._trimEnd = this.clipEnd; + this._trimming = scope; + } + @action + public StopTrimming() { + this.layoutDoc.clipStart = this.trimStart; + this.layoutDoc.clipEnd = this.trimEnd; + this._trimming = TrimScope.None; } + @computed get selectionContainer() { return CollectionStackedTimeline.SelectingRegion !== this ? null : ( <div className="collectionStackedTimeline-selector" style={{ - left: `${((Math.min(this._markerStart, this._markerEnd) - this.trimStart) / this.props.trimDuration()) * 100}%`, - width: `${(Math.abs(this._markerStart - this._markerEnd) / this.props.trimDuration()) * 100}%`, + left: `${((Math.min(this._markerStart, this._markerEnd) - this.trimStart) / this.trimDuration) * 100}%`, + width: `${(Math.abs(this._markerStart - this._markerEnd) / this.trimDuration) * 100}%`, }} /> ); @@ -145,28 +148,21 @@ export class CollectionStackedTimeline extends CollectionSubView< componentDidMount() { document.addEventListener("keydown", this.keyEvents, true); } + + @action componentWillUnmount() { document.removeEventListener("keydown", this.keyEvents, true); if (CollectionStackedTimeline.SelectingRegion === this) { - runInAction( - () => (CollectionStackedTimeline.SelectingRegion = undefined) - ); + CollectionStackedTimeline.SelectingRegion = undefined; } } - anchorStart = (anchor: Doc) => - NumCast(anchor._timecodeToShow, NumCast(anchor[this.props.startTag])) - anchorEnd = (anchor: Doc, val: any = null) => { - const endVal = NumCast(anchor[this.props.endTag], val); - return NumCast( - anchor._timecodeToHide, - endVal === undefined ? null : endVal - ); - } + anchorStart = (anchor: Doc) => NumCast(anchor._timecodeToShow, NumCast(anchor[this.props.startTag])) + anchorEnd = (anchor: Doc, val: any = null) => NumCast(anchor._timecodeToHide, NumCast(anchor[this.props.endTag], val)); toTimeline = (screen_delta: number, width: number) => { return Math.max( - this.props.clipStart, - Math.min(this.props.clipEnd, (screen_delta / width) * this.props.clipDuration + this.props.clipStart)); + this.clipStart, + Math.min(this.clipEnd, (screen_delta / width) * this.clipDuration + this.clipStart)); } rangeClickScript = () => CollectionStackedTimeline.RangeScript; @@ -233,10 +229,7 @@ export class CollectionStackedTimeline extends CollectionSubView< !wasSelecting && CollectionStackedTimeline.SelectingRegion !== this ) { - this._markerStart = this._markerEnd = this.toTimeline( - clientX - rect.x, - rect.width - ); + this._markerStart = this._markerEnd = this.toTimeline(clientX - rect.x, rect.width); CollectionStackedTimeline.SelectingRegion = this; wasSelecting = true; } @@ -254,7 +247,7 @@ export class CollectionStackedTimeline extends CollectionSubView< !isClick && CollectionStackedTimeline.SelectingRegion === this && Math.abs(movement[0]) > 15 && - !this.props.trimming + !this.IsTrimming ) { const anchor = CollectionStackedTimeline.createAnchor( this.rootDoc, @@ -287,7 +280,7 @@ export class CollectionStackedTimeline extends CollectionSubView< this.currentTime ); } else { - !wasPlaying && this.props.setTime(((clientX - rect.x) / rect.width) * this.clipDuration + this.props.clipStart); + !wasPlaying && this.props.setTime(this.toTimeline(clientX - rect.x, rect.width)); } } ); @@ -304,21 +297,19 @@ export class CollectionStackedTimeline extends CollectionSubView< e, action((e, [], []) => { if (rect && this.props.isContentActive()) { - this.props.setStartTrim(Math.min( + this._trimStart = Math.min( Math.max( this.trimStart + (e.movementX / rect.width) * this.clipDuration, 0 ), - this.trimEnd - this.minLength - )); + this.trimEnd - this.minTrimLength + ); } return false; }), emptyFunction, action((e, doubleTap) => { - if (doubleTap) { - this.props.setStartTrim(this.props.clipStart); - } + doubleTap && (this._trimStart = this.clipStart); }) ); } @@ -332,21 +323,19 @@ export class CollectionStackedTimeline extends CollectionSubView< e, action((e, [], []) => { if (rect && this.props.isContentActive()) { - this.props.setEndTrim(Math.max( + this._trimEnd = Math.max( Math.min( this.trimEnd + (e.movementX / rect.width) * this.clipDuration, - this.props.clipStart + this.clipDuration + this.clipStart + this.clipDuration ), - this.trimStart + this.minLength - )); + this.trimStart + this.minTrimLength + ); } return false; }), emptyFunction, action((e, doubleTap) => { - if (doubleTap) { - this.props.setEndTrim(this.props.clipEnd); - } + doubleTap && (this._trimEnd = this.clipEnd); }) ); } @@ -356,17 +345,16 @@ export class CollectionStackedTimeline extends CollectionSubView< if (!de.embedKey && this.props.layerProvider?.(this.props.Document) !== false && this.props.Document._isGroup) return false; if (!super.onInternalDrop(e, de)) return false; - // determine x coordinate of drop and assign it to the documents being dragged --- see internalDocDrop of collectionFreeFormView.tsx for how it's done when dropping onto a 2D freeform view const localPt = this.props.ScreenToLocalTransform().transformPoint(de.x, de.y); const x = localPt[0] - docDragData.offset[0]; const timelinePt = this.toTimeline(x, this.props.PanelWidth()); for (let i = 0; i < docDragData.droppedDocuments.length; i++) { const d = Doc.GetProto(docDragData.droppedDocuments[i]); - if (d._timecodeToHide !== undefined) { - d._timecodeToHide = timelinePt + NumCast(d._timecodeToHide) - NumCast(d._timecodeToShow); + if (this.anchorEnd(d) !== undefined) { + d[d._timecodeToHide === undefined ? this.props.endTag : "_timecodeToHide"] = timelinePt + this.anchorEnd(d) - this.anchorStart(d); } - d._timecodeToShow = timelinePt; + d[d._timecodToShow === undefined ? this.props.startTag : "_timecodToShow"] = timelinePt; } return true; @@ -403,7 +391,7 @@ export class CollectionStackedTimeline extends CollectionSubView< }); Doc.GetProto(anchor)[startTag] = anchorStartTime; Doc.GetProto(anchor)[endTag] = anchorEndTime; - if (Cast(dataDoc[fieldKey], listSpec(Doc), null) !== undefined) { + if (Cast(dataDoc[fieldKey], listSpec(Doc), null)) { Cast(dataDoc[fieldKey], listSpec(Doc), []).push(anchor); } else { dataDoc[fieldKey] = new List<Doc>([anchor]); @@ -546,10 +534,9 @@ export class CollectionStackedTimeline extends CollectionSubView< duration={this.clipDuration} mediaPath={this.props.mediaPath} layoutDoc={this.layoutDoc} - clipStart={this.props.clipStart} - clipEnd={this.props.clipEnd} + clipStart={this.clipStart} + clipEnd={this.clipEnd} PanelHeight={this.timelineContentHeight} - trimming={this.props.trimming} /> </div> ); @@ -582,12 +569,12 @@ export class CollectionStackedTimeline extends CollectionSubView< d.anchor, start + (10 / timelineContentWidth) * this.clipDuration ); - if (end < this.props.clipStart || start > this.props.clipEnd) return (null); - const left = Math.max((start - this.props.clipStart) / this.clipDuration * timelineContentWidth, 0); + if (end < this.clipStart || start > this.clipEnd) return (null); + const left = Math.max((start - this.clipStart) / this.clipDuration * timelineContentWidth, 0); const top = (d.level / maxLevel) * this.timelineContentHeight(); const timespan = end - start; const width = (timespan / this.clipDuration) * timelineContentWidth; - const height = (this.timelineContentHeight()) / maxLevel; + const height = this.timelineContentHeight() / maxLevel; return this.props.Document.hideAnchors ? null : ( <div className={"collectionStackedTimeline-marker-timeline"} @@ -624,28 +611,28 @@ export class CollectionStackedTimeline extends CollectionSubView< </div> ); })} - {!this.props.trimming && this.selectionContainer} + {!this.IsTrimming && this.selectionContainer} {this.renderAudioWaveform} {this.renderDictation} <div className="collectionStackedTimeline-current" style={{ - left: `${((this.currentTime - this.props.clipStart) / this.clipDuration) * 100}%`, + left: `${((this.currentTime - this.clipStart) / this.clipDuration) * 100}%`, }} /> - {this.props.trimming && ( + {this.IsTrimming && ( <> <div className="collectionStackedTimeline-trim-shade" - style={{ width: `${((this.trimStart - this.props.clipStart) / this.clipDuration) * 100}%` }} + style={{ width: `${((this.trimStart - this.clipStart) / this.clipDuration) * 100}%` }} ></div> <div className="collectionStackedTimeline-trim-controls" style={{ - left: `${((this.trimStart - this.props.clipStart) / this.clipDuration) * 100}%`, + left: `${((this.trimStart - this.clipStart) / this.clipDuration) * 100}%`, width: `${((this.trimEnd - this.trimStart) / this.clipDuration) * 100}%`, }} > @@ -662,8 +649,8 @@ export class CollectionStackedTimeline extends CollectionSubView< <div className="collectionStackedTimeline-trim-shade" style={{ - left: `${((this.trimEnd - this.props.clipStart) / this.clipDuration) * 100}%`, - width: `${((this.props.clipEnd - this.trimEnd) / this.clipDuration) * 100}%`, + left: `${((this.trimEnd - this.clipStart) / this.clipDuration) * 100}%`, + width: `${((this.clipEnd - this.trimEnd) / this.clipDuration) * 100}%`, }} ></div> </> @@ -754,8 +741,7 @@ class StackedTimelineAnchor extends React.Component<StackedTimelineAnchorProps> return this.props.toTimeline(e.clientX - rect.x, rect.width); }; const changeAnchor = (anchor: Doc, left: boolean, time: number | undefined) => { - const timelineOnly = - Cast(anchor[this.props.startTag], "number", null) !== undefined; + const timelineOnly = Cast(anchor[this.props.startTag], "number", null) !== undefined; if (timelineOnly) { if (!left && time !== undefined && time <= NumCast(anchor[this.props.startTag])) time = undefined; Doc.SetInPlace( @@ -767,9 +753,7 @@ class StackedTimelineAnchor extends React.Component<StackedTimelineAnchorProps> if (!left) Doc.SetInPlace(anchor, "borderRounding", time !== undefined ? undefined : "100%", true); } else { - left - ? (anchor._timecodeToShow = time) - : (anchor._timecodeToHide = time); + anchor[left ? "_timecodeToShow" : "_timecodeToHide"] = time; } return false; }; @@ -803,10 +787,9 @@ class StackedTimelineAnchor extends React.Component<StackedTimelineAnchorProps> mark: Doc, script: undefined | (() => ScriptField), doublescript: undefined | (() => ScriptField), - x: number, - y: number, - width: number, - height: number + screenXf: () => Transform, + width: () => number, + height: () => number ) { const anchor = observable({ view: undefined as any }); const focusFunc = ( @@ -825,24 +808,20 @@ class StackedTimelineAnchor extends React.Component<StackedTimelineAnchorProps> <DocumentView key="view" {...OmitKeys(this.props, ["NativeWidth", "NativeHeight"]).omit} - ref={action((r: DocumentView | null) => (anchor.view = r))} + ref={action((r: DocumentView | null) => anchor.view = r)} Document={mark} DataDoc={undefined} renderDepth={this.props.renderDepth + 1} LayoutTemplate={undefined} LayoutTemplateString={LabelBox.LayoutStringWithTitle(LabelBox, "data", this.computeTitle())} isDocumentActive={this.props.isDocumentActive} - PanelWidth={() => width} - PanelHeight={() => height} - ScreenToLocalTransform={() => - this.props.ScreenToLocalTransform().translate(-x, -y) - } + PanelWidth={width} + PanelHeight={height} + ScreenToLocalTransform={screenXf} focus={focusFunc} rootSelected={returnFalse} onClick={script} - onDoubleClick={ - this.props.layoutDoc.autoPlayAnchors ? undefined : doublescript - } + onDoubleClick={this.props.layoutDoc.autoPlayAnchors ? undefined : doublescript} ignoreAutoHeight={false} hideResizeHandles={true} bringToFront={emptyFunction} @@ -852,15 +831,17 @@ class StackedTimelineAnchor extends React.Component<StackedTimelineAnchorProps> }; }); + anchorScreenToLocalXf = () => this.props.ScreenToLocalTransform().translate(-this.props.left, -this.props.top); + width = () => this.props.width; + height = () => this.props.height; render() { const inner = this.renderInner( this.props.mark, this.props.rangeClickScript, this.props.rangePlayScript, - this.props.left, - this.props.top, - this.props.width, - this.props.height + this.anchorScreenToLocalXf, + this.width, + this.height ); return ( <> @@ -876,9 +857,7 @@ class StackedTimelineAnchor extends React.Component<StackedTimelineAnchorProps> <div key="right" className="collectionStackedTimeline-resizer" - onPointerDown={(e) => - this.onAnchorDown(e, this.props.mark, false) - } + onPointerDown={(e) => this.onAnchorDown(e, this.props.mark, false)} /> </> )} |
