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.tsx358
1 files changed, 86 insertions, 272 deletions
diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx
index 05e09361b..eb40089ec 100644
--- a/src/client/views/nodes/trails/PresBox.tsx
+++ b/src/client/views/nodes/trails/PresBox.tsx
@@ -358,20 +358,24 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
if (bestTarget) this._navTimer = PresBox.navigateToDoc(bestTarget, activeItem, false);
};
+ static pinDataTypes(target: Doc) {
+ const scrollable = [DocumentType.PDF, DocumentType.RTF, DocumentType.WEB].includes(target.type as any) || target._viewType === CollectionViewType.Stacking;
+ 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);
+ return { scrollable, pannable, temporal, clippable };
+ }
// navigates to the bestTarget document by making sure it is on screen,
// then it applies the view specs stored in activeItem to
@action
static navigateToDoc(bestTarget: Doc, activeItem: Doc, jumpToDoc: boolean) {
- if (bestTarget.type === DocumentType.PDF || bestTarget.type === DocumentType.WEB || bestTarget.type === DocumentType.RTF || bestTarget._viewType === CollectionViewType.Stacking) {
- bestTarget._viewTransition = activeItem.presTransition ? `transform ${activeItem.presTransition}ms` : 'all 0.5s';
- bestTarget._scrollTop = activeItem.presPinViewScroll;
- } else if (bestTarget.type === DocumentType.COMPARISON) {
- bestTarget._clipWidth = activeItem.presPinClipWidth;
- } else if ([DocumentType.AUDIO, DocumentType.VID].includes(bestTarget.type as any)) {
- bestTarget._currentTimecode = activeItem.presStartTime;
- } else {
+ bestTarget._viewTransition = activeItem.presTransition ? `transform ${activeItem.presTransition}ms` : 'all 0.5s';
+ const { scrollable, pannable, temporal, clippable } = this.pinDataTypes(bestTarget);
+ if (clippable) bestTarget._clipWidth = activeItem.presPinClipWidth;
+ if (temporal) bestTarget._currentTimecode = activeItem.presStartTime;
+ if (scrollable) bestTarget._scrollTop = activeItem.presPinViewScroll;
+ if (pannable) {
const contentBounds = Cast(activeItem.contentBounds, listSpec('number'));
- bestTarget._viewTransition = activeItem.presTransition ? `transform ${activeItem.presTransition}ms` : 'all 0.5s';
if (contentBounds) {
bestTarget._panX = (contentBounds[0] + contentBounds[2]) / 2;
bestTarget._panY = (contentBounds[1] + contentBounds[3]) / 2;
@@ -388,6 +392,43 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
return setTimeout(() => (bestTarget._viewTransition = undefined), activeItem.presTransition ? NumCast(activeItem.presTransition) + 10 : 510);
}
+ /// copies values from the targetDoc (which is the prototype of the pinDoc) to
+ /// reserved fields on the pinDoc so that those values can be restored to the
+ /// target doc when navigating to it.
+ @action
+ static pinDocView(pinDoc: Doc, pinProps: PinProps | undefined) {
+ 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.presPinViewScale = pinProps.pinWithView.scale;
+ pinDoc.contentBounds = new List<number>([bounds.left, bounds.top, bounds.left + bounds.width, bounds.top + bounds.height]);
+ }
+ if (pinProps?.pinDocView) {
+ const { scrollable, pannable, temporal, clippable } = this.pinDataTypes(pinDoc);
+ pinDoc.presPinView = (pinProps?.pinWithView ? true : false) || scrollable || temporal || pannable || clippable;
+
+ if (scrollable) pinDoc.presPinViewScroll = pinDoc._scrollTop;
+ else if (clippable) pinDoc.presPinClipWidth = pinDoc._clipWidth;
+ else if (temporal) pinDoc.presEndTime = NumCast((pinDoc.presStartTime = pinDoc._currentTimecode)) + 0.1;
+ else if (pannable) {
+ 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);
+ if (pw && ph && ps) {
+ pinDoc.contentBounds = 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;
+ }
+ }
+ }
+
/**
* This method makes sure that cursor navigates to the element that
* has the option open and last in the group.
@@ -1540,26 +1581,15 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
}
}
- @computed get effectDirection(): string {
- let effect = '';
+ @computed get effectDirection() {
+ // prettier-ignore
switch (this.activeItem.presEffectDirection) {
- case 'left':
- effect = 'Enter from left';
- break;
- case 'right':
- effect = 'Enter from right';
- break;
- case 'top':
- effect = 'Enter from top';
- break;
- case 'bottom':
- effect = 'Enter from bottom';
- break;
- default:
- effect = 'Enter from center';
- break;
+ case 'left': return 'Enter from left';
+ case 'right': return 'Enter from right';
+ case 'top': return'Enter from top';
+ case 'bottom': return 'Enter from bottom';
}
- return effect;
+ return 'Enter from center';
}
@undoBatch
@@ -1582,179 +1612,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
});
};
- @computed get presPinViewOptionsDropdown() {
- const activeItem: Doc = this.activeItem;
- const targetDoc: Doc = this.targetDoc;
- const presPinWithViewIcon = <img src="/assets/pinWithView.png" style={{ margin: 'auto', width: 16, filter: 'invert(1)' }} />;
- return (
- <>
- {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 ? Colors.LIGHT_BLUE : '' }}
- 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 ([DocumentType.AUDIO, DocumentType.VID].includes(targetDoc.type as any)) {
- activeItem.presStartTime = targetDoc._currentTimecode;
- activeItem.presEndTime = NumCast(targetDoc._currentTimecode) + 0.1;
- } else if ((targetDoc.type === DocumentType.COL && targetDoc._viewType === CollectionViewType.Freeform) || targetDoc.type === DocumentType.IMG) {
- const x = targetDoc._panX;
- const y = targetDoc._panY;
- 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 ([DocumentType.AUDIO, DocumentType.VID].includes(targetDoc.type as any)) {
- activeItem.presStartTime = targetDoc._currentTimecode;
- activeItem.presStartTime = NumCast(targetDoc._currentTimecode) + 0.1;
- } else if (targetDoc.type === DocumentType.COMPARISON) {
- const clipWidth = targetDoc._clipWidth;
- activeItem.presPinClipWidth = clipWidth;
- } else {
- const x = targetDoc._panX;
- const y = targetDoc._panY;
- const scale = targetDoc._viewScale;
- activeItem.presPinViewX = x;
- activeItem.presPinViewY = y;
- activeItem.presPinViewScale = scale;
- }
- }}>
- Update
- </div>
- </Tooltip>
- ) : null}
- </div>
- </>
- );
- }
-
- @computed get panOptionsDropdown() {
- const activeItem: Doc = this.activeItem;
- const targetDoc: Doc = this.targetDoc;
- return (
- <>
- {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 }}>
- <input
- className="presBox-input"
- style={{ textAlign: 'left', width: 50 }}
- type="number"
- value={NumCast(activeItem.presPinViewX)}
- onKeyDown={e => e.stopPropagation()}
- onChange={action((e: React.ChangeEvent<HTMLInputElement>) => {
- const val = e.target.value;
- activeItem.presPinViewX = Number(val);
- })}
- />
- </div>
- </div>
- <div className="ribbon-doubleButton" style={{ marginRight: 10 }}>
- <div className="presBox-subheading">Pan Y</div>
- <div className="ribbon-property" style={{ paddingRight: 0, paddingLeft: 0 }}>
- <input
- className="presBox-input"
- style={{ textAlign: 'left', width: 50 }}
- type="number"
- value={NumCast(activeItem.presPinViewY)}
- onKeyDown={e => e.stopPropagation()}
- onChange={action((e: React.ChangeEvent<HTMLInputElement>) => {
- const val = e.target.value;
- activeItem.presPinViewY = Number(val);
- })}
- />
- </div>
- </div>
- <div className="ribbon-doubleButton" style={{ marginRight: 10 }}>
- <div className="presBox-subheading">Scale</div>
- <div className="ribbon-property" style={{ paddingRight: 0, paddingLeft: 0 }}>
- <input
- className="presBox-input"
- style={{ textAlign: 'left', width: 50 }}
- type="number"
- value={NumCast(activeItem.presPinViewScale)}
- onKeyDown={e => e.stopPropagation()}
- onChange={action((e: React.ChangeEvent<HTMLInputElement>) => {
- const val = e.target.value;
- activeItem.presPinViewScale = Number(val);
- })}
- />
- </div>
- </div>
- </div>
- ) : null}
- </>
- );
- }
-
- @computed get scrollOptionsDropdown() {
- const activeItem: Doc = this.activeItem;
- const targetDoc: Doc = this.targetDoc;
- return (
- <>
- {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)}
- onKeyDown={e => e.stopPropagation()}
- onChange={action((e: React.ChangeEvent<HTMLInputElement>) => {
- const val = e.target.value;
- activeItem.presPinViewScroll = Number(val);
- })}
- />
- </div>
- </div>
- </div>
- ) : null}
- </>
- );
- }
-
@computed get mediaStopSlides() {
const activeItem: Doc = this.activeItem;
const list = this.childDocs.map((doc, i) => {
@@ -2102,42 +1959,23 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
};
createTemplate = (layout: string, input?: string) => {
- const activeItem: Doc = this.activeItem;
- const targetDoc: Doc = this.targetDoc;
- let x = 0;
- let y = 0;
- if (activeItem && targetDoc) {
- x = NumCast(targetDoc.x);
- y = NumCast(targetDoc.y) + NumCast(targetDoc._height) + 20;
- }
- let doc = undefined;
- const title = Docs.Create.TextDocument('Click to change title', { title: 'Slide title', _width: 380, _height: 60, x: 10, y: 58, _fontSize: '24pt' });
- const subtitle = Docs.Create.TextDocument('Click to change subtitle', { title: 'Slide subtitle', _width: 380, _height: 50, x: 10, y: 118, _fontSize: '16pt' });
- const header = Docs.Create.TextDocument('Click to change header', { title: 'Slide header', _width: 380, _height: 65, x: 10, y: 80, _fontSize: '20pt' });
- const contentTitle = Docs.Create.TextDocument('Click to change title', { title: 'Slide title', _width: 380, _height: 60, x: 10, y: 10, _fontSize: '24pt' });
- const content = Docs.Create.TextDocument('Click to change text', { title: 'Slide text', _width: 380, _height: 145, x: 10, y: 70, _fontSize: '14pt' });
- const content1 = Docs.Create.TextDocument('Click to change text', { title: 'Column 1', _width: 185, _height: 140, x: 10, y: 80, _fontSize: '14pt' });
- const content2 = Docs.Create.TextDocument('Click to change text', { title: 'Column 2', _width: 185, _height: 140, x: 205, y: 80, _fontSize: '14pt' });
+ const x = this.activeItem && this.targetDoc ? NumCast(this.targetDoc.x) : 0;
+ const y = this.activeItem && this.targetDoc ? NumCast(this.targetDoc.y) + NumCast(this.targetDoc._height) + 20 : 0;
+ const title = () => Docs.Create.TextDocument('Click to change title', { title: 'Slide title', _width: 380, _height: 60, x: 10, y: 58, _fontSize: '24pt' });
+ const subtitle = () => Docs.Create.TextDocument('Click to change subtitle', { title: 'Slide subtitle', _width: 380, _height: 50, x: 10, y: 118, _fontSize: '16pt' });
+ const header = () => Docs.Create.TextDocument('Click to change header', { title: 'Slide header', _width: 380, _height: 65, x: 10, y: 80, _fontSize: '20pt' });
+ const contentTitle = () => Docs.Create.TextDocument('Click to change title', { title: 'Slide title', _width: 380, _height: 60, x: 10, y: 10, _fontSize: '24pt' });
+ const content = () => Docs.Create.TextDocument('Click to change text', { title: 'Slide text', _width: 380, _height: 145, x: 10, y: 70, _fontSize: '14pt' });
+ const content1 = () => Docs.Create.TextDocument('Click to change text', { title: 'Column 1', _width: 185, _height: 140, x: 10, y: 80, _fontSize: '14pt' });
+ const content2 = () => Docs.Create.TextDocument('Click to change text', { title: 'Column 2', _width: 185, _height: 140, x: 205, y: 80, _fontSize: '14pt' });
+ // prettier-ignore
switch (layout) {
- case 'blank':
- doc = Docs.Create.FreeformDocument([], { title: input ? input : 'Blank slide', _width: 400, _height: 225, x: x, y: y });
- break;
- case 'title':
- doc = Docs.Create.FreeformDocument([title, subtitle], { title: input ? input : 'Title slide', _width: 400, _height: 225, _fitContentsToBox: true, x: x, y: y });
- break;
- case 'header':
- doc = Docs.Create.FreeformDocument([header], { title: input ? input : 'Section header', _width: 400, _height: 225, _fitContentsToBox: true, x: x, y: y });
- break;
- case 'content':
- doc = Docs.Create.FreeformDocument([contentTitle, content], { title: input ? input : 'Title and content', _width: 400, _height: 225, _fitContentsToBox: true, x: x, y: y });
- break;
- case 'twoColumns':
- doc = Docs.Create.FreeformDocument([contentTitle, content1, content2], { title: input ? input : 'Title and two columns', _width: 400, _height: 225, _fitContentsToBox: true, x: x, y: y });
- break;
- default:
- break;
+ case 'blank': return Docs.Create.FreeformDocument([], { title: input ? input : 'Blank slide', _width: 400, _height: 225, x, y });
+ case 'title': return Docs.Create.FreeformDocument([title(), subtitle()], { title: input ? input : 'Title slide', _width: 400, _height: 225, _fitContentsToBox: true, x, y });
+ case 'header': return Docs.Create.FreeformDocument([header()], { title: input ? input : 'Section header', _width: 400, _height: 225, _fitContentsToBox: true, x, y });
+ case 'content': return Docs.Create.FreeformDocument([contentTitle(), content()], { title: input ? input : 'Title and content', _width: 400, _height: 225, _fitContentsToBox: true, x, y });
+ case 'twoColumns': return Docs.Create.FreeformDocument([contentTitle(), content1(), content2()], { title: input ? input : 'Title and two columns', _width: 400, _height: 225, _fitContentsToBox: true, x, y })
}
- return doc;
};
// Dropdown that appears when the user wants to begin presenting (either minimize or sidebar view)
@@ -2201,42 +2039,22 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
/**
* Returns the collection type as a string for headers
*/
- @computed get stringType(): string {
- const activeItem: Doc = this.activeItem;
- const targetDoc: Doc = this.targetDoc;
- let type: string = '';
- if (activeItem) {
- switch (targetDoc.type) {
- case DocumentType.PDF:
- type = 'PDF';
- break;
- case DocumentType.RTF:
- type = 'Text node';
- break;
- case DocumentType.COL:
- type = 'Collection';
- break;
- case DocumentType.AUDIO:
- type = 'Audio';
- break;
- case DocumentType.VID:
- type = 'Video';
- break;
- case DocumentType.IMG:
- type = 'Image';
- break;
- case DocumentType.WEB:
- type = 'Web page';
- break;
- case DocumentType.MAP:
- type = 'Map';
- break;
- default:
- type = 'Other node';
- break;
+ @computed get stringType() {
+ if (this.activeItem) {
+ // prettier-ignore
+ switch (this.targetDoc.type) {
+ case DocumentType.PDF: return 'PDF';
+ case DocumentType.RTF: return 'Text node';
+ case DocumentType.COL: return 'Collection';
+ case DocumentType.AUDIO: return 'Audio';
+ case DocumentType.VID: return 'Video';
+ case DocumentType.IMG: return 'Image';
+ case DocumentType.WEB: return 'Web page';
+ case DocumentType.MAP: return 'Map';
+ default: return 'Other node';
}
}
- return type;
+ return '';
}
@observable private openActiveColorPicker: boolean = false;
@@ -2845,10 +2663,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
case DocumentType.PDF || DocumentType.RTF || DocumentType.WEB:
this.updateList(activeItem.frameList);
break;
- case DocumentType.COL:
- break;
- default:
- break;
}
};