From 39c85293f6c3d385ea64ba0db8c9736dfaaec993 Mon Sep 17 00:00:00 2001
From: mehekj <mehek.jethani@gmail.com>
Date: Sun, 20 Mar 2022 15:22:50 -0400
Subject: cleaned up files and added some comments

---
 .../collections/CollectionStackedTimeline.tsx      | 102 +++++++++++++++------
 1 file changed, 76 insertions(+), 26 deletions(-)

(limited to 'src/client/views/collections/CollectionStackedTimeline.tsx')

diff --git a/src/client/views/collections/CollectionStackedTimeline.tsx b/src/client/views/collections/CollectionStackedTimeline.tsx
index 7d9dc39ae..bd7d0083b 100644
--- a/src/client/views/collections/CollectionStackedTimeline.tsx
+++ b/src/client/views/collections/CollectionStackedTimeline.tsx
@@ -43,6 +43,19 @@ import {
 import { LabelBox } from "../nodes/LabelBox";
 import "./CollectionStackedTimeline.scss";
 
+
+
+/**
+ * CollectionStackedTimeline
+ * Main component: CollectionStackedTimeline.tsx
+ * Supporting Components: AudioWaveform
+ * 
+ * CollectionStackedTimeline is a collection view used for audio and video nodes to display a timeline of the temporal media documents with an audio waveform and markers for links and annotations
+ * The actual media is handled in the containing classes (AudioBox, VideoBox) but the timeline deals with rendering and updating timecodes, links, and trimming.
+ * When trimming there are two pairs of times that are tracked: trimStart and trimEnd are the bounds of the trim controls, clipStart and clipEnd are the actual trimmed playback bounds of the clip
+ */
+
+
 type PanZoomDocument = makeInterface<[]>;
 const PanZoomDocument = makeInterface();
 export type CollectionStackedTimelineProps = {
@@ -60,38 +73,42 @@ export type CollectionStackedTimelineProps = {
     fieldKey: string;
 };
 
+// trimming state: shows full clip, current trim bounds, or not trimming
 export enum TrimScope {
     All = 2,
     Clip = 1,
     None = 0,
 }
 
+
 @observer
 export class CollectionStackedTimeline extends CollectionSubView<
     PanZoomDocument,
     CollectionStackedTimelineProps
 >(PanZoomDocument) {
-    @observable static SelectingRegion: CollectionStackedTimeline | undefined;
-    @observable public static CurrentlyPlaying: Doc[];
+    @observable static SelectingRegion: CollectionStackedTimeline | undefined; // timeline selection region
+    @observable public static CurrentlyPlaying: Doc[]; // tracks all currently playing audio and video docs
 
     static RangeScript: ScriptField;
     static LabelScript: ScriptField;
     static RangePlayScript: ScriptField;
     static LabelPlayScript: ScriptField;
 
-    private _timeline: HTMLDivElement | null = null;
-    private _timelineWrapper: HTMLDivElement | null = null;
+    private _timeline: HTMLDivElement | null = null; // ref to actual timeline div
+    private _timelineWrapper: HTMLDivElement | null = null; // ref to timeline wrapper div for zooming and scrolling
     private _markerStart: number = 0;
     @observable _markerEnd: number | undefined;
     @observable _trimming: number = TrimScope.None;
-    @observable _trimStart: number = 0;
-    @observable _trimEnd: number = 0;
+    @observable _trimStart: number = 0; // trim controls start pos
+    @observable _trimEnd: number = 0; // trim controls end pos
 
     @observable _zoomFactor: number = 1;
 
     @observable _scroll: number = 0;
 
+    // ensures that clip doesn't get trimmed so small that controls cannot be adjusted anymore 
     get minTrimLength() { return Math.max(this._timeline?.getBoundingClientRect() ? 0.05 * this.clipDuration : 0, 0.5) }
+
     @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; }
@@ -104,6 +121,7 @@ export class CollectionStackedTimeline extends CollectionSubView<
 
     @computed get zoomFactor() { return this._zoomFactor }
 
+
     constructor(props: any) {
         super(props);
         // onClick play scripts
@@ -135,6 +153,7 @@ export class CollectionStackedTimeline extends CollectionSubView<
         }
     }
 
+
     public get IsTrimming() { return this._trimming; }
 
     @action
@@ -155,24 +174,31 @@ export class CollectionStackedTimeline extends CollectionSubView<
         this._zoomFactor = zoom;
     }
 
+
     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) ?? null);
+
+
+    // converts screen pixel offset to time
     toTimeline = (screen_delta: number, width: number) => {
         return Math.max(
             this.clipStart,
             Math.min(this.clipEnd, (screen_delta / width) * this.clipDuration + this.clipStart));
     }
 
+
     rangeClickScript = () => CollectionStackedTimeline.RangeScript;
     rangePlayScript = () => CollectionStackedTimeline.RangePlayScript;
 
-    // for creating key anchors with key events
+
+    // handles key events for for creating key anchors, scrubbing, exiting trim
     @action
     keyEvents = (e: KeyboardEvent) => {
         if (
             !(e.target instanceof HTMLInputElement) &&
             this.props.isSelected(true)
         ) {
+            // if shift pressed scrub 1 second otherwise 1/10th
             const jump = e.shiftKey ? 1 : 0.1;
             e.stopPropagation();
             switch (e.key) {
@@ -196,6 +222,7 @@ export class CollectionStackedTimeline extends CollectionSubView<
                     }
                     break;
                 case "Escape":
+                    // abandons current trim
                     this._trimStart = this.clipStart;
                     this._trimStart = this.clipEnd;
                     this._trimming = TrimScope.None;
@@ -210,6 +237,7 @@ export class CollectionStackedTimeline extends CollectionSubView<
         }
     }
 
+
     getLinkData(l: Doc) {
         let la1 = l.anchor1 as Doc;
         let la2 = l.anchor2 as Doc;
@@ -224,7 +252,8 @@ export class CollectionStackedTimeline extends CollectionSubView<
         return { la1, la2, linkTime };
     }
 
-    // starting the drag event for anchor resizing
+
+    // handles dragging selection to create markers
     @action
     onPointerDownTimeline = (e: React.PointerEvent): void => {
         const rect = this._timeline?.getBoundingClientRect();
@@ -299,6 +328,8 @@ export class CollectionStackedTimeline extends CollectionSubView<
 
     }
 
+
+    // for dragging trim start handle
     @action
     trimLeft = (e: React.PointerEvent): void => {
         const rect = this._timeline?.getBoundingClientRect();
@@ -325,6 +356,7 @@ export class CollectionStackedTimeline extends CollectionSubView<
         );
     }
 
+    // for dragging trim end handle
     @action
     trimRight = (e: React.PointerEvent): void => {
         const rect = this._timeline?.getBoundingClientRect();
@@ -351,12 +383,15 @@ export class CollectionStackedTimeline extends CollectionSubView<
         );
     }
 
+
+    // for rendering scrolling when timeline zoomed
     @action
     setScroll = (e: React.UIEvent) => {
         e.stopPropagation();
         this._scroll = this._timelineWrapper!.scrollLeft;
     }
 
+    // smooth scrolls to time like when following links overflowed due to zoom
     @action
     scrollToTime = (time: number) => {
         if (this._timelineWrapper) {
@@ -371,6 +406,8 @@ export class CollectionStackedTimeline extends CollectionSubView<
         }
     }
 
+
+    // handles dragging and dropping markers in timeline
     @action
     internalDocDrop(e: Event, de: DragManager.DropEvent, docDragData: DragManager.DocumentDragData, xp: number) {
         if (!de.embedKey && this.props.layerProvider?.(this.props.Document) !== false && this.props.Document._isGroup) return false;
@@ -396,6 +433,8 @@ export class CollectionStackedTimeline extends CollectionSubView<
         return false;
     }
 
+
+    // creates marker on timeline
     @undoBatch
     @action
     static createAnchor(
@@ -430,6 +469,7 @@ export class CollectionStackedTimeline extends CollectionSubView<
         return anchor;
     }
 
+
     @action
     playOnClick = (anchorDoc: Doc, clientX: number) => {
         const seekTimeInSeconds = this.anchorStart(anchorDoc) - 0.25;
@@ -521,14 +561,20 @@ export class CollectionStackedTimeline extends CollectionSubView<
         return level;
     }
 
+
     dictationHeightPercent = 50;
     dictationHeight = () => (this.props.PanelHeight() * (100 - this.dictationHeightPercent)) / 100;
+
     @computed get timelineContentHeight() { return this.props.PanelHeight() * this.dictationHeightPercent / 100; }
     @computed get timelineContentWidth() { return this.props.PanelWidth() * this.zoomFactor - 4 };  // subtract size of container border
+
     dictationScreenToLocalTransform = () => this.props.ScreenToLocalTransform().translate(0, -this.timelineContentHeight);
+
     isContentActive = () => this.props.isSelected() || this.props.isContentActive();
+
     currentTimecode = () => this.currentTime;
 
+
     @computed get renderDictation() {
         const dictation = Cast(this.dataDoc[this.props.dictationKey], Doc, null);
         return !dictation ? null : (
@@ -565,23 +611,8 @@ export class CollectionStackedTimeline extends CollectionSubView<
             </div>
         );
     }
-    @computed get renderAudioWaveform() {
-        return !this.props.mediaPath ? null : (
-            <div className="collectionStackedTimeline-waveform">
-                <AudioWaveform
-                    rawDuration={this.props.rawDuration}
-                    duration={this.clipDuration}
-                    mediaPath={this.props.mediaPath}
-                    layoutDoc={this.layoutDoc}
-                    clipStart={this.clipStart}
-                    clipEnd={this.clipEnd}
-                    zoomFactor={this.zoomFactor}
-                    PanelHeight={this.timelineContentHeight}
-                    PanelWidth={this.timelineContentWidth}
-                />
-            </div>
-        );
-    }
+
+    // renders selection region on timeline
     @computed get selectionContainer() {
         const markerEnd = CollectionStackedTimeline.SelectingRegion === this ? this.currentTime : this._markerEnd;
         return markerEnd === undefined ? null : (
@@ -668,7 +699,6 @@ export class CollectionStackedTimeline extends CollectionSubView<
                         );
                     })}
                     {!this.IsTrimming && this.selectionContainer}
-                    {/* {this.renderAudioWaveform} */}
                     <AudioWaveform
                         rawDuration={this.props.rawDuration}
                         duration={this.clipDuration}
@@ -728,6 +758,12 @@ export class CollectionStackedTimeline extends CollectionSubView<
     }
 }
 
+
+/**
+ * StackedTimelineAnchor
+ * creates the anchors to display markers, links, and embedded documents on timeline
+ */
+
 interface StackedTimelineAnchorProps {
     mark: Doc;
     rangeClickScript: () => ScriptField;
@@ -753,20 +789,26 @@ interface StackedTimelineAnchorProps {
     trimStart: number;
     trimEnd: number;
 }
+
+
 @observer
 class StackedTimelineAnchor extends React.Component<StackedTimelineAnchorProps> {
     _lastTimecode: number;
     _disposer: IReactionDisposer | undefined;
+
     constructor(props: any) {
         super(props);
         this._lastTimecode = this.props.currentTimecode();
     }
 
+    // updates marker document title to reflect correct timecodes
     computeTitle = () => {
         const start = Math.max(NumCast(this.props.mark[this.props.startTag]), this.props.trimStart) - this.props.trimStart;
         const end = Math.min(NumCast(this.props.mark[this.props.endTag]), this.props.trimEnd) - this.props.trimStart;
         return `#${formatTime(start)}-${formatTime(end)}`;
     }
+
+
     componentDidMount() {
         this._disposer = reaction(
             () => this.props.currentTimecode(),
@@ -805,9 +847,12 @@ class StackedTimelineAnchor extends React.Component<StackedTimelineAnchorProps>
             }
         );
     }
+
     componentWillUnmount() {
         this._disposer?.();
     }
+
+
     // starting the drag event for anchor resizing
     onAnchorDown = (e: React.PointerEvent, anchor: Doc, left: boolean): void => {
         this.props._timeline?.setPointerCapture(e.pointerId);
@@ -851,11 +896,15 @@ class StackedTimelineAnchor extends React.Component<StackedTimelineAnchorProps>
         );
     }
 
+
+    // context menu
     contextMenuItems = () => {
         const resetTitle = { script: ScriptField.MakeFunction(`self.title = "#" + formatToTime(self["${this.props.startTag}"]) + "-" + formatToTime(self["${this.props.endTag}"])`)!, icon: "folder-plus", label: "Reset Title" };
         return [resetTitle];
     }
 
+
+    // renders anchor LabelBox
     renderInner = computedFn(function (
         this: StackedTimelineAnchor,
         mark: Doc,
@@ -910,6 +959,7 @@ 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,
-- 
cgit v1.2.3-70-g09d2

