From 31faf2b0683fc15c040d47425f931531c0d8a0f8 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Wed, 27 Jan 2021 12:13:21 -0500
Subject: fixed size of timeline toggle on videoBox and some other tweaks to
 hide documentdeocrations on timeline items.

---
 src/client/views/DocumentDecorations.tsx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

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

diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index fb85684fb..250b93188 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -613,7 +613,7 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b
                 }}>
                     {closeIcon}
                     {bounds.r - bounds.x < 100 ? null : titleArea}
-                    {seldoc.rootDoc.anchorStartTime !== undefined ? (null) :
+                    {seldoc.props.hideDecorations ? (null) :
                         <>
                             {SelectionManager.Views().length !== 1 || seldoc.Document.type === DocumentType.INK ? (null) :
                                 <Tooltip key="i" title={<div className="dash-tooltip">{`${seldoc.finalLayoutKey.includes("icon") ? "De" : ""}Iconify Document`}</div>} placement="top">
-- 
cgit v1.2.3-70-g09d2


From f43f47662293ddb2cd4d2eb217bc4f01b6d22826 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Wed, 27 Jan 2021 13:22:01 -0500
Subject: animated expansion of video box timeline.

---
 src/client/views/DocumentDecorations.tsx           |  2 +-
 .../collections/CollectionStackedTimeline.tsx      |  2 +-
 src/client/views/nodes/VideoBox.tsx                | 32 +++++++++++++++++-----
 3 files changed, 27 insertions(+), 9 deletions(-)

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

diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 250b93188..54e0a7ac7 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -613,7 +613,7 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b
                 }}>
                     {closeIcon}
                     {bounds.r - bounds.x < 100 ? null : titleArea}
-                    {seldoc.props.hideDecorations ? (null) :
+                    {seldoc.props.hideResizeHandles ? (null) :
                         <>
                             {SelectionManager.Views().length !== 1 || seldoc.Document.type === DocumentType.INK ? (null) :
                                 <Tooltip key="i" title={<div className="dash-tooltip">{`${seldoc.finalLayoutKey.includes("icon") ? "De" : ""}Iconify Document`}</div>} placement="top">
diff --git a/src/client/views/collections/CollectionStackedTimeline.tsx b/src/client/views/collections/CollectionStackedTimeline.tsx
index 54cc86523..4b14c3508 100644
--- a/src/client/views/collections/CollectionStackedTimeline.tsx
+++ b/src/client/views/collections/CollectionStackedTimeline.tsx
@@ -292,7 +292,7 @@ export class CollectionStackedTimeline extends CollectionSubView<PanZoomDocument
                 onClick={script}
                 onDoubleClick={this.props.Document.autoPlay ? undefined : doublescript}
                 ignoreAutoHeight={false}
-                hideDecorations={true}
+                hideResizeHandles={true}
                 bringToFront={emptyFunction}
                 scriptContext={this} />
         };
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index 6286b5e26..506ba8c49 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -55,16 +55,17 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps, VideoD
     @observable _marqueeing: number[] | undefined;
     @observable _savedAnnotations: Dictionary<number, HTMLDivElement[]> = new Dictionary<number, HTMLDivElement[]>();
     @observable _screenCapture = false;
-    @observable _visible: boolean = false;
+    @observable _clicking = false;
     @observable _forceCreateYouTubeIFrame = false;
     @observable _playTimer?: NodeJS.Timeout = undefined;
     @observable _fullScreen = false;
     @observable _playing = false;
     @computed get links() { return DocListCast(this.dataDoc.links); }
-    @computed get heightPercent() { return this.layoutDoc._timelineShow ? NumCast(this.layoutDoc._videoTimelineHeightPercent, VideoBox.heightPercent) : 100; }
+    @computed get heightPercent() { return NumCast(this.layoutDoc._timelineHeightPercent, 100); }
     @computed get duration() { return NumCast(this.dataDoc[this.fieldKey + "-duration"]); }
     @computed get anchorDocs() { return DocListCast(this.dataDoc[this.annotationKey + "-timeline"]).concat(DocListCast(this.dataDoc[this.annotationKey])); }
 
+    private get transition() { return this._clicking ? "left 0.5s, width 0.5s, height 0.5s" : ""; }
     public get player(): HTMLVideoElement | null { return this._videoRef; }
 
     constructor(props: Readonly<FieldViewProps>) {
@@ -383,8 +384,8 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps, VideoD
         <div className="videoBox-snapshot" key="snap" onClick={this.onSnapshot} >
             <FontAwesomeIcon icon="camera" size="lg" />
         </div>,
-        <div className="videoBox-timelineButton" key="timeline" onClick={action(e => this.layoutDoc._timelineShow = !this.layoutDoc._timelineShow)}>
-            <FontAwesomeIcon icon={this.layoutDoc._timelineShow ? "eye-slash" : "eye"} size="lg" />
+        <div className="videoBox-timelineButton" key="timeline" onPointerDown={this.onTimelineHdlDown} style={{ bottom: `${100 - this.heightPercent}%` }}>
+            <FontAwesomeIcon icon={"eye"} size="lg" />
         </div>,
         VideoBox._showControls ? (null) : [
             // <div className="control-background">
@@ -412,6 +413,23 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps, VideoD
         e.preventDefault();
     }
 
+    onTimelineHdlDown = action((e: React.PointerEvent) => {
+        this._clicking = true;
+        setupMoveUpEvents(this, e,
+            action((e: PointerEvent) => {
+                this._clicking = false;
+                if (this.active()) {
+                    const local = this.props.ScreenToLocalTransform().transformPoint(e.clientX, e.clientY);
+                    this.layoutDoc._timelineHeightPercent = Math.max(0, Math.min(100, local[1] / this.props.PanelHeight() * 100));
+                }
+                return false;
+            }), emptyFunction,
+            () => {
+                this.layoutDoc._timelineHeightPercent = this.heightPercent !== 100 ? 100 : VideoBox.heightPercent;
+                setTimeout(action(() => this._clicking = false), 500);
+            }, this.active(), this.active());
+    });
+
     onResetDown = (e: React.PointerEvent) => {
         setupMoveUpEvents(this, e, (e: PointerEvent) => {
             this.Seek(Math.max(0, (this.layoutDoc._currentTimecode || 0) + Math.sign(e.movementX) * 0.0333));
@@ -478,7 +496,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps, VideoD
 
     // returns the timeline
     @computed get renderTimeline() {
-        return <div style={{ width: "100%", height: `${100 - this.heightPercent}%`, position: "absolute" }}>
+        return <div style={{ width: "100%", transition: this.transition, height: `${100 - this.heightPercent}%`, position: "absolute" }}>
             <CollectionStackedTimeline ref={this._stackedTimeline}
                 Document={this.props.Document}
                 fieldKey={this.annotationKey}
@@ -519,7 +537,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps, VideoD
     contentFunc = () => [this.youtubeVideoId ? this.youtubeContent : this.content];
 
     @computed get annotationLayer() {
-        return <div className="imageBox-annotationLayer" style={{ height: `${this.heightPercent}%` }} ref={this._annotationLayer} />;
+        return <div className="imageBox-annotationLayer" style={{ transition: this.transition, height: `${this.heightPercent}%` }} ref={this._annotationLayer} />;
     }
 
     marqueeDown = action((e: React.PointerEvent) => {
@@ -548,7 +566,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps, VideoD
                 borderRadius
             }} >
             <div className="videoBox-viewer" onPointerDown={this.marqueeDown} >
-                <div style={{ position: "absolute", width: this.panelWidth(), height: this.panelHeight(), top: 0, left: `${(100 - this.heightPercent) / 2}%` }}>
+                <div style={{ position: "absolute", transition: this.transition, width: this.panelWidth(), height: this.panelHeight(), top: 0, left: `${(100 - this.heightPercent) / 2}%` }}>
                     <CollectionFreeFormView {...OmitKeys(this.props, ["NativeWidth", "NativeHeight", "setContentView"]).omit}
                         fieldKey={this.annotationKey}
                         isAnnotationOverlay={true}
-- 
cgit v1.2.3-70-g09d2


From bc8504151c8b6cb8c427f1f3c97c7f44eebc9426 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Wed, 27 Jan 2021 16:33:45 -0500
Subject: updated documentdecorations title display to be more visible on
 complex backgrounds.  fixed link following behavior (espicall from
 presentations) to timeline annotations.

---
 src/client/views/DocComponent.tsx                  |  5 ++-
 src/client/views/DocumentDecorations.scss          | 38 ++++++++++++----------
 src/client/views/DocumentDecorations.tsx           |  6 ++--
 src/client/views/MainView.scss                     |  2 +-
 .../collectionFreeForm/CollectionFreeFormView.tsx  | 10 +++---
 src/client/views/nodes/PresBox.tsx                 |  7 ++--
 6 files changed, 39 insertions(+), 29 deletions(-)

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

diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx
index 8d545c61b..99f13295d 100644
--- a/src/client/views/DocComponent.tsx
+++ b/src/client/views/DocComponent.tsx
@@ -131,7 +131,10 @@ export function ViewBoxAnnotatableComponent<P extends ViewBoxAnnotatableProps, T
             const docs = indocs.filter(doc => effectiveAcl === AclEdit || effectiveAcl === AclAdmin || GetEffectiveAcl(doc) === AclAdmin);
             if (docs.length) {
                 const docs = doc instanceof Doc ? [doc] : doc;
-                docs.map(doc => doc.isPushpin = doc.annotationOn = undefined);
+                docs.map(doc => {
+                    Doc.SetInPlace(doc, "isPushpin", undefined, true);
+                    Doc.SetInPlace(doc, "annotationOn", undefined, true);
+                });
                 const targetDataDoc = this.dataDoc;
                 const value = DocListCast(targetDataDoc[annotationKey ?? this.annotationKey]);
                 const toRemove = value.filter(v => docs.includes(v));
diff --git a/src/client/views/DocumentDecorations.scss b/src/client/views/DocumentDecorations.scss
index f9b8c1940..22e120167 100644
--- a/src/client/views/DocumentDecorations.scss
+++ b/src/client/views/DocumentDecorations.scss
@@ -79,7 +79,7 @@ $linkGap : 3px;
         grid-column: 5;
         grid-row: 4;
         border-radius: 100%;
-        background: dimgray;
+        background: black;
         height: 8;
         right: -12;
         top: 12;
@@ -145,7 +145,7 @@ $linkGap : 3px;
     .documentDecorations-topRightResizer:hover,
     .documentDecorations-bottomLeftResizer:hover {
         cursor: nesw-resize;
-        background: dimGray;
+        background: black;
         opacity: 1;
     }
 
@@ -169,6 +169,14 @@ $linkGap : 3px;
         cursor: pointer;
     }
 
+    .documentDecorations-titleBackground {
+        background: #ffffffcf;
+        border-radius: 8px;
+        width: 100%;
+        height: 100%;
+        position: absolute;
+    }
+
     .documentDecorations-title {
         opacity: 1;
         grid-column-start: 2;
@@ -177,26 +185,22 @@ $linkGap : 3px;
         overflow: hidden;
         text-align: center;
         display: flex;
-        border-bottom: solid 1px;
-        margin-left: 10px;
-        width: calc(100% - 10px);
+        margin-left: 5px;
+        height: 22px;
+        position: absolute;
+        .documentDecorations-titleSpan {
+            width: 100%;
+            border-radius: 8px;
+            background: #ffffffcf;
+            position: absolute;
+            display: inline-block;
+            cursor: move;
+        }
     }
 
     .focus-visible {
         margin-left: 0px;
     }
-
-    .publishBox {
-        width: 20px;
-        height: 22px;
-        grid-column-start: 3;
-        grid-column-end: 4;
-        pointer-events: all;
-        background: darkgray;
-        display: inline-block;
-        position: absolute;
-        right: 0;
-    }
 }
 
 
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 54e0a7ac7..8d8f4cd3b 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -577,8 +577,8 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b
         const titleArea = this._edtingTitle ?
             <input ref={this._keyinput} className="documentDecorations-title" type="text" name="dynbox" autoComplete="on" value={this._accumulatedTitle}
                 onBlur={e => this.titleBlur(true)} onChange={action(e => this._accumulatedTitle = e.target.value)} onKeyPress={this.titleEntered} /> :
-            <div className="documentDecorations-title" style={{ gridColumnEnd: 5 }} key="title" onPointerDown={this.onTitleDown} >
-                <span style={{ width: "100%", display: "inline-block", cursor: "move" }}>{`${this.selectionTitle}`}</span>
+            <div className="documentDecorations-title" style={{ width: `calc(100% - ${seldoc.props.hideResizeHandles ? 0 : 20}px` }} key="title" onPointerDown={this.onTitleDown} >
+                <span className="documentDecorations-titleSpan">{`${this.selectionTitle}`}</span>
             </div>;
 
         let inMainMenuPanel = false;
@@ -612,7 +612,7 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b
                     top: bounds.y - this._resizeBorderWidth / 2 - this._titleHeight,
                 }}>
                     {closeIcon}
-                    {bounds.r - bounds.x < 100 ? null : titleArea}
+                    {titleArea}
                     {seldoc.props.hideResizeHandles ? (null) :
                         <>
                             {SelectionManager.Views().length !== 1 || seldoc.Document.type === DocumentType.INK ? (null) :
diff --git a/src/client/views/MainView.scss b/src/client/views/MainView.scss
index d6a455a22..8ccb64744 100644
--- a/src/client/views/MainView.scss
+++ b/src/client/views/MainView.scss
@@ -61,7 +61,7 @@
 }
 
 .mainView-container {
-    color: dimgray;
+    color: black;
 
     .lm_title {
         background: #cacaca;
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 73375569f..8c3f0997f 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -931,11 +931,13 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
             const layoutdoc = Doc.Layout(doc);
             const savedState = { px: this.Document._panX, py: this.Document._panY, s: this.Document[this.scaleFieldKey], pt: this.Document._viewTransition };
 
-            willZoom && this.setScaleToZoom(layoutdoc, scale);
-            const newPanX = (NumCast(doc.x) + doc[WidthSym]() / 2) - (this.isAnnotationOverlay ? (Doc.NativeWidth(this.props.Document)) / 2 / this.zoomScaling() : 0);
-            const newPanY = (NumCast(doc.y) + doc[HeightSym]() / 2) - (this.isAnnotationOverlay ? (Doc.NativeHeight(this.props.Document)) / 2 / this.zoomScaling() : 0);
             const newState = HistoryUtil.getState();
-            newState.initializers![this.Document[Id]] = { panX: newPanX, panY: newPanY };
+            if (!layoutdoc.annotationOn) {
+                willZoom && this.setScaleToZoom(layoutdoc, scale);
+                const newPanX = (NumCast(doc.x) + doc[WidthSym]() / 2) - (this.isAnnotationOverlay ? (Doc.NativeWidth(this.props.Document)) / 2 / this.zoomScaling() : 0);
+                const newPanY = (NumCast(doc.y) + doc[HeightSym]() / 2) - (this.isAnnotationOverlay ? (Doc.NativeHeight(this.props.Document)) / 2 / this.zoomScaling() : 0);
+                newState.initializers![this.Document[Id]] = { panX: newPanX, panY: newPanY };
+            }
             HistoryUtil.pushState(newState);
 
             if (DocListCast(this.dataDoc[this.props.fieldKey]).includes(doc)) {
diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx
index 62e497e18..8d0283a12 100644
--- a/src/client/views/nodes/PresBox.tsx
+++ b/src/client/views/nodes/PresBox.tsx
@@ -417,15 +417,16 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
             self._dragArray.splice(0, self._dragArray.length, ...dragViewCache);
             self._eleArray.splice(0, self._eleArray.length, ...eleViewCache);
         });
-        const openInTab = () => {
-            collectionDocView ? collectionDocView.props.addDocTab(targetDoc, "") : this.props.addDocTab(targetDoc, ":left");
+        const openInTab = (doc: Doc, finished?: () => void) => {
+            collectionDocView ? collectionDocView.props.addDocTab(doc, "") : this.props.addDocTab(doc, ":left");
             this.layoutDoc.presCollection = targetDoc;
             // this still needs some fixing
             setTimeout(resetSelection, 500);
+            doc !== targetDoc && setTimeout(() => finished?.(), 100); /// give it some time to create the targetDoc if we're opening up its context
         };
         // If openDocument is selected then it should open the document for the user
         if (activeItem.openDocument) {
-            openInTab();
+            openInTab(targetDoc);
         } else if (curDoc.presMovement === PresMovement.Pan && targetDoc) {
             await DocumentManager.Instance.jumpToDocument(targetDoc, false, openInTab, srcContext, undefined, undefined, undefined, includesDoc || tab ? undefined : resetSelection); // documents open in new tab instead of on right
         } else if ((curDoc.presMovement === PresMovement.Zoom || curDoc.presMovement === PresMovement.Jump) && targetDoc) {
-- 
cgit v1.2.3-70-g09d2

