aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/PresBox.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/nodes/PresBox.tsx')
-rw-r--r--src/client/views/nodes/PresBox.tsx789
1 files changed, 491 insertions, 298 deletions
diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx
index 01a7bed8c..0e92044e0 100644
--- a/src/client/views/nodes/PresBox.tsx
+++ b/src/client/views/nodes/PresBox.tsx
@@ -1,7 +1,7 @@
import React = require("react");
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { Tooltip } from "@material-ui/core";
-import { action, computed, observable, runInAction } from "mobx";
+import { action, computed, observable, runInAction, ObservableMap, IReactionDisposer, reaction } from "mobx";
import { observer } from "mobx-react";
import { ColorState, SketchPicker } from "react-color";
import { Doc, DocCastAsync, DocListCast, DocListCastAsync } from "../../../fields/Doc";
@@ -19,7 +19,7 @@ import { CurrentUserUtils } from "../../util/CurrentUserUtils";
import { DocumentManager } from "../../util/DocumentManager";
import { Scripting } from "../../util/Scripting";
import { SelectionManager } from "../../util/SelectionManager";
-import { undoBatch } from "../../util/UndoManager";
+import { undoBatch, UndoManager } from "../../util/UndoManager";
import { CollectionDockingView } from "../collections/CollectionDockingView";
import { CollectionView, CollectionViewType } from "../collections/CollectionView";
import { TabDocView } from "../collections/TabDocView";
@@ -28,7 +28,6 @@ import { AudioBox } from "./AudioBox";
import { CollectionFreeFormDocumentView } from "./CollectionFreeFormDocumentView";
import { FieldView, FieldViewProps } from './FieldView';
import "./PresBox.scss";
-import { VideoBox } from "./VideoBox";
export enum PresMovement {
Zoom = "zoom",
@@ -38,12 +37,12 @@ export enum PresMovement {
}
export enum PresEffect {
- Fade = "fade",
- Flip = "flip",
- Rotate = "rotate",
- Bounce = "bounce",
- Roll = "roll",
- None = "none",
+ Fade = "Fade",
+ Flip = "Flip",
+ Rotate = "Rotate",
+ Bounce = "Bounce",
+ Roll = "Roll",
+ None = "None",
}
enum PresStatus {
@@ -52,6 +51,13 @@ enum PresStatus {
Edit = "edit"
}
+enum PresColors {
+ LightBlue = "#AEDDF8",
+ DarkBlue = "#5B9FDD",
+ LightBackground = "#ececec",
+ SlideBackground = "#d5dce2",
+}
+
type PresBoxSchema = makeInterface<[typeof documentSchema]>;
const PresBoxDocument = makeInterface(documentSchema);
@@ -59,27 +65,37 @@ const PresBoxDocument = makeInterface(documentSchema);
export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>(PresBoxDocument) {
public static LayoutString(fieldKey: string) { return FieldView.LayoutString(PresBox, fieldKey); }
- public static Instance: PresBox;
+ @observable public static Instance: PresBox;
@observable _isChildActive = false;
@observable _moveOnFromAudio: boolean = true;
@observable _presTimer!: NodeJS.Timeout;
+ @observable _presKeyEventsActive: boolean = false;
- @observable _selectedArray: Doc[] = [];
- @observable _sortedSelectedArray: Doc[] = [];
+ @observable _selectedArray: ObservableMap = new ObservableMap<Doc, any>();
@observable _eleArray: HTMLElement[] = [];
@observable _dragArray: HTMLElement[] = [];
+ @observable _pathBoolean: boolean = false;
+ @observable _expandBoolean: boolean = false;
+ private _disposers: { [name: string]: IReactionDisposer } = {};
@observable private transitionTools: boolean = false;
@observable private newDocumentTools: boolean = false;
@observable private progressivizeTools: boolean = false;
- @observable private presentTools: boolean = false;
- @observable private pathBoolean: 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 tagDocs() {
+ const tagDocs: Doc[] = [];
+ for (const doc of this.childDocs) {
+ const tagDoc = Cast(doc.presentationTargetDoc, Doc, null);
+ tagDocs.push(tagDoc)
+ }
+ return tagDocs;
+ }
@computed get itemIndex() { return NumCast(this.rootDoc._itemIndex); }
- @computed get activeItem() { return Cast(this.childDocs[this.itemIndex], Doc, null); }
+ @computed get activeItem() { return Cast(this.childDocs[NumCast(this.rootDoc._itemIndex)], Doc, null); }
@computed get targetDoc() { return Cast(this.activeItem?.presentationTargetDoc, Doc, null); }
@computed get scrollable(): boolean {
if (this.targetDoc.type === DocumentType.PDF || this.targetDoc.type === DocumentType.WEB || this.targetDoc.type === DocumentType.RTF || this.targetDoc._viewType === CollectionViewType.Stacking) return true;
@@ -92,10 +108,10 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
@computed get presElement() { return Cast(Doc.UserDoc().presElement, Doc, null); }
constructor(props: any) {
super(props);
- if (Doc.UserDoc().activePresentation = this.rootDoc) PresBox.Instance = this;
+ 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", backgroundColor: "transparent", _xMargin: 0, isTemplateDoc: true, isTemplateForField: "data"
+ title: "pres element template", type: DocumentType.PRESELEMENT, backgroundColor: "transparent", _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
@@ -108,60 +124,73 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
}
@computed get selectedDocumentView() {
if (SelectionManager.SelectedDocuments().length) return SelectionManager.SelectedDocuments()[0];
- if (PresBox.Instance && PresBox.Instance._selectedArray) return DocumentManager.Instance.getDocumentView(PresBox.Instance.rootDoc);
- return undefined;
+ if (this._selectedArray.size) return DocumentManager.Instance.getDocumentView(this.rootDoc);
}
@computed get isPres(): boolean {
- document.removeEventListener("keydown", this.keyEvents, true);
+ document.removeEventListener("keydown", PresBox.keyEventsWrapper, true);
if (this.selectedDoc?.type === DocumentType.PRES) {
- document.addEventListener("keydown", this.keyEvents, true);
+ document.removeEventListener("keydown", PresBox.keyEventsWrapper, true);
+ document.addEventListener("keydown", PresBox.keyEventsWrapper, true);
return true;
}
return false;
}
@computed get selectedDoc() { return this.selectedDocumentView?.rootDoc; }
+ @action
componentWillUnmount() {
- document.removeEventListener("keydown", this.keyEvents, true);
+ document.removeEventListener("keydown", PresBox.keyEventsWrapper, true);
+ this._presKeyEventsActive = false;
+ this.resetPresentation();
// Turn of progressivize editors
this.turnOffEdit(true);
+ Object.values(this._disposers).forEach(disposer => disposer?.());
}
- componentDidMount = async () => {
+ @action
+ componentDidMount() {
this.rootDoc.presBox = this.rootDoc;
this.rootDoc._forceRenderEngine = "timeline";
this.rootDoc._replacedChrome = "replaced";
this.layoutDoc.presStatus = PresStatus.Edit;
this.layoutDoc._gridGap = 0;
this.layoutDoc._yMargin = 0;
+ document.removeEventListener("keydown", PresBox.keyEventsWrapper, true);
+ document.addEventListener("keydown", PresBox.keyEventsWrapper, true);
+ this._presKeyEventsActive = true;
this.turnOffEdit(true);
DocListCastAsync((Doc.UserDoc().myPresentations as Doc).data).then(pres =>
!pres?.includes(this.rootDoc) && Doc.AddDocToList(Doc.UserDoc().myPresentations as Doc, "data", this.rootDoc));
+ this._disposers.selection = reaction(() => SelectionManager.SelectedDocuments(),
+ views => views.some(view => view.props.Document === this.rootDoc) && this.updateCurrentPresentation());
}
- updateCurrentPresentation = () => {
- Doc.UserDoc().activePresentation = this.rootDoc;
+ @action
+ updateCurrentPresentation = (pres?: Doc) => {
+ if (pres) Doc.UserDoc().activePresentation = pres;
+ else Doc.UserDoc().activePresentation = this.rootDoc;
+ document.removeEventListener("keydown", PresBox.keyEventsWrapper, true);
+ document.addEventListener("keydown", PresBox.keyEventsWrapper, true);
PresBox.Instance = this;
}
/**
* Called when the user moves to the next slide in the presentation trail.
*/
- @undoBatch
@action
next = () => {
this.updateCurrentPresentation();
const activeNext = Cast(this.childDocs[this.itemIndex + 1], Doc, null);
const activeItem: Doc = this.activeItem;
const targetDoc: Doc = this.targetDoc;
- const childDocs = DocListCast(targetDoc[Doc.LayoutFieldKey(targetDoc)]);
- const currentFrame = Cast(targetDoc._currentFrame, "number", null);
- const lastFrame = Cast(targetDoc.lastFrame, "number", null);
- const curFrame = NumCast(targetDoc._currentFrame);
+ const currentFrame = Cast(targetDoc?._currentFrame, "number", null);
+ const lastFrame = Cast(targetDoc?.lastFrame, "number", null);
+ const curFrame = NumCast(targetDoc?._currentFrame);
let internalFrames: boolean = false;
if (activeItem.presProgressivize || activeItem.zoomProgressivize || targetDoc.scrollProgressivize) internalFrames = true;
// Case 1: There are still other frames and should go through all frames before going to next slide
if (internalFrames && lastFrame !== undefined && curFrame < lastFrame) {
+ const childDocs = DocListCast(targetDoc[Doc.LayoutFieldKey(targetDoc)]);
targetDoc._viewTransition = "all 1s";
setTimeout(() => targetDoc._viewTransition = undefined, 1010);
// targetDoc._currentFrame = curFrame + 1;
@@ -176,7 +205,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
activeItem.playNow = false;
// Case 3: No more frames in current doc and next slide is defined, therefore move to next slide
} else if (this.childDocs[this.itemIndex + 1] !== undefined) {
- if (activeNext.presPinView) setTimeout(() => this.selectPres(), 0);
+ if (activeNext.presPinView || activeNext.presentationTargetDoc === this.layoutDoc.presCollection) setTimeout(() => this.updateCurrentPresentation(), 0);
else this.selectPres();
const nextSelected = this.itemIndex + 1;
if (targetDoc.type === DocumentType.AUDIO) { if (AudioBox.Instance._ele) AudioBox.Instance.pause(); }
@@ -188,9 +217,9 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
if (targetNext.type === DocumentType.AUDIO) AudioBox.Instance.playFrom(NumCast(activeNext.presStartTime));
// if (targetNext.type === DocumentType.VID) { VideoBox.Instance.Play() };
} else if (targetNext.type === DocumentType.AUDIO || targetNext.type === DocumentType.VID) { activeNext.playNow = true; console.log('play next after it is navigated to'); }
- this.gotoDocument(nextSelected, this.itemIndex);
+ this.gotoDocument(nextSelected);
} else if (this.childDocs[this.itemIndex + 1] === undefined && this.layoutDoc.presLoop) {
- this.gotoDocument(0, this.itemIndex);
+ this.gotoDocument(0);
}
}
@@ -199,7 +228,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
* Design choice: If there are frames within the presentation, moving back will not
* got back through the frames but instead directly to the next point in the presentation.
*/
- @undoBatch
@action
back = () => {
this.updateCurrentPresentation();
@@ -209,22 +237,21 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
const prevTargetDoc = Cast(prevItem.presentationTargetDoc, Doc, null);
const lastFrame = Cast(targetDoc.lastFrame, "number", null);
const curFrame = NumCast(targetDoc._currentFrame);
- if (prevItem.presPinView) setTimeout(() => this.selectPres(), 0);
+ if (prevItem.presPinView || prevTargetDoc === this.layoutDoc.presCollection) { setTimeout(() => this.updateCurrentPresentation(), 0); }
else this.selectPres();
if (lastFrame !== undefined && curFrame >= 1) {
this.prevKeyframe(targetDoc, activeItem);
} else if (activeItem) {
let prevSelected = this.itemIndex;
prevSelected = Math.max(0, prevSelected - 1);
- this.gotoDocument(prevSelected, this.itemIndex);
+ this.gotoDocument(prevSelected);
if (NumCast(prevTargetDoc.lastFrame) > 0) prevTargetDoc._currentFrame = NumCast(prevTargetDoc.lastFrame);
}
}
//The function that is called when a document is clicked or reached through next or back.
//it'll also execute the necessary actions if presentation is playing.
- public gotoDocument = action((index: number, fromDoc: number) => {
- this.updateCurrentPresentation();
+ public gotoDocument = action((index: number) => {
Doc.UnBrushAllDocs();
if (index >= 0 && index < this.childDocs.length) {
this.rootDoc._itemIndex = index;
@@ -240,7 +267,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
setTimeout(() => bestTarget._viewTransition = undefined, activeItem.presTransition ? NumCast(activeItem.presTransition) + 10 : 1010);
}
});
- } else {
+ } else if (presTargetDoc) {
presTargetDoc && runInAction(() => {
if (activeItem.presMovement === PresMovement.Jump) presTargetDoc.focusSpeed = 0;
else presTargetDoc.focusSpeed = activeItem.presTransition ? activeItem.presTransition : 500;
@@ -250,7 +277,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
if (presTargetDoc?.lastFrame !== undefined) {
presTargetDoc._currentFrame = 0;
}
- this._selectedArray = [this.childDocs[index]]; //Update selected array
+ this._selectedArray.clear();
+ this.childDocs[index] && this._selectedArray.set(this.childDocs[index], undefined); //Update selected array
//Handles movement to element
if (this.layoutDoc._viewType === "stacking") this.navigateToElement(this.childDocs[index]);
this.onHideDocument(); //Handles hide after/before
@@ -268,7 +296,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
navigateToElement = async (curDoc: Doc) => {
const activeItem: Doc = this.activeItem;
const targetDoc: Doc = this.targetDoc;
- const srcContext = await DocCastAsync(targetDoc.context);
+ const srcContext = await DocCastAsync(targetDoc?.context);
const presCollection = Cast(this.layoutDoc.presCollection, Doc, null);
const collectionDocView = presCollection ? DocumentManager.Instance.getDocumentView(presCollection) : undefined;
this.turnOffEdit();
@@ -277,40 +305,51 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
this.layoutDoc.presCollection = srcContext;
} else if (targetDoc) this.layoutDoc.presCollection = targetDoc;
}
- // if (collectionDocView) {
- // if (srcContext && srcContext !== presCollection) {
- // // Case 1: new srcContext inside of current collection so add a new tab to the current pres collection
- // collectionDocView.props.addDocTab(srcContext, "inPlace");
- // }
- // }
- this.updateCurrentPresentation();
const docToJump = curDoc;
const willZoom = false;
+ const presStatus = this.rootDoc.presStatus;
+ const selViewCache = Array.from(this._selectedArray.keys());
+ const dragViewCache = Array.from(this._dragArray);
+ const eleViewCache = Array.from(this._eleArray);
+ const self = this;
+ const resetSelection = action(() => {
+ const presDocView = DocumentManager.Instance.getDocumentView(self.rootDoc);
+ if (presDocView) SelectionManager.SelectDoc(presDocView, false);
+ self.rootDoc.presStatus = presStatus;
+ self._selectedArray.clear();
+ selViewCache.forEach(doc => self._selectedArray.set(doc, undefined));
+ self._dragArray.splice(0, self._dragArray.length, ...dragViewCache);
+ self._eleArray.splice(0, self._eleArray.length, ...eleViewCache);
+ });
const openInTab = () => {
- collectionDocView ? collectionDocView.props.addDocTab(activeItem, "replace") : this.props.addDocTab(activeItem, "replace:left");
+ collectionDocView ? collectionDocView.props.addDocTab(targetDoc, "") : this.props.addDocTab(targetDoc, ":left");
+ this.layoutDoc.presCollection = targetDoc;
+ // this still needs some fixing
+ setTimeout(resetSelection, 500);
};
// If openDocument is selected then it should open the document for the user
if (activeItem.openDocument) {
openInTab();
- } else
+ } else {
//docToJump stayed same meaning, it was not in the group or was the last element in the group
- if (activeItem.zoomProgressivize && this.rootDoc.presStatus !== PresStatus.Edit) {
- this.zoomProgressivizeNext(targetDoc);
- } else if (docToJump === curDoc) {
+ // if (activeItem.zoomProgressivize && this.rootDoc.presStatus !== PresStatus.Edit) {
+ // this.zoomProgressivizeNext(targetDoc);
+ // } else
+ if (docToJump === curDoc) {
//checking if curDoc has navigation open
if (curDoc.presMovement === PresMovement.Pan && targetDoc) {
await DocumentManager.Instance.jumpToDocument(targetDoc, false, openInTab, srcContext); // documents open in new tab instead of on right
} else if ((curDoc.presMovement === PresMovement.Zoom || curDoc.presMovement === PresMovement.Jump) && targetDoc) {
//awaiting jump so that new scale can be found, since jumping is async
- await DocumentManager.Instance.jumpToDocument(targetDoc, true, openInTab, srcContext); // documents open in new tab instead of on right
+ await DocumentManager.Instance.jumpToDocument(targetDoc, true, openInTab, srcContext, undefined, undefined, undefined, resetSelection); // documents open in new tab instead of on right
}
} else {
//awaiting jump so that new scale can be found, since jumping is async
targetDoc && await DocumentManager.Instance.jumpToDocument(targetDoc, willZoom, undefined, srcContext);
}
+ }
// After navigating to the document, if it is added as a presPinView then it will
// adjust the pan and scale to that of the pinView when it was added.
- // TODO: Add option to remove presPinView
if (activeItem.presPinView) {
// if targetDoc is not displayed but one of its aliases is, then we need to modify that alias, not the original target
const bestTarget = DocumentManager.Instance.getFirstDocumentView(targetDoc)?.props.Document;
@@ -319,6 +358,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
bestTarget._scrollY = activeItem.presPinViewScroll;
} else if (bestTarget.type === DocumentType.COMPARISON) {
bestTarget._clipWidth = activeItem.presPinClipWidth;
+ } else if (bestTarget.type === DocumentType.VID) {
+ bestTarget._currentTimecode = activeItem.presPinTimecode;
} else {
bestTarget._viewTransition = activeItem.presTransition ? `transform ${activeItem.presTransition}ms` : 'all 0.5s';
bestTarget._panX = activeItem.presPinViewX;
@@ -331,9 +372,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
// If website and has presWebsite data associated then on click it should
// go back to that specific website
// TODO: Add progressivize for navigating web (storing websites for given frames)
- if (targetDoc.presWebsiteData) {
- targetDoc.data = targetDoc.presWebsiteData;
- }
}
/**
@@ -381,7 +419,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
}
}
-
/**
* For 'Hide Before' and 'Hide After' buttons making sure that
* they are hidden each time the presentation is updated.
@@ -392,17 +429,21 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
const curDoc = Cast(doc, Doc, null);
const tagDoc = Cast(curDoc.presentationTargetDoc!, Doc, null);
if (tagDoc) tagDoc.opacity = 1;
- if (curDoc.presHideTillShownButton) {
+ const itemIndexes: number[] = this.getAllIndexes(this.tagDocs, tagDoc);
+ const curInd: number = itemIndexes.indexOf(index);
+ if (itemIndexes.length > 1 && curDoc.presHideBefore && curInd !== 0) { }
+ else if (curDoc.presHideBefore) {
if (index > this.itemIndex) {
tagDoc.opacity = 0;
- } else if (!curDoc.presHideAfterButton) {
+ } else if (!curDoc.presHideAfter) {
tagDoc.opacity = 1;
}
}
- if (curDoc.presHideAfterButton) {
+ if (itemIndexes.length > 1 && curDoc.presHideAfter && curInd !== (itemIndexes.length - 1)) { }
+ else if (curDoc.presHideAfter) {
if (index < this.itemIndex) {
tagDoc.opacity = 0;
- } else if (!curDoc.presHideTillShownButton) {
+ } else if (!curDoc.presHideBefore) {
tagDoc.opacity = 1;
}
}
@@ -412,7 +453,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
//The function that starts or resets presentaton functionally, depending on presStatus of the layoutDoc
- @undoBatch
@action
startAutoPres = (startSlide: number) => {
this.updateCurrentPresentation();
@@ -444,7 +484,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
};
this.layoutDoc.presStatus = PresStatus.Autoplay;
this.startPresentation(startSlide);
- this.gotoDocument(startSlide, this.itemIndex);
+ this.gotoDocument(startSlide);
load();
}
@@ -460,26 +500,25 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
//The function that resets the presentation by removing every action done by it. It also
//stops the presentaton.
resetPresentation = () => {
- this.updateCurrentPresentation();
this.rootDoc._itemIndex = 0;
+ for (const doc of this.childDocs) Cast(doc.presentationTargetDoc, Doc, null).opacity = 1;
}
@action togglePath = (srcContext: Doc, off?: boolean) => {
if (off) {
- this.pathBoolean = false;
+ this._pathBoolean = false;
srcContext.presPathView = false;
} else {
- this.pathBoolean = !this.pathBoolean;
- srcContext.presPathView = this.pathBoolean;
+ runInAction(() => this._pathBoolean = !this._pathBoolean);
+ srcContext.presPathView = this._pathBoolean;
}
}
- @undoBatch
@action toggleExpandMode = () => {
- this.rootDoc.expandBoolean = !this.rootDoc.expandBoolean;
+ runInAction(() => this._expandBoolean = !this._expandBoolean);
+ this.rootDoc.expandBoolean = this._expandBoolean;
this.childDocs.forEach((doc) => {
- if (this.rootDoc.expandBoolean) doc.presExpandInlineButton = true;
- else if (!this.rootDoc.expandBoolean) doc.presExpandInlineButton = false;
+ doc.presExpandInlineButton = this._expandBoolean;
});
}
@@ -492,10 +531,10 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
this.updateCurrentPresentation();
this.childDocs.map(doc => {
const tagDoc = doc.presentationTargetDoc as Doc;
- if (doc.presHideTillShownButton && this.childDocs.indexOf(doc) > startIndex) {
+ if (doc.presHideBefore && this.childDocs.indexOf(doc) > startIndex) {
tagDoc.opacity = 0;
}
- if (doc.presHideAfterButton && this.childDocs.indexOf(doc) < startIndex) {
+ if (doc.presHideAfter && this.childDocs.indexOf(doc) < startIndex) {
tagDoc.opacity = 0;
}
});
@@ -504,15 +543,13 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
/**
* The method called to open the presentation as a minimized view
*/
- @undoBatch
@action
updateMinimize = () => {
const docView = DocumentManager.Instance.getDocumentView(this.layoutDoc);
- if (this.layoutDoc.inOverlay) {
+ if (CurrentUserUtils.OverlayDocs.includes(this.layoutDoc)) {
this.layoutDoc.presStatus = PresStatus.Edit;
Doc.RemoveDocFromList((Doc.UserDoc().myOverlayDocs as Doc), undefined, this.rootDoc);
CollectionDockingView.AddSplit(this.rootDoc, "right");
- this.layoutDoc.inOverlay = false;
} else if (this.layoutDoc.context && docView) {
this.layoutDoc.presStatus = PresStatus.Edit;
clearTimeout(this._presTimer);
@@ -540,7 +577,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
* 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;
@@ -550,32 +587,11 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
if (viewType === CollectionViewType.Stacking) this.layoutDoc._gridGap = 0;
});
- /**
- * When the movement dropdown is changes
- */
- @undoBatch
- updateMovement = action((movement: any, activeItem: Doc, targetDoc: Doc) => {
- switch (movement) {
- case PresMovement.Zoom: //Pan and zoom
- activeItem.presMovement = PresMovement.Zoom;
- break;
- case PresMovement.Pan: //Pan
- activeItem.presMovement = PresMovement.Pan;
- break;
- case PresMovement.Jump: //Jump Cut
- activeItem.presJump = true;
- activeItem.presMovement = PresMovement.Jump;
- break;
- case PresMovement.None: default:
- activeItem.presMovement = PresMovement.None;
- break;
- }
- });
setMovementName = action((movement: any, activeItem: Doc): string => {
let output: string = 'none';
switch (movement) {
- case PresMovement.Zoom: output = 'Zoom'; break; //Pan and zoom
+ case PresMovement.Zoom: output = 'Pan & Zoom'; break; //Pan and zoom
case PresMovement.Pan: output = 'Pan'; break; //Pan
case PresMovement.Jump: output = 'Jump cut'; break; //Jump Cut
case PresMovement.None: output = 'None'; break; //None
@@ -589,23 +605,28 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
addDocumentFilter = (doc: Doc | Doc[]) => {
const docs = doc instanceof Doc ? [doc] : doc;
docs.forEach((doc, i) => {
- if (this.childDocs.includes(doc)) {
- if (docs.length === i + 1) return false;
- } else if (doc.type === DocumentType.LABEL) {
+ if (doc.type === DocumentType.LABEL) {
const audio = Cast(doc.annotationOn, Doc, null);
if (audio) {
- audio.aliasOf instanceof Doc;
audio.presStartTime = NumCast(doc.audioStart);
audio.presEndTime = NumCast(doc.audioEnd);
audio.presDuration = NumCast(doc.audioEnd) - NumCast(doc.audioStart);
TabDocView.PinDoc(audio, false, true);
- setTimeout(() => this.removeDocument(doc), 1);
+ setTimeout(() => this.removeDocument(doc), 0);
return false;
}
} else {
- doc.aliasOf instanceof Doc && (doc.presentationTargetDoc = doc.aliasOf);
- !this.childDocs.includes(doc) && (doc.presMovement = PresMovement.Zoom);
- if (this.rootDoc.expandBoolean) doc.presExpandInlineButton = true;
+ if (!doc.aliasOf) {
+ const original = Doc.MakeAlias(doc);
+ TabDocView.PinDoc(original);
+ setTimeout(() => this.removeDocument(doc), 0);
+ return false;
+ } else {
+ if (!doc.presentationTargetDoc) doc.title = doc.title + " - Slide";
+ doc.aliasOf instanceof Doc && (doc.presentationTargetDoc = doc.aliasOf);
+ doc.presMovement = PresMovement.Zoom;
+ if (this._expandBoolean) doc.presExpandInlineButton = true;
+ }
}
});
return true;
@@ -622,41 +643,43 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
*/
@action
sortArray = (): Doc[] => {
- return this.childDocs.filter(doc => this._selectedArray.includes(doc));
+ return this.childDocs.filter(doc => this._selectedArray.has(doc));
}
/**
* Method to get the list of selected items in the order in which they have been selected
*/
@computed get listOfSelected() {
- const list = this._selectedArray.map((doc: Doc, index: any) => {
+ const list = Array.from(this._selectedArray.keys()).map((doc: Doc, index: any) => {
const curDoc = Cast(doc, Doc, null);
const tagDoc = Cast(curDoc.presentationTargetDoc!, Doc, null);
- if (tagDoc) return <div className="selectedList-items">{index + 1}. {curDoc.title}</div>;
+ if (curDoc && curDoc === this.activeItem) return <div className="selectedList-items"><b>{index + 1}. {curDoc.title}</b></div>
+ else if (tagDoc) return <div className="selectedList-items">{index + 1}. {curDoc.title}</div>;
else if (curDoc) return <div className="selectedList-items">{index + 1}. {curDoc.title}</div>;
});
return list;
}
@action
- selectPres = () => {
- const presDocView = DocumentManager.Instance.getDocumentView(this.rootDoc)!;
+ selectPres = (pres?: Doc) => {
+ const presDocView = DocumentManager.Instance.getDocumentView(pres ? pres : this.rootDoc)!;
SelectionManager.SelectDoc(presDocView, false);
}
//Regular click
@action
selectElement = (doc: Doc) => {
- this.gotoDocument(this.childDocs.indexOf(doc), NumCast(this.itemIndex));
- if (doc.presPinView) setTimeout(() => this.selectPres(), 0);
- else this.selectPres();
+ const context = Cast(doc.context, Doc, null);
+ this.gotoDocument(this.childDocs.indexOf(doc));
+ if (doc.presPinView || doc.presentationTargetDoc === this.layoutDoc.presCollection) setTimeout(() => this.updateCurrentPresentation(context), 0);
+ else this.updateCurrentPresentation(context);
}
//Command click
@action
multiSelect = (doc: Doc, ref: HTMLElement, drag: HTMLElement) => {
- if (!this._selectedArray.includes(doc)) {
- this._selectedArray.push(doc);
+ if (!this._selectedArray.has(doc)) {
+ this._selectedArray.set(doc, undefined);
this._eleArray.push(ref);
this._dragArray.push(drag);
}
@@ -666,11 +689,11 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
//Shift click
@action
shiftSelect = (doc: Doc, ref: HTMLElement, drag: HTMLElement) => {
- this._selectedArray = [];
+ this._selectedArray.clear();
// const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null);
if (this.activeItem) {
for (let i = Math.min(this.itemIndex, this.childDocs.indexOf(doc)); i <= Math.max(this.itemIndex, this.childDocs.indexOf(doc)); i++) {
- this._selectedArray.push(this.childDocs[i]);
+ this._selectedArray.set(this.childDocs[i], undefined);
this._eleArray.push(ref);
this._dragArray.push(drag);
}
@@ -678,72 +701,102 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
this.selectPres();
}
+ //regular click
+ @action
+ 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);
+ this.selectPres();
+ }
+
+ modifierSelect = (doc: Doc, ref: HTMLElement, drag: HTMLElement, focus: boolean, cmdClick: boolean, shiftClick: boolean) => {
+ if (cmdClick) this.multiSelect(doc, ref, drag);
+ else if (shiftClick) this.shiftSelect(doc, ref, drag);
+ else this.regularSelect(doc, ref, drag, focus);
+ }
+
+ static keyEventsWrapper = (e: KeyboardEvent) => {
+ PresBox.Instance.keyEvents(e);
+ }
+
// Key for when the presentaiton is active
- @undoBatch
- keyEvents = action(async (e: KeyboardEvent) => {
+ @action
+ keyEvents = (e: KeyboardEvent) => {
if (e.target instanceof HTMLInputElement) return;
let handled = false;
const anchorNode = document.activeElement as HTMLDivElement;
if (anchorNode && anchorNode.className?.includes("lm_title")) return;
- if (e.keyCode === 27) { // Escape key
- if (this.layoutDoc.inOverlay) { this.updateMinimize(); }
- else if (this.layoutDoc.presStatus === "edit") { this._selectedArray = []; this._eleArray = []; this._dragArray = []; }
- else this.layoutDoc.presStatus = "edit";
- if (this._presTimer) clearTimeout(this._presTimer);
- handled = true;
- } if ((e.metaKey || e.altKey) && e.keyCode === 65) { // Ctrl-A to select all
- if (this.layoutDoc.presStatus === "edit") {
- this._selectedArray = this.childDocs;
+ switch (e.key) {
+ case "Backspace":
+ if (this.layoutDoc.presStatus === "edit") {
+ undoBatch(action(() => {
+ for (const doc of Array.from(this._selectedArray.keys())) {
+ this.removeDocument(doc);
+ }
+ this._selectedArray.clear();
+ this._eleArray.length = 0;
+ this._dragArray.length = 0;
+ }))();
+ handled = true;
+ }
+ break;
+ case "Escape":
+ if (CurrentUserUtils.OverlayDocs.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);
handled = true;
- }
- } if (e.keyCode === 37 || e.keyCode === 38) { // left(37) / a(65) / up(38) to go back
- this.back();
- if (this._presTimer) clearTimeout(this._presTimer);
- handled = true;
- } if (e.keyCode === 39 || e.keyCode === 40) { // right (39) / d(68) / down(40) to go to next
- this.next();
- if (this._presTimer) clearTimeout(this._presTimer);
- handled = true;
- } if (e.keyCode === 32) { // spacebar to 'present' or autoplay
- if (this.layoutDoc.presStatus === "manual") this.startAutoPres(this.itemIndex);
- else if (this.layoutDoc.presStatus === "auto") if (this._presTimer) clearTimeout(this._presTimer);
- handled = true;
- } if (e.keyCode === 8) { // delete selected items
- if (this.layoutDoc.presStatus === "edit") {
- await Promise.all<boolean>(this._selectedArray.map((doc, i): boolean => {
- const removed: boolean = this.removeDocument(doc);
- console.log("Is removed? : " + i + " | " + removed);
- return removed;
- }));
- action(() => this._selectedArray = []);
- action(() => this._eleArray = []);
- action(() => this._dragArray = []);
+ break;
+ case "Down": case "ArrowDown":
+ case "Right": case "ArrowRight":
+ if (this.itemIndex >= this.childDocs.length - 1) return;
+ if (e.shiftKey) { // TODO: update to work properly
+ this.rootDoc._itemIndex = NumCast(this.rootDoc._itemIndex) + 1;
+ this._selectedArray.set(this.childDocs[this.rootDoc._itemIndex], undefined);
+ } else {
+ this.next();
+ if (this._presTimer) { clearTimeout(this._presTimer); this.layoutDoc.presStatus = PresStatus.Manual; }
+ }
handled = true;
- }
- } if (handled) {
+ break;
+ case "Up": case "ArrowUp":
+ case "Left": case "ArrowLeft":
+ if (this.itemIndex === 0) return;
+ if (e.shiftKey) { // TODO: update to work properly
+ this.rootDoc._itemIndex = NumCast(this.rootDoc._itemIndex) - 1;
+ this._selectedArray.set(this.childDocs[this.rootDoc._itemIndex], undefined);
+ } else {
+ this.back();
+ if (this._presTimer) { clearTimeout(this._presTimer); this.layoutDoc.presStatus = PresStatus.Manual; }
+ }
+ handled = true;
+ break;
+ case "Spacebar": case " ":
+ if (this.layoutDoc.presStatus === PresStatus.Manual) this.startAutoPres(this.itemIndex);
+ else if (this.layoutDoc.presStatus === PresStatus.Autoplay) if (this._presTimer) clearTimeout(this._presTimer);
+ handled = true;
+ break;
+ case "a":
+ if ((e.metaKey || e.altKey) && this.layoutDoc.presStatus === "edit") {
+ this._selectedArray.clear();
+ this.childDocs.forEach(doc => this._selectedArray.set(doc, undefined));
+ handled = true;
+ }
+ default:
+ break;
+ }
+ if (handled) {
e.stopPropagation();
e.preventDefault();
- } if ((e.keyCode === 37 || e.keyCode === 38) && e.shiftKey) { // left(37) / a(65) / up(38) to go back
- if (this.layoutDoc.presStatus === "edit" && this._selectedArray.length > 0) {
- const index = this.childDocs.indexOf(this._selectedArray[this._selectedArray.length]);
- if ((index - 1) > 0) this._selectedArray.push(this.childDocs[index - 1]);
- }
- handled = true;
- } if ((e.keyCode === 39 || e.keyCode === 40) && e.shiftKey) { // left(37) / a(65) / up(38) to go back
- if (this.layoutDoc.presStatus === "edit" && this._selectedArray.length > 0) {
- const index = this.childDocs.indexOf(this._selectedArray[this._selectedArray.length]);
- if ((index - 1) > 0) {
- this._selectedArray.push(this.childDocs[index - 1]);
- }
- }
- handled = true;
}
- });
+ }
/**
*
*/
- @undoBatch
@action
viewPaths = () => {
const srcContext = Cast(this.rootDoc.presCollection, Doc, null);
@@ -752,26 +805,60 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
}
}
+ getAllIndexes = (arr: Doc[], val: Doc): number[] => {
+ var indexes = [], i;
+ for (i = 0; i < arr.length; i++)
+ if (arr[i] === val)
+ indexes.push(i);
+ return indexes;
+ }
+
// Adds the index in the pres path graphically
@computed get order() {
const order: JSX.Element[] = [];
- this.childDocs.forEach((doc, index) => {
+ const docs: Doc[] = [];
+ this.childDocs.filter(doc => Cast(doc.presentationTargetDoc, Doc, null)).forEach((doc, index) => {
const tagDoc = Cast(doc.presentationTargetDoc, Doc, null);
- const srcContext = Cast(tagDoc?.context, Doc, null);
+ const srcContext = Cast(tagDoc.context, Doc, null);
const width = NumCast(tagDoc._width) / 10;
const height = Math.max(NumCast(tagDoc._height) / 10, 15);
const edge = Math.max(width, height);
const fontSize = edge * 0.8;
- // Case A: Document is contained within the colleciton
+ const gap = 2;
+ // Case A: Document is contained within the collection
if (this.rootDoc.presCollection === srcContext) {
+ if (docs.includes(tagDoc)) {
+ const prevOccurances: number = this.getAllIndexes(docs, tagDoc).length;
+ docs.push(tagDoc);
+ order.push(
+ <div className="pathOrder"
+ key={tagDoc.id + 'pres' + index}
+ style={{ top: NumCast(tagDoc.y) + (prevOccurances * (edge + gap) - (edge / 2)), left: NumCast(tagDoc.x) - (edge / 2), width: edge, height: edge, fontSize: fontSize }}
+ onClick={() => this.selectElement(doc)}>
+ <div className="pathOrder-frame">{index + 1}</div>
+ </div>);
+ } else {
+ docs.push(tagDoc);
+ order.push(
+ <div className="pathOrder"
+ key={tagDoc.id + 'pres' + index}
+ style={{ top: NumCast(tagDoc.y) - (edge / 2), left: NumCast(tagDoc.x) - (edge / 2), width: edge, height: edge, fontSize: fontSize }}
+ onClick={() => this.selectElement(doc)}>
+ <div className="pathOrder-frame">{index + 1}</div>
+ </div>);
+ }
+ // Case B: Document is presPinView and is presCollection
+ } else if (doc.pinWithView && this.layoutDoc.presCollection === tagDoc) {
+ docs.push(tagDoc);
order.push(
- <div className="pathOrder" style={{ top: NumCast(tagDoc.y) - (edge / 2), left: NumCast(tagDoc.x) - (edge / 2), width: edge, height: edge, fontSize: fontSize }}>
+ <div className="pathOrder" key={tagDoc.id + 'pres' + index} style={{ top: 0, left: 0 }}>
<div className="pathOrder-frame">{index + 1}</div>
</div>);
- // Case B: Document is not inside of the collection
+ // Case C: Document is not contained within presCollection
} else {
+ docs.push(tagDoc);
order.push(
- <div className="pathOrder" style={{ top: 0, left: 0 }}>
+ <div className="pathOrder" key={tagDoc.id + 'pres' + index} style={{ position: 'absolute', top: 0, left: 0 }}>
<div className="pathOrder-frame">{index + 1}</div>
</div>);
}
@@ -818,49 +905,102 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
/>);
}
- /**
- * The function that is called on click to turn fading document after presented option on/off.
- * It also makes sure that the option swithches from hide-after to this one, since both
- * can't coexist.
- */
- @action
- onFadeDocumentAfterPresentedClick = (e: React.MouseEvent) => {
- e.stopPropagation();
- const activeItem: Doc = this.activeItem;
- const targetDoc: Doc = this.targetDoc;
- activeItem.presFadeButton = !activeItem.presFadeButton;
- if (!activeItem.presFadeButton) {
- if (targetDoc) {
- targetDoc.opacity = 1;
- }
- } else {
- activeItem.presHideAfterButton = false;
- if (this.rootDoc.presStatus !== "edit" && targetDoc) {
- targetDoc.opacity = 0.5;
- }
- }
- }
-
// Converts seconds to ms and updates presTransition
- @undoBatch
setTransitionTime = (number: String, change?: number) => {
let timeInMS = Number(number) * 1000;
if (change) timeInMS += change;
if (timeInMS < 100) timeInMS = 100;
if (timeInMS > 10000) timeInMS = 10000;
- if (this.activeItem) this.activeItem.presTransition = timeInMS;
+ Array.from(this._selectedArray.keys()).forEach((doc) => doc.presTransition = timeInMS);
}
// Converts seconds to ms and updates presDuration
- @undoBatch
setDurationTime = (number: String, change?: number) => {
let timeInMS = Number(number) * 1000;
if (change) timeInMS += change;
if (timeInMS < 100) timeInMS = 100;
if (timeInMS > 20000) timeInMS = 20000;
- if (this.activeItem) this.activeItem.presDuration = timeInMS;
+ Array.from(this._selectedArray.keys()).forEach((doc) => doc.presDuration = timeInMS);
+ }
+
+ /**
+ * When the movement dropdown is changes
+ */
+ @undoBatch
+ updateMovement = action((movement: any, all?: boolean) => {
+ const array: any[] = all ? this.childDocs : Array.from(this._selectedArray.keys());
+ array.forEach((doc) => {
+ switch (movement) {
+ case PresMovement.Zoom: //Pan and zoom
+ doc.presMovement = PresMovement.Zoom;
+ break;
+ case PresMovement.Pan: //Pan
+ doc.presMovement = PresMovement.Pan;
+ break;
+ case PresMovement.Jump: //Jump Cut
+ doc.presJump = true;
+ doc.presMovement = PresMovement.Jump;
+ break;
+ case PresMovement.None: default:
+ doc.presMovement = PresMovement.None;
+ break;
+ }
+ })
+ });
+
+ @undoBatch
+ @action
+ updateHideBefore = (activeItem: Doc) => {
+ activeItem.presHideBefore = !activeItem.presHideBefore;
+ Array.from(this._selectedArray.keys()).forEach((doc) => doc.presHideBefore = activeItem.presHideBefore);
+ }
+
+ @undoBatch
+ @action
+ updateHideAfter = (activeItem: Doc) => {
+ activeItem.presHideAfter = !activeItem.presHideAfter;
+ Array.from(this._selectedArray.keys()).forEach((doc) => doc.presHideAfter = activeItem.presHideAfter);
+ }
+
+ @undoBatch
+ @action
+ updateOpenDoc = (activeItem: Doc) => {
+ activeItem.openDocument = !activeItem.openDocument;
+ Array.from(this._selectedArray.keys()).forEach((doc) => {
+ doc.openDocument = activeItem.openDocument;
+ });
+ }
+
+ @undoBatch
+ @action
+ 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);
+ switch (effect) {
+ case PresEffect.Bounce:
+ tagDoc.presEffect = PresEffect.Bounce;
+ break;
+ case PresEffect.Fade:
+ tagDoc.presEffect = PresEffect.Fade;
+ break;
+ case PresEffect.Flip:
+ tagDoc.presEffect = PresEffect.Flip;
+ break;
+ case PresEffect.Roll:
+ tagDoc.presEffect = PresEffect.Roll;
+ break;
+ case PresEffect.Rotate:
+ tagDoc.presEffect = PresEffect.Rotate;
+ break;
+ case PresEffect.None: default:
+ tagDoc.presEffect = PresEffect.None;
+ break;
+ }
+ });
}
+ _batch: UndoManager.Batch | undefined = undefined;
@computed get transitionDropdown() {
const activeItem: Doc = this.activeItem;
@@ -879,10 +1019,10 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
{this.setMovementName(activeItem.presMovement, activeItem)}
<FontAwesomeIcon className='presBox-dropdownIcon' style={{ gridColumn: 2, color: this.openMovementDropdown ? '#5B9FDD' : 'black' }} icon={"angle-down"} />
<div className={'presBox-dropdownOptions'} id={'presBoxMovementDropdown'} onPointerDown={e => e.stopPropagation()} style={{ display: this.openMovementDropdown ? "grid" : "none" }}>
- <div className={`presBox-dropdownOption ${activeItem.presMovement === PresMovement.None ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.updateMovement(PresMovement.None, activeItem, targetDoc)}>None</div>
- <div className={`presBox-dropdownOption ${activeItem.presMovement === PresMovement.Zoom ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.updateMovement(PresMovement.Zoom, activeItem, targetDoc)}>Pan and Zoom</div>
- <div className={`presBox-dropdownOption ${activeItem.presMovement === PresMovement.Pan ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.updateMovement(PresMovement.Pan, activeItem, targetDoc)}>Pan</div>
- <div className={`presBox-dropdownOption ${activeItem.presMovement === PresMovement.Jump ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.updateMovement(PresMovement.Jump, activeItem, targetDoc)}>Jump cut</div>
+ <div className={`presBox-dropdownOption ${activeItem.presMovement === PresMovement.None ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.updateMovement(PresMovement.None)}>None</div>
+ <div className={`presBox-dropdownOption ${activeItem.presMovement === PresMovement.Zoom ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.updateMovement(PresMovement.Zoom)}>Pan {"&"} Zoom</div>
+ <div className={`presBox-dropdownOption ${activeItem.presMovement === PresMovement.Pan ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.updateMovement(PresMovement.Pan)}>Pan</div>
+ <div className={`presBox-dropdownOption ${activeItem.presMovement === PresMovement.Jump ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.updateMovement(PresMovement.Jump)}>Jump cut</div>
</div>
</div>
<div className="ribbon-doubleButton" style={{ display: activeItem.presMovement === PresMovement.Pan || activeItem.presMovement === PresMovement.Zoom ? "inline-flex" : "none" }}>
@@ -893,15 +1033,23 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
onChange={action((e) => this.setTransitionTime(e.target.value))} /> s
</div>
<div className="ribbon-propertyUpDown">
- <div className="ribbon-propertyUpDownItem" onClick={() => this.setTransitionTime(String(transitionSpeed), 1000)}>
+ <div className="ribbon-propertyUpDownItem" onClick={undoBatch(() => this.setTransitionTime(String(transitionSpeed), 1000))}>
<FontAwesomeIcon icon={"caret-up"} />
</div>
- <div className="ribbon-propertyUpDownItem" onClick={() => this.setTransitionTime(String(transitionSpeed), -1000)}>
+ <div className="ribbon-propertyUpDownItem" onClick={undoBatch(() => this.setTransitionTime(String(transitionSpeed), -1000))}>
<FontAwesomeIcon icon={"caret-down"} />
</div>
</div>
</div>
- <input type="range" step="0.1" min="0.1" max="10" value={transitionSpeed} className={`toolbar-slider ${activeItem.presMovement === PresMovement.Pan || activeItem.presMovement === PresMovement.Zoom ? "" : "none"}`} id="toolbar-slider" onChange={(e: React.ChangeEvent<HTMLInputElement>) => { e.stopPropagation(); this.setTransitionTime(e.target.value); }} />
+ <input type="range" step="0.1" min="0.1" max="10" value={transitionSpeed}
+ className={`toolbar-slider ${activeItem.presMovement === PresMovement.Pan || activeItem.presMovement === PresMovement.Zoom ? "" : "none"}`}
+ id="toolbar-slider"
+ onPointerDown={() => this._batch = UndoManager.StartBatch("presTransition")}
+ onPointerUp={() => this._batch?.end()}
+ onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
+ e.stopPropagation();
+ this.setTransitionTime(e.target.value);
+ }} />
<div className={`slider-headers ${activeItem.presMovement === PresMovement.Pan || activeItem.presMovement === PresMovement.Zoom ? "" : "none"}`}>
<div className="slider-text">Fast</div>
<div className="slider-text">Medium</div>
@@ -911,28 +1059,33 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
<div className="ribbon-box">
Visibility {"&"} Duration
<div className="ribbon-doubleButton">
- <Tooltip title={<><div className="dash-tooltip">{"Hide before presented"}</div></>}><div className={`ribbon-toggle ${activeItem.presHideTillShownButton ? "active" : ""}`} onClick={undoBatch(() => activeItem.presHideTillShownButton = !activeItem.presHideTillShownButton)}>Hide before</div></Tooltip>
- <Tooltip title={<><div className="dash-tooltip">{"Hide after presented"}</div></>}><div className={`ribbon-toggle ${activeItem.presHideAfterButton ? "active" : ""}`} onClick={undoBatch(() => activeItem.presHideAfterButton = !activeItem.presHideAfterButton)}>Hide after</div></Tooltip>
- <Tooltip title={<><div className="dash-tooltip">{"Open document in a new tab"}</div></>}><div className="ribbon-toggle" style={{ backgroundColor: activeItem.openDocument ? "#aedef8" : "" }} onClick={undoBatch(() => activeItem.openDocument = !activeItem.openDocument)}>Open</div></Tooltip>
+ <Tooltip title={<><div className="dash-tooltip">{"Hide before presented"}</div></>}><div className={`ribbon-toggle ${activeItem.presHideBefore ? "active" : ""}`} onClick={() => this.updateHideBefore(activeItem)}>Hide before</div></Tooltip>
+ <Tooltip title={<><div className="dash-tooltip">{"Hide after presented"}</div></>}><div className={`ribbon-toggle ${activeItem.presHideAfter ? "active" : ""}`} onClick={() => this.updateHideAfter(activeItem)}>Hide after</div></Tooltip>
+ <Tooltip title={<><div className="dash-tooltip">{"Open document in a new tab"}</div></>}><div className="ribbon-toggle" style={{ backgroundColor: activeItem.openDocument ? "#aedef8" : "" }} onClick={() => this.updateOpenDoc(activeItem)}>Open</div></Tooltip>
</div>
<div className="ribbon-doubleButton" >
<div className="presBox-subheading">Slide Duration</div>
<div className="ribbon-property">
<input className="presBox-input"
type="number" value={duration}
- // onFocus={() => document.removeEventListener("keydown", this.keyEvents, true)}
onChange={action((e) => this.setDurationTime(e.target.value))} /> s
</div>
<div className="ribbon-propertyUpDown">
- <div className="ribbon-propertyUpDownItem" onClick={() => this.setDurationTime(String(duration), 1000)}>
+ <div className="ribbon-propertyUpDownItem" onClick={undoBatch(() => this.setDurationTime(String(duration), 1000))}>
<FontAwesomeIcon icon={"caret-up"} />
</div>
- <div className="ribbon-propertyUpDownItem" onClick={() => this.setDurationTime(String(duration), -1000)}>
+ <div className="ribbon-propertyUpDownItem" onClick={undoBatch(() => this.setDurationTime(String(duration), -1000))}>
<FontAwesomeIcon icon={"caret-down"} />
</div>
</div>
</div>
- <input type="range" step="0.1" min="0.1" max="20" value={duration} style={{ display: targetDoc.type === DocumentType.AUDIO ? "none" : "block" }} className={"toolbar-slider"} id="duration-slider" onChange={(e: React.ChangeEvent<HTMLInputElement>) => { e.stopPropagation(); this.setDurationTime(e.target.value); }} />
+ <input type="range" step="0.1" min="0.1" max="20" value={duration}
+ style={{ display: targetDoc.type === DocumentType.AUDIO ? "none" : "block" }}
+ className={"toolbar-slider"} id="duration-slider"
+ onPointerDown={() => { this._batch = UndoManager.StartBatch("presDuration"); }}
+ onPointerUp={() => { if (this._batch) this._batch.end(); }}
+ onChange={(e: React.ChangeEvent<HTMLInputElement>) => { e.stopPropagation(); this.setDurationTime(e.target.value); }}
+ />
<div className={"slider-headers"} style={{ display: targetDoc.type === DocumentType.AUDIO ? "none" : "grid" }}>
<div className="slider-text">Short</div>
<div className="slider-text">Medium</div>
@@ -945,12 +1098,12 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
{effect}
<FontAwesomeIcon className='presBox-dropdownIcon' style={{ gridColumn: 2, color: this.openEffectDropdown ? '#5B9FDD' : 'black' }} icon={"angle-down"} />
<div className={'presBox-dropdownOptions'} id={'presBoxMovementDropdown'} style={{ display: this.openEffectDropdown ? "grid" : "none" }} onPointerDown={e => e.stopPropagation()}>
- <div className={'presBox-dropdownOption'} onPointerDown={e => e.stopPropagation()} onClick={undoBatch(() => targetDoc.presEffect = 'None')}>None</div>
- <div className={'presBox-dropdownOption'} onPointerDown={e => e.stopPropagation()} onClick={undoBatch(() => targetDoc.presEffect = 'Fade')}>Fade In</div>
- <div className={'presBox-dropdownOption'} onPointerDown={e => e.stopPropagation()} onClick={undoBatch(() => targetDoc.presEffect = 'Flip')}>Flip</div>
- <div className={'presBox-dropdownOption'} onPointerDown={e => e.stopPropagation()} onClick={undoBatch(() => targetDoc.presEffect = 'Rotate')}>Rotate</div>
- <div className={'presBox-dropdownOption'} onPointerDown={e => e.stopPropagation()} onClick={undoBatch(() => targetDoc.presEffect = 'Bounce')}>Bounce</div>
- <div className={'presBox-dropdownOption'} onPointerDown={e => e.stopPropagation()} onClick={undoBatch(() => targetDoc.presEffect = 'Roll')}>Roll</div>
+ <div className={'presBox-dropdownOption'} onPointerDown={e => e.stopPropagation()} onClick={() => this.updateEffect(PresEffect.None)}>None</div>
+ <div className={'presBox-dropdownOption'} onPointerDown={e => e.stopPropagation()} onClick={() => this.updateEffect(PresEffect.Fade)}>Fade In</div>
+ <div className={'presBox-dropdownOption'} onPointerDown={e => e.stopPropagation()} onClick={() => this.updateEffect(PresEffect.Flip)}>Flip</div>
+ <div className={'presBox-dropdownOption'} onPointerDown={e => e.stopPropagation()} onClick={() => this.updateEffect(PresEffect.Rotate)}>Rotate</div>
+ <div className={'presBox-dropdownOption'} onPointerDown={e => e.stopPropagation()} onClick={() => this.updateEffect(PresEffect.Bounce)}>Bounce</div>
+ <div className={'presBox-dropdownOption'} onPointerDown={e => e.stopPropagation()} onClick={() => this.updateEffect(PresEffect.Roll)}>Roll</div>
</div>
</div>
<div className="ribbon-doubleButton" style={{ display: effect === 'None' ? "none" : "inline-flex" }}>
@@ -968,9 +1121,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
</div>
</div>
<div className="ribbon-final-box">
- <div className={this._selectedArray.length === 0 ? "ribbon-final-button" : "ribbon-final-button-hidden"} onClick={() => this.applyTo(this._selectedArray)}>
- Apply to selected
- </div>
<div className="ribbon-final-button-hidden" onClick={() => this.applyTo(this.childDocs)}>
Apply to all
</div>
@@ -997,19 +1147,17 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
applyTo = (array: Doc[]) => {
const activeItem: Doc = this.activeItem;
const targetDoc: Doc = this.targetDoc;
+ this.updateMovement(activeItem.presMovement, true);
+ this.updateEffect(targetDoc.presEffect, true);
array.forEach((doc) => {
const curDoc = Cast(doc, Doc, null);
const tagDoc = Cast(curDoc.presentationTargetDoc, Doc, null);
if (tagDoc && targetDoc) {
curDoc.presTransition = activeItem.presTransition;
curDoc.presDuration = activeItem.presDuration;
- tagDoc.presEffect = targetDoc.presEffect;
tagDoc.presEffectDirection = targetDoc.presEffectDirection;
- tagDoc.presMovement = targetDoc.presMovement;
- curDoc.presMovement = activeItem.presMovement;
- this.updateMovement(activeItem.presMovement, curDoc, tagDoc);
- curDoc.presHideTillShownButton = activeItem.presHideTillShownButton;
- curDoc.presHideAfterButton = activeItem.presHideAfterButton;
+ curDoc.presHideBefore = activeItem.presHideBefore;
+ curDoc.presHideAfter = activeItem.presHideAfter;
}
});
}
@@ -1022,12 +1170,12 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
<div>
<div className={'presBox-ribbon'} onClick={e => e.stopPropagation()} onPointerUp={e => e.stopPropagation()} onPointerDown={e => e.stopPropagation()}>
<div className="ribbon-box">
- <div className="ribbon-doubleButton" style={{ display: targetDoc.type === DocumentType.VID || targetDoc.type === DocumentType.AUDIO ? "inline-flex" : "none" }}>
+ <div className="ribbon-doubleButton" style={{ display: targetDoc.type === DocumentType.AUDIO ? "inline-flex" : "none" }}>
<div className="ribbon-toggle" style={{ backgroundColor: activeItem.playAuto ? "#aedef8" : "" }} onClick={() => activeItem.playAuto = !activeItem.playAuto}>Play automatically</div>
<div className="ribbon-toggle" style={{ display: "flex", backgroundColor: activeItem.playAuto ? "" : "#aedef8" }} onClick={() => activeItem.playAuto = !activeItem.playAuto}>Play on next</div>
</div>
- {targetDoc.type === DocumentType.VID ? <div className="ribbon-toggle" style={{ backgroundColor: activeItem.presVidFullScreen ? "#aedef8" : "" }} onClick={() => activeItem.presVidFullScreen = !activeItem.presVidFullScreen}>Full screen</div> : (null)}
- {targetDoc.type === DocumentType.VID || targetDoc.type === DocumentType.AUDIO ? <div className="ribbon-doubleButton" style={{ marginRight: 10 }}>
+ {/* {targetDoc.type === DocumentType.VID ? <div className="ribbon-toggle" style={{ backgroundColor: activeItem.presVidFullScreen ? "#aedef8" : "" }} onClick={() => activeItem.presVidFullScreen = !activeItem.presVidFullScreen}>Full screen</div> : (null)} */}
+ {targetDoc.type === DocumentType.AUDIO ? <div className="ribbon-doubleButton" style={{ marginRight: 10 }}>
<div className="presBox-subheading">Start time</div>
<div className="ribbon-property" style={{ paddingRight: 0, paddingLeft: 0 }}>
<input className="presBox-input"
@@ -1036,7 +1184,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
onChange={action((e: React.ChangeEvent<HTMLInputElement>) => { activeItem.presStartTime = Number(e.target.value); })} />
</div>
</div> : (null)}
- {targetDoc.type === DocumentType.VID || targetDoc.type === DocumentType.AUDIO ? <div className="ribbon-doubleButton" style={{ marginRight: 10 }}>
+ {targetDoc.type === DocumentType.AUDIO ? <div className="ribbon-doubleButton" style={{ marginRight: 10 }}>
<div className="presBox-subheading">End time</div>
<div className="ribbon-property" style={{ paddingRight: 0, paddingLeft: 0 }}>
<input className="presBox-input"
@@ -1045,13 +1193,45 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
onChange={action((e: React.ChangeEvent<HTMLInputElement>) => { const val = e.target.value; activeItem.presEndTime = Number(val); })} />
</div>
</div> : (null)}
- {targetDoc.type === DocumentType.COL ? 'Presentation Pin View' : (null)}
- <div className="ribbon-doubleButton" style={{ display: targetDoc.type === DocumentType.COL ? "inline-flex" : "none" }}>
- <div className="ribbon-toggle" style={{ width: 20, padding: 0, backgroundColor: activeItem.presPinView ? "#aedef8" : "" }}
+ {this.panable || this.scrollable || this.targetDoc.type === DocumentType.COMPARISON ? 'Pinned view' : (null)}
+ <div className="ribbon-doubleButton">
+ <Tooltip title={<><div className="dash-tooltip">{activeItem.presPinView ? "Turn off pin with view" : "Turn on pin with view"}</div></>}><div className="ribbon-toggle" style={{ width: 20, padding: 0, backgroundColor: activeItem.presPinView ? PresColors.LightBlue : "" }}
onClick={() => {
activeItem.presPinView = !activeItem.presPinView;
targetDoc.presPinView = activeItem.presPinView;
if (activeItem.presPinView) {
+ if (targetDoc.type === DocumentType.PDF || targetDoc.type === DocumentType.RTF || targetDoc.type === DocumentType.WEB || targetDoc._viewType === CollectionViewType.Stacking) {
+ const scroll = targetDoc._scrollTop;
+ activeItem.presPinView = true;
+ activeItem.presPinViewScroll = scroll;
+ } else if (targetDoc.type === DocumentType.VID) {
+ activeItem.presPinTimecode = targetDoc._currentTimecode;
+ } else if ((targetDoc.type === DocumentType.COL && targetDoc._viewType === CollectionViewType.Freeform) || targetDoc.type === DocumentType.IMG) {
+ const x = targetDoc._panX;
+ const y = targetDoc._panY;
+ const scale = targetDoc._viewScale;
+ activeItem.presPinView = true;
+ activeItem.presPinViewX = x;
+ activeItem.presPinViewY = y;
+ activeItem.presPinViewScale = scale;
+ } else if (targetDoc.type === DocumentType.COMPARISON) {
+ const width = targetDoc._clipWidth;
+ activeItem.presPinClipWidth = width;
+ activeItem.presPinView = true;
+ }
+ }
+ }}>{presPinWithViewIcon}</div></Tooltip>
+ {activeItem.presPinView ? <Tooltip title={<><div className="dash-tooltip">{"Update the pinned view with the view of the selected document"}</div></>}><div className="ribbon-button"
+ onClick={() => {
+ 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;
@@ -1059,18 +1239,9 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
activeItem.presPinViewY = y;
activeItem.presPinViewScale = scale;
}
- }}>{presPinWithViewIcon}</div>
- {activeItem.presPinView ? <div className="ribbon-button"
- onClick={() => {
- const x = targetDoc._panX;
- const y = targetDoc._panY;
- const scale = targetDoc._viewScale;
- activeItem.presPinViewX = x;
- activeItem.presPinViewY = y;
- activeItem.presPinViewScale = scale;
- }}>Update</div> : (null)}
+ }}>Update</div></Tooltip> : (null)}
</div>
- <div style={{ display: activeItem.presPinView ? "block" : "none" }}>
+ {this.panable ? <div style={{ display: activeItem.presPinView ? "block" : "none" }}>
<div className="ribbon-doubleButton" style={{ marginRight: 10 }}>
<div className="presBox-subheading">Pan X</div>
<div className="ribbon-property" style={{ paddingRight: 0, paddingLeft: 0 }}>
@@ -1098,7 +1269,18 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
onChange={action((e: React.ChangeEvent<HTMLInputElement>) => { const val = e.target.value; activeItem.presPinViewScale = Number(val); })} />
</div>
</div>
- </div>
+ </div> : (null)}
+ {this.scrollable ? <div style={{ display: activeItem.presPinView ? "block" : "none" }}>
+ <div className="ribbon-doubleButton" style={{ marginRight: 10 }}>
+ <div className="presBox-subheading">Scroll</div>
+ <div className="ribbon-property" style={{ paddingRight: 0, paddingLeft: 0 }}>
+ <input className="presBox-input"
+ style={{ textAlign: 'left', width: 50 }}
+ type="number" value={NumCast(activeItem.presPinViewScroll)}
+ onChange={action((e: React.ChangeEvent<HTMLInputElement>) => { const val = e.target.value; activeItem.presPinViewScroll = Number(val); })} />
+ </div>
+ </div>
+ </div> : (null)}
{/* <div className="ribbon-doubleButton" style={{ display: targetDoc.type === DocumentType.WEB ? "inline-flex" : "none" }}>
<div className="ribbon-toggle" onClick={this.progressivizeText}>Store original website</div>
</div> */}
@@ -1205,7 +1387,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
if (data && presData) {
data.push(doc);
TabDocView.PinDoc(doc, false);
- this.gotoDocument(this.childDocs.length, this.itemIndex);
+ this.gotoDocument(this.childDocs.length);
} else {
this.props.addDocTab(doc, "add:right");
}
@@ -1255,10 +1437,10 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
@computed get presentDropdown() {
return (
<div className={`dropdown-play ${this.presentTools ? "active" : ""}`} onClick={e => e.stopPropagation()} onPointerUp={e => e.stopPropagation()} onPointerDown={e => e.stopPropagation()}>
- <div className="dropdown-play-button" onClick={(action(() => { this.updateMinimize(); this.turnOffEdit(true); }))}>
+ <div className="dropdown-play-button" onClick={undoBatch(action(() => { this.updateMinimize(); this.turnOffEdit(true); }))}>
Minimize
</div>
- <div className="dropdown-play-button" onClick={(action(() => { this.layoutDoc.presStatus = "manual"; this.turnOffEdit(true); }))}>
+ <div className="dropdown-play-button" onClick={undoBatch(action(() => { this.layoutDoc.presStatus = "manual"; this.turnOffEdit(true); }))}>
Sidebar view
</div>
</div>
@@ -1266,7 +1448,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
}
// Case in which the document has keyframes to navigate to next key frame
- @undoBatch
@action
nextKeyframe = (tagDoc: Doc, curDoc: Doc): void => {
const childDocs = DocListCast(tagDoc[Doc.LayoutFieldKey(tagDoc)]);
@@ -1282,7 +1463,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
tagDoc.lastFrame = Math.max(NumCast(tagDoc._currentFrame), NumCast(tagDoc.lastFrame));
}
- @undoBatch
@action
prevKeyframe = (tagDoc: Doc, actItem: Doc): void => {
const childDocs = DocListCast(tagDoc[Doc.LayoutFieldKey(tagDoc)]);
@@ -1604,7 +1784,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
return tags;
}
- @undoBatch
@action
nextAppearFrame = (doc: Doc, i: number): void => {
// const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null);
@@ -1617,7 +1796,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
this.updateOpacityList(doc["opacity-indexed"], NumCast(doc.appearFrame));
}
- @undoBatch
@action
prevAppearFrame = (doc: Doc, i: number): void => {
// const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null);
@@ -1678,30 +1856,43 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
const propIcon = CurrentUserUtils.propertiesWidth > 0 ? "angle-double-right" : "angle-double-left";
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);
return (mode === CollectionViewType.Carousel3D) ? (null) : (
- <div id="toolbarContainer" className={'presBox-toolbar'} style={{ display: this.layoutDoc.presStatus === "edit" ? "inline-flex" : "none" }}>
+ <div id="toolbarContainer" className={'presBox-toolbar'}>
{/* <Tooltip title={<><div className="dash-tooltip">{"Add new slide"}</div></>}><div className={`toolbar-button ${this.newDocumentTools ? "active" : ""}`} onClick={action(() => this.newDocumentTools = !this.newDocumentTools)}>
<FontAwesomeIcon icon={"plus"} />
<FontAwesomeIcon className={`dropdown ${this.newDocumentTools ? "active" : ""}`} icon={"angle-down"} />
</div></Tooltip> */}
<Tooltip title={<><div className="dash-tooltip">{"View paths"}</div></>}>
- <div style={{ opacity: this.childDocs.length > 1 ? 1 : 0.3 }} className={`toolbar-button ${this.pathBoolean ? "active" : ""}`} onClick={this.childDocs.length > 1 ? this.viewPaths : undefined}>
+ <div style={{ opacity: this.childDocs.length > 1 ? 1 : 0.3, color: this._pathBoolean ? PresColors.DarkBlue : 'white', width: isMini ? "100%" : undefined }} className={"toolbar-button"} onClick={this.childDocs.length > 1 ? this.viewPaths : undefined}>
<FontAwesomeIcon icon={"exchange-alt"} />
</div>
</Tooltip>
- <div className="toolbar-divider" />
- <Tooltip title={<><div className="dash-tooltip">{this.rootDoc.expandBoolean ? "Minimize all" : "Expand all"}</div></>}>
- <div className={`toolbar-button ${this.rootDoc.expandBoolean ? "active" : ""}`} onClick={this.toggleExpandMode}>
- {/* <FontAwesomeIcon icon={this.rootDoc.expandBoolean ? "eye-slash" : "eye"} /> */}
- <FontAwesomeIcon icon={"eye"} />
- </div>
- </Tooltip>
- <div className="toolbar-divider" />
- <Tooltip title={<><div className="dash-tooltip">{propTitle}</div></>}>
- <div className="toolbar-button" style={{ position: 'absolute', right: 4, fontSize: 16 }} onClick={this.toggleProperties}>
- <FontAwesomeIcon className={"toolbar-thumbtack"} icon={propIcon} style={{ color: CurrentUserUtils.propertiesWidth > 0 ? '#AEDDF8' : 'white' }} />
- </div>
- </Tooltip>
+ {isMini ? (null) :
+ <>
+ <div className="toolbar-divider" />
+ <Tooltip title={<><div className="dash-tooltip">{this._expandBoolean ? "Minimize all" : "Expand all"}</div></>}>
+ <div className={"toolbar-button"}
+ style={{ color: this._expandBoolean ? PresColors.DarkBlue : 'white' }}
+ onClick={this.toggleExpandMode}>
+ {/* <FontAwesomeIcon icon={this.rootDoc.expandBoolean ? "eye-slash" : "eye"} /> */}
+ <FontAwesomeIcon icon={"eye"} />
+ </div>
+ </Tooltip>
+ <div className="toolbar-divider" />
+ <Tooltip title={<><div className="dash-tooltip">{presKeyEvents ? "Keys are active" : "Keys are not active - click anywhere on the presentation trail to activate keys"}</div></>}>
+ <div className="toolbar-button" style={{ cursor: presKeyEvents ? 'default' : 'pointer', position: 'absolute', right: 30, fontSize: 16 }}>
+ <FontAwesomeIcon className={"toolbar-thumbtack"} icon={"keyboard"} style={{ color: presKeyEvents ? PresColors.DarkBlue : 'white' }} />
+ </div>
+ </Tooltip>
+ <Tooltip title={<><div className="dash-tooltip">{propTitle}</div></>}>
+ <div className="toolbar-button" style={{ position: 'absolute', right: 4, fontSize: 16 }} onClick={this.toggleProperties}>
+ <FontAwesomeIcon className={"toolbar-thumbtack"} icon={propIcon} style={{ color: CurrentUserUtils.propertiesWidth > 0 ? PresColors.DarkBlue : 'white' }} />
+ </div>
+ </Tooltip>
+ </>
+ }
</div>
);
}
@@ -1713,25 +1904,26 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
*/
@computed get topPanel() {
const mode = StrCast(this.rootDoc._viewType) as CollectionViewType;
+ const isMini: boolean = this.toolbarWidth <= 100;
return (
<div className="presBox-buttons" style={{ display: this.rootDoc._chromeStatus === "disabled" ? "none" : undefined }}>
- <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>
- </select>
- <div className="presBox-presentPanel" style={{ opacity: this.childDocs.length > 0 ? 1 : 0.3 }}>
+ </select>}
+ <div className="presBox-presentPanel" style={{ opacity: this.childDocs.length ? 1 : 0.3 }}>
<span className={`presBox-button ${this.layoutDoc.presStatus === "edit" ? "present" : ""}`}>
- <div className="presBox-button-left" onClick={() => (this.childDocs.length > 0) && (this.layoutDoc.presStatus = "manual")}>
+ <div className="presBox-button-left" onClick={undoBatch(() => (this.childDocs.length) && (this.layoutDoc.presStatus = "manual"))}>
<FontAwesomeIcon icon={"play-circle"} />
<div style={{ display: this.props.PanelWidth() > 200 ? "inline-flex" : "none" }}>&nbsp; Present</div>
</div>
- {(mode === CollectionViewType.Carousel3D) ? (null) : <div className={`presBox-button-right ${this.presentTools ? "active" : ""}`}
+ {(mode === CollectionViewType.Carousel3D || isMini) ? (null) : <div className={`presBox-button-right ${this.presentTools ? "active" : ""}`}
onClick={(action(() => {
- if (this.childDocs.length > 0) this.presentTools = !this.presentTools;
+ if (this.childDocs.length) this.presentTools = !this.presentTools;
}))}>
<FontAwesomeIcon className="dropdown" style={{ margin: 0, transform: this.presentTools ? 'rotate(180deg)' : 'rotate(0deg)' }} icon={"angle-down"} />
{this.presentDropdown}
@@ -1825,19 +2017,19 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
@computed get playButtons() {
// Case 1: There are still other frames and should go through all frames before going to next slide
return (<div className="presPanelOverlay" style={{ display: this.layoutDoc.presStatus !== "edit" ? "inline-flex" : "none" }}>
- <Tooltip title={<><div className="dash-tooltip">{"Loop"}</div></>}><div className="presPanel-button" style={{ color: this.layoutDoc.presLoop ? '#AEDDF8' : 'white' }} 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 ? PresColors.DarkBlue : 'white' }} onClick={() => this.layoutDoc.presLoop = !this.layoutDoc.presLoop}><FontAwesomeIcon icon={"redo-alt"} /></div></Tooltip>
<div className="presPanel-divider"></div>
- <div className="presPanel-button" onClick={this.back}><FontAwesomeIcon icon={"arrow-left"} /></div>
- <Tooltip title={<><div className="dash-tooltip">{this.layoutDoc.presStatus === "auto" ? "Pause" : "Autoplay"}</div></>}><div className="presPanel-button" onClick={this.startOrPause}><FontAwesomeIcon icon={this.layoutDoc.presStatus === "auto" ? "pause" : "play"} /></div></Tooltip>
- <div className="presPanel-button" onClick={this.next}><FontAwesomeIcon icon={"arrow-right"} /></div>
+ <div className="presPanel-button" 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 === PresStatus.Autoplay ? "pause" : "play"} /></div></Tooltip>
+ <div className="presPanel-button" onClick={() => { this.next(); if (this._presTimer) { clearTimeout(this._presTimer); this.layoutDoc.presStatus = PresStatus.Manual; } }}><FontAwesomeIcon icon={"arrow-right"} /></div>
<div className="presPanel-divider"></div>
<div className="presPanel-button-text" style={{ display: this.props.PanelWidth() > 250 ? "inline-flex" : "none" }}>
Slide {this.itemIndex + 1} / {this.childDocs.length}
{this.playButtonFrames}
</div>
<div className="presPanel-divider"></div>
- {this.props.PanelWidth() > 250 ? <div className="presPanel-button-text" onClick={() => { this.layoutDoc.presStatus = "edit"; clearTimeout(this._presTimer); }}>EXIT</div>
- : <div className="presPanel-button" onClick={() => this.layoutDoc.presStatus = "edit"}>
+ {this.props.PanelWidth() > 250 ? <div className="presPanel-button-text" onClick={undoBatch(action(() => { this.layoutDoc.presStatus = "edit"; clearTimeout(this._presTimer); }))}>EXIT</div>
+ : <div className="presPanel-button" onClick={undoBatch(action(() => this.layoutDoc.presStatus = "edit"))}>
<FontAwesomeIcon icon={"times"} />
</div>}
</div>);
@@ -1845,7 +2037,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
@action
startOrPause = () => {
- if (this.layoutDoc.presStatus === "manual" || this.layoutDoc.presStatus === "edit") this.startAutoPres(this.itemIndex);
+ if (this.layoutDoc.presStatus === PresStatus.Manual || this.layoutDoc.presStatus === PresStatus.Edit) this.startAutoPres(this.itemIndex);
else this.pauseAutoPres();
}
@@ -1855,25 +2047,26 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
// needed to ensure that the childDocs are loaded for looking up fields
this.childDocs.slice();
const mode = StrCast(this.rootDoc._viewType) as CollectionViewType;
- return this.layoutDoc.inOverlay ?
+ const presKeyEvents: boolean = (this.isPres && this._presKeyEventsActive && this.rootDoc === Doc.UserDoc().activePresentation);
+ return CurrentUserUtils.OverlayDocs.includes(this.rootDoc) ?
<div className="miniPres">
- <div className="presPanelOverlay" style={{ display: "inline-flex", height: 35, background: '#323232', top: 0, zIndex: 3000000 }}>
- <Tooltip title={<><div className="dash-tooltip">{"Loop"}</div></>}><div className="presPanel-button" style={{ color: this.layoutDoc.presLoop ? '#AEDDF8' : undefined }} onClick={() => this.layoutDoc.presLoop = !this.layoutDoc.presLoop}><FontAwesomeIcon icon={"redo-alt"} /></div></Tooltip>
+ <div className="presPanelOverlay" style={{ display: "inline-flex", height: 30, background: '#323232', top: 0, zIndex: 3000000, boxShadow: presKeyEvents ? '0 0 0px 3px ' + PresColors.DarkBlue : undefined }}>
+ <Tooltip title={<><div className="dash-tooltip">{"Loop"}</div></>}><div className="presPanel-button" style={{ color: this.layoutDoc.presLoop ? PresColors.DarkBlue : undefined }} onClick={() => this.layoutDoc.presLoop = !this.layoutDoc.presLoop}><FontAwesomeIcon icon={"redo-alt"} /></div></Tooltip>
<div className="presPanel-divider"></div>
- <div className="presPanel-button" onClick={this.back}><FontAwesomeIcon icon={"arrow-left"} /></div>
- <Tooltip title={<><div className="dash-tooltip">{this.layoutDoc.presStatus === "auto" ? "Pause" : "Autoplay"}</div></>}><div className="presPanel-button" onClick={this.startOrPause}><FontAwesomeIcon icon={this.layoutDoc.presStatus === "auto" ? "pause" : "play"} /></div></Tooltip>
- <div className="presPanel-button" onClick={this.next}><FontAwesomeIcon icon={"arrow-right"} /></div>
+ <div className="presPanel-button" 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" onClick={() => { this.next(); if (this._presTimer) { clearTimeout(this._presTimer); this.layoutDoc.presStatus = PresStatus.Manual; } }}><FontAwesomeIcon icon={"arrow-right"} /></div>
<div className="presPanel-divider"></div>
<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={() => { this.updateMinimize(); this.layoutDoc.presStatus = "edit"; clearTimeout(this._presTimer); }}>EXIT</div>
+ <div className="presPanel-button-text" onClick={undoBatch(action(() => { this.updateMinimize(); this.layoutDoc.presStatus = PresStatus.Edit; clearTimeout(this._presTimer); }))}>EXIT</div>
</div>
</div>
:
- <div className="presBox-cont" style={{ minWidth: this.layoutDoc.inOverlay ? 240 : undefined }} >
+ <div className="presBox-cont" style={{ minWidth: CurrentUserUtils.OverlayDocs.includes(this.layoutDoc) ? 240 : undefined }} >
{this.topPanel}
{this.toolbar}
{this.newDocumentToolbarDropdown}
@@ -1900,7 +2093,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
}
Scripting.addGlobal(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 ? 30 : 26;
+ 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;