diff options
author | mehekj <mehek.jethani@gmail.com> | 2021-10-28 15:12:34 -0400 |
---|---|---|
committer | mehekj <mehek.jethani@gmail.com> | 2021-10-28 15:12:34 -0400 |
commit | 7f08f0fec32a28e1dc19f00021f99352f55a045c (patch) | |
tree | a4f22a74ed74a72a763cbb69177ff2c8b535dbd1 | |
parent | 4c698f82b6407715d360a4fde539838dd12d4d1a (diff) |
fixed marker document decorations on scroll in zoomed timeline
-rw-r--r-- | src/client/views/AudioWaveform.tsx | 2 | ||||
-rw-r--r-- | src/client/views/MainView.tsx | 2 | ||||
-rw-r--r-- | src/client/views/collections/CollectionStackedTimeline.scss | 32 | ||||
-rw-r--r-- | src/client/views/collections/CollectionStackedTimeline.tsx | 16 | ||||
-rw-r--r-- | src/client/views/nodes/AudioBox.scss | 123 | ||||
-rw-r--r-- | src/client/views/nodes/AudioBox.tsx | 43 |
6 files changed, 138 insertions, 80 deletions
diff --git a/src/client/views/AudioWaveform.tsx b/src/client/views/AudioWaveform.tsx index ca1dd6f36..58384792e 100644 --- a/src/client/views/AudioWaveform.tsx +++ b/src/client/views/AudioWaveform.tsx @@ -90,7 +90,7 @@ export class AudioWaveform extends React.Component<AudioWaveformProps> { <Waveform color={Colors.MEDIUM_BLUE} height={this.waveHeight} - barWidth={10.0 / this.audioBuckets.length} + barWidth={200.0 / this.audioBuckets.length} pos={this.props.duration} duration={this.props.duration} peaks={this.audioBuckets} diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 9a885fbf8..ce71dcc01 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -187,7 +187,7 @@ export class MainView extends React.Component { fa.faArrowAltCircleDown, fa.faArrowAltCircleUp, fa.faArrowAltCircleLeft, fa.faArrowAltCircleRight, fa.faStopCircle, fa.faCheckCircle, fa.faGripVertical, fa.faSortUp, fa.faSortDown, fa.faTable, fa.faTh, fa.faThList, fa.faProjectDiagram, fa.faSignature, fa.faColumns, fa.faChevronCircleUp, fa.faUpload, fa.faBorderAll, fa.faBraille, fa.faChalkboard, fa.faPencilAlt, fa.faEyeSlash, fa.faSmile, fa.faIndent, fa.faOutdent, fa.faChartBar, fa.faBan, fa.faPhoneSlash, fa.faGripLines, - fa.faSave, fa.faBookmark, fa.faList, fa.faListOl, fa.faFolderPlus, fa.faLightbulb, fa.faBookOpen); + fa.faSave, fa.faBookmark, fa.faList, fa.faListOl, fa.faFolderPlus, fa.faLightbulb, fa.faBookOpen, fa.faSearchPlus, fa.faVolumeUp, fa.faVolumeMute); this.initAuthenticationRouters(); } diff --git a/src/client/views/collections/CollectionStackedTimeline.scss b/src/client/views/collections/CollectionStackedTimeline.scss index 843c5dcb5..19913350b 100644 --- a/src/client/views/collections/CollectionStackedTimeline.scss +++ b/src/client/views/collections/CollectionStackedTimeline.scss @@ -2,8 +2,24 @@ .timeline-container { height: calc(100% - 50px); - overflow-x: scroll; + overflow-x: auto; border: none; + background-color: $white; + border: 2px solid $dark-gray; + border-width: 0 2px 0 2px; +} + +::-webkit-scrollbar { + position: relative; + -webkit-appearance: none; + height: 5px; +} + +::-webkit-scrollbar-thumb { + position: relative; + -webkit-appearance: none; + height: 5px; + background-color: $medium-gray; } .collectionStackedTimeline { @@ -12,20 +28,6 @@ z-index: 1000; height: 100%; - ::-webkit-scrollbar { - position: relative; - -webkit-appearance: none; - height: 5px; - background-color: white; - } - - ::-webkit-scrollbar-thumb { - position: relative; - -webkit-appearance: none; - height: 5px; - background-color: $medium-gray; - } - .collectionStackedTimeline-trim-shade { position: absolute; height: 100%; diff --git a/src/client/views/collections/CollectionStackedTimeline.tsx b/src/client/views/collections/CollectionStackedTimeline.tsx index 82a6b2a66..37fd42bc1 100644 --- a/src/client/views/collections/CollectionStackedTimeline.tsx +++ b/src/client/views/collections/CollectionStackedTimeline.tsx @@ -89,6 +89,8 @@ export class CollectionStackedTimeline extends CollectionSubView< @observable _zoomFactor: number = 1; + @observable _scroll: number = 0; + get minTrimLength() { return this._timeline?.getBoundingClientRect() ? 0.05 * this.clipDuration : 0; } @computed get trimStart() { return this.IsTrimming !== TrimScope.None ? this._trimStart : this.clipStart; } @computed get trimDuration() { return this.trimEnd - this.trimStart; } @@ -219,7 +221,6 @@ export class CollectionStackedTimeline extends CollectionSubView< @action onPointerDownTimeline = (e: React.PointerEvent): void => { const rect = this._timeline?.getBoundingClientRect(); - const scrollLeft = this._timeline?.scrollLeft; const clientX = e.clientX; const diff = rect ? clientX - rect?.x : null; const shiftKey = e.shiftKey; @@ -344,6 +345,11 @@ export class CollectionStackedTimeline extends CollectionSubView< } @action + setScroll = (e: React.MouseEvent) => { + this._scroll = e.currentTarget.scrollLeft; + } + + @action internalDocDrop(e: Event, de: DragManager.DropEvent, docDragData: DragManager.DocumentDragData, xp: number) { if (!de.embedKey && this.props.layerProvider?.(this.props.Document) !== false && this.props.Document._isGroup) return false; if (!super.onInternalDrop(e, de)) return false; @@ -533,7 +539,6 @@ export class CollectionStackedTimeline extends CollectionSubView< ); } @computed get renderAudioWaveform() { - console.log(this.props.mediaPath) return !this.props.mediaPath ? null : ( <div className="collectionStackedTimeline-waveform"> <AudioWaveform @@ -563,7 +568,7 @@ export class CollectionStackedTimeline extends CollectionSubView< } render() { - const timelineContentWidth = this.props.PanelWidth() * this.zoomFactor; + const timelineContentWidth = this.props.PanelWidth() * this.zoomFactor - 4; // subtract size of container border const overlaps: { anchorStartTime: number; anchorEndTime: number; @@ -576,7 +581,8 @@ export class CollectionStackedTimeline extends CollectionSubView< const maxLevel = overlaps.reduce((m, o) => Math.max(m, o.level), 0) + 2; return (<div ref={this.createDashEventsTarget} style={{ pointerEvents: SnappingManager.GetIsDragging() ? "all" : undefined }}> <div className="timeline-container" - style={{ width: this.props.PanelWidth() }}> + style={{ width: this.props.PanelWidth() }} + onScroll={this.setScroll}> <div className="collectionStackedTimeline" ref={(timeline: HTMLDivElement | null) => (this._timeline = timeline)} @@ -616,7 +622,7 @@ export class CollectionStackedTimeline extends CollectionSubView< mark={d.anchor} rangeClickScript={this.rangeClickScript} rangePlayScript={this.rangePlayScript} - left={left} + left={left - this._scroll} top={top} width={width} height={height} diff --git a/src/client/views/nodes/AudioBox.scss b/src/client/views/nodes/AudioBox.scss index d466c6c3b..b3df7e79f 100644 --- a/src/client/views/nodes/AudioBox.scss +++ b/src/client/views/nodes/AudioBox.scss @@ -92,6 +92,62 @@ height: 100%; color: $white; + .audiobox-button { + margin: 2.5px; + cursor: pointer; + width: 25px; + height: 25px; + border-radius: 50%; + background: $dark-gray; + display: flex; + align-items: center; + justify-content: center; + + svg { + width: 15px; + } + + &:hover { + background: $black; + } + } + + svg { + width: 10px; + } + + input[type="range"] { + width: 70px; + -webkit-appearance: none; + background: none; + margin: 5px; + } + + input[type="range"]:focus { + outline: none; + } + + input[type="range"]::-webkit-slider-runnable-track { + width: 100%; + height: 6px; + cursor: pointer; + box-shadow: 0; + background: $light-gray; + border-radius: 3px; + } + + input[type="range"]::-webkit-slider-thumb { + box-shadow: 0; + border: 0; + height: 10px; + width: 10px; + border-radius: 10px; + background: $medium-blue; + cursor: pointer; + -webkit-appearance: none; + margin: -2px; + } + .audiobox-controls { display: flex; flex-direction: row; @@ -104,66 +160,20 @@ display: flex; flex-direction: row; width: 100px; - - .audiobox-button { - margin: 2.5px; - cursor: pointer; - width: 25px; - height: 25px; - border-radius: 50%; - background: $dark-gray; - display: flex; - align-items: center; - justify-content: center; - - svg { - width: 15px; - } - - &:hover { - background: $black; - } - } } .controls-right { display: flex; flex-direction: row; - svg { - width: 10px; - } - - input[type="range"] { - width: 70px; - -webkit-appearance: none; - background: none; - margin: 5px; - } - - input[type="range"]:focus { - outline: none; - } - - input[type="range"]::-webkit-slider-runnable-track { - width: 100%; - height: 6px; - cursor: pointer; - box-shadow: 0; - background: $light-gray; - border-radius: 3px; - } + .audiobox-button { + width: 15px; + height: 15px; + margin: 0; - input[type="range"]::-webkit-slider-thumb { - box-shadow: 0; - border: 0; - height: 10px; - width: 10px; - border-radius: 10px; - background: $medium-blue; - cursor: pointer; - -webkit-appearance: none; - margin: -2px; + svg { + width: 10px; + } } } } @@ -171,6 +181,7 @@ .audiobox-playback { width: 100%; height: calc(100% - 50px); + background: $white; .audiobox-timeline { height: 100%; @@ -193,5 +204,11 @@ height: 20px; padding: 3px; font-size: $small-text; + + .bottom-controls-middle { + display: flex; + flex-direction: row; + align-items: center; + } } } diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx index 48e324971..3a3eb78e1 100644 --- a/src/client/views/nodes/AudioBox.tsx +++ b/src/client/views/nodes/AudioBox.tsx @@ -21,6 +21,7 @@ import { ContextMenuProps } from "../ContextMenuItem"; import { ViewBoxAnnotatableComponent, ViewBoxAnnotatableProps } from "../DocComponent"; import "./AudioBox.scss"; import { FieldView, FieldViewProps } from "./FieldView"; +import { timeStamp } from "console"; declare class MediaRecorder { constructor(e: any); // whatever MediaRecorder has @@ -60,6 +61,8 @@ export class AudioBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp _stream: MediaStream | undefined; _play: any = null; + @observable _volume: number = 1; + @observable _muted: boolean = false; @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`]); } @@ -155,8 +158,8 @@ export class AudioBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp this.mediaState = media_state.Playing; this._play = setTimeout( () => { - if (fullPlay) this.setPlayheadTime(this.timeline!.trimStart); this.Pause(); + if (fullPlay) this.setPlayheadTime(this.timeline!.trimStart); }, (end - start) * 1000); } else { @@ -260,6 +263,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp Pause = () => { this._ele?.pause(); this.mediaState = media_state.Paused; + // clearTimeout(this._play); // stops clip from jumping back to beginning } // creates a text document for dictation @@ -374,6 +378,23 @@ export class AudioBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp this.timeline?.setZoom(zoom); } + @action + setVolume = (volume: number) => { + if (this._ele) { + this._volume = volume; + this._ele.volume = volume; + } + } + + @action + toggleMute = (e: React.PointerEvent) => { + e.stopPropagation(); + if (this._ele) { + this._muted = !this._muted; + this._ele.muted = this._muted; + } + } + setupTimelineDrop = (r: HTMLDivElement | null) => { if (r && this.timeline) { this._dropDisposer?.(); @@ -434,11 +455,15 @@ export class AudioBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp </div> </div> <div className="controls-right"> - <FontAwesomeIcon icon={["fas", "search"]} /> - <input type="range" step="0.1" min="1" max="5" value={this.timeline?._zoomFactor} - className="toolbar-slider" id="zoom-slider" + <div className="audiobox-button" + title={this._muted ? "unmute" : "mute"} + onPointerDown={this.toggleMute}> + <FontAwesomeIcon icon={this._muted ? "volume-mute" : "volume-up"} /> + </div> + <input type="range" step="0.1" min="0" max="1" value={this._volume} + className="toolbar-slider" id="volume-slider" onPointerDown={(e: React.PointerEvent) => { e.stopPropagation(); }} - onChange={(e: React.ChangeEvent<HTMLInputElement>) => { this.zoom(Number(e.target.value)); }} + onChange={(e: React.ChangeEvent<HTMLInputElement>) => { this.setVolume(Number(e.target.value)) }} /> </div> </div> @@ -455,6 +480,14 @@ export class AudioBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp <div className="timecode-current"> {this.timeline && formatTime(Math.round(NumCast(this.layoutDoc._currentTimecode) - NumCast(this.timeline.clipStart)))} </div> + <div className="bottom-controls-middle"> + <FontAwesomeIcon icon="search-plus" /> + <input type="range" step="0.1" min="1" max="5" value={this.timeline?._zoomFactor} + className="toolbar-slider" id="zoom-slider" + onPointerDown={(e: React.PointerEvent) => { e.stopPropagation(); }} + onChange={(e: React.ChangeEvent<HTMLInputElement>) => { this.zoom(Number(e.target.value)); }} + /> + </div> <div className="timecode-duration"> {this.timeline && formatTime(Math.round(NumCast(this.timeline?.clipDuration)))} </div> |