aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/trails/PresBox.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/nodes/trails/PresBox.tsx')
-rw-r--r--src/client/views/nodes/trails/PresBox.tsx186
1 files changed, 94 insertions, 92 deletions
diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx
index 0c4d514cd..7cb976105 100644
--- a/src/client/views/nodes/trails/PresBox.tsx
+++ b/src/client/views/nodes/trails/PresBox.tsx
@@ -5,8 +5,8 @@ import { action, computed, IReactionDisposer, observable, ObservableSet, reactio
import { observer } from 'mobx-react';
import { ColorState, SketchPicker } from 'react-color';
import { Bounce, Fade, Flip, LightSpeed, Roll, Rotate, Zoom } from 'react-reveal';
-import { Doc, DocListCast, DocListCastAsync, FieldResult, Opt } from '../../../../fields/Doc';
-import { Copy } from '../../../../fields/FieldSymbols';
+import { Doc, DocListCast, DocListCastAsync, FieldResult, Opt, StrListCast } from '../../../../fields/Doc';
+import { Copy, Id } from '../../../../fields/FieldSymbols';
import { InkTool } from '../../../../fields/InkField';
import { List } from '../../../../fields/List';
import { ObjectField } from '../../../../fields/ObjectField';
@@ -31,19 +31,17 @@ import { CollectionFreeFormDocumentView } from '../CollectionFreeFormDocumentVie
import { FieldView, FieldViewProps } from '../FieldView';
import './PresBox.scss';
import { PresEffect, PresMovement, PresStatus } from './PresEnums';
+import { privateEncrypt } from 'crypto';
+import { ScriptingBox } from '../ScriptingBox';
+import { DocServer } from '../../../DocServer';
export interface PinProps {
audioRange?: boolean;
activeFrame?: number;
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;
+ pinViewport?: MarqueeViewBounds; // pin a specific viewport on a freeform view (use MarqueeView.CurViewBounds to compute if no region has been selected)
+ pinDocLayout?: boolean; // pin layout info (width/height/x/y)
+ pinDocContent?: boolean; // pin data info (scroll/pan/zoom/text)
}
@observer
@@ -268,6 +266,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
// Case 3: Last slide and presLoop is toggled ON or it is in Edit mode
this.nextSlide(0);
}
+ return this.itemIndex;
};
// Called when the user activates 'back' - to move to the previous part of the pres. trail
@@ -298,6 +297,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
// Case 3: Pres loop is on so it should go to the last slide
this.gotoDocument(this.childDocs.length - 1, activeItem);
}
+ return this.itemIndex;
};
//The function that is called when a document is clicked or reached through next or back.
@@ -351,16 +351,17 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
const pannable = [DocumentType.IMG].includes(target.type as any) || (target.type === DocumentType.COL && target._viewType === CollectionViewType.Freeform);
const temporal = [DocumentType.AUDIO, DocumentType.VID].includes(target.type as any);
const clippable = [DocumentType.COMPARISON].includes(target.type as any);
- const dataview = [DocumentType.INK].includes(target.type as any) && target.activeFrame === undefined;
+ const dataview = [DocumentType.INK, DocumentType.COL].includes(target.type as any) && target.activeFrame === undefined;
+ const poslayoutview = [DocumentType.COL].includes(target.type as any) && target.activeFrame === undefined;
const textview = [DocumentType.RTF].includes(target.type as any) && target.activeFrame === undefined;
- return { scrollable, pannable, temporal, clippable, dataview, textview };
+ return { scrollable, pannable, temporal, clippable, dataview, textview, poslayoutview };
}
@action
static restoreTargetDocView(bestTarget: Doc, activeItem: Doc) {
const transTime = NumCast(activeItem.presTransition, 500);
const presTransitionTime = `all ${transTime}ms`;
- const { scrollable, pannable, temporal, clippable, dataview, textview } = this.pinDataTypes(bestTarget);
+ const { scrollable, pannable, temporal, clippable, dataview, textview, poslayoutview } = this.pinDataTypes(bestTarget);
bestTarget._viewTransition = presTransitionTime;
if (clippable) bestTarget._clipWidth = activeItem.presPinClipWidth;
if (temporal) bestTarget._currentTimecode = activeItem.presStartTime;
@@ -372,8 +373,32 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
dv?.brushView?.({ panX: (contentBounds[0] + contentBounds[2]) / 2, panY: (contentBounds[1] + contentBounds[3]) / 2, width: contentBounds[2] - contentBounds[0], height: contentBounds[3] - contentBounds[1] });
}
}
- if (dataview) Doc.GetProto(bestTarget).data = activeItem.presData instanceof ObjectField ? activeItem.presData[Copy]() : activeItem.presData;
- if (textview) Doc.GetProto(bestTarget).text = activeItem.presData instanceof ObjectField ? activeItem.presData[Copy]() : activeItem.presData;
+ if (dataview) Doc.GetProto(bestTarget)[Doc.LayoutFieldKey(bestTarget)] = activeItem.presData instanceof ObjectField ? activeItem.presData[Copy]() : activeItem.presData;
+ if (textview) Doc.GetProto(bestTarget)[Doc.LayoutFieldKey(bestTarget)] = activeItem.presData instanceof ObjectField ? activeItem.presData[Copy]() : activeItem.presData;
+ if (poslayoutview) {
+ StrListCast(activeItem.presPinLayoutData)
+ .map(str => JSON.parse(str) as { id: string; x: number; y: number; w: number; h: number })
+ .forEach(data => {
+ const doc = DocServer.GetCachedRefField(data.id) as Doc;
+ doc._dataTransition = presTransitionTime;
+ doc.x = data.x;
+ doc.y = data.y;
+ doc._width = data.w;
+ doc._height = data.h;
+ });
+ setTimeout(
+ () =>
+ StrListCast(activeItem.presPinLayoutData)
+ .map(str => JSON.parse(str) as { id: string; x: number; y: number; w: number; h: number })
+ .forEach(
+ action(data => {
+ const doc = DocServer.GetCachedRefField(data.id) as Doc;
+ doc._dataTransition = undefined;
+ })
+ ),
+ transTime + 10
+ );
+ }
if (pannable) {
const contentBounds = Cast(activeItem.presPinViewBounds, listSpec('number'));
if (contentBounds) {
@@ -383,7 +408,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
const dv = DocumentManager.Instance.getDocumentView(bestTarget);
if (dv) {
const computedScale = NumCast(activeItem.presZoom, 1) * Math.min(dv.props.PanelWidth() / viewport.width, dv.props.PanelHeight() / viewport.height);
- activeItem.presMovement === 'zoom' && (bestTarget._viewScale = activeItem.presZoom !== undefined ? computedScale : Math.min(computedScale, NumCast(bestTarget._viewScale)));
+ activeItem.presMovement === 'zoom' && (bestTarget._viewScale = computedScale);
dv.ComponentView?.brushView?.(viewport);
}
} else {
@@ -400,47 +425,41 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
/// target doc when navigating to it.
@action
static pinDocView(pinDoc: Doc, pinProps: PinProps | undefined, targetDoc: Doc) {
- if (pinProps?.pinWithView) {
- // If pinWithView option set then update scale and x / y props of slide
- const bounds = pinProps.pinWithView.bounds;
- pinDoc.presPinView = true;
- pinDoc.presPinViewX = bounds.left + bounds.width / 2;
- pinDoc.presPinViewY = bounds.top + bounds.height / 2;
- pinDoc.presPinViewBounds = new List<number>([bounds.left, bounds.top, bounds.left + bounds.width, bounds.top + bounds.height]);
- }
- if (pinProps?.pinDocView) {
- const { scrollable, pannable, temporal, clippable, dataview, textview } = this.pinDataTypes(pinDoc);
- pinDoc.presPinView = (pinProps?.pinWithView ? true : false) || scrollable || temporal || pannable || clippable || dataview || textview || pinProps.activeFrame !== undefined;
+ const { scrollable, pannable, temporal, clippable, dataview, textview, poslayoutview } = this.pinDataTypes(pinDoc);
+ if (pinProps?.pinDocLayout) {
+ pinDoc.presPinLayout = true;
pinDoc.presX = NumCast(targetDoc.x);
pinDoc.presY = NumCast(targetDoc.y);
pinDoc.presRot = NumCast(targetDoc.jitterRotation);
pinDoc.presWidth = NumCast(targetDoc.width);
pinDoc.presHeight = NumCast(targetDoc.height);
-
- if (scrollable) {
- pinDoc.presPinViewScroll = pinDoc._scrollTop;
- }
+ }
+ if (pinProps?.pinDocContent) {
+ pinDoc.presPinData = scrollable || temporal || pannable || clippable || dataview || textview || poslayoutview || pinProps.activeFrame !== undefined;
+ if (dataview) pinDoc.presData = targetDoc[Doc.LayoutFieldKey(targetDoc)] instanceof ObjectField ? (targetDoc[Doc.LayoutFieldKey(targetDoc)] as ObjectField)[Copy]() : targetDoc.data;
+ if (textview) pinDoc.presData = targetDoc[Doc.LayoutFieldKey(targetDoc)] instanceof ObjectField ? (targetDoc[Doc.LayoutFieldKey(targetDoc)] as ObjectField)[Copy]() : targetDoc.text;
+ if (scrollable) pinDoc.presPinViewScroll = pinDoc._scrollTop;
if (clippable) pinDoc.presPinClipWidth = pinDoc._clipWidth;
+ if (poslayoutview) pinDoc.presPinLayoutData = new List<string>(DocListCast(pinDoc.presData).map(d => JSON.stringify({ id: d[Id], x: NumCast(d.x), y: NumCast(d.y), w: NumCast(d._width), h: NumCast(d._height) })));
+ if (pannable) {
+ pinDoc.presPinViewX = NumCast(pinDoc._panX);
+ pinDoc.presPinViewY = NumCast(pinDoc._panY);
+ pinDoc.presPinViewScale = NumCast(pinDoc._viewScale, 1);
+ }
if (temporal) {
pinDoc.presStartTime = pinDoc._currentTimecode;
const duration = NumCast(pinDoc[`${Doc.LayoutFieldKey(pinDoc)}-duration`], NumCast(pinDoc.presStartTime) + 0.1);
pinDoc.presEndTime = NumCast(pinDoc.clipEnd, duration);
}
- if (textview) pinDoc.presData = targetDoc.text instanceof ObjectField ? targetDoc.text[Copy]() : targetDoc.text;
- if (dataview) pinDoc.presData = targetDoc.data instanceof ObjectField ? targetDoc.data[Copy]() : targetDoc.data;
- if (pannable || scrollable) {
- const panX = NumCast(pinDoc._panX);
- const panY = NumCast(pinDoc._panY);
- const pw = NumCast(pinProps.panelWidth);
- const ph = NumCast(pinProps.panelHeight);
- const ps = NumCast(pinDoc._viewScale, 1);
- if (pw && ph && ps) {
- pinDoc.presPinViewBounds = new List<number>([panX - pw / 2 / ps, panY - ph / 2 / ps, panX + pw / 2 / ps, panY + ph / 2 / ps]);
- }
- pinDoc.presPinViewX = panX;
- pinDoc.presPinViewY = panY;
- pinDoc.presPinViewScale = ps;
- }
+ }
+ if (pinProps?.pinViewport) {
+ // If pinWithView option set then update scale and x / y props of slide
+ const bounds = pinProps.pinViewport;
+ pinDoc.presPinView = true;
+ pinDoc.presPinViewScale = NumCast(pinDoc._viewScale, 1);
+ pinDoc.presPinViewX = bounds.left + bounds.width / 2;
+ pinDoc.presPinViewY = bounds.top + bounds.height / 2;
+ pinDoc.presPinViewBounds = new List<number>([bounds.left, bounds.top, bounds.left + bounds.width, bounds.top + bounds.height]);
}
}
@@ -497,7 +516,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
};
static NavigateToTarget(targetDoc: Doc, activeItem: Doc, openInTab: any, srcContext: Doc, finished?: () => void) {
- if (activeItem.presPinView && DocCast(targetDoc.context)?._currentFrame === undefined) {
+ if ((activeItem.presPinLayout || activeItem.presPinView) && DocCast(targetDoc.context)?._currentFrame === undefined) {
const transTime = NumCast(activeItem.presTransition, 500);
const presTransitionTime = `all ${transTime}ms`;
targetDoc._dataTransition = presTransitionTime;
@@ -514,11 +533,13 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
} else if (targetDoc && activeItem.presMovement !== PresMovement.None) {
LightboxView.SetLightboxDoc(undefined);
const zooming = activeItem.presMovement !== PresMovement.Pan;
- DocumentManager.Instance.jumpToDocument(targetDoc, zooming, openInTab, srcContext ? [srcContext] : [], undefined, undefined, undefined, finished, undefined, true, NumCast(activeItem.presZoom));
+ DocumentManager.Instance.jumpToDocument(targetDoc, zooming, openInTab, srcContext ? [srcContext] : [], undefined, undefined, undefined, finished, undefined, true, NumCast(activeItem.presZoom, 1));
+ } else if (activeItem.presMovement === PresMovement.None && targetDoc.type === DocumentType.SCRIPTING) {
+ (DocumentManager.Instance.getFirstDocumentView(targetDoc)?.ComponentView as ScriptingBox)?.onRun?.();
}
// 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) {
+ if (activeItem.presPinData || activeItem.presPinView) {
clearTimeout(PresBox._navTimer);
// targetDoc may or may not be displayed. this gets the first available document (or alias) view that matches targetDoc
const bestTarget = DocumentManager.Instance.getFirstDocumentView(targetDoc)?.props.Document;
@@ -615,42 +636,19 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
//The function that starts or resets presentaton functionally, depending on presStatus of the layoutDoc
@action
startAutoPres = (startSlide: number) => {
- this.updateCurrentPresentation();
- let activeItem: Doc = this.activeItem;
- let targetDoc: Doc = this.targetDoc;
- let duration = NumCast(activeItem.presDuration) + NumCast(activeItem.presTransition);
- const timer = (ms: number) => new Promise(res => (this._presTimer = setTimeout(res, ms)));
- const load = async () => {
- // Wrap the loop into an async function for this to work
- for (var i = startSlide; i < this.childDocs.length; i++) {
- activeItem = Cast(this.childDocs[this.itemIndex], Doc, null);
- targetDoc = Cast(activeItem.presentationTargetDoc, Doc, null);
- duration = NumCast(activeItem.presDuration) + NumCast(activeItem.presTransition);
- if (duration < 100) {
- duration = 2500;
- }
- if (NumCast(targetDoc.lastFrame) > 0) {
- for (var f = 0; f < NumCast(targetDoc.lastFrame); f++) {
- await timer(duration / NumCast(targetDoc.lastFrame));
- this.next();
- }
- }
-
- await timer(duration);
- this.next(); // then the created Promise can be awaited
- if (i === this.childDocs.length - 1) {
- setTimeout(() => {
- clearTimeout(this._presTimer);
- if (this.layoutDoc.presStatus === 'auto' && !this.layoutDoc.presLoop) this.layoutDoc.presStatus = PresStatus.Manual;
- else if (this.layoutDoc.presLoop) this.startAutoPres(0);
- }, duration);
- }
- }
- };
this.layoutDoc.presStatus = PresStatus.Autoplay;
this.startPresentation(startSlide);
- this.gotoDocument(startSlide, activeItem);
- load();
+ clearTimeout(this._presTimer);
+ const func = (itemIndex: number) => {
+ if (itemIndex === this.next()) this.layoutDoc.presStatus = PresStatus.Manual;
+ else
+ this._presTimer = setTimeout(
+ () => this.layoutDoc.presStatus !== PresStatus.Manual && func(this.itemIndex),
+ NumCast(this.activeItem.presDuration, this.activeItem.type === DocumentType.SCRIPTING ? 0 : 2500) + NumCast(this.activeItem.presTransition)
+ );
+ };
+
+ func(this.itemIndex);
};
// The function pauses the auto presentation
@@ -659,7 +657,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
if (this.layoutDoc.presStatus === PresStatus.Autoplay) {
if (this._presTimer) clearTimeout(this._presTimer);
this.layoutDoc.presStatus = PresStatus.Manual;
- this.layoutDoc.presLoop = false;
this.childDocs.forEach(this.stopTempMedia);
}
};
@@ -667,7 +664,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
//The function that resets the presentation by removing every action done by it. It also
//stops the presentaton.
resetPresentation = () => {
- this.rootDoc._itemIndex = 0;
this.childDocs
.map(doc => Cast(doc.presentationTargetDoc, Doc, null))
.filter(doc => doc instanceof Doc)
@@ -706,8 +702,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
* @param startIndex: index that the presentation will start at
*/
startPresentation = (startIndex: number) => {
- this.updateCurrentPresentation();
- this.childDocs.map(doc => {
+ this.childDocs.forEach(doc => {
const tagDoc = doc.presentationTargetDoc as Doc;
if (doc.presHideBefore && this.childDocs.indexOf(doc) > startIndex) {
tagDoc.opacity = 0;
@@ -716,6 +711,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
tagDoc.opacity = 0;
}
});
+ this.gotoDocument(startIndex, this.activeItem);
};
/**
@@ -996,7 +992,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
break;
case 'Spacebar':
case ' ':
- if (this.layoutDoc.presStatus === PresStatus.Manual) this.startAutoPres(this.itemIndex);
+ if (this.layoutDoc.presStatus === PresStatus.Manual) this.startOrPause(true);
else if (this.layoutDoc.presStatus === PresStatus.Autoplay) if (this._presTimer) clearTimeout(this._presTimer);
handled = true;
break;
@@ -1254,7 +1250,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
if (activeItem && targetDoc) {
const type = targetDoc.type;
const transitionSpeed = activeItem.presTransition ? NumCast(activeItem.presTransition) / 1000 : 0.5;
- const zoom = activeItem.presZoom ? NumCast(activeItem.presZoom) * 100 : 75;
+ const zoom = NumCast(activeItem.presZoom, 1) * 100;
let duration = activeItem.presDuration ? NumCast(activeItem.presDuration) / 1000 : 2;
if (activeItem.type === DocumentType.AUDIO) duration = NumCast(activeItem.duration);
const effect = this.activeItem.presEffect ? this.activeItem.presEffect : 'None';
@@ -1808,6 +1804,11 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
);
}
+ scrollFocus = () => {
+ this.startOrPause(false);
+ return undefined;
+ };
+
// Case in which the document has keyframes to navigate to next key frame
@action
nextKeyframe = (tagDoc: Doc, curDoc: Doc): void => {
@@ -2480,7 +2481,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
<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}>
+ <div className="presPanel-button" onClick={e => this.startOrPause(true)}>
<FontAwesomeIcon icon={this.layoutDoc.presStatus === PresStatus.Autoplay ? 'pause' : 'play'} />
</div>
</Tooltip>
@@ -2529,7 +2530,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
}
@action
- startOrPause = () => {
+ startOrPause = (makeActive = true) => {
+ makeActive && this.updateCurrentPresentation();
if (this.layoutDoc.presStatus === PresStatus.Manual || this.layoutDoc.presStatus === PresStatus.Edit) this.startAutoPres(this.itemIndex);
else this.pauseAutoPres();
};
@@ -2613,7 +2615,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
<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)}>
+ <div className="presPanel-button" onPointerDown={e => setupMoveUpEvents(this, e, returnFalse, returnFalse, () => this.startOrPause(true), false, false)}>
<FontAwesomeIcon icon={this.layoutDoc.presStatus === 'auto' ? 'pause' : 'play'} />
</div>
</Tooltip>