aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/trails/PresBox.tsx
diff options
context:
space:
mode:
authorGeireann Lindfield Roberts <60007097+geireann@users.noreply.github.com>2022-06-30 12:28:25 -0700
committerGeireann Lindfield Roberts <60007097+geireann@users.noreply.github.com>2022-06-30 12:28:25 -0700
commit891b03238ee7bf6bd9e83cc20c1720c42059ce04 (patch)
treeb912f6f1e8177106ce015896882cdc8bb11acafd /src/client/views/nodes/trails/PresBox.tsx
parentbb02d3a052efdbf25d1069059a92b7a9d9cc1708 (diff)
parentea6e63648b21c46672b1b7cb1da0cbaa6857d0c1 (diff)
Merge branch 'master' into parker
Diffstat (limited to 'src/client/views/nodes/trails/PresBox.tsx')
-rw-r--r--src/client/views/nodes/trails/PresBox.tsx414
1 files changed, 257 insertions, 157 deletions
diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx
index 8a0d03ae8..b169ad6cd 100644
--- a/src/client/views/nodes/trails/PresBox.tsx
+++ b/src/client/views/nodes/trails/PresBox.tsx
@@ -10,17 +10,16 @@ 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 } from '../../../../Utils';
+import { BoolCast, Cast, DocCast, 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";
@@ -30,12 +29,21 @@ import { CollectionFreeFormDocumentView } from "../CollectionFreeFormDocumentVie
import { FieldView, FieldViewProps } from '../FieldView';
import "./PresBox.scss";
import { PresEffect, PresMovement, PresStatus } from "./PresEnums";
+import { ScriptingGlobals } from "../../../util/ScriptingGlobals";
-export class PinProps {
+export interface 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
@@ -47,17 +55,17 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
* @param renderDoc
* @param layoutDoc
*/
- static renderEffectsDoc(renderDoc: any, layoutDoc: Doc) {
+ static renderEffectsDoc(renderDoc: any, layoutDoc: Doc, presDoc: Doc) {
const effectProps = {
- left: layoutDoc.presEffectDirection === PresEffect.Left,
- right: layoutDoc.presEffectDirection === PresEffect.Right,
- top: layoutDoc.presEffectDirection === PresEffect.Top,
- bottom: layoutDoc.presEffectDirection === PresEffect.Bottom,
+ left: presDoc.presEffectDirection === PresEffect.Left,
+ right: presDoc.presEffectDirection === PresEffect.Right,
+ top: presDoc.presEffectDirection === PresEffect.Top,
+ bottom: presDoc.presEffectDirection === PresEffect.Bottom,
opposite: true,
- delay: layoutDoc.presTransition,
+ delay: presDoc.presTransition,
// when: this.layoutDoc === PresBox.Instance.childDocs[PresBox.Instance.itemIndex]?.presentationTargetDoc,
};
- switch (layoutDoc.presEffect) {
+ switch (presDoc.presEffect) {
case PresEffect.Zoom: return (<Zoom {...effectProps}>{renderDoc}</Zoom>);
case PresEffect.Fade: return (<Fade {...effectProps}>{renderDoc}</Fade>);
case PresEffect.Flip: return (<Flip {...effectProps}>{renderDoc}</Flip>);
@@ -71,7 +79,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
}
public static EffectsProvider(layoutDoc: Doc, renderDoc: any) {
return PresBox.Instance && layoutDoc === PresBox.Instance.childDocs[PresBox.Instance.itemIndex]?.presentationTargetDoc ?
- PresBox.renderEffectsDoc(renderDoc, layoutDoc)
+ PresBox.renderEffectsDoc(renderDoc, layoutDoc, PresBox.Instance.childDocs[PresBox.Instance.itemIndex])
:
renderDoc;
}
@@ -90,13 +98,20 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
@observable _expandBoolean: boolean = false;
private _disposers: { [name: string]: IReactionDisposer } = {};
+
+ @observable static startMarquee: boolean = false; // onclick "+ new slide" in presentation mode, set as true, then when marquee selection finish, onPointerUp automatically triggers PinWithView
@observable private transitionTools: boolean = false;
@observable private newDocumentTools: boolean = false;
@observable private progressivizeTools: boolean = false;
@observable private openMovementDropdown: boolean = false;
@observable private openEffectDropdown: boolean = false;
@observable private presentTools: boolean = false;
- @computed get childDocs() { return DocListCast(this.dataDoc[this.fieldKey]); }
+ @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<Doc, number> = new Map();
+
@computed get tagDocs() {
const tagDocs: Doc[] = [];
for (const doc of this.childDocs) {
@@ -117,21 +132,9 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
if ((this.targetDoc.type === DocumentType.COL && this.targetDoc._viewType === CollectionViewType.Freeform) || this.targetDoc.type === DocumentType.IMG) return true;
else return false;
}
- @computed get presElement() { return Cast(Doc.UserDoc().presElement, Doc, null); }
constructor(props: any) {
super(props);
- if (Doc.UserDoc().activePresentation = this.rootDoc) runInAction(() => PresBox.Instance = this);
- if (!this.presElement) { // create exactly one presElmentBox template to use by any and all presentations.
- Doc.UserDoc().presElement = new PrefetchProxy(Docs.Create.PresElementBoxDocument({
- title: "pres element template", type: DocumentType.PRESELEMENT, _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 });
- }
+ if (CurrentUserUtils.ActivePresentation = this.rootDoc) runInAction(() => PresBox.Instance = this);
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() {
@@ -149,8 +152,10 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
}
@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();
@@ -161,22 +166,22 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
@action
componentDidMount() {
- this.rootDoc.presBox = this.rootDoc;
+ this._unmounting = false;
this.rootDoc._forceRenderEngine = "timeline";
this.layoutDoc.presStatus = PresStatus.Edit;
this.layoutDoc._gridGap = 0;
this.layoutDoc._yMargin = 0;
this.turnOffEdit(true);
- DocListCastAsync((Doc.UserDoc().myTrails as Doc).data).then(pres =>
- !pres?.includes(this.rootDoc) && Doc.AddDocToList(Doc.UserDoc().myTrails as Doc, "data", this.rootDoc));
+ DocListCastAsync(CurrentUserUtils.MyTrails.data).then(pres =>
+ !pres?.includes(this.rootDoc) && Doc.AddDocToList(CurrentUserUtils.MyTrails, "data", this.rootDoc));
this._disposers.selection = reaction(() => SelectionManager.Views(),
views => views.some(view => view.props.Document === this.rootDoc) && this.updateCurrentPresentation());
}
@action
updateCurrentPresentation = (pres?: Doc) => {
- if (pres) Doc.UserDoc().activePresentation = pres;
- else Doc.UserDoc().activePresentation = this.rootDoc;
+ if (pres) CurrentUserUtils.ActivePresentation = pres;
+ else CurrentUserUtils.ActivePresentation = this.rootDoc;
document.removeEventListener("keydown", PresBox.keyEventsWrapper, true);
document.addEventListener("keydown", PresBox.keyEventsWrapper, true);
this._presKeyEventsActive = true;
@@ -202,30 +207,18 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
const targMedia = DocumentManager.Instance.getDocumentView(targetDoc);
targMedia?.ComponentView?.playFrom?.(NumCast(activeItem.presStartTime), NumCast(activeItem.presStartTime) + duration);
}
- // if (targetDoc.type === DocumentType.AUDIO) {
- // if (this._mediaTimer && this._mediaTimer[1] === targetDoc) clearTimeout(this._mediaTimer[0]);
- // targetDoc._triggerAudio = NumCast(activeItem.presStartTime);
- // this._mediaTimer = [setTimeout(() => targetDoc._audioStop = true, duration * 1000), targetDoc];
- // } else if (targetDoc.type === DocumentType.VID) {
- // targetDoc._triggerVideoStop = true;
- // setTimeout(() => targetDoc._currentTimecode = NumCast(activeItem.presStartTime), 10);
- // setTimeout(() => targetDoc._triggerVideo = true, 20);
- // this._mediaTimer = [setTimeout(() => targetDoc._triggerVideoStop = true, (duration * 1000) + 20), targetDoc];
- // }
}
stopTempMedia = (targetDocField: FieldResult) => {
const targetDoc = Cast(targetDocField, Doc, null);
- if (targetDoc?.type === DocumentType.AUDIO) {
- if (this._mediaTimer && this._mediaTimer[1] === targetDoc) clearTimeout(this._mediaTimer[0]);
- targetDoc._audioStop = true;
- } else if (targetDoc?.type === DocumentType.VID) {
- if (this._mediaTimer && this._mediaTimer[1] === targetDoc) clearTimeout(this._mediaTimer[0]);
- targetDoc._triggerVideoStop = true;
+ if ([DocumentType.VID, DocumentType.AUDIO].includes(targetDoc.type as any)) {
+ const targMedia = DocumentManager.Instance.getDocumentView(targetDoc);
+ targMedia?.ComponentView?.Pause?.();
}
}
//TODO: al: it seems currently that tempMedia doesn't stop onslidechange after clicking the button; the time the tempmedia stop depends on the start & end time
+ // TODO: to handle child slides (entering into subtrail and exiting), also the next() and back() functions
// No more frames in current doc and next slide is defined, therefore move to next slide
nextSlide = (activeNext: Doc) => {
const targetNext = Cast(activeNext.presentationTargetDoc, Doc, null);
@@ -311,6 +304,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
this.startTempMedia(targetDoc, activeItem);
}
if (targetDoc) {
+ Doc.linkFollowHighlight((targetDoc.annotationOn instanceof Doc) ? [targetDoc, targetDoc.annotationOn] : targetDoc);
targetDoc && runInAction(() => {
if (activeItem.presMovement === PresMovement.Jump) targetDoc.focusSpeed = 0;
else targetDoc.focusSpeed = activeItem.presTransition ? activeItem.presTransition : 500;
@@ -322,7 +316,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
}
if (!group) this._selectedArray.clear();
this.childDocs[index] && this._selectedArray.set(this.childDocs[index], undefined); //Update selected array
- if (this.layoutDoc._viewType === "stacking" && !group) this.navigateToElement(this.childDocs[index]); //Handles movement to element only when presTrail is list
+ this.navigateToElement(this.childDocs[index]); //Handles movement to element only when presTrail is list
this.onHideDocument(); //Handles hide after/before
}
});
@@ -331,22 +325,40 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
navigateToView = (targetDoc: Doc, activeItem: Doc) => {
clearTimeout(this._navTimer);
const bestTarget = DocumentManager.Instance.getFirstDocumentView(targetDoc)?.props.Document;
- 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.presPinTimecode;
+ 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]));
+ };
} else {
- bestTarget._viewTransition = activeItem.presTransition ? `transform ${activeItem.presTransition}ms` : 'all 0.5s';
bestTarget._panX = activeItem.presPinViewX;
bestTarget._panY = activeItem.presPinViewY;
bestTarget._viewScale = activeItem.presPinViewScale;
}
- this._navTimer = setTimeout(() => bestTarget._viewTransition = undefined, activeItem.presTransition ? NumCast(activeItem.presTransition) + 10 : 510);
- });
+ }
+ return setTimeout(() => bestTarget._viewTransition = undefined, activeItem.presTransition ? NumCast(activeItem.presTransition) + 10 : 510);
}
/**
@@ -360,7 +372,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
navigateToElement = async (curDoc: Doc) => {
const activeItem: Doc = this.activeItem;
const targetDoc: Doc = this.targetDoc;
- const srcContext = Cast(targetDoc.context, Doc, null);
+ const srcContext = Cast(targetDoc.context, Doc, null) ?? Cast(Cast(targetDoc.annotationOn, Doc, null)?.context, Doc, null);
const presCollection = Cast(this.layoutDoc.presCollection, Doc, null);
const collectionDocView = presCollection ? DocumentManager.Instance.getDocumentView(presCollection) : undefined;
const includesDoc: boolean = DocListCast(presCollection?.data).includes(targetDoc);
@@ -388,7 +400,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
self._eleArray.splice(0, self._eleArray.length, ...eleViewCache);
});
const openInTab = (doc: Doc, finished?: () => void) => {
- collectionDocView ? collectionDocView.props.addDocTab(doc, "") : this.props.addDocTab(doc, ":left");
+ collectionDocView ? collectionDocView.props.addDocTab(doc, "") : this.props.addDocTab(doc, "");
this.layoutDoc.presCollection = targetDoc;
// this still needs some fixing
setTimeout(resetSelection, 500);
@@ -401,17 +413,20 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
// If openDocument is selected then it should open the document for the user
if (activeItem.openDocument) {
LightboxView.SetLightboxDoc(targetDoc);
+ // openInTab(targetDoc);
} else if (curDoc.presMovement === PresMovement.Pan && targetDoc) {
LightboxView.SetLightboxDoc(undefined);
- 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
+ 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
} 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, 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 ? [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);
}
@@ -601,27 +616,21 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
* The method called to open the presentation as a minimized view
*/
@action
- updateMinimize = () => {
- const docView = DocumentManager.Instance.getDocumentView(this.layoutDoc);
- if (CurrentUserUtils.OverlayDocs.includes(this.layoutDoc)) {
- console.log("case 1");
+ updateMinimize = async () => {
+ if (DocListCast(CurrentUserUtils.MyOverlayDocs?.data).includes(this.layoutDoc)) {
this.layoutDoc.presStatus = PresStatus.Edit;
- Doc.RemoveDocFromList((Doc.UserDoc().myOverlayDocs as Doc), undefined, this.rootDoc);
+ Doc.RemoveDocFromList(CurrentUserUtils.MyOverlayDocs, undefined, this.rootDoc);
CollectionDockingView.AddSplit(this.rootDoc, "right");
- } else if ((true || this.layoutDoc.context) && docView) {
- console.log("case 2");
+ } else {
this.layoutDoc.presStatus = PresStatus.Edit;
clearTimeout(this._presTimer);
const pt = this.props.ScreenToLocalTransform().inverse().transformPoint(0, 0);
this.rootDoc.x = pt[0] + (this.props.PanelWidth() - 250);
this.rootDoc.y = pt[1] + 10;
- this.rootDoc._height = 35;
- this.rootDoc._width = 250;
- docView.props.removeDocument?.(this.layoutDoc);
- Doc.AddDocToList((Doc.UserDoc().myOverlayDocs as Doc), undefined, this.rootDoc);
- } else {
- console.log("case 3");
- // TODO glr: fix this case
+ this.rootDoc._height = 30;
+ this.rootDoc._width = 248;
+ Doc.AddDocToList(CurrentUserUtils.MyOverlayDocs, undefined, this.rootDoc);
+ this.props.removeDocument?.(this.layoutDoc);
}
}
@@ -629,14 +638,17 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
* 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
- viewType === CollectionViewType.Stacking && (this.rootDoc._pivotField = undefined);
+ [CollectionViewType.Tree || CollectionViewType.Stacking].includes(viewType) && (this.rootDoc._pivotField = undefined);
this.rootDoc._viewType = viewType;
- if (viewType === CollectionViewType.Stacking) this.layoutDoc._gridGap = 0;
+ if (this.isTreeOrStack) {
+ this.layoutDoc._gridGap = 0;
+ }
});
/**
@@ -710,11 +722,11 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
});
return true;
}
- childLayoutTemplate = () => this.rootDoc._viewType !== CollectionViewType.Stacking ? undefined : this.presElement;
- removeDocument = (doc: Doc) => Doc.RemoveDocFromList(this.dataDoc, this.fieldKey, doc);
+ childLayoutTemplate = () => !this.isTreeOrStack ? undefined : DocCast(Doc.UserDoc().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;
- isContentActive = (outsideReaction?: boolean) => ((CurrentUserUtils.SelectedTool === InkTool.None && this.props.layerProvider?.(this.layoutDoc) !== false) &&
+ isContentActive = (outsideReaction?: boolean) => ((CurrentUserUtils.ActiveTool === InkTool.None && !this.layoutDoc._lockedPosition) &&
(this.layoutDoc.forceActive || this.props.isSelected(outsideReaction) || this._isChildActive || this.props.renderDepth === 0) ? true : false)
/**
@@ -809,13 +821,13 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
//regular click
@action
- regularSelect = (doc: Doc, ref: HTMLElement, drag: HTMLElement, focus: boolean) => {
+ regularSelect = (doc: Doc, ref: HTMLElement, drag: HTMLElement, focus: boolean, selectPres = true) => {
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);
- this.selectPres();
+ selectPres && this.selectPres();
}
modifierSelect = (doc: Doc, ref: HTMLElement, drag: HTMLElement, focus: boolean, cmdClick: boolean, shiftClick: boolean) => {
@@ -850,7 +862,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
}
break;
case "Escape":
- if (CurrentUserUtils.OverlayDocs.includes(this.layoutDoc)) { this.updateMinimize(); }
+ if (DocListCast(CurrentUserUtils.MyOverlayDocs?.data).includes(this.layoutDoc)) { this.updateMinimize(); }
else if (this.layoutDoc.presStatus === "edit") { this._selectedArray.clear(); this._eleArray.length = this._dragArray.length = 0; }
else this.layoutDoc.presStatus = "edit";
if (this._presTimer) clearTimeout(this._presTimer);
@@ -984,7 +996,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
/**
* 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
+ * Design choice: When this is called it sets _fitContentsToBox 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)
@@ -1103,7 +1115,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
updateEffectDirection = (effect: any, all?: boolean) => {
const array: any[] = all ? this.childDocs : Array.from(this._selectedArray.keys());
array.forEach((doc) => {
- const tagDoc = Cast(doc.presentationTargetDoc, Doc, null);
+ const tagDoc = doc;// Cast(doc.presentationTargetDoc, Doc, null);
switch (effect) {
case PresEffect.Left:
tagDoc.presEffectDirection = PresEffect.Left;
@@ -1129,7 +1141,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
updateEffect = (effect: any, all?: boolean) => {
const array: any[] = all ? this.childDocs : Array.from(this._selectedArray.keys());
array.forEach((doc) => {
- const tagDoc = Cast(doc.presentationTargetDoc, Doc, null);
+ const tagDoc = doc;//Cast(doc.presentationTargetDoc, Doc, null);
switch (effect) {
case PresEffect.Bounce:
tagDoc.presEffect = PresEffect.Bounce;
@@ -1166,7 +1178,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
const zoom = activeItem.presZoom ? NumCast(activeItem.presZoom) * 100 : 75;
let duration = activeItem.presDuration ? NumCast(activeItem.presDuration) / 1000 : 2;
if (activeItem.type === DocumentType.AUDIO) duration = NumCast(activeItem.duration);
- const effect = targetDoc.presEffect ? targetDoc.presEffect : 'None';
+ const effect = this.activeItem.presEffect ? this.activeItem.presEffect : 'None';
activeItem.presMovement = activeItem.presMovement ? activeItem.presMovement : 'Zoom';
return (
<div className={`presBox-ribbon ${this.transitionTools && this.layoutDoc.presStatus === PresStatus.Edit ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onPointerUp={e => e.stopPropagation()} onClick={action(e => { e.stopPropagation(); this.openMovementDropdown = false; this.openEffectDropdown = false; })}>
@@ -1218,6 +1230,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
<div className="ribbon-property">
<input className="presBox-input"
type="number" value={transitionSpeed}
+ onKeyDown={e => e.stopPropagation()}
onChange={action((e) => this.setTransitionTime(e.target.value))} /> s
</div>
<div className="ribbon-propertyUpDown">
@@ -1257,6 +1270,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
<div className="ribbon-property">
<input className="presBox-input"
type="number" value={duration}
+ onKeyDown={e => e.stopPropagation()}
onChange={action((e) => this.setDurationTime(e.target.value))} /> s
</div>
<div className="ribbon-propertyUpDown">
@@ -1288,12 +1302,12 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
{effect}
<FontAwesomeIcon className='presBox-dropdownIcon' style={{ gridColumn: 2, color: this.openEffectDropdown ? Colors.MEDIUM_BLUE : 'black' }} icon={"angle-down"} />
<div className={'presBox-dropdownOptions'} id={'presBoxMovementDropdown'} style={{ display: this.openEffectDropdown ? "grid" : "none" }} onPointerDown={e => e.stopPropagation()}>
- <div className={`presBox-dropdownOption ${targetDoc.presEffect === PresEffect.None || !targetDoc.presEffect ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.updateEffect(PresEffect.None)}>None</div>
- <div className={`presBox-dropdownOption ${targetDoc.presEffect === PresEffect.Fade ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.updateEffect(PresEffect.Fade)}>Fade In</div>
- <div className={`presBox-dropdownOption ${targetDoc.presEffect === PresEffect.Flip ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.updateEffect(PresEffect.Flip)}>Flip</div>
- <div className={`presBox-dropdownOption ${targetDoc.presEffect === PresEffect.Rotate ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.updateEffect(PresEffect.Rotate)}>Rotate</div>
- <div className={`presBox-dropdownOption ${targetDoc.presEffect === PresEffect.Bounce ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.updateEffect(PresEffect.Bounce)}>Bounce</div>
- <div className={`presBox-dropdownOption ${targetDoc.presEffect === PresEffect.Roll ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.updateEffect(PresEffect.Roll)}>Roll</div>
+ <div className={`presBox-dropdownOption ${this.activeItem.presEffect === PresEffect.None || !this.activeItem.presEffect ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.updateEffect(PresEffect.None)}>None</div>
+ <div className={`presBox-dropdownOption ${this.activeItem.presEffect === PresEffect.Fade ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.updateEffect(PresEffect.Fade)}>Fade In</div>
+ <div className={`presBox-dropdownOption ${this.activeItem.presEffect === PresEffect.Flip ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.updateEffect(PresEffect.Flip)}>Flip</div>
+ <div className={`presBox-dropdownOption ${this.activeItem.presEffect === PresEffect.Rotate ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.updateEffect(PresEffect.Rotate)}>Rotate</div>
+ <div className={`presBox-dropdownOption ${this.activeItem.presEffect === PresEffect.Bounce ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.updateEffect(PresEffect.Bounce)}>Bounce</div>
+ <div className={`presBox-dropdownOption ${this.activeItem.presEffect === PresEffect.Roll ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.updateEffect(PresEffect.Roll)}>Roll</div>
</div>
</div>
<div className="ribbon-doubleButton" style={{ display: effect === 'None' ? "none" : "inline-flex" }}>
@@ -1303,11 +1317,11 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
</div>
</div>
<div className="effectDirection" style={{ display: effect === 'None' ? "none" : "grid", width: 40 }}>
- <Tooltip title={<><div className="dash-tooltip">{"Enter from left"}</div></>}><div style={{ gridColumn: 1, gridRow: 2, justifySelf: 'center', color: targetDoc.presEffectDirection === PresEffect.Left ? Colors.LIGHT_BLUE : "black", cursor: "pointer" }} onClick={() => this.updateEffectDirection(PresEffect.Left)}><FontAwesomeIcon icon={"angle-right"} /></div></Tooltip>
- <Tooltip title={<><div className="dash-tooltip">{"Enter from right"}</div></>}><div style={{ gridColumn: 3, gridRow: 2, justifySelf: 'center', color: targetDoc.presEffectDirection === PresEffect.Right ? Colors.LIGHT_BLUE : "black", cursor: "pointer" }} onClick={() => this.updateEffectDirection(PresEffect.Right)}><FontAwesomeIcon icon={"angle-left"} /></div></Tooltip>
- <Tooltip title={<><div className="dash-tooltip">{"Enter from top"}</div></>}><div style={{ gridColumn: 2, gridRow: 1, justifySelf: 'center', color: targetDoc.presEffectDirection === PresEffect.Top ? Colors.LIGHT_BLUE : "black", cursor: "pointer" }} onClick={() => this.updateEffectDirection(PresEffect.Top)}><FontAwesomeIcon icon={"angle-down"} /></div></Tooltip>
- <Tooltip title={<><div className="dash-tooltip">{"Enter from bottom"}</div></>}><div style={{ gridColumn: 2, gridRow: 3, justifySelf: 'center', color: targetDoc.presEffectDirection === PresEffect.Bottom ? Colors.LIGHT_BLUE : "black", cursor: "pointer" }} onClick={() => this.updateEffectDirection(PresEffect.Bottom)}><FontAwesomeIcon icon={"angle-up"} /></div></Tooltip>
- <Tooltip title={<><div className="dash-tooltip">{"Enter from center"}</div></>}><div style={{ gridColumn: 2, gridRow: 2, width: 10, height: 10, alignSelf: 'center', justifySelf: 'center', border: targetDoc.presEffectDirection === PresEffect.Center || !targetDoc.presEffectDirection ? `solid 2px ${Colors.LIGHT_BLUE}` : "solid 2px black", borderRadius: "100%", cursor: "pointer" }} onClick={() => this.updateEffectDirection(PresEffect.Center)}></div></Tooltip>
+ <Tooltip title={<><div className="dash-tooltip">{"Enter from left"}</div></>}><div style={{ gridColumn: 1, gridRow: 2, justifySelf: 'center', color: this.activeItem.presEffectDirection === PresEffect.Left ? Colors.LIGHT_BLUE : "black", cursor: "pointer" }} onClick={() => this.updateEffectDirection(PresEffect.Left)}><FontAwesomeIcon icon={"angle-right"} /></div></Tooltip>
+ <Tooltip title={<><div className="dash-tooltip">{"Enter from right"}</div></>}><div style={{ gridColumn: 3, gridRow: 2, justifySelf: 'center', color: this.activeItem.presEffectDirection === PresEffect.Right ? Colors.LIGHT_BLUE : "black", cursor: "pointer" }} onClick={() => this.updateEffectDirection(PresEffect.Right)}><FontAwesomeIcon icon={"angle-left"} /></div></Tooltip>
+ <Tooltip title={<><div className="dash-tooltip">{"Enter from top"}</div></>}><div style={{ gridColumn: 2, gridRow: 1, justifySelf: 'center', color: this.activeItem.presEffectDirection === PresEffect.Top ? Colors.LIGHT_BLUE : "black", cursor: "pointer" }} onClick={() => this.updateEffectDirection(PresEffect.Top)}><FontAwesomeIcon icon={"angle-down"} /></div></Tooltip>
+ <Tooltip title={<><div className="dash-tooltip">{"Enter from bottom"}</div></>}><div style={{ gridColumn: 2, gridRow: 3, justifySelf: 'center', color: this.activeItem.presEffectDirection === PresEffect.Bottom ? Colors.LIGHT_BLUE : "black", cursor: "pointer" }} onClick={() => this.updateEffectDirection(PresEffect.Bottom)}><FontAwesomeIcon icon={"angle-up"} /></div></Tooltip>
+ <Tooltip title={<><div className="dash-tooltip">{"Enter from center"}</div></>}><div style={{ gridColumn: 2, gridRow: 2, width: 10, height: 10, alignSelf: 'center', justifySelf: 'center', border: this.activeItem.presEffectDirection === PresEffect.Center || !this.activeItem.presEffectDirection ? `solid 2px ${Colors.LIGHT_BLUE}` : "solid 2px black", borderRadius: "100%", cursor: "pointer" }} onClick={() => this.updateEffectDirection(PresEffect.Center)}></div></Tooltip>
</div>
</div>}
<div className="ribbon-final-box">
@@ -1322,7 +1336,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
@computed get effectDirection(): string {
let effect = '';
- switch (this.targetDoc.presEffectDirection) {
+ switch (this.activeItem.presEffectDirection) {
case 'left': effect = "Enter from left"; break;
case 'right': effect = "Enter from right"; break;
case 'top': effect = "Enter from top"; break;
@@ -1338,8 +1352,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
const activeItem: Doc = this.activeItem;
const targetDoc: Doc = this.targetDoc;
this.updateMovement(activeItem.presMovement, true);
- this.updateEffect(targetDoc.presEffect, true);
- this.updateEffectDirection(targetDoc.presEffectDirection, true);
+ this.updateEffect(activeItem.presEffect, true);
+ this.updateEffectDirection(activeItem.presEffectDirection, true);
array.forEach((doc) => {
const curDoc = Cast(doc, Doc, null);
const tagDoc = Cast(curDoc.presentationTargetDoc, Doc, null);
@@ -1369,8 +1383,9 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
const scroll = targetDoc._scrollTop;
activeItem.presPinView = true;
activeItem.presPinViewScroll = scroll;
- } else if (targetDoc.type === DocumentType.VID) {
- activeItem.presPinTimecode = targetDoc._currentTimecode;
+ } else if ([DocumentType.AUDIO, DocumentType.VID].includes(targetDoc.type as any)) {
+ 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) {
const x = targetDoc._panX;
const y = targetDoc._panY;
@@ -1391,8 +1406,9 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
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 ([DocumentType.AUDIO, DocumentType.VID].includes(targetDoc.type as any)) {
+ activeItem.presStartTime = targetDoc._currentTimecode;
+ activeItem.presStartTime = NumCast(targetDoc._currentTimecode) + 0.1;
} else if (targetDoc.type === DocumentType.COMPARISON) {
const clipWidth = targetDoc._clipWidth;
activeItem.presPinClipWidth = clipWidth;
@@ -1422,6 +1438,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
<input className="presBox-input"
style={{ textAlign: 'left', width: 50 }}
type="number" value={NumCast(activeItem.presPinViewX)}
+ onKeyDown={e => e.stopPropagation()}
onChange={action((e: React.ChangeEvent<HTMLInputElement>) => { const val = e.target.value; activeItem.presPinViewX = Number(val); })} />
</div>
</div>
@@ -1431,6 +1448,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
<input className="presBox-input"
style={{ textAlign: 'left', width: 50 }}
type="number" value={NumCast(activeItem.presPinViewY)}
+ onKeyDown={e => e.stopPropagation()}
onChange={action((e: React.ChangeEvent<HTMLInputElement>) => { const val = e.target.value; activeItem.presPinViewY = Number(val); })} />
</div>
</div>
@@ -1440,6 +1458,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
<input className="presBox-input"
style={{ textAlign: 'left', width: 50 }}
type="number" value={NumCast(activeItem.presPinViewScale)}
+ onKeyDown={e => e.stopPropagation()}
onChange={action((e: React.ChangeEvent<HTMLInputElement>) => { const val = e.target.value; activeItem.presPinViewScale = Number(val); })} />
</div>
</div>
@@ -1460,6 +1479,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
<input className="presBox-input"
style={{ textAlign: 'left', width: 50 }}
type="number" value={NumCast(activeItem.presPinViewScroll)}
+ onKeyDown={e => e.stopPropagation()}
onChange={action((e: React.ChangeEvent<HTMLInputElement>) => { const val = e.target.value; activeItem.presPinViewScroll = Number(val); })} />
</div>
</div>
@@ -1485,6 +1505,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
@computed get mediaOptionsDropdown() {
const activeItem: Doc = this.activeItem;
const targetDoc: Doc = this.targetDoc;
+ const clipStart: number = NumCast(activeItem.clipStart);
+ const clipEnd: number = NumCast(activeItem.clipEnd);
const duration = Math.round(NumCast(activeItem[`${Doc.LayoutFieldKey(activeItem)}-duration`]) * 10);
const mediaStopDocInd: number = NumCast(activeItem.mediaStopDoc);
const mediaStopDocStr: string = mediaStopDocInd ? mediaStopDocInd + ". " + this.childDocs[mediaStopDocInd - 1].title : "";
@@ -1504,6 +1526,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
<input className="presBox-input"
style={{ textAlign: 'center', width: 30, height: 15, fontSize: 10 }}
type="number" value={NumCast(activeItem.presStartTime)}
+ onKeyDown={e => e.stopPropagation()}
onChange={action((e: React.ChangeEvent<HTMLInputElement>) => { activeItem.presStartTime = Number(e.target.value); })}
/>
</div>
@@ -1522,6 +1545,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
</div>
<div id={"endTime"} className="slider-number" style={{ backgroundColor: Colors.LIGHT_GRAY }}>
<input className="presBox-input"
+ onKeyDown={e => e.stopPropagation()}
style={{ textAlign: 'center', width: 30, height: 15, fontSize: 10 }}
type="number" value={NumCast(activeItem.presEndTime)}
onChange={action((e: React.ChangeEvent<HTMLInputElement>) => { activeItem.presEndTime = Number(e.target.value); })}
@@ -1530,7 +1554,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
</div>
</div>
<div className="multiThumb-slider">
- <input type="range" step="0.1" min="0" max={duration / 10} value={NumCast(activeItem.presEndTime)}
+ <input type="range" step="0.1" min={clipStart} max={clipEnd} value={NumCast(activeItem.presEndTime)}
style={{ gridColumn: 1, gridRow: 1 }}
className={`toolbar-slider ${"end"}`}
id="toolbar-slider"
@@ -1554,7 +1578,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
e.stopPropagation();
activeItem.presEndTime = Number(e.target.value);
}} />
- <input type="range" step="0.1" min="0" max={duration / 10} value={NumCast(activeItem.presStartTime)}
+ <input type="range" step="0.1" min={clipStart} max={clipEnd} value={NumCast(activeItem.presStartTime)}
style={{ gridColumn: 1, gridRow: 1 }}
className={`toolbar-slider ${"start"}`}
id="toolbar-slider"
@@ -1580,9 +1604,9 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
}} />
</div>
<div className={`slider-headers ${activeItem.presMovement === PresMovement.Pan || activeItem.presMovement === PresMovement.Zoom ? "" : "none"}`}>
- <div className="slider-text">0 s</div>
+ <div className="slider-text">{clipStart} s</div>
<div className="slider-text"></div>
- <div className="slider-text">{duration / 10} s</div>
+ <div className="slider-text">{clipEnd} s</div>
</div>
</div>
<div className="ribbon-final-box">
@@ -1775,16 +1799,16 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
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, _fitToBox: true, x: x, y: y });
+ doc = Docs.Create.FreeformDocument([title, subtitle], { title: input ? input : "Title slide", _width: 400, _height: 225, _fitContentsToBox: true, x: x, y: y });
break;
case 'header':
- doc = Docs.Create.FreeformDocument([header], { title: input ? input : "Section header", _width: 400, _height: 225, _fitToBox: true, x: x, y: y });
+ doc = Docs.Create.FreeformDocument([header], { title: input ? input : "Section header", _width: 400, _height: 225, _fitContentsToBox: true, x: x, y: y });
break;
case 'content':
- doc = Docs.Create.FreeformDocument([contentTitle, content], { title: input ? input : "Title and content", _width: 400, _height: 225, _fitToBox: true, x: x, y: y });
+ doc = Docs.Create.FreeformDocument([contentTitle, content], { title: input ? input : "Title and content", _width: 400, _height: 225, _fitContentsToBox: 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, _fitToBox: true, x: x, y: y });
+ doc = Docs.Create.FreeformDocument([contentTitle, content1, content2], { title: input ? input : "Title and two columns", _width: 400, _height: 225, _fitContentsToBox: true, x: x, y: y });
break;
default:
break;
@@ -2217,7 +2241,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
const propTitle = CurrentUserUtils.propertiesWidth > 0 ? "Close Presentation Panel" : "Open Presentation Panel";
const mode = StrCast(this.rootDoc._viewType) as CollectionViewType;
const isMini: boolean = this.toolbarWidth <= 100;
- const presKeyEvents: boolean = (this.isPres && this._presKeyEventsActive && this.rootDoc === Doc.UserDoc().activePresentation);
+ const presKeyEvents: boolean = (this.isPres && this._presKeyEventsActive && this.rootDoc === CurrentUserUtils.ActivePresentation);
const activeColor = Colors.LIGHT_BLUE;
const inactiveColor = Colors.WHITE;
return (mode === CollectionViewType.Carousel3D) ? (null) : (
@@ -2268,13 +2292,14 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
const isMini: boolean = this.toolbarWidth <= 100;
return (
<div className="presBox-buttons" style={{ display: !this.rootDoc._chromeHidden ? "none" : undefined }}>
- {isMini || Doc.UserDoc().noviceMode ? (null) : <select className="presBox-viewPicker"
+ {isMini ? (null) : <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.Carousel3D}>3D Carousel</option>
+ <option onPointerDown={e => e.stopPropagation()} value={CollectionViewType.Tree}>Tree</option>
+ {Doc.noviceMode ? (null) : <option onPointerDown={e => e.stopPropagation()} value={CollectionViewType.Carousel3D}>3D Carousel</option>}
</select>}
<div className="presBox-presentPanel" style={{ opacity: this.childDocs.length ? 1 : 0.3 }}>
<span className={`presBox-button ${this.layoutDoc.presStatus === "edit" ? "present" : ""}`}>
@@ -2414,66 +2439,141 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
else this.pauseAutoPres();
}
+ @action
+ prevClicked = (e: PointerEvent) => {
+ this.back();
+ if (this._presTimer) {
+ clearTimeout(this._presTimer);
+ this.layoutDoc.presStatus = PresStatus.Manual;
+ }
+ }
+
+ @action
+ nextClicked = (e: PointerEvent) => {
+ this.next();
+ if (this._presTimer) {
+ clearTimeout(this._presTimer);
+ this.layoutDoc.presStatus = PresStatus.Manual;
+ }
+ }
+ @undoBatch
+ @action
+ exitClicked = (e: PointerEvent) => {
+ this.updateMinimize();
+ this.layoutDoc.presStatus = PresStatus.Edit;
+ clearTimeout(this._presTimer);
+ }
+
+ @action
+ startMarqueeCreateSlide = () => {
+ PresBox.startMarquee = true;
+ }
+
+ AddToMap = (treeViewDoc: Doc, index: number[]): Doc[] => {
+ var indexNum = 0;
+ 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<Doc>(sorted); // 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<Doc>(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<Doc, number>) => [...treeViewMap.entries()].sort((a: [Doc, number], b: [Doc, number]) => a[1] > b[1] ? 1 : a[1] < b[1] ? -1 : 0).map(kv => kv[0]);
+
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;
- const presKeyEvents: boolean = (this.isPres && this._presKeyEventsActive && this.rootDoc === Doc.UserDoc().activePresentation);
+ const presKeyEvents: boolean = (this.isPres && this._presKeyEventsActive && this.rootDoc === CurrentUserUtils.ActivePresentation);
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) ?
- <div className="miniPres">
+ return DocListCast(CurrentUserUtils.MyOverlayDocs?.data).includes(this.rootDoc) ?
+ <div className="miniPres" onClick={e => e.stopPropagation()}>
<div className="presPanelOverlay" style={{ display: "inline-flex", height: 30, background: '#323232', top: 0, zIndex: 3000000, boxShadow: presKeyEvents ? '0 0 0px 3px ' + Colors.MEDIUM_BLUE : undefined }}>
- <Tooltip title={<><div className="dash-tooltip">{"Loop"}</div></>}><div className="presPanel-button" style={{ color: this.layoutDoc.presLoop ? Colors.MEDIUM_BLUE : undefined }} onClick={() => this.layoutDoc.presLoop = !this.layoutDoc.presLoop}><FontAwesomeIcon icon={"redo-alt"} /></div></Tooltip>
+ <Tooltip title={<><div className="dash-tooltip">{"Loop"}</div></>}><div className="presPanel-button" style={{ color: this.layoutDoc.presLoop ? Colors.MEDIUM_BLUE : undefined }}
+ onPointerDown={e => setupMoveUpEvents(this, e, returnFalse, returnFalse, () => this.layoutDoc.presLoop = !this.layoutDoc.presLoop, false, false)}><FontAwesomeIcon icon={"redo-alt"} /></div></Tooltip>
<div className="presPanel-divider"></div>
- <div className="presPanel-button" style={{ opacity: presStart ? 0.4 : 1 }} onClick={() => { this.back(); if (this._presTimer) { clearTimeout(this._presTimer); this.layoutDoc.presStatus = PresStatus.Manual; } }}><FontAwesomeIcon icon={"arrow-left"} /></div>
- <Tooltip title={<><div className="dash-tooltip">{this.layoutDoc.presStatus === PresStatus.Autoplay ? "Pause" : "Autoplay"}</div></>}><div className="presPanel-button" onClick={this.startOrPause}><FontAwesomeIcon icon={this.layoutDoc.presStatus === "auto" ? "pause" : "play"} /></div></Tooltip>
- <div className="presPanel-button" style={{ opacity: presEnd ? 0.4 : 1 }} onClick={() => { this.next(); if (this._presTimer) { clearTimeout(this._presTimer); this.layoutDoc.presStatus = PresStatus.Manual; } }}><FontAwesomeIcon icon={"arrow-right"} /></div>
+ <div className="presPanel-button" style={{ opacity: presStart ? 0.4 : 1 }}
+ onPointerDown={e => setupMoveUpEvents(this, e, returnFalse, returnFalse, this.prevClicked, false, false)}><FontAwesomeIcon icon={"arrow-left"} /></div>
+ <Tooltip title={<><div className="dash-tooltip">{this.layoutDoc.presStatus === PresStatus.Autoplay ? "Pause" : "Autoplay"}</div></>}><div className="presPanel-button"
+ onPointerDown={e => setupMoveUpEvents(this, e, returnFalse, returnFalse, this.startOrPause, false, false)}><FontAwesomeIcon icon={this.layoutDoc.presStatus === "auto" ? "pause" : "play"} /></div></Tooltip>
+ <div className="presPanel-button" style={{ opacity: presEnd ? 0.4 : 1 }}
+ onPointerDown={e => setupMoveUpEvents(this, e, returnFalse, returnFalse, this.nextClicked, false, false)}><FontAwesomeIcon icon={"arrow-right"} /></div>
<div className="presPanel-divider"></div>
- <Tooltip title={<><div className="dash-tooltip">{"Click to return to 1st slide"}</div></>}><div className="presPanel-button" style={{ border: 'solid 1px white' }} onClick={() => this.gotoDocument(0, this.activeItem)}><b>1</b></div></Tooltip>
+ <Tooltip title={<><div className="dash-tooltip">{"Click to return to 1st slide"}</div></>}><div className="presPanel-button" style={{ border: 'solid 1px white' }}
+ onPointerDown={e => setupMoveUpEvents(this, e, returnFalse, returnFalse, () => this.gotoDocument(0, this.activeItem), false, false)}><b>1</b></div></Tooltip>
<div className="presPanel-button-text">
Slide {this.itemIndex + 1} / {this.childDocs.length}
{this.playButtonFrames}
</div>
- <div className="presPanel-divider"></div>
- <div className="presPanel-button-text" onClick={undoBatch(action(() => { this.updateMinimize(); this.layoutDoc.presStatus = PresStatus.Edit; clearTimeout(this._presTimer); }))}>EXIT</div>
+ <div className="presPanel-divider" />
+ <div className="presPanel-button-text" onPointerDown={e =>
+ setupMoveUpEvents(this, e, returnFalse, returnFalse, this.exitClicked, false, false)}>EXIT</div>
</div>
- </div>
+ </div >
:
- <div className="presBox-cont" style={{ minWidth: CurrentUserUtils.OverlayDocs.includes(this.layoutDoc) ? 240 : undefined }} >
+ <div className="presBox-cont" style={{ minWidth: DocListCast(CurrentUserUtils.MyOverlayDocs?.data).includes(this.layoutDoc) ? 240 : undefined }} >
{this.topPanel}
{this.toolbar}
{this.newDocumentToolbarDropdown}
<div className="presBox-listCont">
- {mode !== CollectionViewType.Invalid ?
- <CollectionView {...this.props}
- ContainingCollectionDoc={this.props.Document}
- PanelWidth={this.props.PanelWidth}
- PanelHeight={this.panelHeight}
- childIgnoreNativeSize={true}
- moveDocument={returnFalse}
- childFitWidth={returnTrue}
- childOpacity={returnOne}
- childLayoutTemplate={this.childLayoutTemplate}
- filterAddDocument={this.addDocumentFilter}
- removeDocument={returnFalse}
- dontRegisterView={true}
- focus={this.selectElement}
- ScreenToLocalTransform={this.getTransform}
- />
- : (null)
+ <div className="Slide" style={{ height: `calc(100% - 30px)` }}>
+ {mode !== CollectionViewType.Invalid ?
+ <CollectionView {...this.props}
+ ContainingCollectionDoc={this.props.Document}
+ PanelWidth={this.props.PanelWidth}
+ PanelHeight={this.panelHeight}
+ childIgnoreNativeSize={true}
+ moveDocument={returnFalse}
+ childFitWidth={returnTrue}
+ childOpacity={returnOne}
+ childLayoutTemplate={this.childLayoutTemplate}
+ filterAddDocument={this.addDocumentFilter}
+ removeDocument={returnFalse}
+ dontRegisterView={true}
+ focus={this.selectElement}
+ scriptContext={this}
+ ScreenToLocalTransform={this.getTransform}
+ AddToMap={this.AddToMap}
+ RemFromMap={this.RemFromMap}
+ hierarchyIndex={[]}
+ /> : (null)
+ }
+ </div>
+
+ { // if the document type is a presentation, then the collection stacking view has a "+ new slide" button at the bottom of the stack
+ <Tooltip title={<div className="dash-tooltip">{"Click on document to pin to presentaiton or make a marquee selection to pin your desired view"}</div>}>
+ <button className="add-slide-button" onPointerDown={this.startMarqueeCreateSlide}>
+ + NEW SLIDE
+ </button>
+ </Tooltip>
}
</div>
</div>;
}
}
-ScriptingGlobals.add(function lookupPresBoxField(container: Doc, field: string, data: Doc) {
- if (field === 'indexInPres') return DocListCast(container[StrCast(container.presentationFieldKey)]).indexOf(data);
- if (field === 'presCollapsedHeight') return container._viewType === CollectionViewType.Stacking ? 35 : 31;
- if (field === 'presStatus') return container.presStatus;
- if (field === '_itemIndex') return container._itemIndex;
- if (field === 'presBox') return container;
- return undefined;
+
+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));
}); \ No newline at end of file