aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/trails/PresSlideBox.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/nodes/trails/PresSlideBox.tsx')
-rw-r--r--src/client/views/nodes/trails/PresSlideBox.tsx628
1 files changed, 628 insertions, 0 deletions
diff --git a/src/client/views/nodes/trails/PresSlideBox.tsx b/src/client/views/nodes/trails/PresSlideBox.tsx
new file mode 100644
index 000000000..3dbb3da88
--- /dev/null
+++ b/src/client/views/nodes/trails/PresSlideBox.tsx
@@ -0,0 +1,628 @@
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { Tooltip } from '@mui/material';
+import { action, computed, IReactionDisposer, makeObservable, observable, reaction, runInAction } from 'mobx';
+import { observer } from 'mobx-react';
+import * as React from 'react';
+import { returnFalse, returnTrue, setupMoveUpEvents } from '../../../../ClientUtils';
+import { Doc, DocListCast, Opt } from '../../../../fields/Doc';
+import { Id } from '../../../../fields/FieldSymbols';
+import { List } from '../../../../fields/List';
+import { BoolCast, DocCast, NumCast, StrCast } from '../../../../fields/Types';
+import { emptyFunction } from '../../../../Utils';
+import { Docs } from '../../../documents/Documents';
+import { CollectionViewType, DocumentType } from '../../../documents/DocumentTypes';
+import { DragManager } from '../../../util/DragManager';
+import { SnappingManager } from '../../../util/SnappingManager';
+import { Transform } from '../../../util/Transform';
+import { undoable, undoBatch } from '../../../util/UndoManager';
+import { TreeView } from '../../collections/TreeView';
+import { ViewBoxBaseComponent } from '../../DocComponent';
+import { EditableView } from '../../EditableView';
+import { Colors } from '../../global/globalEnums';
+import { PinDocView } from '../../PinFuncs';
+import { StyleProp } from '../../StyleProp';
+import { returnEmptyDocViewList } from '../../StyleProvider';
+import { DocumentView } from '../DocumentView';
+import { FieldView, FieldViewProps } from '../FieldView';
+import { PresBox } from './PresBox';
+import './PresSlideBox.scss';
+import { PresMovement } from './PresEnums';
+/**
+ * This class models the view a document added to presentation will have in the presentation.
+ * It involves some functionality for its buttons and options.
+ */
+@observer
+export class PresSlideBox extends ViewBoxBaseComponent<FieldViewProps>() {
+ public static LayoutString(fieldKey: string) {
+ return FieldView.LayoutString(PresSlideBox, fieldKey);
+ }
+ private _itemRef: React.RefObject<HTMLDivElement> = React.createRef();
+ private _dragRef: React.RefObject<HTMLDivElement> = React.createRef();
+ private _titleRef: React.RefObject<EditableView> = React.createRef();
+ private _heightDisposer: IReactionDisposer | undefined;
+ readonly expandViewHeight = 100;
+ readonly collapsedHeight = 35;
+
+ constructor(props: FieldViewProps) {
+ super(props);
+ makeObservable(this);
+ }
+
+ @observable _dragging = false;
+
+ // the presentation view that renders this slide
+ @computed get presBoxView() {
+ return this.DocumentView?.()
+ .containerViewPath?.()
+ .slice()
+ .reverse()
+ .find(dv => dv?.ComponentView instanceof PresBox)?.ComponentView as Opt<PresBox>;
+ }
+
+ // the presentation view document that renders this slide
+ @computed get presBox() {
+ return this.presBoxView?.Document;
+ }
+
+ // Since this node is being rendered with a template, this method retrieves
+ // the actual slide being rendered from the auto-generated rendering template
+ @computed get slideDoc() {
+ return this.rootDoc;
+ }
+
+ // this is the document in the workspaces that is targeted by the slide
+ @computed get targetDoc() {
+ return DocCast(this.slideDoc.presentation_targetDoc, this.slideDoc)!;
+ }
+
+ // computes index of this presentation slide in the presBox list
+ @computed get indexInPres() {
+ return this.presBoxView?.SlideIndex(this.slideDoc) ?? 0;
+ }
+
+ @computed get selectedArray() {
+ return this.presBoxView?.selectedArray;
+ }
+
+ @computed get videoRecordingIsInOverlay() {
+ return Doc.MyOverlayDocs.some(doc => doc.slides === this.slideDoc);
+ }
+
+ componentDidMount() {
+ this.layoutDoc.layout_hideLinkButton = true;
+ this._heightDisposer = reaction(
+ () => ({ expand: this.slideDoc.presentation_expandInlineButton, height: this.collapsedHeight }),
+ ({ expand, height }) => {
+ this.layoutDoc._height = height + (expand ? this.expandViewHeight : 0);
+ },
+ { fireImmediately: true }
+ );
+ }
+ componentWillUnmount() {
+ this._heightDisposer?.();
+ }
+
+ presExpandDocumentClick = () => {
+ this.slideDoc.presentation_expandInlineButton = !this.slideDoc.presentation_expandInlineButton;
+ };
+ embedHeight = () => this.collapsedHeight + this.expandViewHeight;
+ embedWidth = () => this._props.PanelWidth() / 2;
+ // prettier-ignore
+ styleProvider = ( doc: Doc | undefined, props: Opt<FieldViewProps>, property: string ) =>
+ (property === StyleProp.Opacity ? 1 : this._props.styleProvider?.(doc, props, property));
+ /**
+ * The function that is responsible for rendering a preview or not for this
+ * presentation element.
+ */
+ @computed get renderEmbeddedInline() {
+ return !this.slideDoc.presentation_expandInlineButton || !this.targetDoc ? null : (
+ <div className="presItem-embedded" style={{ height: this.embedHeight(), width: '50%' }}>
+ <DocumentView
+ Document={PresBox.targetRenderedDoc(this.slideDoc) ?? this.slideDoc}
+ PanelWidth={this.embedWidth}
+ PanelHeight={this.embedHeight}
+ isContentActive={this._props.isContentActive}
+ styleProvider={this.styleProvider}
+ hideLinkButton
+ ScreenToLocalTransform={Transform.Identity}
+ renderDepth={this._props.renderDepth + 1}
+ containerViewPath={returnEmptyDocViewList}
+ childFilters={this._props.childFilters}
+ childFiltersByRanges={this._props.childFiltersByRanges}
+ searchFilterDocs={this._props.searchFilterDocs}
+ addDocument={returnFalse}
+ removeDocument={returnFalse}
+ fitContentsToBox={returnTrue}
+ moveDocument={this._props.moveDocument!}
+ focus={emptyFunction}
+ whenChildContentsActiveChanged={returnFalse}
+ addDocTab={returnFalse}
+ pinToPres={returnFalse}
+ />
+ </div>
+ );
+ }
+
+ @computed get renderGroupSlides() {
+ const childDocs = DocListCast(this.targetDoc.data);
+ const groupSlides = childDocs.map((doc: Doc, ind: number) => (
+ <div
+ key={doc[Id]}
+ className="presItem-groupSlide"
+ onClick={e => {
+ e.stopPropagation();
+ e.preventDefault();
+ this.presBoxView?.modifierSelect(doc, this._itemRef.current!, this._dragRef.current!, e.shiftKey || e.ctrlKey || e.metaKey, e.ctrlKey || e.metaKey, e.shiftKey);
+ this.presExpandDocumentClick();
+ }}>
+ <div className="presItem-groupNum">{`${ind + 1}.`}</div>
+ <div className="presItem-name">
+ <EditableView
+ ref={this._titleRef}
+ editing={undefined}
+ contents={StrCast(doc.title)}
+ overflow="ellipsis"
+ GetValue={() => StrCast(doc.title)}
+ SetValue={(value: string) => {
+ doc.title = !value.trim().length ? '-untitled-' : value;
+ return true;
+ }}
+ />
+ </div>
+ </div>
+ ));
+ return groupSlides;
+ }
+
+ @computed get transition() {
+ let transitionInS: number;
+ if (this.slideDoc.presentation_transition) transitionInS = NumCast(this.slideDoc.presentation_transition) / 1000;
+ else transitionInS = 0.5;
+ return this.slideDoc.presentation_movement === PresMovement.Jump || this.slideDoc.presentation_movement === PresMovement.None ? null : 'M: ' + transitionInS + 's';
+ }
+
+ @action
+ headerDown = (e: React.PointerEvent<HTMLDivElement>) => {
+ const element = e.target as HTMLDivElement;
+ e.stopPropagation();
+ e.preventDefault();
+ if (element && !(e.ctrlKey || e.metaKey || e.button === 2)) {
+ this.presBoxView?.regularSelect(this.slideDoc, this._itemRef.current!, this._dragRef.current!, true, false);
+ setupMoveUpEvents(this, e, this.startDrag, emptyFunction, clickEv => {
+ clickEv.stopPropagation();
+ clickEv.preventDefault();
+ this.presBoxView?.modifierSelect(this.slideDoc, this._itemRef.current!, this._dragRef.current!, clickEv.shiftKey || clickEv.ctrlKey || clickEv.metaKey, clickEv.ctrlKey || clickEv.metaKey, clickEv.shiftKey);
+ this.presBoxView?.activeItem && this.showRecording(this.presBoxView?.activeItem);
+ });
+ }
+ };
+
+ /**
+ * Function to drag and drop the pres element to a diferent location
+ */
+ startDrag = (e: PointerEvent) => {
+ this.presBoxView?.regularSelect(this.slideDoc, this._itemRef.current!, this._dragRef.current!, true, false);
+ const miniView: boolean = this.toolbarWidth <= 100;
+ const activeItem = this.slideDoc;
+ const dragArray = this.presBoxView?._dragArray ?? [];
+ const dragData = new DragManager.DocumentDragData(this.presBoxView?.sortArray() ?? []);
+ if (!dragData.draggedDocuments.length) dragData.draggedDocuments.push(this.slideDoc);
+ dragData.treeViewDoc = this.presBox?._type_collection === CollectionViewType.Tree ? this.presBox : undefined; // this.DocumentView?.()?._props.treeViewDoc;
+ dragData.moveDocument = this._props.moveDocument;
+ const dragItem: HTMLElement[] = [];
+ const classesToRestore = new Map<HTMLElement, string>();
+ if (dragArray.length === 1) {
+ const doc = this._itemRef.current || dragArray[0];
+ if (doc) {
+ classesToRestore.set(doc, doc.className);
+ doc.className = miniView ? 'presItem-miniSlide' : 'presItem-slide';
+ dragItem.push(doc);
+ }
+ } else if (dragArray.length >= 1) {
+ const doc = document.createElement('div');
+ doc.className = 'presItem-multiDrag';
+ doc.innerText = 'Move ' + (this.selectedArray?.size ?? 0) + ' slides';
+ doc.style.position = 'absolute';
+ doc.style.top = e.clientY + 'px';
+ doc.style.left = e.clientX - 50 + 'px';
+ dragItem.push(doc);
+ }
+
+ if (activeItem) {
+ runInAction(() => {
+ this._dragging = true;
+ });
+ DragManager.StartDocumentDrag(
+ dragItem.map(ele => ele),
+ dragData,
+ e.clientX,
+ e.clientY,
+ undefined,
+ action(() => {
+ Array.from(classesToRestore).forEach(pair => (pair[0].className = pair[1]));
+ this._dragging = false;
+ })
+ );
+ return true;
+ }
+ return false;
+ };
+
+ onPointerOver = () => {
+ document.removeEventListener('pointermove', this.onPointerMove);
+ document.addEventListener('pointermove', this.onPointerMove);
+ };
+
+ onPointerMove = (e: PointerEvent) => {
+ const slide = this._itemRef.current;
+ const dragIsPresItem = DragManager.docsBeingDragged.some(d => d.presentation_targetDoc);
+ if (slide && dragIsPresItem) {
+ const rect = slide.getBoundingClientRect();
+ const y = e.clientY - rect.top; // y position within the element.
+ const height = slide.clientHeight;
+ const halfLine = height / 2;
+ if (y <= halfLine) {
+ slide.style.borderTop = `solid 2px ${Colors.MEDIUM_BLUE}`;
+ slide.style.borderBottom = '0px';
+ } else if (y > halfLine) {
+ slide.style.borderTop = '0px';
+ slide.style.borderBottom = `solid 2px ${Colors.MEDIUM_BLUE}`;
+ }
+ }
+ document.removeEventListener('pointermove', this.onPointerMove);
+ };
+
+ onPointerLeave = () => {
+ const slide = this._itemRef.current;
+ if (slide) {
+ slide.style.borderTop = '0px';
+ slide.style.borderBottom = '0px';
+ }
+ document.removeEventListener('pointermove', this.onPointerMove);
+ };
+
+ @action
+ toggleProperties = () => {
+ if (SnappingManager.PropertiesWidth < 5) {
+ SnappingManager.SetPropertiesWidth(250);
+ }
+ };
+
+ removePresentationItem = undoable(
+ action((e: React.MouseEvent) => {
+ e.stopPropagation();
+ if (this.presBox && this.indexInPres < (this.presBoxView?.itemIndex || 0)) {
+ this.presBox.itemIndex = (this.presBoxView?.itemIndex || 0) - 1;
+ }
+ this._props.removeDocument?.(this.slideDoc);
+ this.presBoxView?.removeFromSelectedArray(this.slideDoc);
+ this.removeAllRecordingInOverlay();
+ }),
+ 'Remove doc from pres trail'
+ );
+
+ // set title of the individual pres slide
+ onSetValue = undoable(
+ action((value: string) => {
+ this.slideDoc.title = !value.trim().length ? '-untitled-' : value;
+ return true;
+ }),
+ 'set title of pres element'
+ );
+
+ /**
+ * Method called for updating the view of the currently selected document
+ *
+ * @param targetDoc
+ * @param activeItem
+ */
+ @undoBatch
+ updateCapturedContainerLayout = (presTargetDoc: Doc, activeItem: Doc) => {
+ const targetDoc = DocCast(presTargetDoc.annotationOn) ?? presTargetDoc;
+ activeItem.config_x = NumCast(targetDoc.x);
+ activeItem.config_y = NumCast(targetDoc.y);
+ activeItem.config_rotation = NumCast(targetDoc.rotation);
+ activeItem.config_width = NumCast(targetDoc.width);
+ activeItem.config_height = NumCast(targetDoc.height);
+ activeItem.config_pinLayout = !activeItem.config_pinLayout;
+ // activeItem.config_pinLayout = true;
+ };
+
+ /**
+ * Method called for updating the view of the currently selected document
+ *
+ * @param presTargetDoc
+ * @param activeItem
+ */
+ updateCapturedViewContents = undoable(
+ action((presTargetDoc: Doc, activeItem: Doc) => {
+ const target = DocCast(presTargetDoc.annotationOn) ?? presTargetDoc;
+ PinDocView(activeItem, { pinData: PresBox.pinDataTypes(target) }, target);
+ }),
+ 'updated captured view contents'
+ );
+
+ // a previously recorded video will have timecode defined
+ static videoIsRecorded = (activeItem: Opt<Doc>) => 'layout_currentTimecode' in (DocCast(activeItem?.recording) ?? {});
+
+ removeAllRecordingInOverlay = () => Doc.MyOverlayDocs.filter(doc => doc.slides === this.slideDoc).forEach(Doc.RemFromMyOverlay);
+
+ /// remove all videos that have been recorded from overlay (leave videso that are being recorded to avoid losing data)
+ static removeEveryExistingRecordingInOverlay = () => {
+ Doc.MyOverlayDocs.filter(doc => doc.slides !== null && PresSlideBox.videoIsRecorded(DocCast(doc.slides))) //
+ .forEach(Doc.RemFromMyOverlay);
+ };
+
+ hideRecording = undoable(
+ action((e: React.MouseEvent) => {
+ e.stopPropagation();
+ this.removeAllRecordingInOverlay();
+ }),
+ 'hide video recording'
+ );
+
+ showRecording = undoable(
+ action((activeItem: Doc, iconClick: boolean = false) => {
+ // remove the overlays on switch *IF* not opened from the specific icon
+ if (!iconClick) PresSlideBox.removeEveryExistingRecordingInOverlay();
+
+ DocCast(activeItem.recording) && Doc.AddToMyOverlay(DocCast(activeItem.recording)!);
+ }),
+ 'show video recording'
+ );
+
+ startRecording = undoable(
+ action((e: React.MouseEvent, activeItem: Doc) => {
+ e.stopPropagation();
+ if (PresSlideBox.videoIsRecorded(activeItem)) {
+ // if we already have an existing recording
+ this.showRecording(activeItem, true);
+ // // if we already have an existing recording
+ // Doc.AddToMyOverlay(Cast(activeItem.recording, Doc, null));
+ } else {
+ // we dont have any recording
+ // Remove every recording that already exists in overlay view
+ // this is a design decision to clear to focus in on the recoding mode
+ PresSlideBox.removeEveryExistingRecordingInOverlay();
+
+ // create and add a recording to the slide
+ // make recording box appear in the bottom right corner of the screen
+ Doc.AddToMyOverlay(
+ (activeItem.recording = Docs.Create.WebCamDocument('', {
+ _width: 384,
+ _height: 216,
+ overlayX: window.innerWidth - 384 - 20,
+ overlayY: window.innerHeight - 216 - 20,
+ layout_hideDocumentButtonBar: true,
+ layout_hideDecorationTitle: true,
+ layout_hideOpenButton: true,
+ cloneFieldFilter: new List<string>(['isSystem']),
+ slides: activeItem, // attach the slide to the recording
+ }))
+ );
+ }
+ }),
+ 'start video recording'
+ );
+
+ @undoBatch
+ lfg = (e: React.MouseEvent) => {
+ e.stopPropagation();
+ // TODO: fix this bug
+ // const { toggleChildrenRun } = this.slideDoc;
+ TreeView.ToggleChildrenRun.get(this.slideDoc)?.();
+
+ // call this.slideDoc.recurChildren() to get all the children
+ // if (iconClick) PresSlideBox.showVideo = false;
+ };
+
+ @computed
+ get toolbarWidth(): number {
+ const presBoxDocView = DocumentView.getDocumentView(this.presBox);
+ const width = NumCast(this.presBox?._width);
+ return presBoxDocView ? presBoxDocView._props.PanelWidth() : width || 300;
+ }
+
+ @computed get presButtons() {
+ const { presBox, targetDoc, slideDoc: activeItem } = this;
+ const presBoxColor = StrCast(presBox?._backgroundColor);
+ const presColorBool = presBoxColor ? presBoxColor !== Colors.WHITE && presBoxColor !== 'transparent' : false;
+ const hasChildren = BoolCast(this.slideDoc?.hasChildren);
+
+ const items: JSX.Element[] = [];
+
+ items.push(
+ <Tooltip key="slide" title={<div className="dash-tooltip">Update captured doc layout</div>}>
+ <div
+ className="slideButton"
+ onPointerDown={e => setupMoveUpEvents(this, e, returnFalse, emptyFunction, () => this.updateCapturedContainerLayout(targetDoc, activeItem), true)}
+ style={{ opacity: activeItem.config_pinLayout ? 1 : 0.5, fontWeight: 700, display: 'flex' }}>
+ L
+ </div>
+ </Tooltip>
+ );
+ items.push(
+ <Tooltip key="flex" title={<div className="dash-tooltip">Update captured doc content</div>}>
+ <div
+ className="slideButton"
+ onPointerDown={e => setupMoveUpEvents(this, e, returnFalse, emptyFunction, () => this.updateCapturedViewContents(targetDoc, activeItem))}
+ style={{ opacity: activeItem.config_pinData || activeItem.config_pinView ? 1 : 0.5, fontWeight: 700, display: 'flex' }}>
+ C
+ </div>
+ </Tooltip>
+ );
+ items.push(
+ <Tooltip key="slash" title={<div className="dash-tooltip">{this.videoRecordingIsInOverlay ? 'Hide Recording' : `${PresSlideBox.videoIsRecorded(activeItem) ? 'Show' : 'Start'} recording`}</div>}>
+ <div className="slideButton" onClick={e => (this.videoRecordingIsInOverlay ? this.hideRecording(e) : this.startRecording(e, activeItem))} style={{ fontWeight: 700 }}>
+ <FontAwesomeIcon icon={`video${this.videoRecordingIsInOverlay ? '-slash' : ''}`} onPointerDown={e => e.stopPropagation()} />
+ </div>
+ </Tooltip>
+ );
+ if (this.indexInPres !== 0) {
+ items.push(
+ <Tooltip
+ key="arrow"
+ title={
+ <div className="dash-tooltip">
+ {!activeItem.presentation_groupWithUp
+ ? 'Not grouped with previous slide (click to group)'
+ : activeItem.presentation_groupWithUp === 1
+ ? 'Run simultaneously with previous slide (click again to run after)'
+ : 'Run after previous slide (click to ungroup from previous)'}
+ </div>
+ }>
+ <div
+ className="slideButton"
+ onClick={() => {
+ activeItem.presentation_groupWithUp = (NumCast(activeItem.presentation_groupWithUp) + 1) % 3;
+ }}
+ style={{
+ zIndex: 1000 - this.indexInPres,
+ fontWeight: 700,
+ backgroundColor: activeItem.presentation_groupWithUp ? (presColorBool ? presBoxColor : Colors.MEDIUM_BLUE) : undefined,
+ outline: NumCast(activeItem.presentation_groupWithUp) > 1 ? 'solid black 1px' : undefined,
+ height: activeItem.presentation_groupWithUp ? 53 : 18,
+ transform: activeItem.presentation_groupWithUp ? 'translate(0, -17px)' : undefined,
+ }}>
+ <div style={{ transform: activeItem.presentation_groupWithUp ? 'rotate(180deg) translate(0, -17.5px)' : 'rotate(0deg)' }}>
+ <FontAwesomeIcon icon="arrow-up" onPointerDown={e => e.stopPropagation()} />
+ </div>
+ </div>
+ </Tooltip>
+ );
+ }
+ items.push(
+ <Tooltip key="eye" title={<div className="dash-tooltip">{this.slideDoc.presentation_expandInlineButton ? 'Minimize' : 'Expand'}</div>}>
+ <div
+ className="slideButton"
+ onClick={e => {
+ e.stopPropagation();
+ this.presExpandDocumentClick();
+ }}>
+ <FontAwesomeIcon icon={this.slideDoc.presentation_expandInlineButton ? 'eye-slash' : 'eye'} onPointerDown={e => e.stopPropagation()} />
+ </div>
+ </Tooltip>
+ );
+ if (!Doc.noviceMode && hasChildren) {
+ // TODO: replace with if treeveiw, has childrenDocs
+ items.push(
+ <Tooltip key="children" title={<div className="dash-tooltip">Run child processes (tree only)</div>}>
+ <div
+ className="slideButton"
+ onClick={e => {
+ e.stopPropagation();
+ this.lfg(e);
+ }}
+ style={{ fontWeight: 700 }}>
+ <FontAwesomeIcon icon="circle-play" onPointerDown={e => e.stopPropagation()} />
+ </div>
+ </Tooltip>
+ );
+ }
+ items.push(
+ <Tooltip key="trash" title={<div className="dash-tooltip">Remove from presentation</div>}>
+ <div className="slideButton" onClick={this.removePresentationItem}>
+ <FontAwesomeIcon icon="trash" onPointerDown={e => e.stopPropagation()} />
+ </div>
+ </Tooltip>
+ );
+ items.push(
+ <Tooltip key="customize-slide" title={<div className="dash-tooltip">Customize Slide</div>}>
+ <div
+ className={'slideButton'}
+ onClick={() => {
+ this.presBoxView?.regularSelect(this.slideDoc, this._itemRef.current!, this._dragRef.current!, true, false);
+ PresBox.Instance.navigateToActiveItem();
+ PresBox.Instance.openProperties();
+ PresBox.Instance.slideToModify = this.Document;
+ }}>
+ <FontAwesomeIcon icon={'edit'} onPointerDown={e => e.stopPropagation()} />
+ </div>
+ </Tooltip>
+ );
+ return items;
+ }
+
+ @computed get mainItem() {
+ const { presBox, slideDoc: activeItem } = this;
+ const isSelected: boolean = !!this.selectedArray?.has(activeItem);
+ const isCurrent: boolean = this.presBox?._itemIndex === this.indexInPres;
+ const miniView: boolean = this.toolbarWidth <= 110;
+ const presBoxColor: string = StrCast(presBox?._backgroundColor);
+ const presColorBool: boolean = presBoxColor ? presBoxColor !== Colors.WHITE && presBoxColor !== 'transparent' : false;
+
+ return (
+ <div
+ className="presItem-container"
+ key={activeItem[Id] + this.indexInPres}
+ ref={this._itemRef}
+ style={{
+ backgroundColor: presColorBool ? (isSelected ? 'rgba(250,250,250,0.3)' : 'transparent') : isSelected ? Colors.LIGHT_BLUE : 'transparent',
+ opacity: this._dragging ? 0.3 : 1,
+ paddingLeft: NumCast(this.layoutDoc._xPadding, this._props.xPadding),
+ paddingRight: NumCast(this.layoutDoc._xPadding, this._props.xPadding),
+ paddingTop: NumCast(this.layoutDoc._yPadding, this._props.yPadding),
+ paddingBottom: NumCast(this.layoutDoc._yPadding, this._props.yPadding),
+ }}
+ onDoubleClick={action(() => {
+ this.toggleProperties();
+ this.presBoxView?.regularSelect(activeItem, this._itemRef.current!, this._dragRef.current!, false);
+ })}
+ onPointerOver={this.onPointerOver}
+ onPointerLeave={this.onPointerLeave}
+ onPointerDown={this.headerDown}>
+ {miniView ? (
+ <div className={`presItem-miniSlide ${isSelected ? 'active' : ''}`} ref={this._dragRef}>
+ {`${this.indexInPres + 1}.`}
+ </div>
+ ) : (
+ <div
+ ref={this._dragRef}
+ className={`presItem-slide ${isCurrent ? 'active' : ''}${activeItem.runProcess ? ' testingv2' : ''}`}
+ style={{
+ display: 'infline-block',
+ backgroundColor: this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.BackgroundColor) as string,
+ // layout_boxShadow: presBoxColor && presBoxColor !== 'white' && presBoxColor !== 'transparent' ? (isCurrent ? '0 0 0px 1.5px' + presBoxColor : undefined) : undefined,
+ border: presBoxColor && presBoxColor !== 'white' && presBoxColor !== 'transparent' ? (isCurrent ? presBoxColor + ' solid 2.5px' : undefined) : undefined,
+ }}>
+ <div
+ className="presItem-name"
+ style={{
+ display: 'inline-flex',
+ pointerEvents: isSelected ? undefined : 'none',
+ width: `calc(100% ${activeItem.presentation_expandInlineButton ? '- 50%' : ''} - ${this.presButtons.length * 22}px`,
+ cursor: isSelected ? 'text' : 'grab',
+ }}>
+ <div
+ className="presItem-number"
+ title="select without navigation"
+ onPointerDown={e => {
+ e.stopPropagation();
+ if (this._itemRef.current && this._dragRef.current) {
+ this.presBoxView?.modifierSelect(activeItem, this._itemRef.current, this._dragRef.current, true, false, false);
+ }
+ }}
+ onClick={e => e.stopPropagation()}>{`${this.indexInPres + 1}. `}</div>
+ <EditableView ref={this._titleRef} oneLine editing={!isSelected ? false : undefined} contents={StrCast(activeItem.title)} overflow="ellipsis" GetValue={() => StrCast(activeItem.title)} SetValue={this.onSetValue} />
+ </div>
+ {/* <Tooltip title={<><div className="dash-tooltip">{"Movement speed"}</div></>}><div className="presItem-time" style={{ display: showMore ? "block" : "none" }}>{this.transition}</div></Tooltip> */}
+ {/* <Tooltip title={<><div className="dash-tooltip">{"Duration"}</div></>}><div className="presItem-time" style={{ display: showMore ? "block" : "none" }}>{this.duration}</div></Tooltip> */}
+ <div className="presItem-slideButtons" style={{ position: 'absolute', right: 0 }}>
+ {...this.presButtons}
+ </div>
+ {this.renderEmbeddedInline}
+ </div>
+ )}
+ </div>
+ );
+ }
+
+ render() {
+ return !(this.slideDoc instanceof Doc) || this.targetDoc instanceof Promise ? null : this.mainItem;
+ }
+}
+
+Docs.Prototypes.TemplateMap.set(DocumentType.PRESSLIDE, {
+ layout: { view: PresSlideBox, dataField: 'data' },
+ options: { acl: '', title: 'presSlide', _layout_fitWidth: true, _xMargin: 0, isTemplateDoc: true },
+});