diff options
-rw-r--r-- | deploy/index.html | 65 | ||||
-rw-r--r-- | deploy/loader.css | 141 | ||||
-rw-r--r-- | src/client/util/CurrentUserUtils.ts | 2 | ||||
-rw-r--r-- | src/client/views/MainView.tsx | 7 | ||||
-rw-r--r-- | src/client/views/PropertiesView.tsx | 6 | ||||
-rw-r--r-- | src/client/views/collections/CollectionStackingView.tsx | 2 | ||||
-rw-r--r-- | src/client/views/collections/TabDocView.tsx | 4 | ||||
-rw-r--r-- | src/client/views/nodes/AudioBox.tsx | 31 | ||||
-rw-r--r-- | src/client/views/nodes/PresBox.scss | 10 | ||||
-rw-r--r-- | src/client/views/nodes/PresBox.tsx | 27 | ||||
-rw-r--r-- | src/client/views/presentationview/PresElementBox.tsx | 2 |
11 files changed, 266 insertions, 31 deletions
diff --git a/deploy/index.html b/deploy/index.html index 282acc0ce..af67ac301 100644 --- a/deploy/index.html +++ b/deploy/index.html @@ -7,9 +7,74 @@ <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> <script src="https://cdnjs.cloudflare.com/ajax/libs/typescript/3.3.1/typescript.min.js"></script> + <style> + .dash-loader { + display: flex; + align-content: center; + justify-content: center; + background-color: #AEDDF8; + z-index: 10; + width: 100%; + height: 100%; + } + + .dash-loader-container { + width: 20vw; + height: 20vw; + display: flex; + align-items: center; + justify-content: center; + border-radius: 100%; + background-color: #5B9FDD; + align-self: center; + } + + .dash-d-path { + stroke-dasharray: 1000; + stroke-dashoffset: 1000; + animation: dash-d-path 3s linear infinite; + } + + @keyframes dash-d-path { + 0% { + stroke-dashoffset: 1000; + /* stroke-width: 0px; */ + } + + 20% { + stroke-dashoffset: 0; + /* stroke-width: 20px; */ + } + + 70% { + stroke-dashoffset: 0; + /* stroke-width: 20px; */ + } + + 90% { + stroke-dashoffset: 1000; + /* stroke-width: 0px; */ + } + + 100% { + stroke-dashoffset: 1000; + /* stroke-width: 0px; */ + } + } + </style> </head> <body style="display:flex" id="dash-body"> + <div class="dash-loader" id="loader" style="z-index:10; width:100%; height:100%"> + <div class="dash-loader-container"> + <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200px" + height="200px" viewBox="0 0 250 350"> + <path class="dash-d-path" fill-rule="evenodd" stroke="#ececec" stroke-width="20px" stroke-linecap="butt" + stroke-linejoin="miter" fill="none" + d="M196.500,18.500 C195.888,79.462 194.655,160.273 197.500,195.500 C198.117,203.144 199.664,225.773 189.500,246.500 C183.949,257.819 175.192,268.535 163.500,277.500 C147.404,289.842 133.006,294.212 121.500,295.500 C106.618,297.166 92.057,294.673 79.500,288.500 C68.970,283.324 58.384,274.780 49.500,261.500 C39.958,247.237 35.188,230.375 35.500,213.500 C35.760,199.463 39.572,185.692 46.500,173.500 C55.433,157.780 65.945,148.829 75.500,143.500 C85.352,138.005 98.187,134.141 114.500,134.500 C128.982,134.819 143.177,139.076 155.500,146.500 C186.160,164.973 196.208,196.242 197.500,216.500 C197.663,219.061 197.578,222.985 197.500,226.500 C197.092,244.967 195.719,262.030 195.500,280.500 C195.460,283.898 195.500,293.783 195.500,300.500 C195.500,304.834 195.500,309.189 195.500,313.500 " /> + </svg> + </div> + </div> <!-- <script src="https://hypothes.is/embed.js" async></script> --> <div id="root" style="position:absolute;width:100%;height:100%;overflow: hidden;"></div> <script src="/bundle.js"></script> diff --git a/deploy/loader.css b/deploy/loader.css new file mode 100644 index 000000000..065862013 --- /dev/null +++ b/deploy/loader.css @@ -0,0 +1,141 @@ +.dash-loader { + display: flex; + align-content: center; + justify-content: center; + background-color: lightcyan; + z-index: 10; + width: 100%; + height: 100%; +} + +.dash-loader-container { + width: 100; + align-self: center; +} + +.dash-d-path { + stroke-dasharray: 1000; + stroke-dashoffset: 1000; + animation: dash-d-path 10s linear infinite; +} + +@keyframes dash-d-path { + 0% { + stroke-dashoffset: 1000; + /* stroke-width: 0px; */ + } + + 10% { + stroke-dashoffset: 0; + /* stroke-width: 20px; */ + } + + 90% { + stroke-dashoffset: 0; + /* stroke-width: 20px; */ + } + + 100% { + stroke-dashoffset: 1000; + /* stroke-width: 0px; */ + } +} + +.dash-a-path { + stroke-dasharray: 1000; + stroke-dashoffset: 1000; + animation: dash-a-path 10s linear infinite; +} + +@keyframes dash-a-path { + 0% { + stroke-dashoffset: 1000; + /* stroke-width: 0px; */ + } + + 7% { + stroke-dashoffset: 1000; + /* stroke-width: 0px; */ + } + + 17% { + stroke-dashoffset: 0; + /* stroke-width: 20px; */ + } + + 90% { + stroke-dashoffset: 0; + /* stroke-width: 20px; */ + } + + 100% { + stroke-dashoffset: 1000; + /* stroke-width: 0px; */ + } +} + +.dash-s-path { + stroke-dasharray: 1000; + stroke-dashoffset: 1000; + animation: dash-s-path 10s linear infinite; +} + +@keyframes dash-s-path { + 0% { + stroke-dashoffset: 1000; + /* stroke-width: 0px; */ + } + + 14% { + stroke-dashoffset: 1000; + /* stroke-width: 0px; */ + } + + 20% { + stroke-dashoffset: 0; + /* stroke-width: 20px; */ + } + + 90% { + stroke-dashoffset: 0; + /* stroke-width: 20px; */ + } + + 100% { + stroke-dashoffset: 1000; + /* stroke-width: 0px; */ + } +} + +.dash-h-path { + stroke-dasharray: 1000; + stroke-dashoffset: 1000; + animation: dash-h-path 10s linear infinite; +} + +@keyframes dash-h-path { + 0% { + stroke-dashoffset: 1000; + /* stroke-width: 0px; */ + } + + 18% { + stroke-dashoffset: 1000; + /* stroke-width: 0px; */ + } + + 28% { + stroke-dashoffset: 0; + /* stroke-width: 20px; */ + } + + 90% { + stroke-dashoffset: 0; + /* stroke-width: 20px; */ + } + + 100% { + stroke-dashoffset: 1000; + /* stroke-width: 0px; */ + } +}
\ No newline at end of file diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 99dfbaf1c..213bc3d88 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -63,7 +63,7 @@ export class CurrentUserUtils { [this.ficon({ ignoreClick: true, icon: "mobile", - backgroundColor: "rgba(0,0,0,0)" + backgroundColor: "transparent" }), this.mobileTextContainer({}, [this.mobileButtonText({}, "NEW MOBILE BUTTON"), this.mobileButtonInfo({}, "You can customize this button and make it your own.")])]); diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index ce526f842..03d2e33df 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -86,6 +86,13 @@ export class MainView extends React.Component { componentDidMount() { document.getElementById("root")?.addEventListener("scroll", e => ((ele) => ele.scrollLeft = ele.scrollTop = 0)(document.getElementById("root")!)); + const ele = document.getElementById("loader"); + if (ele) { + setTimeout(() => { + // remove from DOM + ele.outerHTML = ''; + }, 0); + } new InkStrokeProperties(); this._sidebarContent.proto = undefined; DocServer.setPlaygroundFields(["x", "y", "dataTransition", "_delayAutoHeight", "_autoHeight", "_showSidebar", "_sidebarWidthPercent", "_width", "_height", "_viewTransition", "_panX", "_panY", "_viewScale", "_scrollY", "_scrollTop", "hidden", "_curPage", "_viewType", "_chromeStatus"]); // can play with these fields on someone else's diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index 245e612b3..97bca110b 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -992,7 +992,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { <div className="propertiesView-title" style={{ width: this.props.width }}> Presentation </div> - <div className="propertiesView-name"> + <div className="propertiesView-name" style={{ borderBottom: 0 }}> {this.editableTitle} <div className="propertiesView-presSelected"> <div className="propertiesView-selectedCount"> @@ -1029,7 +1029,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { {PresBox.Instance.progressivizeDropdown} </div> : null} </div>} */} - {/* {!selectedItem || (!scrollable && !pannable) ? (null) : <div className="propertiesView-presTrails"> + {!selectedItem ? (null) : <div className="propertiesView-presTrails"> <div className="propertiesView-presTrails-title" onPointerDown={action(() => { this.openSlideOptions = !this.openSlideOptions; })} style={{ backgroundColor: this.openSlideOptions ? "black" : "" }}> @@ -1041,7 +1041,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { {this.openSlideOptions ? <div className="propertiesView-presTrails-content"> {PresBox.Instance.optionsDropdown} </div> : null} - </div>} */} + </div>} {/* <div className="propertiesView-presTrails"> <div className="propertiesView-presTrails-title" onPointerDown={action(() => { this.openAddSlide = !this.openAddSlide; })} diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 4b3393e14..35331cc15 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -290,7 +290,7 @@ export class CollectionStackingView extends CollectionSubView<StackingDocument, dropAfter = where[axis] > (pos[axis] + pos1[axis]) / 2 ? 1 : 0; } }); - const oldDocs = this.childDocs.length; + // const oldDocs = this.childDocs.length; if (super.onInternalDrop(e, de)) { const droppedDocs = this.childDocs.slice().filter((d: Doc, ind: number) => ind >= oldDocs); // if the drop operation adds something to the end of the list, then use that as the new document (may be different than what was dropped e.g., in the case of a button which is dropped but which creates say, a note). const newDocs = droppedDocs.length ? droppedDocs : de.complete.docDragData.droppedDocuments; // if nothing was added to the end of the list, then presumably the dropped documents were already in the list, but possibly got reordered so we use them. diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx index 7f8f57088..4c0073dcc 100644 --- a/src/client/views/collections/TabDocView.tsx +++ b/src/client/views/collections/TabDocView.tsx @@ -442,8 +442,8 @@ export class TabDocView extends React.Component<TabDocViewProps> { let docColor = StrCast(doc?._backgroundColor, StrCast(doc?.backgroundColor)); if (!docColor) { switch (doc?.type) { - case DocumentType.PRESELEMENT: docColor = TabDocView.darkScheme ? "dimgrey" : ""; break; - case DocumentType.PRES: docColor = TabDocView.darkScheme ? "#3e3e3e" : "black"; break; + case DocumentType.PRESELEMENT: docColor = TabDocView.darkScheme ? "" : ""; break; + case DocumentType.PRES: docColor = TabDocView.darkScheme ? "#3e3e3e" : "white"; break; case DocumentType.FONTICON: docColor = "black"; break; case DocumentType.RTF: docColor = TabDocView.darkScheme ? "#2d2d2d" : "#f1efeb"; case DocumentType.LABEL: diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx index 4f6c5cebe..1bdba7f9e 100644 --- a/src/client/views/nodes/AudioBox.tsx +++ b/src/client/views/nodes/AudioBox.tsx @@ -27,6 +27,8 @@ import Waveform from "react-audio-waveform"; import axios from "axios"; import { SnappingManager } from "../../util/SnappingManager"; import { CurrentUserUtils } from "../../util/CurrentUserUtils"; +import { LinkDocPreview } from "./LinkDocPreview"; +import { FormattedTextBoxComment } from "./formattedText/FormattedTextBoxComment"; declare class MediaRecorder { // whatever MediaRecorder has @@ -49,6 +51,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps, AudioD _linkPlayDisposer: IReactionDisposer | undefined; _reactionDisposer: IReactionDisposer | undefined; _scrubbingDisposer: IReactionDisposer | undefined; + private _disposers: { [name: string]: IReactionDisposer } = {}; _ele: HTMLAudioElement | null = null; _recorder: any; _recordStart = 0; @@ -106,9 +109,10 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps, AudioD } componentWillUnmount() { - this._reactionDisposer?.(); - this._linkPlayDisposer?.(); - this._scrubbingDisposer?.(); + this._disposers.reaction?.(); + this._disposers.linkPlay?.(); + this._disposers.scrubbing?.(); + this._disposers.audioStart?.(); } @action @@ -118,7 +122,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps, AudioD } this.audioState = this.path ? "paused" : undefined; - this._linkPlayDisposer = reaction(() => this.layoutDoc.scrollToLinkID, + this._disposers.linkPlay = reaction(() => this.layoutDoc.scrollToLinkID, scrollLinkId => { if (scrollLinkId) { DocListCast(this.dataDoc.links).filter(l => l[Id] === scrollLinkId).map(l => { @@ -130,7 +134,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps, AudioD }, { fireImmediately: true }); // for play when link is selected - this._reactionDisposer = reaction(() => SelectionManager.SelectedDocuments(), + this._disposers.reaction = reaction(() => SelectionManager.SelectedDocuments(), selected => { const sel = selected.length ? selected[0].props.Document : undefined; let link; @@ -145,7 +149,22 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps, AudioD this.layoutDoc.playOnSelect && this.recordingStart && !sel && this.pause(); } }); - this._scrubbingDisposer = reaction(() => AudioBox._scrubTime, (time) => this.layoutDoc.playOnSelect && this.playFromTime(AudioBox._scrubTime)); + this._disposers.scrubbing = reaction(() => AudioBox._scrubTime, (time) => this.layoutDoc.playOnSelect && this.playFromTime(AudioBox._scrubTime)); + + this._disposers._audioStart = reaction( + () => this.Document._audioStart, + (audioStart) => { + if (audioStart !== undefined) { + if (this.props.renderDepth !== -1 && !LinkDocPreview.TargetDoc && !FormattedTextBoxComment.linkDoc) { + const delay = this._audioRef.current ? 0 : 250; // wait for mainCont and try again to play + const startTime: number = NumCast(this.Document._audioStart); + setTimeout(() => this._audioRef.current && this.playFrom(startTime), delay); + setTimeout(() => { this.Document._currentTimecode = startTime; this.Document._audioStart = undefined; }, 10 + delay); + } + } + }, + { fireImmediately: true } + ); } playLink = (doc: Doc) => { diff --git a/src/client/views/nodes/PresBox.scss b/src/client/views/nodes/PresBox.scss index de2aee8fa..56b3b0593 100644 --- a/src/client/views/nodes/PresBox.scss +++ b/src/client/views/nodes/PresBox.scss @@ -420,20 +420,20 @@ $light-background: #ececec; background-color: #ececec; border: 1px solid #9f9f9f; grid-template-rows: max-content; - + .frameList-header { display: grid; width: 100%; height: 20px; background-color: #9f9f9f; - + .frameList-headerButtons { display: flex; grid-column: 7; width: 60px; justify-self: right; justify-content: flex-end; - + .headerButton { cursor: pointer; position: relative; @@ -452,7 +452,7 @@ $light-background: #ececec; transition: 0.2s; margin-right: 3px; } - + .headerButton:hover { background-color: rgba(0, 0, 0, 1); transform: scale(1.15); @@ -1061,7 +1061,7 @@ $light-background: #ececec; background-color: #5a5a5a; } - + } // .miniPres { diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx index 455ee87e1..dd6e368e8 100644 --- a/src/client/views/nodes/PresBox.tsx +++ b/src/client/views/nodes/PresBox.tsx @@ -117,7 +117,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> if (Doc.UserDoc().activePresentation = this.rootDoc) runInAction(() => PresBox.Instance = this); if (!this.presElement) { // create exactly one presElmentBox template to use by any and all presentations. Doc.UserDoc().presElement = new PrefetchProxy(Docs.Create.PresElementBoxDocument({ - title: "pres element template", type: DocumentType.PRESELEMENT, backgroundColor: "transparent", _xMargin: 0, isTemplateDoc: true, isTemplateForField: "data" + title: "pres element template", type: DocumentType.PRESELEMENT, _xMargin: 0, isTemplateDoc: true, isTemplateForField: "data" })); // this script will be called by each presElement to get rendering-specific info that the PresBox knows about but which isn't written to the PresElement // this is a design choice -- we could write this data to the presElements which would require a reaction to keep it up to date, and it would prevent @@ -191,7 +191,9 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> // 'Play on next' for audio or video therefore first navigate to the audio/video before it should be played nextAudioVideo = (targetDoc: Doc, activeItem: Doc) => { - if (targetDoc.type === DocumentType.AUDIO) AudioBox.Instance.playFrom(NumCast(activeItem.presStartTime)); + if (targetDoc.type === DocumentType.AUDIO) { + targetDoc._audioStart = NumCast(activeItem.presStartTime); + } // if (targetDoc.type === DocumentType.VID) { VideoBox.Instance.Play() }; activeItem.playNow = false; } @@ -201,13 +203,12 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> const nextSelected = this.itemIndex + 1; this.gotoDocument(nextSelected); - // const targetNext = Cast(activeNext.presentationTargetDoc, Doc, null); + const targetNext = Cast(activeNext.presentationTargetDoc, Doc, null); // If next slide is audio / video 'Play automatically' then the next slide should be played - // if (activeNext && (targetNext.type === DocumentType.AUDIO || targetNext.type === DocumentType.VID) && activeNext.playAuto) { - // console.log('play next automatically'); - // if (targetNext.type === DocumentType.AUDIO) AudioBox.Instance.playFrom(NumCast(activeNext.presStartTime)); - // // if (targetNext.type === DocumentType.VID) { VideoBox.Instance.Play() }; - // } else if (targetNext.type === DocumentType.AUDIO || targetNext.type === DocumentType.VID) { activeNext.playNow = true; console.log('play next after it is navigated to'); } + if (activeNext && (targetNext.type === DocumentType.AUDIO || targetNext.type === DocumentType.VID) && activeNext.playAuto) { + if (targetNext.type === DocumentType.AUDIO) targetNext._audioStart = NumCast(activeNext.presStartTime); + // if (targetNext.type === DocumentType.VID) { VideoBox.Instance.Play() }; + } else if (targetNext.type === DocumentType.AUDIO || targetNext.type === DocumentType.VID) { activeNext.playNow = true; console.log('play next after it is navigated to'); } } // Called when the user activates 'next' - to move to the next part of the pres. trail @@ -229,11 +230,10 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> } else if (this.childDocs[this.itemIndex + 1] === undefined && this.layoutDoc.presLoop) { // Case 4: Last slide and presLoop is toggled ON this.gotoDocument(0); + } else if ((targetDoc.type === DocumentType.AUDIO || targetDoc.type === DocumentType.VID) && !activeItem.playAuto && activeItem.playNow && this.layoutDoc.presStatus !== PresStatus.Autoplay) { + // Case 2: 'Play on next' for audio or video therefore first navigate to the audio/video before it should be played + this.nextAudioVideo(targetDoc, activeItem); } - // else if ((targetDoc.type === DocumentType.AUDIO || targetDoc.type === DocumentType.VID) && !activeItem.playAuto && activeItem.playNow && this.layoutDoc.presStatus !== PresStatus.Autoplay) { - // // Case 2: 'Play on next' for audio or video therefore first navigate to the audio/video before it should be played - // this.nextAudioVideo(targetDoc, activeItem); - // } } // Called when the user activates 'back' - to move to the previous part of the pres. trail @@ -610,6 +610,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> addDocumentFilter = (doc: Doc | Doc[]) => { const docs = doc instanceof Doc ? [doc] : doc; docs.forEach((doc, i) => { + if (doc.presentationTargetDoc) return true; if (doc.type === DocumentType.LABEL) { const audio = Cast(doc.annotationOn, Doc, null); if (audio) { @@ -1926,7 +1927,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> <FontAwesomeIcon className={`dropdown ${this.newDocumentTools ? "active" : ""}`} icon={"angle-down"} /> </div></Tooltip> */} <Tooltip title={<><div className="dash-tooltip">{"View paths"}</div></>}> - <div style={{ opacity: this.childDocs.length > 1 ? 1 : 0.3, color: this._pathBoolean ? PresColor.DarkBlue : 'white', width: isMini ? "100%" : undefined }} className={"toolbar-button"} onClick={this.childDocs.length > 1 ? this.viewPaths : undefined}> + <div style={{ opacity: this.childDocs.length > 1 && this.layoutDoc.presCollection ? 1 : 0.3, color: this._pathBoolean ? PresColor.DarkBlue : 'white', width: isMini ? "100%" : undefined }} className={"toolbar-button"} onClick={this.childDocs.length > 1 && this.layoutDoc.presCollection ? this.viewPaths : undefined}> <FontAwesomeIcon icon={"exchange-alt"} /> </div> </Tooltip> diff --git a/src/client/views/presentationview/PresElementBox.tsx b/src/client/views/presentationview/PresElementBox.tsx index 8d4bd4b8b..49049b805 100644 --- a/src/client/views/presentationview/PresElementBox.tsx +++ b/src/client/views/presentationview/PresElementBox.tsx @@ -305,10 +305,12 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDoc onPointerUp={this.headerUp} > {miniView ? + // when width is LESS than 110 px <div className={`presItem-miniSlide ${isSelected ? "active" : ""}`} ref={miniView ? this._dragRef : null}> {`${this.indexInPres + 1}.`} </div> : + // when width is MORE than 110 px <div className="presItem-number"> {`${this.indexInPres + 1}.`} </div>} |