diff options
-rw-r--r-- | src/client/views/nodes/AudioBox.scss | 37 | ||||
-rw-r--r-- | src/client/views/nodes/AudioBox.tsx | 86 |
2 files changed, 111 insertions, 12 deletions
diff --git a/src/client/views/nodes/AudioBox.scss b/src/client/views/nodes/AudioBox.scss index e9420a072..06498182d 100644 --- a/src/client/views/nodes/AudioBox.scss +++ b/src/client/views/nodes/AudioBox.scss @@ -46,6 +46,38 @@ width: 100%; height: 100%; position: relative; + + + } + + .recording { + margin-top: auto; + margin-bottom: auto; + width: 100%; + height: 80%; + position: relative; + padding-right: 5px; + display: flex; + + .time { + position: relative; + height: 100%; + width: 100%; + font-size: 20; + text-align: center; + } + + .buttons { + position: relative; + margin-top: auto; + margin-bottom: auto; + width: 25px; + padding: 5px; + } + + .buttons:hover { + background-color: darkgrey; + } } .audiobox-controls { @@ -54,6 +86,7 @@ position: relative; display: flex; padding-left: 2px; + background: lightgrey; .audiobox-player { margin-top: auto; @@ -73,6 +106,10 @@ padding: 2px; } + .audiobox-playhead:hover { + background-color: darkgrey; + } + .audiobox-dictation { align-items: center; display: inherit; diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx index 5c921cea4..cb56ae203 100644 --- a/src/client/views/nodes/AudioBox.tsx +++ b/src/client/views/nodes/AudioBox.tsx @@ -50,9 +50,14 @@ export class AudioBox extends ViewBoxBaseComponent<FieldViewProps, AudioDocument _ele: HTMLAudioElement | null = null; _recorder: any; _recordStart = 0; + _pauseStart = 0; + _pauseEnd = 0; + _pausedTime = 0; _stream: MediaStream | undefined; + @observable private _paused: boolean = false; @observable private static _scrubTime = 0; + @observable private _repeat: boolean = false; @computed get audioState(): undefined | "recording" | "paused" | "playing" { return this.dataDoc.audioState as (undefined | "recording" | "paused" | "playing"); } set audioState(value) { this.dataDoc.audioState = value; } public static SetScrubTime = (timeInMillisFrom1970: number) => { runInAction(() => AudioBox._scrubTime = 0); runInAction(() => AudioBox._scrubTime = timeInMillisFrom1970); }; @@ -106,8 +111,12 @@ export class AudioBox extends ViewBoxBaseComponent<FieldViewProps, AudioDocument } pause = action(() => { - this._ele!.pause(); - this.audioState = "paused"; + if (this._repeat) { + this.playFrom(0); + } else { + this._ele!.pause(); + this.audioState = "paused"; + } }); playFromTime = (absoluteTime: number) => { @@ -134,8 +143,13 @@ export class AudioBox extends ViewBoxBaseComponent<FieldViewProps, AudioDocument updateRecordTime = () => { if (this.audioState === "recording") { - setTimeout(this.updateRecordTime, 30); - this.layoutDoc.currentTimecode = (new Date().getTime() - this._recordStart) / 1000; + if (this._paused) { + setTimeout(this.updateRecordTime, 30); + this._pausedTime += (new Date().getTime() - this._recordStart) / 1000; + } else { + setTimeout(this.updateRecordTime, 30); + this.layoutDoc.currentTimecode = (new Date().getTime() - this._recordStart - this.pauseTime) / 1000; + } } } @@ -167,7 +181,7 @@ export class AudioBox extends ViewBoxBaseComponent<FieldViewProps, AudioDocument stopRecording = action(() => { this._recorder.stop(); this._recorder = undefined; - this.dataDoc.duration = (new Date().getTime() - this._recordStart) / 1000; + this.dataDoc.duration = (new Date().getTime() - this._recordStart - this.pauseTime) / 1000; this.audioState = "paused"; this._stream?.getAudioTracks()[0].stop(); const ind = DocUtils.ActiveRecordings.indexOf(this.props.Document); @@ -222,6 +236,34 @@ export class AudioBox extends ViewBoxBaseComponent<FieldViewProps, AudioDocument </audio>; } + @action + onRepeat = (e: React.MouseEvent) => { + this._repeat = !this._repeat; + e.stopPropagation(); + } + + @action + recordPause = (e: React.MouseEvent) => { + this._pauseStart = new Date().getTime(); + this._paused = true; + this._recorder.pause(); + e.stopPropagation(); + + } + + @action + recordPlay = (e: React.MouseEvent) => { + this._pauseEnd = new Date().getTime(); + this._paused = false; + this._recorder.resume(); + e.stopPropagation(); + + } + + @computed get pauseTime() { + return (this._pauseEnd - this._pauseStart); + } + render() { const interactive = this.active() ? "-interactive" : ""; return <div className={`audiobox-container`} onContextMenu={this.specificContextMenu} onClick={!this.path ? this.recordClick : undefined}> @@ -230,14 +272,34 @@ export class AudioBox extends ViewBoxBaseComponent<FieldViewProps, AudioDocument <div className="audiobox-dictation" onClick={this.onFile}> <FontAwesomeIcon style={{ width: "30px", background: this.layoutDoc.playOnSelect ? "yellow" : "rgba(0,0,0,0)" }} icon="file-alt" size={this.props.PanelHeight() < 36 ? "1x" : "2x"} /> </div> - <button className={`audiobox-record${interactive}`} style={{ backgroundColor: this.audioState === "recording" ? "red" : "black" }}> - {this.audioState === "recording" ? "STOP" : "RECORD"} - </button> + {/* <button className={`audiobox-record${interactive}`} style={{ backgroundColor: this.audioState === "recording" ? "lightgrey" : "black" }}> + {this.audioState === "recording" ? + <div className="recording" style={{}}> + 10:00 + <FontAwesomeIcon style={{ width: "100%" }} icon={"stop-circle"} size={this.props.PanelHeight() < 36 ? "1x" : "2x"} /> + <FontAwesomeIcon style={{ width: "100%" }} icon={"pause"} size={this.props.PanelHeight() < 36 ? "1x" : "2x"} /> </div> : "RECORD"} + </button> */} + {this.audioState === "recording" ? + <div className="recording" onClick={e => e.stopPropagation()}> + <div className="buttons" onClick={this.recordClick}> + <FontAwesomeIcon style={{ width: "100%" }} icon={"stop"} size={this.props.PanelHeight() < 36 ? "1x" : "2x"} /> + </div> + <div className="buttons" onClick={this._paused ? this.recordPlay : this.recordPause}> + <FontAwesomeIcon style={{ width: "100%" }} icon={this._paused ? "play" : "pause"} size={this.props.PanelHeight() < 36 ? "1x" : "2x"} /> + </div> + <div className="time">{NumCast(this.layoutDoc.currentTimecode).toFixed(1)}</div> + </div> + + : + <button className={`audiobox-record${interactive}`} style={{ backgroundColor: "black" }}> + RECORD + </button>} </div> : - <div className="audiobox-controls"> - <div className="audiobox-player" onClick={this.onPlay}> - <div className="audiobox-playhead"> <FontAwesomeIcon style={{ width: "100%" }} icon={this.audioState === "paused" ? "play" : "pause"} size={this.props.PanelHeight() < 36 ? "1x" : "2x"} /></div> - <div className="audiobox-playhead" onClick={this.onStop}><FontAwesomeIcon style={{ width: "100%", background: this.layoutDoc.playOnSelect ? "yellow" : "dimGray" }} icon="hand-point-left" size={this.props.PanelHeight() < 36 ? "1x" : "2x"} /></div> + <div className="audiobox-controls" onClick={this.layoutDoc.playOnSelect ? this.onPlay : undefined}> + <div className="audiobox-player" > + <div className="audiobox-playhead" onClick={this.onPlay}> <FontAwesomeIcon style={{ width: "100%" }} icon={this.audioState === "paused" ? "play" : "pause"} size={this.props.PanelHeight() < 36 ? "1x" : "2x"} /></div> + <div className="audiobox-playhead" onClick={this.onStop}><FontAwesomeIcon style={{ width: "100%", background: this.layoutDoc.playOnSelect ? "darkgrey" : "" }} icon="hand-point-left" size={this.props.PanelHeight() < 36 ? "1x" : "2x"} /></div> + <div className="audiobox-playhead" onClick={this.onRepeat}><FontAwesomeIcon style={{ width: "100%", background: this._repeat ? "darkgrey" : "" }} icon="redo-alt" size={this.props.PanelHeight() < 36 ? "1x" : "2x"} /></div> <div className="audiobox-timeline" onClick={e => e.stopPropagation()} onPointerDown={e => { if (e.button === 0 && !e.ctrlKey) { |