diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/client/util/DocumentManager.ts | 6 | ||||
-rw-r--r-- | src/client/views/.DS_Store | bin | 6148 -> 10244 bytes | |||
-rw-r--r-- | src/client/views/MainView.tsx | 6 | ||||
-rw-r--r-- | src/client/views/PropertiesButtons.tsx | 46 | ||||
-rw-r--r-- | src/client/views/collections/CollectionDockingView.scss | 15 | ||||
-rw-r--r-- | src/client/views/collections/CollectionDockingView.tsx | 30 | ||||
-rw-r--r-- | src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx | 32 | ||||
-rw-r--r-- | src/client/views/collections/collectionFreeForm/PropertiesView.scss | 37 | ||||
-rw-r--r-- | src/client/views/collections/collectionFreeForm/PropertiesView.tsx | 76 | ||||
-rw-r--r-- | src/client/views/nodes/PresBox.scss | 142 | ||||
-rw-r--r-- | src/client/views/nodes/PresBox.tsx | 723 | ||||
-rw-r--r-- | src/client/views/nodes/formattedText/FormattedTextBox.tsx | 19 | ||||
-rw-r--r-- | src/client/views/presentationview/PresElementBox.scss | 12 | ||||
-rw-r--r-- | src/client/views/presentationview/PresElementBox.tsx | 14 |
14 files changed, 590 insertions, 568 deletions
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index d18eac374..523dbfca0 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -127,10 +127,6 @@ export class DocumentManager { CollectionDockingView.AddRightSplit(doc); finished?.(); } - // static openInPlace = (doc: Doc, finished?: () => void) => { - // CollectionDockingView.AddTab(doc); - // finished?.(); - // } public jumpToDocument = async ( targetDoc: Doc, // document to display willZoom: boolean, // whether to zoom doc to take up most of screen @@ -180,7 +176,7 @@ export class DocumentManager { const targetDocContextView = getFirstDocView(targetDocContext); targetDocContext._scrollY = 0; // this will force PDFs to activate and load their annotations / allow scrolling if (targetDocContextView) { // we found a context view and aren't forced to create a new one ... focus on the context first.. - targetDocContext._viewTransition = "transform 10000ms"; + targetDocContext._viewTransition = "transform 500ms"; targetDocContextView.props.focus(targetDocContextView.props.Document, willZoom); // now find the target document within the context diff --git a/src/client/views/.DS_Store b/src/client/views/.DS_Store Binary files differindex 3ce88292c..c379549d0 100644 --- a/src/client/views/.DS_Store +++ b/src/client/views/.DS_Store diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index f7c7b542f..2ed485188 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -175,10 +175,8 @@ export class MainView extends React.Component { fa.faFillDrip, fa.faLink, fa.faUnlink, fa.faBold, fa.faItalic, fa.faChevronLeft, fa.faUnderline, fa.faStrikethrough, fa.faSuperscript, fa.faSubscript, fa.faIndent, fa.faEyeDropper, fa.faPaintRoller, fa.faBars, fa.faBrush, fa.faShapes, fa.faEllipsisH, fa.faHandPaper, fa.faMap, fa.faUser, faHireAHelper, fa.faDesktop, fa.faTrashRestore, fa.faUsers, fa.faWrench, fa.faCog, fa.faMap, fa.faBellSlash, fa.faExpandAlt, fa.faArchive, fa.faBezierCurve, fa.faCircle, - fa.faLongArrowAltRight, fa.faPenFancy, fa.faAngleDoubleRight, faBuffer, fa.faExpand, fa.faUndo, fa.faSlidersH, fa.faAngleDoubleLeft); - //Pres trail icons (just for the sake of merging) - library.add(fa.faAngleUp, fa.faAngleDown, fa.faPlayCircle, fa.faClock, - fa.faRocket, fa.faExchangeAlt, faBuffer); + fa.faLongArrowAltRight, fa.faPenFancy, fa.faAngleDoubleRight, faBuffer, fa.faExpand, fa.faUndo, fa.faSlidersH, fa.faAngleDoubleLeft, fa.faAngleUp, + fa.faAngleDown, fa.faPlayCircle, fa.faClock, fa.faRocket, fa.faExchangeAlt, faBuffer); this.initEventListeners(); this.initAuthenticationRouters(); } diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx index 29afd447f..5c584d270 100644 --- a/src/client/views/PropertiesButtons.tsx +++ b/src/client/views/PropertiesButtons.tsx @@ -221,8 +221,7 @@ export class PropertiesButtons extends React.Component<{}, {}> { <div className="propertiesButtons-linker" style={{ backgroundColor: isPinned ? "white" : "", color: isPinned ? "black" : "white" }} onClick={e => DockedFrameRenderer.PinDoc(targetDoc, isPinned)}> - <FontAwesomeIcon className="documentdecorations-icon" size="lg" icon="map-pin" - /> + <FontAwesomeIcon className="documentdecorations-icon" size="lg" icon="map-pin" /> </div> <div className="propertiesButtons-title" style={{ @@ -237,31 +236,34 @@ export class PropertiesButtons extends React.Component<{}, {}> { @computed get pinWithViewButton() { const targetDoc = this.selectedDoc; - const isPinned = targetDoc && Doc.isDocPinned(targetDoc); if (targetDoc) { const x = targetDoc._panX; const y = targetDoc._panY; const scale = targetDoc._viewScale; } - return !targetDoc ? (null) : <Tooltip title={<><div className="dash-tooltip">{"Pin with this view"}</div></>}> - <div className="propertiesButtons-linker" - style={{ backgroundColor: "white", color: "black" }} - onClick={e => { - if (targetDoc) { - DockedFrameRenderer.PinDoc(targetDoc, false); - const activeDoc = PresBox.Instance.childDocs[PresBox.Instance.childDocs.length - 1]; - const x = targetDoc._panX; - const y = targetDoc._panY; - const scale = targetDoc._viewScale; - activeDoc.presPinView = true; - activeDoc.presPinViewX = x; - activeDoc.presPinViewY = y; - activeDoc.presPinViewScale = scale; - } - }}> - <div style={{ position: 'absolute', fontSize: 25, fontWeight: 700, transform: 'translate(42%, -7px)', color: 'rgba(0,0,0,0.2)' }}>V</div> - <FontAwesomeIcon className="documentdecorations-icon" size="sm" icon="map-pin" /> - </div></Tooltip>; + return !targetDoc ? (null) : <Tooltip title={<><div className="dash-tooltip">{"Pin with this view"}</div></>} placement="top"> + <div> + <div className="propertiesButtons-linker" + onClick={e => { + if (targetDoc) { + DockedFrameRenderer.PinDoc(targetDoc, false); + const activeDoc = PresBox.Instance.childDocs[PresBox.Instance.childDocs.length - 1]; + const x = targetDoc._panX; + const y = targetDoc._panY; + const scale = targetDoc._viewScale; + activeDoc.presPinView = true; + activeDoc.presPinViewX = x; + activeDoc.presPinViewY = y; + activeDoc.presPinViewScale = scale; + } + }}> + <FontAwesomeIcon className="documentdecorations-icon" size="lg" icon="map-pin" /> + <div style={{ position: 'relative', fontSize: 25, fontWeight: 700, transform: 'translate(0, -20px)', color: 'rgba(250,250,250,0.5)' }}>V</div> + </div> + + <div className="propertiesButtons-title">{"View"}</div> + </div> + </Tooltip>; } diff --git a/src/client/views/collections/CollectionDockingView.scss b/src/client/views/collections/CollectionDockingView.scss index 98babc3d2..4204ef5bb 100644 --- a/src/client/views/collections/CollectionDockingView.scss +++ b/src/client/views/collections/CollectionDockingView.scss @@ -54,6 +54,21 @@ transition: all 0.3s; } + .miniPres-button-frame { + justify-self: center; + align-self: center; + align-items: center; + display: grid; + grid-template-columns: auto auto auto; + justify-content: space-around; + font-size: 11; + margin-left: 7; + width: 30; + height: 85%; + background-color: rgba(91, 157, 221, 0.4); + border-radius: 5px; + } + .miniPres-divider { width: 0.5px; height: 80%; diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 6d4a7f311..7e096fa37 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -870,20 +870,24 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> { return currentFrame; } renderMiniPres() { - return <div className="miniPres" style={{ - width: 250, height: 30, background: '#323232' - }}> - <div className="miniPresOverlay" > - <div className="miniPres-button" onClick={PresBox.Instance.back}><FontAwesomeIcon icon={"arrow-left"} /></div> - <div className="miniPres-button" onClick={() => PresBox.Instance.startOrResetPres(PresBox.Instance.itemIndex)}><FontAwesomeIcon icon={PresBox.Instance.layoutDoc.presStatus === "auto" ? "pause" : "play"} /></div> - <div className="miniPres-button" onClick={PresBox.Instance.next}><FontAwesomeIcon icon={"arrow-right"} /></div> - <div className="miniPres-divider"></div> - <div className="miniPres-button-text">Slide {PresBox.Instance.itemIndex + 1} / {PresBox.Instance.childDocs.length}</div> - {/* <div className="miniPres-button-text">{this.getCurrentFrame}</div> */} - <div className="miniPres-divider"></div> - <div className="miniPres-button-text" onClick={PresBox.Instance.updateMinimize}>EXIT</div> + return ( + <div className="miniPres" + style={{ width: 250, height: 30, background: '#323232' }} + > + {<div className="miniPresOverlay"> + <div className="miniPres-button" onClick={PresBox.Instance.back}><FontAwesomeIcon icon={"arrow-left"} /></div> + <div className="miniPres-button" onClick={() => PresBox.Instance.startAutoPres(PresBox.Instance.itemIndex)}><FontAwesomeIcon icon={PresBox.Instance.layoutDoc.presStatus === "auto" ? "pause" : "play"} /></div> + <div className="miniPres-button" onClick={PresBox.Instance.next}><FontAwesomeIcon icon={"arrow-right"} /></div> + <div className="miniPres-divider"></div> + <div className="miniPres-button-text"> + Slide {PresBox.Instance.itemIndex + 1} / {PresBox.Instance.childDocs.length} + {PresBox.Instance.playButtonFrames} + </div> + <div className="miniPres-divider"></div> + <div className="miniPres-button-text" onClick={PresBox.Instance.updateMinimize}>EXIT</div> + </div>} </div> - </div>; + ); } renderMiniMap() { return <div className="miniMap" style={{ diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index ffeb3024d..5b1f3c01c 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -1495,33 +1495,18 @@ interface CollectionFreeFormViewPannableContentsProps { @observer class CollectionFreeFormViewPannableContents extends React.Component<CollectionFreeFormViewPannableContentsProps>{ @computed get zoomProgressivize() { - if (this.props.zoomProgressivize) { - console.log("should render"); - return ( - <> - {PresBox.Instance.zoomProgressivizeContainer} - </> - ); - } + return PresBox.Instance && this.props.zoomProgressivize ? PresBox.Instance.zoomProgressivizeContainer : (null); } @computed get progressivize() { - if (this.props.progressivize) { - console.log("should render"); - return ( - <> - {PresBox.Instance.progressivizeChildDocs} - </> - ); - } + return PresBox.Instance && this.props.progressivize ? PresBox.Instance.progressivizeChildDocs : (null); } @computed get presPaths() { const presPaths = "presPaths" + (this.props.presPaths ? "" : "-hidden"); - if (this.props.presPaths) { - return ( - <> - <div>{PresBox.Instance.order}</div> + if (PresBox.Instance) return ( + <> + {!this.props.presPaths ? (null) : <><div>{PresBox.Instance.order}</div> <svg className={presPaths}> <defs> <marker id="arrow" markerWidth="3" overflow="visible" markerHeight="3" refX="5" refY="5" orient="auto" markerUnits="strokeWidth"> @@ -1542,10 +1527,9 @@ class CollectionFreeFormViewPannableContents extends React.Component<CollectionF </marker> </defs>; {PresBox.Instance.paths} - </svg> - </> - ); - } + </svg></>} + </> + ); } render() { diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.scss b/src/client/views/collections/collectionFreeForm/PropertiesView.scss index fef1db9aa..5e0c9fcbb 100644 --- a/src/client/views/collections/collectionFreeForm/PropertiesView.scss +++ b/src/client/views/collections/collectionFreeForm/PropertiesView.scss @@ -424,6 +424,43 @@ } } + + .propertiesView-presTrails { + border-bottom: 1px solid black; + //padding: 8.5px; + + .propertiesView-presTrails-title { + font-weight: bold; + font-size: 12.5px; + padding: 4px; + display: flex; + color: white; + padding-left: 8px; + background-color: rgb(51, 51, 51); + + &:hover { + cursor: pointer; + } + + .propertiesView-presTrails-title-icon { + float: right; + right: 0; + position: absolute; + margin-left: 2px; + margin-right: 9px; + + &:hover { + cursor: pointer; + } + } + } + + .propertiesView-presTrails-content { + font-size: 10px; + padding: 10px; + margin-left: 5px; + } + } } .inking-button { diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx index 5634a438a..1a8ee3ea1 100644 --- a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx +++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx @@ -52,8 +52,8 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { @computed get selectedDocumentView() { if (SelectionManager.SelectedDocuments().length) { return SelectionManager.SelectedDocuments()[0]; - } else if (PresBox.Instance?._selectedArray.length >= 1) { - return DocumentManager.Instance.getDocumentView(PresBox.Instance?.rootDoc); + } else if (PresBox.Instance._selectedArray.length) { + return DocumentManager.Instance.getDocumentView(PresBox.Instance.rootDoc); } else { return undefined; } } @computed get isPres(): boolean { @@ -75,11 +75,10 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { // @observable addButtonPressed: boolean = false; //Pres Trails booleans: - @observable openAddSlide: boolean = true; - @observable openPresentationTools: boolean = true; - @observable openPresTransitions: boolean = true; - @observable openPresProgressivize: boolean = true; - @observable openSlideOptions: boolean = true; + @observable openPresTransitions: boolean = false; + @observable openPresProgressivize: boolean = false; + @observable openAddSlide: boolean = false; + @observable openSlideOptions: boolean = false; @observable inActions: boolean = false; @observable _controlBtn: boolean = false; @@ -949,6 +948,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { </div>; } if (this.isPres) { + const selectedItem: boolean = PresBox.Instance._selectedArray.length > 0; return <div className="propertiesView" style={{ width: this.props.width }} > <div className="propertiesView-title" style={{ width: this.props.width }}> Presentation @@ -965,56 +965,56 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { </div> </div> </div> - <div className="propertiesView-settings"> - <div className="propertiesView-settings-title" - onPointerDown={() => runInAction(() => { this.openAddSlide = !this.openAddSlide; })} - style={{ backgroundColor: this.openAddSlide ? "black" : "" }}> - <FontAwesomeIcon icon={"plus"} /> Add new slide - <div className="propertiesView-settings-title-icon"> - <FontAwesomeIcon icon={this.openAddSlide ? "caret-down" : "caret-right"} size="lg" color="white" /> - </div> - </div> - {this.openAddSlide ? <div className="propertiesView-settings-content"> - {PresBox.Instance?.newDocumentDropdown} - </div> : null} - </div> - <div className="propertiesView-sharing"> - <div className="propertiesView-sharing-title" + {!selectedItem ? (null) : <div className="propertiesView-presTrails"> + <div className="propertiesView-presTrails-title" onPointerDown={() => runInAction(() => { this.openPresTransitions = !this.openPresTransitions; })} style={{ backgroundColor: this.openPresTransitions ? "black" : "" }}> <FontAwesomeIcon icon={"rocket"} /> Transitions - <div className="propertiesView-sharing-title-icon"> + <div className="propertiesView-presTrails-title-icon"> <FontAwesomeIcon icon={this.openPresTransitions ? "caret-down" : "caret-right"} size="lg" color="white" /> </div> </div> - {this.openPresTransitions ? <div className="propertiesView-sharing-content"> - {PresBox.Instance?.transitionDropdown} + {this.openPresTransitions ? <div className="propertiesView-presTrails-content"> + {PresBox.Instance.transitionDropdown} </div> : null} - </div> - <div className="propertiesView-sharing"> - <div className="propertiesView-sharing-title" + </div>} + {!selectedItem ? (null) : <div className="propertiesView-presTrails"> + <div className="propertiesView-presTrails-title" onPointerDown={() => runInAction(() => { this.openPresProgressivize = !this.openPresProgressivize; })} style={{ backgroundColor: this.openPresProgressivize ? "black" : "" }}> <FontAwesomeIcon icon={"tasks"} /> Progressivize - <div className="propertiesView-sharing-title-icon"> + <div className="propertiesView-presTrails-title-icon"> <FontAwesomeIcon icon={this.openPresProgressivize ? "caret-down" : "caret-right"} size="lg" color="white" /> </div> </div> - {this.openPresProgressivize ? <div className="propertiesView-sharing-content"> - {PresBox.Instance?.progressivizeDropdown} + {this.openPresProgressivize ? <div className="propertiesView-presTrails-content"> + {PresBox.Instance.progressivizeDropdown} </div> : null} - </div> - <div className="propertiesView-sharing"> - <div className="propertiesView-sharing-title" + </div>} + {!selectedItem ? (null) : <div className="propertiesView-presTrails"> + <div className="propertiesView-presTrails-title" onPointerDown={() => runInAction(() => { this.openSlideOptions = !this.openSlideOptions; })} style={{ backgroundColor: this.openSlideOptions ? "black" : "" }}> - <FontAwesomeIcon icon={"cog"} /> {PresBox.Instance?.stringType} options - <div className="propertiesView-sharing-title-icon"> + <FontAwesomeIcon icon={"cog"} /> {PresBox.Instance.stringType} options + <div className="propertiesView-presTrails-title-icon"> <FontAwesomeIcon icon={this.openSlideOptions ? "caret-down" : "caret-right"} size="lg" color="white" /> </div> </div> - {this.openSlideOptions ? <div className="propertiesView-sharing-content"> - {PresBox.Instance?.optionsDropdown} + {this.openSlideOptions ? <div className="propertiesView-presTrails-content"> + {PresBox.Instance.optionsDropdown} + </div> : null} + </div>} + <div className="propertiesView-presTrails"> + <div className="propertiesView-presTrails-title" + onPointerDown={() => runInAction(() => { this.openAddSlide = !this.openAddSlide; })} + style={{ backgroundColor: this.openAddSlide ? "black" : "" }}> + <FontAwesomeIcon icon={"plus"} /> Add new slide + <div className="propertiesView-presTrails-title-icon"> + <FontAwesomeIcon icon={this.openAddSlide ? "caret-down" : "caret-right"} size="lg" color="white" /> + </div> + </div> + {this.openAddSlide ? <div className="propertiesView-presTrails-content"> + {PresBox.Instance.newDocumentDropdown} </div> : null} </div> <div className="propertiesView-sharing"> diff --git a/src/client/views/nodes/PresBox.scss b/src/client/views/nodes/PresBox.scss index 16821f5bc..a87b0e466 100644 --- a/src/client/views/nodes/PresBox.scss +++ b/src/client/views/nodes/PresBox.scss @@ -1,3 +1,7 @@ +$light-blue: #AEDDF8; +$dark-blue: #5B9FDD; +$light-background: #ececec; + .presBox-cont { position: absolute; display: block; @@ -20,17 +24,13 @@ margin-top: 3px; } - .presBox-toolbar { - display: none; - } - .presBox-toolbar-dropdown { border-radius: 5px; background-color: white; transform: translate(8px, -5px); box-shadow: 1px 1px 4px 4px rgba(0, 0, 0, 0.25); z-index: 1000; - width: 315; + width: calc(100% - 50px); height: max-content; justify-self: center; letter-spacing: normal; @@ -40,7 +40,7 @@ font-size: 13; } - .presBox-toolbar.active { + .presBox-toolbar { position: relative; display: inline-flex; align-items: center; @@ -59,7 +59,7 @@ } .toolbar-button.active { - color: #AEDDF8; + color: $light-blue; } .toolbar-transitionButtons { @@ -85,7 +85,6 @@ display: flex; width: max-content; height: 25px; - /* background-color: pink; */ justify-content: center; transform: rotate(90deg); align-items: center; @@ -120,7 +119,7 @@ .dropdown.active { transform: rotate(180deg); - color: #AEDDF8; + color: $light-blue; opacity: 0.8; } @@ -128,10 +127,7 @@ position: relative; display: inline; font-family: Roboto; - /* background-color: white; */ color: black; - width: 100%; - height: max-content; z-index: 100; transition: 0.7s; @@ -157,7 +153,6 @@ margin-left: 5px; margin-top: 5px; margin-bottom: 5px; - /* border-radius: 5px; */ margin-right: 5px; width: max-content; justify-content: center; @@ -166,52 +161,6 @@ padding-left: 10px; } - // .toolbar-slider { - // position: relative; - // align-self: center; - // justify-self: left; - // -webkit-appearance: none; - // background-color: #5b9ddd; - // overflow: hidden; - // margin-top: 5px; - // width: 100%; - // max-width: 200px; - - // } - - // .toolbar-slider:focus { - // outline: none; - // } - - // .effectDirection { - // justify-self: center; - // align-self: center; - // align-items: center; - // justify-content: center; - // grid-template-columns: 13px 13px 13px; - // display: grid; - // } - - // .toolbar-slider::-webkit-slider-thumb { - // -webkit-appearance: none; - // background-color: #5b9ddd; - // box-shadow: -100 vw 0 0 100vw pink; - // width: 12px; - // height: 12px; - // } - - // .toolbar-slider::-webkit-slider-runnable-track { - // position: relative; - // align-self: center; - // justify-self: left; - // -webkit-appearance: none; - // background-color: #5b9ddd; - // margin-top: 5px; - // border: solid 1px black; - // border-radius: 10px; - // height: 5px; - // left: 0px; - // } .presBox-subheading { font-size: 11; font-weight: 400; @@ -235,20 +184,20 @@ .toolbar-slider:focus { outline: none; } - + .toolbar-slider::-webkit-slider-runnable-track { - height: 10px; - -webkit-appearance: none; - margin-top: -1px; + height: 10px; + -webkit-appearance: none; + margin-top: -1px; } - + .toolbar-slider::-webkit-slider-thumb { - width: 10px; - -webkit-appearance: none; - height: 10px; - cursor: ew-resize; - background: #5b9ddd; - box-shadow: -100vw 0 0 100vw #aedef8; + width: 10px; + -webkit-appearance: none; + height: 10px; + cursor: ew-resize; + background: #5b9ddd; + box-shadow: -100vw 0 0 100vw #aedef8; } } @@ -298,7 +247,7 @@ justify-self: left; margin-top: 5px; padding-left: 10px; - background-color: rgb(222, 222, 222); + background-color: $light-background; border: solid 1px black; min-width: 80px; max-width: 200px; @@ -323,7 +272,7 @@ cursor: pointer; position: relative; height: 100%; - background: #d5dce2; + background: $light-background; display: flex; align-items: center; justify-content: center; @@ -417,7 +366,7 @@ font-size: 10.5; font-weight: 200; height: 20; - background-color: #dedede; + background-color: $light-background; border: solid 1px black; display: flex; margin-top: 5px; @@ -487,7 +436,7 @@ .presBox-dropdownOptions { position: absolute; - top: 29px; + top: 24px; left: -1px; z-index: 200; width: 85%; @@ -509,10 +458,10 @@ grid-template-columns: auto 20%; position: relative; border: solid 1px black; - background-color: #dedede; + background-color: $light-background; border-radius: 5px; font-size: 10; - height: 30; + height: 25; padding-left: 5px; align-items: center; margin-top: 5px; @@ -583,6 +532,8 @@ align-items: center; justify-content: center; border-radius: 4px; + padding-left: 7px; + padding-right: 7px; border-bottom-right-radius: 0; border-top-right-radius: 0; } @@ -597,6 +548,8 @@ align-items: center; justify-content: center; border-radius: 4px; + padding-left: 7px; + padding-right: 7px; border-bottom-left-radius: 0; border-top-left-radius: 0; } @@ -633,7 +586,7 @@ align-items: center; justify-content: center; transform: translate(0px, -1px); - background-color: #dedede; + background-color: $light-background; width: 40px; height: 15px; align-self: center; @@ -647,7 +600,7 @@ .layout-container { padding: 5px; display: grid; - background-color: #dedede; + background-color: $light-background; grid-template-columns: repeat(auto-fit, minmax(90px, 100px)); width: 100%; border: solid 1px black; @@ -722,6 +675,7 @@ position: relative; width: 100%; background: gray; + min-height: 35px; padding-top: 5px; padding-bottom: 5px; display: grid; @@ -746,7 +700,7 @@ min-width: 150px; } - + select { background: #323232; @@ -782,8 +736,7 @@ .presBox-button.present { display: flex; - min-width: 100px; - width: 100px; + width: max-content; position: absolute; right: 10px; @@ -792,19 +745,21 @@ } } - + .miniPresOverlay { background-color: #323232; color: white; border-radius: 5px; grid-template-rows: 100%; height: 25; - width: 200; + width: max-content; + min-width: max-content; justify-content: space-evenly; align-items: center; display: flex; position: absolute; right: 10px; + transition: all 0.2s; .miniPres-button-text { display: flex; @@ -812,6 +767,10 @@ width: max-content; font-family: Roboto; font-weight: 400; + margin-left: 3px; + margin-right: 3px; + padding-right: 3px; + padding-left: 3px; letter-spacing: normal; border-radius: 5px; align-items: center; @@ -825,10 +784,27 @@ border-right: solid 1px #5a5a5a; } + .miniPres-button-frame { + justify-self: center; + align-self: center; + align-items: center; + display: grid; + grid-template-columns: auto auto auto; + justify-content: space-around; + font-size: 11; + margin-left: 7; + width: 30; + height: 85%; + background-color: rgba(91, 157, 221, 0.4); + border-radius: 5px; + } + .miniPres-button { display: flex; height: 20; min-width: 20; + margin-left: 3px; + margin-right: 3px; border-radius: 100%; align-items: center; justify-content: center; diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx index ccf1fb8e3..230137584 100644 --- a/src/client/views/nodes/PresBox.tsx +++ b/src/client/views/nodes/PresBox.tsx @@ -20,17 +20,10 @@ import { Docs, DocUtils } from "../../documents/Documents"; import { PrefetchProxy } from "../../../fields/Proxy"; import { ScriptField } from "../../../fields/ScriptField"; import { Scripting } from "../../util/Scripting"; -import { InkingStroke } from "../InkingStroke"; -import { HighlightSpanKind } from "typescript"; -import { SearchUtil } from "../../util/SearchUtil"; import { CollectionFreeFormDocumentView } from "./CollectionFreeFormDocumentView"; -import { child } from "serializr"; import { List } from "../../../fields/List"; import { Tooltip } from "@material-ui/core"; import { CollectionFreeFormViewChrome } from "../collections/CollectionMenu"; -import { conformsTo } from "lodash"; -import { translate } from "googleapis/build/src/apis/translate"; -import { DragManager, dropActionType } from "../../util/DragManager"; import { actionAsync } from "mobx-utils"; import { SelectionManager } from "../../util/SelectionManager"; import { AudioBox } from "./AudioBox"; @@ -41,9 +34,26 @@ const PresBoxDocument = makeInterface(documentSchema); @observer export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>(PresBoxDocument) { public static LayoutString(fieldKey: string) { return FieldView.LayoutString(PresBox, fieldKey); } - private treedropDisposer?: DragManager.DragDropDisposer; static Instance: PresBox; + @observable _isChildActive = false; + @observable _moveOnFromAudio: boolean = true; + @observable _presTimer!: NodeJS.Timeout; + + @observable _selectedArray: Doc[] = []; + @observable _sortedSelectedArray: Doc[] = []; + @observable _eleArray: HTMLElement[] = []; + @observable _dragArray: HTMLElement[] = []; + + @observable private transitionTools: boolean = false; + @observable private newDocumentTools: boolean = false; + @observable private progressivizeTools: boolean = false; + @observable private moreInfoTools: boolean = false; + @observable private playTools: boolean = false; + @observable private presentTools: boolean = false; + @observable private pathBoolean: boolean = false; + @observable private expandBoolean: boolean = false; + @computed get childDocs() { return DocListCast(this.dataDoc[this.fieldKey]); } @computed get itemIndex() { return NumCast(this.rootDoc._itemIndex); } @computed get presElement() { return Cast(Doc.UserDoc().presElement, Doc, null); } @@ -63,8 +73,23 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> } this.props.Document.presentationFieldKey = this.fieldKey; // provide info to the presElement script so that it can look up rendering information about the presBox } - - + @computed get selectedDocumentView() { + if (SelectionManager.SelectedDocuments().length) { + return SelectionManager.SelectedDocuments()[0]; + } else if (PresBox.Instance._selectedArray.length) { + return DocumentManager.Instance.getDocumentView(PresBox.Instance.rootDoc); + } else { return undefined; } + } + @computed get isPres(): boolean { + if (this.selectedDoc?.type === DocumentType.PRES) { + document.addEventListener("keydown", this.keyEvents, true); + return true; + } else { + document.removeEventListener("keydown", this.keyEvents, true); + return false; + } + } + @computed get selectedDoc() { return this.selectedDocumentView?.rootDoc; } componentDidMount() { this.rootDoc.presBox = this.rootDoc; @@ -72,33 +97,22 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> this.rootDoc._replacedChrome = "replaced"; this.layoutDoc.presStatus = "edit"; this.layoutDoc._gridGap = 5; - // document.addEventListener("keydown", this.keyEvents, false); - } - - componentWillUnmount() { - this.treedropDisposer?.(); - } - - onPointerOver = () => { - document.addEventListener("keydown", this.keyEvents, true); - } - - onPointerLeave = () => { - document.removeEventListener("keydown", this.keyEvents, true); } updateCurrentPresentation = () => { Doc.UserDoc().activePresentation = this.rootDoc; } - @observable _moveOnFromAudio: boolean = false; - + /** + * Called when the user moves to the next slide in the presentation trail. + */ @undoBatch @action next = () => { this.updateCurrentPresentation(); const activeNext = Cast(this.childDocs[this.itemIndex + 1], Doc, null); - const presTargetDoc = Cast(this.childDocs[this.itemIndex].presentationTargetDoc, Doc, null); + const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); + const presTargetDoc = Cast(activeItem.presentationTargetDoc, Doc, null); const childDocs = DocListCast(presTargetDoc[Doc.LayoutFieldKey(presTargetDoc)]); const currentFrame = Cast(presTargetDoc.currentFrame, "number", null); const lastFrame = Cast(presTargetDoc.lastFrame, "number", null); @@ -114,29 +128,24 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> if (presTargetDoc.presProgressivize) CollectionFreeFormDocumentView.updateKeyframe(childDocs, currentFrame || 0); if (presTargetDoc.zoomProgressivize) this.zoomProgressivizeNext(presTargetDoc); // Case 2: Audio or video therefore wait to play the audio or video before moving on - } else if ((presTargetDoc.type === DocumentType.VID || presTargetDoc.type === DocumentType.AUDIO) && !this._moveOnFromAudio) { - if (presTargetDoc.type === DocumentType.AUDIO) { - AudioBox.Instance.playFrom(0); - this._moveOnFromAudio = true; - } - if (presTargetDoc.type === DocumentType.VID) { - this._moveOnFromAudio = true; - } + } else if ((presTargetDoc.type === DocumentType.AUDIO) && !this._moveOnFromAudio) { + AudioBox.Instance.playFrom(0); + this._moveOnFromAudio = true; // Case 3: No more frames in current doc and next slide is defined, therefore move to next slide - } else if (activeNext !== undefined) { - if (!presTargetDoc.presProgressivize) { - const nextTagDoc = Cast(this.childDocs[this.itemIndex + 1].presentationTargetDoc, Doc, null); - const nextChildDocs = DocListCast(nextTagDoc[Doc.LayoutFieldKey(presTargetDoc)]); - nextChildDocs.forEach((doc, i) => { - doc.opacity = 1; - }); - } + } else if (this.childDocs[this.itemIndex + 1] !== undefined) { const nextSelected = this.itemIndex + 1; this.gotoDocument(nextSelected, this.itemIndex); - this._moveOnFromAudio = false; + const targetNext = Cast(activeNext.presentationTargetDoc, Doc, null); + if (activeNext && targetNext.type === DocumentType.AUDIO && activeNext.playAuto) { + } else { this._moveOnFromAudio = false }; } } + /** + * Called when the user moves back + * Design choice: If there are frames within the presentation, moving back will not + * got back through the frames but instead directly to the next point in the presentation. + */ @undoBatch @action back = () => { @@ -149,6 +158,93 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> } } + //The function that is called when a document is clicked or reached through next or back. + //it'll also execute the necessary actions if presentation is playing. + public gotoDocument = action((index: number, fromDoc: number) => { + this.updateCurrentPresentation(); + Doc.UnBrushAllDocs(); + if (index >= 0 && index < this.childDocs.length) { + this.rootDoc._itemIndex = index; + const presTargetDoc = Cast(this.childDocs[this.itemIndex].presentationTargetDoc, Doc, null); + if (presTargetDoc?.lastFrame !== undefined) { + presTargetDoc.currentFrame = 0; + } + this.navigateToElement(this.childDocs[index]); //Handles movement to element + this._selectedArray = [this.childDocs[index]]; //Update selected array + this.onHideDocument(); //Handles hide after/before + } + }); + + /** + * This method makes sure that cursor navigates to the element that + * has the option open and last in the group. + * Design choice: If the next document is not in presCollection or + * presCollection itself then if there is a presCollection it will add + * a new tab. If presCollection is undefined it will open the document + * on the right. + */ + navigateToElement = async (curDoc: Doc) => { + const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); + const targetDoc = Cast(activeItem.presentationTargetDoc, Doc, null); + const srcContext = await DocCastAsync(targetDoc.context); + const presCollection = Cast(this.layoutDoc.presCollection, Doc, null); + const collectionDocView = presCollection ? await DocumentManager.Instance.getDocumentView(presCollection) : undefined; + this.turnOffEdit(); + + if (this.itemIndex >= 0) { + if (targetDoc) { + if (srcContext) this.layoutDoc.presCollection = srcContext; + } else if (targetDoc) this.layoutDoc.presCollection = targetDoc; + } + if (collectionDocView) { + if (srcContext && srcContext !== presCollection) { + // Case 1: new srcContext inside of current collection so add a new tab to the current pres collection + collectionDocView.props.addDocTab(srcContext, "inPlace"); + } + } + this.updateCurrentPresentation(); + const docToJump = curDoc; + const willZoom = false; + + //docToJump stayed same meaning, it was not in the group or was the last element in the group + if (targetDoc.zoomProgressivize && this.rootDoc.presStatus !== 'edit') { + this.zoomProgressivizeNext(targetDoc); + } else if (docToJump === curDoc) { + //checking if curDoc has navigation open + if (curDoc.presNavButton && targetDoc) { + await DocumentManager.Instance.jumpToDocument(targetDoc, false, undefined, srcContext); + } else if (curDoc.presZoomButton && targetDoc) { + //awaiting jump so that new scale can be found, since jumping is async + await DocumentManager.Instance.jumpToDocument(targetDoc, true, undefined, srcContext); + } + } else { + //awaiting jump so that new scale can be found, since jumping is async + targetDoc && await DocumentManager.Instance.jumpToDocument(targetDoc, willZoom, undefined, srcContext); + } + // After navigating to the document, if it is added as a presPinView then it will + // adjust the pan and scale to that of the pinView when it was added. + // TODO: Add option to remove presPinView + if (activeItem.presPinView) { + targetDoc._panX = activeItem.presPinViewX; + targetDoc._panY = activeItem.presPinViewY; + targetDoc._viewScale = activeItem.presPinViewScale; + } + // If openDocument is selected then it should open the document for the user + if (collectionDocView && activeItem.openDocument) { + collectionDocView.props.addDocTab(activeItem, "inPlace"); + } + // If website and has presWebsite data associated then on click it should + // go back to that specific website + // TODO: Add progressivize for navigating web (storing websites for given frames) + if (targetDoc.presWebsiteData) { + targetDoc.data = targetDoc.presWebsiteData; + } + } + + /** + * Uses the viewfinder to progressivize through the different views of a single collection. + * @param presTargetDoc: document for which internal zoom is used + */ zoomProgressivizeNext = (presTargetDoc: Doc) => { const srcContext = Cast(presTargetDoc.context, Doc, null); const docView = DocumentManager.Instance.getDocumentView(presTargetDoc); @@ -190,6 +286,10 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> } + /** + * For 'Hide Before' and 'Hide After' buttons making sure that + * they are hidden each time the presentation is updated. + */ @action onHideDocument = () => { this.childDocs.forEach((doc, index) => { @@ -213,97 +313,11 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> }); } - /** - * This method makes sure that cursor navigates to the element that - * has the option open and last in the group. If not in the group, and it has - * the option open, navigates to that element. - */ - navigateToElement = async (curDoc: Doc) => { - const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); - const targetDoc = Cast(activeItem.presentationTargetDoc, Doc, null); - const srcContext = await DocCastAsync(targetDoc.context); - const presCollection = Cast(this.layoutDoc.presCollection, Doc, null); - const collectionDocView = presCollection ? await DocumentManager.Instance.getDocumentView(presCollection) : undefined; - this.turnOffEdit(); - - if (this.itemIndex >= 0) { - if (targetDoc) { - if (srcContext) this.layoutDoc.presCollection = srcContext; - } else if (targetDoc) this.layoutDoc.presCollection = targetDoc; - } - if (collectionDocView) { - if (srcContext && srcContext !== presCollection) { - // Case 1: new srcContext inside of current collection so add a new tab to the current pres collection - collectionDocView.props.addDocTab(srcContext, "inPlace"); - } - } - // else if (srcContext) { - // console.log("Case 2: srcContext - not open and collection containing this document exists, so open collection that contains it and then await zooming in on document"); - // this.props.addDocTab(srcContext, "onRight"); - // } else if (!srcContext) { - // console.log("Case 3: !srcContext - no collection containing this document, therefore open document itself on right"); - // this.props.addDocTab(targetDoc, "onRight"); - // } - this.updateCurrentPresentation(); - const docToJump = curDoc; - const willZoom = false; - - //docToJump stayed same meaning, it was not in the group or was the last element in the group - if (targetDoc.zoomProgressivize && this.rootDoc.presStatus !== 'edit') { - this.zoomProgressivizeNext(targetDoc); - } else if (docToJump === curDoc) { - //checking if curDoc has navigation open - if (curDoc.presNavButton && targetDoc) { - await DocumentManager.Instance.jumpToDocument(targetDoc, false, undefined, srcContext); - } else if (curDoc.presZoomButton && targetDoc) { - //awaiting jump so that new scale can be found, since jumping is async - await DocumentManager.Instance.jumpToDocument(targetDoc, true, undefined, srcContext); - } - } else { - //awaiting jump so that new scale can be found, since jumping is async - targetDoc && await DocumentManager.Instance.jumpToDocument(targetDoc, willZoom, undefined, srcContext); - } - if (activeItem.presPinView) { - targetDoc._panX = activeItem.presPinViewX; - targetDoc._panY = activeItem.presPinViewY; - targetDoc._viewScale = activeItem.presPinViewScale; - } - if (collectionDocView && activeItem.openDocument) { - collectionDocView.props.addDocTab(activeItem, "inPlace"); - } - if (targetDoc.presWebsiteData) { - targetDoc.data = targetDoc.presWebsiteData; - } - } - - //The function that is called when a document is clicked or reached through next or back. - //it'll also execute the necessary actions if presentation is playing. - public gotoDocument = action((index: number, fromDoc: number) => { - this.updateCurrentPresentation(); - Doc.UnBrushAllDocs(); - if (index >= 0 && index < this.childDocs.length) { - this.rootDoc._itemIndex = index; - const presTargetDoc = Cast(this.childDocs[this.itemIndex].presentationTargetDoc, Doc, null); - if (presTargetDoc?.lastFrame !== undefined) { - presTargetDoc.currentFrame = 0; - } - this.navigateToElement(this.childDocs[index]); - this._selectedArray = [this.childDocs[index]]; - // this.hideIfNotPresented(index); - // this.showAfterPresented(index); - // this.hideDocumentInPres(); - this.onHideDocument(); - // this.onHideAfterPresClick(); - } - }); - - @observable _presTimer!: NodeJS.Timeout; - - //The function that starts or resets presentaton functionally, depending on status flag. + //The function that starts or resets presentaton functionally, depending on presStatus of the layoutDoc @undoBatch @action - startOrResetPres = (startSlide: number) => { + startAutoPres = (startSlide: number) => { this.updateCurrentPresentation(); const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); const targetDoc = Cast(activeItem.presentationTargetDoc, Doc, null); @@ -326,15 +340,20 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> //The function that resets the presentation by removing every action done by it. It also //stops the presentaton. + // TODO: Ensure resetPresentation is called when the presentation is closed resetPresentation = () => { this.updateCurrentPresentation(); - this.childDocs.forEach(doc => (doc.presentationTargetDoc as Doc).opacity = 1); this.rootDoc._itemIndex = 0; - // this.layoutDoc.presStatus = false; } - //The function that starts the presentation, also checking if actions should be applied - //directly at start. + @action togglePath = () => this.pathBoolean = !this.pathBoolean; + @action toggleExpand = () => this.expandBoolean = !this.expandBoolean; + + /** + * The function that starts the presentation at the given index, also checking if actions should be applied + * directly at start. + * @param startIndex: index that the presentation will start at + */ startPresentation = (startIndex: number) => { this.updateCurrentPresentation(); this.childDocs.map(doc => { @@ -348,55 +367,70 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> }); } + /** + * The method called to open the presentation as a minimized view + * TODO: Look at old updateMinimize and compare... + */ updateMinimize = () => { const srcContext = Cast(this.rootDoc.presCollection, Doc, null); this.turnOffEdit(); if (srcContext) { if (srcContext.miniPres) { - document.removeEventListener("keydown", this.minimizeEvents, false); srcContext.miniPres = false; CollectionDockingView.AddRightSplit(this.rootDoc); } else { - document.addEventListener("keydown", this.minimizeEvents, false); srcContext.miniPres = true; this.props.addDocTab?.(this.rootDoc, "close"); } } } + /** + * Called when the user changes the view type + * Either 'List' (stacking) or 'Slides' (carousel) + */ @undoBatch viewChanged = action((e: React.ChangeEvent) => { //@ts-ignore const viewType = e.target.selectedOptions[0].value as CollectionViewType; - viewType === CollectionViewType.Stacking && (this.rootDoc._pivotField = undefined); // pivot field may be set by the user in timeline view (or some other way) -- need to reset it here + // pivot field may be set by the user in timeline view (or some other way) -- need to reset it here + viewType === CollectionViewType.Stacking && (this.rootDoc._pivotField = undefined); this.rootDoc._viewType = viewType; if (viewType === CollectionViewType.Stacking) this.layoutDoc._gridGap = 5; }); + /** + * When the movement dropdown is changes + */ @undoBatch movementChanged = action((movement: string) => { const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); const targetDoc = Cast(activeItem.presentationTargetDoc, Doc, null); - if (movement === 'zoom') { - activeItem.presZoomButton = !activeItem.presZoomButton; - if (activeItem.presZoomButton) activeItem.presMovement = 'Zoom'; - else activeItem.presMovement = 'None'; - activeItem.presNavButton = false; - } else if (movement === 'nav') { - activeItem.presZoomButton = false; - activeItem.presNavButton = !activeItem.presNavButton; - if (activeItem.presNavButton) activeItem.presMovement = 'Pan'; - else activeItem.presMovement = 'None'; - } else if (movement === 'switch') { - targetDoc.presTransition = 0; - activeItem.presSwitchButton = !activeItem.presSwitchButton; - if (activeItem.presSwitchButton) activeItem.presMovement = 'Jump cut'; - else activeItem.presMovement = 'None'; - } else { - activeItem.presMovement = 'None'; - activeItem.presZoomButton = false; - activeItem.presNavButton = false; - activeItem.presSwitchButton = false; + switch (movement) { + case 'zoom': //Pan and zoom + activeItem.presZoomButton = !activeItem.presZoomButton; + if (activeItem.presZoomButton) activeItem.presMovement = 'Zoom'; + else activeItem.presMovement = 'None'; + activeItem.presNavButton = false; + break; + case 'pan': //Pan + activeItem.presZoomButton = false; + activeItem.presNavButton = !activeItem.presNavButton; + if (activeItem.presNavButton) activeItem.presMovement = 'Pan'; + else activeItem.presMovement = 'None'; + break; + case 'jump': //Jump Cut + targetDoc.presTransition = 0; + activeItem.presSwitchButton = !activeItem.presSwitchButton; + if (activeItem.presSwitchButton) activeItem.presMovement = 'Jump cut'; + else activeItem.presMovement = 'None'; + break; + case 'none': default: + activeItem.presMovement = 'None'; + activeItem.presZoomButton = false; + activeItem.presNavButton = false; + activeItem.presSwitchButton = false; + break; } }); @@ -421,13 +455,9 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> active = (outsideReaction?: boolean) => ((Doc.GetSelectedTool() === InkTool.None && !this.layoutDoc.isBackground) && (this.layoutDoc.forceActive || this.props.isSelected(outsideReaction) || this._isChildActive || this.props.renderDepth === 0) ? true : false) - // KEYS - @observable _selectedArray: Doc[] = []; - @observable _sortedSelectedArray: Doc[] = []; - @observable _eleArray: HTMLElement[] = []; - @observable _dragArray: HTMLElement[] = []; - - //TODO: Update to radix / quick sort + /** + * For sorting the array so that the order is maintained when it is dropped. + */ @action sortArray = (): Doc[] => { const sort: Doc[] = this._selectedArray; @@ -439,6 +469,9 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> return sort; } + /** + * Method to get the list of selected items in the order in which they have been selected + */ @computed get listOfSelected() { const list = this._selectedArray.map((doc: Doc, index: any) => { const activeItem = Cast(doc, Doc, null); @@ -459,9 +492,11 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> //Command click @action multiSelect = (doc: Doc, ref: HTMLElement, drag: HTMLElement) => { - this._selectedArray.push(this.childDocs[this.childDocs.indexOf(doc)]); - this._eleArray.push(ref); - this._dragArray.push(drag); + if (!this._selectedArray.includes(doc)) { + this._selectedArray.push(this.childDocs[this.childDocs.indexOf(doc)]); + this._eleArray.push(ref); + this._dragArray.push(drag); + } } //Shift click @@ -478,20 +513,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> } } - @action - minimizeEvents = (e: KeyboardEvent) => { - e.stopPropagation(); - e.preventDefault(); - if (e.keyCode === 27) { // Escape key - this.layoutDoc.presStatus = "edit"; - } if (e.keyCode === 37) { // left(37) / a(65) / up(38) to go back - this.back(); - } if (e.keyCode === 39) { // right (39) / d(68) / down(40) to go to next - this.next(); - } - } - - //Esc click + // Key for when the presentaiton is active (according to Selection Manager) @action keyEvents = (e: KeyboardEvent) => { e.stopPropagation(); @@ -502,12 +524,12 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> else this.layoutDoc.presStatus = "edit"; } if ((e.metaKey || e.altKey) && e.keyCode === 65) { // Ctrl-A to select all if (this.layoutDoc.presStatus === "edit") this._selectedArray = this.childDocs; - } if (e.keyCode === 37) { // left(37) / a(65) / up(38) to go back - if (this.layoutDoc.presStatus !== "edit") this.back(); - } if (e.keyCode === 39) { // right (39) / d(68) / down(40) to go to next - if (this.layoutDoc.presStatus !== "edit") this.next(); + } if (e.keyCode === 37 || e.keyCode === 38) { // left(37) / a(65) / up(38) to go back + this.back(); + } if (e.keyCode === 39 || e.keyCode === 40) { // right (39) / d(68) / down(40) to go to next + this.next(); } if (e.keyCode === 32) { // spacebar to 'present' or autoplay - if (this.layoutDoc.presStatus !== "edit") this.startOrResetPres(0); + if (this.layoutDoc.presStatus !== "edit") this.startAutoPres(0); else this.layoutDoc.presStatus = "manual"; } if (e.keyCode === 8) { // delete selected items @@ -519,15 +541,9 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> } } - @observable private transitionTools: boolean = false; - @observable private newDocumentTools: boolean = false; - @observable private progressivizeTools: boolean = false; - @observable private moreInfoTools: boolean = false; - @observable private playTools: boolean = false; - @observable private presentTools: boolean = false; - @observable private pathBoolean: boolean = false; - @observable private expandBoolean: boolean = false; - + /** + * + */ @undoBatch @action viewPaths = async () => { @@ -551,16 +567,19 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> const fit = srcContext?._fitToBox; } + // Adds the index in the pres path graphically @computed get order() { const order: JSX.Element[] = []; this.childDocs.forEach((doc, index) => { const targetDoc = Cast(doc.presentationTargetDoc, Doc, null); const srcContext = Cast(targetDoc.context, Doc, null); + // Case A: Document is contained within the colleciton if (this.rootDoc.presCollection === srcContext) { order.push( <div className="pathOrder" style={{ top: NumCast(targetDoc.y), left: NumCast(targetDoc.x) }}> <div className="pathOrder-frame">{index + 1}</div> </div>); + // Case B: Document is not inside of the collection } else { order.push( <div className="pathOrder" style={{ top: 0, left: 0 }}> @@ -571,6 +590,14 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> return order; } + /** + * Method called for viewing paths which adds a single line with + * points at the center of each document added. + * Design choice: When this is called it sets _fitToBox as true so the + * user can have an overview of all of the documents in the collection. + * (Design needed for when documents in presentation trail are in another + * collection) + */ @computed get paths() { let pathPoints = ""; this.childDocs.forEach((doc, index) => { @@ -601,9 +628,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> />); } - @action togglePath = () => this.pathBoolean = !this.pathBoolean; - @action toggleExpand = () => this.expandBoolean = !this.expandBoolean; - /** * The function that is called on click to turn fading document after presented option on/off. * It also makes sure that the option swithches from hide-after to this one, since both @@ -627,13 +651,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> } } - // WHAT IS THIS? - @action - dropdownToggle = (menu: string) => { - const dropMenu = document.getElementById('presBox' + menu + 'Dropdown'); - if (dropMenu) dropMenu.style.display === 'none' ? dropMenu.style.display = 'block' : dropMenu.style.display = 'none'; - } - + // Converts seconds to ms and updates presTransition setTransitionTime = (number: String) => { const timeInMS = Number(number) * 1000; const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); @@ -641,6 +659,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> if (targetDoc) targetDoc.presTransition = timeInMS; } + // Converts seconds to ms and updates presDuration setDurationTime = (number: String) => { const timeInMS = Number(number) * 1000; const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); @@ -648,29 +667,28 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> if (targetDoc) targetDoc.presDuration = timeInMS; } + @computed get transitionDropdown() { const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); const targetDoc = Cast(activeItem?.presentationTargetDoc, Doc, null); if (activeItem && targetDoc) { const transitionSpeed = targetDoc.presTransition ? String(Number(targetDoc.presTransition) / 1000) : 0.5; - const duration = targetDoc.presDuration ? String(Number(targetDoc.presDuration) / 1000) : 2; + let duration = targetDoc.presDuration ? String(Number(targetDoc.presDuration) / 1000) : 2; + if (targetDoc.type === DocumentType.AUDIO) duration = NumCast(targetDoc.duration); const effect = targetDoc.presEffect ? targetDoc.presEffect : 'None'; activeItem.presMovement = activeItem.presMovement ? activeItem.presMovement : 'Zoom'; return ( <div className={`presBox-ribbon ${this.transitionTools && this.layoutDoc.presStatus === "edit" ? "active" : ""}`} onClick={e => e.stopPropagation()} onPointerUp={e => e.stopPropagation()} onPointerDown={e => e.stopPropagation()}> <div className="ribbon-box"> Movement - <div className="presBox-dropdown" - onPointerDown={e => e.stopPropagation()} - // onClick={() => this.dropdownToggle('Movement')} - > + <div className="presBox-dropdown" onPointerDown={e => e.stopPropagation()}> {activeItem.presMovement} <FontAwesomeIcon className='presBox-dropdownIcon' style={{ gridColumn: 2 }} icon={"angle-down"} /> <div className={'presBox-dropdownOptions'} id={'presBoxMovementDropdown'} onClick={e => e.stopPropagation()}> <div className={`presBox-dropdownOption ${activeItem.presMovement === 'None' ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.movementChanged('none')}>None</div> <div className={`presBox-dropdownOption ${activeItem.presMovement === 'Zoom' ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.movementChanged('zoom')}>Pan and Zoom</div> - <div className={`presBox-dropdownOption ${activeItem.presMovement === 'Pan' ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.movementChanged('nav')}>Pan</div> - <div className={`presBox-dropdownOption ${activeItem.presMovement === 'Jump cut' ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.movementChanged('switch')}>Jump cut</div> + <div className={`presBox-dropdownOption ${activeItem.presMovement === 'Pan' ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.movementChanged('pan')}>Pan</div> + <div className={`presBox-dropdownOption ${activeItem.presMovement === 'Jump cut' ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.movementChanged('jump')}>Jump cut</div> </div> </div> <div className="ribbon-doubleButton" style={{ display: activeItem.presMovement === 'Pan' || activeItem.presMovement === 'Zoom' ? "inline-flex" : "none" }}> @@ -694,8 +712,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> <div className="presBox-subheading">Slide Duration</div> <div className="ribbon-property"> {duration} s </div> </div> - <input type="range" step="0.1" min="0.1" max="10" value={duration} style={{ transform: 'rotate(0deg)' }} className={"toolbar-slider"} id="duration-slider" onChange={(e: React.ChangeEvent<HTMLInputElement>) => { e.stopPropagation(); this.setDurationTime(e.target.value); }} /> - <div className={"slider-headers"}> + <input type="range" step="0.1" min="0.1" max="10" value={duration} style={{ display: targetDoc.type === DocumentType.AUDIO ? "none" : "block" }} className={"toolbar-slider"} id="duration-slider" onChange={(e: React.ChangeEvent<HTMLInputElement>) => { e.stopPropagation(); this.setDurationTime(e.target.value); }} /> + <div className={"slider-headers"} style={{ display: targetDoc.type === DocumentType.AUDIO ? "none" : "grid" }}> <div className="slider-text">Short</div> <div className="slider-text">Medium</div> <div className="slider-text">Long</div> @@ -783,12 +801,26 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> <div className={'presBox-ribbon'} onClick={e => e.stopPropagation()} onPointerUp={e => e.stopPropagation()} onPointerDown={e => e.stopPropagation()}> <div className="ribbon-box"> <div className="ribbon-doubleButton" style={{ display: targetDoc.type === DocumentType.VID || targetDoc.type === DocumentType.AUDIO ? "inline-flex" : "none" }}> - <div className="ribbon-button" style={{ backgroundColor: activeItem.presProgressivize ? "#aedef8" : "" }} onClick={this.progressivizeChild}>Start automatically</div> - <div className="ribbon-button" style={{ display: "flex", backgroundColor: targetDoc.editProgressivize ? "#aedef8" : "" }} onClick={this.editProgressivize}>Start manually</div> + <div className="ribbon-button" style={{ backgroundColor: activeItem.playAuto ? "#aedef8" : "" }} onClick={() => activeItem.playAuto = !activeItem.playAuto}>Play automatically</div> + <div className="ribbon-button" style={{ display: "flex", backgroundColor: activeItem.playAuto ? "" : "#aedef8" }} onClick={() => activeItem.playAuto = !activeItem.playAuto}>Play on next</div> </div> <div className="ribbon-doubleButton" style={{ display: "flex" }}> <div className="ribbon-button" style={{ backgroundColor: activeItem.openDocument ? "#aedef8" : "" }} onClick={() => activeItem.openDocument = !activeItem.openDocument}>Open document</div> </div> + <div className="ribbon-doubleButton" style={{ display: targetDoc.type === DocumentType.COL ? "inline-flex" : "none" }}> + <div className="ribbon-button" style={{ backgroundColor: activeItem.presPinView ? "#aedef8" : "" }} + onClick={() => { + activeItem.presPinView = !activeItem.presPinView; + if (activeItem.presPinView) { + const x = targetDoc._panX; + const y = targetDoc._panY; + const scale = targetDoc._viewScale; + activeItem.presPinViewX = x; + activeItem.presPinViewY = y; + activeItem.presPinViewScale = scale; + } + }}>Presentation pin view</div> + </div> <div className="ribbon-doubleButton" style={{ display: targetDoc.type === DocumentType.WEB ? "inline-flex" : "none" }}> <div className="ribbon-button" onClick={this.progressivizeText}>Store original website</div> </div> @@ -838,12 +870,10 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> <div className={"presBox-ribbon"} onClick={e => e.stopPropagation()} onPointerUp={e => e.stopPropagation()} onPointerDown={e => e.stopPropagation()}> <div className="ribbon-box"> Slide Title: <br></br> - {/* <div className="dropdown-textInput"> */} <input className="ribbon-textInput" placeholder="..." type="text" name="fname" ref={this.inputRef} onChange={(e) => { e.stopPropagation(); runInAction(() => this.title = e.target.value); }}></input> - {/* </div> */} </div> <div className="ribbon-box"> Choose type: @@ -893,12 +923,14 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> if (freeform && layout) doc = this.createTemplate(layout, title); if (!freeform && !layout) doc = Docs.Create.TextDocument("", { _nativeWidth: 400, _width: 225, title: title }); const presCollection = Cast(this.layoutDoc.presCollection, Doc, null); - const data = Cast(presCollection.data, listSpec(Doc)); + const data = Cast(presCollection?.data, listSpec(Doc)); const presData = Cast(this.rootDoc.data, listSpec(Doc)); if (data && doc && presData) { data.push(doc); DockedFrameRenderer.PinDoc(doc, false); this.gotoDocument(this.childDocs.length, this.itemIndex); + } else { + this.props.addDocTab(doc as Doc, "onRight"); } } @@ -916,7 +948,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> const subtitle = Docs.Create.TextDocument("Click to change subtitle", { title: "Slide subtitle", _width: 380, _height: 50, x: 10, y: 118, _fontSize: "16pt" }); const header = Docs.Create.TextDocument("Click to change header", { title: "Slide header", _width: 380, _height: 65, x: 10, y: 80, _fontSize: "20pt" }); const contentTitle = Docs.Create.TextDocument("Click to change title", { title: "Slide title", _width: 380, _height: 60, x: 10, y: 10, _fontSize: "24pt" }); - const content = Docs.Create.TextDocument("Click to change texte", { title: "Slide text", _width: 380, _height: 145, x: 10, y: 70, _fontSize: "14pt" }); + const content = Docs.Create.TextDocument("Click to change text", { title: "Slide text", _width: 380, _height: 145, x: 10, y: 70, _fontSize: "14pt" }); const content1 = Docs.Create.TextDocument("Click to change text", { title: "Column 1", _width: 185, _height: 140, x: 10, y: 80, _fontSize: "14pt" }); const content2 = Docs.Create.TextDocument("Click to change text", { title: "Column 2", _width: 185, _height: 140, x: 205, y: 80, _fontSize: "14pt" }); switch (layout) { @@ -941,20 +973,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> return doc; } - // Dropdown that appears for autoplay - @computed get playDropdown() { - return ( - <div className={`dropdown-play ${this.playTools ? "active" : ""}`} onClick={e => e.stopPropagation()} onPointerUp={e => e.stopPropagation()} onPointerDown={e => e.stopPropagation()}> - <div className="dropdown-play-button" onClick={() => this.startOrResetPres(this.itemIndex)}> - Present from current slide - </div> - <div className="dropdown-play-button" onClick={() => this.startOrResetPres(0)}> - Present from first slide - </div> - </div> - ); - } - // Dropdown that appears when the user wants to begin presenting (either minimize or sidebar view) @computed get presentDropdown() { return ( @@ -962,19 +980,13 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> <div className="dropdown-play-button" onClick={this.updateMinimize}> Minimize </div> - <div className="dropdown-play-button" onClick={() => { this.startOrResetPres(0); this.turnOffEdit(); }}> + <div className="dropdown-play-button" onClick={(action(() => { this.layoutDoc.presStatus = "manual"; this.turnOffEdit(); }))}> Sidebar view </div> </div> ); } - // For toggling the options when the user wants to select play - @action togglePlay = () => { this.playTools = !this.playTools; }; - - // For toggling the options when the user wants to select play - @action togglePresent = () => { this.presentTools = !this.presentTools; }; - // Case in which the document has keyframes to navigate to next key frame @undoBatch @action @@ -986,10 +998,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> CollectionFreeFormDocumentView.setupScroll(tagDoc, 0); CollectionFreeFormDocumentView.setupKeyframes(childDocs, 0); } - // let lastFrame: number = 0; - // childDocs.forEach((doc) => { - // if (NumCast(doc.appearFrame) > lastFrame) lastFrame = NumCast(doc.appearFrame); - // }); CollectionFreeFormDocumentView.updateScrollframe(tagDoc, currentFrame); CollectionFreeFormDocumentView.updateKeyframe(childDocs, currentFrame || 0); tagDoc.currentFrame = Math.max(0, (currentFrame || 0) + 1); @@ -1027,6 +1035,9 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> } } + /** + * Returns the collection type as a string for headers + */ @computed get stringType(): string { const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); const targetDoc = Cast(activeItem?.presentationTargetDoc, Doc, null); @@ -1064,10 +1075,10 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> <div className="ribbon-button" style={{ display: activeItem.zoomProgressivize ? "flex" : "none", backgroundColor: targetDoc.editZoomProgressivize ? "#aedef8" : "" }} onClick={this.editZoomProgressivize}>Viewfinder</div> {/* <div className="ribbon-button" style={{ display: activeItem.zoomProgressivize ? "flex" : "none", backgroundColor: targetDoc.editSnapZoomProgressivize ? "#aedef8" : "" }} onClick={this.editSnapZoomProgressivize}>Snapshot</div> */} </div> - <div className="ribbon-doubleButton" style={{ display: targetDoc.type === DocumentType.COL && targetDoc._viewType === 'freeform' ? "inline-flex" : "none" }}> + {/* <div className="ribbon-doubleButton" style={{ display: targetDoc.type === DocumentType.COL && targetDoc._viewType === 'freeform' ? "inline-flex" : "none" }}> <div className="ribbon-button" onClick={this.progressivizeText}>Text progressivize</div> <div className="ribbon-button" style={{ display: activeItem.textProgressivize ? "flex" : "none", backgroundColor: targetDoc.editTextProgressivize ? "#aedef8" : "" }} onClick={this.editTextProgressivize}>Edit</div> - </div> + </div> */} <div className="ribbon-doubleButton" style={{ display: targetDoc._viewType === "stacking" || targetDoc.type === DocumentType.PDF || targetDoc.type === DocumentType.WEB || targetDoc.type === DocumentType.RTF ? "inline-flex" : "none" }}> <div className="ribbon-button" style={{ backgroundColor: activeItem.scrollProgressivize ? "#aedef8" : "" }} onClick={this.progressivizeScroll}>Scroll progressivize</div> <div className="ribbon-button" style={{ display: activeItem.scrollProgressivize ? "flex" : "none", backgroundColor: targetDoc.editScrollProgressivize ? "#aedef8" : "" }} onClick={this.editScrollProgressivize}>Edit</div> @@ -1099,7 +1110,10 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> } turnOffEdit = () => { - this.childDocs.forEach((doc, index) => { + this.childDocs.forEach((doc) => { + doc.editSnapZoomProgressivize = false; + doc.editZoomProgressivize = false; + doc.editScrollProgressivize = false; const targetDoc = Cast(doc.presentationTargetDoc, Doc, null); targetDoc.editSnapZoomProgressivize = false; targetDoc.editZoomProgressivize = false; @@ -1376,8 +1390,10 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> const doc = document.getElementById('resizable'); if (doc && tagDocView) { - const scale = tagDocView.childScaling(); - const scale2 = tagDocView.props.ScreenToLocalTransform().Scale; + const scale2 = tagDocView.childScaling(); + const scale3 = tagDocView.props.ScreenToLocalTransform().Scale; + const scale = NumCast(targetDoc._viewScale); + console.log("scale: " + NumCast(targetDoc._viewScale)); let height = doc.offsetHeight; let width = doc.offsetWidth; let top = doc.offsetTop; @@ -1414,9 +1430,9 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> // } //Bottom right if (this._isDraggingBR) { - const newHeight = height += (e.movementY * scale2); + const newHeight = height += (e.movementY * scale); doc.style.height = newHeight + 'px'; - const newWidth = width += (e.movementX * scale2); + const newWidth = width += (e.movementX * scale); doc.style.width = newWidth + 'px'; // Bottom left } else if (this._isDraggingBL) { @@ -1428,26 +1444,26 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> doc.style.left = newLeft + 'px'; // Top right } else if (this._isDraggingTR) { - const newWidth = width += (e.movementX * tagDocView.props.ScreenToLocalTransform().Scale); + const newWidth = width += (e.movementX * scale); doc.style.width = newWidth + 'px'; - const newHeight = height -= (e.movementY * tagDocView.props.ScreenToLocalTransform().Scale); + const newHeight = height -= (e.movementY * scale); doc.style.height = newHeight + 'px'; - const newTop = top += (e.movementY * tagDocView.props.ScreenToLocalTransform().Scale); + const newTop = top += (e.movementY * scale); doc.style.top = newTop + 'px'; // Top left } else if (this._isDraggingTL) { - const newWidth = width -= (e.movementX * tagDocView.props.ScreenToLocalTransform().Scale); + const newWidth = width -= (e.movementX * scale); doc.style.width = newWidth + 'px'; - const newHeight = height -= (e.movementY * tagDocView.props.ScreenToLocalTransform().Scale); + const newHeight = height -= (e.movementY * scale); doc.style.height = newHeight + 'px'; - const newTop = top += (e.movementY * tagDocView.props.ScreenToLocalTransform().Scale); + const newTop = top += (e.movementY * scale); doc.style.top = newTop + 'px'; - const newLeft = left += (e.movementX * tagDocView.props.ScreenToLocalTransform().Scale); + const newLeft = left += (e.movementX * scale); doc.style.left = newLeft + 'px'; } else if (this._isDragging) { - const newTop = top += (e.movementY * tagDocView.props.ScreenToLocalTransform().Scale); + const newTop = top += (e.movementY * scale); doc.style.top = newTop + 'px'; - const newLeft = left += (e.movementX * tagDocView.props.ScreenToLocalTransform().Scale); + const newLeft = left += (e.movementX * scale); doc.style.left = newLeft + 'px'; } this.updateList(targetDoc, targetDoc["viewfinder-width-indexed"], width); @@ -1487,20 +1503,24 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> @computed get zoomProgressivizeContainer() { const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); const targetDoc = Cast(activeItem?.presentationTargetDoc, Doc, null); - if (targetDoc.editZoomProgressivize) { + if (targetDoc) { + const vfLeft: number = this.checkList(targetDoc, targetDoc["viewfinder-left-indexed"]); + const vfWidth: number = this.checkList(targetDoc, targetDoc["viewfinder-width-indexed"]); + const vfTop: number = this.checkList(targetDoc, targetDoc["viewfinder-top-indexed"]); + const vfHeight: number = this.checkList(targetDoc, targetDoc["viewfinder-height-indexed"]); return ( <> - <div id="resizable" className="resizable" onPointerDown={this.onPointerMid} style={{ width: this.checkList(targetDoc, targetDoc["viewfinder-width-indexed"]), height: this.checkList(targetDoc, targetDoc["viewfinder-height-indexed"]), top: this.checkList(targetDoc, targetDoc["viewfinder-top-indexed"]), left: this.checkList(targetDoc, targetDoc["viewfinder-left-indexed"]), position: 'absolute' }}> + {!targetDoc.editZoomProgressivize ? (null) : <div id="resizable" className="resizable" onPointerDown={this.onPointerMid} style={{ width: vfWidth, height: vfHeight, top: vfTop, left: vfLeft, position: 'absolute' }}> <div className='resizers'> <div id="resizer-tl" className='resizer top-left' onPointerDown={this.onPointerTL}></div> <div id="resizer-tr" className='resizer top-right' onPointerDown={this.onPointerTR}></div> <div id="resizer-bl" className='resizer bottom-left' onPointerDown={this.onPointerBL}></div> <div id="resizer-br" className='resizer bottom-right' onPointerDown={this.onPointerBR}></div> </div> - </div> + </div>} </> ); - } else return null; + } } @computed get progressivizeChildDocs() { @@ -1585,116 +1605,107 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> @computed get toolbar() { const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); - if (activeItem) { - return ( - <> - <Tooltip title={<><div className="dash-tooltip">{"Add new slide"}</div></>}><div className={`toolbar-button ${this.newDocumentTools ? "active" : ""}`} onClick={action(() => this.newDocumentTools = !this.newDocumentTools)}><FontAwesomeIcon icon={"plus"} /> - <FontAwesomeIcon className={`dropdown ${this.newDocumentTools ? "active" : ""}`} icon={"angle-down"} /> - </div></Tooltip> - <div className="toolbar-divider" /> - <Tooltip title={<><div className="dash-tooltip">{"View paths"}</div></>}><div className={`toolbar-button ${this.pathBoolean ? "active" : ""}`}> - <FontAwesomeIcon icon={"exchange-alt"} onClick={this.viewPaths} /> - </div></Tooltip> - <Tooltip title={<><div className="dash-tooltip">{this.expandBoolean ? "Minimize all" : "Expand all"}</div></>}> - <div className={`toolbar-button ${this.expandBoolean ? "active" : ""}`} onClick={() => { this.toggleExpand(); this.childDocs.forEach((doc, ind) => { if (this.expandBoolean) doc.presExpandInlineButton = true; else doc.presExpandInlineButton = false; }); }}> - <FontAwesomeIcon icon={"eye"} /> - </div> - </Tooltip> - {/* <div className="toolbar-button"><FontAwesomeIcon title={"Portal"} icon={"eye"} onClick={this.toolbarTest} /></div> */} - <div className="toolbar-divider" /> - {/* <Tooltip title={<><div className="dash-tooltip">{"Transitions"}</div></>}><div className={`toolbar-button ${this.transitionTools ? "active" : ""}`} onClick={this.toggleTransitionTools}> - <FontAwesomeIcon icon={"rocket"} /> - <div style={{ display: this.props.PanelWidth() > 430 ? "block" : "none" }} className="toolbar-buttonText"> Transitions</div> - <FontAwesomeIcon className={`dropdown ${this.transitionTools ? "active" : ""}`} icon={"angle-down"} /> - </div></Tooltip> - <div className="toolbar-divider" /> - <Tooltip title={<><div className="dash-tooltip">{"Progressivize"}</div></>}><div className={`toolbar-button ${this.progressivizeTools ? "active" : ""}`} onClick={this.toggleProgressivize}> - <FontAwesomeIcon icon={"tasks"} /> - <div style={{ display: this.props.PanelWidth() > 430 ? "block" : "none" }} className="toolbar-buttonText"> Progressivize</div> - <FontAwesomeIcon className={`dropdown ${this.progressivizeTools ? "active" : ""}`} icon={"angle-down"} /> - </div></Tooltip> - <div className="toolbar-divider" /> */} - {/* <div className="toolbar-button" style={{ position: 'absolute', right: 23, transform: 'rotate(45deg)', fontSize: 16 }}> - <FontAwesomeIcon className={"toolbar-thumbtack"} icon={"thumbtack"} /> + return ( + <div id="toolbarContainer" className={'presBox-toolbar'} style={{ display: this.layoutDoc.presStatus === "edit" ? "inline-flex" : "none" }}> + <Tooltip title={<><div className="dash-tooltip">{"Add new slide"}</div></>}><div className={`toolbar-button ${this.newDocumentTools ? "active" : ""}`} onClick={action(() => this.newDocumentTools = !this.newDocumentTools)}> + <FontAwesomeIcon icon={"plus"} /> + <FontAwesomeIcon className={`dropdown ${this.newDocumentTools ? "active" : ""}`} icon={"angle-down"} /> + </div></Tooltip> + <div className="toolbar-divider" /> + <Tooltip title={<><div className="dash-tooltip">{"View paths"}</div></>}> + <div style={{ opacity: this.childDocs.length > 1 ? 1 : 0.3 }} className={`toolbar-button ${this.pathBoolean ? "active" : ""}`} onClick={this.childDocs.length > 1 ? this.viewPaths : undefined}> + <FontAwesomeIcon icon={"exchange-alt"} /> </div> - <div className={`toolbar-button ${this.moreInfoTools ? "active" : ""}`} onClick={this.toggleMoreInfo}> - <div className={`toolbar-moreInfo ${this.moreInfoTools ? "active" : ""}`}> - <div className="toolbar-moreInfoBall" /> - <div className="toolbar-moreInfoBall" /> - <div className="toolbar-moreInfoBall" /> - </div> - </div> */} - </> - ); - } else { - return ( - <> - <Tooltip title={<><div className="dash-tooltip">{"Add new slide"}</div></>}><div className={`toolbar-button ${this.newDocumentTools ? "active" : ""}`} onClick={action(() => this.newDocumentTools = !this.newDocumentTools)}> - <FontAwesomeIcon icon={"plus"} /> - <FontAwesomeIcon className={`dropdown ${this.newDocumentTools ? "active" : ""}`} icon={"angle-down"} /> - </div></Tooltip> - {/* <div className="toolbar-button" style={{ position: 'absolute', right: 23, transform: 'rotate(45deg)', fontSize: 16 }}> - <FontAwesomeIcon className={"toolbar-thumbtack"} icon={"thumbtack"} /> + </Tooltip> + <Tooltip title={<><div className="dash-tooltip">{this.expandBoolean ? "Minimize all" : "Expand all"}</div></>}> + <div style={{ opacity: this.childDocs.length > 0 ? 1 : 0.3 }} className={`toolbar-button ${this.expandBoolean ? "active" : ""}`} onClick={() => { if (this.childDocs.length > 0) this.toggleExpand(); this.childDocs.forEach((doc, ind) => { if (this.expandBoolean) doc.presExpandInlineButton = true; else doc.presExpandInlineButton = false; }); }}> + <FontAwesomeIcon icon={"eye"} /> </div> - <div className={`toolbar-button ${this.moreInfoTools ? "active" : ""}`} onClick={this.toggleMoreInfo}> - <div className={`toolbar-moreInfo ${this.moreInfoTools ? "active" : ""}`}> - <div className="toolbar-moreInfoBall" /> - <div className="toolbar-moreInfoBall" /> - <div className="toolbar-moreInfoBall" /> - </div> - </div> */} - </> - ); - } + </Tooltip> + <div className="toolbar-divider" /> + </div> + ); } - render() { - this.childDocs.slice(); // needed to insure that the childDocs are loaded for looking up fields + /** + * Top panel containes: + * viewPicker: The option to choose between List and Slides view for the presentaiton trail + * presentPanel: The button to start the presentation / open minimized view of the presentation + */ + @computed get topPanel() { const mode = StrCast(this.rootDoc._viewType) as CollectionViewType; - // const addDocument = (doc: Doc | Doc[], relativeTo?: Doc, before?: boolean) => { - // return add(doc, relativeTo ? relativeTo : docs[i], before !== undefined ? before : false); - // }; - return <div onPointerOver={this.onPointerOver} onPointerLeave={this.onPointerLeave} className="presBox-cont" style={{ minWidth: this.layoutDoc.inOverlay ? 240 : undefined }} > + return ( <div className="presBox-buttons" style={{ display: this.rootDoc._chromeStatus === "disabled" ? "none" : undefined }}> <select className="presBox-viewPicker" + style={{ display: this.layoutDoc.presStatus === "edit" ? "block" : "none" }} onPointerDown={e => e.stopPropagation()} onChange={this.viewChanged} value={mode}> <option onPointerDown={e => e.stopPropagation()} value={CollectionViewType.Stacking}>List</option> <option onPointerDown={e => e.stopPropagation()} value={CollectionViewType.Carousel}>Slides</option> </select> - <div className="presBox-presentPanel"> + <div className="presBox-presentPanel" style={{ opacity: this.childDocs.length > 0 ? 1 : 0.3 }}> <span className={`presBox-button ${this.layoutDoc.presStatus === "edit" ? "present" : ""}`}> - <div className="presBox-button-left" onClick={() => this.layoutDoc.presStatus = "manual"}><FontAwesomeIcon icon={"play-circle"} /> Present </div> - <div className={`presBox-button-right ${this.presentTools ? "active" : ""}`} onClick={e => { e.stopPropagation; this.togglePresent(); }}> + <div className="presBox-button-left" onClick={() => { if (this.childDocs.length > 0) this.layoutDoc.presStatus = "manual" }}> + <FontAwesomeIcon icon={"play-circle"} /> + <div style={{ display: this.props.PanelWidth() > 200 ? "inline-flex" : "none" }}> Present</div> + </div> + <div className={`presBox-button-right ${this.presentTools ? "active" : ""}`} + onClick={(action(() => { + if (this.childDocs.length > 0) this.presentTools = !this.presentTools; + }))}> <FontAwesomeIcon className="dropdown" style={{ margin: 0, transform: this.presentTools ? 'rotate(180deg)' : 'rotate(0deg)' }} icon={"angle-down"} /> {this.presentDropdown} </div> </span> - <div className="miniPresOverlay" style={{ display: this.layoutDoc.presStatus !== "edit" ? "inline-flex" : "none" }}> - {/* <span className={`presBox-button ${this.layoutDoc.presStatus !== "edit" ? "active" : ""}`}> - <div className="presBox-button-left" onClick={() => this.startOrResetPres(0)}> - <FontAwesomeIcon icon={"clock"} /> - <FontAwesomeIcon icon={this.layoutDoc.presStatus === "auto" ? "pause" : "play"} /> - </div> - <div className={`presBox-button-right ${this.playTools ? "active" : ""}`} onClick={e => { e.stopPropagation; this.togglePlay(); }}> - <FontAwesomeIcon className="dropdown" style={{ margin: 0, transform: this.playTools ? 'rotate(180deg)' : 'rotate(0deg)' }} icon={"angle-down"} /> - {this.playDropdown} - </div> - </span> */} - <div className="miniPres-button" onClick={this.back}><FontAwesomeIcon icon={"arrow-left"} /></div> - <div className="miniPres-button" onClick={() => this.startOrResetPres(this.itemIndex)}><FontAwesomeIcon icon={PresBox.Instance.layoutDoc.presStatus === "auto" ? "pause" : "play"} /></div> - <div className="miniPres-button" onClick={this.next}><FontAwesomeIcon icon={"arrow-right"} /></div> - <div className="miniPres-divider"></div> - <div className="miniPres-button-text">Slide {this.itemIndex + 1} / {this.childDocs.length}</div> - <div className="miniPres-divider"></div> - <div className="miniPres-button" onClick={() => this.layoutDoc.presStatus = "edit"}> - <FontAwesomeIcon icon={"times"} /> - </div> - </div> + {this.playButtons} </div> </div> - <div id="toolbarContainer" className={`presBox-toolbar ${this.layoutDoc.presStatus === "edit" ? "active" : ""}`}> {this.toolbar} </div> + ); + } + + @computed get playButtonFrames() { + const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); + const targetDoc = Cast(activeItem?.presentationTargetDoc, Doc, null); + return ( + <> + {targetDoc ? <div className="miniPres-button-frame" style={{ display: targetDoc.lastFrame !== undefined && targetDoc.lastFrame >= 0 ? "inline-flex" : "none" }}> + <div>{targetDoc.currentFrame}</div> + <div className="miniPres-divider" style={{ border: 'solid 0.5px white', height: '60%' }}></div> + <div>{targetDoc.lastFrame}</div> + </div> : null} + </> + ); + } + + @computed get playButtons() { + // Case 1: There are still other frames and should go through all frames before going to next slide + return (<div className="miniPresOverlay" style={{ display: this.layoutDoc.presStatus !== "edit" ? "inline-flex" : "none" }}> + <div className="miniPres-button" onClick={this.back}><FontAwesomeIcon icon={"arrow-left"} /></div> + <div className="miniPres-button" onClick={() => this.startAutoPres(this.itemIndex)}><FontAwesomeIcon icon={this.layoutDoc.presStatus === "auto" ? "pause" : "play"} /></div> + <div className="miniPres-button" onClick={this.next}><FontAwesomeIcon icon={"arrow-right"} /></div> + <div className="miniPres-divider"></div> + <div className="miniPres-button-text" style={{ display: this.props.PanelWidth() > 250 ? "inline-flex" : "none" }}> + Slide {this.itemIndex + 1} / {this.childDocs.length} + {this.playButtonFrames} + </div> + <div className="miniPres-divider"></div> + {this.props.PanelWidth() > 250 ? <div className="miniPres-button-text" onClick={() => this.layoutDoc.presStatus = "edit"}>EXIT</div> + : <div className="miniPres-button" onClick={() => this.layoutDoc.presStatus = "edit"}> + <FontAwesomeIcon icon={"times"} /> + </div>} + </div>); + } + + render() { + // calling this method for keyEvents + this.isPres; + // needed to ensure that the childDocs are loaded for looking up fields + this.childDocs.slice(); + const mode = StrCast(this.rootDoc._viewType) as CollectionViewType; + return <div className="presBox-cont" style={{ minWidth: this.layoutDoc.inOverlay ? 240 : undefined }} > + {this.topPanel} + {this.toolbar} {this.newDocumentToolbarDropdown} <div className="presBox-listCont"> {mode !== CollectionViewType.Invalid ? diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index af4bd77c7..cc37cf586 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -577,7 +577,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp const mainBulletText: string[] = []; const mainBulletList: Doc[] = []; if (list) { - const newBullets: Doc[] = this.recursiveProgressivize(1, list); + const newBullets: Doc[] = this.recursiveProgressivize(1, list)[0]; mainBulletList.push.apply(mainBulletList, newBullets); } console.log(mainBulletList.length); @@ -591,7 +591,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp this.props.addDocument?.(doc); } - recursiveProgressivize = (nestDepth: number, list: HTMLCollectionOf<HTMLLIElement>, d?: number, y?: number, before?: string): Doc[] => { + recursiveProgressivize = (nestDepth: number, list: HTMLCollectionOf<HTMLLIElement>, d?: number, y?: number, before?: string): [Doc[], number] => { const mainBulletList: Doc[] = []; let b = d ? d : 0; let yLoc = y ? y : 0; @@ -607,29 +607,30 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp if (listItem.childElementCount > 1) { b++; nestCount++; - count = before ? count + nestCount + "." : nestCount + "."; yLoc += height; + count = before ? count + nestCount + "." : nestCount + "."; const text = listItem.getElementsByTagName("p")[0].innerText; const length = text.length; - const bullet1 = Docs.Create.TextDocument(count + " " + text, { title: "Slide text", _width: width, _height: height, x: xLoc, y: 10 + (yLoc), _fontSize: fontSize, backgroundColor: "rgba(0,0,0,0)", appearFrame: d ? d : b }); + const bullet1 = Docs.Create.TextDocument(count + " " + text, { title: "Slide text", _width: width, _autoHeight: true, x: xLoc, y: (yLoc), _fontSize: fontSize, backgroundColor: "rgba(0,0,0,0)", appearFrame: d ? d : b }); + // yLoc += NumCast(bullet1._height); mainBulletList.push(bullet1); const newList = this.recursiveProgressivize(nestDepth + 1, listItem.getElementsByTagName("li"), b, yLoc, count); - mainBulletList.push.apply(mainBulletList, newList); - b += newList.length; + mainBulletList.push.apply(mainBulletList, newList[0]); yLoc += newList.length * (55 - ((nestDepth + 1) * 5)); } else { b++; nestCount++; - count = before ? count + nestCount + "." : nestCount + "."; yLoc += height; + count = before ? count + nestCount + "." : nestCount + "."; const text = listItem.innerText; const length = text.length; - const bullet1 = Docs.Create.TextDocument(count + " " + text, { title: "Slide text", _width: width, _height: height, x: xLoc, y: 10 + (yLoc), _fontSize: fontSize, backgroundColor: "rgba(0,0,0,0)", appearFrame: d ? d : b }); + const bullet1 = Docs.Create.TextDocument(count + " " + text, { title: "Slide text", _width: width, _autoHeight: true, x: xLoc, y: (yLoc), _fontSize: fontSize, backgroundColor: "rgba(0,0,0,0)", appearFrame: d ? d : b }); + // yLoc += NumCast(bullet1._height); mainBulletList.push(bullet1); } } }); - return mainBulletList; + return [mainBulletList, yLoc]; } recordDictation = () => { diff --git a/src/client/views/presentationview/PresElementBox.scss b/src/client/views/presentationview/PresElementBox.scss index fa70b2a41..1e776384a 100644 --- a/src/client/views/presentationview/PresElementBox.scss +++ b/src/client/views/presentationview/PresElementBox.scss @@ -1,6 +1,10 @@ +$light-blue: #AEDDF8; +$dark-blue: #5B9FDD; +$light-background: #ececec; + .presElementBox-item { display: grid; - grid-template-columns: max-content max-content max-content; + grid-template-columns: max-content max-content max-content max-content; background-color: #d5dce2; font-family: Roboto; letter-spacing: normal; @@ -26,7 +30,7 @@ z-index: -1; width: calc(100% + 200px); height: calc(100% + 8px); - background-color: #AEDDF8; + background-color: $light-blue; } .presElementBox-highlightTop { @@ -69,7 +73,7 @@ .presElementBox-active { color: black; border-radius: 6px; - border: solid 2px #5B9FDD; + border: solid 2px $dark-blue; } .presElementBox-buttons { @@ -118,7 +122,7 @@ padding-left: 10px; padding-right: 10px; letter-spacing: normal; - max-width: max-content; + width: max-content; text-overflow: ellipsis; overflow: hidden; white-space: pre; diff --git a/src/client/views/presentationview/PresElementBox.tsx b/src/client/views/presentationview/PresElementBox.tsx index 11ffde9dd..a6dbb76ef 100644 --- a/src/client/views/presentationview/PresElementBox.tsx +++ b/src/client/views/presentationview/PresElementBox.tsx @@ -189,7 +189,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDoc DataDoc={this.targetDoc[DataSym] !== this.targetDoc && this.targetDoc[DataSym]} LibraryPath={emptyPath} fitToBox={true} - backgroundColor={() => "darkgrey"} + backgroundColor={this.props.backgroundColor} rootSelected={returnTrue} addDocument={returnFalse} removeDocument={returnFalse} @@ -238,7 +238,6 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDoc e.stopPropagation(); e.preventDefault(); if (element) { - console.log(element.className); if (PresBox.Instance._eleArray.includes(element)) { setupMoveUpEvents(this, e, this.startDrag, emptyFunction, emptyFunction); } @@ -254,11 +253,8 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDoc } startDrag = (e: PointerEvent, down: number[], delta: number[]) => { - // const ele: HTMLElement[] = PresBox.Instance._eleArray.map(doc => doc); const activeItem = this.rootDoc; const dragData = new DragManager.DocumentDragData(PresBox.Instance.sortArray().map(doc => doc)); - // let value = this.getValue(this._heading); - // value = typeof value === "string" ? `"${value}"` : value; const dragItem: HTMLElement[] = []; PresBox.Instance._dragArray.map(ele => { const drag = ele; @@ -330,14 +326,14 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDoc <div className="presElementBox-number"> {`${this.indexInPres + 1}.`} </div> - <div ref={this._dragRef} className="presElementBox-name"> + <div ref={this._dragRef} className="presElementBox-name" style={{ maxWidth: (PresBox.Instance.toolbarWidth - 70) }}> {`${this.targetDoc?.title}`} </div> <Tooltip title={<><div className="dash-tooltip">{"Movement speed"}</div></>}><div className="presElementBox-time" style={{ display: PresBox.Instance.toolbarWidth > 300 ? "block" : "none" }}>{this.transition}</div></Tooltip> <Tooltip title={<><div className="dash-tooltip">{"Duration"}</div></>}><div className="presElementBox-time" style={{ display: PresBox.Instance.toolbarWidth > 300 ? "block" : "none" }}>{this.duration}</div></Tooltip> + <Tooltip title={<><div className="dash-tooltip">{"Presentation pin view"}</div></>}><div className="presElementBox-time" style={{ fontWeight: 700, display: this.rootDoc.presPinView && PresBox.Instance.toolbarWidth > 300 ? "block" : "none" }}>V</div></Tooltip> <Tooltip title={<><div className="dash-tooltip">{"Remove from presentation"}</div></>}><div className="presElementBox-closeIcon" - // onPointerDown={e => e.stopPropagation()} onClick={e => { this.props.removeDocument?.(this.rootDoc); e.stopPropagation(); @@ -363,6 +359,4 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDoc </div> ); } -} - -// this.layoutDoc.title !== "pres element template"
\ No newline at end of file +}
\ No newline at end of file |