From 7e0a60dc39ce2ad3fc8f90197f5ade7fe5e5b112 Mon Sep 17 00:00:00 2001 From: mehekj Date: Sat, 11 Sep 2021 11:47:22 -0400 Subject: fixed record buttons and trimmed marker width appearance --- src/client/views/collections/CollectionStackedTimeline.tsx | 8 ++++++-- src/client/views/nodes/AudioBox.scss | 14 +++++++------- 2 files changed, 13 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionStackedTimeline.tsx b/src/client/views/collections/CollectionStackedTimeline.tsx index 51e05e278..56621d6d5 100644 --- a/src/client/views/collections/CollectionStackedTimeline.tsx +++ b/src/client/views/collections/CollectionStackedTimeline.tsx @@ -548,10 +548,14 @@ export class CollectionStackedTimeline extends CollectionSubView< ); const left = this.props.trimming ? (start / this.duration) * timelineContentWidth - : (start - this.trimStart) / this.props.trimDuration * timelineContentWidth; + : Math.max((start - this.trimStart) / this.props.trimDuration * timelineContentWidth, 0); const top = (d.level / maxLevel) * this.timelineContentHeight(); const timespan = end - start; - const width = (timespan / this.props.trimDuration) * timelineContentWidth; + let width = (timespan / this.props.trimDuration) * timelineContentWidth; + width = (!this.props.trimming && left == 0) ? + width - ((this.trimStart - start) / this.props.trimDuration * timelineContentWidth) : width; + width = (!this.props.trimming && this.trimEnd < end) ? + width - ((end - this.trimEnd) / this.props.trimDuration * timelineContentWidth) : width; const height = this.timelineContentHeight() / maxLevel return this.props.Document.hideAnchors ? null : (
Date: Sun, 12 Sep 2021 12:31:19 -0400 Subject: changed record button --- src/client/views/nodes/AudioBox.scss | 5 +++++ src/client/views/nodes/AudioBox.tsx | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/AudioBox.scss b/src/client/views/nodes/AudioBox.scss index 0b720ef16..93ad7ebcd 100644 --- a/src/client/views/nodes/AudioBox.scss +++ b/src/client/views/nodes/AudioBox.scss @@ -54,6 +54,11 @@ .audiobox-record { pointer-events: none; + color: white; + display: flex; + align-items: center; + justify-content: center; + font-size: $large-header; } .recording { diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx index bcc8e042a..4b1ab9d30 100644 --- a/src/client/views/nodes/AudioBox.tsx +++ b/src/client/views/nodes/AudioBox.tsx @@ -643,12 +643,12 @@ export class AudioBox extends ViewBoxAnnotatableComponent<
) : ( - + )} ) : ( -- cgit v1.2.3-70-g09d2 From 64e265d9cba009469081fdf4ba3272c78a3a76a8 Mon Sep 17 00:00:00 2001 From: mehekj Date: Mon, 20 Sep 2021 22:25:03 -0400 Subject: partially added dragging timeline markers --- .../collections/CollectionStackedTimeline.tsx | 11 +- src/client/views/nodes/AudioBox.scss | 61 ++++------ src/client/views/nodes/AudioBox.tsx | 129 +++++++++++---------- src/client/views/nodes/VideoBox.tsx | 10 ++ 4 files changed, 108 insertions(+), 103 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionStackedTimeline.tsx b/src/client/views/collections/CollectionStackedTimeline.tsx index 8608700aa..0ef6f852a 100644 --- a/src/client/views/collections/CollectionStackedTimeline.tsx +++ b/src/client/views/collections/CollectionStackedTimeline.tsx @@ -354,6 +354,13 @@ export class CollectionStackedTimeline extends CollectionSubView< // 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 x = docDragData.offset[0]; + const timelineContentWidth = this.props.PanelWidth(); + for (let i = 0; i < docDragData.droppedDocuments.length; i++) { + const d = docDragData.droppedDocuments[i]; + d._timecodeToShow = x / timelineContentWidth * this.props.trimDuration + NumCast(d._timecodeToShow); + d._timecodeToHide = x / timelineContentWidth * this.props.trimDuration + NumCast(d._timecodeToHide); + } return true; } @@ -573,14 +580,14 @@ export class CollectionStackedTimeline extends CollectionSubView< const left = this.props.trimming ? (start / this.duration) * timelineContentWidth : Math.max((start - this.trimStart) / this.props.trimDuration * timelineContentWidth, 0); - const top = (d.level / maxLevel) * this.timelineContentHeight(); + const top = (d.level / maxLevel) * this.timelineContentHeight() + 15; const timespan = end - start; let width = (timespan / this.props.trimDuration) * timelineContentWidth; width = (!this.props.trimming && left == 0) ? width - ((this.trimStart - start) / this.props.trimDuration * timelineContentWidth) : width; width = (!this.props.trimming && this.trimEnd < end) ? width - ((end - this.trimEnd) / this.props.trimDuration * timelineContentWidth) : width; - const height = this.timelineContentHeight() / maxLevel + const height = (this.timelineContentHeight()) / maxLevel; return this.props.Document.hideAnchors ? null : (
- (this.layoutDoc.dontAutoPlayFollowedLinks = - !this.layoutDoc.dontAutoPlayFollowedLinks), + (this.layoutDoc.dontAutoPlayFollowedLinks = + !this.layoutDoc.dontAutoPlayFollowedLinks), icon: "expand-arrows-alt", }); funcs.push({ @@ -637,77 +638,77 @@ export class AudioBox extends ViewBoxAnnotatableComponent<
) : ( -
- +
+ RECORD -
- )} +
+ )} ) : ( +
+
-
-
- {" "} - -
-
- -
-
- {this.renderTimeline} -
- {this.audio} -
- {this._trimming ? - formatTime(Math.round(NumCast(this.layoutDoc._currentTimecode))) - : formatTime(Math.round(NumCast(this.layoutDoc._currentTimecode) - NumCast(this._trimStart)))} -
-
- {this._trimming || !this._trimEnd ? - formatTime(Math.round(NumCast(this.duration))) - : formatTime(Math.round(NumCast(this.trimDuration)))} -
+ {" "} + +
+
+ +
+
+ {this.renderTimeline} +
+ {this.audio} +
+ {this._trimming ? + formatTime(Math.round(NumCast(this.layoutDoc._currentTimecode))) + : formatTime(Math.round(NumCast(this.layoutDoc._currentTimecode) - NumCast(this._trimStart)))} +
+
+ {this._trimming || !this._trimEnd ? + formatTime(Math.round(NumCast(this.duration))) + : formatTime(Math.round(NumCast(this.trimDuration)))}
- )} +
+ )}
); } diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx index 90de3227f..7dd82ad13 100644 --- a/src/client/views/nodes/VideoBox.tsx +++ b/src/client/views/nodes/VideoBox.tsx @@ -60,9 +60,17 @@ export class VideoBox extends ViewBoxAnnotatableComponent { this.player && (this.layoutDoc._currentTimecode = this.player.currentTime); + this.layoutDoc.clipEnd = this.layoutDoc.clipEnd ? Math.min(this.duration, NumCast(this.layoutDoc.clipEnd)) : this.duration; + this._trimEnd = this._trimEnd ? Math.min(this.duration, this._trimEnd) : this.duration; try { this._youtubePlayer && (this.layoutDoc._currentTimecode = this._youtubePlayer.getCurrentTime?.()); } catch (e) { -- cgit v1.2.3-70-g09d2 From ad921f6ee14735be136784e90c824632086aa43a Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 22 Sep 2021 13:33:34 -0400 Subject: fixed dragging anchor on audio timeline to position correctly. fixed being able to drop anywhere on audio box. fixed undoing drag anchor and drag handles of audio anchors. --- src/client/views/DocumentDecorations.tsx | 4 +- .../collections/CollectionStackedTimeline.tsx | 49 ++++--- src/client/views/nodes/AudioBox.tsx | 153 +++++++++++---------- 3 files changed, 112 insertions(+), 94 deletions(-) (limited to 'src') diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index d785d5419..29fcee822 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -426,8 +426,8 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number, P const canOpen = SelectionManager.Views().some(docView => !docView.props.Document._stayInCollection && !docView.props.Document.isGroup && !docView.props.Document.hideOpenButton); const canDelete = SelectionManager.Views().some(docView => { const collectionAcl = docView.props.ContainingCollectionView ? GetEffectiveAcl(docView.props.ContainingCollectionDoc?.[DataSym]) : AclEdit; - return (!docView.rootDoc._stayInCollection || docView.rootDoc.isInkMask) && - (collectionAcl === AclAdmin || collectionAcl === AclEdit || GetEffectiveAcl(docView.rootDoc) === AclAdmin); + //return (!docView.rootDoc._stayInCollection || docView.rootDoc.isInkMask) && + return (collectionAcl === AclAdmin || collectionAcl === AclEdit || GetEffectiveAcl(docView.rootDoc) === AclAdmin); }); const topBtn = (key: string, icon: string, pointerDown: undefined | ((e: React.PointerEvent) => void), click: undefined | ((e: any) => void), title: string) => ( {title}
} placement="top"> diff --git a/src/client/views/collections/CollectionStackedTimeline.tsx b/src/client/views/collections/CollectionStackedTimeline.tsx index 9577256c9..970947b12 100644 --- a/src/client/views/collections/CollectionStackedTimeline.tsx +++ b/src/client/views/collections/CollectionStackedTimeline.tsx @@ -30,7 +30,7 @@ import { LinkManager } from "../../util/LinkManager"; import { Scripting } from "../../util/Scripting"; import { SelectionManager } from "../../util/SelectionManager"; import { Transform } from "../../util/Transform"; -import { undoBatch } from "../../util/UndoManager"; +import { undoBatch, UndoManager } from "../../util/UndoManager"; import { AudioWaveform } from "../AudioWaveform"; import { CollectionSubView } from "../collections/CollectionSubView"; import { LightboxView } from "../LightboxView"; @@ -354,12 +354,13 @@ export class CollectionStackedTimeline extends CollectionSubView< // 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 x = docDragData.offset[0]; + const localPt = this.props.ScreenToLocalTransform().transformPoint(de.x, de.y); + const x = localPt[0] - docDragData.offset[0]; const timelineContentWidth = this.props.PanelWidth(); for (let i = 0; i < docDragData.droppedDocuments.length; i++) { - const d = docDragData.droppedDocuments[i]; - d._timecodeToShow = x / timelineContentWidth * this.props.trimDuration + NumCast(d._timecodeToShow); - d._timecodeToHide = x / timelineContentWidth * this.props.trimDuration + NumCast(d._timecodeToHide); + const d = Doc.GetProto(docDragData.droppedDocuments[i]); + d._timecodeToHide = x / timelineContentWidth * this.props.trimDuration + NumCast(d._timecodeToHide) - NumCast(d._timecodeToShow); + d._timecodeToShow = x / timelineContentWidth * this.props.trimDuration; } return true; @@ -774,13 +775,19 @@ class StackedTimelineAnchor extends React.Component } return false; }; + var undo: UndoManager.Batch | undefined; + setupMoveUpEvents( this, e, - (e) => changeAnchor(anchor, left, newTime(e)), + (e) => { + if (!undo) undo = UndoManager.StartBatch("drag anchor"); + return changeAnchor(anchor, left, newTime(e)) + }, (e) => { this.props.setTime(newTime(e)); this.props._timeline?.releasePointerCapture(e.pointerId); + undo?.end(); }, emptyFunction ); @@ -862,21 +869,21 @@ class StackedTimelineAnchor extends React.Component {inner.view} {!inner.anchor.view || !SelectionManager.IsSelected(inner.anchor.view) ? null : ( - <> -
this.onAnchorDown(e, this.props.mark, true)} - /> -
- this.onAnchorDown(e, this.props.mark, false) - } - /> - - )} + <> +
this.onAnchorDown(e, this.props.mark, true)} + /> +
+ this.onAnchorDown(e, this.props.mark, false) + } + /> + + )} ); } diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx index 830c73278..9281cac9a 100644 --- a/src/client/views/nodes/AudioBox.tsx +++ b/src/client/views/nodes/AudioBox.tsx @@ -6,7 +6,7 @@ import { IReactionDisposer, observable, reaction, - runInAction, + runInAction } from "mobx"; import { observer } from "mobx-react"; import { DateField } from "../../../fields/DateField"; @@ -20,19 +20,19 @@ import { emptyFunction, formatTime } from "../../../Utils"; import { DocUtils } from "../../documents/Documents"; import { Networking } from "../../Network"; import { CurrentUserUtils } from "../../util/CurrentUserUtils"; +import { DragManager } from "../../util/DragManager"; import { SnappingManager } from "../../util/SnappingManager"; import { CollectionStackedTimeline } from "../collections/CollectionStackedTimeline"; import { ContextMenu } from "../ContextMenu"; import { ContextMenuProps } from "../ContextMenuItem"; import { ViewBoxAnnotatableComponent, - ViewBoxAnnotatableProps, + ViewBoxAnnotatableProps } from "../DocComponent"; +import { Colors } from "../global/globalEnums"; import "./AudioBox.scss"; import { FieldView, FieldViewProps } from "./FieldView"; import { LinkDocPreview } from "./LinkDocPreview"; -import { faLessThan } from "@fortawesome/free-solid-svg-icons"; -import { Colors } from "../global/globalEnums"; import e = require("connect-flash"); declare class MediaRecorder { @@ -167,11 +167,13 @@ export class AudioBox extends ViewBoxAnnotatableComponent< } componentWillUnmount() { + this.dropDisposer?.(); Object.values(this._disposers).forEach((disposer) => disposer?.()); const ind = DocUtils.ActiveRecordings.indexOf(this); ind !== -1 && DocUtils.ActiveRecordings.splice(ind, 1); } + private dropDisposer?: DragManager.DragDropDisposer; @action componentDidMount() { this.props.setContentView?.(this); // this tells the DocumentView that this AudioBox is the "content" of the document. this allows the DocumentView to indirectly call getAnchor() on the AudioBox when making a link. @@ -337,8 +339,8 @@ export class AudioBox extends ViewBoxAnnotatableComponent< (this.layoutDoc.dontAutoPlayFollowedLinks ? "" : "Don't") + " play when link is selected", event: () => - (this.layoutDoc.dontAutoPlayFollowedLinks = - !this.layoutDoc.dontAutoPlayFollowedLinks), + (this.layoutDoc.dontAutoPlayFollowedLinks = + !this.layoutDoc.dontAutoPlayFollowedLinks), icon: "expand-arrows-alt", }); funcs.push({ @@ -591,6 +593,17 @@ export class AudioBox extends ViewBoxAnnotatableComponent< : ""; return (
{ + if (r && this._stackedTimeline.current) { + this.dropDisposer?.(); + this.dropDisposer = DragManager.MakeDropTarget(r, + (e, de) => { + const [xp, yp] = this.props.ScreenToLocalTransform().transformPoint(de.x, de.y); + de.complete.docDragData && this._stackedTimeline.current!.internalDocDrop(e, de, de.complete.docDragData, xp); + } + , this.layoutDoc, undefined); + } + }} className="audiobox-container" onContextMenu={this.specificContextMenu} onClick={ @@ -607,9 +620,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<
@@ -638,77 +649,77 @@ export class AudioBox extends ViewBoxAnnotatableComponent<
) : ( -
- +
+ RECORD -
- )} +
+ )}
) : ( -
-
+
- {" "} - -
-
- -
-
- {this.renderTimeline} -
- {this.audio} -
- {this._trimming ? - formatTime(Math.round(NumCast(this.layoutDoc._currentTimecode))) - : formatTime(Math.round(NumCast(this.layoutDoc._currentTimecode) - NumCast(this._trimStart)))} -
-
- {this._trimming || !this._trimEnd ? - formatTime(Math.round(NumCast(this.duration))) - : formatTime(Math.round(NumCast(this.trimDuration)))} +
+ {" "} + +
+
+ +
+
+ {this.renderTimeline} +
+ {this.audio} +
+ {this._trimming ? + formatTime(Math.round(NumCast(this.layoutDoc._currentTimecode))) + : formatTime(Math.round(NumCast(this.layoutDoc._currentTimecode) - NumCast(this._trimStart)))} +
+
+ {this._trimming || !this._trimEnd ? + formatTime(Math.round(NumCast(this.duration))) + : formatTime(Math.round(NumCast(this.trimDuration)))} +
-
- )} + )}
); } -- cgit v1.2.3-70-g09d2 From 657c24efd3083bf64e841fa1bb9ccd59ed4a0281 Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 22 Sep 2021 13:57:06 -0400 Subject: fixed up context menu for audio box labels . --- src/client/views/nodes/AudioBox.tsx | 4 ++-- src/client/views/nodes/DocumentView.tsx | 5 +++-- src/client/views/nodes/LabelBox.tsx | 4 ++-- 3 files changed, 7 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx index 9281cac9a..06f1c4ae1 100644 --- a/src/client/views/nodes/AudioBox.tsx +++ b/src/client/views/nodes/AudioBox.tsx @@ -16,7 +16,7 @@ import { makeInterface } from "../../../fields/Schema"; import { ComputedField } from "../../../fields/ScriptField"; import { Cast, NumCast } from "../../../fields/Types"; import { AudioField, nullAudio } from "../../../fields/URLField"; -import { emptyFunction, formatTime } from "../../../Utils"; +import { emptyFunction, formatTime, OmitKeys } from "../../../Utils"; import { DocUtils } from "../../documents/Documents"; import { Networking } from "../../Network"; import { CurrentUserUtils } from "../../util/CurrentUserUtils"; @@ -548,7 +548,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent< return ( this.Document.followLinkZoom = !this.Document.followLinkZoom, icon: this.Document.ignoreClick ? "unlock" : "lock" }); + this.props.CollectionFreeFormDocumentView && onClicks.push({ description: (this.Document.followLinkZoom ? "Don't" : "") + " zoom following link", event: () => this.Document.followLinkZoom = !this.Document.followLinkZoom, icon: this.Document.ignoreClick ? "unlock" : "lock" }); if (!this.Document.annotationOn) { const options = cm.findByDescription("Options..."); @@ -788,6 +788,7 @@ export class DocumentViewInternal extends DocComponent { const funcs: ContextMenuProps[] = []; - funcs.push({ + !Doc.UserDoc().noviceMode && funcs.push({ description: "Clear Script Params", event: () => { const params = Cast(this.paramsDoc["onClick-paramFieldKeys"], listSpec("string"), []); params?.map(p => this.paramsDoc[p] = undefined); }, icon: "trash" }); - ContextMenu.Instance.addItem({ description: "OnClick...", noexpand: true, subitems: funcs, icon: "mouse-pointer" }); + funcs.length && ContextMenu.Instance.addItem({ description: "OnClick...", noexpand: true, subitems: funcs, icon: "mouse-pointer" }); } @undoBatch -- cgit v1.2.3-70-g09d2 From bafc47fe100002e37c7abcada3dc44f3bfb66f62 Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 23 Sep 2021 11:16:53 -0400 Subject: a bunch of fixes to audio timelines to support undoing clips, simplifying audioWaveform and having it recompute when a clip is made. --- src/client/views/AudioWaveform.tsx | 117 ++++++++------------- .../collections/CollectionStackedTimeline.tsx | 16 ++- src/client/views/nodes/AudioBox.tsx | 59 ++++++----- src/client/views/nodes/VideoBox.tsx | 12 ++- 4 files changed, 91 insertions(+), 113 deletions(-) (limited to 'src') diff --git a/src/client/views/AudioWaveform.tsx b/src/client/views/AudioWaveform.tsx index 8f3b7c2cd..1e676e1f0 100644 --- a/src/client/views/AudioWaveform.tsx +++ b/src/client/views/AudioWaveform.tsx @@ -1,6 +1,6 @@ import React = require("react"); import axios from "axios"; -import { action, computed } from "mobx"; +import { action, computed, reaction, IReactionDisposer } from "mobx"; import { observer } from "mobx-react"; import Waveform from "react-audio-waveform"; import { Doc } from "../../fields/Doc"; @@ -12,7 +12,8 @@ import "./AudioWaveform.scss"; import { Colors } from "./global/globalEnums"; export interface AudioWaveformProps { - duration: number; + duration: number; // length of media clip + rawDuration: number; // length of underlying media data mediaPath: string; layoutDoc: Doc; trimming: boolean; @@ -22,19 +23,28 @@ export interface AudioWaveformProps { @observer export class AudioWaveform extends React.Component { public static NUMBER_OF_BUCKETS = 100; + _disposer: IReactionDisposer | undefined; @computed get _waveHeight() { return Math.max(50, this.props.PanelHeight()); } + + @computed get clipStart() { return NumCast(this.props.layoutDoc.clipStart); } + @computed get clipEnd() { return NumCast(this.props.layoutDoc.clipEnd, this.props.rawDuration); } + @computed get audioBuckets() { return Cast(this.props.layoutDoc.audioBuckets, listSpec("number"), []); } + @computed get audioBucketRange() { return Cast(this.props.layoutDoc.audioBucketRange, listSpec("number"), [-1, -1]); } + componentWillUnmount() { + this._disposer?.(); + } componentDidMount() { - const audioBuckets = Cast( - this.props.layoutDoc.audioBuckets, - listSpec("number"), - [] - ); - if (!audioBuckets.length) { - this.props.layoutDoc.audioBuckets = new List([0, 0]); /// "lock" to prevent other views from computing the same data - setTimeout(this.createWaveformBuckets); - } + this._disposer = reaction(() => [this.clipStart, this.clipEnd, this.audioBuckets.length, ...this.audioBucketRange], + (range) => { + if (range[2] !== AudioWaveform.NUMBER_OF_BUCKETS || range[3] !== range[0] || range[4] !== range[1]) { + this.props.layoutDoc.audioBucketRange = new List([range[0], range[1]]); // setting these values here serves as a "lock" to prevent multiple attempts to create the waveform at nearly the same time. + this.props.layoutDoc.audioBuckets = new List(numberRange(AudioWaveform.NUMBER_OF_BUCKETS)); + setTimeout(this.createWaveformBuckets); + } + }, { fireImmediately: true }); + } // decodes the audio file into peaks for generating the waveform @@ -45,81 +55,44 @@ export class AudioWaveform extends React.Component { context.decodeAudioData( response.data, action((buffer) => { - const decodedAudioData = buffer.getChannelData(0); + const rawDecodedAudioData = buffer.getChannelData(0); + const startInd = this.clipStart / this.props.rawDuration; + const endInd = this.clipEnd / this.props.rawDuration; + const decodedAudioData = rawDecodedAudioData.slice(Math.floor(startInd * rawDecodedAudioData.length), Math.floor(endInd * rawDecodedAudioData.length)); const bucketDataSize = Math.floor( decodedAudioData.length / AudioWaveform.NUMBER_OF_BUCKETS ); const brange = Array.from(Array(bucketDataSize)); - this.props.layoutDoc.audioBuckets = new List( - numberRange(AudioWaveform.NUMBER_OF_BUCKETS).map( - (i: number) => - brange.reduce( - (p, x, j) => - Math.abs( - Math.max(p, decodedAudioData[i * bucketDataSize + j]) - ), - 0 - ) / 2 - ) + const bucketList = numberRange(AudioWaveform.NUMBER_OF_BUCKETS).map( + (i: number) => + brange.reduce( + (p, x, j) => + Math.abs( + Math.max(p, decodedAudioData[i * bucketDataSize + j]) + ), + 0 + ) / 2 ); + this.props.layoutDoc.audioBucketRange = new List([this.clipStart, this.clipEnd]); + this.props.layoutDoc.audioBuckets = new List(bucketList); }) ); } ); } - - @action - createTrimBuckets = () => { - const audioBuckets = Cast( - this.props.layoutDoc.audioBuckets, - listSpec("number"), - [] - ); - - const start = Math.floor( - (NumCast(this.props.layoutDoc.clipStart) / this.props.duration) * 100 - ); - const end = Math.floor( - (NumCast(this.props.layoutDoc.clipEnd) / this.props.duration) * 100 - ); - return audioBuckets.slice(start, end); - } - render() { - const audioBuckets = Cast( - this.props.layoutDoc.audioBuckets, - listSpec("number"), - [] - ); - return (
- {this.props.trimming || !this.props.layoutDoc.clipEnd ? ( - - ) : ( - - )} +
); } diff --git a/src/client/views/collections/CollectionStackedTimeline.tsx b/src/client/views/collections/CollectionStackedTimeline.tsx index 970947b12..0985e5b2e 100644 --- a/src/client/views/collections/CollectionStackedTimeline.tsx +++ b/src/client/views/collections/CollectionStackedTimeline.tsx @@ -61,9 +61,10 @@ export type CollectionStackedTimelineProps = { endTag: string; mediaPath: string; dictationKey: string; + rawDuration: number; trimming: boolean; - trimStart: number; - trimEnd: number; + trimStart: () => number; + trimEnd: () => number; trimDuration: number; setStartTrim: (newStart: number) => void; setEndTrim: (newEnd: number) => void; @@ -94,11 +95,11 @@ export class CollectionStackedTimeline extends CollectionSubView< } get trimStart() { - return this.props.trimStart; + return this.props.trimStart(); } get trimEnd() { - return this.props.trimEnd; + return this.props.trimEnd(); } get duration() { @@ -540,6 +541,7 @@ export class CollectionStackedTimeline extends CollectionSubView< return !this.props.mediaPath ? null : (
= this.layoutDoc._height; @observable _paused: boolean = false; @observable _trimming: boolean = false; - @observable _trimStart: number = NumCast(this.layoutDoc.clipStart) ? NumCast(this.layoutDoc.clipStart) : 0; - @observable _trimEnd: number = NumCast(this.layoutDoc.clipEnd) ? NumCast(this.layoutDoc.clipEnd) - : this.duration; + @observable _trimStart: number = NumCast(this.layoutDoc.clipStart); + @observable _trimEnd: number = NumCast(this.layoutDoc.clipEnd, this.duration); + @computed get trimStart() { return this._trimming ? this._trimStart : NumCast(this.layoutDoc.clipStart); } + @computed get trimEnd() { return this._trimming ? this._trimEnd : NumCast(this.layoutDoc.clipEnd, this.duration); } @computed get mediaState(): | undefined @@ -84,7 +86,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent< | "recording" | "paused" | "playing" { - return this.dataDoc.mediaState as + return this.layoutDoc.mediaState as | undefined | "pendingRecording" | "recording" @@ -92,7 +94,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent< | "playing"; } set mediaState(value) { - this.dataDoc.mediaState = value; + this.layoutDoc.mediaState = value; } public static SetScrubTime = action((timeInMillisFrom1970: number) => { AudioBox._scrubTime = 0; @@ -104,11 +106,15 @@ export class AudioBox extends ViewBoxAnnotatableComponent< DateField )?.date.getTime(); } - @computed get duration() { + @computed get rawDuration() { return NumCast(this.dataDoc[`${this.fieldKey}-duration`]); } + @computed get duration() { + return NumCast(this.layoutDoc.clipEnd, NumCast(this.layoutDoc.clipStart) + NumCast(this.dataDoc[`${this.fieldKey}-duration`])) - NumCast(this.layoutDoc.clipStart); + // NumCast(this.dataDoc[`${this.fieldKey}-duration`]); + } @computed get trimDuration() { - return this._trimming && this._trimEnd ? this.duration : this._trimEnd - this._trimStart; + return this.trimEnd - this.trimStart; } @computed get anchorDocs() { return DocListCast(this.dataDoc[this.annotationKey]); @@ -228,8 +234,6 @@ export class AudioBox extends ViewBoxAnnotatableComponent< runInAction( () => (this.dataDoc[this.fieldKey + "-duration"] = htmlEle.duration) ); - this.layoutDoc.clipEnd = this.layoutDoc.clipEnd ? Math.min(this.duration, NumCast(this.layoutDoc.clipEnd)) : this.duration; - this._trimEnd = this._trimEnd ? Math.min(this.duration, this._trimEnd) : this.duration; this.links .map((l) => this.getLinkData(l)) .forEach(({ la1, la2, linkTime }) => { @@ -259,7 +263,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent< // play back the audio from time @action - playFrom = (seekTimeInSeconds: number, endTime: number = this._trimEnd, fullPlay: boolean = false) => { + playFrom = (seekTimeInSeconds: number, endTime: number = this.trimEnd, fullPlay: boolean = false) => { clearTimeout(this._play); if (Number.isNaN(this._ele?.duration)) { setTimeout(() => this.playFrom(seekTimeInSeconds, endTime), 500); @@ -270,9 +274,9 @@ export class AudioBox extends ViewBoxAnnotatableComponent< } else { this.Pause(); } - } else if (this._trimStart <= endTime && seekTimeInSeconds <= this._trimEnd) { - const start = Math.max(this._trimStart, seekTimeInSeconds); - const end = Math.min(this._trimEnd, endTime); + } else if (this.trimStart <= endTime && seekTimeInSeconds <= this.trimEnd) { + const start = Math.max(this.trimStart, seekTimeInSeconds); + const end = Math.min(this.trimEnd, endTime); this._ele.currentTime = start; this._ele.play(); runInAction(() => (this.mediaState = "playing")); @@ -385,14 +389,14 @@ export class AudioBox extends ViewBoxAnnotatableComponent< Play = (e?: any) => { let start; if (this._ended || this._ele!.currentTime === this.duration) { - start = this._trimStart; + start = NumCast(this.layoutDoc.clipStart); this._ended = false; } else { start = this._ele!.currentTime; } - this.playFrom(start, this._trimEnd, true); + this.playFrom(start, this.trimEnd, true); e?.stopPropagation?.(); } @@ -502,16 +506,16 @@ export class AudioBox extends ViewBoxAnnotatableComponent< } // hides trim controls and displays new clip - @action - finishTrim = () => { + @undoBatch + finishTrim = action(() => { if (this.mediaState === "playing") { this.Pause(); } - this.layoutDoc.clipStart = this._trimStart; - this.layoutDoc.clipEnd = this._trimEnd; + this.layoutDoc.clipStart = this.trimStart; + this.layoutDoc.clipEnd = this.trimEnd; + this.setAnchorTime(Math.max(Math.min(this.trimEnd, this._ele!.currentTime), this.trimStart)); this._trimming = false; - this.setAnchorTime(Math.max(Math.min(this._trimEnd, this._ele!.currentTime), this._trimStart)); - } + }); @action setStartTrim = (newStart: number) => { @@ -544,6 +548,8 @@ export class AudioBox extends ViewBoxAnnotatableComponent< this.heightPercent) / 100 // panelHeight * heightPercent is player height. * heightPercent is timeline height (as per css inline) timelineWidth = () => this.props.PanelWidth() - AudioBox.playheadWidth; + trimEndFunc = () => this.trimEnd; + trimStartFunc = () => this.trimStart; @computed get renderTimeline() { return ( {this._trimming ? formatTime(Math.round(NumCast(this.layoutDoc._currentTimecode))) - : formatTime(Math.round(NumCast(this.layoutDoc._currentTimecode) - NumCast(this._trimStart)))} + : formatTime(Math.round(NumCast(this.layoutDoc._currentTimecode) - NumCast(this.trimStart)))}
{this._trimming || !this._trimEnd ? diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx index 3fc460102..84eeacc29 100644 --- a/src/client/views/nodes/VideoBox.tsx +++ b/src/client/views/nodes/VideoBox.tsx @@ -9,7 +9,7 @@ import { InkTool } from "../../../fields/InkField"; import { makeInterface } from "../../../fields/Schema"; import { Cast, NumCast, StrCast } from "../../../fields/Types"; import { AudioField, nullAudio, VideoField } from "../../../fields/URLField"; -import { emptyFunction, formatTime, OmitKeys, returnOne, setupMoveUpEvents, Utils, returnFalse } from "../../../Utils"; +import { emptyFunction, formatTime, OmitKeys, returnOne, setupMoveUpEvents, Utils, returnFalse, returnZero } from "../../../Utils"; import { Docs, DocUtils } from "../../documents/Documents"; import { Networking } from "../../Network"; import { CurrentUserUtils } from "../../util/CurrentUserUtils"; @@ -526,6 +526,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent this.props.ScreenToLocalTransform().scale(this.scaling()).translate(0, -this.heightPercent / 100 * this.props.PanelHeight()); setAnchorTime = (time: number) => this.player!.currentTime = this.layoutDoc._currentTimecode = time; timelineHeight = () => this.props.PanelHeight() * (100 - this.heightPercent) / 100; + trimEndFunc = () => this.duration; @computed get renderTimeline() { return
{ }} - setEndTrim={() => { }} + setStartTrim={emptyFunction} + setEndTrim={emptyFunction} />
; } -- cgit v1.2.3-70-g09d2 From 802840c0e23bf4fcdcdf9ec262c45b09525be813 Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 23 Sep 2021 20:53:56 -0400 Subject: fixed getting duration of audioclip and setting trimEnd the first time. --- src/client/views/nodes/AudioBox.tsx | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx index 538d7d5cb..bde1a3d72 100644 --- a/src/client/views/nodes/AudioBox.tsx +++ b/src/client/views/nodes/AudioBox.tsx @@ -76,9 +76,11 @@ export class AudioBox extends ViewBoxAnnotatableComponent< @observable _paused: boolean = false; @observable _trimming: boolean = false; @observable _trimStart: number = NumCast(this.layoutDoc.clipStart); - @observable _trimEnd: number = NumCast(this.layoutDoc.clipEnd, this.duration); + @observable _trimEnd: number | undefined = Cast(this.layoutDoc.clipEnd, "number"); @computed get trimStart() { return this._trimming ? this._trimStart : NumCast(this.layoutDoc.clipStart); } - @computed get trimEnd() { return this._trimming ? this._trimEnd : NumCast(this.layoutDoc.clipEnd, this.duration); } + @computed get trimEnd() { + return this._trimming && this._trimEnd !== undefined ? this._trimEnd : NumCast(this.layoutDoc.clipEnd, this.duration); + } @computed get mediaState(): | undefined @@ -132,13 +134,6 @@ export class AudioBox extends ViewBoxAnnotatableComponent< constructor(props: Readonly) { super(props); AudioBox.Instance = this; - - if (this.duration === undefined) { - runInAction( - () => - (this.Document[this.fieldKey + "-duration"] = this.Document.duration) - ); - } } getLinkData(l: Doc) { @@ -229,11 +224,6 @@ export class AudioBox extends ViewBoxAnnotatableComponent< timecodeChanged = () => { const htmlEle = this._ele; if (this.mediaState !== "recording" && htmlEle) { - htmlEle.duration && - htmlEle.duration !== Infinity && - runInAction( - () => (this.dataDoc[this.fieldKey + "-duration"] = htmlEle.duration) - ); this.links .map((l) => this.getLinkData(l)) .forEach(({ la1, la2, linkTime }) => { @@ -320,6 +310,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent< const [{ result }] = await Networking.UploadFilesToServer(e.data); if (!(result instanceof Error)) { this.props.Document[this.props.fieldKey] = new AudioField(result.accessPaths.agnostic.client); + if (this._trimEnd === undefined) this._trimEnd = this.duration; } }; this._recordStart = new Date().getTime(); @@ -438,7 +429,16 @@ export class AudioBox extends ViewBoxAnnotatableComponent< // returns the html audio element @computed get audio() { - return