aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/AudioBox.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/nodes/AudioBox.tsx')
-rw-r--r--src/client/views/nodes/AudioBox.tsx267
1 files changed, 105 insertions, 162 deletions
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