diff options
author | bobzel <zzzman@gmail.com> | 2021-09-25 22:01:10 -0400 |
---|---|---|
committer | bobzel <zzzman@gmail.com> | 2021-09-25 22:01:10 -0400 |
commit | 9dd7cb1cffdc436d1ac47ab1c6f67c2c88be2718 (patch) | |
tree | b1de62819fc76280936fc46ca59739b63063f383 /src | |
parent | 86f4560fb9624ee59f1a8143457c9ea80f32eb98 (diff) |
more cleanup/refactoring.
Diffstat (limited to 'src')
-rw-r--r-- | src/client/views/nodes/AudioBox.scss | 14 | ||||
-rw-r--r-- | src/client/views/nodes/AudioBox.tsx | 267 | ||||
-rw-r--r-- | src/client/views/nodes/VideoBox.tsx | 16 | ||||
-rw-r--r-- | src/client/views/nodes/trails/PresBox.tsx | 19 |
4 files changed, 117 insertions, 199 deletions
diff --git a/src/client/views/nodes/AudioBox.scss b/src/client/views/nodes/AudioBox.scss index 6adda4730..b33c7f506 100644 --- a/src/client/views/nodes/AudioBox.scss +++ b/src/client/views/nodes/AudioBox.scss @@ -41,11 +41,11 @@ } .audiobox-control-interactive { - pointer-events: all; + pointer-events: all; } .audiobox-record-interactive, - .audiobox-record { + .audiobox-record { pointer-events: all; cursor: pointer; width: 100%; @@ -58,11 +58,12 @@ gap: 10px; color: white; font-weight: bold; - } + background-color: $dark-gray; + } - .audiobox-record { + .audiobox-record { pointer-events: none; - } + } .recording { margin-top: auto; @@ -241,6 +242,9 @@ .audiobox-timeline { position: absolute; + top: 0; + background: white; + height: 100%; width: 100%; z-index: 1000; overflow: hidden; diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx index e66003f88..6e6558030 100644 --- a/src/client/views/nodes/AudioBox.tsx +++ b/src/client/views/nodes/AudioBox.tsx @@ -23,7 +23,6 @@ import { Colors } from "../global/globalEnums"; import "./AudioBox.scss"; import { FieldView, FieldViewProps } from "./FieldView"; import { LinkDocPreview } from "./LinkDocPreview"; -import e = require("connect-flash"); declare class MediaRecorder { constructor(e: any); // whatever MediaRecorder has @@ -44,6 +43,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp public static Enabled = false; static playheadWidth = 40; // width of playhead static heightPercent = 75; // height of timeline in percent of height of audioBox. + @observable static _scrubTime = 0; _dropDisposer?: DragManager.DragDropDisposer; _disposers: { [name: string]: IReactionDisposer } = {}; @@ -57,7 +57,6 @@ export class AudioBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp _stream: MediaStream | undefined; _play: any = null; - @observable static _scrubTime = 0; @observable _paused: boolean = false; @computed get recordingStart() { return DateCast(this.dataDoc[this.fieldKey + "-recordingStart"])?.date.getTime(); } @computed get rawDuration() { return NumCast(this.dataDoc[`${this.fieldKey}-duration`]); } @@ -116,33 +115,6 @@ export class AudioBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp this.path && this.setAnchorTime(NumCast(this.layoutDoc.clipStart)); this.path && this.timecodeChanged(); - - this._disposers.triggerAudio = reaction( - () => !LinkDocPreview.LinkInfo && this.props.renderDepth !== -1 - ? NumCast(this.Document._triggerAudio, null) - : undefined, - (start) => - start !== undefined && setTimeout(() => { - this.playFrom(start); - setTimeout(() => { - this.Document._currentTimecode = start; - this.Document._triggerAudio = undefined; - }, 10); - }), // wait for mainCont and try again to play - { fireImmediately: true } - ); - - this._disposers.audioStop = reaction( - () => this.props.renderDepth !== -1 && !LinkDocPreview.LinkInfo - ? Cast(this.Document._audioStop, "number", null) - : undefined, - (audioStop) => - audioStop !== undefined && setTimeout(() => { - this.Pause(); - setTimeout(() => (this.Document._audioStop = undefined), 10); - }), // wait for mainCont and try again to play - { fireImmediately: true } - ); } // for updating the timecode @@ -305,12 +277,12 @@ export class AudioBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp onFile = (e: any) => { const newDoc = CurrentUserUtils.GetNewTextDoc( "", - NumCast(this.props.Document.x), - NumCast(this.props.Document.y) + - NumCast(this.props.Document._height) + + NumCast(this.rootDoc.x), + NumCast(this.rootDoc.y) + + NumCast(this.layoutDoc._height) + 10, - NumCast(this.props.Document._width), - 2 * NumCast(this.props.Document._height) + NumCast(this.layoutDoc._width), + 2 * NumCast(this.layoutDoc._height) ); Doc.GetProto(newDoc).recordingSource = this.dataDoc; Doc.GetProto(newDoc).recordingStart = ComputedField.MakeFunction( @@ -332,8 +304,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp // returns the path of the audio file @computed get path() { - const field = Cast(this.props.Document[this.fieldKey], AudioField); - const path = field instanceof AudioField ? field.url.href : ""; + const path = Cast(this.props.Document[this.fieldKey], AudioField, null)?.url.href || ""; return path === nullAudio ? "" : path; } @@ -473,133 +444,105 @@ export class AudioBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp })); } - render() { - return ( - <div - ref={r => { - if (r && this.timeline) { - this._dropDisposer?.(); - this._dropDisposer = DragManager.MakeDropTarget(r, - (e, de) => { - const [xp, yp] = this.props.ScreenToLocalTransform().transformPoint(de.x, de.y); - de.complete.docDragData && this.timeline!.internalDocDrop(e, de, de.complete.docDragData, xp); - } - , this.layoutDoc, undefined); - } - }} - className="audiobox-container" - onContextMenu={this.specificContextMenu} - onClick={ - !this.path && !this._recorder ? this.recordAudioAnnotation : undefined - } - style={{ - pointerEvents: - this.props.layerProvider?.(this.layoutDoc) === false - ? "none" - : undefined, - }} - > - {!this.path ? ( - <div className="audiobox-buttons"> - <div className="audiobox-dictation" onClick={this.onFile}> - <FontAwesomeIcon - style={{ width: "30px" }} - icon="file-alt" - size={this.props.PanelHeight() < 36 ? "1x" : "2x"} - /> - </div> - {this.mediaState === media_state.Recording || this.mediaState === media_state.Playing ? ( - <div className="recording" onClick={(e) => e.stopPropagation()}> - <div className="recording-buttons" onClick={this.recordClick}> - <FontAwesomeIcon - icon="stop" - size={this.props.PanelHeight() < 36 ? "1x" : "2x"} - /> - </div> - <div - className="recording-buttons" - onClick={this._paused ? this.recordPlay : this.recordPause} - > - <FontAwesomeIcon - icon={this._paused ? "play" : "pause"} - size={this.props.PanelHeight() < 36 ? "1x" : "2x"} - /> - </div> - <div className="time"> - {formatTime( - Math.round(NumCast(this.layoutDoc._currentTimecode)) - )} - </div> - </div> - ) : ( - <div - className={`audiobox-record${this.props.isContentActive() ? "-interactive" : ""}`} - style={{ backgroundColor: Colors.DARK_GRAY }} - > - <FontAwesomeIcon icon="microphone" /> - RECORD - </div> - )} + @computed get recordingControls() { + return <div className="audiobox-buttons"> + <div className="audiobox-dictation" onClick={this.onFile}> + <FontAwesomeIcon + style={{ width: "30px" }} + icon="file-alt" + size={this.props.PanelHeight() < 36 ? "1x" : "2x"} /> + </div> + {[media_state.Recording, media_state.Playing].includes(this.mediaState) ? + <div className="recording" onClick={(e) => e.stopPropagation()}> + <div className="recording-buttons" onClick={this.recordClick}> + <FontAwesomeIcon + icon="stop" + size={this.props.PanelHeight() < 36 ? "1x" : "2x"} /> </div> - ) : ( - <div - className="audiobox-controls" - style={{ - pointerEvents: - this._isAnyChildContentActive || this.props.isContentActive() - ? "all" - : "none", - }} - > - <div className="audiobox-dictation" /> - <div - className="audiobox-player" - style={{ height: `${AudioBox.heightPercent}%` }} - > - <div - className="audiobox-buttons" - title={this.mediaState === media_state.Paused ? "play" : "pause"} - onClick={this.mediaState === media_state.Paused ? this.Play : this.Pause} - > - {" "} - <FontAwesomeIcon - icon={this.mediaState === media_state.Paused ? "play" : "pause"} - size={"1x"} - /> - </div> - <div - className="audiobox-buttons" - title={this.timeline?.IsTrimming !== TrimScope.None ? "finish" : "trim"} - onPointerDown={this.onClipPointerDown} - > - <FontAwesomeIcon - icon={this.timeline?.IsTrimming !== TrimScope.None ? "check" : "cut"} - size={"1x"} - /> - </div> - <div - className="audiobox-timeline" - style={{ - top: 0, - height: `100%`, - left: AudioBox.playheadWidth, - width: `calc(100% - ${AudioBox.playheadWidth}px)`, - background: "white", - }} - > - {this.renderTimeline} - </div> - {this.audio} - <div className="audioBox-current-time"> - {this.timeline && formatTime(Math.round(NumCast(this.layoutDoc._currentTimecode) - NumCast(this.timeline.clipStart)))} - </div> - <div className="audioBox-total-time"> - {this.timeline && formatTime(Math.round(NumCast(this.timeline?.clipDuration)))} - </div> - </div> - </div> - )} + <div className="recording-buttons" + onClick={this._paused ? this.recordPlay : this.recordPause} + > + <FontAwesomeIcon + icon={this._paused ? "play" : "pause"} + size={this.props.PanelHeight() < 36 ? "1x" : "2x"} /> + </div> + <div className="time"> + {formatTime(Math.round(NumCast(this.layoutDoc._currentTimecode)))} + </div> + </div> + : + <div className={`audiobox-record${this.props.isContentActive() ? "-interactive" : ""}`}> + <FontAwesomeIcon icon="microphone" /> + RECORD + </div>} + </div>; + } + + @computed get playbackControls() { + return <div className="audiobox-controls" + style={{ pointerEvents: this._isAnyChildContentActive || this.props.isContentActive() ? "all" : "none", }} + > + <div className="audiobox-dictation" /> + <div className="audiobox-player" + style={{ height: `${AudioBox.heightPercent}%` }} + > + <div className="audiobox-buttons" + title={this.mediaState === media_state.Paused ? "play" : "pause"} + onClick={this.mediaState === media_state.Paused ? this.Play : this.Pause} + > + {" "} + <FontAwesomeIcon + icon={this.mediaState === media_state.Paused ? "play" : "pause"} + size={"1x"} /> + </div> + <div className="audiobox-buttons" + title={this.timeline?.IsTrimming !== TrimScope.None ? "finish" : "trim"} + onPointerDown={this.onClipPointerDown} + > + <FontAwesomeIcon + icon={this.timeline?.IsTrimming !== TrimScope.None ? "check" : "cut"} + size={"1x"} /> + </div> + <div className="audiobox-timeline" + style={{ + left: AudioBox.playheadWidth, + width: `calc(100% - ${AudioBox.playheadWidth}px)`, + }} + > + {this.renderTimeline} + </div> + {this.audio} + <div className="audioBox-current-time"> + {this.timeline && formatTime(Math.round(NumCast(this.layoutDoc._currentTimecode) - NumCast(this.timeline.clipStart)))} + </div> + <div className="audioBox-total-time"> + {this.timeline && formatTime(Math.round(NumCast(this.timeline?.clipDuration)))} + </div> </div> - ); + </div>; + } + + setupTimelineDrop = (r: HTMLDivElement | null) => { + if (r && this.timeline) { + this._dropDisposer?.(); + this._dropDisposer = DragManager.MakeDropTarget(r, + (e, de) => { + const [xp, yp] = this.props.ScreenToLocalTransform().transformPoint(de.x, de.y); + de.complete.docDragData && this.timeline!.internalDocDrop(e, de, de.complete.docDragData, xp); + }, + this.layoutDoc, undefined); + } + } + + render() { + return <div + ref={this.setupTimelineDrop} + className="audiobox-container" + onContextMenu={this.specificContextMenu} + onClick={!this.path && !this._recorder ? this.recordAudioAnnotation : undefined} + style={{ pointerEvents: this.props.layerProvider?.(this.layoutDoc) === false ? "none" : undefined }} + > + {!this.path ? this.recordingControls : this.playbackControls} + </div>; } }
\ No newline at end of file diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx index b00fb75a3..3435c2a24 100644 --- a/src/client/views/nodes/VideoBox.tsx +++ b/src/client/views/nodes/VideoBox.tsx @@ -222,22 +222,6 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp 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. - this._disposers.triggerVideo = reaction( - () => !LinkDocPreview.LinkInfo && this.props.renderDepth !== -1 ? NumCast(this.Document._triggerVideo, null) : undefined, - time => time !== undefined && setTimeout(() => { - this.player && this.Play(); - setTimeout(() => this.Document._triggerVideo = undefined, 10); - }, this.player ? 0 : 250), // wait for mainCont and try again to play - { fireImmediately: true } - ); - this._disposers.triggerStop = reaction( - () => this.props.renderDepth !== -1 && !LinkDocPreview.LinkInfo ? NumCast(this.Document._triggerVideoStop, null) : undefined, - stop => stop !== undefined && setTimeout(() => { - this.player && this.Pause(); - setTimeout(() => this.Document._triggerVideoStop = undefined, 10); - }, this.player ? 0 : 250), // wait for mainCont and try again to play - { fireImmediately: true } - ); if (this.youtubeVideoId) { const youtubeaspect = 400 / 315; const nativeWidth = Doc.NativeWidth(this.layoutDoc); diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx index 8e61a224c..f4892d77c 100644 --- a/src/client/views/nodes/trails/PresBox.tsx +++ b/src/client/views/nodes/trails/PresBox.tsx @@ -200,26 +200,13 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> const targMedia = DocumentManager.Instance.getDocumentView(targetDoc); targMedia?.ComponentView?.playFrom?.(NumCast(activeItem.presStartTime), NumCast(activeItem.presStartTime) + duration); } - // if (targetDoc.type === DocumentType.AUDIO) { - // if (this._mediaTimer && this._mediaTimer[1] === targetDoc) clearTimeout(this._mediaTimer[0]); - // targetDoc._triggerAudio = NumCast(activeItem.presStartTime); - // this._mediaTimer = [setTimeout(() => targetDoc._audioStop = true, duration * 1000), targetDoc]; - // } else if (targetDoc.type === DocumentType.VID) { - // targetDoc._triggerVideoStop = true; - // setTimeout(() => targetDoc._currentTimecode = NumCast(activeItem.presStartTime), 10); - // setTimeout(() => targetDoc._triggerVideo = true, 20); - // this._mediaTimer = [setTimeout(() => targetDoc._triggerVideoStop = true, (duration * 1000) + 20), targetDoc]; - // } } stopTempMedia = (targetDocField: FieldResult) => { const targetDoc = Cast(targetDocField, Doc, null); - if (targetDoc?.type === DocumentType.AUDIO) { - if (this._mediaTimer && this._mediaTimer[1] === targetDoc) clearTimeout(this._mediaTimer[0]); - targetDoc._audioStop = true; - } else if (targetDoc?.type === DocumentType.VID) { - if (this._mediaTimer && this._mediaTimer[1] === targetDoc) clearTimeout(this._mediaTimer[0]); - targetDoc._triggerVideoStop = true; + if ([DocumentType.VID, DocumentType.AUDIO].includes(targetDoc.type as any)) { + const targMedia = DocumentManager.Instance.getDocumentView(targetDoc); + targMedia?.ComponentView?.Pause?.(); } } |