diff options
5 files changed, 64 insertions, 34 deletions
diff --git a/src/client/views/collections/CollectionStackedTimeline.scss b/src/client/views/collections/CollectionStackedTimeline.scss index 36aa36978..e8b6817b4 100644 --- a/src/client/views/collections/CollectionStackedTimeline.scss +++ b/src/client/views/collections/CollectionStackedTimeline.scss @@ -10,6 +10,10 @@ border-width: 0 2px 0 2px; } +::-webkit-scrollbar { + height: 5px; +} + .collectionStackedTimeline { position: absolute; background: $off-white; diff --git a/src/client/views/collections/collectionLinear/CollectionLinearView.scss b/src/client/views/collections/collectionLinear/CollectionLinearView.scss index 8fe804466..d86e2d81f 100644 --- a/src/client/views/collections/collectionLinear/CollectionLinearView.scss +++ b/src/client/views/collections/collectionLinear/CollectionLinearView.scss @@ -13,7 +13,7 @@ background-color: $medium-blue-alt; } - >input:not(:checked)~&.true { + > input:not(:checked) ~ &.true { background-color: transparent; } @@ -27,7 +27,7 @@ overflow: visible !important; } - >span { + > span { background: $dark-gray; color: $white; border-radius: 18px; @@ -54,6 +54,7 @@ padding-right: 20px; vertical-align: middle; font-size: 12.5px; + pointer-events: all; } .bottomPopup-descriptions { @@ -82,7 +83,7 @@ color: black; } - >label { + > label { pointer-events: all; cursor: pointer; background-color: $medium-blue; @@ -100,20 +101,20 @@ justify-content: center; transition: 0.2s; - &:hover{ + &:hover { filter: brightness(0.85); } } - >input { + > input { display: none; } - >input:not(:checked)~.collectionLinearView-content { + > input:not(:checked) ~ .collectionLinearView-content { display: none; } - >input:checked~label { + > input:checked ~ label { transform: rotate(45deg); transition: transform 0.5s; cursor: pointer; @@ -147,4 +148,4 @@ } } } -}
\ No newline at end of file +} diff --git a/src/client/views/collections/collectionLinear/CollectionLinearView.tsx b/src/client/views/collections/collectionLinear/CollectionLinearView.tsx index 35b7fb5e9..3a06df746 100644 --- a/src/client/views/collections/collectionLinear/CollectionLinearView.tsx +++ b/src/client/views/collections/collectionLinear/CollectionLinearView.tsx @@ -3,12 +3,13 @@ import { Tooltip } from '@material-ui/core'; import { action, IReactionDisposer, observable, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; -import { Doc, HeightSym, Opt, WidthSym } from '../../../../fields/Doc'; +import { Doc, HeightSym, Opt, WidthSym, DataSym } from '../../../../fields/Doc'; import { documentSchema } from '../../../../fields/documentSchemas'; import { Id } from '../../../../fields/FieldSymbols'; import { makeInterface } from '../../../../fields/Schema'; import { BoolCast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types'; -import { emptyFunction, returnEmptyDoclist, returnTrue, Utils } from '../../../../Utils'; +import { emptyFunction, returnEmptyDoclist, returnTrue, returnFalse, OmitKeys, Utils } from '../../../../Utils'; +import { DocUtils } from '../../../documents/Documents'; import { DragManager } from '../../../util/DragManager'; import { Transform } from '../../../util/Transform'; import { Colors, Shadows } from '../../global/globalEnums'; @@ -19,6 +20,7 @@ import { LinkDescriptionPopup } from '../../nodes/LinkDescriptionPopup'; import { StyleProp } from '../../StyleProvider'; import { CollectionSubView } from '../CollectionSubView'; import { CollectionViewType } from '../CollectionView'; +import { DocumentManager } from "../../../util/DocumentManager"; import "./CollectionLinearView.scss"; @@ -122,6 +124,7 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) { let dref: Opt<HTMLDivElement>; const docXf = () => this.getTransform(dref); // const scalable = pair.layout.onClick || pair.layout.onDragStart; + doc.title == "audio recording 1" && console.log(doc); return hidden ? (null) : <div className={`collectionLinearView-docBtn`} key={doc[Id]} ref={r => dref = r || undefined} style={{ pointerEvents: "all", @@ -225,9 +228,17 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) { add button to close out audio from currently playing */} {AudioBox.CurrentlyPlaying && AudioBox.CurrentlyPlaying.length != 0 && StrCast(this.layoutDoc.title) === "docked buttons" ? <span className="bottomPopup-background"> <span className="bottomPopup-text"> - Currently listening to: {AudioBox.CurrentlyPlaying.map((clip) => clip.dataDoc.title + ", ")} + Currently listening to: {AudioBox.CurrentlyPlaying.map((clip) => + <span onPointerDown={() => { + DocumentManager.Instance.jumpToDocument(clip, true); + }}>{clip.title}, </span> + )} </span> </span> : null} + + {/* {AudioBox.CurrentlyPlaying && AudioBox.CurrentlyPlaying.length != 0 && StrCast(this.layoutDoc.title) === "docked buttons" ? + this.getDisplayDoc(AudioBox.CurrentlyPlaying[0]) : null} */} + </div> </div>; } diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx index acd025fbd..67c8902f9 100644 --- a/src/client/views/nodes/AudioBox.tsx +++ b/src/client/views/nodes/AudioBox.tsx @@ -38,7 +38,7 @@ enum media_state { } @observer export class AudioBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps & FieldViewProps, AudioDocument>(AudioDocument) { - @observable public static CurrentlyPlaying: AudioBox[]; + @observable public static CurrentlyPlaying: Doc[]; public static LayoutString(fieldKey: string) { return FieldView.LayoutString(AudioBox, fieldKey); } public static SetScrubTime = action((timeInMillisFrom1970: number) => { @@ -63,6 +63,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp _stream: MediaStream | undefined; _play: any = null; + @observable _finished: boolean = false; @observable _volume: number = 1; @observable _muted: boolean = false; @observable _paused: boolean = false; @@ -157,11 +158,10 @@ export class AudioBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp if (!AudioBox.CurrentlyPlaying) { AudioBox.CurrentlyPlaying = []; } - if (AudioBox.CurrentlyPlaying.indexOf(this) == -1) { - AudioBox.CurrentlyPlaying.push(this); + if (AudioBox.CurrentlyPlaying.indexOf(this.Document) == -1) { + AudioBox.CurrentlyPlaying.push(this.Document); } - fullPlay = endTime ? fullPlay : true; clearTimeout(this._play); // abort any previous clip ending if (Number.isNaN(this._ele?.duration)) { // audio element isn't loaded yet... wait 1/2 second and try again setTimeout(() => this.playFrom(seekTimeInSeconds, endTime), 500); @@ -175,14 +175,14 @@ export class AudioBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp this.mediaState = media_state.Playing; this._play = setTimeout( () => { - this.Pause(false); - if (fullPlay) this.setPlayheadTime(this.timeline!.trimStart); + if (fullPlay) this._finished = true; // removes from currently playing if playback has reached end of range marker else this.removeCurrentlyPlaying(); + this.Pause(); }, (end - start) * 1000); } else { - this.Pause(false); + this.Pause(); } } } @@ -190,7 +190,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp // removes from currently playing display @action removeCurrentlyPlaying = () => { - AudioBox.CurrentlyPlaying.splice(AudioBox.CurrentlyPlaying.indexOf(this), 1); + AudioBox.CurrentlyPlaying.splice(AudioBox.CurrentlyPlaying.indexOf(this.Document), 1); } // update the recording time @@ -277,20 +277,26 @@ export class AudioBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp // for play button Play = (e?: any) => { + e?.stopPropagation?.(); + if (this.timeline && this._ele) { const eleTime = this._ele.currentTime; - const start = eleTime >= this.timeline.trimEnd || eleTime <= this.timeline.trimStart ? this.timeline.trimStart : eleTime; + let start = eleTime >= this.timeline.trimEnd || eleTime <= this.timeline.trimStart ? this.timeline.trimStart : eleTime; + if (this._finished) { + this._finished = false; + start = this.timeline.trimStart; + } this.playFrom(start, this.timeline.trimEnd, true); - e?.stopPropagation?.(); } } // pause play back @action - Pause = (timeoutClear: boolean = true) => { + Pause = () => { this._ele?.pause(); this.mediaState = media_state.Paused; - if (timeoutClear) clearTimeout(this._play); // prevents jump back to beginning when manually paused + if (!this._finished) clearTimeout(this._play); + AudioBox.CurrentlyPlaying.splice(AudioBox.CurrentlyPlaying.indexOf(this.Document), 1); } // creates a text document for dictation @@ -318,7 +324,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp // ref for updating time setRef = (e: HTMLAudioElement | null) => { e?.addEventListener("timeupdate", this.timecodeChanged); - e?.addEventListener("ended", () => this.Pause(false)); + e?.addEventListener("ended", () => { this._finished = true; this.Pause() }); this._ele = e; } diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx index ec6519abd..fbefa02bc 100644 --- a/src/client/views/nodes/VideoBox.tsx +++ b/src/client/views/nodes/VideoBox.tsx @@ -76,6 +76,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp @observable _playTimer?: NodeJS.Timeout = undefined; @observable _fullScreen = false; @observable _playing = false; + @observable _finished: boolean = false; @computed get links() { return DocListCast(this.dataDoc.links); } @computed get heightPercent() { return NumCast(this.layoutDoc._timelineHeightPercent, 100); } @@ -120,15 +121,21 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp @action public Play = (update: boolean = true) => { this._playing = true; const eleTime = this.player?.currentTime || 0; - const start = eleTime >= (this.timeline?.trimEnd || 0) ? this.timeline?.trimStart || 0 : eleTime; - try { - this._audioPlayer && this.player && (this._audioPlayer.currentTime = this.player?.currentTime); - update && this.player && this.playFrom(start, undefined, true); - update && this._audioPlayer?.play(); - update && this._youtubePlayer?.playVideo(); - this._youtubePlayer && !this._playTimer && (this._playTimer = setInterval(this.updateTimecode, 5)); - } catch (e) { - console.log("Video Play Exception:", e); + if (this.timeline) { + let start = eleTime >= this.timeline.trimEnd || eleTime <= this.timeline.trimStart ? this.timeline.trimStart : eleTime; + if (this._finished) { + this._finished = false; + start = this.timeline.trimStart; + } + try { + this._audioPlayer && this.player && (this._audioPlayer.currentTime = this.player?.currentTime); + update && this.player && this.playFrom(start, undefined, true); + update && this._audioPlayer?.play(); + update && this._youtubePlayer?.playVideo(); + this._youtubePlayer && !this._playTimer && (this._playTimer = setInterval(this.updateTimecode, 5)); + } catch (e) { + console.log("Video Play Exception:", e); + } } this.updateTimecode(); } @@ -157,6 +164,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp this._youtubePlayer && SelectionManager.DeselectAll(); // if we don't deselect the player, then we get an annoying YouTube spinner I guess telling us we're paused. this._playTimer = undefined; this.updateTimecode(); + if (!this._finished) clearTimeout(this._playRegionTimer);; } @action public FullScreen = () => { @@ -407,7 +415,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp this._playing = true; this._playRegionTimer = setTimeout( () => { - if (fullPlay) this.setPlayheadTime(this.timeline?.trimStart || 0); + if (fullPlay) this._finished = true; this.Pause(); }, this._playRegionDuration * 1000); } else { |