aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/collections
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2021-09-24 22:31:22 -0400
committerbobzel <zzzman@gmail.com>2021-09-24 22:31:22 -0400
commit6bcf4ae5f3953ba10ba1fba6c7d2246514a90eed (patch)
tree859bb94c62c70a5c731376afe4aae5573036c8f7 /src/client/views/collections
parentcbf22b4ccaab14a7c8cb62137ea09b58a001e13a (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.tsx193
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)}
/>
</>
)}