aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/collections/CollectionStackedTimeline.tsx
diff options
context:
space:
mode:
authorusodhi <61431818+usodhi@users.noreply.github.com>2021-02-01 18:42:38 -0500
committerusodhi <61431818+usodhi@users.noreply.github.com>2021-02-01 18:42:38 -0500
commitb160a00f80c4855e190d75f97482b5b019e77437 (patch)
tree4fd150d45a5c49b9d5572edcb663956c0b29dd60 /src/client/views/collections/CollectionStackedTimeline.tsx
parent888fb3b3933e7aa48e9ac3abe85536328fcca336 (diff)
parent41bb365dd4f787aec2262dcb07508e0de3837e10 (diff)
more merge
Diffstat (limited to 'src/client/views/collections/CollectionStackedTimeline.tsx')
-rw-r--r--src/client/views/collections/CollectionStackedTimeline.tsx293
1 files changed, 147 insertions, 146 deletions
diff --git a/src/client/views/collections/CollectionStackedTimeline.tsx b/src/client/views/collections/CollectionStackedTimeline.tsx
index 1775250fa..d4eb66fcc 100644
--- a/src/client/views/collections/CollectionStackedTimeline.tsx
+++ b/src/client/views/collections/CollectionStackedTimeline.tsx
@@ -1,17 +1,18 @@
import React = require("react");
-import { action, computed, IReactionDisposer, observable } from "mobx";
+import { action, computed, IReactionDisposer, observable, runInAction } from "mobx";
import { observer } from "mobx-react";
import { computedFn } from "mobx-utils";
-import { Doc, Opt } from "../../../fields/Doc";
+import { Doc, Opt, DocListCast } from "../../../fields/Doc";
import { Id } from "../../../fields/FieldSymbols";
import { List } from "../../../fields/List";
import { listSpec, makeInterface } from "../../../fields/Schema";
import { ComputedField, ScriptField } from "../../../fields/ScriptField";
import { Cast, NumCast } from "../../../fields/Types";
-import { emptyFunction, formatTime, OmitKeys, returnFalse, setupMoveUpEvents } from "../../../Utils";
+import { emptyFunction, formatTime, OmitKeys, returnFalse, setupMoveUpEvents, StopEvent } from "../../../Utils";
import { Docs } from "../../documents/Documents";
import { Scripting } from "../../util/Scripting";
import { SelectionManager } from "../../util/SelectionManager";
+import { undoBatch } from "../../util/UndoManager";
import { CollectionSubView } from "../collections/CollectionSubView";
import { DocumentView } from "../nodes/DocumentView";
import { LabelBox } from "../nodes/LabelBox";
@@ -28,69 +29,80 @@ export type CollectionStackedTimelineProps = {
playing: () => boolean;
setTime: (time: number) => void;
isChildActive: () => boolean;
+ startTag: string;
+ endTag: string;
+ fieldKeySuffix?: string;
};
@observer
export class CollectionStackedTimeline extends CollectionSubView<PanZoomDocument, CollectionStackedTimelineProps>(PanZoomDocument) {
+ @observable static SelectingRegion: CollectionStackedTimeline | undefined = undefined;
static RangeScript: ScriptField;
static LabelScript: ScriptField;
static RangePlayScript: ScriptField;
static LabelPlayScript: ScriptField;
- _disposers: { [name: string]: IReactionDisposer } = {};
- _doubleTime: NodeJS.Timeout | undefined; // bcz: Hack! this must be called _doubleTime since setupMoveDragEvents will use that field name
- _ele: HTMLAudioElement | null = null;
- _start: number = 0;
- _left: boolean = false;
- _dragging = false;
- _play: any = null;
- _audioRef = React.createRef<HTMLDivElement>();
- _timeline: Opt<HTMLDivElement>;
- _markerStart: number = 0;
- _currAnchor: Opt<Doc>;
-
- @observable static SelectingRegion: CollectionStackedTimeline | undefined = undefined;
+ private _timeline: HTMLDivElement | null = null;
+ private _markerStart: number = 0;
@observable _markerEnd: number = 0;
- @observable _position: number = 0;
- @computed get anchorDocs() { return this.childDocs; }
- @computed get currentTime() { return NumCast(this.props.Document._currentTimecode); }
+
+ get duration() { return this.props.duration; }
+ @computed get anchorDocs() { return this.props.fieldKeySuffix ? this.childDocs.concat(...DocListCast(this.rootDoc[this.props.fieldKey + this.props.fieldKeySuffix])) : this.childDocs; }
+ @computed get currentTime() { return NumCast(this.layoutDoc._currentTimecode); }
+ @computed get selectionContainer() {
+ return CollectionStackedTimeline.SelectingRegion !== this ? (null) : <div className="collectionStackedTimeline-selector" style={{
+ left: `${Math.min(NumCast(this._markerStart), NumCast(this._markerEnd)) / this.duration * 100}%`,
+ width: `${Math.abs(this._markerStart - this._markerEnd) / this.duration * 100}%`
+ }} />;
+ }
constructor(props: any) {
super(props);
// onClick play scripts
- CollectionStackedTimeline.RangeScript = CollectionStackedTimeline.RangeScript || ScriptField.MakeFunction(`scriptContext.clickAnchor(this)`, { self: Doc.name, scriptContext: "any" })!;
- CollectionStackedTimeline.LabelScript = CollectionStackedTimeline.LabelScript || ScriptField.MakeFunction(`scriptContext.clickAnchor(this)`, { self: Doc.name, scriptContext: "any" })!;
- CollectionStackedTimeline.RangePlayScript = CollectionStackedTimeline.RangePlayScript || ScriptField.MakeFunction(`scriptContext.playOnClick(this)`, { self: Doc.name, scriptContext: "any" })!;
- CollectionStackedTimeline.LabelPlayScript = CollectionStackedTimeline.LabelPlayScript || ScriptField.MakeFunction(`scriptContext.playOnClick(this)`, { self: Doc.name, scriptContext: "any" })!;
+ CollectionStackedTimeline.RangeScript = CollectionStackedTimeline.RangeScript || ScriptField.MakeFunction(`scriptContext.clickAnchor(this, clientX)`, { self: Doc.name, scriptContext: "any", clientX: "number" })!;
+ CollectionStackedTimeline.LabelScript = CollectionStackedTimeline.LabelScript || ScriptField.MakeFunction(`scriptContext.clickAnchor(this, clientX)`, { self: Doc.name, scriptContext: "any", clientX: "number" })!;
+ CollectionStackedTimeline.RangePlayScript = CollectionStackedTimeline.RangePlayScript || ScriptField.MakeFunction(`scriptContext.playOnClick(this, clientX)`, { self: Doc.name, scriptContext: "any", clientX: "number" })!;
+ CollectionStackedTimeline.LabelPlayScript = CollectionStackedTimeline.LabelPlayScript || ScriptField.MakeFunction(`scriptContext.playOnClick(this, clientX)`, { self: Doc.name, scriptContext: "any", clientX: "number" })!;
+ }
+
+ componentDidMount() { document.addEventListener("keydown", this.keyEvents, true); }
+ componentWillUnmount() {
+ document.removeEventListener("keydown", this.keyEvents, true);
+ if (CollectionStackedTimeline.SelectingRegion === this) runInAction(() => 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);
}
+ toTimeline = (screen_delta: number, width: number) => Math.max(0, Math.min(this.duration, screen_delta / width * this.duration));
+ rangeClickScript = () => CollectionStackedTimeline.RangeScript;
+ labelClickScript = () => CollectionStackedTimeline.LabelScript;
+ rangePlayScript = () => CollectionStackedTimeline.RangePlayScript;
+ labelPlayScript = () => CollectionStackedTimeline.LabelPlayScript;
// for creating key anchors with key events
@action
keyEvents = (e: KeyboardEvent) => {
- if (e.target instanceof HTMLInputElement) return;
- if (!this.props.playing()) return; // can't create if video is not playing
- switch (e.key) {
- case "x": // currently set to x, but can be a different key
- const currTime = this.currentTime;
- if (this._start) {
- this._markerStart = currTime;
- // this._start = false;
- // this._visible = true;
- } else {
- this.createAnchor(this._markerStart, currTime);
- // this._start = true;
- // this._visible = false;
- }
+ if (!(e.target instanceof HTMLInputElement) && this.props.isSelected(true)) {
+ switch (e.key) {
+ case " ":
+ if (!CollectionStackedTimeline.SelectingRegion) {
+ this._markerStart = this._markerEnd = this.currentTime;
+ CollectionStackedTimeline.SelectingRegion = this;
+ } else {
+ CollectionStackedTimeline.createAnchor(this.rootDoc, this.dataDoc, this.props.fieldKey, this.props.startTag, this.props.endTag, this.currentTime);
+ CollectionStackedTimeline.SelectingRegion = undefined;
+ }
+ }
}
}
- anchorStart = (anchor: Doc) => NumCast(anchor.anchorStartTime, NumCast(anchor._timecodeToShow, NumCast(anchor.videoStart)));
- anchorEnd = (anchor: Doc, defaultVal: any = null) => NumCast(anchor.anchorEndTime, NumCast(anchor._timecodeToHide, NumCast(anchor.videoEnd, defaultVal)));
-
getLinkData(l: Doc) {
let la1 = l.anchor1 as Doc;
let la2 = l.anchor2 as Doc;
- const linkTime = NumCast(la2.anchorStartTime, NumCast(la1.anchorStartTime));
+ const linkTime = NumCast(la2[this.props.startTag], NumCast(la1[this.props.startTag]));
if (Doc.AreProtosEqual(la1, this.dataDoc)) {
la1 = l.anchor2 as Doc;
la2 = l.anchor1 as Doc;
@@ -98,132 +110,134 @@ export class CollectionStackedTimeline extends CollectionSubView<PanZoomDocument
return { la1, la2, linkTime };
}
- // ref for timeline
- timelineRef = (timeline: HTMLDivElement) => {
- this._timeline = timeline;
- }
-
- // updates the anchor with the new time
- @action
- changeAnchor = (anchor: Opt<Doc>, time: number) => {
- anchor && (this._left ? anchor.anchorStartTime = time : anchor.anchorEndTime = time);
- }
-
- // checks if the two anchors are the same with start and end time
- isSame = (m1: any, m2: any) => {
- return this.anchorStart(m1) === this.anchorStart(m2) && this.anchorEnd(m1) === this.anchorEnd(m2);
- }
-
- @computed get selectionContainer() {
- return CollectionStackedTimeline.SelectingRegion !== this ? (null) : <div className="audiobox-container" style={{
- left: `${Math.min(NumCast(this._markerStart), NumCast(this._markerEnd)) / this.props.duration * 100}%`,
- width: `${Math.abs(this._markerStart - this._markerEnd) / this.props.duration * 100}%`, height: "100%", top: "0%"
- }} />;
- }
-
// starting the drag event for anchor resizing
@action
onPointerDownTimeline = (e: React.PointerEvent): void => {
- const rect = this._timeline?.getBoundingClientRect();// (e.target as any).getBoundingClientRect();
- if (rect && e.target !== this._audioRef.current && this.props.active()) {
+ const rect = this._timeline?.getBoundingClientRect();
+ const clientX = e.clientX;
+ if (rect && this.props.active()) {
const wasPlaying = this.props.playing();
if (wasPlaying) this.props.Pause();
- else if (!this._doubleTime) {
- this._doubleTime = setTimeout(() => {
- this._doubleTime = undefined;
- this.props.setTime((e.clientX - rect.x) / rect.width * this.props.duration);
- }, 300);
- }
- this._markerStart = this._markerEnd = this.toTimeline(e.clientX - rect.x, rect.width);
- CollectionStackedTimeline.SelectingRegion = this;
+ const wasSelecting = CollectionStackedTimeline.SelectingRegion === this;
setupMoveUpEvents(this, e,
action(e => {
+ if (!wasSelecting && CollectionStackedTimeline.SelectingRegion !== this) {
+ this._markerStart = this._markerEnd = this.toTimeline(clientX - rect.x, rect.width);
+ CollectionStackedTimeline.SelectingRegion = this;
+ }
this._markerEnd = this.toTimeline(e.clientX - rect.x, rect.width);
return false;
}),
- action((e, movement) => {
+ action((e, movement, isClick) => {
this._markerEnd = this.toTimeline(e.clientX - rect.x, rect.width);
if (this._markerEnd < this._markerStart) {
const tmp = this._markerStart;
this._markerStart = this._markerEnd;
this._markerEnd = tmp;
}
- CollectionStackedTimeline.SelectingRegion === this && (Math.abs(movement[0]) > 15) && this.createAnchor(this._markerStart, this._markerEnd);
- CollectionStackedTimeline.SelectingRegion = undefined;
+ if (!isClick && CollectionStackedTimeline.SelectingRegion === this && (Math.abs(movement[0]) > 15)) {
+ CollectionStackedTimeline.createAnchor(this.rootDoc, this.dataDoc, this.props.fieldKey, this.props.startTag, this.props.endTag,
+ this._markerStart, this._markerEnd);
+ }
+ (!isClick || !wasSelecting) && (CollectionStackedTimeline.SelectingRegion = undefined);
}),
(e, doubleTap) => {
this.props.select(false);
- e.shiftKey && this.createAnchor(this.currentTime);
+ e.shiftKey && CollectionStackedTimeline.createAnchor(this.rootDoc, this.dataDoc, this.props.fieldKey, this.props.startTag, this.props.endTag, this.currentTime);
!wasPlaying && doubleTap && this.props.Play();
- }
- , this.props.isSelected(true) || this.props.isChildActive());
+ },
+ this.props.isSelected(true) || this.props.isChildActive(), undefined,
+ () => !wasPlaying && this.props.setTime((clientX - rect.x) / rect.width * this.duration));
}
}
+ @undoBatch
@action
- createAnchor(anchorStartTime?: number, anchorEndTime?: number) {
- if (anchorStartTime === undefined) return this.props.Document;
+ static createAnchor(rootDoc: Doc, dataDoc: Doc, fieldKey: string, startTag: string, endTag: string, anchorStartTime?: number, anchorEndTime?: number) {
+ if (anchorStartTime === undefined) return rootDoc;
const anchor = Docs.Create.LabelDocument({
- title: ComputedField.MakeFunction(`"#" + formatToTime(self.anchorStartTime) + "-" + formatToTime(self.anchorEndTime)`) as any,
+ title: ComputedField.MakeFunction(`"#" + formatToTime(self["${startTag}"]) + "-" + formatToTime(self["${endTag}"])`) as any,
useLinkSmallAnchor: true,
hideLinkButton: true,
- anchorStartTime,
- anchorEndTime,
- annotationOn: this.props.Document
+ annotationOn: rootDoc
});
- if (Cast(this.dataDoc[this.props.fieldKey], listSpec(Doc), null) !== undefined) {
- Cast(this.dataDoc[this.props.fieldKey], listSpec(Doc), []).push(anchor);
+ Doc.GetProto(anchor)[startTag] = anchorStartTime;
+ Doc.GetProto(anchor)[endTag] = anchorEndTime;
+ if (Cast(dataDoc[fieldKey], listSpec(Doc), null) !== undefined) {
+ Cast(dataDoc[fieldKey], listSpec(Doc), []).push(anchor);
} else {
- this.dataDoc[this.props.fieldKey] = new List<Doc>([anchor]);
+ dataDoc[fieldKey] = new List<Doc>([anchor]);
}
return anchor;
}
- // play back the audio from time
@action
- playOnClick = (anchorDoc: Doc) => {
- this.props.playFrom(this.anchorStart(anchorDoc), this.anchorEnd(anchorDoc, this.props.duration));
+ playOnClick = (anchorDoc: Doc, clientX: number) => {
+ const seekTimeInSeconds = this.anchorStart(anchorDoc);
+ const endTime = this.anchorEnd(anchorDoc);
+ if (this.layoutDoc.autoPlay) {
+ if (this.props.playing()) this.props.Pause();
+ else this.props.playFrom(seekTimeInSeconds, endTime);
+ } else {
+ if (seekTimeInSeconds < NumCast(this.layoutDoc._currentTimecode) && endTime > NumCast(this.layoutDoc._currentTimecode)) {
+ if (!this.layoutDoc.autoPlay && this.props.playing()) {
+ this.props.Pause();
+ } else {
+ this.props.Play();
+ }
+ } else {
+ this.props.playFrom(seekTimeInSeconds, endTime);
+ }
+ }
return { select: true };
}
- // play back the audio from time
@action
- clickAnchor = (anchorDoc: Doc) => {
- if (this.props.Document.autoPlay) return this.playOnClick(anchorDoc);
- this.props.setTime(this.anchorStart(anchorDoc));
+ clickAnchor = (anchorDoc: Doc, clientX: number) => {
+ const seekTimeInSeconds = this.anchorStart(anchorDoc);
+ const endTime = this.anchorEnd(anchorDoc);
+ if (seekTimeInSeconds < NumCast(this.layoutDoc._currentTimecode) + 1e-4 && endTime > NumCast(this.layoutDoc._currentTimecode) - 1e-4) {
+ if (this.props.playing()) this.props.Pause();
+ else if (this.layoutDoc.autoPlay) this.props.Play();
+ else if (!this.layoutDoc.autoPlay) {
+ const rect = this._timeline?.getBoundingClientRect();
+ rect && this.props.setTime(this.toTimeline(clientX - rect.x, rect.width));
+ }
+ } else {
+ if (this.layoutDoc.autoPlay) this.props.playFrom(seekTimeInSeconds, endTime);
+ else this.props.setTime(seekTimeInSeconds);
+ }
return { select: true };
}
- toTimeline = (screen_delta: number, width: number) => Math.max(0, Math.min(this.props.duration, screen_delta / width * this.props.duration));
+
// starting the drag event for anchor resizing
- onPointerDown = (e: React.PointerEvent, m: Doc, left: boolean): void => {
- this._currAnchor = m;
- this._left = left;
+ onAnchorDown = (e: React.PointerEvent, anchor: Doc, left: boolean): void => {
this._timeline?.setPointerCapture(e.pointerId);
+ const newTime = (e: PointerEvent) => {
+ const rect = (e.target as any).getBoundingClientRect();
+ return this.toTimeline(e.clientX - rect.x, rect.width);
+ };
+ const changeAnchor = (anchor: Doc, left: boolean, time: number) => {
+ const timelineOnly = Cast(anchor[this.props.startTag], "number", null) !== undefined;
+ if (timelineOnly) Doc.SetInPlace(anchor, left ? this.props.startTag : this.props.endTag, time, true);
+ else left ? anchor._timecodeToShow = time : anchor._timecodeToHide = time;
+ return false;
+ };
setupMoveUpEvents(this, e,
+ (e) => changeAnchor(anchor, left, newTime(e)),
(e) => {
- const rect = (e.target as any).getBoundingClientRect();
- this.changeAnchor(this._currAnchor, this.toTimeline(e.clientX - rect.x, rect.width));
- return false;
- },
- (e) => {
- const rect = (e.target as any).getBoundingClientRect();
- this.props.setTime(this.toTimeline(e.clientX - rect.x, rect.width));
+ this.props.setTime(newTime(e));
this._timeline?.releasePointerCapture(e.pointerId);
},
emptyFunction);
}
- rangeClickScript = () => CollectionStackedTimeline.RangeScript;
- labelClickScript = () => CollectionStackedTimeline.LabelScript;
- rangePlayScript = () => CollectionStackedTimeline.RangePlayScript;
- labelPlayScript = () => CollectionStackedTimeline.LabelPlayScript;
-
// makes sure no anchors overlaps each other by setting the correct position and width
getLevel = (m: Doc, placed: { anchorStartTime: number, anchorEndTime: number, level: number }[]) => {
const timelineContentWidth = this.props.PanelWidth();
const x1 = this.anchorStart(m);
- const x2 = this.anchorEnd(m, x1 + 10 / timelineContentWidth * this.props.duration);
+ const x2 = this.anchorEnd(m, x1 + 10 / timelineContentWidth * this.duration);
let max = 0;
const overlappedLevels = new Set(placed.map(p => {
const y1 = p.anchorStartTime;
@@ -248,21 +262,19 @@ export class CollectionStackedTimeline extends CollectionSubView<PanZoomDocument
ref={action((r: DocumentView | null) => anchor.view = r)}
Document={mark}
DataDoc={undefined}
- PanelWidth={() => width}
- PanelHeight={() => height}
renderDepth={this.props.renderDepth + 1}
- focus={() => this.props.playLink(mark)}
- rootSelected={returnFalse}
LayoutTemplate={undefined}
LayoutTemplateString={LabelBox.LayoutString("data")}
- ContainingCollectionDoc={this.props.Document}
- removeDocument={this.props.removeDocument}
+ PanelWidth={() => width}
+ PanelHeight={() => height}
ScreenToLocalTransform={() => this.props.ScreenToLocalTransform().translate(-x, -y)}
- parentActive={(out) => this.props.isSelected(out) || this.props.isChildActive()}
- whenActiveChanged={this.props.whenActiveChanged}
+ focus={() => this.props.playLink(mark)}
+ parentActive={out => this.props.isSelected(out) || this.props.isChildActive()}
+ rootSelected={returnFalse}
onClick={script}
onDoubleClick={this.props.Document.autoPlay ? undefined : doublescript}
ignoreAutoHeight={false}
+ hideResizeHandles={true}
bringToFront={emptyFunction}
scriptContext={this} />
};
@@ -273,8 +285,8 @@ export class CollectionStackedTimeline extends CollectionSubView<PanZoomDocument
{inner.view}
{!inner.anchor.view || !SelectionManager.IsSelected(inner.anchor.view) ? (null) :
<>
- <div key="left" className="left-resizer" onPointerDown={e => this.onPointerDown(e, mark, true)} />
- <div key="right" className="resizer" onPointerDown={e => this.onPointerDown(e, mark, false)} />
+ <div key="left" className="collectionStackedTimeline-left-resizer" onPointerDown={e => this.onAnchorDown(e, mark, true)} />
+ <div key="right" className="collectionStackedTimeline-resizer" onPointerDown={e => this.onAnchorDown(e, mark, false)} />
</>}
</>;
});
@@ -285,39 +297,28 @@ export class CollectionStackedTimeline extends CollectionSubView<PanZoomDocument
const overlaps: { anchorStartTime: number, anchorEndTime: number, level: number }[] = [];
const drawAnchors = this.anchorDocs.map(anchor => ({ level: this.getLevel(anchor, overlaps), anchor }));
const maxLevel = overlaps.reduce((m, o) => Math.max(m, o.level), 0) + 2;
- return <div className="audiobox-timeline" style={{ height: "100%", width: "100%" }} ref={this.timelineRef}
- onClick={e => {
- if (this.props.isChildActive() || this.props.isSelected(false)) {
- e.stopPropagation(); e.preventDefault();
- }
- }}
- onPointerDown={e => {
- if (this.props.isChildActive() || this.props.isSelected(false)) {
- e.button === 0 && !e.ctrlKey && this.onPointerDownTimeline(e);
- }
- }}>
+ const isActive = this.props.isChildActive() || this.props.isSelected(false);
+ return <div className="collectionStackedTimeline" ref={(timeline: HTMLDivElement | null) => this._timeline = timeline}
+ onClick={e => isActive && StopEvent(e)} onPointerDown={e => isActive && this.onPointerDownTimeline(e)}>
{drawAnchors.map(d => {
- const m = d.anchor;
- const start = this.anchorStart(m);
- const end = this.anchorEnd(m, start + 10 / timelineContentWidth * this.props.duration);
- const left = start / this.props.duration * timelineContentWidth;
+ const start = this.anchorStart(d.anchor);
+ const end = this.anchorEnd(d.anchor, start + 10 / timelineContentWidth * this.duration);
+ const left = start / this.duration * timelineContentWidth;
const top = d.level / maxLevel * timelineContentHeight;
const timespan = end - start;
return this.props.Document.hideAnchors ? (null) :
- <div className={`audiobox-marker-${this.props.PanelHeight() < 32 ? "mini" : ""}timeline`} key={m[Id]}
- style={{ left, top, width: `${timespan / this.props.duration * 100}%`, height: `${1 / maxLevel * 100}%` }}
- onClick={e => { this.props.playFrom(start, this.anchorEnd(m)); e.stopPropagation(); }} >
- {this.renderAnchor(m, this.rangeClickScript, this.rangePlayScript,
+ <div className={"collectionStackedTimeline-marker-timeline"} key={d.anchor[Id]}
+ style={{ left, top, width: `${timespan / this.duration * timelineContentWidth}px`, height: `${timelineContentHeight / maxLevel}px` }}
+ onClick={e => { this.props.playFrom(start, this.anchorEnd(d.anchor)); e.stopPropagation(); }} >
+ {this.renderAnchor(d.anchor, this.rangeClickScript, this.rangePlayScript,
left,
top,
- timelineContentWidth * timespan / this.props.duration,
+ timelineContentWidth * timespan / this.duration,
timelineContentHeight / maxLevel)}
</div>;
})}
{this.selectionContainer}
- <div className="audiobox-current" ref={this._audioRef} onClick={e => { e.stopPropagation(); e.preventDefault(); }}
- style={{ left: `${this.currentTime / this.props.duration * 100}%`, pointerEvents: "none" }}
- />
+ <div className="collectionStackedTimeline-current" style={{ left: `${this.currentTime / this.duration * 100}%` }} />
</div>;
}
}