aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormehekj <mehek.jethani@gmail.com>2021-10-28 15:12:34 -0400
committermehekj <mehek.jethani@gmail.com>2021-10-28 15:12:34 -0400
commit7f08f0fec32a28e1dc19f00021f99352f55a045c (patch)
treea4f22a74ed74a72a763cbb69177ff2c8b535dbd1
parent4c698f82b6407715d360a4fde539838dd12d4d1a (diff)
fixed marker document decorations on scroll in zoomed timeline
-rw-r--r--src/client/views/AudioWaveform.tsx2
-rw-r--r--src/client/views/MainView.tsx2
-rw-r--r--src/client/views/collections/CollectionStackedTimeline.scss32
-rw-r--r--src/client/views/collections/CollectionStackedTimeline.tsx16
-rw-r--r--src/client/views/nodes/AudioBox.scss123
-rw-r--r--src/client/views/nodes/AudioBox.tsx43
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>