From 3415f672292bb349c7d9ec66564933a746ee3b25 Mon Sep 17 00:00:00 2001 From: mehekj Date: Mon, 20 Jun 2022 18:27:29 -0400 Subject: Revert "Merge branch 'master' into temporalmedia-mehek" This reverts commit 145117365b2708ef6b365c6f0f10c38b85a87307, reversing changes made to 7eedde332010c8896be636f0b5c6a7b2c8043e48. --- src/client/views/nodes/trails/PresBox.tsx | 152 ++++---- src/client/views/nodes/trails/PresElementBox.scss | 328 ++++++++-------- src/client/views/nodes/trails/PresElementBox.tsx | 438 ++++++++++------------ 3 files changed, 429 insertions(+), 489 deletions(-) (limited to 'src/client/views/nodes/trails') diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx index 1dd6fef9b..e32f2826f 100644 --- a/src/client/views/nodes/trails/PresBox.tsx +++ b/src/client/views/nodes/trails/PresBox.tsx @@ -10,16 +10,17 @@ import { InkTool } from "../../../../fields/InkField"; import { List } from "../../../../fields/List"; import { PrefetchProxy } from "../../../../fields/Proxy"; import { listSpec } from "../../../../fields/Schema"; +import { ScriptField } from "../../../../fields/ScriptField"; import { BoolCast, Cast, NumCast, StrCast } from "../../../../fields/Types"; import { emptyFunction, returnFalse, returnOne, returnTrue, setupMoveUpEvents } from '../../../../Utils'; import { Docs } from "../../../documents/Documents"; import { DocumentType } from "../../../documents/DocumentTypes"; import { CurrentUserUtils } from "../../../util/CurrentUserUtils"; import { DocumentManager } from "../../../util/DocumentManager"; +import { ScriptingGlobals } from "../../../util/ScriptingGlobals"; import { SelectionManager } from "../../../util/SelectionManager"; import { undoBatch, UndoManager } from "../../../util/UndoManager"; import { CollectionDockingView } from "../../collections/CollectionDockingView"; -import { MarqueeViewBounds } from "../../collections/collectionFreeForm"; import { CollectionView, CollectionViewType } from "../../collections/CollectionView"; import { TabDocView } from "../../collections/TabDocView"; import { ViewBoxBaseComponent } from "../../DocComponent"; @@ -29,21 +30,12 @@ import { CollectionFreeFormDocumentView } from "../CollectionFreeFormDocumentVie import { FieldView, FieldViewProps } from '../FieldView'; import "./PresBox.scss"; import { PresEffect, PresMovement, PresStatus } from "./PresEnums"; -import { ScriptingGlobals } from "../../../util/ScriptingGlobals"; -export interface PinProps { +export class PinProps { audioRange?: boolean; + unpin?: boolean; setPosition?: boolean; hidePresBox?: boolean; - pinWithView?: PinViewProps; - pinDocView?: boolean; // whether the current view specs of the document should be saved the pinned document - panelWidth?: number; // panel width and height of the document (used to compute the bounds of the pinned view area) - panelHeight?: number -} - -export interface PinViewProps { - bounds: MarqueeViewBounds; - scale: number; } @observer @@ -106,11 +98,12 @@ export class PresBox extends ViewBoxBaseComponent() { @observable private openMovementDropdown: boolean = false; @observable private openEffectDropdown: boolean = false; @observable private presentTools: boolean = false; - @computed get isTreeOrStack() {return [CollectionViewType.Tree, CollectionViewType.Stacking].includes(StrCast(this.layoutDoc._viewType) as any) } - @computed get isTree() { return this.layoutDoc._viewType === CollectionViewType.Tree;} - @computed get presFieldKey() { return StrCast(this.layoutDoc.presFieldKey, "data"); } - @computed get childDocs() { return DocListCast(this.rootDoc[this.presFieldKey]); } - @observable _treeViewMap: Map = new Map(); + // @computed get childDocs() { return DocListCast(this.rootDoc[this.fieldKey]); } + // TODO: [AL] add childDocs() and treeMap fields + // @computed get childDocs() { return DocListCast(this.rootDoc.presentationaLinearizedDocuments); } + //_treeViewMap:Map + @computed get childDocs() { return this.layoutDoc._viewType === CollectionViewType.Tree ? DocListCast(this.rootDoc.presentationLinearizedDocuments) : DocListCast(this.rootDoc[this.fieldKey]); } + @observable _treeViewMap: Map = new Map(); @computed get tagDocs() { const tagDocs: Doc[] = []; @@ -139,6 +132,12 @@ export class PresBox extends ViewBoxBaseComponent() { Doc.UserDoc().presElement = new PrefetchProxy(Docs.Create.PresElementBoxDocument({ title: "pres element template", type: DocumentType.PRESELEMENT, _fitWidth: true, _xMargin: 0, isTemplateDoc: true, isTemplateForField: "data" })); + // this script will be called by each presElement to get rendering-specific info that the PresBox knows about but which isn't written to the PresElement + // this is a design choice -- we could write this data to the presElements which would require a reaction to keep it up to date, and it would prevent + // the preselement docs from being part of multiple presentations since they would all have the same field, or we'd have to keep per-presentation data + // stored on each pres element. + (this.presElement as Doc).lookupField = ScriptField.MakeFunction("lookupPresBoxField(container, field, data)", + { field: "string", data: Doc.name, container: Doc.name }); } this.props.Document.presentationFieldKey = this.fieldKey; // provide info to the presElement script so that it can look up rendering information about the presBox @@ -158,10 +157,8 @@ export class PresBox extends ViewBoxBaseComponent() { } @computed get selectedDoc() { return this.selectedDocumentView?.rootDoc; } - _unmounting = false; @action componentWillUnmount() { - this._unmounting = true; document.removeEventListener("keydown", PresBox.keyEventsWrapper, true); this._presKeyEventsActive = false; this.resetPresentation(); @@ -172,7 +169,7 @@ export class PresBox extends ViewBoxBaseComponent() { @action componentDidMount() { - this._unmounting = false; + this.rootDoc.presBox = this.rootDoc; this.rootDoc._forceRenderEngine = "timeline"; this.layoutDoc.presStatus = PresStatus.Edit; this.layoutDoc._gridGap = 0; @@ -331,40 +328,22 @@ export class PresBox extends ViewBoxBaseComponent() { navigateToView = (targetDoc: Doc, activeItem: Doc) => { clearTimeout(this._navTimer); const bestTarget = DocumentManager.Instance.getFirstDocumentView(targetDoc)?.props.Document; - if (bestTarget) console.log(bestTarget.title, bestTarget.type); - else console.log("no best target"); - if (bestTarget) this._navTimer = PresBox.navigateToDoc(bestTarget, activeItem, false); - } - - // navigates to the bestTarget document by making sure it is on screen, - // then it applies the view specs stored in activeItem to - @action - static navigateToDoc(bestTarget:Doc, activeItem:Doc, jumpToDoc:boolean) { - if (bestTarget.type === DocumentType.PDF || bestTarget.type === DocumentType.WEB || bestTarget.type === DocumentType.RTF || bestTarget._viewType === CollectionViewType.Stacking) { - bestTarget._viewTransition = activeItem.presTransition ? `transform ${activeItem.presTransition}ms` : 'all 0.5s'; - bestTarget._scrollTop = activeItem.presPinViewScroll; - } else if (bestTarget.type === DocumentType.COMPARISON) { - bestTarget._clipWidth = activeItem.presPinClipWidth; - } else if ([DocumentType.AUDIO, DocumentType.VID].includes(bestTarget.type as any)) { - bestTarget._currentTimecode = activeItem.presStartTime; - } else { - const contentBounds= Cast(activeItem.contentBounds, listSpec("number")); - bestTarget._viewTransition = activeItem.presTransition ? `transform ${activeItem.presTransition}ms` : 'all 0.5s'; - if (contentBounds) { - bestTarget._panX = (contentBounds[0] + contentBounds[2])/2; - bestTarget._panY = (contentBounds[1] + contentBounds[3])/2; - const dv = DocumentManager.Instance.getDocumentView(bestTarget); - if (dv) { - bestTarget._viewScale = Math.min(dv.props.PanelHeight() / (contentBounds[3] - contentBounds[1]), - dv.props.PanelWidth() / (contentBounds[2]- contentBounds[0])); - }; + bestTarget && runInAction(() => { + if (bestTarget.type === DocumentType.PDF || bestTarget.type === DocumentType.WEB || bestTarget.type === DocumentType.RTF || bestTarget._viewType === CollectionViewType.Stacking) { + bestTarget._viewTransition = activeItem.presTransition ? `transform ${activeItem.presTransition}ms` : 'all 0.5s'; + bestTarget._scrollTop = activeItem.presPinViewScroll; + } else if (bestTarget.type === DocumentType.COMPARISON) { + bestTarget._clipWidth = activeItem.presPinClipWidth; + } else if (bestTarget.type === DocumentType.VID) { + bestTarget._currentTimecode = activeItem.presStartTime; } else { + bestTarget._viewTransition = activeItem.presTransition ? `transform ${activeItem.presTransition}ms` : 'all 0.5s'; bestTarget._panX = activeItem.presPinViewX; bestTarget._panY = activeItem.presPinViewY; bestTarget._viewScale = activeItem.presPinViewScale; } - } - return setTimeout(() => bestTarget._viewTransition = undefined, activeItem.presTransition ? NumCast(activeItem.presTransition) + 10 : 510); + this._navTimer = setTimeout(() => bestTarget._viewTransition = undefined, activeItem.presTransition ? NumCast(activeItem.presTransition) + 10 : 510); + }); } /** @@ -422,17 +401,15 @@ export class PresBox extends ViewBoxBaseComponent() { // openInTab(targetDoc); } else if (curDoc.presMovement === PresMovement.Pan && targetDoc) { LightboxView.SetLightboxDoc(undefined); - await DocumentManager.Instance.jumpToDocument(targetDoc, false, openInTab, srcContext ? [srcContext]:[], undefined, undefined, undefined, includesDoc || tab ? undefined : resetSelection, undefined, true); // documents open in new tab instead of on right + await DocumentManager.Instance.jumpToDocument(targetDoc, false, openInTab, [srcContext], undefined, undefined, undefined, includesDoc || tab ? undefined : resetSelection, undefined, true); // documents open in new tab instead of on right } else if ((curDoc.presMovement === PresMovement.Zoom || curDoc.presMovement === PresMovement.Jump) && targetDoc) { LightboxView.SetLightboxDoc(undefined); //awaiting jump so that new scale can be found, since jumping is async - await DocumentManager.Instance.jumpToDocument(targetDoc, true, openInTab, srcContext ? [srcContext]:[], undefined, undefined, undefined, includesDoc || tab ? undefined : resetSelection, undefined, true, NumCast(curDoc.presZoom)); // documents open in new tab instead of on right + await DocumentManager.Instance.jumpToDocument(targetDoc, true, openInTab, [srcContext], undefined, undefined, undefined, includesDoc || tab ? undefined : resetSelection, undefined, true, NumCast(curDoc.presZoom)); // documents open in new tab instead of on right } // 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. if (activeItem.presPinView) { - console.log(targetDoc.title); - console.log("presPinView in PresBox.tsx:420"); // if targetDoc is not displayed but one of its aliases is, then we need to modify that alias, not the original target this.navigateToView(targetDoc, activeItem); } @@ -644,17 +621,14 @@ export class PresBox extends ViewBoxBaseComponent() { * Called when the user changes the view type * Either 'List' (stacking) or 'Slides' (carousel) */ - @undoBatch + // @undoBatch viewChanged = action((e: React.ChangeEvent) => { //@ts-ignore const viewType = e.target.selectedOptions[0].value as CollectionViewType; - this.layoutDoc.presFieldKey = this.fieldKey+(viewType === CollectionViewType.Tree ?"-linearized":""); // pivot field may be set by the user in timeline view (or some other way) -- need to reset it here [CollectionViewType.Tree || CollectionViewType.Stacking].includes(viewType) && (this.rootDoc._pivotField = undefined); this.rootDoc._viewType = viewType; - if (this.isTreeOrStack) { - this.layoutDoc._gridGap = 0; - } + if ([CollectionViewType.Tree || CollectionViewType.Stacking].includes(viewType)) this.layoutDoc._gridGap = 0; }); /** @@ -728,7 +702,7 @@ export class PresBox extends ViewBoxBaseComponent() { }); return true; } - childLayoutTemplate = () => !this.isTreeOrStack ? undefined : this.presElement; + childLayoutTemplate = () => ![CollectionViewType.Stacking, CollectionViewType.Tree].includes(this.rootDoc._viewType as any) ? undefined : this.presElement; removeDocument = (doc: Doc) => Doc.RemoveDocFromList(this.rootDoc, this.fieldKey, doc); getTransform = () => this.props.ScreenToLocalTransform().translate(-5, -65);// listBox padding-left and pres-box-cont minHeight panelHeight = () => this.props.PanelHeight() - 40; @@ -827,13 +801,13 @@ export class PresBox extends ViewBoxBaseComponent() { //regular click @action - regularSelect = (doc: Doc, ref: HTMLElement, drag: HTMLElement, focus: boolean, selectPres = true) => { + regularSelect = (doc: Doc, ref: HTMLElement, drag: HTMLElement, focus: boolean) => { this._selectedArray.clear(); this._selectedArray.set(doc, undefined); this._eleArray.splice(0, this._eleArray.length, ref); this._dragArray.splice(0, this._dragArray.length, drag); focus && this.selectElement(doc); - selectPres && this.selectPres(); + this.selectPres(); } modifierSelect = (doc: Doc, ref: HTMLElement, drag: HTMLElement, focus: boolean, cmdClick: boolean, shiftClick: boolean) => { @@ -1002,7 +976,7 @@ export class PresBox extends ViewBoxBaseComponent() { /** * 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 _fitContentsToBox as true so the + * 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) @@ -1389,7 +1363,7 @@ export class PresBox extends ViewBoxBaseComponent() { const scroll = targetDoc._scrollTop; activeItem.presPinView = true; activeItem.presPinViewScroll = scroll; - } else if ([DocumentType.AUDIO, DocumentType.VID].includes(targetDoc.type as any)) { + } else if (targetDoc.type === DocumentType.VID) { activeItem.presStartTime = targetDoc._currentTimecode; activeItem.presEndTime = NumCast(targetDoc._currentTimecode) + 0.1; } else if ((targetDoc.type === DocumentType.COL && targetDoc._viewType === CollectionViewType.Freeform) || targetDoc.type === DocumentType.IMG) { @@ -1412,7 +1386,7 @@ export class PresBox extends ViewBoxBaseComponent() { if (targetDoc.type === DocumentType.PDF || targetDoc.type === DocumentType.WEB || targetDoc.type === DocumentType.RTF) { const scroll = targetDoc._scrollTop; activeItem.presPinViewScroll = scroll; - } else if ([DocumentType.AUDIO, DocumentType.VID].includes(targetDoc.type as any)) { + } else if (targetDoc.type === DocumentType.VID) { activeItem.presStartTime = targetDoc._currentTimecode; activeItem.presStartTime = NumCast(targetDoc._currentTimecode) + 0.1; } else if (targetDoc.type === DocumentType.COMPARISON) { @@ -1805,16 +1779,16 @@ export class PresBox extends ViewBoxBaseComponent() { doc = Docs.Create.FreeformDocument([], { title: input ? input : "Blank slide", _width: 400, _height: 225, x: x, y: y }); break; case 'title': - doc = Docs.Create.FreeformDocument([title, subtitle], { title: input ? input : "Title slide", _width: 400, _height: 225, _fitContentsToBox: true, x: x, y: y }); + doc = Docs.Create.FreeformDocument([title, subtitle], { title: input ? input : "Title slide", _width: 400, _height: 225, _fitToBox: true, x: x, y: y }); break; case 'header': - doc = Docs.Create.FreeformDocument([header], { title: input ? input : "Section header", _width: 400, _height: 225, _fitContentsToBox: true, x: x, y: y }); + doc = Docs.Create.FreeformDocument([header], { title: input ? input : "Section header", _width: 400, _height: 225, _fitToBox: true, x: x, y: y }); break; case 'content': - doc = Docs.Create.FreeformDocument([contentTitle, content], { title: input ? input : "Title and content", _width: 400, _height: 225, _fitContentsToBox: true, x: x, y: y }); + doc = Docs.Create.FreeformDocument([contentTitle, content], { title: input ? input : "Title and content", _width: 400, _height: 225, _fitToBox: true, x: x, y: y }); break; case 'twoColumns': - doc = Docs.Create.FreeformDocument([contentTitle, content1, content2], { title: input ? input : "Title and two columns", _width: 400, _height: 225, _fitContentsToBox: true, x: x, y: y }); + doc = Docs.Create.FreeformDocument([contentTitle, content1, content2], { title: input ? input : "Title and two columns", _width: 400, _height: 225, _fitToBox: true, x: x, y: y }); break; default: break; @@ -2480,27 +2454,27 @@ export class PresBox extends ViewBoxBaseComponent() { for (let i = 0; i < index.length; i++) { indexNum += (index[i] * (10 ** (-i))); } - if (this._treeViewMap.get(treeViewDoc) !== indexNum) { - this._treeViewMap.set(treeViewDoc, indexNum); - const sorted = this.sort(this._treeViewMap); - const curList = DocListCast(this.dataDoc[this.presFieldKey]); - if (sorted.length !== curList.length || sorted.some((doc,ind) => doc !== curList[ind])) { - this.dataDoc[this.presFieldKey] = new List(sorted); // this is a flat array of Docs - } - } + this._treeViewMap.set(indexNum, treeViewDoc); + this.props.Document.presentationLinearizedDocuments = new List(this.sort(this._treeViewMap)); // this is a flat array of Docs return this.childDocs; } RemFromMap = (treeViewDoc: Doc, index: number[]): Doc[] => { - if (!this._unmounting && this.isTree) { - this._treeViewMap.delete(treeViewDoc); - this.dataDoc[this.presFieldKey] = new List(this.sort(this._treeViewMap)); + var indexNum = 0; + for (let i = 0; i < index.length; i++) { + indexNum += (index[i] * (10 ** (-i))); + } + console.log(String(index), treeViewDoc) + this._treeViewMap.delete(indexNum); + const overlay = (Doc.UserDoc().myOverlayDocs as Doc); + if (!DocListCast(overlay[Doc.LayoutFieldKey(overlay)]).includes(this.rootDoc)) { + this.props.Document.presentationLinearizedDocuments = new List(this.sort(this._treeViewMap)); } return this.childDocs; } // TODO: [AL] implement sort function for an array of numbers (e.g. arr[1,2,4] v arr[1,2,1]) - sort = (treeViewMap: Map) => [...treeViewMap.entries()].sort((a: [Doc, number], b: [Doc, number]) => a[1] > b[1] ? 1 : a[1] < b[1] ? -1 : 0).map(kv => kv[0]); + sort = (treeViewMap: Map) => [...treeViewMap.entries()].sort().map(kv => kv[1]); render() { // calling this method for keyEvents @@ -2512,7 +2486,7 @@ export class PresBox extends ViewBoxBaseComponent() { const presEnd: boolean = !this.layoutDoc.presLoop && (this.itemIndex === this.childDocs.length - 1); const presStart: boolean = !this.layoutDoc.presLoop && (this.itemIndex === 0); return CurrentUserUtils.OverlayDocs.includes(this.rootDoc) ? -
e.stopPropagation()}> +
{"Loop"}
}>
setupMoveUpEvents(this, e, returnFalse, returnFalse, () => this.layoutDoc.presLoop = !this.layoutDoc.presLoop, false, false)}>
@@ -2556,8 +2530,8 @@ export class PresBox extends ViewBoxBaseComponent() { removeDocument={returnFalse} dontRegisterView={true} focus={this.selectElement} - scriptContext={this} ScreenToLocalTransform={this.getTransform} + // TODO: [AL] implement AddToMap, RemFromMap functions (outside this) AddToMap={this.AddToMap} RemFromMap={this.RemFromMap} hierarchyIndex={[]} @@ -2576,10 +2550,12 @@ export class PresBox extends ViewBoxBaseComponent() {
; } } - -ScriptingGlobals.add(function navigateToDoc(bestTarget:Doc, activeItem:Doc) { - const srcContext = Cast(bestTarget.context, Doc, null) ?? Cast(Cast(bestTarget.annotationOn, Doc, null)?.context, Doc, null); - const openInTab = (doc: Doc, finished?: () => void) => {CollectionDockingView.AddSplit(doc, "right"); finished?.(); }; - DocumentManager.Instance.jumpToDocument(bestTarget, true, openInTab, srcContext ? [srcContext]:[], - undefined, undefined, undefined, () => PresBox.navigateToDoc(bestTarget, activeItem, true), undefined, true, NumCast(activeItem.presZoom)); +// this func communicates with PresBoxElement to send information of the doc +ScriptingGlobals.add(function lookupPresBoxField(presBoxDoc: Doc, field: string, presEleDoc: Doc) { + if (field === 'indexInPres') return DocListCast(presBoxDoc._viewType === CollectionViewType.Tree ? presBoxDoc.presentationLinearizedDocuments : presBoxDoc[StrCast(presBoxDoc.presentationFieldKey)]).indexOf(presEleDoc); + if (field === 'presCollapsedHeight') return [CollectionViewType.Tree || CollectionViewType.Stacking].includes(presBoxDoc._viewType as any) ? 35 : 31; + if (field === 'presStatus') return presBoxDoc.presStatus; + if (field === '_itemIndex') return presBoxDoc._itemIndex; + if (field === 'presBox') return presBoxDoc; + return undefined; }); \ No newline at end of file diff --git a/src/client/views/nodes/trails/PresElementBox.scss b/src/client/views/nodes/trails/PresElementBox.scss index 969f034a8..789a6d9f3 100644 --- a/src/client/views/nodes/trails/PresElementBox.scss +++ b/src/client/views/nodes/trails/PresElementBox.scss @@ -5,157 +5,155 @@ $slide-background: #d5dce2; $slide-active: #5B9FDD; .presItem-container { - cursor: grab; - display: flex; - grid-template-columns: 20px auto; - font-family: Roboto; - letter-spacing: normal; - position: relative; - pointer-events: all; - width: 100%; - height: 100%; - font-weight: 400; - -webkit-touch-callout: none; - -webkit-user-select: none; - -khtml-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - align-items: center; + cursor: grab; + display: grid; + grid-template-columns: 20px auto; + font-family: Roboto; + letter-spacing: normal; + position: relative; + pointer-events: all; + width: 100%; + height: 100%; + font-weight: 400; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + align-items: center; - // .presItem-number { - // margin-top: 3.5px; - // font-size: 12px; - // font-weight: 700; - // text-align: center; - // justify-self: center; - // align-self: flex-start; - // position: relative; - // display: inline-block; - // overflow: hidden; - // } + .presItem-number { + margin-top: 3.5px; + font-size: 12px; + font-weight: 700; + text-align: center; + justify-self: center; + align-self: flex-start; + position: relative; + display: inline-block; + overflow: hidden; + } } .presItem-slide { - position: relative; - height: 100%; - width: 100%; - border-bottom: .5px solid grey; - display: flex; - justify-content: space-between; - align-items: center; - grid-template-rows: 16px 10px auto; - grid-template-columns: max-content max-content max-content max-content auto; + position: relative; + background-color: #d5dce2; + border-radius: 5px; + height: calc(100% - 7px); + width: 100%; + display: grid; + grid-template-rows: 16px 10px auto; + grid-template-columns: max-content max-content max-content max-content auto; - .presItem-name { - display: flex; - min-width: 20px; - z-index: 300; - top: 2px; - align-self: center; - font-size: 11px; - font-family: Roboto; - font-weight: 500; - position: relative; - padding-left: 10px; - padding-right: 10px; - letter-spacing: normal; - width: max-content; - text-overflow: ellipsis; - overflow: hidden; - white-space: pre; - } + .presItem-name { + min-width: 20px; + z-index: 300; + top: 2px; + align-self: center; + font-size: 11px; + font-family: Roboto; + font-weight: 500; + position: relative; + padding-left: 10px; + padding-right: 10px; + letter-spacing: normal; + width: max-content; + text-overflow: ellipsis; + overflow: hidden; + white-space: pre; + } - .presItem-docName { - min-width: 20px; - z-index: 300; - align-self: center; - font-size: 9px; - font-family: Roboto; - font-weight: 300; - position: relative; - padding-left: 10px; - padding-right: 10px; - letter-spacing: normal; - width: max-content; - text-overflow: ellipsis; - overflow: hidden; - white-space: pre; - grid-row: 2; - grid-column: 1/6; - } + .presItem-docName { + min-width: 20px; + z-index: 300; + align-self: center; + font-size: 9px; + font-family: Roboto; + font-weight: 300; + position: relative; + padding-left: 10px; + padding-right: 10px; + letter-spacing: normal; + width: max-content; + text-overflow: ellipsis; + overflow: hidden; + white-space: pre; + grid-row: 2; + grid-column: 1/6; + } - .presItem-time { - align-self: center; - position: relative; - padding-right: 10px; - top: 1px; - font-size: 10; - font-weight: 300; - font-family: Roboto; - z-index: 300; - letter-spacing: normal; - } + .presItem-time { + align-self: center; + position: relative; + padding-right: 10px; + top: 1px; + font-size: 10; + font-weight: 300; + font-family: Roboto; + z-index: 300; + letter-spacing: normal; + } - .presItem-embedded { - overflow: hidden; - grid-row: 3; - grid-column: 1/8; - position: relative; - display: flex; - width: auto; - justify-content: center; - margin: auto; - margin-bottom: 2px; - border-bottom-left-radius: 5px; - border-bottom-right-radius: 5px; - } + .presItem-embedded { + overflow: hidden; + grid-row: 3; + grid-column: 1/8; + position: relative; + display: flex; + width: auto; + justify-content: center; + margin: auto; + margin-bottom: 2px; + border-bottom-left-radius: 5px; + border-bottom-right-radius: 5px; + } - .presItem-embeddedMask { - width: 100%; - height: 100%; - position: absolute; - border-radius: 3px; - top: 0; - left: 0; - z-index: 1; - overflow: hidden; - } + .presItem-embeddedMask { + width: 100%; + height: 100%; + position: absolute; + border-radius: 3px; + top: 0; + left: 0; + z-index: 1; + overflow: hidden; + } - .presItem-slideButtons { - display: flex; - grid-column: 7; - grid-row: 1/3; - width: max-content; - justify-self: right; - justify-content: flex-end; + .presItem-slideButtons { + display: flex; + grid-column: 7; + grid-row: 1/3; + width: max-content; + justify-self: right; + justify-content: flex-end; - .slideButton { - cursor: pointer; - position: relative; - border-radius: 100px; - z-index: 300; - width: 18px; - height: 18px; - display: flex; - font-size: 12px; - justify-self: center; - align-self: center; - background-color: rgba(0, 0, 0, 0.5); - color: white; - justify-content: center; - align-items: center; - transition: 0.2s; - margin-right: 3px; - } + .slideButton { + cursor: pointer; + position: relative; + border-radius: 100px; + z-index: 300; + width: 18px; + height: 18px; + display: flex; + font-size: 12px; + justify-self: center; + align-self: center; + background-color: rgba(0, 0, 0, 0.5); + color: white; + justify-content: center; + align-items: center; + transition: 0.2s; + margin-right: 3px; + } - .slideButton:hover { - background-color: rgba(0, 0, 0, 1); - transform: scale(1.2); - } - } + .slideButton:hover { + background-color: rgba(0, 0, 0, 1); + transform: scale(1.2); + } + } } // .presItem-slide:hover { @@ -194,7 +192,7 @@ $slide-active: #5B9FDD; // } .presItem-slide.active { - box-shadow: 0 0 0px 2.5px $dark-blue; + box-shadow: 0 0 0px 1.5px $dark-blue; } .presItem-slide.group { @@ -203,7 +201,7 @@ $slide-active: #5B9FDD; .presItem-slide.activeGroup { border-radius: 5px; - box-shadow: 0 0 0px 2.5px $dark-blue; + box-shadow: 0 0 0px 1.5px $dark-blue; } .presItem-groupSlideContainer { @@ -239,38 +237,38 @@ $slide-active: #5B9FDD; } .presItem-multiDrag { - font-family: Roboto; - font-weight: 600; - color: white; - text-align: center; - justify-content: center; - align-content: center; - width: 100px; - height: 30px; - position: absolute; - background-color: $dark-blue; - z-index: 4000; - border-radius: 10px; - box-shadow: black 0.4vw 0.4vw 0.8vw; - line-height: 30px; + font-family: Roboto; + font-weight: 600; + color: white; + text-align: center; + justify-content: center; + align-content: center; + width: 100px; + height: 30px; + position: absolute; + background-color: $dark-blue; + z-index: 4000; + border-radius: 10px; + box-shadow: black 0.4vw 0.4vw 0.8vw; + line-height: 30px; } .presItem-miniSlide { - font-weight: 700; - font-size: 12; - grid-column: 1/8; - align-self: center; - justify-self: center; - background-color: #d5dce2; - width: 26px; - text-align: center; - height: 26px; - line-height: 28px; - border-radius: 100%; + font-weight: 700; + font-size: 12; + grid-column: 1/8; + align-self: center; + justify-self: center; + background-color: #d5dce2; + width: 26px; + text-align: center; + height: 26px; + line-height: 28px; + border-radius: 100%; } .presItem-miniSlide.active { - box-shadow: 0 0 0px 1.5px $dark-blue; + box-shadow: 0 0 0px 1.5px $dark-blue; } .expandButton { diff --git a/src/client/views/nodes/trails/PresElementBox.tsx b/src/client/views/nodes/trails/PresElementBox.tsx index 50df00612..bbabcb2de 100644 --- a/src/client/views/nodes/trails/PresElementBox.tsx +++ b/src/client/views/nodes/trails/PresElementBox.tsx @@ -2,18 +2,17 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { Tooltip } from "@material-ui/core"; import { action, computed, IReactionDisposer, observable, reaction } from "mobx"; import { observer } from "mobx-react"; -import { Doc, DocListCast, HeightSym, Opt, WidthSym } from "../../../../fields/Doc"; +import { DataSym, Doc, DocListCast, Opt } from "../../../../fields/Doc"; import { Id } from "../../../../fields/FieldSymbols"; import { BoolCast, Cast, NumCast, StrCast } from "../../../../fields/Types"; import { emptyFunction, returnEmptyDoclist, returnFalse, returnTrue, setupMoveUpEvents } from "../../../../Utils"; -import { Docs, DocUtils } from "../../../documents/Documents"; +import { DocUtils } from "../../../documents/Documents"; import { DocumentType } from "../../../documents/DocumentTypes"; import { CurrentUserUtils } from "../../../util/CurrentUserUtils"; import { DocumentManager } from "../../../util/DocumentManager"; import { DragManager } from "../../../util/DragManager"; import { Transform } from "../../../util/Transform"; import { undoBatch } from "../../../util/UndoManager"; -import { CollectionViewType } from "../../collections/CollectionView"; import { ViewBoxBaseComponent } from '../../DocComponent'; import { EditableView } from "../../EditableView"; import { Colors } from "../../global/globalEnums"; @@ -24,7 +23,7 @@ import { PresBox } from "./PresBox"; import "./PresElementBox.scss"; import { PresMovement } from "./PresEnums"; import React = require("react"); -import { List } from "../../../../fields/List"; +import { CollectionViewType } from "../../collections/CollectionView"; /** * This class models the view a document added to presentation will have in the presentation. * It involves some functionality for its buttons and options. @@ -35,10 +34,12 @@ export class PresElementBox extends ViewBoxBaseComponent() { _heightDisposer: IReactionDisposer | undefined; @observable _dragging = false; - @computed get indexInPres() { return DocListCast(this.presBox[StrCast(this.presBox.presFieldKey, "data")]).indexOf(this.rootDoc); } // the index field is where this document is in the presBox display list (since this value is different for each presentation element, the value can't be stored on the layout template which is used by all display elements) - @computed get collapsedHeight() { return [CollectionViewType.Tree, CollectionViewType.Stacking].includes(this.presBox._viewType as any) ? 35 : 31; } // the collapsed height changes depending on the state of the presBox. We could store this on the presentation element template if it's used by only one presentation - but if it's shared by multiple, then this value must be looked up - @computed get presStatus() { return this.presBox.presStatus; } - @computed get presBox() { return (this.props.DocumentView?.().props.treeViewDoc ?? this.props.ContainingCollectionDoc)!; } + // these fields are conditionally computed fields on the layout document that take this document as a parameter + @computed get indexInPres() { return Number(this.lookupField("indexInPres")); } // the index field is where this document is in the presBox display list (since this value is different for each presentation element, the value can't be stored on the layout template which is used by all display elements) + @computed get collapsedHeight() { return Number(this.lookupField("presCollapsedHeight")); } // the collapsed height changes depending on the state of the presBox. We could store this on the presentation element template if it's used by only one presentation - but if it's shared by multiple, then this value must be looked up + @computed get presStatus() { return StrCast(this.lookupField("presStatus")); } + @computed get itemIndex() { return NumCast(this.lookupField("_itemIndex")); } + @computed get presBox() { return Cast(this.lookupField("presBox"), Doc, null); } @computed get targetDoc() { return Cast(this.rootDoc.presentationTargetDoc, Doc, null) || this.rootDoc; } componentDidMount() { @@ -76,8 +77,8 @@ export class PresElementBox extends ViewBoxBaseComponent() { return !this.rootDoc.presExpandInlineButton || !this.targetDoc ? (null) :
() { isContentActive={this.props.isContentActive} addDocTab={returnFalse} pinToPres={returnFalse} - fitContentsToBox={returnTrue} + fitContentsToDoc={returnTrue} PanelWidth={this.embedWidth} PanelHeight={this.embedHeight} ScreenToLocalTransform={Transform.Identity} @@ -166,11 +167,11 @@ export class PresElementBox extends ViewBoxBaseComponent() { e.preventDefault(); if (element && !(e.ctrlKey || e.metaKey)) { if (PresBox.Instance._selectedArray.has(this.rootDoc)) { - PresBox.Instance._selectedArray.size === 1 && PresBox.Instance.regularSelect(this.rootDoc, this._itemRef.current!, this._dragRef.current!, false, false); + PresBox.Instance._selectedArray.size === 1 && PresBox.Instance.regularSelect(this.rootDoc, this._itemRef.current!, this._dragRef.current!, false); setupMoveUpEvents(this, e, this.startDrag, emptyFunction, emptyFunction); } else { setupMoveUpEvents(this, e, ((e: PointerEvent) => { - PresBox.Instance.regularSelect(this.rootDoc, this._itemRef.current!, this._dragRef.current!, false, false); + PresBox.Instance.regularSelect(this.rootDoc, this._itemRef.current!, this._dragRef.current!, false); return this.startDrag(e); }), emptyFunction, emptyFunction); } @@ -196,7 +197,7 @@ export class PresElementBox extends ViewBoxBaseComponent() { dragData.moveDocument = this.props.docViewPath().lastElement()?.props.moveDocument; const dragItem: HTMLElement[] = []; if (dragArray.length === 1) { - const doc = this._itemRef.current || dragArray[0]; + const doc = dragArray[0]; doc.className = miniView ? "presItem-miniSlide" : "presItem-slide"; dragItem.push(doc); } else if (dragArray.length >= 1) { @@ -260,12 +261,11 @@ export class PresElementBox extends ViewBoxBaseComponent() { @undoBatch removeItem = action((e: React.MouseEvent) => { - e.stopPropagation(); this.props.removeDocument?.(this.rootDoc); if (PresBox.Instance._selectedArray.has(this.rootDoc)) { PresBox.Instance._selectedArray.delete(this.rootDoc); } - this.removeAllRecordingInOverlay() + e.stopPropagation(); }); // set the value/title of the individual pres element @@ -285,230 +285,196 @@ export class PresElementBox extends ViewBoxBaseComponent() { @undoBatch @action updateView = (targetDoc: Doc, activeItem: Doc) => { - switch (targetDoc.type) { - case DocumentType.PDF: case DocumentType.WEB: case DocumentType.RTF : - const scroll = targetDoc._scrollTop; - activeItem.presPinViewScroll = scroll; - break; - case DocumentType.VID: case DocumentType.AUDIO: - activeItem.presStartTime = targetDoc._currentTimecode; - break; - case DocumentType.COMPARISON : - const clipWidth = targetDoc._clipWidth; - activeItem.presPinClipWidth = clipWidth; - break; - default: - const x = targetDoc._panX; - const y = targetDoc._panY; - const scale = targetDoc._viewScale; - activeItem.presPinViewX = x; - activeItem.presPinViewY = y; - activeItem.presPinViewScale = scale; + if (targetDoc.type === DocumentType.PDF || targetDoc.type === DocumentType.WEB || targetDoc.type === DocumentType.RTF) { + const scroll = targetDoc._scrollTop; + activeItem.presPinViewScroll = scroll; + } else if (targetDoc.type === DocumentType.VID) { + activeItem.presPinTimecode = targetDoc._currentTimecode; + } else if (targetDoc.type === DocumentType.COMPARISON) { + const clipWidth = targetDoc._clipWidth; + activeItem.presPinClipWidth = clipWidth; + } else { + const x = targetDoc._panX; + const y = targetDoc._panY; + const scale = targetDoc._viewScale; + activeItem.presPinViewX = x; + activeItem.presPinViewY = y; + activeItem.presPinViewScale = scale; } } - @computed get recordingIsInOverlay() { - let isInOverlay = false - DocListCast((Doc.UserDoc().myOverlayDocs as Doc).data).forEach((doc) => { - if (doc.slides === this.rootDoc) { - isInOverlay = true - return - } - }) - return isInOverlay - } - - removeAllRecordingInOverlay = () => { - DocListCast((Doc.UserDoc().myOverlayDocs as Doc).data).forEach((doc) => { - if (doc.slides === this.rootDoc) { - Doc.RemoveDocFromList((Doc.UserDoc().myOverlayDocs as Doc), undefined, doc); - } - }) - } - - @undoBatch - @action - hideRecording = (e: React.MouseEvent) => { - e.stopPropagation() - this.removeAllRecordingInOverlay() - } - - @undoBatch - @action - showRecording = (activeItem: Doc) => { - this.removeAllRecordingInOverlay() - if (activeItem.recording) { - // if we already have an existing recording - Doc.AddDocToList((Doc.UserDoc().myOverlayDocs as Doc), undefined, Cast(activeItem.recording, Doc, null)); - - } - } - - @undoBatch - @action - startRecording = (activeItem: Doc) => { - // Remove every recording that already exists in overlay view - DocListCast((Doc.UserDoc().myOverlayDocs as Doc).data).forEach((doc) => { - if (doc.slides !== null) { - Doc.RemoveDocFromList((Doc.UserDoc().myOverlayDocs as Doc), undefined, doc); - } - }) - - if (activeItem.recording) { - // if we already have an existing recording - Doc.AddDocToList((Doc.UserDoc().myOverlayDocs as Doc), undefined, Cast(activeItem.recording, Doc, null)); - - } else { - // if we dont have any recording - const recording = Docs.Create.WebCamDocument("", { - _width: 400, _height: 200, - // hideDocumentButtonBar: true, - hideDecorationTitle: true, - hideOpenButton: true, - // hideDeleteButton: true, - cloneFieldFilter: new List(["system"]) - }); - - // attach the recording to the slide, and attach the slide to the recording - recording.slides = activeItem - activeItem.recording = recording - - // make recording box appear in the bottom right corner of the screen - recording.x = window.innerWidth - recording[WidthSym]() - 20; - recording.y = window.innerHeight - recording[HeightSym]() - 20; - Doc.AddDocToList((Doc.UserDoc().myOverlayDocs as Doc), undefined, recording); - } - } - - @computed - get toolbarWidth(): number { - const presBoxDocView = DocumentManager.Instance.getDocumentView(this.presBox); - let width: number = NumCast(this.presBox._width); - if (presBoxDocView) width = presBoxDocView.props.PanelWidth(); - if (width === 0) width = 300; - return width; - } + @computed + get toolbarWidth(): number { + const presBoxDocView = DocumentManager.Instance.getDocumentView(this.presBox); + let width: number = NumCast(this.presBox._width); + if (presBoxDocView) width = presBoxDocView.props.PanelWidth(); + if (width === 0) width = 300; + return width; + } - @computed get mainItem() { - const isSelected: boolean = PresBox.Instance?._selectedArray.has(this.rootDoc); - const toolbarWidth: number = this.toolbarWidth; - const showMore: boolean = this.toolbarWidth >= 300; - const miniView: boolean = this.toolbarWidth <= 110; - const presBox: Doc = this.presBox; //presBox - const presBoxColor: string = StrCast(presBox._backgroundColor); - const presColorBool: boolean = presBoxColor ? (presBoxColor !== Colors.WHITE && presBoxColor !== "transparent") : false; - const targetDoc: Doc = this.targetDoc; - const activeItem: Doc = this.rootDoc; - return ( -
= 300; + const miniView: boolean = this.toolbarWidth <= 110; + const presBox: Doc = this.presBox; //presBox + const presBoxColor: string = StrCast(presBox._backgroundColor); + const presColorBool: boolean = presBoxColor ? (presBoxColor !== Colors.WHITE && presBoxColor !== "transparent") : false; + const targetDoc: Doc = this.targetDoc; + const activeItem: Doc = this.rootDoc; + const isGroup: boolean = BoolCast(targetDoc._isGroup); + return ( +
{ + e.stopPropagation(); + e.preventDefault(); + PresBox.Instance.modifierSelect(this.rootDoc, this._itemRef.current!, this._dragRef.current!, !e.shiftKey && !e.ctrlKey && !e.metaKey, e.ctrlKey || e.metaKey, e.shiftKey); + }} + onDoubleClick={action(e => { + if (isGroup) { + this.rootDoc.presExpandGroup = !this.rootDoc.presExpandGroup; + } else { + this.toggleProperties(); + PresBox.Instance.regularSelect(this.rootDoc, this._itemRef.current!, this._dragRef.current!, true); + } + })} + onPointerOver={this.onPointerOver} + onPointerLeave={this.onPointerLeave} + onPointerDown={this.headerDown} + onPointerUp={this.headerUp} + > + {miniView ? + // when width is LESS than 110 px +
+ {`${this.indexInPres + 1}.`} +
+ : + // when width is MORE than 110 px +
+ {`${this.indexInPres + 1}.`} +
} + {isGroup ? +
{ - e.stopPropagation(); - e.preventDefault(); - PresBox.Instance.modifierSelect(this.rootDoc, this._itemRef.current!, this._dragRef.current!, !e.shiftKey && !e.ctrlKey && !e.metaKey, e.ctrlKey || e.metaKey, e.shiftKey); - this.showRecording(activeItem); - }} - onDoubleClick={action(e => { - this.toggleProperties(); - PresBox.Instance.regularSelect(this.rootDoc, this._itemRef.current!, this._dragRef.current!, true); - })} - onPointerOver={this.onPointerOver} - onPointerLeave={this.onPointerLeave} - onPointerDown={this.headerDown} - onPointerUp={this.headerUp} - > - {/* {miniView ? - // when width is LESS than 110 px -
- {`${this.indexInPres + 1}.`} -
- : - // when width is MORE than 110 px -
- {`${this.indexInPres + 1}.`} -
} */} - {/*
- {`${this.indexInPres + 1}.`} -
*/} - {miniView ? (null) :
-
-
{`${this.indexInPres + 1}. `}
- StrCast(activeItem.title)} - SetValue={this.onSetValue} - /> -
- {/*
{"Movement speed"}
}>
{this.transition}
*/} - {/*
{"Duration"}
}>
{this.duration}
*/} -
-
{"Update view"}
}> -
this.updateView(targetDoc, activeItem)} - style={{ fontWeight: 700, display: activeItem.presPinView ? "flex" : "none" }}>V
-
- - {this.recordingIsInOverlay ? -
{"Hide Recording"}
}> -
- e.stopPropagation()} /> -
-
: -
{"Start recording"}
}> -
this.startRecording(activeItem)} - style={{ fontWeight: 700 }}> - e.stopPropagation()} /> -
-
- } - - - {/* {this.indexInPres === 0 ? (null) :
{activeItem.groupWithUp ? "Ungroup" : "Group with up"}
}> -
activeItem.groupWithUp = !activeItem.groupWithUp} - style={{ - zIndex: 1000 - this.indexInPres, - fontWeight: 700, - backgroundColor: activeItem.groupWithUp ? presColorBool ? presBoxColor : Colors.MEDIUM_BLUE : undefined, - height: activeItem.groupWithUp ? 53 : 18, - transform: activeItem.groupWithUp ? "translate(0, -17px)" : undefined - }}> -
- e.stopPropagation()} /> -
-
-
} */} -
{this.rootDoc.presExpandInlineButton ? "Minimize" : "Expand"}
}>
{ e.stopPropagation(); this.presExpandDocumentClick(); }}> - e.stopPropagation()} /> -
-
{"Remove from presentation"}
}>
- e.stopPropagation()} /> -
-
- {/*
{activeItem.presPinView ? (<>View of {targetDoc.title}) : targetDoc.title}
*/} - {this.renderEmbeddedInline} -
} -
); - } + backgroundColor: this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.BackgroundColor), + boxShadow: presBoxColor && presBoxColor !== "white" && presBoxColor !== "transparent" ? isSelected ? "0 0 0px 1.5px" + presBoxColor : undefined : undefined + }}> +
+ StrCast(activeItem.title)} + SetValue={this.onSetValue} + /> +
+
+
{"Update view"}
}> +
this.updateView(targetDoc, activeItem)} + style={{ fontWeight: 700, display: activeItem.presPinView ? "flex" : "none" }}>V
+
+ {this.indexInPres === 0 ? (null) :
{activeItem.groupWithUp ? "Ungroup" : "Group with up"}
}> +
activeItem.groupWithUp = !activeItem.groupWithUp} + style={{ + zIndex: 1000 - this.indexInPres, + fontWeight: 700, + backgroundColor: activeItem.groupWithUp ? presColorBool ? presBoxColor : Colors.MEDIUM_BLUE : undefined, + height: activeItem.groupWithUp ? 53 : 18, + transform: activeItem.groupWithUp ? "translate(0, -17px)" : undefined + }}> +
+ e.stopPropagation()} /> +
+
+
} +
{this.rootDoc.presExpandInlineButton ? "Minimize" : "Expand"}
}>
{ e.stopPropagation(); this.presExpandDocumentClick(); }}> + e.stopPropagation()} /> +
+
{"Remove from presentation"}
}>
+ e.stopPropagation()} /> +
+
+
+
+ {this.rootDoc.presExpandGroup ? this.renderGroupSlides : (null)} +
+
{activeItem.presPinView ? (<>View of {targetDoc.title}) : targetDoc.title}
+
{ + if (isGroup) { + this.rootDoc.presExpandGroup = !this.rootDoc.presExpandGroup; + } + }} + > + +
+
+ : (null)} + {miniView || isGroup ? (null) :
+
+ StrCast(activeItem.title)} + SetValue={this.onSetValue} + /> +
+
{"Movement speed"}
}>
{this.transition}
+
{"Duration"}
}>
{this.duration}
+
+
{"Update view"}
}> +
this.updateView(targetDoc, activeItem)} + style={{ fontWeight: 700, display: activeItem.presPinView ? "flex" : "none" }}>V
+
+ {this.indexInPres === 0 ? (null) :
{activeItem.groupWithUp ? "Ungroup" : "Group with up"}
}> +
activeItem.groupWithUp = !activeItem.groupWithUp} + style={{ + zIndex: 1000 - this.indexInPres, + fontWeight: 700, + backgroundColor: activeItem.groupWithUp ? presColorBool ? presBoxColor : Colors.MEDIUM_BLUE : undefined, + height: activeItem.groupWithUp ? 53 : 18, + transform: activeItem.groupWithUp ? "translate(0, -17px)" : undefined + }}> +
+ e.stopPropagation()} /> +
+
+
} +
{this.rootDoc.presExpandInlineButton ? "Minimize" : "Expand"}
}>
{ e.stopPropagation(); this.presExpandDocumentClick(); }}> + e.stopPropagation()} /> +
+
{"Remove from presentation"}
}>
+ e.stopPropagation()} /> +
+
+
{activeItem.presPinView ? (<>View of {targetDoc.title}) : targetDoc.title}
+ {this.renderEmbeddedInline} +
} +
); + } - render() { - return !(this.rootDoc instanceof Doc) || this.targetDoc instanceof Promise ? (null) : this.mainItem; - } + render() { + return !(this.rootDoc instanceof Doc) || this.targetDoc instanceof Promise ? (null) : this.mainItem; + } } \ No newline at end of file -- cgit v1.2.3-70-g09d2