diff options
| author | bobzel <zzzman@gmail.com> | 2023-05-22 11:25:32 -0400 |
|---|---|---|
| committer | bobzel <zzzman@gmail.com> | 2023-05-22 11:25:32 -0400 |
| commit | bed3309e1fda6597b2a8fea10ad82cd3a0402051 (patch) | |
| tree | fe599bbdc5fca2c221e1e0f7a60995b7cd39f870 /src/client/views/nodes/AudioBox.tsx | |
| parent | 887a4f7e0fc25fde87b20a5de2e7b0aee561cc78 (diff) | |
| parent | 3d26d5b2654841a9b92f3d66b28d1dc8e36cca6a (diff) | |
merged physics with master
Diffstat (limited to 'src/client/views/nodes/AudioBox.tsx')
| -rw-r--r-- | src/client/views/nodes/AudioBox.tsx | 109 |
1 files changed, 57 insertions, 52 deletions
diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx index 1d59d3356..0cb849923 100644 --- a/src/client/views/nodes/AudioBox.tsx +++ b/src/client/views/nodes/AudioBox.tsx @@ -7,10 +7,11 @@ import { Doc, DocListCast } from '../../../fields/Doc'; import { ComputedField } from '../../../fields/ScriptField'; import { Cast, DateCast, NumCast } from '../../../fields/Types'; import { AudioField, nullAudio } from '../../../fields/URLField'; -import { emptyFunction, formatTime, OmitKeys, returnFalse, setupMoveUpEvents } from '../../../Utils'; +import { emptyFunction, formatTime, returnFalse, setupMoveUpEvents } from '../../../Utils'; import { DocUtils } from '../../documents/Documents'; import { Networking } from '../../Network'; import { DragManager } from '../../util/DragManager'; +import { LinkManager } from '../../util/LinkManager'; import { undoBatch } from '../../util/UndoManager'; import { CollectionStackedTimeline, TrimScope } from '../collections/CollectionStackedTimeline'; import { ContextMenu } from '../ContextMenu'; @@ -18,6 +19,7 @@ import { ContextMenuProps } from '../ContextMenuItem'; import { ViewBoxAnnotatableComponent, ViewBoxAnnotatableProps } from '../DocComponent'; import './AudioBox.scss'; import { FieldView, FieldViewProps } from './FieldView'; +import { PinProps, PresBox } from './trails'; /** * AudioBox @@ -37,7 +39,7 @@ declare class MediaRecorder { constructor(e: any); // whatever MediaRecorder has } -enum media_state { +export enum media_state { PendingRecording = 'pendingRecording', Recording = 'recording', Paused = 'paused', @@ -70,17 +72,11 @@ export class AudioBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp @observable _muted: boolean = false; @observable _paused: boolean = false; // is recording paused // @observable rawDuration: number = 0; // computed from the length of the audio element when loaded - - constructor(props: any) { - super(props); - this.props.setContentView?.(this); - } - @computed get recordingStart() { return DateCast(this.dataDoc[this.fieldKey + '-recordingStart'])?.date.getTime(); } @computed get rawDuration() { - return NumCast(this.dataDoc[`${this.fieldKey}-duration`]); + return NumCast(this.dataDoc[`${this.fieldKey}_duration`]); } // bcz: shouldn't be needed since it's computed from audio element // mehek: not 100% sure but i think due to the order in which things are loaded this is necessary ^^ // if you get rid of it and set the value to 0 the timeline and waveform will set their bounds incorrectly @@ -89,7 +85,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp return this.props.PanelHeight() < 50; } // used to collapse timeline when node is shrunk @computed get links() { - return DocListCast(this.dataDoc.links); + return LinkManager.Links(this.dataDoc); } @computed get mediaState() { return this.dataDoc.mediaState as media_state; @@ -117,6 +113,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp @action componentDidMount() { + this.props.setContentView?.(this); if (this.path) { this.mediaState = media_state.Paused; this.setPlayheadTime(NumCast(this.layoutDoc.clipStart)); @@ -126,30 +123,29 @@ export class AudioBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp } getLinkData(l: Doc) { - let la1 = l.anchor1 as Doc; - let la2 = l.anchor2 as Doc; + let la1 = l.link_anchor_1 as Doc; + let la2 = l.link_anchor_2 as Doc; const linkTime = this.timeline?.anchorStart(la2) || this.timeline?.anchorStart(la1) || 0; if (Doc.AreProtosEqual(la1, this.dataDoc)) { - la1 = l.anchor2 as Doc; - la2 = l.anchor1 as Doc; + la1 = l.link_anchor_2 as Doc; + la2 = l.link_anchor_1 as Doc; } return { la1, la2, linkTime }; } - getAnchor = (addAsAnnotation: boolean) => { - return ( + getAnchor = (addAsAnnotation: boolean, pinProps?: PinProps) => { + const anchor = CollectionStackedTimeline.createAnchor( this.rootDoc, this.dataDoc, this.annotationKey, - '_timecodeToShow' /* audioStart */, - '_timecodeToHide' /* audioEnd */, - this._ele?.currentTime || Cast(this.props.Document._currentTimecode, 'number', null) || (this.mediaState === media_state.Recording ? (Date.now() - (this.recordingStart || 0)) / 1000 : undefined), + this._ele?.currentTime || Cast(this.props.Document._layout_currentTimecode, 'number', null) || (this.mediaState === media_state.Recording ? (Date.now() - (this.recordingStart || 0)) / 1000 : undefined), undefined, undefined, addAsAnnotation - ) || this.rootDoc - ); + ) || this.rootDoc; + PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), temporal: true } }, this.rootDoc); + return anchor; }; // updates timecode and shows it in timeline, follows links at time @@ -159,12 +155,12 @@ export class AudioBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp this.links .map(l => this.getLinkData(l)) .forEach(({ la1, la2, linkTime }) => { - if (linkTime > NumCast(this.layoutDoc._currentTimecode) && linkTime < this._ele!.currentTime) { + if (linkTime > NumCast(this.layoutDoc._layout_currentTimecode) && linkTime < this._ele!.currentTime) { Doc.linkFollowHighlight(la1); } }); - this.layoutDoc._currentTimecode = this._ele.currentTime; - this.timeline?.scrollToTime(NumCast(this.layoutDoc._currentTimecode)); + this.layoutDoc._layout_currentTimecode = this._ele.currentTime; + this.timeline?.scrollToTime(NumCast(this.layoutDoc._layout_currentTimecode)); } }; @@ -201,8 +197,9 @@ export class AudioBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp // removes from currently playing display @action removeCurrentlyPlaying = () => { - if (CollectionStackedTimeline.CurrentlyPlaying) { - const index = CollectionStackedTimeline.CurrentlyPlaying.indexOf(this.layoutDoc); + const docView = this.props.DocumentView?.(); + if (CollectionStackedTimeline.CurrentlyPlaying && docView) { + const index = CollectionStackedTimeline.CurrentlyPlaying.indexOf(docView); index !== -1 && CollectionStackedTimeline.CurrentlyPlaying.splice(index, 1); } }; @@ -210,11 +207,12 @@ export class AudioBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp // adds doc to currently playing display @action addCurrentlyPlaying = () => { + const docView = this.props.DocumentView?.(); if (!CollectionStackedTimeline.CurrentlyPlaying) { CollectionStackedTimeline.CurrentlyPlaying = []; } - if (CollectionStackedTimeline.CurrentlyPlaying.indexOf(this.layoutDoc) === -1) { - CollectionStackedTimeline.CurrentlyPlaying.push(this.layoutDoc); + if (docView && CollectionStackedTimeline.CurrentlyPlaying.indexOf(docView) === -1) { + CollectionStackedTimeline.CurrentlyPlaying.push(docView); } }; @@ -223,7 +221,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp if (this.mediaState === media_state.Recording) { setTimeout(this.updateRecordTime, 30); if (!this._paused) { - this.layoutDoc._currentTimecode = (new Date().getTime() - this._recordStart - this._pausedTime) / 1000; + this.layoutDoc._layout_currentTimecode = (new Date().getTime() - this._recordStart - this._pausedTime) / 1000; } } }; @@ -255,7 +253,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp this._recorder = undefined; const now = new Date().getTime(); this._paused && (this._pausedTime += now - this._pauseStart); - this.dataDoc[this.fieldKey + '-duration'] = (now - this._recordStart - this._pausedTime) / 1000; + this.dataDoc[this.fieldKey + '_duration'] = (now - this._recordStart - this._pausedTime) / 1000; this.mediaState = media_state.Paused; this._stream?.getAudioTracks()[0].stop(); const ind = DocUtils.ActiveRecordings.indexOf(this); @@ -329,18 +327,28 @@ export class AudioBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp } }; - // pause play back + IsPlaying = () => this.mediaState === media_state.Playing; + TogglePause = () => { + if (this.mediaState === media_state.Paused) this.Play(); + else this.pause(); + }; + // pause playback without removing from the playback list to allow user to play it again. @action - Pause = () => { + pause = () => { if (this._ele) { this._ele.pause(); this.mediaState = media_state.Paused; // if paused in the middle of playback, prevents restart on next play if (!this._finished) clearTimeout(this._play); - this.removeCurrentlyPlaying(); } }; + // pause playback and remove from playback list + @action + Pause = () => { + this.pause(); + this.removeCurrentlyPlaying(); + }; // for dictation button, creates a text document for dictation onFile = (e: any) => { @@ -354,10 +362,10 @@ export class AudioBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp Doc.GetProto(newDoc).recordingSource = this.dataDoc; Doc.GetProto(newDoc).recordingStart = ComputedField.MakeFunction(`self.recordingSource["${this.fieldKey}-recordingStart"]`); Doc.GetProto(newDoc).mediaState = ComputedField.MakeFunction('self.recordingSource.mediaState'); - if (DocListCast(Doc.MyOverlayDocs?.data).includes(this.rootDoc)) { + if (Doc.IsInMyOverlay(this.rootDoc)) { newDoc.overlayX = this.rootDoc.x; newDoc.overlayY = NumCast(this.rootDoc.y) + NumCast(this.rootDoc._height); - Doc.AddDocToList(Doc.MyOverlayDocs, undefined, newDoc); + Doc.AddToMyOverlay(newDoc); } else { this.props.addDocument?.(newDoc); } @@ -414,11 +422,11 @@ export class AudioBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp if (!this.layoutDoc.dontAutoPlayFollowedLinks) { this.playFrom(this.timeline?.anchorStart(link) || 0, this.timeline?.anchorEnd(link)); } else { - this._ele!.currentTime = this.layoutDoc._currentTimecode = this.timeline?.anchorStart(link) || 0; + this._ele!.currentTime = this.layoutDoc._layout_currentTimecode = this.timeline?.anchorStart(link) || 0; } } else { this.links - .filter(l => l.anchor1 === link || l.anchor2 === link) + .filter(l => l.link_anchor_1 === link || l.link_anchor_2 === link) .forEach(l => { const { la1, la2 } = this.getLinkData(l); const startTime = this.timeline?.anchorStart(la1) || this.timeline?.anchorStart(la2); @@ -427,7 +435,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp if (!this.layoutDoc.dontAutoPlayFollowedLinks) { this.playFrom(startTime, endTime); } else { - this._ele!.currentTime = this.layoutDoc._currentTimecode = startTime; + this._ele!.currentTime = this.layoutDoc._layout_currentTimecode = startTime; } } }); @@ -437,9 +445,9 @@ export class AudioBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp @action timelineWhenChildContentsActiveChanged = (isActive: boolean) => this.props.whenChildContentsActiveChanged((this._isAnyChildContentActive = isActive)); - timelineScreenToLocal = () => this.props.ScreenToLocalTransform().translate(0, -AudioBox.bottomControlsHeight); + timelineScreenToLocal = () => this.props.ScreenToLocalTransform().translate(0, -AudioBox.topControlsHeight); - setPlayheadTime = (time: number) => (this._ele!.currentTime = this.layoutDoc._currentTimecode = time); + setPlayheadTime = (time: number) => (this._ele!.currentTime /*= this.layoutDoc._layout_currentTimecode*/ = time); playing = () => this.mediaState === media_state.Playing; @@ -539,7 +547,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp <div className="record-button" onPointerDown={this._paused ? this.recordPlay : this.recordPause}> <FontAwesomeIcon size="2x" icon={this._paused ? 'play' : 'pause'} /> </div> - <div className="record-timecode">{formatTime(Math.round(NumCast(this.layoutDoc._currentTimecode)))}</div> + <div className="record-timecode">{formatTime(Math.round(NumCast(this.layoutDoc._layout_currentTimecode)))}</div> </div> ) : ( <div className="audiobox-start-record" onPointerDown={this.Record}> @@ -615,7 +623,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp {this.audio} <div className="audiobox-timecodes"> - <div className="timecode-current">{this.timeline && formatTime(Math.round(NumCast(this.layoutDoc._currentTimecode) - NumCast(this.timeline.clipStart)))}</div> + <div className="timecode-current">{this.timeline && formatTime(Math.round(NumCast(this.layoutDoc._layout_currentTimecode) - NumCast(this.timeline.clipStart)))}</div> {this.miniPlayer ? ( <div>/</div> ) : ( @@ -626,15 +634,11 @@ export class AudioBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp step="0.1" min="1" max="5" - value={this.timeline?._zoomFactor} + value={this.timeline?._zoomFactor ?? 1} className="toolbar-slider" id="zoom-slider" - onPointerDown={(e: React.PointerEvent) => { - e.stopPropagation(); - }} - onChange={(e: React.ChangeEvent<HTMLInputElement>) => { - this.zoom(Number(e.target.value)); - }} + onPointerDown={(e: React.PointerEvent) => e.stopPropagation()} + onChange={(e: React.ChangeEvent<HTMLInputElement>) => this.zoom(Number(e.target.value))} /> </div> )} @@ -650,7 +654,9 @@ export class AudioBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp return ( <CollectionStackedTimeline ref={action((r: any) => (this._stackedTimeline = r))} - {...OmitKeys(this.props, ['CollectionFreeFormDocumentView']).omit} + {...this.props} + CollectionFreeFormDocumentView={undefined} + dataFieldKey={this.fieldKey} fieldKey={this.annotationKey} dictationKey={this.fieldKey + '-dictation'} mediaPath={this.path} @@ -658,7 +664,6 @@ export class AudioBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp startTag={'_timecodeToShow' /* audioStart */} endTag={'_timecodeToHide' /* audioEnd */} bringToFront={emptyFunction} - CollectionView={undefined} playFrom={this.playFrom} setTime={this.setPlayheadTime} playing={this.playing} @@ -685,7 +690,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp <audio ref={this.setRef} className={`audiobox-control${this.props.isContentActive() ? '-interactive' : ''}`} - onLoadedData={action(e => this._ele?.duration && this._ele?.duration !== Infinity && (this.dataDoc[this.fieldKey + '-duration'] = this._ele.duration))}> + onLoadedData={action(e => this._ele?.duration && this._ele?.duration !== Infinity && (this.dataDoc[this.fieldKey + '_duration'] = this._ele.duration))}> <source src={this.path} type="audio/mpeg" /> Not supported. </audio> |
