diff options
| author | Bob Zeleznik <zzzman@gmail.com> | 2020-02-08 13:48:11 -0500 |
|---|---|---|
| committer | Bob Zeleznik <zzzman@gmail.com> | 2020-02-08 13:48:11 -0500 |
| commit | 90d7fb57a64011763ad1d608126eacb052061e43 (patch) | |
| tree | fd96990ebd0ffe38f2285fbbceca942c1fb45587 /src/client/views/nodes/PresBox.tsx | |
| parent | e310c0fdcef6ac71ee492470d4ac689cbb094167 (diff) | |
| parent | 1b046f76cf39f1f6cb1875aa84b45db74b6d994e (diff) | |
Merge branch 'master' into monika_animation
Diffstat (limited to 'src/client/views/nodes/PresBox.tsx')
| -rw-r--r-- | src/client/views/nodes/PresBox.tsx | 198 |
1 files changed, 123 insertions, 75 deletions
diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx index cbb83b511..6c4cbba12 100644 --- a/src/client/views/nodes/PresBox.tsx +++ b/src/client/views/nodes/PresBox.tsx @@ -2,23 +2,27 @@ import React = require("react"); import { library } from '@fortawesome/fontawesome-svg-core'; import { faArrowLeft, faArrowRight, faEdit, faMinus, faPlay, faPlus, faStop, faTimes } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { action, computed, reaction, IReactionDisposer } from "mobx"; +import { action, computed, IReactionDisposer, reaction, observable, runInAction } from "mobx"; import { observer } from "mobx-react"; import { Doc, DocListCast, DocListCastAsync } from "../../../new_fields/Doc"; -import { listSpec } from "../../../new_fields/Schema"; +import { listSpec, makeInterface } from "../../../new_fields/Schema"; import { Cast, FieldValue, NumCast } from "../../../new_fields/Types"; import { CurrentUserUtils } from "../../../server/authentication/models/current_user_utils"; +import { Docs } from "../../documents/Documents"; import { DocumentManager } from "../../util/DocumentManager"; import { undoBatch } from "../../util/UndoManager"; -import { CollectionViewType } from "../collections/CollectionView"; import { CollectionDockingView } from "../collections/CollectionDockingView"; -import { CollectionView } from "../collections/CollectionView"; +import { CollectionView, CollectionViewType } from "../collections/CollectionView"; import { ContextMenu } from "../ContextMenu"; import { FieldView, FieldViewProps } from './FieldView'; import "./PresBox.scss"; -import { DocumentType } from "../../documents/DocumentTypes"; -import { Docs } from "../../documents/Documents"; -import { ComputedField } from "../../../new_fields/ScriptField"; +import { CollectionCarouselView } from "../collections/CollectionCarouselView"; +import { returnFalse } from "../../../Utils"; +import { ContextMenuProps } from "../ContextMenuItem"; +import { CollectionTimeView } from "../collections/CollectionTimeView"; +import { documentSchema } from "../../../new_fields/documentSchemas"; +import { InkingControl } from "../InkingControl"; +import { InkTool } from "../../../new_fields/InkField"; library.add(faArrowLeft); library.add(faArrowRight); @@ -32,38 +36,45 @@ library.add(faEdit); @observer export class PresBox extends React.Component<FieldViewProps> { public static LayoutString(fieldKey: string) { return FieldView.LayoutString(PresBox, fieldKey); } - _docListChangedReaction: IReactionDisposer | undefined; + _childReaction: IReactionDisposer | undefined; + _slideshowReaction: IReactionDisposer | undefined; + @observable _isChildActive = false; + componentDidMount() { - this._docListChangedReaction = reaction(() => { - const value = FieldValue(Cast(this.props.Document[this.props.fieldKey], listSpec(Doc))); - return value ? value.slice() : value; - }, () => { - const value = FieldValue(Cast(this.props.Document[this.props.fieldKey], listSpec(Doc))); - if (value) { - value.forEach((item, i) => { - if (item instanceof Doc && item.type !== DocumentType.PRESELEMENT) { - let pinDoc = Docs.Create.PresElementBoxDocument({ backgroundColor: "transparent" }); - Doc.GetProto(pinDoc).presentationTargetDoc = item; - Doc.GetProto(pinDoc).title = ComputedField.MakeFunction('(this.presentationTargetDoc instanceof Doc) && this.presentationTargetDoc.title.toString()'); - value.splice(i, 1, pinDoc); + const userDoc = CurrentUserUtils.UserDocument; + this._slideshowReaction = reaction(() => this.props.Document._slideshow, + (slideshow) => { + if (!slideshow) { + let presTemp = Cast(userDoc.presentationTemplate, Doc); + if (presTemp instanceof Promise) { + presTemp.then(presTemp => this.props.Document.childLayout = presTemp); } - }); - } - }); + else if (presTemp === undefined) { + presTemp = userDoc.presentationTemplate = Docs.Create.PresElementBoxDocument({ backgroundColor: "transparent", _xMargin: 5, isTemplateDoc: true, isTemplateForField: "data" }); + } + else { + this.props.Document.childLayout = presTemp; + } + } else { + this.props.Document.childLayout = undefined; + } + }, { fireImmediately: true }); + this._childReaction = reaction(() => this.childDocs.slice(), (children) => children.forEach((child, i) => child.presentationIndex = i), { fireImmediately: true }); } - componentWillUnmount() { - this._docListChangedReaction && this._docListChangedReaction(); + this._childReaction?.(); + this._slideshowReaction?.(); } @computed get childDocs() { return DocListCast(this.props.Document[this.props.fieldKey]); } next = async () => { - const current = NumCast(this.props.Document.selectedDoc); + runInAction(() => Doc.UserDoc().curPresentation = this.props.Document); + const current = NumCast(this.props.Document._itemIndex); //asking to get document at current index - let docAtCurrentNext = await this.getDocAtIndex(current + 1); + const docAtCurrentNext = await this.getDocAtIndex(current + 1); if (docAtCurrentNext !== undefined) { - let presDocs = DocListCast(this.props.Document[this.props.fieldKey]); + const presDocs = DocListCast(this.props.Document[this.props.fieldKey]); let nextSelected = current + 1; for (; nextSelected < presDocs.length - 1; nextSelected++) { @@ -76,17 +87,18 @@ export class PresBox extends React.Component<FieldViewProps> { } } back = async () => { - const current = NumCast(this.props.Document.selectedDoc); + action(() => Doc.UserDoc().curPresentation = this.props.Document); + const current = NumCast(this.props.Document._itemIndex); //requesting for the doc at current index - let docAtCurrent = await this.getDocAtIndex(current); + const docAtCurrent = await this.getDocAtIndex(current); if (docAtCurrent !== undefined) { //asking for its presentation id. let prevSelected = current; let zoomOut: boolean = false; - let presDocs = await DocListCastAsync(this.props.Document[this.props.fieldKey]); - let currentsArray: Doc[] = []; + const presDocs = await DocListCastAsync(this.props.Document[this.props.fieldKey]); + const currentsArray: Doc[] = []; for (; presDocs && prevSelected > 0 && presDocs[prevSelected].groupButton; prevSelected--) { currentsArray.push(presDocs[prevSelected]); } @@ -104,8 +116,8 @@ export class PresBox extends React.Component<FieldViewProps> { //If so making sure to zoom out, which goes back to state before zooming action if (current > 0) { if (zoomOut || docAtCurrent.showButton) { - let prevScale = NumCast(this.childDocs[prevSelected].viewScale, null); - let curScale = DocumentManager.Instance.getScaleOfDocView(this.childDocs[current]); + const prevScale = NumCast(this.childDocs[prevSelected].viewScale, null); + const curScale = DocumentManager.Instance.getScaleOfDocView(this.childDocs[current]); if (prevScale !== undefined && prevScale !== curScale) { DocumentManager.Instance.zoomIntoScale(docAtCurrent, prevScale); } @@ -115,12 +127,17 @@ export class PresBox extends React.Component<FieldViewProps> { } } + whenActiveChanged = action((isActive: boolean) => this.props.whenActiveChanged(this._isChildActive = isActive)); + active = (outsideReaction?: boolean) => ((InkingControl.Instance.selectedTool === InkTool.None && !this.props.Document.isBackground) && + (this.props.Document.forceActive || this.props.isSelected(outsideReaction) || this._isChildActive || this.props.renderDepth === 0) ? true : false) + /** * This is the method that checks for the actions that need to be performed * after the document has been presented, which involves 3 button options: * Hide Until Presented, Hide After Presented, Fade After Presented */ showAfterPresented = (index: number) => { + action(() => Doc.UserDoc().curPresentation = this.props.Document); this.childDocs.forEach((doc, ind) => { //the order of cases is aligned based on priority if (doc.hideTillShownButton && ind <= index) { @@ -141,6 +158,7 @@ export class PresBox extends React.Component<FieldViewProps> { * Hide Until Presented, Hide After Presented, Fade After Presented */ hideIfNotPresented = (index: number) => { + action(() => Doc.UserDoc().curPresentation = this.props.Document); this.childDocs.forEach((key, ind) => { //the order of cases is aligned based on priority @@ -162,13 +180,14 @@ export class PresBox extends React.Component<FieldViewProps> { * te option open, navigates to that element. */ navigateToElement = async (curDoc: Doc, fromDocIndex: number) => { - let fromDoc = this.childDocs[fromDocIndex].presentationTargetDoc as Doc; + action(() => Doc.UserDoc().curPresentation = this.props.Document); + const fromDoc = this.childDocs[fromDocIndex].presentationTargetDoc as Doc; let docToJump = curDoc; let willZoom = false; - let presDocs = DocListCast(this.props.Document[this.props.fieldKey]); + const presDocs = DocListCast(this.props.Document[this.props.fieldKey]); let nextSelected = presDocs.indexOf(curDoc); - let currentDocGroups: Doc[] = []; + const currentDocGroups: Doc[] = []; for (; nextSelected < presDocs.length - 1; nextSelected++) { if (!presDocs[nextSelected + 1].groupButton) { break; @@ -188,15 +207,17 @@ export class PresBox extends React.Component<FieldViewProps> { }); //docToJump stayed same meaning, it was not in the group or was the last element in the group + const aliasOf = await Cast(docToJump.aliasOf, Doc); + const srcContext = aliasOf && await Cast(aliasOf.sourceContext, Doc); if (docToJump === curDoc) { //checking if curDoc has navigation open - let target = await curDoc.presentationTargetDoc as Doc; - if (curDoc.navButton) { - DocumentManager.Instance.jumpToDocument(target, false); - } else if (curDoc.showButton) { - let curScale = DocumentManager.Instance.getScaleOfDocView(fromDoc); + const target = await Cast(curDoc.presentationTargetDoc, Doc); + if (curDoc.navButton && target) { + DocumentManager.Instance.jumpToDocument(target, false, undefined, srcContext); + } else if (curDoc.showButton && target) { + const curScale = DocumentManager.Instance.getScaleOfDocView(fromDoc); //awaiting jump so that new scale can be found, since jumping is async - await DocumentManager.Instance.jumpToDocument(target, true); + await DocumentManager.Instance.jumpToDocument(target, true, undefined, srcContext); curDoc.viewScale = DocumentManager.Instance.getScaleOfDocView(target); //saving the scale user was on before zooming in @@ -207,11 +228,12 @@ export class PresBox extends React.Component<FieldViewProps> { } return; } - let curScale = DocumentManager.Instance.getScaleOfDocView(fromDoc); + const curScale = DocumentManager.Instance.getScaleOfDocView(fromDoc); //awaiting jump so that new scale can be found, since jumping is async - await DocumentManager.Instance.jumpToDocument(await docToJump.presentationTargetDoc as Doc, willZoom); - let newScale = DocumentManager.Instance.getScaleOfDocView(await curDoc.presentationTargetDoc as Doc); + const presTargetDoc = await docToJump.presentationTargetDoc as Doc; + await DocumentManager.Instance.jumpToDocument(presTargetDoc, willZoom, undefined, srcContext); + const newScale = DocumentManager.Instance.getScaleOfDocView(await curDoc.presentationTargetDoc as Doc); curDoc.viewScale = newScale; //saving the scale that user was on if (curScale !== 1) { @@ -226,7 +248,7 @@ export class PresBox extends React.Component<FieldViewProps> { getDocAtIndex = async (index: number) => { const list = FieldValue(Cast(this.props.Document[this.props.fieldKey], listSpec(Doc))); if (list && index >= 0 && index < list.length) { - this.props.Document.selectedDoc = index; + this.props.Document._itemIndex = index; //awaiting async call to finish to get Doc instance return list[index]; } @@ -238,7 +260,7 @@ export class PresBox extends React.Component<FieldViewProps> { public removeDocument = (doc: Doc) => { const value = FieldValue(Cast(this.props.Document[this.props.fieldKey], listSpec(Doc))); if (value) { - let indexOfDoc = value.indexOf(doc); + const indexOfDoc = value.indexOf(doc); if (indexOfDoc !== - 1) { value.splice(indexOfDoc, 1)[0]; return true; @@ -249,12 +271,12 @@ export class PresBox extends React.Component<FieldViewProps> { //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. - @action public gotoDocument = async (index: number, fromDoc: number) => { + action(() => Doc.UserDoc().curPresentation = this.props.Document); Doc.UnBrushAllDocs(); const list = FieldValue(Cast(this.props.Document[this.props.fieldKey], listSpec(Doc))); if (list && index >= 0 && index < list.length) { - this.props.Document.selectedDoc = index; + this.props.Document._itemIndex = index; if (!this.props.Document.presStatus) { this.props.Document.presStatus = true; @@ -271,26 +293,33 @@ export class PresBox extends React.Component<FieldViewProps> { } //The function that starts or resets presentaton functionally, depending on status flag. - @action startOrResetPres = () => { + action(() => Doc.UserDoc().curPresentation = this.props.Document); if (this.props.Document.presStatus) { this.resetPresentation(); } else { this.props.Document.presStatus = true; this.startPresentation(0); - this.gotoDocument(0, NumCast(this.props.Document.selectedDoc)); + this.gotoDocument(0, NumCast(this.props.Document._itemIndex)); } } + addDocument = (doc: Doc) => { + const newPinDoc = Doc.MakeAlias(doc); + newPinDoc.presentationTargetDoc = doc; + return Doc.AddDocToList(this.props.Document, this.props.fieldKey, newPinDoc); + } + + //The function that resets the presentation by removing every action done by it. It also //stops the presentaton. - @action resetPresentation = () => { + action(() => Doc.UserDoc().curPresentation = this.props.Document); this.childDocs.forEach((doc: Doc) => { doc.opacity = 1; doc.viewScale = 1; }); - this.props.Document.selectedDoc = 0; + this.props.Document._itemIndex = 0; this.props.Document.presStatus = false; if (this.childDocs.length !== 0) { DocumentManager.Instance.zoomIntoScale(this.childDocs[0], 1); @@ -300,6 +329,7 @@ export class PresBox extends React.Component<FieldViewProps> { //The function that starts the presentation, also checking if actions should be applied //directly at start. startPresentation = (startIndex: number) => { + action(() => Doc.UserDoc().curPresentation = this.props.Document); this.childDocs.map(doc => { if (doc.hideTillShownButton && this.childDocs.indexOf(doc) > startIndex) { doc.opacity = 0; @@ -327,42 +357,63 @@ export class PresBox extends React.Component<FieldViewProps> { })); specificContextMenu = (e: React.MouseEvent): void => { - ContextMenu.Instance.addItem({ description: "Make Current Presentation", event: action(() => Doc.UserDoc().curPresentation = this.props.Document), icon: "asterisk" }); + const funcs: ContextMenuProps[] = []; + funcs.push({ description: "Show as Slideshow", event: action(() => this.props.Document._slideshow = "slideshow"), icon: "asterisk" }); + funcs.push({ description: "Show as Timeline", event: action(() => this.props.Document._slideshow = "timeline"), icon: "asterisk" }); + funcs.push({ description: "Show as List", event: action(() => this.props.Document._slideshow = undefined), icon: "asterisk" }); + ContextMenu.Instance.addItem({ description: "Presentation Funcs...", subitems: funcs, icon: "asterisk" }); } /** * Initially every document starts with a viewScale 1, which means * that they will be displayed in a canvas with scale 1. */ - @action initializeScaleViews = (docList: Doc[], viewtype: number) => { - this.props.Document.chromeStatus = "disabled"; - let hgt = (viewtype === CollectionViewType.Tree) ? 50 : 72; + this.props.Document._chromeStatus = "disabled"; + const hgt = (viewtype === CollectionViewType.Tree) ? 50 : 46; docList.forEach((doc: Doc) => { doc.presBox = this.props.Document; doc.presBoxKey = this.props.fieldKey; doc.collapsedHeight = hgt; - doc.height = ComputedField.MakeFunction("this.collapsedHeight + Number(this.embedOpen ? 100:0)"); - let curScale = NumCast(doc.viewScale, null); + doc._nativeWidth = doc._nativeHeight = undefined; + const curScale = NumCast(doc.viewScale, null); if (curScale === undefined) { doc.viewScale = 1; } }); } - selectElement = (doc: Doc) => { - let index = DocListCast(this.props.Document[this.props.fieldKey]).indexOf(doc); - index !== -1 && this.gotoDocument(index, NumCast(this.props.Document.selectedDoc)); + const index = DocListCast(this.props.Document[this.props.fieldKey]).indexOf(doc); + index !== -1 && this.gotoDocument(index, NumCast(this.props.Document._itemIndex)); } getTransform = () => { - return this.props.ScreenToLocalTransform().translate(-10, -50);// listBox padding-left and pres-box-cont minHeight + return this.props.ScreenToLocalTransform().translate(0, -50);// listBox padding-left and pres-box-cont minHeight + } + panelHeight = () => { + return this.props.PanelHeight() - 20; } render() { - this.initializeScaleViews(this.childDocs, NumCast(this.props.Document.viewType)); - return ( - <div className="presBox-cont" onContextMenu={this.specificContextMenu}> + this.initializeScaleViews(this.childDocs, NumCast(this.props.Document._viewType)); + return (this.props.Document._slideshow ? + <div className="presBox-cont" onContextMenu={this.specificContextMenu} style={{ pointerEvents: this.active() ? "all" : "none" }} > + {this.props.Document.inOverlay ? (null) : + <div className="presBox-listCont" > + {this.props.Document._slideshow === "slideshow" ? + <CollectionCarouselView {...this.props} PanelHeight={this.panelHeight} chromeCollapsed={true} annotationsKey={""} CollectionView={undefined} + moveDocument={returnFalse} + addDocument={this.addDocument} removeDocument={returnFalse} focus={this.selectElement} ScreenToLocalTransform={this.getTransform} /> + : + <CollectionTimeView {...this.props} PanelHeight={this.panelHeight} chromeCollapsed={true} annotationsKey={""} CollectionView={undefined} + moveDocument={returnFalse} + addDocument={this.addDocument} removeDocument={returnFalse} focus={this.selectElement} ScreenToLocalTransform={this.getTransform} /> + } + </div>} + <button className="presBox-backward" title="Back" onClick={this.back}><FontAwesomeIcon icon={"arrow-left"} /></button> + <button className="presBox-forward" title="Next" onClick={this.next}><FontAwesomeIcon icon={"arrow-right"} /></button> + </div> + : <div className="presBox-cont" onContextMenu={this.specificContextMenu}> <div className="presBox-buttons"> <button className="presBox-button" title="Back" onClick={this.back}><FontAwesomeIcon icon={"arrow-left"} /></button> <button className="presBox-button" title={"Reset Presentation" + this.props.Document.presStatus ? "" : " From Start"} onClick={this.startOrResetPres}> @@ -370,13 +421,10 @@ export class PresBox extends React.Component<FieldViewProps> { </button> <button className="presBox-button" title="Next" onClick={this.next}><FontAwesomeIcon icon={"arrow-right"} /></button> <button className="presBox-button" title={this.props.Document.inOverlay ? "Expand" : "Minimize"} onClick={this.toggleMinimize}><FontAwesomeIcon icon={"eye"} /></button> - </div> - {this.props.Document.inOverlay ? (null) : - <div className="presBox-listCont" > - <CollectionView {...this.props} focus={this.selectElement} ScreenToLocalTransform={this.getTransform} /> - </div> - } - </div> - ); + {this.props.Document.inOverlay ? (null) : + <div className="presBox-listCont"> + <CollectionView {...this.props} whenActiveChanged={this.whenActiveChanged} PanelHeight={this.panelHeight} addDocument={this.addDocument} focus={this.selectElement} ScreenToLocalTransform={this.getTransform} /> + </div>} + </div></div>); } }
\ No newline at end of file |
