From 6efc3545ccca2bcb0aaf219b2a9ff1c4f06e9e91 Mon Sep 17 00:00:00 2001
From: geireann <60007097+geireann@users.noreply.github.com>
Date: Wed, 25 Nov 2020 00:10:33 +0800
Subject: loader

---
 src/client/views/MainView.tsx | 7 +++++++
 1 file changed, 7 insertions(+)

(limited to 'src/client/views/MainView.tsx')

diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 452ce61ff..2100f1458 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -85,6 +85,13 @@ export class MainView extends React.Component {
 
     componentDidMount() {
         document.getElementById("root")?.addEventListener("scroll", e => ((ele) => ele.scrollLeft = ele.scrollTop = 0)(document.getElementById("root")!));
+        const ele = document.getElementById("loader");
+        if (ele) {
+            setTimeout(() => {
+                // remove from DOM
+                ele.outerHTML = '';
+            }, 0);
+        }
         new InkStrokeProperties();
         this._sidebarContent.proto = undefined;
         DocServer.setPlaygroundFields(["x", "y", "dataTransition", "_delayAutoHeight", "_autoHeight", "_showSidebar", "_sidebarWidthPercent", "_width", "_height", "_viewTransition", "_panX", "_panY", "_viewScale", "_scrollY", "_scrollTop", "hidden", "_curPage", "_viewType", "_chromeStatus"]); // can play with these fields on someone else's
-- 
cgit v1.2.3-70-g09d2


From 534a4e81e84adbd46b629731ac3ca7d3ea41a670 Mon Sep 17 00:00:00 2001
From: geireann <60007097+geireann@users.noreply.github.com>
Date: Sun, 29 Nov 2020 11:15:30 +0800
Subject: temporal media updates for pres. trails

---
 deploy/index.html                                  |   4 +-
 src/client/views/MainView.tsx                      |   8 +-
 src/client/views/PropertiesView.tsx                |   8 +-
 src/client/views/nodes/AudioBox.tsx                |  22 +-
 src/client/views/nodes/PresBox.scss                |  83 +++-
 src/client/views/nodes/PresBox.tsx                 | 323 +++++++++-----
 src/client/views/nodes/VideoBox.tsx                |  51 ++-
 .../views/presentationview/PresElementBox.scss     |  41 +-
 .../views/presentationview/PresElementBox.tsx      |   3 +-
 .../views/presentationview/PresProperties.tsx      | 492 +++++++++++++++++++++
 10 files changed, 901 insertions(+), 134 deletions(-)
 create mode 100644 src/client/views/presentationview/PresProperties.tsx

(limited to 'src/client/views/MainView.tsx')

diff --git a/deploy/index.html b/deploy/index.html
index af67ac301..beb7dd205 100644
--- a/deploy/index.html
+++ b/deploy/index.html
@@ -14,8 +14,8 @@
             justify-content: center;
             background-color: #AEDDF8;
             z-index: 10;
-            width: 100%;
-            height: 100%;
+            width: 100vw;
+            height: 100vh;
         }
 
         .dash-loader-container {
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 03d2e33df..b1e008dad 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -87,11 +87,11 @@ export class MainView extends React.Component {
     componentDidMount() {
         document.getElementById("root")?.addEventListener("scroll", e => ((ele) => ele.scrollLeft = ele.scrollTop = 0)(document.getElementById("root")!));
         const ele = document.getElementById("loader");
+
         if (ele) {
-            setTimeout(() => {
-                // remove from DOM
-                ele.outerHTML = '';
-            }, 0);
+            // remove from DOM
+            setTimeout(() => { ele.style.opacity = "0"; }, 0);
+            setTimeout(() => ele.outerHTML = '', 10000);
         }
         new InkStrokeProperties();
         this._sidebarContent.proto = undefined;
diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx
index 97bca110b..c656a020e 100644
--- a/src/client/views/PropertiesView.tsx
+++ b/src/client/views/PropertiesView.tsx
@@ -1007,7 +1007,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                         <div className="propertiesView-presTrails-title"
                             onPointerDown={action(() => { this.openPresTransitions = !this.openPresTransitions; })}
                             style={{ backgroundColor: this.openPresTransitions ? "black" : "" }}>
-                            &nbsp; <FontAwesomeIcon icon={"rocket"} /> &nbsp; Transitions
+                            &nbsp; <FontAwesomeIcon style={{ alignSelf: "center" }} icon={"rocket"} /> &nbsp; Transitions
                         <div className="propertiesView-presTrails-title-icon">
                                 <FontAwesomeIcon icon={this.openPresTransitions ? "caret-down" : "caret-right"} size="lg" color="white" />
                             </div>
@@ -1029,17 +1029,17 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                             {PresBox.Instance.progressivizeDropdown}
                         </div> : null}
                     </div>} */}
-                    {!selectedItem ? (null) : <div className="propertiesView-presTrails">
+                    {!selectedItem || (type !== DocumentType.VID && type !== DocumentType.AUDIO) ? (null) : <div className="propertiesView-presTrails">
                         <div className="propertiesView-presTrails-title"
                             onPointerDown={action(() => { this.openSlideOptions = !this.openSlideOptions; })}
                             style={{ backgroundColor: this.openSlideOptions ? "black" : "" }}>
-                            &nbsp; <FontAwesomeIcon icon={"cog"} /> &nbsp; {scrollable ? "Scroll options" : "Pan options"}
+                            &nbsp; <FontAwesomeIcon style={{ alignSelf: "center" }} icon={type === DocumentType.AUDIO ? "file-audio" : "file-video"} /> &nbsp; {type === DocumentType.AUDIO ? "Audio Options" : "Video Options"}
                             <div className="propertiesView-presTrails-title-icon">
                                 <FontAwesomeIcon icon={this.openSlideOptions ? "caret-down" : "caret-right"} size="lg" color="white" />
                             </div>
                         </div>
                         {this.openSlideOptions ? <div className="propertiesView-presTrails-content">
-                            {PresBox.Instance.optionsDropdown}
+                            {PresBox.Instance.mediaOptionsDropdown}
                         </div> : null}
                     </div>}
                     {/* <div className="propertiesView-presTrails">
diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx
index 1bdba7f9e..2527a2db1 100644
--- a/src/client/views/nodes/AudioBox.tsx
+++ b/src/client/views/nodes/AudioBox.tsx
@@ -48,9 +48,9 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps, AudioD
     static RangeScript: ScriptField;
     static LabelScript: ScriptField;
 
-    _linkPlayDisposer: IReactionDisposer | undefined;
-    _reactionDisposer: IReactionDisposer | undefined;
-    _scrubbingDisposer: IReactionDisposer | undefined;
+    // _linkPlayDisposer: IReactionDisposer | undefined;
+    // _reactionDisposer: IReactionDisposer | undefined;
+    // _scrubbingDisposer: IReactionDisposer | undefined;
     private _disposers: { [name: string]: IReactionDisposer } = {};
     _ele: HTMLAudioElement | null = null;
     _recorder: any;
@@ -151,7 +151,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps, AudioD
             });
         this._disposers.scrubbing = reaction(() => AudioBox._scrubTime, (time) => this.layoutDoc.playOnSelect && this.playFromTime(AudioBox._scrubTime));
 
-        this._disposers._audioStart = reaction(
+        this._disposers.audioStart = reaction(
             () => this.Document._audioStart,
             (audioStart) => {
                 if (audioStart !== undefined) {
@@ -165,6 +165,20 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps, AudioD
             },
             { fireImmediately: true }
         );
+
+        this._disposers.audioStop = reaction(
+            () => this.Document._audioStop,
+            (audioStop) => {
+                if (audioStop !== undefined) {
+                    if (this.props.renderDepth !== -1 && !LinkDocPreview.TargetDoc && !FormattedTextBoxComment.linkDoc) {
+                        const delay = this._audioRef.current ? 0 : 250; // wait for mainCont and try again to play
+                        setTimeout(() => this._audioRef.current && this.pause(), delay);
+                        setTimeout(() => { this.Document._audioStop = undefined; }, 10 + delay);
+                    }
+                }
+            },
+            { fireImmediately: true }
+        );
     }
 
     playLink = (doc: Doc) => {
diff --git a/src/client/views/nodes/PresBox.scss b/src/client/views/nodes/PresBox.scss
index 56b3b0593..6579dbf41 100644
--- a/src/client/views/nodes/PresBox.scss
+++ b/src/client/views/nodes/PresBox.scss
@@ -127,6 +127,17 @@ $light-background: #ececec;
     opacity: 0.8;
 }
 
+.presBox-radioButtons {
+    background-color: rgba(0, 0, 0, 0.1);
+
+    .checkbox-container {
+        margin-left: 10px;
+        display: inline-flex;
+        height: 20px;
+        align-items: center;
+    }
+}
+
 .presBox-ribbon {
     position: relative;
     display: inline;
@@ -209,6 +220,42 @@ $light-background: #ececec;
     }
 
     @media screen and (-webkit-min-device-pixel-ratio:0) {
+
+        .multiThumb-slider {
+            display: grid;
+            background-color: $light-background;
+            height: 10px;
+            border-radius: 10px;
+            overflow: hidden;
+
+            .toolbar-slider {
+                margin-top: 0px;
+                background: none;
+                -webkit-appearance: none;
+                pointer-events: none;
+            }
+
+            .toolbar-slider.start::-webkit-slider-thumb {
+                width: 10px;
+                pointer-events: auto;
+                -webkit-appearance: none;
+                height: 10px;
+                cursor: ew-resize;
+                background: $dark-blue;
+                box-shadow: -100vw 0 0 100vw $light-background;
+            }
+
+            .toolbar-slider.end::-webkit-slider-thumb {
+                width: 10px;
+                pointer-events: auto;
+                -webkit-appearance: none;
+                height: 10px;
+                cursor: ew-resize;
+                background: $dark-blue;
+                box-shadow: -100vw 0 0 100vw $light-blue;
+            }
+        }
+
         .toolbar-slider {
             margin-top: 5px;
             position: relative;
@@ -219,7 +266,7 @@ $light-background: #ececec;
             height: 10px;
             border-radius: 10px;
             -webkit-appearance: none;
-            background-color: #ececec;
+            background-color: $light-background;
         }
 
         .toolbar-slider:focus {
@@ -234,14 +281,44 @@ $light-background: #ececec;
 
         .toolbar-slider::-webkit-slider-thumb {
             width: 10px;
+            pointer-events: auto;
             -webkit-appearance: none;
             height: 10px;
             cursor: ew-resize;
-            background: #5b9ddd;
-            box-shadow: -100vw 0 0 100vw #aedef8;
+            background: $dark-blue;
+            box-shadow: -100vw 0 0 100vw $light-blue;
+        }
+
+        .presBox-checkbox {
+            -webkit-appearance: none;
+            -webkit-user-select: none;
+            -moz-user-select: none;
+            -ms-user-select: none;
+            user-select: none;
+            margin: 0;
+            margin-right: 3px;
+            border-radius: 100%;
+            height: 15px;
+            width: 15px;
+            cursor: pointer;
+            background: $light-background;
+        }
+
+        .presBox-checkbox:focus {
+            outline: none;
+        }
+
+        .presBox-checkbox:hover {
+            background: #c0c0c0;
+        }
+
+        .presBox-checkbox:checked {
+            background: $light-blue;
         }
     }
 
+
+
     .slider-headers {
         position: relative;
         display: grid;
diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx
index 1405016ae..9fb07040d 100644
--- a/src/client/views/nodes/PresBox.tsx
+++ b/src/client/views/nodes/PresBox.tsx
@@ -24,7 +24,6 @@ import { CollectionDockingView } from "../collections/CollectionDockingView";
 import { CollectionView, CollectionViewType } from "../collections/CollectionView";
 import { TabDocView } from "../collections/TabDocView";
 import { ViewBoxBaseComponent } from "../DocComponent";
-import { AudioBox } from "./AudioBox";
 import { CollectionFreeFormDocumentView } from "./CollectionFreeFormDocumentView";
 import { FieldView, FieldViewProps } from './FieldView';
 import "./PresBox.scss";
@@ -193,6 +192,10 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
     nextAudioVideo = (targetDoc: Doc, activeItem: Doc) => {
         if (targetDoc.type === DocumentType.AUDIO) {
             targetDoc._audioStart = NumCast(activeItem.presStartTime);
+
+        } else if (targetDoc.type === DocumentType.VID) {
+            targetDoc._currentTimecode = NumCast(activeItem.presStartTime);
+            setTimeout(() => targetDoc._videoStart = true, 0);
         }
         // if (targetDoc.type === DocumentType.VID) { VideoBox.Instance.Play() };
         activeItem.playNow = false;
@@ -214,7 +217,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
         // If next slide is audio / video 'Play automatically' then the next slide should be played
         if (activeNext && (targetNext.type === DocumentType.AUDIO || targetNext.type === DocumentType.VID) && activeNext.playAuto) {
             if (targetNext.type === DocumentType.AUDIO) targetNext._audioStart = 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'); }
     }
 
@@ -1071,6 +1073,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
     @computed get transitionDropdown() {
         const activeItem: Doc = this.activeItem;
         const targetDoc: Doc = this.targetDoc;
+        const type: DocumentType = targetDoc.type;
         const isPresCollection: boolean = (targetDoc === this.layoutDoc.presCollection);
         const isPinWithView: boolean = BoolCast(activeItem.presPinView);
         if (activeItem && targetDoc) {
@@ -1137,7 +1140,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
                             {isPresCollection ? (null) : <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 ? PresColor.LightBlue : "" }} onClick={() => this.updateOpenDoc(activeItem)}>Open</div></Tooltip>
                         </div>
-                        <div className="ribbon-doubleButton" >
+                        {(type === DocumentType.AUDIO || type === DocumentType.VID) ? (null) : <div className="ribbon-doubleButton" >
                             <div className="presBox-subheading">Slide Duration</div>
                             <div className="ribbon-property">
                                 <input className="presBox-input"
@@ -1152,7 +1155,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
                                     <FontAwesomeIcon icon={"caret-down"} />
                                 </div>
                             </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"
@@ -1235,20 +1238,233 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
             }
         });
     }
-    @computed get optionsDropdown() {
+
+    @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 ? PresColor.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;
+                                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)}
+                                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)}
+                                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)}
+                                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)}
+                                onChange={action((e: React.ChangeEvent<HTMLInputElement>) => { const val = e.target.value; activeItem.presPinViewScroll = Number(val); })} />
+                        </div>
+                    </div>
+                </div> : (null)}
+            </>
+        );
+    }
+
+    @computed get mediaOptionsDropdown() {
+        const activeItem: Doc = this.activeItem;
+        const targetDoc: Doc = this.targetDoc;
         if (activeItem && targetDoc) {
             return (
                 <div>
                     <div className={'presBox-ribbon'} onClick={e => e.stopPropagation()} onPointerUp={e => e.stopPropagation()} onPointerDown={e => e.stopPropagation()}>
-                        <div className="ribbon-box">
+                        <div>
+                            <div className="presBox-subheading">Start playing:</div>
+                            <div className="presBox-radioButtons">
+                                <div className="checkbox-container">
+                                    <input className="presBox-checkbox"
+                                        type="checkbox"
+                                        onChange={() => activeItem.mediaPlay = "manual"}
+                                        checked={activeItem.mediaPlay === "manual"}
+                                    />
+                                    <div>Start manually</div>
+                                </div>
+                                <div className="checkbox-container">
+                                    <input className="presBox-checkbox"
+                                        type="checkbox"
+                                        onChange={() => activeItem.mediaPlay = "auto"}
+                                        checked={activeItem.mediaPlay === "auto"}
+                                    />
+                                    <div>Play with slide</div>
+                                </div>
+                                <div className="checkbox-container">
+                                    <input className="presBox-checkbox"
+                                        type="checkbox"
+                                        onChange={() => activeItem.mediaPlay = "onClick"}
+                                        checked={activeItem.mediaPlay === "onClick"}
+                                    />
+                                    <div>Play on click</div>
+                                </div>
+                            </div>
+                            <div className="presBox-subheading">Stop playing:</div>
+                            <div className="presBox-radioButtons">
+                                <div className="checkbox-container">
+                                    <input className="presBox-checkbox"
+                                        type="checkbox"
+                                        onChange={() => activeItem.mediaStop = "manual"}
+                                        checked={activeItem.mediaStop === "manual"}
+                                    />
+                                    <div>Stop manually</div>
+                                </div>
+                                <div className="checkbox-container">
+                                    <input className="presBox-checkbox"
+                                        type="checkbox"
+                                        onChange={() => activeItem.mediaStop = "afterCurrent"}
+                                        checked={activeItem.mediaStop === "afterCurrent"}
+                                    />
+                                    <div>After current slide</div>
+                                </div>
+                                <div className="checkbox-container">
+                                    <input className="presBox-checkbox"
+                                        type="checkbox"
+                                        onChange={() => activeItem.mediaStop = "afterSlide"}
+                                        checked={activeItem.mediaStop === "afterSlide"}
+                                    />
+                                    <div>After slide
+                                    {activeItem.mediaStop !== "afterSlide" ?
+                                            (null)
+                                            :
+                                            <div className="presBox-dropdown" onClick={action(e => { e.stopPropagation(); this.openMovementDropdown = !this.openMovementDropdown; })} style={{ borderBottomLeftRadius: this.openMovementDropdown ? 0 : 5, border: this.openMovementDropdown ? `solid 2px ${PresColor.DarkBlue}` : 'solid 1px black' }}>
+                                                {this.setMovementName(activeItem.presMovement, activeItem)}
+                                                <FontAwesomeIcon className='presBox-dropdownIcon' style={{ gridColumn: 2, color: this.openMovementDropdown ? PresColor.DarkBlue : '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)}>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>
+                                </div>
+                            </div>
+                            <div className="presBox-subheading">Range:</div>
+                            <div className="multiThumb-slider">
+                                <input type="range" step="0.1" min="0" max={NumCast(activeItem.duration)} value={NumCast(activeItem.presEndTime)}
+                                    style={{ gridColumn: 1, gridRow: 1 }}
+                                    className={`toolbar-slider ${"end"}`}
+                                    id="toolbar-slider"
+                                    onPointerDown={() => this._batch = UndoManager.StartBatch("presEndTime")}
+                                    onPointerUp={() => this._batch?.end()}
+                                    onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
+                                        e.stopPropagation();
+                                        activeItem.presEndTime = Number(e.target.value);
+                                    }} />
+                                <input type="range" step="0.1" min="0" max={NumCast(activeItem.duration)} value={NumCast(activeItem.presStartTime)}
+                                    style={{ gridColumn: 1, gridRow: 1 }}
+                                    className={`toolbar-slider ${"start"}`}
+                                    id="toolbar-slider"
+                                    onPointerDown={() => this._batch = UndoManager.StartBatch("presEndTime")}
+                                    onPointerUp={() => this._batch?.end()}
+                                    onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
+                                        e.stopPropagation();
+                                        activeItem.presStartTime = Number(e.target.value);
+                                    }} />
+                            </div>
+                            <div className={`slider-headers ${activeItem.presMovement === PresMovement.Pan || activeItem.presMovement === PresMovement.Zoom ? "" : "none"}`}>
+                                <div className="slider-text">0 s</div>
+                                <div className="slider-text"></div>
+                                <div className="slider-text">{Math.round(NumCast(activeItem.duration))} s</div>
+                            </div>
+                        </div>
+                        {/* <div className="ribbon-box">
                             <div className="ribbon-doubleButton" style={{ display: targetDoc.type === DocumentType.AUDIO ? "inline-flex" : "none" }}>
                                 <div className="ribbon-toggle" style={{ backgroundColor: activeItem.playAuto ? PresColor.LightBlue : "" }} onClick={() => activeItem.playAuto = !activeItem.playAuto}>Play automatically</div>
                                 <div className="ribbon-toggle" style={{ display: "flex", backgroundColor: activeItem.playAuto ? "" : PresColor.LightBlue }} onClick={() => activeItem.playAuto = !activeItem.playAuto}>Play on next</div>
                             </div>
-                            {/* {targetDoc.type === DocumentType.VID ? <div className="ribbon-toggle" style={{ backgroundColor: activeItem.presVidFullScreen ? PresColor.LightBlue : "" }} 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 }}>
@@ -1267,98 +1483,7 @@ 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)}
-                            {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 ? PresColor.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;
-                                            activeItem.presPinViewX = x;
-                                            activeItem.presPinViewY = y;
-                                            activeItem.presPinViewScale = scale;
-                                        }
-                                    }}>Update</div></Tooltip> : (null)}
-                            </div>
-                            {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)}
-                                            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)}
-                                            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)}
-                                            onChange={action((e: React.ChangeEvent<HTMLInputElement>) => { const val = e.target.value; activeItem.presPinViewScale = Number(val); })} />
-                                    </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> */}
-                        </div>
+                        </div> */}
                     </div>
                 </div >
             );
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index 8ce76a347..998ca839d 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -21,6 +21,8 @@ import { documentSchema } from "../../../fields/documentSchemas";
 import { Networking } from "../../Network";
 import { SnappingManager } from "../../util/SnappingManager";
 import { SelectionManager } from "../../util/SelectionManager";
+import { LinkDocPreview } from "./LinkDocPreview";
+import { FormattedTextBoxComment } from "./formattedText/FormattedTextBoxComment";
 const path = require('path');
 
 export const timeSchema = createSchema({
@@ -32,8 +34,9 @@ const VideoDocument = makeInterface(documentSchema, timeSchema);
 @observer
 export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps, VideoDocument>(VideoDocument) {
     static _youtubeIframeCounter: number = 0;
-    private _reactionDisposer?: IReactionDisposer;
-    private _youtubeReactionDisposer?: IReactionDisposer;
+    // private _reactionDisposer?: IReactionDisposer;
+    // private _youtubeReactionDisposer?: IReactionDisposer;
+    private _disposers: { [name: string]: IReactionDisposer } = {};
     private _youtubePlayer: YT.Player | undefined = undefined;
     private _videoRef: HTMLVideoElement | null = null;
     private _youtubeIframeId: number = -1;
@@ -181,7 +184,32 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps, VideoD
 
     componentDidMount() {
         if (this.props.setVideoBox) this.props.setVideoBox(this);
-
+        this._disposers.videoStart = reaction(
+            () => this.Document._videoStart,
+            (videoStart) => {
+                if (videoStart !== undefined) {
+                    if (this.props.renderDepth !== -1 && !LinkDocPreview.TargetDoc && !FormattedTextBoxComment.linkDoc) {
+                        const delay = this.player ? 0 : 250; // wait for mainCont and try again to play
+                        setTimeout(() => this.player && this.Play(), delay);
+                        setTimeout(() => { this.Document._videoStart = undefined; }, 10 + delay);
+                    }
+                }
+            },
+            { fireImmediately: true }
+        );
+        this._disposers.videoStop = reaction(
+            () => this.Document._videoStop,
+            (videoStop) => {
+                if (videoStop !== undefined) {
+                    if (this.props.renderDepth !== -1 && !LinkDocPreview.TargetDoc && !FormattedTextBoxComment.linkDoc) {
+                        const delay = this.player ? 0 : 250; // wait for mainCont and try again to play
+                        setTimeout(() => this.player && this.Pause(), delay);
+                        setTimeout(() => { this.Document._videoStop = undefined; }, 10 + delay);
+                    }
+                }
+            },
+            { fireImmediately: true }
+        );
         if (this.youtubeVideoId) {
             const youtubeaspect = 400 / 315;
             const nativeWidth = Doc.NativeWidth(this.layoutDoc);
@@ -196,8 +224,9 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps, VideoD
 
     componentWillUnmount() {
         this.Pause();
-        this._reactionDisposer?.();
-        this._youtubeReactionDisposer?.();
+        this._disposers.reactionDisposer?.();
+        this._disposers.youtubeReactionDisposer?.();
+        this._disposers.videoStart?.();
     }
 
     @action
@@ -207,8 +236,8 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps, VideoD
             this._videoRef!.ontimeupdate = this.updateTimecode;
             // @ts-ignore
             vref.onfullscreenchange = action((e) => this._fullScreen = vref.webkitDisplayingFullscreen);
-            this._reactionDisposer?.();
-            this._reactionDisposer = reaction(() => (this.layoutDoc._currentTimecode || 0),
+            this._disposers.reactionDisposer?.();
+            this._disposers.reactionDisposer = reaction(() => (this.layoutDoc._currentTimecode || 0),
                 time => !this._playing && (vref.currentTime = time), { fireImmediately: true });
         }
     }
@@ -293,10 +322,10 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps, VideoD
             if (event.data === YT.PlayerState.PAUSED && this._playing) this.Pause(false);
         });
         const onYoutubePlayerReady = (event: any) => {
-            this._reactionDisposer?.();
-            this._youtubeReactionDisposer?.();
-            this._reactionDisposer = reaction(() => this.layoutDoc._currentTimecode, () => !this._playing && this.Seek((this.layoutDoc._currentTimecode || 0)));
-            this._youtubeReactionDisposer = reaction(
+            this._disposers.reactionDisposer?.();
+            this._disposers.youtubeReactionDisposer?.();
+            this._disposers.reactionDisposer = reaction(() => this.layoutDoc._currentTimecode, () => !this._playing && this.Seek((this.layoutDoc._currentTimecode || 0)));
+            this._disposers.youtubeReactionDisposer = reaction(
                 () => !this.props.Document.isAnnotating && Doc.GetSelectedTool() === InkTool.None && this.props.isSelected(true) && !SnappingManager.GetIsDragging() && !DocumentDecorations.Instance.Interacting,
                 (interactive) => iframe.style.pointerEvents = interactive ? "all" : "none", { fireImmediately: true });
         };
diff --git a/src/client/views/presentationview/PresElementBox.scss b/src/client/views/presentationview/PresElementBox.scss
index ed1aa9a1e..e1eeefc30 100644
--- a/src/client/views/presentationview/PresElementBox.scss
+++ b/src/client/views/presentationview/PresElementBox.scss
@@ -122,12 +122,6 @@ $slide-active: #5B9FDD;
     }
 
 
-    .presItem-slideButtons {
-        display: none;
-    }
-}
-
-.presItem-slide:hover {
     .presItem-slideButtons {
         display: flex;
         grid-column: 7;
@@ -162,6 +156,41 @@ $slide-active: #5B9FDD;
     }
 }
 
+// .presItem-slide:hover {
+    //     .presItem-slideButtons {
+    //         display: flex;
+    //         grid-column: 7;
+    //         grid-row: 1/3;
+    //         width: max-content;
+    //         justify-self: right;
+    //         justify-content: flex-end;
+
+    //         .slideButton {
+    //             cursor: pointer;
+    //             position: relative;
+    //             border-radius: 100px;
+    //             z-index: 300;
+    //             width: 18px;
+    //             height: 18px;
+    //             display: flex;
+    //             font-size: 12px;
+    //             justify-self: center;
+    //             align-self: center;
+    //             background-color: rgba(0, 0, 0, 0.5);
+    //             color: white;
+    //             justify-content: center;
+    //             align-items: center;
+    //             transition: 0.2s;
+    //             margin-right: 3px;
+    //         }
+
+    //         .slideButton:hover {
+    //             background-color: rgba(0, 0, 0, 1);
+    //             transform: scale(1.2);
+    //         }
+    //     }
+    // }
+
 .presItem-slide.active {
     box-shadow: 0 0 0px 1.5px $dark-blue;
 }
diff --git a/src/client/views/presentationview/PresElementBox.tsx b/src/client/views/presentationview/PresElementBox.tsx
index 463249ab8..9ec39b792 100644
--- a/src/client/views/presentationview/PresElementBox.tsx
+++ b/src/client/views/presentationview/PresElementBox.tsx
@@ -348,6 +348,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDoc
                             <div className="slideButton"
                                 onClick={() => activeItem.groupWithUp = !activeItem.groupWithUp}
                                 style={{
+                                    zIndex: 1000 - this.indexInPres,
                                     fontWeight: 700,
                                     backgroundColor: activeItem.groupWithUp ? presColorBool ? presBoxColor : PresColor.DarkBlue : undefined,
                                     height: activeItem.groupWithUp ? 53 : 18,
@@ -367,7 +368,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDoc
                             <FontAwesomeIcon icon={"trash"} onPointerDown={e => e.stopPropagation()} />
                         </div></Tooltip>
                     </div>
-                    <div className="presItem-docName" style={{ maxWidth: showMore ? (toolbarWidth - 185) : toolbarWidth - 95 }}>{activeItem.presPinView ? (<><i>View of </i> {targetDoc.title}</>) : targetDoc.title}</div>
+                    <div className="presItem-docName" style={{ maxWidth: showMore ? (toolbarWidth - 195) : toolbarWidth - 105 }}>{activeItem.presPinView ? (<><i>View of </i> {targetDoc.title}</>) : targetDoc.title}</div>
                     {this.renderEmbeddedInline}
                 </div>}
             </div >);
diff --git a/src/client/views/presentationview/PresProperties.tsx b/src/client/views/presentationview/PresProperties.tsx
new file mode 100644
index 000000000..edad41861
--- /dev/null
+++ b/src/client/views/presentationview/PresProperties.tsx
@@ -0,0 +1,492 @@
+import React from "react";
+import { action, computed, observable, reaction } from "mobx";
+import { Doc } from "../../../fields/Doc";
+import { BoolCast, Cast, NumCast } from "../../../fields/Types";
+import { undoBatch, UndoManager } from "../../util/UndoManager";
+import { PresBox, PresColor, PresEffect, PresMovement } from "../nodes/PresBox";
+import { DocumentType } from "../../documents/DocumentTypes";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { CollectionViewType } from "../collections/CollectionView";
+import { Tooltip } from "@material-ui/core";
+
+
+export class PresProperties {
+
+    @observable public static Instance: PresProperties;
+
+    @computed get pres(): PresBox { return PresBox.Instance; }
+
+    @computed get activeItem() { return Cast(this.pres.childDocs[NumCast(PresBox.Instance.rootDoc._itemIndex)], Doc, null); }
+    @computed get targetDoc() { return Cast(this.pres.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;
+        else return false;
+    }
+    @computed get panable(): boolean {
+        if ((this.targetDoc.type === DocumentType.COL && this.targetDoc._viewType === CollectionViewType.Freeform) || this.targetDoc.type === DocumentType.IMG) return true;
+        else return false;
+    }
+
+
+    @observable private openMovementDropdown: boolean = false;
+    @observable private openEffectDropdown: boolean = false;
+
+    _batch: UndoManager.Batch | undefined = undefined;
+
+
+    @computed get effectDirection(): string {
+        let effect = '';
+        switch (this.targetDoc.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;
+        }
+        return effect;
+    }
+
+    @undoBatch
+    @action
+    updateHideBefore = (activeItem: Doc) => {
+        activeItem.presHideBefore = !activeItem.presHideBefore;
+        Array.from(this.pres._selectedArray.keys()).forEach((doc) => doc.presHideBefore = activeItem.presHideBefore);
+    }
+
+    @undoBatch
+    @action
+    updateHideAfter = (activeItem: Doc) => {
+        activeItem.presHideAfter = !activeItem.presHideAfter;
+        Array.from(this.pres._selectedArray.keys()).forEach((doc) => doc.presHideAfter = activeItem.presHideAfter);
+    }
+
+    @undoBatch
+    @action
+    updateOpenDoc = (activeItem: Doc) => {
+        activeItem.openDocument = !activeItem.openDocument;
+        Array.from(this.pres._selectedArray.keys()).forEach((doc) => {
+            doc.openDocument = activeItem.openDocument;
+        });
+    }
+
+    /**
+     * When the movement dropdown is changes
+     */
+    @undoBatch
+    updateMovement = action((movement: any, all?: boolean) => {
+        const array: any[] = all ? this.pres.childDocs : Array.from(this.pres._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
+    updateEffect = (effect: any, all?: boolean) => {
+        const array: any[] = all ? this.pres.childDocs : Array.from(this.pres._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;
+            }
+        });
+    }
+
+    @undoBatch
+    @action
+    updateEffectDirection = (effect: any, all?: boolean) => {
+        const array: any[] = all ? this.pres.childDocs : Array.from(this.pres._selectedArray.keys());
+        array.forEach((doc) => {
+            const tagDoc = Cast(doc.presentationTargetDoc, Doc, null);
+            switch (effect) {
+                case PresEffect.Left:
+                    tagDoc.presEffectDirection = PresEffect.Left;
+                    break;
+                case PresEffect.Right:
+                    tagDoc.presEffectDirection = PresEffect.Right;
+                    break;
+                case PresEffect.Top:
+                    tagDoc.presEffectDirection = PresEffect.Top;
+                    break;
+                case PresEffect.Bottom:
+                    tagDoc.presEffectDirection = PresEffect.Bottom;
+                    break;
+                case PresEffect.Center: default:
+                    tagDoc.presEffectDirection = PresEffect.Center;
+                    break;
+            }
+        });
+    }
+
+    // Converts seconds to ms and updates presTransition
+    setTransitionTime = (number: String, change?: number) => {
+        let timeInMS = Number(number) * 1000;
+        if (change) timeInMS += change;
+        if (timeInMS < 100) timeInMS = 100;
+        if (timeInMS > 10000) timeInMS = 10000;
+        Array.from(PresBox.Instance._selectedArray.keys()).forEach((doc) => doc.presTransition = timeInMS);
+    }
+
+    // Converts seconds to ms and updates presDuration
+    setDurationTime = (number: String, change?: number) => {
+        let timeInMS = Number(number) * 1000;
+        if (change) timeInMS += change;
+        if (timeInMS < 100) timeInMS = 100;
+        if (timeInMS > 20000) timeInMS = 20000;
+        Array.from(PresBox.Instance._selectedArray.keys()).forEach((doc) => doc.presDuration = timeInMS);
+    }
+
+    setMovementName = action((movement: any, activeItem: Doc): string => {
+        let output: string = 'none';
+        switch (movement) {
+            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 = 'No Movement'; break; //None
+            default: output = 'Zoom'; activeItem.presMovement = 'zoom'; break; //default set as zoom
+        }
+        return output;
+    });
+
+    @computed get transitionDropdown() {
+        const activeItem: Doc = this.activeItem;
+        const targetDoc: Doc = this.targetDoc;
+        const isPresCollection: boolean = (targetDoc === this.pres.layoutDoc.presCollection);
+        const isPinWithView: boolean = BoolCast(activeItem.presPinView);
+        if (activeItem && targetDoc) {
+            const transitionSpeed = activeItem.presTransition ? NumCast(activeItem.presTransition) / 1000 : 0.5;
+            let duration = activeItem.presDuration ? NumCast(activeItem.presDuration) / 1000 : 2;
+            if (activeItem.type === DocumentType.AUDIO) duration = NumCast(activeItem.duration);
+            const effect = targetDoc.presEffect ? targetDoc.presEffect : 'None';
+            activeItem.presMovement = activeItem.presMovement ? activeItem.presMovement : 'Zoom';
+            return (
+                <div className={`presBox-ribbon ${this.pres.layoutDoc.presStatus === "edit" ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onPointerUp={e => e.stopPropagation()} onClick={action(e => { e.stopPropagation(); this.openMovementDropdown = false; this.openEffectDropdown = false; })}>
+                    <div className="ribbon-box">
+                        Movement
+                        {isPresCollection || (isPresCollection && isPinWithView) ?
+                            <div className="ribbon-property" style={{ marginLeft: 0, height: 25, textAlign: 'left', paddingLeft: 5, paddingRight: 5, fontSize: 10 }}>
+                                {this.scrollable ? "Scroll to pinned view" : !isPinWithView ? "No movement" : "Pan & Zoom to pinned view"}
+                            </div>
+                            :
+                            <div className="presBox-dropdown" onClick={action(e => { e.stopPropagation(); this.openMovementDropdown = !this.openMovementDropdown; })} style={{ borderBottomLeftRadius: this.openMovementDropdown ? 0 : 5, border: this.openMovementDropdown ? `solid 2px ${PresColor.DarkBlue}` : 'solid 1px black' }}>
+                                {this.setMovementName(activeItem.presMovement, activeItem)}
+                                <FontAwesomeIcon className='presBox-dropdownIcon' style={{ gridColumn: 2, color: this.openMovementDropdown ? PresColor.DarkBlue : '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)}>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" }}>
+                            <div className="presBox-subheading">Transition Speed</div>
+                            <div className="ribbon-property">
+                                <input className="presBox-input"
+                                    type="number" value={transitionSpeed}
+                                    onChange={action((e) => this.setTransitionTime(e.target.value))} /> s
+                            </div>
+                            <div className="ribbon-propertyUpDown">
+                                <div className="ribbon-propertyUpDownItem" onClick={undoBatch(() => this.setTransitionTime(String(transitionSpeed), 1000))}>
+                                    <FontAwesomeIcon icon={"caret-up"} />
+                                </div>
+                                <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"
+                            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>
+                            <div className="slider-text">Slow</div>
+                        </div>
+                    </div>
+                    <div className="ribbon-box">
+                        Visibility {"&"} Duration
+                        <div className="ribbon-doubleButton">
+                            {isPresCollection ? (null) : <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>}
+                            {isPresCollection ? (null) : <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 ? PresColor.LightBlue : "" }} 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}
+                                    onChange={action((e) => this.setDurationTime(e.target.value))} /> s
+                            </div>
+                            <div className="ribbon-propertyUpDown">
+                                <div className="ribbon-propertyUpDownItem" onClick={undoBatch(() => this.setDurationTime(String(duration), 1000))}>
+                                    <FontAwesomeIcon icon={"caret-up"} />
+                                </div>
+                                <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"
+                            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>
+                            <div className="slider-text">Long</div>
+                        </div>
+                    </div>
+                    {isPresCollection ? (null) : <div className="ribbon-box">
+                        Effects
+                        <div className="presBox-dropdown" onClick={action(e => { e.stopPropagation(); this.openEffectDropdown = !this.openEffectDropdown; })} style={{ borderBottomLeftRadius: this.openEffectDropdown ? 0 : 5, border: this.openEffectDropdown ? `solid 2px ${PresColor.DarkBlue}` : 'solid 1px black' }}>
+                            {effect}
+                            <FontAwesomeIcon className='presBox-dropdownIcon' style={{ gridColumn: 2, color: this.openEffectDropdown ? PresColor.DarkBlue : 'black' }} icon={"angle-down"} />
+                            <div className={'presBox-dropdownOptions'} id={'presBoxMovementDropdown'} style={{ display: this.openEffectDropdown ? "grid" : "none" }} onPointerDown={e => e.stopPropagation()}>
+                                <div className={`presBox-dropdownOption ${targetDoc.presEffect === PresEffect.None || !targetDoc.presEffect ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.updateEffect(PresEffect.None)}>None</div>
+                                <div className={`presBox-dropdownOption ${targetDoc.presEffect === PresEffect.Fade ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.updateEffect(PresEffect.Fade)}>Fade In</div>
+                                <div className={`presBox-dropdownOption ${targetDoc.presEffect === PresEffect.Flip ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.updateEffect(PresEffect.Flip)}>Flip</div>
+                                <div className={`presBox-dropdownOption ${targetDoc.presEffect === PresEffect.Rotate ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.updateEffect(PresEffect.Rotate)}>Rotate</div>
+                                <div className={`presBox-dropdownOption ${targetDoc.presEffect === PresEffect.Bounce ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.updateEffect(PresEffect.Bounce)}>Bounce</div>
+                                <div className={`presBox-dropdownOption ${targetDoc.presEffect === PresEffect.Roll ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.updateEffect(PresEffect.Roll)}>Roll</div>
+                            </div>
+                        </div>
+                        <div className="ribbon-doubleButton" style={{ display: effect === 'None' ? "none" : "inline-flex" }}>
+                            <div className="presBox-subheading" >Effect direction</div>
+                            <div className="ribbon-property">
+                                {this.effectDirection}
+                            </div>
+                        </div>
+                        <div className="effectDirection" style={{ display: effect === 'None' ? "none" : "grid", width: 40 }}>
+                            <Tooltip title={<><div className="dash-tooltip">{"Enter from left"}</div></>}><div style={{ gridColumn: 1, gridRow: 2, justifySelf: 'center', color: targetDoc.presEffectDirection === PresEffect.Left ? PresColor.LightBlue : "black", cursor: "pointer" }} onClick={() => this.updateEffectDirection(PresEffect.Left)}><FontAwesomeIcon icon={"angle-right"} /></div></Tooltip>
+                            <Tooltip title={<><div className="dash-tooltip">{"Enter from right"}</div></>}><div style={{ gridColumn: 3, gridRow: 2, justifySelf: 'center', color: targetDoc.presEffectDirection === PresEffect.Right ? PresColor.LightBlue : "black", cursor: "pointer" }} onClick={() => this.updateEffectDirection(PresEffect.Right)}><FontAwesomeIcon icon={"angle-left"} /></div></Tooltip>
+                            <Tooltip title={<><div className="dash-tooltip">{"Enter from top"}</div></>}><div style={{ gridColumn: 2, gridRow: 1, justifySelf: 'center', color: targetDoc.presEffectDirection === PresEffect.Top ? PresColor.LightBlue : "black", cursor: "pointer" }} onClick={() => this.updateEffectDirection(PresEffect.Top)}><FontAwesomeIcon icon={"angle-down"} /></div></Tooltip>
+                            <Tooltip title={<><div className="dash-tooltip">{"Enter from bottom"}</div></>}><div style={{ gridColumn: 2, gridRow: 3, justifySelf: 'center', color: targetDoc.presEffectDirection === PresEffect.Bottom ? PresColor.LightBlue : "black", cursor: "pointer" }} onClick={() => this.updateEffectDirection(PresEffect.Bottom)}><FontAwesomeIcon icon={"angle-up"} /></div></Tooltip>
+                            <Tooltip title={<><div className="dash-tooltip">{"Enter from center"}</div></>}><div style={{ gridColumn: 2, gridRow: 2, width: 10, height: 10, alignSelf: 'center', justifySelf: 'center', border: targetDoc.presEffectDirection === PresEffect.Center || !targetDoc.presEffectDirection ? `solid 2px ${PresColor.LightBlue}` : "solid 2px black", borderRadius: "100%", cursor: "pointer" }} onClick={() => this.updateEffectDirection(PresEffect.Center)}></div></Tooltip>
+                        </div>
+                    </div>}
+                    <div className="ribbon-final-box">
+                        <div className="ribbon-final-button-hidden" onClick={() => this.applyTo(this.pres.childDocs)}>
+                            Apply to all
+                        </div>
+                    </div>
+                </div >
+            );
+        }
+    }
+
+    @undoBatch
+    @action
+    applyTo = (array: Doc[]) => {
+        const activeItem: Doc = this.activeItem;
+        const targetDoc: Doc = this.targetDoc;
+        this.updateMovement(activeItem.presMovement, true);
+        this.updateEffect(targetDoc.presEffect, true);
+        this.updateEffectDirection(targetDoc.presEffectDirection, true);
+        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;
+                curDoc.presHideBefore = activeItem.presHideBefore;
+                curDoc.presHideAfter = activeItem.presHideAfter;
+            }
+        });
+    }
+
+    @computed get mediaOptionsDropdown() {
+        const activeItem: Doc = this.activeItem;
+        const targetDoc: Doc = this.targetDoc;
+        if (activeItem && targetDoc) {
+            return (
+                <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.AUDIO ? "inline-flex" : "none" }}>
+                                <div className="ribbon-toggle" style={{ backgroundColor: activeItem.playAuto ? PresColor.LightBlue : "" }} onClick={() => activeItem.playAuto = !activeItem.playAuto}>Play automatically</div>
+                                <div className="ribbon-toggle" style={{ display: "flex", backgroundColor: activeItem.playAuto ? "" : PresColor.LightBlue }} onClick={() => activeItem.playAuto = !activeItem.playAuto}>Play on next</div>
+                            </div>
+                            {/* {targetDoc.type === DocumentType.VID ? <div className="ribbon-toggle" style={{ backgroundColor: activeItem.presVidFullScreen ? PresColor.LightBlue : "" }} 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"
+                                        style={{ textAlign: 'left', width: 50 }}
+                                        type="number" value={NumCast(activeItem.presStartTime)}
+                                        onChange={action((e: React.ChangeEvent<HTMLInputElement>) => { activeItem.presStartTime = Number(e.target.value); })} />
+                                </div>
+                            </div> : (null)}
+                            {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"
+                                        style={{ textAlign: 'left', width: 50 }}
+                                        type="number" value={NumCast(activeItem.presEndTime)}
+                                        onChange={action((e: React.ChangeEvent<HTMLInputElement>) => { const val = e.target.value; activeItem.presEndTime = Number(val); })} />
+                                </div>
+                            </div> : (null)}
+                        </div>
+                    </div>
+                </div >
+            );
+        }
+    }
+
+    @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 ? PresColor.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;
+                                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)}
+                                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)}
+                                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)}
+                                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)}
+                                onChange={action((e: React.ChangeEvent<HTMLInputElement>) => { const val = e.target.value; activeItem.presPinViewScroll = Number(val); })} />
+                        </div>
+                    </div>
+                </div> : (null)}
+            </>
+        );
+    }
+}
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2


From e72068df41088f2bd842733f0e45cdfb4d28e6de Mon Sep 17 00:00:00 2001
From: geireann <60007097+geireann@users.noreply.github.com>
Date: Sun, 29 Nov 2020 13:24:34 +0800
Subject: pres trails temporal media and fixing group with up

---
 src/client/views/MainView.tsx                      |   2 +-
 .../views/collections/CollectionStackingView.tsx   |   2 +-
 src/client/views/collections/TabDocView.tsx        |   6 +-
 src/client/views/nodes/PresBox.tsx                 | 116 ++++++++++++++-------
 .../views/presentationview/PresElementBox.tsx      |   2 +-
 5 files changed, 83 insertions(+), 45 deletions(-)

(limited to 'src/client/views/MainView.tsx')

diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index b1e008dad..3c46e0f89 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -148,7 +148,7 @@ export class MainView extends React.Component {
             fa.faSearch, fa.faFileDownload, fa.faFileUpload, fa.faStop, fa.faCalculator, fa.faWindowMaximize, fa.faAddressCard, fa.faQuestionCircle, fa.faArrowLeft,
             fa.faArrowRight, fa.faArrowDown, fa.faArrowUp, fa.faBolt, fa.faBullseye, fa.faCaretUp, fa.faCat, fa.faCheck, fa.faChevronRight, fa.faChevronLeft, fa.faChevronDown, fa.faChevronUp,
             fa.faClone, fa.faCloudUploadAlt, fa.faCommentAlt, fa.faCompressArrowsAlt, fa.faCut, fa.faEllipsisV, fa.faEraser, fa.faExclamation, fa.faFileAlt,
-            fa.faFileAudio, fa.faFilePdf, fa.faFilm, fa.faFilter, fa.faFont, fa.faGlobeAmericas, fa.faGlobeAsia, fa.faHighlighter, fa.faLongArrowAltRight, fa.faMousePointer,
+            fa.faFileAudio, fa.faFileVideo, fa.faFilePdf, fa.faFilm, fa.faFilter, fa.faFont, fa.faGlobeAmericas, fa.faGlobeAsia, fa.faHighlighter, fa.faLongArrowAltRight, fa.faMousePointer,
             fa.faMusic, fa.faObjectGroup, fa.faPause, fa.faPen, fa.faPenNib, fa.faPhone, fa.faPlay, fa.faPortrait, fa.faRedoAlt, fa.faStamp, fa.faStickyNote,
             fa.faTimesCircle, fa.faThumbtack, fa.faTree, fa.faTv, fa.faUndoAlt, fa.faVideo, fa.faAsterisk, fa.faBrain, fa.faImage, fa.faPaintBrush, fa.faTimes,
             fa.faEye, fa.faArrowsAlt, fa.faQuoteLeft, fa.faSortAmountDown, fa.faAlignLeft, fa.faAlignCenter, fa.faAlignRight, fa.faHeading, fa.faRulerCombined,
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index 35331cc15..4b3393e14 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -290,7 +290,7 @@ export class CollectionStackingView extends CollectionSubView<StackingDocument,
                     dropAfter = where[axis] > (pos[axis] + pos1[axis]) / 2 ? 1 : 0;
                 }
             });
-            // const oldDocs = this.childDocs.length;
+            const oldDocs = this.childDocs.length;
             if (super.onInternalDrop(e, de)) {
                 const droppedDocs = this.childDocs.slice().filter((d: Doc, ind: number) => ind >= oldDocs); // if the drop operation adds something to the end of the list, then use that as the new document (may be different than what was dropped e.g., in the case of a button which is dropped but which creates say, a note).
                 const newDocs = droppedDocs.length ? droppedDocs : de.complete.docDragData.droppedDocuments; // if nothing was added to the end of the list, then presumably the dropped documents were already in the list, but possibly got reordered so we use them.
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index 45fab480c..0f228bc06 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -172,9 +172,11 @@ export class TabDocView extends React.Component<TabDocViewProps> {
             const size: number = PresBox.Instance?._selectedArray.size;
             const presSelected: Doc | undefined = presArray && size ? presArray[size - 1] : undefined;
             Doc.AddDocToList(curPres, "data", pinDoc, presSelected);
-            if (pinDoc.type === "audio" && !audioRange) {
+            if (pinDoc.type === DocumentType.AUDIO || pinDoc.type === DocumentType.VID && !audioRange) {
+                pinDoc.mediaStart = "manual";
+                pinDoc.mediaStop = "manual";
                 pinDoc.presStartTime = 0;
-                pinDoc.presEndTime = doc.duration;
+                pinDoc.presEndTime = pinDoc.type === DocumentType.AUDIO ? doc.duration : NumCast(doc["data-duration"]);
             }
             if (curPres.expandBoolean) pinDoc.presExpandInlineButton = true;
             const dview = CollectionDockingView.Instance.props.Document;
diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx
index 9fb07040d..ed2cb9fa1 100644
--- a/src/client/views/nodes/PresBox.tsx
+++ b/src/client/views/nodes/PresBox.tsx
@@ -210,7 +210,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
                 break;
             } else {
                 console.log("Title: " + this.childDocs[nextSelected].title);
-                this.gotoDocument(nextSelected);
+                this.gotoDocument(nextSelected, true);
             }
         }
         const targetNext = Cast(activeNext.presentationTargetDoc, Doc, null);
@@ -276,7 +276,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
 
     //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) => {
+    public gotoDocument = action((index: number, group?: boolean) => {
         Doc.UnBrushAllDocs();
         if (index >= 0 && index < this.childDocs.length) {
             this.rootDoc._itemIndex = index;
@@ -292,9 +292,9 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
             if (presTargetDoc?.lastFrame !== undefined) {
                 presTargetDoc._currentFrame = 0;
             }
-            this._selectedArray.clear();
+            if (!group) this._selectedArray.clear();
             this.childDocs[index] && this._selectedArray.set(this.childDocs[index], undefined); //Update selected array
-            if (this.layoutDoc._viewType === "stacking") this.navigateToElement(this.childDocs[index]); //Handles movement to element only when presTrail is list
+            if (this.layoutDoc._viewType === "stacking" && !group) this.navigateToElement(this.childDocs[index]); //Handles movement to element only when presTrail is list
             this.onHideDocument(); //Handles hide after/before
         }
     });
@@ -1073,7 +1073,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
     @computed get transitionDropdown() {
         const activeItem: Doc = this.activeItem;
         const targetDoc: Doc = this.targetDoc;
-        const type: DocumentType = targetDoc.type;
+        const type = targetDoc.type;
         const isPresCollection: boolean = (targetDoc === this.layoutDoc.presCollection);
         const isPinWithView: boolean = BoolCast(activeItem.presPinView);
         if (activeItem && targetDoc) {
@@ -1103,7 +1103,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
                             </div>
                         }
                         <div className="ribbon-doubleButton" style={{ display: activeItem.presMovement === PresMovement.Pan || activeItem.presMovement === PresMovement.Zoom ? "inline-flex" : "none" }}>
-                            <div className="presBox-subheading">Transition Speed</div>
+                            <div className="presBox-subheading">Movement Speed</div>
                             <div className="ribbon-property">
                                 <input className="presBox-input"
                                     type="number" value={transitionSpeed}
@@ -1140,34 +1140,36 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
                             {isPresCollection ? (null) : <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 ? PresColor.LightBlue : "" }} onClick={() => this.updateOpenDoc(activeItem)}>Open</div></Tooltip>
                         </div>
-                        {(type === DocumentType.AUDIO || type === DocumentType.VID) ? (null) : <div className="ribbon-doubleButton" >
-                            <div className="presBox-subheading">Slide Duration</div>
-                            <div className="ribbon-property">
-                                <input className="presBox-input"
-                                    type="number" value={duration}
-                                    onChange={action((e) => this.setDurationTime(e.target.value))} /> s
+                        {(type === DocumentType.AUDIO || type === DocumentType.VID) ? (null) : <>
+                            <div className="ribbon-doubleButton" >
+                                <div className="presBox-subheading">Slide Duration</div>
+                                <div className="ribbon-property">
+                                    <input className="presBox-input"
+                                        type="number" value={duration}
+                                        onChange={action((e) => this.setDurationTime(e.target.value))} /> s
                             </div>
-                            <div className="ribbon-propertyUpDown">
-                                <div className="ribbon-propertyUpDownItem" onClick={undoBatch(() => this.setDurationTime(String(duration), 1000))}>
-                                    <FontAwesomeIcon icon={"caret-up"} />
-                                </div>
-                                <div className="ribbon-propertyUpDownItem" onClick={undoBatch(() => this.setDurationTime(String(duration), -1000))}>
-                                    <FontAwesomeIcon icon={"caret-down"} />
+                                <div className="ribbon-propertyUpDown">
+                                    <div className="ribbon-propertyUpDownItem" onClick={undoBatch(() => this.setDurationTime(String(duration), 1000))}>
+                                        <FontAwesomeIcon icon={"caret-up"} />
+                                    </div>
+                                    <div className="ribbon-propertyUpDownItem" onClick={undoBatch(() => this.setDurationTime(String(duration), -1000))}>
+                                        <FontAwesomeIcon icon={"caret-down"} />
+                                    </div>
                                 </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"
-                            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>
-                            <div className="slider-text">Long</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"
+                                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>
+                                <div className="slider-text">Long</div>
+                            </div>
+                        </>}
                     </div>
                     {isPresCollection ? (null) : <div className="ribbon-box">
                         Effects
@@ -1368,24 +1370,24 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
                                 <div className="checkbox-container">
                                     <input className="presBox-checkbox"
                                         type="checkbox"
-                                        onChange={() => activeItem.mediaPlay = "manual"}
-                                        checked={activeItem.mediaPlay === "manual"}
+                                        onChange={() => activeItem.mediaStart = "manual"}
+                                        checked={activeItem.mediaStart === "manual"}
                                     />
                                     <div>Start manually</div>
                                 </div>
                                 <div className="checkbox-container">
                                     <input className="presBox-checkbox"
                                         type="checkbox"
-                                        onChange={() => activeItem.mediaPlay = "auto"}
-                                        checked={activeItem.mediaPlay === "auto"}
+                                        onChange={() => activeItem.mediaStart = "auto"}
+                                        checked={activeItem.mediaStart === "auto"}
                                     />
                                     <div>Play with slide</div>
                                 </div>
                                 <div className="checkbox-container">
                                     <input className="presBox-checkbox"
                                         type="checkbox"
-                                        onChange={() => activeItem.mediaPlay = "onClick"}
-                                        checked={activeItem.mediaPlay === "onClick"}
+                                        onChange={() => activeItem.mediaStart = "onClick"}
+                                        checked={activeItem.mediaStart === "onClick"}
                                     />
                                     <div>Play on click</div>
                                 </div>
@@ -1432,8 +1434,42 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
                                 </div>
                             </div>
                             <div className="presBox-subheading">Range:</div>
+                            <div className={`slider-headers ${activeItem.presMovement === PresMovement.Pan || activeItem.presMovement === PresMovement.Zoom ? "" : "none"}`}>
+                                <div className="slider-text">
+                                    Start time:
+                                </div>
+                                <div className="slider-text">
+                                    Duration:
+                                </div>
+                                <div className="slider-text">
+                                    End time:
+                                </div>
+                            </div>
+                            <div className={`slider-headers ${activeItem.presMovement === PresMovement.Pan || activeItem.presMovement === PresMovement.Zoom ? "" : "none"}`}>
+                                <div className="slider-text">
+                                    <div className="ribbon-property" style={{ paddingRight: 0, paddingLeft: 0 }}>
+                                        <input className="presBox-input"
+                                            style={{ textAlign: 'left', width: 50 }}
+                                            type="number" value={NumCast(activeItem.presStartTime)}
+                                            onChange={action((e: React.ChangeEvent<HTMLInputElement>) => { activeItem.presStartTime = Number(e.target.value); })}
+                                        /> s
+                                    </div>
+                                </div>
+                                <div className="slider-text">
+                                    {Math.round((NumCast(activeItem.presEndTime) - NumCast(activeItem.presStartTime)) * 10) / 10} s
+                                </div>
+                                <div className="slider-text">
+                                    <div className="ribbon-property" style={{ paddingRight: 0, paddingLeft: 0 }}>
+                                        <input className="presBox-input"
+                                            style={{ textAlign: 'right', width: 50 }}
+                                            type="number" value={NumCast(activeItem.presEndTime)}
+                                            onChange={action((e: React.ChangeEvent<HTMLInputElement>) => { activeItem.presEndTime = Number(e.target.value); })}
+                                        /> s
+                                    </div>
+                                </div>
+                            </div>
                             <div className="multiThumb-slider">
-                                <input type="range" step="0.1" min="0" max={NumCast(activeItem.duration)} value={NumCast(activeItem.presEndTime)}
+                                <input type="range" step="0.1" min="0" max={activeItem.type === DocumentType.AUDIO ? Math.round(NumCast(activeItem.duration) * 10) / 10 : Math.round(NumCast(activeItem["data-duration"]) * 10) / 10} value={NumCast(activeItem.presEndTime)}
                                     style={{ gridColumn: 1, gridRow: 1 }}
                                     className={`toolbar-slider ${"end"}`}
                                     id="toolbar-slider"
@@ -1443,7 +1479,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
                                         e.stopPropagation();
                                         activeItem.presEndTime = Number(e.target.value);
                                     }} />
-                                <input type="range" step="0.1" min="0" max={NumCast(activeItem.duration)} value={NumCast(activeItem.presStartTime)}
+                                <input type="range" step="0.1" min="0" max={activeItem.type === DocumentType.AUDIO ? Math.round(NumCast(activeItem.duration) * 10) / 10 : Math.round(NumCast(activeItem["data-duration"]) * 10) / 10} value={NumCast(activeItem.presStartTime)}
                                     style={{ gridColumn: 1, gridRow: 1 }}
                                     className={`toolbar-slider ${"start"}`}
                                     id="toolbar-slider"
@@ -1457,7 +1493,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
                             <div className={`slider-headers ${activeItem.presMovement === PresMovement.Pan || activeItem.presMovement === PresMovement.Zoom ? "" : "none"}`}>
                                 <div className="slider-text">0 s</div>
                                 <div className="slider-text"></div>
-                                <div className="slider-text">{Math.round(NumCast(activeItem.duration))} s</div>
+                                <div className="slider-text">{activeItem.type === DocumentType.AUDIO ? Math.round(NumCast(activeItem.duration) * 10) / 10 : Math.round(NumCast(activeItem["data-duration"]) * 10) / 10} s</div>
                             </div>
                         </div>
                         {/* <div className="ribbon-box">
diff --git a/src/client/views/presentationview/PresElementBox.tsx b/src/client/views/presentationview/PresElementBox.tsx
index 9ec39b792..23f0dbdee 100644
--- a/src/client/views/presentationview/PresElementBox.tsx
+++ b/src/client/views/presentationview/PresElementBox.tsx
@@ -117,7 +117,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDoc
 
     @computed get duration() {
         let durationInS: number;
-        if (this.rootDoc.type === DocumentType.AUDIO) { durationInS = NumCast(this.rootDoc.presEndTime) - NumCast(this.rootDoc.presStartTime); durationInS = Math.round(durationInS * 10) / 10; }
+        if (this.rootDoc.type === DocumentType.AUDIO || this.rootDoc.type === DocumentType.VID) { durationInS = NumCast(this.rootDoc.presEndTime) - NumCast(this.rootDoc.presStartTime); durationInS = Math.round(durationInS * 10) / 10; }
         else if (this.rootDoc.presDuration) durationInS = NumCast(this.rootDoc.presDuration) / 1000;
         else durationInS = 2;
         return "D: " + durationInS + "s";
-- 
cgit v1.2.3-70-g09d2


From 69f247903d289aeac6383ba3a6912504a6172873 Mon Sep 17 00:00:00 2001
From: geireann <60007097+geireann@users.noreply.github.com>
Date: Wed, 2 Dec 2020 18:34:23 +0800
Subject: loader progress bar (superficial)

- temp media changes
---
 deploy/index.html                   |  83 +++++++++---
 deploy/loader.css                   | 141 ---------------------
 src/client/views/MainView.tsx       |  12 +-
 src/client/views/PropertiesView.tsx |   4 +-
 src/client/views/nodes/PresBox.scss |  18 ++-
 src/client/views/nodes/PresBox.tsx  | 245 +++++++++++++++++++-----------------
 6 files changed, 226 insertions(+), 277 deletions(-)
 delete mode 100644 deploy/loader.css

(limited to 'src/client/views/MainView.tsx')

diff --git a/deploy/index.html b/deploy/index.html
index beb7dd205..4e0c2dfa4 100644
--- a/deploy/index.html
+++ b/deploy/index.html
@@ -13,20 +13,51 @@
             align-content: center;
             justify-content: center;
             background-color: #AEDDF8;
+            transition: 3s;
             z-index: 10;
             width: 100vw;
             height: 100vh;
         }
 
         .dash-loader-container {
-            width: 20vw;
-            height: 20vw;
+            display: grid;
+            grid-auto-rows: auto 30px auto;
+        }
+
+        .dash-progress-bar {
+            width: 200px;
+            height: 5px;
+            align-self: center;
+            margin-top: 20px;
+            background-color: #ececec;
+            border-radius: 5px;
+            overflow: hidden;
+        }
+
+        .dash-progress {
+            width: 0%;
+            height: 20px;
+            background-color: #5b9fdd;
+            transition: 0.1s;
+        }
+
+        .dash-animation-container {
+            width: 10vw;
+            height: 10vw;
             display: flex;
             align-items: center;
             justify-content: center;
             border-radius: 100%;
             background-color: #5B9FDD;
-            align-self: center;
+            justify-self: center;
+            align-self: flex-end;
+        }
+
+        .dash-loader-text {
+            font-size: 15px;
+            font-family: "Roboto";
+            text-align: center;
+            color: #5B9FDD;
         }
 
         .dash-d-path {
@@ -38,41 +69,63 @@
         @keyframes dash-d-path {
             0% {
                 stroke-dashoffset: 1000;
-                /* stroke-width: 0px; */
             }
 
             20% {
                 stroke-dashoffset: 0;
-                /* stroke-width: 20px; */
             }
 
             70% {
                 stroke-dashoffset: 0;
-                /* stroke-width: 20px; */
             }
 
             90% {
                 stroke-dashoffset: 1000;
-                /* stroke-width: 0px; */
             }
 
             100% {
                 stroke-dashoffset: 1000;
-                /* stroke-width: 0px; */
             }
         }
     </style>
 </head>
 
 <body style="display:flex" id="dash-body">
-    <div class="dash-loader" id="loader" style="z-index:10; width:100%; height:100%">
+    <div class="dash-loader" id="loader" style="z-index:10; width:100%; height:100%;">
         <div class="dash-loader-container">
-            <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200px"
-                height="200px" viewBox="0 0 250 350">
-                <path class="dash-d-path" fill-rule="evenodd" stroke="#ececec" stroke-width="20px" stroke-linecap="butt"
-                    stroke-linejoin="miter" fill="none"
-                    d="M196.500,18.500 C195.888,79.462 194.655,160.273 197.500,195.500 C198.117,203.144 199.664,225.773 189.500,246.500 C183.949,257.819 175.192,268.535 163.500,277.500 C147.404,289.842 133.006,294.212 121.500,295.500 C106.618,297.166 92.057,294.673 79.500,288.500 C68.970,283.324 58.384,274.780 49.500,261.500 C39.958,247.237 35.188,230.375 35.500,213.500 C35.760,199.463 39.572,185.692 46.500,173.500 C55.433,157.780 65.945,148.829 75.500,143.500 C85.352,138.005 98.187,134.141 114.500,134.500 C128.982,134.819 143.177,139.076 155.500,146.500 C186.160,164.973 196.208,196.242 197.500,216.500 C197.663,219.061 197.578,222.985 197.500,226.500 C197.092,244.967 195.719,262.030 195.500,280.500 C195.460,283.898 195.500,293.783 195.500,300.500 C195.500,304.834 195.500,309.189 195.500,313.500 " />
-            </svg>
+            <div class="dash-animation-container">
+                <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100px"
+                    height="100px" viewBox="0 0 250 350">
+                    <path class="dash-d-path" fill-rule="evenodd" stroke="#ececec" stroke-width="30px"
+                        stroke-linecap="butt" stroke-linejoin="miter" fill="none"
+                        d="M196.500,18.500 C195.888,79.462 194.655,160.273 197.500,195.500 C198.117,203.144 199.664,225.773 189.500,246.500 C183.949,257.819 175.192,268.535 163.500,277.500 C147.404,289.842 133.006,294.212 121.500,295.500 C106.618,297.166 92.057,294.673 79.500,288.500 C68.970,283.324 58.384,274.780 49.500,261.500 C39.958,247.237 35.188,230.375 35.500,213.500 C35.760,199.463 39.572,185.692 46.500,173.500 C55.433,157.780 65.945,148.829 75.500,143.500 C85.352,138.005 98.187,134.141 114.500,134.500 C128.982,134.819 143.177,139.076 155.500,146.500 C186.160,164.973 196.208,196.242 197.500,216.500 C197.663,219.061 197.578,222.985 197.500,226.500 C197.092,244.967 195.719,262.030 195.500,280.500 C195.460,283.898 195.500,293.783 195.500,300.500 C195.500,304.834 195.500,309.189 195.500,313.500 " />
+                </svg>
+            </div>
+            <div class="dash-progress-bar">
+                <div id="dash-progress" class="dash-progress">
+                </div>
+                <script>
+                    setTimeout(() => {
+                        document.getElementById("dash-progress").style.width = "10%"
+                        document.getElementById("dash-loader-text").innerHTML = "Loading Dash..."
+                    }, 500);
+                    setTimeout(() => {
+                        document.getElementById("dash-progress").style.width = "30%"
+                        document.getElementById("dash-loader-text").innerHTML = "Preparing dashboards..."
+                    }, 1000);
+                    setTimeout(() => {
+                        document.getElementById("dash-progress").style.width = "50%"
+                        document.getElementById("dash-loader-text").innerHTML = "Fetching documents..."
+                    }, 1500);
+                    setTimeout(() => {
+                        document.getElementById("dash-progress").style.width = "70%"
+                        document.getElementById("dash-loader-text").innerHTML = "Finalising setup..."
+                    }, 3000);
+                </script>
+            </div>
+            <div id="dash-loader-text" class="dash-loader-text">
+                Loading Dash...
+            </div>
         </div>
     </div>
     <!-- <script src="https://hypothes.is/embed.js" async></script> -->
diff --git a/deploy/loader.css b/deploy/loader.css
deleted file mode 100644
index 065862013..000000000
--- a/deploy/loader.css
+++ /dev/null
@@ -1,141 +0,0 @@
-.dash-loader {
-    display: flex;
-    align-content: center;
-    justify-content: center;
-    background-color: lightcyan;
-    z-index: 10;
-    width: 100%;
-    height: 100%;
-}
-
-.dash-loader-container {
-    width: 100;
-    align-self: center;
-}
-
-.dash-d-path {
-    stroke-dasharray: 1000;
-    stroke-dashoffset: 1000;
-    animation: dash-d-path 10s linear infinite;
-}
-
-@keyframes dash-d-path {
-    0% {
-        stroke-dashoffset: 1000;
-        /* stroke-width: 0px; */
-    }
-
-    10% {
-        stroke-dashoffset: 0;
-        /* stroke-width: 20px; */
-    }
-
-    90% {
-        stroke-dashoffset: 0;
-        /* stroke-width: 20px; */
-    }
-
-    100% {
-        stroke-dashoffset: 1000;
-        /* stroke-width: 0px; */
-    }
-}
-
-.dash-a-path {
-    stroke-dasharray: 1000;
-    stroke-dashoffset: 1000;
-    animation: dash-a-path 10s linear infinite;
-}
-
-@keyframes dash-a-path {
-    0% {
-        stroke-dashoffset: 1000;
-        /* stroke-width: 0px; */
-    }
-
-    7% {
-        stroke-dashoffset: 1000;
-        /* stroke-width: 0px; */
-    }
-
-    17% {
-        stroke-dashoffset: 0;
-        /* stroke-width: 20px; */
-    }
-
-    90% {
-        stroke-dashoffset: 0;
-        /* stroke-width: 20px; */
-    }
-
-    100% {
-        stroke-dashoffset: 1000;
-        /* stroke-width: 0px; */
-    }
-}
-
-.dash-s-path {
-    stroke-dasharray: 1000;
-    stroke-dashoffset: 1000;
-    animation: dash-s-path 10s linear infinite;
-}
-
-@keyframes dash-s-path {
-    0% {
-        stroke-dashoffset: 1000;
-        /* stroke-width: 0px; */
-    }
-
-    14% {
-        stroke-dashoffset: 1000;
-        /* stroke-width: 0px; */
-    }
-
-    20% {
-        stroke-dashoffset: 0;
-        /* stroke-width: 20px; */
-    }
-
-    90% {
-        stroke-dashoffset: 0;
-        /* stroke-width: 20px; */
-    }
-
-    100% {
-        stroke-dashoffset: 1000;
-        /* stroke-width: 0px; */
-    }
-}
-
-.dash-h-path {
-    stroke-dasharray: 1000;
-    stroke-dashoffset: 1000;
-    animation: dash-h-path 10s linear infinite;
-}
-
-@keyframes dash-h-path {
-    0% {
-        stroke-dashoffset: 1000;
-        /* stroke-width: 0px; */
-    }
-
-    18% {
-        stroke-dashoffset: 1000;
-        /* stroke-width: 0px; */
-    }
-
-    28% {
-        stroke-dashoffset: 0;
-        /* stroke-width: 20px; */
-    }
-
-    90% {
-        stroke-dashoffset: 0;
-        /* stroke-width: 20px; */
-    }
-
-    100% {
-        stroke-dashoffset: 1000;
-        /* stroke-width: 0px; */
-    }
-}
\ No newline at end of file
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 12e361dc1..747bde64d 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -87,11 +87,15 @@ export class MainView extends React.Component {
     componentDidMount() {
         document.getElementById("root")?.addEventListener("scroll", e => ((ele) => ele.scrollLeft = ele.scrollTop = 0)(document.getElementById("root")!));
         const ele = document.getElementById("loader");
-
-        if (ele) {
+        const prog = document.getElementById("dash-progress");
+        if (ele && prog) {
             // remove from DOM
-            setTimeout(() => { ele.style.opacity = "0"; }, 0);
-            setTimeout(() => ele.outerHTML = '', 10000);
+            setTimeout(() => {
+                clearTimeout();
+                prog.style.transition = "1s";
+                prog.style.width = "100%";
+            }, 0);
+            setTimeout(() => ele.outerHTML = '', 1000);
         }
         new InkStrokeProperties();
         this._sidebarContent.proto = undefined;
diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx
index a9076fea7..3c77bc309 100644
--- a/src/client/views/PropertiesView.tsx
+++ b/src/client/views/PropertiesView.tsx
@@ -1016,7 +1016,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                             {PresBox.Instance.transitionDropdown}
                         </div> : null}
                     </div>}
-                    {!selectedItem || type === DocumentType.VID || type === DocumentType.AUDIO ? (null) : <div className="propertiesView-presTrails">
+                    {/* {!selectedItem || type === DocumentType.VID || type === DocumentType.AUDIO ? (null) : <div className="propertiesView-presTrails">
                         <div className="propertiesView-presTrails-title"
                             onPointerDown={action(() => this.openPresProgressivize = !this.openPresProgressivize)}
                             style={{ backgroundColor: this.openPresProgressivize ? "black" : "" }}>
@@ -1028,7 +1028,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                         {this.openPresProgressivize ? <div className="propertiesView-presTrails-content">
                             {PresBox.Instance.progressivizeDropdown}
                         </div> : null}
-                    </div>}
+                    </div>} */}
                     {!selectedItem || (type !== DocumentType.VID && type !== DocumentType.AUDIO) ? (null) : <div className="propertiesView-presTrails">
                         <div className="propertiesView-presTrails-title"
                             onPointerDown={action(() => { this.openSlideOptions = !this.openSlideOptions; })}
diff --git a/src/client/views/nodes/PresBox.scss b/src/client/views/nodes/PresBox.scss
index ba21cef42..1ba86232b 100644
--- a/src/client/views/nodes/PresBox.scss
+++ b/src/client/views/nodes/PresBox.scss
@@ -129,7 +129,9 @@ $dark-grey: #656565;
 }
 
 .presBox-radioButtons {
-    background-color: rgba(0, 0, 0, 0.1);
+    font-size: 10px;
+    font-weight: 200;
+    // background-color: rgba(0, 0, 0, 0.1);
 
     .checkbox-container {
         margin-left: 10px;
@@ -345,6 +347,20 @@ $dark-grey: #656565;
         font-weight: 100;
         margin-top: 3px;
         font-size: 10px;
+
+        .slider-block {
+            width: 63px;
+            border-radius: 5px;
+            text-align: center;
+            margin-bottom: 8px;
+            margin-top: 8px;
+        }
+
+        .slider-number {
+            border-radius: 3px;
+            width: 30px;
+            margin: auto;
+        }
     }
 
     .slider-value {
diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx
index d21e1603d..a4f79571e 100644
--- a/src/client/views/nodes/PresBox.tsx
+++ b/src/client/views/nodes/PresBox.tsx
@@ -640,10 +640,14 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
         if (this.childDocs[stopDocIndex - 1].mediaStopTriggerList) {
             const list = DocListCast(this.childDocs[stopDocIndex - 1].mediaStopTriggerList);
             list.push(activeItem);
+            // this.childDocs[stopDocIndex - 1].mediaStopTriggerList = list;
+            console.log(list);
         } else {
             this.childDocs[stopDocIndex - 1].mediaStopTriggerList = new List<Doc>();
             const list = DocListCast(this.childDocs[stopDocIndex - 1].mediaStopTriggerList);
             list.push(activeItem);
+            // this.childDocs[stopDocIndex - 1].mediaStopTriggerList = list;
+            console.log(list);
         }
     });
 
@@ -1424,102 +1428,138 @@ 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>
-                            <div className="presBox-subheading">Range:</div>
-                            <div className={"slider-headers"}>
-                                <div className="slider-text">
-                                    Start time:
-                                </div>
-                                <div className="slider-text">
-                                    Duration:
-                                </div>
-                                <div className="slider-text">
-                                    End time:
-                                </div>
-                            </div>
-                            <div className={"slider-headers"} style={{ marginTop: 0 }}>
-                                <div className="slider-text">
-                                    <input className="presBox-input"
-                                        style={{ textAlign: 'left', width: 30, height: 15, fontSize: 10 }}
-                                        type="number" value={NumCast(activeItem.presStartTime)}
-                                        onChange={action((e: React.ChangeEvent<HTMLInputElement>) => { activeItem.presStartTime = Number(e.target.value); })}
-                                    /> s
+                            <div className="ribbon-box">
+                                Start {"&"} End Time
+                                <div className={"slider-headers"}>
+                                    <div className="slider-block" >
+                                        <div className="slider-text" style={{ fontWeight: 500 }}>
+                                            Start time (s)
+                                        </div>
+                                        <div id={"startTime"} className="slider-number" style={{ backgroundColor: PresColor.LightBackground }}>
+                                            <input className="presBox-input"
+                                                style={{ textAlign: 'center', width: 30, height: 15, fontSize: 10 }}
+                                                type="number" value={NumCast(activeItem.presStartTime)}
+                                                onChange={action((e: React.ChangeEvent<HTMLInputElement>) => { activeItem.presStartTime = Number(e.target.value); })}
+                                            />
+                                        </div>
+                                    </div>
+                                    <div className="slider-block">
+                                        <div className="slider-text" style={{ fontWeight: 500 }}>
+                                            Duration (s)
+                                        </div>
+                                        <div className="slider-number" style={{ backgroundColor: PresColor.LightBlue }}>
+                                            {Math.round((NumCast(activeItem.presEndTime) - NumCast(activeItem.presStartTime)) * 10) / 10}
+                                        </div>
+                                    </div>
+                                    <div className="slider-block">
+                                        <div className="slider-text" style={{ fontWeight: 500 }}>
+                                            End time (s)
+                                        </div>
+                                        <div id={"endTime"} className="slider-number" style={{ backgroundColor: PresColor.LightBackground }}>
+                                            <input className="presBox-input"
+                                                style={{ textAlign: 'center', width: 30, height: 15, fontSize: 10 }}
+                                                type="number" value={NumCast(activeItem.presEndTime)}
+                                                onChange={action((e: React.ChangeEvent<HTMLInputElement>) => { activeItem.presEndTime = Number(e.target.value); })}
+                                            />
+                                        </div>
                                     </div>
-                                <div className="slider-text">
-                                    {Math.round((NumCast(activeItem.presEndTime) - NumCast(activeItem.presStartTime)) * 10) / 10} s
                                 </div>
-                                <div className="slider-text">
-                                    <input className="presBox-input"
-                                        style={{ textAlign: 'right', width: 30, height: 15, fontSize: 10 }}
-                                        type="number" value={NumCast(activeItem.presEndTime)}
-                                        onChange={action((e: React.ChangeEvent<HTMLInputElement>) => { activeItem.presEndTime = Number(e.target.value); })}
-                                    /> s
+                                <div className="multiThumb-slider">
+                                    <input type="range" step="0.1" min="0" max={activeItem.type === DocumentType.AUDIO ? Math.round(NumCast(activeItem.duration) * 10) / 10 : Math.round(NumCast(activeItem["data-duration"]) * 10) / 10} value={NumCast(activeItem.presEndTime)}
+                                        style={{ gridColumn: 1, gridRow: 1 }}
+                                        className={`toolbar-slider ${"end"}`}
+                                        id="toolbar-slider"
+                                        onPointerDown={() => {
+                                            this._batch = UndoManager.StartBatch("presEndTime");
+                                            const endBlock = document.getElementById("endTime");
+                                            if (endBlock) {
+                                                endBlock.style.color = PresColor.LightBackground;
+                                                endBlock.style.backgroundColor = PresColor.DarkBlue;
+                                            }
+                                        }}
+                                        onPointerUp={() => {
+                                            this._batch?.end();
+                                            const endBlock = document.getElementById("endTime");
+                                            if (endBlock) {
+                                                endBlock.style.color = "black";
+                                                endBlock.style.backgroundColor = PresColor.LightBackground;
+                                            }
+                                        }}
+                                        onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
+                                            e.stopPropagation();
+                                            activeItem.presEndTime = Number(e.target.value);
+                                        }} />
+                                    <input type="range" step="0.1" min="0" max={activeItem.type === DocumentType.AUDIO ? Math.round(NumCast(activeItem.duration) * 10) / 10 : Math.round(NumCast(activeItem["data-duration"]) * 10) / 10} value={NumCast(activeItem.presStartTime)}
+                                        style={{ gridColumn: 1, gridRow: 1 }}
+                                        className={`toolbar-slider ${"start"}`}
+                                        id="toolbar-slider"
+                                        onPointerDown={() => {
+                                            this._batch = UndoManager.StartBatch("presStartTime");
+                                            const startBlock = document.getElementById("startTime");
+                                            if (startBlock) {
+                                                startBlock.style.color = PresColor.LightBackground;
+                                                startBlock.style.backgroundColor = PresColor.DarkBlue;
+                                            }
+                                        }}
+                                        onPointerUp={() => {
+                                            this._batch?.end();
+                                            const startBlock = document.getElementById("startTime");
+                                            if (startBlock) {
+                                                startBlock.style.color = "black";
+                                                startBlock.style.backgroundColor = PresColor.LightBackground;
+                                            }
+                                        }}
+                                        onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
+                                            e.stopPropagation();
+                                            activeItem.presStartTime = Number(e.target.value);
+                                        }} />
                                 </div>
-                            </div>
-                            <div className="multiThumb-slider">
-                                <input type="range" step="0.1" min="0" max={activeItem.type === DocumentType.AUDIO ? Math.round(NumCast(activeItem.duration) * 10) / 10 : Math.round(NumCast(activeItem["data-duration"]) * 10) / 10} value={NumCast(activeItem.presEndTime)}
-                                    style={{ gridColumn: 1, gridRow: 1 }}
-                                    className={`toolbar-slider ${"end"}`}
-                                    id="toolbar-slider"
-                                    onPointerDown={() => this._batch = UndoManager.StartBatch("presEndTime")}
-                                    onPointerUp={() => this._batch?.end()}
-                                    onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
-                                        e.stopPropagation();
-                                        activeItem.presEndTime = Number(e.target.value);
-                                    }} />
-                                <input type="range" step="0.1" min="0" max={activeItem.type === DocumentType.AUDIO ? Math.round(NumCast(activeItem.duration) * 10) / 10 : Math.round(NumCast(activeItem["data-duration"]) * 10) / 10} value={NumCast(activeItem.presStartTime)}
-                                    style={{ gridColumn: 1, gridRow: 1 }}
-                                    className={`toolbar-slider ${"start"}`}
-                                    id="toolbar-slider"
-                                    onPointerDown={() => this._batch = UndoManager.StartBatch("presEndTime")}
-                                    onPointerUp={() => this._batch?.end()}
-                                    onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
-                                        e.stopPropagation();
-                                        activeItem.presStartTime = Number(e.target.value);
-                                    }} />
-                            </div>
-                            <div className={`slider-headers ${activeItem.presMovement === PresMovement.Pan || activeItem.presMovement === PresMovement.Zoom ? "" : "none"}`}>
-                                <div className="slider-text">0 s</div>
-                                <div className="slider-text"></div>
-                                <div className="slider-text">{activeItem.type === DocumentType.AUDIO ? Math.round(NumCast(activeItem.duration) * 10) / 10 : Math.round(NumCast(activeItem["data-duration"]) * 10) / 10} s</div>
-                            </div>
-                            <div className="presBox-subheading">Start playing:</div>
-                            <div className="presBox-radioButtons">
-                                <div className="checkbox-container">
-                                    <input className="presBox-checkbox"
-                                        type="checkbox"
-                                        onChange={() => activeItem.mediaStart = "manual"}
-                                        checked={activeItem.mediaStart === "manual"}
-                                    />
-                                    <div>On click</div>
-                                </div>
-                                <div className="checkbox-container">
-                                    <input className="presBox-checkbox"
-                                        type="checkbox"
-                                        onChange={() => activeItem.mediaStart = "auto"}
-                                        checked={activeItem.mediaStart === "auto"}
-                                    />
-                                    <div>Automatically</div>
+                                <div className={`slider-headers ${activeItem.presMovement === PresMovement.Pan || activeItem.presMovement === PresMovement.Zoom ? "" : "none"}`}>
+                                    <div className="slider-text">0 s</div>
+                                    <div className="slider-text"></div>
+                                    <div className="slider-text">{activeItem.type === DocumentType.AUDIO ? Math.round(NumCast(activeItem.duration) * 10) / 10 : Math.round(NumCast(activeItem["data-duration"]) * 10) / 10} s</div>
                                 </div>
                             </div>
-                            <div className="presBox-subheading">Stop playing:</div>
-                            <div className="presBox-radioButtons">
-                                <div className="checkbox-container">
-                                    <input className="presBox-checkbox"
-                                        type="checkbox"
-                                        onChange={() => activeItem.mediaStop = "manual"}
-                                        checked={activeItem.mediaStop === "manual"}
-                                    />
-                                    <div>At audio end time</div>
-                                </div>
-                                <div className="checkbox-container">
-                                    <input className="presBox-checkbox"
-                                        type="checkbox"
-                                        onChange={() => activeItem.mediaStop = "auto"}
-                                        checked={activeItem.mediaStop === "auto"}
-                                    />
-                                    <div>On slide change</div>
+                            <div className="ribbon-final-box">
+                                Playback
+                                <div className="presBox-subheading">Start playing:</div>
+                                <div className="presBox-radioButtons">
+                                    <div className="checkbox-container">
+                                        <input className="presBox-checkbox"
+                                            type="checkbox"
+                                            onChange={() => activeItem.mediaStart = "manual"}
+                                            checked={activeItem.mediaStart === "manual"}
+                                        />
+                                        <div>On click</div>
+                                    </div>
+                                    <div className="checkbox-container">
+                                        <input className="presBox-checkbox"
+                                            type="checkbox"
+                                            onChange={() => activeItem.mediaStart = "auto"}
+                                            checked={activeItem.mediaStart === "auto"}
+                                        />
+                                        <div>Automatically</div>
+                                    </div>
                                 </div>
-                                <div className="checkbox-container">
+                                <div className="presBox-subheading">Stop playing:</div>
+                                <div className="presBox-radioButtons">
+                                    <div className="checkbox-container">
+                                        <input className="presBox-checkbox"
+                                            type="checkbox"
+                                            onChange={() => activeItem.mediaStop = "manual"}
+                                            checked={activeItem.mediaStop === "manual"}
+                                        />
+                                        <div>At audio end time</div>
+                                    </div>
+                                    <div className="checkbox-container">
+                                        <input className="presBox-checkbox"
+                                            type="checkbox"
+                                            onChange={() => activeItem.mediaStop = "auto"}
+                                            checked={activeItem.mediaStop === "auto"}
+                                        />
+                                        <div>On slide change</div>
+                                    </div>
+                                    {/* <div className="checkbox-container">
                                     <input className="presBox-checkbox"
                                         type="checkbox"
                                         onChange={() => activeItem.mediaStop = "afterSlide"}
@@ -1535,33 +1575,10 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
                                             {this.mediaStopSlides}
                                         </select>
                                     </div>
+                                </div> */}
                                 </div>
                             </div>
                         </div>
-                        {/* <div className="ribbon-box">
-                            <div className="ribbon-doubleButton" style={{ display: targetDoc.type === DocumentType.AUDIO ? "inline-flex" : "none" }}>
-                                <div className="ribbon-toggle" style={{ backgroundColor: activeItem.playAuto ? PresColor.LightBlue : "" }} onClick={() => activeItem.playAuto = !activeItem.playAuto}>Play automatically</div>
-                                <div className="ribbon-toggle" style={{ display: "flex", backgroundColor: activeItem.playAuto ? "" : PresColor.LightBlue }} onClick={() => activeItem.playAuto = !activeItem.playAuto}>Play on next</div>
-                            </div>
-                            {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"
-                                        style={{ textAlign: 'left', width: 50 }}
-                                        type="number" value={NumCast(activeItem.presStartTime)}
-                                        onChange={action((e: React.ChangeEvent<HTMLInputElement>) => { activeItem.presStartTime = Number(e.target.value); })} />
-                                </div>
-                            </div> : (null)}
-                            {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"
-                                        style={{ textAlign: 'left', width: 50 }}
-                                        type="number" value={NumCast(activeItem.presEndTime)}
-                                        onChange={action((e: React.ChangeEvent<HTMLInputElement>) => { const val = e.target.value; activeItem.presEndTime = Number(val); })} />
-                                </div>
-                            </div> : (null)}
-                        </div> */}
                     </div>
                 </div >
             );
-- 
cgit v1.2.3-70-g09d2

