From 6c7101d4f69dd79a83a48d04356748213c38a435 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Mon, 11 Apr 2022 13:31:33 -0400
Subject: making layout icons work better.

---
 src/client/views/StyleProvider.tsx | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

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

diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index 649ee8394..739670ecf 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -117,7 +117,10 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
             doc?.type === DocumentType.RTF) && showTitle() && !StrCast(doc?.showTitle).includes(":hover") ? 15 : 0;
         case StyleProp.BackgroundColor: {
             if (MainView.Instance.LastButton === doc) return Colors.LIGHT_GRAY;
-            let docColor: Opt<string> = StrCast(doc?.[fieldKey + "backgroundColor"], StrCast(doc?._backgroundColor, isCaption ? "rgba(0,0,0,0.4)" : ""));
+            let docColor: Opt<string> =
+                StrCast(doc?.[fieldKey + "backgroundColor"],
+                    StrCast(doc?._backgroundColor,
+                        StrCast(props?.Document.backgroundColor, isCaption ? "rgba(0,0,0,0.4)" : "")));
             switch (doc?.type) {
                 case DocumentType.PRESELEMENT: docColor = docColor || (darkScheme() ? "" : ""); break;
                 case DocumentType.PRES: docColor = docColor || (darkScheme() ? Colors.DARK_GRAY : Colors.WHITE); break;
@@ -127,7 +130,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
                 case DocumentType.INK: docColor = doc?.isInkMask ? "rgba(0,0,0,0.7)" : undefined; break;
                 case DocumentType.SLIDER: break;
                 case DocumentType.EQUATION: docColor = docColor || "transparent"; break;
-                case DocumentType.LABEL: docColor = docColor || (doc.annotationOn !== undefined ? "rgba(128, 128, 128, 0.18)" : undefined); break;
+                case DocumentType.LABEL: docColor = docColor || (doc.annotationOn !== undefined ? "rgba(128, 128, 128, 0.18)" : undefined) || (darkScheme() ? Colors.DARK_GRAY : Colors.LIGHT_GRAY); break;
                 case DocumentType.BUTTON: docColor = docColor || (darkScheme() ? Colors.DARK_GRAY : Colors.LIGHT_GRAY); break;
                 case DocumentType.LINKANCHOR: docColor = isAnchor ? Colors.LIGHT_BLUE : "transparent"; break;
                 case DocumentType.LINK: docColor = (isAnchor ? docColor : "") || "transparent"; break;
-- 
cgit v1.2.3-70-g09d2


From 49437d51b277206f31cdcdf0106944bab8330f4d Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Mon, 11 Apr 2022 16:06:15 -0400
Subject: lots of layout fixes to groups, labels, ink to support iconification
 better.  simpliifed documentdecorations.  fixed display artifacts related to
 things not showing up when dragging, or otherwise not getting a halo of
 nested freeform colletions.

---
 src/client/util/CurrentUserUtils.ts                |   8 +-
 src/client/util/DragManager.ts                     |   2 +-
 src/client/views/DocumentDecorations.scss          | 496 ++++++++++-----------
 src/client/views/DocumentDecorations.tsx           |  10 +-
 src/client/views/InkingStroke.tsx                  |   6 +-
 src/client/views/StyleProvider.tsx                 |   6 +-
 .../collectionFreeForm/CollectionFreeFormView.tsx  |  11 +-
 .../views/nodes/CollectionFreeFormDocumentView.tsx |   5 +-
 src/client/views/nodes/DocumentIcon.tsx            |   1 +
 src/client/views/nodes/DocumentView.scss           |   3 +
 src/client/views/nodes/DocumentView.tsx            |   8 +-
 src/client/views/nodes/LabelBigText.js             |   1 +
 src/client/views/nodes/LabelBox.scss               |   2 +-
 src/client/views/nodes/LabelBox.tsx                |  31 +-
 14 files changed, 275 insertions(+), 315 deletions(-)

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

diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index bc4dbcb2e..6d8e2d30c 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -320,17 +320,17 @@ export class CurrentUserUtils {
         }
         if (doc["template-icon-view-img"] === undefined) {
             const iconImageView = Docs.Create.ImageDocument("http://www.cs.brown.edu/~bcz/face.gif", {
-                title: "data", _width: 50, isTemplateDoc: true, onClick: ScriptField.MakeScript("deiconifyView(documentView)", { documentView: "any" }), system: true
+                title: "data", _width: 150, isTemplateDoc: true, onClick: ScriptField.MakeScript("deiconifyView(documentView)", { documentView: "any" }), system: true
             });
             iconImageView.isTemplateDoc = makeTemplate(iconImageView, true, "icon_" + DocumentType.IMG);
             doc["template-icon-view-img"] = new PrefetchProxy(iconImageView);
         }
         if (doc["template-icon-view-col"] === undefined) {
-            const iconColView = Docs.Create.ImageDocument("", { title: "icon", _width: 180 / 4, _height: 135 / 4, onClick: ScriptField.MakeScript("deiconifyView(documentView)", { documentView: "any" }), system: true });
+            const iconColView = Docs.Create.ImageDocument("", { title: "icon", _width: 360 / 4, _height: 270 / 4, onClick: ScriptField.MakeScript("deiconifyView(documentView)", { documentView: "any" }), system: true });
             iconColView.isTemplateDoc = makeTemplate(iconColView, true, "icon_" + DocumentType.COL);
             const proto = iconColView.proto as Doc;
-            proto["icon-nativeWidth"] = 180 / 4;
-            proto["icon-nativeHeight"] = 135 / 4;
+            proto["icon-nativeWidth"] = 360 / 4;
+            proto["icon-nativeHeight"] = 270 / 4;
             proto.icon = new ImageField("http://www.cs.brown.edu/~bcz/noImage.png");
             doc["template-icon-view-col"] = new PrefetchProxy(iconColView);
         }
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index d6d04db9a..94a09eac4 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -424,7 +424,7 @@ export namespace DragManager {
 
         const hideDragShowOriginalElements = (hide: boolean) => {
             dragLabel.style.display = hide ? "" : "none";
-            //!hide && dragElements.map(dragElement => dragElement.parentNode === dragDiv && dragDiv.removeChild(dragElement));
+            !hide && dragElements.map(dragElement => dragElement.parentNode === dragDiv && dragDiv.removeChild(dragElement));
             eles.forEach(ele => ele.hidden = hide);
         };
         options?.hideSource && hideDragShowOriginalElements(true);
diff --git a/src/client/views/DocumentDecorations.scss b/src/client/views/DocumentDecorations.scss
index 82dca1287..35e37a2cd 100644
--- a/src/client/views/DocumentDecorations.scss
+++ b/src/client/views/DocumentDecorations.scss
@@ -4,8 +4,8 @@ $linkGap: 3px;
 
 .documentDecorations-Dark,
 .documentDecorations {
-  position: absolute;
-  z-index: 2000;
+    position: absolute;
+    z-index: 2000;
 }
 .documentDecorations-Dark {
     background: dimgray;
@@ -17,11 +17,11 @@ $linkGap: 3px;
     left: 0;
     display: grid;
     grid-template-rows: 20px 8px 1fr 8px;
-    grid-template-columns: 8px 16px 1fr 8px 8px;
+    grid-template-columns: 8px 1fr 8px;
     pointer-events: none;
 
     .documentDecorations-centerCont {
-        grid-column: 3;
+        grid-column: 2;
         background: none;
     }
 
@@ -41,6 +41,7 @@ $linkGap: 3px;
         opacity: 1;
         transform: translate(10px, 10px);
         grid-row: 4;
+        grid-column: 3
     }
 
     .documentDecorations-topLeftResizer,
@@ -73,20 +74,18 @@ $linkGap: 3px;
 
     .documentDecorations-topResizer,
     .documentDecorations-bottomResizer {
-        grid-column-start: 2;
-        grid-column-end: 5;
+        grid-column: 2;
     }
 
     .documentDecorations-bottomRightResizer,
     .documentDecorations-topRightResizer,
     .documentDecorations-rightResizer {
-        grid-column-start: 5;
-        grid-column-end: 7;
+        grid-column: 3;
     }
 
     .documentDecorations-rotation,
     .documentDecorations-borderRadius {
-        grid-column: 5;
+        grid-column: 3;
         grid-row: 4;
         border-radius: 100%;
         background: black;
@@ -132,114 +131,113 @@ $linkGap: 3px;
         opacity: 1;
     }
 
-  .documentDecorations-topLeftResizer,
-  .documentDecorations-leftResizer,
-  .documentDecorations-bottomLeftResizer {
-    grid-column: 1;
-  }
-
-  .documentDecorations-topResizer,
-  .documentDecorations-bottomResizer {
-    grid-column-start: 2;
-    grid-column-end: 5;
-  }
-
-  .documentDecorations-bottomRightResizer,
-  .documentDecorations-topRightResizer,
-  .documentDecorations-rightResizer {
-    grid-column-start: 5;
-    grid-column-end: 7;
-  }
-
-  .documentDecorations-rotation,
-  .documentDecorations-borderRadius {
-    grid-column: 5;
-    grid-row: 4;
-    border-radius: 100%;
-    background: black;
-    height: 8;
-    right: -12;
-    top: 12;
-    position: relative;
-    pointer-events: all;
-    cursor: nwse-resize;
-
-    .borderRadiusTooltip {
-      width: 10px;
-      height: 10px;
-      position: absolute;
-    }
-  }
-  .documentDecorations-rotation {
-    background: transparent;
-    right: -15;
-  }
-
-  .documentDecorations-topLeftResizer,
-  .documentDecorations-bottomRightResizer {
-    cursor: nwse-resize;
-    background: unset;
-    opacity: 1;
-  }
+    .documentDecorations-topLeftResizer,
+    .documentDecorations-leftResizer,
+    .documentDecorations-bottomLeftResizer {
+        grid-column: 1;
+    }
 
-  .documentDecorations-topLeftResizer {
-    border-left: 2px solid;
-    border-top: solid 2px;
-  }
+    .documentDecorations-topResizer,
+    .documentDecorations-bottomResizer {
+        grid-column: 2;
+    }
 
-  .documentDecorations-bottomRightResizer {
-    border-right: 2px solid;
-    border-bottom: solid 2px;
-  }
+    .documentDecorations-bottomRightResizer,
+    .documentDecorations-topRightResizer,
+    .documentDecorations-rightResizer {
+        grid-column: 3
+    }
 
-  .documentDecorations-topLeftResizer:hover,
-  .documentDecorations-bottomRightResizer:hover {
-    opacity: 1;
-  }
+    .documentDecorations-rotation,
+    .documentDecorations-borderRadius {
+        grid-column: 3;
+        grid-row: 4;
+        border-radius: 100%;
+        background: black;
+        height: 8;
+        right: -12;
+        top: 12;
+        position: relative;
+        pointer-events: all;
+        cursor: nwse-resize;
 
-  .documentDecorations-bottomRightResizer {
-    grid-row: 4;
-  }
+        .borderRadiusTooltip {
+            width: 10px;
+            height: 10px;
+            position: absolute;
+        }
+    }
+    .documentDecorations-rotation {
+        background: transparent;
+        right: -15;
+    }
 
-  .documentDecorations-topRightResizer,
-  .documentDecorations-bottomLeftResizer {
-    cursor: nesw-resize;
-    background: unset;
-    opacity: 1;
-  }
+    .documentDecorations-topLeftResizer,
+    .documentDecorations-bottomRightResizer {
+        cursor: nwse-resize;
+        background: unset;
+        opacity: 1;
+    }
+
+    .documentDecorations-topLeftResizer {
+        border-left: 2px solid;
+        border-top: solid 2px;
+    }
+
+    .documentDecorations-bottomRightResizer {
+        border-right: 2px solid;
+        border-bottom: solid 2px;
+    }
+
+    .documentDecorations-topLeftResizer:hover,
+    .documentDecorations-bottomRightResizer:hover {
+        opacity: 1;
+    }
+
+    .documentDecorations-bottomRightResizer {
+        grid-row: 4;
+    }
+
+    .documentDecorations-topRightResizer,
+    .documentDecorations-bottomLeftResizer {
+        cursor: nesw-resize;
+        background: unset;
+        opacity: 1;
+    }
 
-  .documentDecorations-topRightResizer {
-    border-right: 2px solid;
-    border-top: 2px solid;
-  }
+    .documentDecorations-topRightResizer {
+        border-right: 2px solid;
+        border-top: 2px solid;
+    }
 
-  .documentDecorations-bottomLeftResizer {
-    border-left: 2px solid;
-    border-bottom: 2px solid;
-  }
+    .documentDecorations-bottomLeftResizer {
+        border-left: 2px solid;
+        border-bottom: 2px solid;
+    }
 
-  .documentDecorations-topRightResizer:hover,
-  .documentDecorations-bottomLeftResizer:hover {
+.documentDecorations-topRightResizer:hover,
+.documentDecorations-bottomLeftResizer:hover {
     cursor: nesw-resize;
     background: black;
     opacity: 1;
-  }
+}
 
-  .documentDecorations-topResizer,
-  .documentDecorations-bottomResizer {
+.documentDecorations-topResizer,
+.documentDecorations-bottomResizer {
     cursor: ns-resize;
-  }
+}
 
-    .documentDecorations-title-Dark,
-    .documentDecorations-title {
+.documentDecorations-title-Dark,
+.documentDecorations-title {
         opacity: 1;
-        grid-column-start: 2;
-        grid-column-end: 4;
+        width: 100%;
+        grid-column: 2;
         pointer-events: auto;
         overflow: hidden;
         text-align: center;
         display: flex;
-        margin-left: 5px;
+        padding-left: 5px;
+        padding-right: 12px;
         height: 20px;
         position: absolute;
         border-radius: 8px;
@@ -247,7 +245,7 @@ $linkGap: 3px;
 
         .documentDecorations-titleSpan, 
         .documentDecorations-titleSpan-Dark  {
-            width: 100%;
+            width: calc(100% - 17px); // = padding-left + padding-right
             border-radius: 8px;
             background: #ffffffa0;
             position: absolute;
@@ -263,105 +261,61 @@ $linkGap: 3px;
         background: black;
     }
 
-  .documentDecorations-contextMenu {
-    width: 25px;
-    height: calc(100% + 8px); // 8px for the height of the top resizer bar
-    grid-column-start: 2;
-    grid-column-end: 2;
-    pointer-events: all;
-    padding-left: 5px;
-    cursor: pointer;
-  }
-
-  .documentDecorations-titleBackground {
-    background: #ffffffcf;
-    border-radius: 8px;
-    width: 100%;
-    height: 100%;
-    position: absolute;
-  }
-
-  .documentDecorations-title {
-    opacity: 1;
-    grid-column-start: 2;
-    grid-column-end: 4;
-    pointer-events: auto;
-    overflow: hidden;
-    text-align: center;
-    display: flex;
-    margin-left: 5px;
-    height: 20px;
-    position: absolute;
-    .documentDecorations-titleSpan {
-      width: 100%;
-      border-radius: 8px;
-      background: #ffffffcf;
-      position: absolute;
-      display: inline-block;
-      cursor: move;
-    }
-  }
-
-  .focus-visible {
-    margin-left: 0px;
-  }
-}
+    .documentDecorations-titleBackground {
+        background: #ffffffcf;
+        border-radius: 8px;
+        width: 100%;
+        height: 100%;
+        position: absolute;
+    }
 
-.documentDecorations-iconifyButton {
-  opacity: 1;
-  grid-column-start: 4;
-  grid-column-end: 4;
-  pointer-events: all;
-  right: 0;
-  cursor: pointer;
-  position: absolute;
-  width: 20px;
+    .focus-visible {
+        margin-left: 0px;
+    }
 }
 
 .documentDecorations-openButton {
-  display: flex;
-  align-items: center;
-  opacity: 1;
-  grid-column-start: 5;
-  grid-column-end: 5;
-  pointer-events: all;
-  cursor: pointer;
+    display: flex;
+    align-items: center;
+    opacity: 1;
+    grid-column-start: 3;
+    pointer-events: all;
+    cursor: pointer;
 }
 
 .documentDecorations-closeButton {
-  display: flex;
-  align-items: center;
-  opacity: 1;
-  grid-column-start: 1;
-  grid-column-end: 3;
-  pointer-events: all;
-  cursor: pointer;
-
-  > svg {
-    margin: 0;
-  }
+    display: flex;
+    align-items: center;
+    opacity: 1;
+    grid-column: 1;
+    pointer-events: all;
+    cursor: pointer;
+
+    > svg {
+        margin: 0;
+    }
 }
 
 .documentDecorations-background {
-  background: lightblue;
-  position: absolute;
-  opacity: 0.1;
+    background: lightblue;
+    position: absolute;
+    opacity: 0.1;
 }
 
 .linkFlyout {
-  grid-column: 2/4;
+    grid-column: 2/4;
 }
 
 .linkButton-empty:hover {
-  background: $medium-gray;
-  transform: scale(1.05);
-  cursor: pointer;
+    background: $medium-gray;
+    transform: scale(1.05);
+    cursor: pointer;
 }
 
 .linkButton-nonempty:hover {
-  background: $medium-gray;
-  transform: scale(1.05);
-  cursor: pointer;
+    background: $medium-gray;
+    transform: scale(1.05);
+    cursor: pointer;
 }
 
 .link-button-container {
@@ -379,132 +333,132 @@ $linkGap: 3px;
 }
 
 .linkButtonWrapper {
-  pointer-events: auto;
-  padding-right: 5px;
-  width: 25px;
+    pointer-events: auto;
+    padding-right: 5px;
+    width: 25px;
 }
 
 .linkButton-linker {
-  height: 20px;
-  width: 20px;
-  text-align: center;
-  border-radius: 50%;
-  pointer-events: auto;
-  color: $dark-gray;
-  border: $dark-gray 1px solid;
+    height: 20px;
+    width: 20px;
+    text-align: center;
+    border-radius: 50%;
+    pointer-events: auto;
+    color: $dark-gray;
+    border: $dark-gray 1px solid;
 }
 
 .linkButton-linker:hover {
-  cursor: pointer;
-  transform: scale(1.05);
+    cursor: pointer;
+    transform: scale(1.05);
 }
 
 .linkButton-empty,
 .linkButton-nonempty {
-  height: 20px;
-  width: 20px;
-  border-radius: 50%;
-  opacity: 0.9;
-  pointer-events: auto;
-  background-color: $dark-gray;
-  color: $white;
-  text-transform: uppercase;
-  letter-spacing: 2px;
-  font-size: 75%;
-  transition: transform 0.2s;
-  text-align: center;
-  display: flex;
-  justify-content: center;
-  align-items: center;
-
-  &:hover {
-    background: $medium-gray;
-    transform: scale(1.05);
-    cursor: pointer;
-  }
+    height: 20px;
+    width: 20px;
+    border-radius: 50%;
+    opacity: 0.9;
+    pointer-events: auto;
+    background-color: $dark-gray;
+    color: $white;
+    text-transform: uppercase;
+    letter-spacing: 2px;
+    font-size: 75%;
+    transition: transform 0.2s;
+    text-align: center;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+
+    &:hover {
+        background: $medium-gray;
+        transform: scale(1.05);
+        cursor: pointer;
+    }
 }
 
 .templating-menu {
-  position: absolute;
-  pointer-events: auto;
-  text-transform: uppercase;
-  letter-spacing: 2px;
-  font-size: 75%;
-  transition: transform 0.2s;
-  text-align: center;
-  display: flex;
-  justify-content: center;
-  align-items: center;
+    position: absolute;
+    pointer-events: auto;
+    text-transform: uppercase;
+    letter-spacing: 2px;
+    font-size: 75%;
+    transition: transform 0.2s;
+    text-align: center;
+    display: flex;
+    justify-content: center;
+    align-items: center;
 }
 
 .documentdecorations-icon {
-  margin: 0px;
+    margin: 0px;
 }
 
 .templating-button,
 .docDecs-tagButton {
-  width: 20px;
-  height: 20px;
-  border-radius: 50%;
-  opacity: 0.9;
-  font-size: 14;
-  background-color: $dark-gray;
-  color: $white;
-  text-align: center;
-  cursor: pointer;
-
-  &:hover {
-    background: $medium-gray;
-    transform: scale(1.05);
-  }
+    width: 20px;
+    height: 20px;
+    border-radius: 50%;
+    opacity: 0.9;
+    font-size: 14;
+    background-color: $dark-gray;
+    color: $white;
+    text-align: center;
+    cursor: pointer;
+
+    &:hover {
+        background: $medium-gray;
+        transform: scale(1.05);
+    }
 }
 
 #template-list {
-  position: absolute;
-  top: 25px;
-  left: 0px;
-  width: max-content;
-  font-family: $sans-serif;
-  font-size: 12px;
-  background-color: $light-gray;
-  padding: 2px 12px;
-  list-style: none;
-
-  .templateToggle,
-  .chromeToggle {
-    text-align: left;
-  }
-
-  input {
-    margin-right: 10px;
-  }
+    position: absolute;
+    top: 25px;
+    left: 0px;
+    width: max-content;
+    font-family: $sans-serif;
+    font-size: 12px;
+    background-color: $light-gray;
+    padding: 2px 12px;
+    list-style: none;
+
+    .templateToggle,
+    .chromeToggle {
+        text-align: left;
+    }
+
+    input {
+        margin-right: 10px;
+    }
 }
 
 @-moz-keyframes spin {
-  100% {
-    -moz-transform: rotate(360deg);
-  }
+    100% {
+        -moz-transform: rotate(360deg);
+    }
 }
 
 @-webkit-keyframes spin {
-  100% {
-    -webkit-transform: rotate(360deg);
-  }
+    100% {
+        -webkit-transform: rotate(360deg);
+    }
 }
 
 @keyframes spin {
-  100% {
-    -webkit-transform: rotate(360deg);
-    transform: rotate(360deg);
-  }
+    100% {
+        -webkit-transform: rotate(360deg);
+        transform: rotate(360deg);
+    }
 }
 
 @keyframes shadow-pulse {
-  0% {
-    box-shadow: 0 0 0 0px rgba(0, 0, 0, 0.8);
-  }
+    0% {
+        box-shadow: 0 0 0 0px rgba(0, 0, 0, 0.8);
+    }
 
-  100% {
-    box-shadow: 0 0 0 10px rgba(0, 255, 0, 0);
-  }
+    100% {
+        box-shadow: 0 0 0 10px rgba(0, 255, 0, 0);
+    }
 }
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 1487d5bb0..353843b8d 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -449,7 +449,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number, P
         if (SnappingManager.GetIsDragging() || bounds.r - bounds.x < 1 || bounds.x === Number.MAX_VALUE || !seldoc || this._hidden || isNaN(bounds.r) || isNaN(bounds.b) || isNaN(bounds.x) || isNaN(bounds.y)) {
             return (null);
         }
-        const hideResizers = seldoc.props.hideResizeHandles || seldoc.rootDoc.hideResizeHandles;
+        const hideResizers = seldoc.props.hideResizeHandles || seldoc.rootDoc.hideResizeHandles || seldoc.rootDoc.isGroup;
         const hideTitle = seldoc.props.hideDecorationTitle || seldoc.rootDoc.hideDecorationTitle;
         const canOpen = SelectionManager.Views().some(docView => !docView.props.Document._stayInCollection && !docView.props.Document.isGroup && !docView.props.Document.hideOpenButton);
         const canDelete = SelectionManager.Views().some(docView => {
@@ -466,16 +466,16 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number, P
             </Tooltip>);
 
         const colorScheme = StrCast(CurrentUserUtils.ActiveDashboard?.colorScheme);
-        const titleArea = hideTitle ? <div className="documentDecorations-title" onPointerDown={this.onTitleDown} style={{ width: "100%" }} key="title" /> :
+        const titleArea = hideTitle ? <div className="documentDecorations-title" onPointerDown={this.onTitleDown} key="title" /> :
             this._edtingTitle ?
                 <input ref={this._keyinput} className={`documentDecorations-title${colorScheme}`}
-                    style={{ width: `calc(100% - ${hideResizers ? 0 : 20}px` }}
+                    style={{ width: `100%` }}
                     type="text" name="dynbox" autoComplete="on"
                     value={this._accumulatedTitle}
                     onBlur={e => this.titleBlur()}
                     onChange={action(e => this._accumulatedTitle = e.target.value)}
                     onKeyPress={this.titleEntered} /> :
-                <div className="documentDecorations-title" style={{ width: `calc(100% - ${hideResizers ? 0 : 20}px` }} key="title" onPointerDown={this.onTitleDown} >
+                <div className="documentDecorations-title" style={{ width: `100%` }} key="title" onPointerDown={this.onTitleDown} >
                     <span className={`documentDecorations-titleSpan${colorScheme}`}>{`${this.selectionTitle}`}</span>
                 </div>;
 
@@ -515,8 +515,6 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number, P
                     {!canOpen ? (null) : topBtn("open", "external-link-alt", this.onMaximizeDown, undefined, "Open in Tab (ctrl: as alias, shift: in new collection)")}
                     {hideResizers ? (null) :
                         <>
-                            {SelectionManager.Views().length !== 1 || hideTitle ? (null) :
-                                topBtn("iconify", `window-${seldoc.finalLayoutKey.includes("icon") ? "restore" : "minimize"}`, undefined, this.onIconifyClick, `${seldoc.finalLayoutKey.includes("icon") ? "De" : ""}Iconify Document`)}
                             <div key="tl" className={`documentDecorations-topLeftResizer ${resizerScheme}`} onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()} />
                             <div key="t" className={`documentDecorations-topResizer ${resizerScheme}`} onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()} />
                             <div key="tr" className={`documentDecorations-topRightResizer ${resizerScheme}`} onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()} />
diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx
index 5e589fdea..06671961d 100644
--- a/src/client/views/InkingStroke.tsx
+++ b/src/client/views/InkingStroke.tsx
@@ -70,11 +70,7 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps>() {
 
     // transform is the inherited screentolocal xf plus any scaling that was done to make the stroke
     // fit within its panel (e.g., for content fitting views like Lightbox or multicolumn, etc)
-    screenToLocal = () => {
-        console.log("Scaling = " + this.props.scaling?.())
-        console.log("Stolocal = " + this.props.ScreenToLocalTransform().Scale)
-        return this.props.ScreenToLocalTransform().scale(this.props.scaling?.() || 1);
-    }
+    screenToLocal = () => this.props.ScreenToLocalTransform().scale(this.props.scaling?.() || 1);
 
     getAnchor = () => {
         console.log(document.activeElement);
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index 739670ecf..eb6551fc8 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -98,7 +98,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
         case StyleProp.ShowTitle: return (doc && !doc.presentationTargetDoc &&
             StrCast(doc._showTitle,
                 props?.showTitle?.() ||
-                (!Doc.IsSystem(doc) && [DocumentType.COL, DocumentType.RTF, DocumentType.IMG, DocumentType.VID].includes(doc.type as any) ?
+                (!Doc.IsSystem(doc) && [DocumentType.COL, DocumentType.LABEL, DocumentType.RTF, DocumentType.IMG, DocumentType.VID].includes(doc.type as any) ?
                     (doc.author === Doc.CurrentUserEmail ? StrCast(Doc.UserDoc().showTitle) :
                         "author;creationDate") : "")) || "");
         case StyleProp.Color:
@@ -114,7 +114,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
         case StyleProp.BorderPath: return comicStyle() && props?.renderDepth && doc?.type !== DocumentType.INK ? { path: wavyBorderPath(props?.PanelWidth?.() || 0, props?.PanelHeight?.() || 0), fill: wavyBorderPath(props?.PanelWidth?.() || 0, props?.PanelHeight?.() || 0, .08), width: 3 } : { path: undefined, width: 0 };
         case StyleProp.JitterRotation: return comicStyle() ? random(-1, 1, NumCast(doc?.x), NumCast(doc?.y)) * ((props?.PanelWidth() || 0) > (props?.PanelHeight() || 0) ? 5 : 10) : 0;
         case StyleProp.HeaderMargin: return ([CollectionViewType.Stacking, CollectionViewType.Masonry, CollectionViewType.Tree].includes(doc?._viewType as any) ||
-            doc?.type === DocumentType.RTF) && showTitle() && !StrCast(doc?.showTitle).includes(":hover") ? 15 : 0;
+            doc?.type === DocumentType.RTF || doc?.type === DocumentType.LABEL) && showTitle() && !StrCast(doc?.showTitle).includes(":hover") ? 15 : 0;
         case StyleProp.BackgroundColor: {
             if (MainView.Instance.LastButton === doc) return Colors.LIGHT_GRAY;
             let docColor: Opt<string> =
@@ -143,7 +143,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
                 case DocumentType.COL:
                     if (StrCast(Doc.LayoutField(doc)).includes(SliderBox.name)) break;
                     docColor = docColor ||
-                        (doc?._isGroup ? "#00000004" : // very faint highlight to show bounds of group
+                        (doc?._isGroup ? "#00000010" : // very faint highlight to show bounds of group
                             (doc?._viewType === CollectionViewType.Pile || Doc.IsSystem(doc) ? (darkScheme() ? Colors.DARK_GRAY : Colors.LIGHT_GRAY) : // system docs (seen in treeView) get a grayish background
                                 isBackground() ? "cyan" : // ?? is there a good default for a background collection
                                     doc.annotationOn ? "#00000015" : // faint interior for collections on PDFs, images, etc
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 7ca6dfd93..04beed541 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1014,8 +1014,8 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
         } else if (doc.isInkMask) {
             doc.zIndex = 5000;
         } else {
-            const docs = this.childLayoutPairs.map(pair => pair.layout);
-            docs.slice().sort((doc1, doc2) => NumCast(doc1.zIndex) - NumCast(doc2.zIndex));
+            const docs = this.childLayoutPairs.map(pair => pair.layout).slice();
+            docs.sort((doc1, doc2) => NumCast(doc1.zIndex) - NumCast(doc2.zIndex));
             let zlast = docs.length ? Math.max(docs.length, NumCast(docs[docs.length - 1].zIndex)) : 1;
             if (zlast - docs.length > 100) {
                 for (let i = 0; i < docs.length; i++) doc.zIndex = i + 1;
@@ -1414,12 +1414,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
         }));
     }
 
-    clicks = 0;
     updateIcon = () => {
-        if (this.clicks) {
-            console.log("UPDATE ICON");
-        }
-        this.clicks++;
         this.props.docViewPath().lastElement().ContentDiv!.style.width = (this.layoutDoc[WidthSym]()).toString();
         this.props.docViewPath().lastElement().ContentDiv!.style.height = (this.layoutDoc[HeightSym]()).toString();
         var htmlString = this._mainCont && new XMLSerializer().serializeToString(this.props.docViewPath().lastElement().ContentDiv!);
@@ -1431,7 +1426,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
         CreateImage(
             "",
             document.styleSheets,
-            htmlString?.replace(/"marqueeView"/g, '"marqueeView marqueeView2"'),
+            htmlString?.replace(/docView-hack/g, 'documentView-hack'),
             nativeWidth,
             nativeWidth * this.props.PanelHeight() / this.props.PanelWidth(),
             NumCast(this.layoutDoc._scrollTop)
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index 5149d370f..ba34d846e 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -167,7 +167,10 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
             PanelHeight: this.panelHeight,
         };
         const background = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
-        const mixBlendMode = StrCast(this.layoutDoc.mixBlendMode) as any || (typeof background === "string" && DashColor(background).alpha() !== 1 ? "multiply" : undefined);
+        const mixBlendMode = "";//StrCast(this.layoutDoc.mixBlendMode) as any || (typeof background === "string" && DashColor(background).alpha() !== 1 ? "multiply" : undefined);
+        if (mixBlendMode) {
+            console.log(mixBlendMode);
+        }
         return <div className={"collectionFreeFormDocumentView-container"}
             style={{
                 outline: this.Highlight ? "orange solid 2px" : "",
diff --git a/src/client/views/nodes/DocumentIcon.tsx b/src/client/views/nodes/DocumentIcon.tsx
index 433a0bf48..a9c998757 100644
--- a/src/client/views/nodes/DocumentIcon.tsx
+++ b/src/client/views/nodes/DocumentIcon.tsx
@@ -1,3 +1,4 @@
+
 import { observer } from "mobx-react";
 import * as React from "react";
 import { DocumentView } from "./DocumentView";
diff --git a/src/client/views/nodes/DocumentView.scss b/src/client/views/nodes/DocumentView.scss
index 4565f8504..5c5d2df10 100644
--- a/src/client/views/nodes/DocumentView.scss
+++ b/src/client/views/nodes/DocumentView.scss
@@ -3,6 +3,9 @@
 .documentView-effectsWrapper {
     border-radius: inherit;
 }
+.documentView-hack {
+    display: inline;
+}
 
 .documentView-customBorder {
     width:100%;
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 185eafa4a..423a5edbf 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -887,10 +887,10 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
                 focus={this.focus}
                 layoutKey={this.finalLayoutKey} />
             {this.layoutDoc.hideAllLinks ? (null) : this.allLinkEndpoints}
-            {!this.props.isSelected() || this.hideLinkButton || this.props.renderDepth === -1 || SnappingManager.GetIsDragging() ? (null) :
+            {(!this.props.isSelected() && !this._isHovering) || this.hideLinkButton || this.props.renderDepth === -1 || SnappingManager.GetIsDragging() ? (null) :
                 <DocumentLinksButton View={this.props.DocumentView()}
                     ContentScaling={this.props.ContentScaling}
-                    Offset={[this.topMost ? 0 : -15, undefined, undefined, this.topMost ? 10 : -20]} />
+                    Offset={[this.topMost ? 0 : !this.props.isSelected() ? - 15 : -30, undefined, undefined, this.topMost ? 10 : !this.props.isSelected() ? - 15 : -30]} />
             }
             {audioView}
         </div>;
@@ -1111,7 +1111,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
             this.boxShadow || (this.props.Document.isTemplateForField ? "black 0.2vw 0.2vw 0.8vw" : undefined);
 
         // Return surrounding highlight 
-        return <div className={DocumentView.ROOT_DIV} ref={this._mainCont}
+        return <div className={`${DocumentView.ROOT_DIV} docView-hack`} ref={this._mainCont}
             onContextMenu={this.onContextMenu}
             onKeyDown={this.onKeyDown}
             onPointerDown={this.onPointerDown}
@@ -1119,7 +1119,6 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
             onPointerEnter={e => !SnappingManager.GetIsDragging() && Doc.BrushDoc(this.props.Document)}
             onPointerLeave={e => !hasDescendantTarget(e.nativeEvent.x, e.nativeEvent.y, this.ContentDiv) && Doc.UnBrushDoc(this.props.Document)}
             style={{
-                display: "inline",
                 borderRadius: this.borderRounding,
                 pointerEvents: this.pointerEvents,
                 outline: highlighting && !this.borderRounding ? `${highlightColor} ${highlightStyle} ${highlightIndex}px` : "solid 0px",
@@ -1244,6 +1243,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
             const deiconifyLayout = Cast(this.Document.deiconifyLayout, "string", null);
             this.switchViews(deiconifyLayout ? true : false, deiconifyLayout);
             this.Document.deiconifyLayout = undefined;
+            this.props.bringToFront(this.rootDoc);
         }
     }
     @undoBatch
diff --git a/src/client/views/nodes/LabelBigText.js b/src/client/views/nodes/LabelBigText.js
index 78fe2839e..02c36c4bc 100644
--- a/src/client/views/nodes/LabelBigText.js
+++ b/src/client/views/nodes/LabelBigText.js
@@ -156,6 +156,7 @@ export default function BigText(element, options) {
         width: element.offsetWidth, //Note: This is slightly larger than the jQuery version
         height: element.offsetHeight,
     };
+    if (!box.width || !box.height) return element;
 
 
     if (options.rotateText !== null) {
diff --git a/src/client/views/nodes/LabelBox.scss b/src/client/views/nodes/LabelBox.scss
index 6a0d651d2..42e158584 100644
--- a/src/client/views/nodes/LabelBox.scss
+++ b/src/client/views/nodes/LabelBox.scss
@@ -4,7 +4,7 @@
     border-radius: inherit;
     display: flex;
     flex-direction: column;
-    position: absolute;
+    position: relative;
 }
 
 .labelBox-mainButton {
diff --git a/src/client/views/nodes/LabelBox.tsx b/src/client/views/nodes/LabelBox.tsx
index c689d9f40..3405a7635 100644
--- a/src/client/views/nodes/LabelBox.tsx
+++ b/src/client/views/nodes/LabelBox.tsx
@@ -30,6 +30,11 @@ export class LabelBox extends ViewBoxBaseComponent<(FieldViewProps & LabelBoxPro
 
     componentDidMount() {
         this.props.setContentView?.(this);
+        console.log("MOUNTING")
+    }
+
+    componentDidUpdate() {
+        console.log("UPDATING")
     }
 
     getTitle() {
@@ -73,6 +78,19 @@ export class LabelBox extends ViewBoxBaseComponent<(FieldViewProps & LabelBoxPro
     @observable _mouseOver = false;
     @computed get hoverColor() { return this._mouseOver ? StrCast(this.layoutDoc._hoverBackgroundColor) : "unset"; }
 
+    fitTextToBox = (r: any) => {
+        BigText(r, {
+            rotateText: null,
+            fontSizeFactor: 1,
+            minimumFontSize: NumCast(this.layoutDoc._minFontSize),
+            maximumFontSize: NumCast(this.layoutDoc._maxFontSize),
+            limitingDimension: "both",
+            horizontalAlign: "center",
+            verticalAlign: "center",
+            textAlign: "center",
+            whiteSpace: "nowrap"
+        })
+    }
     // (!missingParams || !missingParams.length ? "" : "(" + missingParams.map(m => m + ":").join(" ") + ")")
     render() {
         const params = Cast(this.paramsDoc["onClick-paramFieldKeys"], listSpec("string"), []);
@@ -97,17 +115,8 @@ export class LabelBox extends ViewBoxBaseComponent<(FieldViewProps & LabelBoxPro
                 }} >
                     <span ref={r => {
                         if (r) {
-                            BigText(r, {
-                                rotateText: null,
-                                fontSizeFactor: 1,
-                                minimumFontSize: NumCast(this.layoutDoc._minFontSize),
-                                maximumFontSize: NumCast(this.layoutDoc._maxFontSize),
-                                limitingDimension: "both",
-                                horizontalAlign: "center",
-                                verticalAlign: "center",
-                                textAlign: "center",
-                                whiteSpace: "nowrap"
-                            });
+                            if (!r.offsetWidth || !r.offsetHeight) setTimeout(() => this.fitTextToBox(r));
+                            else this.fitTextToBox(r);
                         }
                     }}>{label.startsWith("#") ? (null) : label}</span>
                 </div>
-- 
cgit v1.2.3-70-g09d2


From 0f8b556ac88632d31db4218bcea2e7a559deb6e4 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Mon, 11 Apr 2022 20:11:42 -0400
Subject: fixed sendtoback menu and functionality.  fixed mixedblendmode for
 groups.  fixed orange highlighting when docs are toggled hidden.   fixed
 placement of linking button.

---
 src/client/util/DocumentManager.ts                        |  5 ++++-
 src/client/views/StyleProvider.tsx                        | 11 ++++++-----
 src/client/views/nodes/CollectionFreeFormDocumentView.tsx | 10 ++++------
 src/client/views/nodes/DocumentLinksButton.tsx            |  2 +-
 src/client/views/nodes/DocumentView.tsx                   |  4 ++--
 5 files changed, 17 insertions(+), 15 deletions(-)

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

diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index ad6d90bc3..6076de055 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -169,7 +169,10 @@ export class DocumentManager {
         const getFirstDocView = LightboxView.LightboxDoc ? DocumentManager.Instance.getLightboxDocumentView : DocumentManager.Instance.getFirstDocumentView;
         const docView = getFirstDocView(targetDoc, originatingDoc);
         const wasHidden = targetDoc.hidden;  // 
-        if (wasHidden) runInAction(() => targetDoc.hidden = false);  // if the target is hidden, un-hide it here.
+        if (wasHidden) runInAction(() => {
+            targetDoc.hidden = false;
+            docView?.props.bringToFront(targetDoc);
+        });  // if the target is hidden, un-hide it here.
         const focusAndFinish = (didFocus: boolean) => {
             if (originatingDoc?.isPushpin) {
                 if (!didFocus && !wasHidden) {  // don't toggle the hidden state if the doc was already un-hidden as part of this document traversal
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index eb6551fc8..37ef96782 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -143,13 +143,14 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
                 case DocumentType.COL:
                     if (StrCast(Doc.LayoutField(doc)).includes(SliderBox.name)) break;
                     docColor = docColor ||
-                        (doc?._isGroup ? "#00000010" : // very faint highlight to show bounds of group
-                            (doc?._viewType === CollectionViewType.Pile || Doc.IsSystem(doc) ? (darkScheme() ? Colors.DARK_GRAY : Colors.LIGHT_GRAY) : // system docs (seen in treeView) get a grayish background
-                                isBackground() ? "cyan" : // ?? is there a good default for a background collection
-                                    doc.annotationOn ? "#00000015" : // faint interior for collections on PDFs, images, etc
+                        (doc?._viewType === CollectionViewType.Pile || Doc.IsSystem(doc) ? (darkScheme() ? Colors.DARK_GRAY : Colors.LIGHT_GRAY) : // system docs (seen in treeView) get a grayish background
+                            isBackground() ? "cyan" : // ?? is there a good default for a background collection
+                                doc.annotationOn ? "#00000015" : // faint interior for collections on PDFs, images, etc
+                                    (doc?._isGroup ? undefined : // groups get a faint background color in CollectionfreeformDocumentView
                                         StrCast((props?.renderDepth || 0) > 0 ?
                                             Doc.UserDoc().activeCollectionNestedBackground :
-                                            Doc.UserDoc().activeCollectionBackground ?? (darkScheme() ? Colors.BLACK : Colors.WHITE))));
+                                            Doc.UserDoc().activeCollectionBackground ?? (darkScheme() ? Colors.BLACK : Colors.WHITE))
+                                    ));
                     break;
                 //if (doc._viewType !== CollectionViewType.Freeform && doc._viewType !== CollectionViewType.Time) return "rgb(62,62,62)";
                 default: docColor = docColor || (darkScheme() ? Colors.DARK_GRAY : Colors.WHITE); break;
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index ba34d846e..277d6dc53 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -166,11 +166,9 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
             PanelWidth: this.panelWidth,
             PanelHeight: this.panelHeight,
         };
-        const background = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
-        const mixBlendMode = "";//StrCast(this.layoutDoc.mixBlendMode) as any || (typeof background === "string" && DashColor(background).alpha() !== 1 ? "multiply" : undefined);
-        if (mixBlendMode) {
-            console.log(mixBlendMode);
-        }
+        var background = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
+        const mixBlendMode = StrCast(this.layoutDoc.mixBlendMode) as any || (typeof background === "string" && DashColor(background).alpha() !== 1 ? "multiply" : undefined);
+        if (!background && this.rootDoc.isGroup) background = "#00000004";
         return <div className={"collectionFreeFormDocumentView-container"}
             style={{
                 outline: this.Highlight ? "orange solid 2px" : "",
@@ -179,7 +177,7 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
                 transform: this.transform,
                 transition: this.props.dataTransition ? this.props.dataTransition : this.dataProvider ? this.dataProvider.transition : StrCast(this.layoutDoc.dataTransition),
                 zIndex: this.ZInd,
-                mixBlendMode,
+                mixBlendMode: mixBlendMode,
                 display: this.ZInd === -99 ? "none" : undefined
             }} >
             {this.props.renderCutoffProvider(this.props.Document) ?
diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx
index 6d96a9ab6..46537df7e 100644
--- a/src/client/views/nodes/DocumentLinksButton.tsx
+++ b/src/client/views/nodes/DocumentLinksButton.tsx
@@ -278,7 +278,7 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
 
         //render circular tooltip if it isn't set to invisible and show the number of doc links the node has, and render inner-menu link button for starting/stopping links if currently in menu
         return (!Array.from(this.filteredLinks).length && !this.props.AlwaysOn) ? (null) :
-            <div className="documentLinksButton-wrapper" >
+            <div className="documentLinksButton-wrapper" style={{ transform: this.props.InMenu ? undefined : `scale(${(this.props.ContentScaling?.() || 1) * this.props.View.screenToLocalTransform().Scale})` }} >
                 {
                     (this.props.InMenu && (DocumentLinksButton.StartLink || this.props.StartLink)) ||
                         (!DocumentLinksButton.LinkEditorDocView && !this.props.InMenu) ?
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 423a5edbf..9ec7b9a58 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -752,7 +752,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
                     zorderItems.push({ description: "Send to Back", event: () => SelectionManager.Views().forEach(dv => dv.props.bringToFront(dv.rootDoc, true)), icon: "expand-arrows-alt" });
                     zorderItems.push({ description: this.rootDoc._raiseWhenDragged !== false ? "Keep ZIndex when dragged" : "Allow ZIndex to change when dragged", event: undoBatch(action(() => this.rootDoc._raiseWhenDragged = this.rootDoc._raiseWhenDragged === undefined ? false : undefined)), icon: "expand-arrows-alt" });
                 }
-                !zorders && cm.addItem({ description: "ZOrder...", subitems: zorderItems, icon: "compass" });
+                !zorders && cm.addItem({ description: "ZOrder...", noexpand: true, subitems: zorderItems, icon: "compass" });
 
                 !Doc.UserDoc().noviceMode && onClicks.push({ description: "Enter Portal", event: this.makeIntoPortal, icon: "window-restore" });
                 !Doc.UserDoc().noviceMode && onClicks.push({ description: "Toggle Detail", event: this.setToggleDetail, icon: "concierge-bell" });
@@ -1119,6 +1119,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
             onPointerEnter={e => !SnappingManager.GetIsDragging() && Doc.BrushDoc(this.props.Document)}
             onPointerLeave={e => !hasDescendantTarget(e.nativeEvent.x, e.nativeEvent.y, this.ContentDiv) && Doc.UnBrushDoc(this.props.Document)}
             style={{
+                display: this.hidden ? "inline" : undefined,
                 borderRadius: this.borderRounding,
                 pointerEvents: this.pointerEvents,
                 outline: highlighting && !this.borderRounding ? `${highlightColor} ${highlightStyle} ${highlightIndex}px` : "solid 0px",
@@ -1322,7 +1323,6 @@ export class DocumentView extends React.Component<DocumentViewProps> {
                         ContentScaling={this.ContentScale}
                         ScreenToLocalTransform={this.screenToLocalTransform}
                         focus={this.props.focus || emptyFunction}
-                        bringToFront={emptyFunction}
                         ref={action((r: DocumentViewInternal | null) => r && (this.docView = r))} />
                 </div>)}
         </div>);
-- 
cgit v1.2.3-70-g09d2


From 7cd890392f79f1783af2bdb0fe86fa6a49db849a Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Mon, 11 Apr 2022 23:17:07 -0400
Subject: fixes to header to be transparent for icons.  layout fixes for doc
 decoratoins title row.  groups are not semi transnparent anymore to avoid
 mixBlendMode confusion

---
 src/client/util/CurrentUserUtils.ts                       | 13 +++++--------
 src/client/views/DocumentDecorations.scss                 |  9 +++++----
 src/client/views/DocumentDecorations.tsx                  |  3 +--
 src/client/views/StyleProvider.tsx                        |  2 +-
 src/client/views/nodes/CollectionFreeFormDocumentView.tsx |  5 +++--
 src/client/views/nodes/DocumentView.tsx                   |  6 ++++--
 6 files changed, 19 insertions(+), 19 deletions(-)

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

diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 0e392cc85..bf722157a 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -303,7 +303,7 @@ export class CurrentUserUtils {
         }
         if (doc["template-icon-view-rtf"] === undefined) {
             const iconRtfView = Docs.Create.LabelDocument({
-                title: "icon_" + DocumentType.RTF, textTransform: "unset", letterSpacing: "unset", layout: LabelBox.LayoutString("text"),
+                title: "icon_" + DocumentType.RTF, _showTitle: "creationDate", textTransform: "unset", letterSpacing: "unset", layout: LabelBox.LayoutString("text"),
                 _singleLine: false, _minFontSize: 18, _maxFontSize: 24,
                 _width: 150, _height: 70, _xPadding: 10, _yPadding: 10, isTemplateDoc: true, onClick: ScriptField.MakeScript("deiconifyView(documentView)", { documentView: "any" }), system: true
             });
@@ -320,13 +320,13 @@ export class CurrentUserUtils {
         }
         if (doc["template-icon-view-img"] === undefined) {
             const iconImageView = Docs.Create.ImageDocument("http://www.cs.brown.edu/~bcz/face.gif", {
-                title: "data", _width: 150, isTemplateDoc: true, onClick: ScriptField.MakeScript("deiconifyView(documentView)", { documentView: "any" }), system: true
+                title: "data", _width: 150, isTemplateDoc: true, _showTitle: "title", onClick: ScriptField.MakeScript("deiconifyView(documentView)", { documentView: "any" }), system: true
             });
             iconImageView.isTemplateDoc = makeTemplate(iconImageView, true, "icon_" + DocumentType.IMG);
             doc["template-icon-view-img"] = new PrefetchProxy(iconImageView);
         }
         if (doc["template-icon-view-col"] === undefined) {
-            const iconColView = Docs.Create.ImageDocument("", { title: "icon", _width: 360 / 4, _height: 270 / 4, onClick: ScriptField.MakeScript("deiconifyView(documentView)", { documentView: "any" }), system: true });
+            const iconColView = Docs.Create.ImageDocument("", { title: "icon", _showTitle: "title", _width: 360 / 4, _height: 270 / 4, onClick: ScriptField.MakeScript("deiconifyView(documentView)", { documentView: "any" }), system: true });
             iconColView.isTemplateDoc = makeTemplate(iconColView, true, "icon_" + DocumentType.COL);
             const proto = iconColView.proto as Doc;
             proto["icon-nativeWidth"] = 360 / 4;
@@ -335,7 +335,7 @@ export class CurrentUserUtils {
             doc["template-icon-view-col"] = new PrefetchProxy(iconColView);
         }
         if (doc["template-icon-view-video"] === undefined) {
-            const iconVidView = Docs.Create.ImageDocument("", { title: "icon", _width: 360 / 4, _height: 270 / 4, onClick: ScriptField.MakeScript("deiconifyView(documentView)", { documentView: "any" }), system: true });
+            const iconVidView = Docs.Create.ImageDocument("", { title: "icon", _width: 360 / 4, _height: 270 / 4, _showTitle: "title", onClick: ScriptField.MakeScript("deiconifyView(documentView)", { documentView: "any" }), system: true });
             iconVidView.isTemplateDoc = makeTemplate(iconVidView, true, "icon_" + DocumentType.VID);
             const proto = iconVidView.proto as Doc;
             proto["icon-nativeWidth"] = 360 / 4;
@@ -344,7 +344,7 @@ export class CurrentUserUtils {
             doc["template-icon-view-video"] = new PrefetchProxy(iconVidView);
         }
         if (doc["template-icon-view-pdf"] === undefined) {
-            const iconPdfView = Docs.Create.ImageDocument("", { title: "icon", _width: 360 / 4, _height: 270 / 4, onClick: ScriptField.MakeScript("deiconifyView(documentView)", { documentView: "any" }), system: true });
+            const iconPdfView = Docs.Create.ImageDocument("", { title: "icon", _width: 360 / 4, _height: 270 / 4, _showTitle: "title", onClick: ScriptField.MakeScript("deiconifyView(documentView)", { documentView: "any" }), system: true });
             iconPdfView.isTemplateDoc = makeTemplate(iconPdfView, true, "icon_" + DocumentType.PDF);
             const proto = iconPdfView.proto as Doc;
             proto["icon-nativeWidth"] = 360 / 4;
@@ -1344,9 +1344,6 @@ export class CurrentUserUtils {
             // undefined means ColorScheme.Light until all CSS is updated with values for each color scheme (e.g., see MainView.scss, DocumentDecorations.scss)
             doc.activeDashboard.colorScheme = doc.activeDashboard.colorScheme === ColorScheme.Light ? undefined : doc.activeDashboard.colorScheme;
         }
-        if (doc.activeCollectionBackground === "white") { // temporary to avoid having to rebuild the databse for old accounts that have this set by default.
-            doc.activeCollectionBackground = undefined;
-        }
         return doc;
     }
 
diff --git a/src/client/views/DocumentDecorations.scss b/src/client/views/DocumentDecorations.scss
index 7432d45bf..481b90249 100644
--- a/src/client/views/DocumentDecorations.scss
+++ b/src/client/views/DocumentDecorations.scss
@@ -230,15 +230,15 @@ $linkGap: 3px;
 .documentDecorations-title-Dark,
 .documentDecorations-title {
         opacity: 1;
-        width: 100%;
+        width: calc(100% - 8px); // = margin-left + margin-right
         grid-column: 2;
         grid-column-end: 2;
         pointer-events: auto;
         overflow: hidden;
         text-align: center;
         display: flex;
-        padding-left: 2px;
-        padding-right: 2px;
+        margin-left: 6px; // closeButton width (14) - leftColumn width (8)
+        margin-right: 2px;
         height: 20px;
         position: absolute;
         border-radius: 8px;
@@ -246,7 +246,7 @@ $linkGap: 3px;
 
         .documentDecorations-titleSpan, 
         .documentDecorations-titleSpan-Dark  {
-            width: calc(100% - 17px); // = padding-left + padding-right
+            width: 100% ;
             border-radius: 8px;
             background: #ffffffa0;
             position: absolute;
@@ -290,6 +290,7 @@ $linkGap: 3px;
     opacity: 1;
     grid-column: 1;
     pointer-events: all;
+    width: 14px;
     cursor: pointer;
 
     > svg {
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 353843b8d..9d9505c08 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -469,13 +469,12 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number, P
         const titleArea = hideTitle ? <div className="documentDecorations-title" onPointerDown={this.onTitleDown} key="title" /> :
             this._edtingTitle ?
                 <input ref={this._keyinput} className={`documentDecorations-title${colorScheme}`}
-                    style={{ width: `100%` }}
                     type="text" name="dynbox" autoComplete="on"
                     value={this._accumulatedTitle}
                     onBlur={e => this.titleBlur()}
                     onChange={action(e => this._accumulatedTitle = e.target.value)}
                     onKeyPress={this.titleEntered} /> :
-                <div className="documentDecorations-title" style={{ width: `100%` }} key="title" onPointerDown={this.onTitleDown} >
+                <div className="documentDecorations-title" key="title" onPointerDown={this.onTitleDown} >
                     <span className={`documentDecorations-titleSpan${colorScheme}`}>{`${this.selectionTitle}`}</span>
                 </div>;
 
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index 37ef96782..2ce78f64f 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -146,7 +146,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
                         (doc?._viewType === CollectionViewType.Pile || Doc.IsSystem(doc) ? (darkScheme() ? Colors.DARK_GRAY : Colors.LIGHT_GRAY) : // system docs (seen in treeView) get a grayish background
                             isBackground() ? "cyan" : // ?? is there a good default for a background collection
                                 doc.annotationOn ? "#00000015" : // faint interior for collections on PDFs, images, etc
-                                    (doc?._isGroup ? undefined : // groups get a faint background color in CollectionfreeformDocumentView
+                                    (doc?._isGroup ? undefined :
                                         StrCast((props?.renderDepth || 0) > 0 ?
                                             Doc.UserDoc().activeCollectionNestedBackground :
                                             Doc.UserDoc().activeCollectionBackground ?? (darkScheme() ? Colors.BLACK : Colors.WHITE))
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index 277d6dc53..7fb2c235a 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -18,6 +18,8 @@ import "./CollectionFreeFormDocumentView.scss";
 import { DocumentView, DocumentViewProps } from "./DocumentView";
 import React = require("react");
 import { DocumentType } from "../../documents/DocumentTypes";
+import { collectionSchema } from "../../../fields/documentSchemas";
+import { CollectionViewType } from "../collections/CollectionView";
 
 export interface CollectionFreeFormDocumentViewProps extends DocumentViewProps {
     dataProvider?: (doc: Doc, replica: string) => { x: number, y: number, zIndex?: number, opacity?: number, highlight?: boolean, z: number, transition?: string } | undefined;
@@ -167,8 +169,7 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
             PanelHeight: this.panelHeight,
         };
         var background = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
-        const mixBlendMode = StrCast(this.layoutDoc.mixBlendMode) as any || (typeof background === "string" && DashColor(background).alpha() !== 1 ? "multiply" : undefined);
-        if (!background && this.rootDoc.isGroup) background = "#00000004";
+        const mixBlendMode = StrCast(this.layoutDoc.mixBlendMode) as any || (typeof background === "string" && background && DashColor(background).alpha() !== 1 ? "multiply" : undefined);
         return <div className={"collectionFreeFormDocumentView-container"}
             style={{
                 outline: this.Highlight ? "orange solid 2px" : "",
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 9ec7b9a58..195f6c9e5 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -859,9 +859,10 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
                     style={{ color: [DocListCast(this.dataDoc[this.LayoutFieldKey + "-audioAnnotations"]).length ? "blue" : "gray", "green", "red"][this._mediaState] }}
                     icon={!DocListCast(this.dataDoc[this.LayoutFieldKey + "-audioAnnotations"]).length ? "microphone" : "file-audio"} size="sm" />
             </div>;
+
         return <div className="documentView-contentsView"
             style={{
-                pointerEvents: this.props.pointerEvents as any ? this.props.pointerEvents as any : (this.rootDoc.type !== DocumentType.INK && ((this.props.contentPointerEvents as any) || (this.isContentActive())) ? "all" : "none"),
+                pointerEvents: this.props.pointerEvents as any ?? this.rootDoc.layoutKey === "layout_icon" ? "none" : (this.rootDoc.type !== DocumentType.INK && ((this.props.contentPointerEvents as any) || (this.isContentActive())) ? "all" : "none"),
                 height: this.headerMargin ? `calc(100% - ${this.headerMargin}px)` : undefined,
             }}>
             {!this._retryThumb || !this.thumbShown() ? (null) :
@@ -1030,7 +1031,8 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
                 />
             </div>;
         const targetDoc = (showTitle?.startsWith("_") ? this.layoutDoc : this.rootDoc);
-        const background = StrCast(SharingManager.Instance.users.find(users => users.user.email === this.dataDoc.author)?.sharingDoc.userColor, [DocumentType.RTF, DocumentType.COL].includes(this.rootDoc.type as any) ? StrCast(Doc.SharingDoc().userColor) : "rgba(0,0,0,0.4)");
+        const background = StrCast(SharingManager.Instance.users.find(users => users.user.email === this.dataDoc.author)?.sharingDoc.userColor,
+            Doc.UserDoc().showTitle && [DocumentType.RTF, DocumentType.COL].includes(this.rootDoc.type as any) ? StrCast(Doc.SharingDoc().userColor) : "rgba(0,0,0,0.4)");
         const titleView = !showTitle ? (null) :
             <div className={`documentView-titleWrapper${showTitleHover ? "-hover" : ""}`} key="title" style={{
                 position: this.headerMargin ? "relative" : "absolute",
-- 
cgit v1.2.3-70-g09d2


From fd58a5f8598815ab1ab3893e60973654a59a52c1 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Tue, 12 Apr 2022 10:54:28 -0400
Subject: cleaned up errors/warnings.   fixed dragging to turn off pointer
 events on whatever's being dragged.

---
 src/client/util/DocumentManager.ts                             | 10 ++++++----
 src/client/util/DragManager.ts                                 |  2 +-
 src/client/views/StyleProvider.tsx                             |  4 +++-
 src/client/views/collections/CollectionDockingView.tsx         |  4 ++--
 .../collections/collectionFreeForm/CollectionFreeFormView.tsx  |  2 +-
 src/client/views/nodes/CollectionFreeFormDocumentView.tsx      |  4 ++--
 src/client/views/nodes/LabelBox.tsx                            |  7 +------
 src/client/views/nodes/PDFBox.tsx                              |  6 +++---
 src/client/views/nodes/VideoBox.tsx                            |  2 +-
 src/client/views/nodes/formattedText/FormattedTextBox.tsx      |  2 +-
 10 files changed, 21 insertions(+), 22 deletions(-)

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

diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index 6076de055..1d603e18f 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -169,10 +169,12 @@ export class DocumentManager {
         const getFirstDocView = LightboxView.LightboxDoc ? DocumentManager.Instance.getLightboxDocumentView : DocumentManager.Instance.getFirstDocumentView;
         const docView = getFirstDocView(targetDoc, originatingDoc);
         const wasHidden = targetDoc.hidden;  // 
-        if (wasHidden) runInAction(() => {
-            targetDoc.hidden = false;
-            docView?.props.bringToFront(targetDoc);
-        });  // if the target is hidden, un-hide it here.
+        if (wasHidden) {
+            runInAction(() => {
+                targetDoc.hidden = false;
+                docView?.props.bringToFront(targetDoc);
+            });  // if the target is hidden, un-hide it here.
+        }
         const focusAndFinish = (didFocus: boolean) => {
             if (originatingDoc?.isPushpin) {
                 if (!didFocus && !wasHidden) {  // don't toggle the hidden state if the doc was already un-hidden as part of this document traversal
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 94a09eac4..13e5940d6 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -405,7 +405,7 @@ export namespace DragManager {
                 Array.from(pdfBox).filter(pb => pb.width && pb.height).map((pb, i) => pb.getContext('2d')!.drawImage(pdfBoxSrc[i], 0, 0));
             }
             [dragElement, ...Array.from(dragElement.getElementsByTagName('*'))].forEach(ele =>
-                ele.hasAttribute("style") && ((ele as any).style.pointerEvents = "none"));
+                (ele as any).style && ((ele as any).style.pointerEvents = "none"));
 
             dragDiv.appendChild(dragElement);
             if (dragElement !== ele) {
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index 2ce78f64f..9803f9782 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -149,7 +149,9 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
                                     (doc?._isGroup ? undefined :
                                         StrCast((props?.renderDepth || 0) > 0 ?
                                             Doc.UserDoc().activeCollectionNestedBackground :
-                                            Doc.UserDoc().activeCollectionBackground ?? (darkScheme() ? Colors.BLACK : Colors.WHITE))
+                                            Doc.UserDoc().activeCollectionBackground ?? (darkScheme() ?
+                                                Colors.BLACK :
+                                                "linear-gradient(#065fff, #85c1f9)"))
                                     ));
                     break;
                 //if (doc._viewType !== CollectionViewType.Freeform && doc._viewType !== CollectionViewType.Time) return "rgb(62,62,62)";
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 6931d9896..e95371aaa 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -92,7 +92,7 @@ export class CollectionDockingView extends CollectionSubView() {
                 DragManager.CompleteWindowDrag = undefined;
             }
             finishDrag?.(aborted);
-        }
+        };
     }
     @undoBatch
     public CloseFullScreen = () => {
@@ -316,7 +316,7 @@ export class CollectionDockingView extends CollectionSubView() {
             }
             this._goldenLayout.init();
             this._goldenLayout.root.layoutManager.on('itemDropped', this.tabItemDropped);
-            this._goldenLayout.root.layoutManager.on('dragStart', this.tabDragStart)
+            this._goldenLayout.root.layoutManager.on('dragStart', this.tabDragStart);
             this._goldenLayout.root.layoutManager.on('activeContentItemChanged', this.stateChanged);
         }
     }
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 04beed541..9b0acffdf 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1417,7 +1417,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
     updateIcon = () => {
         this.props.docViewPath().lastElement().ContentDiv!.style.width = (this.layoutDoc[WidthSym]()).toString();
         this.props.docViewPath().lastElement().ContentDiv!.style.height = (this.layoutDoc[HeightSym]()).toString();
-        var htmlString = this._mainCont && new XMLSerializer().serializeToString(this.props.docViewPath().lastElement().ContentDiv!);
+        const htmlString = this._mainCont && new XMLSerializer().serializeToString(this.props.docViewPath().lastElement().ContentDiv!);
         this.props.docViewPath().lastElement().ContentDiv!.style.width = "";
         this.props.docViewPath().lastElement().ContentDiv!.style.height = "";
         const nativeWidth = this.layoutDoc[WidthSym]();
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index 7fb2c235a..3e35039e3 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -168,8 +168,8 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
             PanelWidth: this.panelWidth,
             PanelHeight: this.panelHeight,
         };
-        var background = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
-        const mixBlendMode = StrCast(this.layoutDoc.mixBlendMode) as any || (typeof background === "string" && background && DashColor(background).alpha() !== 1 ? "multiply" : undefined);
+        const background = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
+        const mixBlendMode = StrCast(this.layoutDoc.mixBlendMode) as any || (typeof background === "string" && background && (!background.startsWith("linear") && DashColor(background).alpha() !== 1) ? "multiply" : undefined);
         return <div className={"collectionFreeFormDocumentView-container"}
             style={{
                 outline: this.Highlight ? "orange solid 2px" : "",
diff --git a/src/client/views/nodes/LabelBox.tsx b/src/client/views/nodes/LabelBox.tsx
index 3405a7635..d539ca9b8 100644
--- a/src/client/views/nodes/LabelBox.tsx
+++ b/src/client/views/nodes/LabelBox.tsx
@@ -30,11 +30,6 @@ export class LabelBox extends ViewBoxBaseComponent<(FieldViewProps & LabelBoxPro
 
     componentDidMount() {
         this.props.setContentView?.(this);
-        console.log("MOUNTING")
-    }
-
-    componentDidUpdate() {
-        console.log("UPDATING")
     }
 
     getTitle() {
@@ -89,7 +84,7 @@ export class LabelBox extends ViewBoxBaseComponent<(FieldViewProps & LabelBoxPro
             verticalAlign: "center",
             textAlign: "center",
             whiteSpace: "nowrap"
-        })
+        });
     }
     // (!missingParams || !missingParams.length ? "" : "(" + missingParams.map(m => m + ":").join(" ") + ")")
     render() {
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index 3f1771e68..c73823a2b 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -63,7 +63,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
         }
         if (oldDiv instanceof HTMLCanvasElement) {
             const canvas = oldDiv as HTMLCanvasElement;
-            var img = document.createElement('img'); // create a Image Element
+            const img = document.createElement('img'); // create a Image Element
             img.src = canvas.toDataURL();   //image source
             img.style.width = canvas.style.width;
             img.style.height = canvas.style.height;
@@ -79,8 +79,8 @@ export class PDFBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
         const newDiv = docViewContent.cloneNode(true) as HTMLDivElement;
         newDiv.style.width = (this.layoutDoc[WidthSym]()).toString();
         newDiv.style.height = (this.layoutDoc[HeightSym]()).toString();
-        this.replaceCanvases(docViewContent, newDiv)
-        var htmlString = this._pdfViewer?._mainCont.current && new XMLSerializer().serializeToString(newDiv);
+        this.replaceCanvases(docViewContent, newDiv);
+        const htmlString = this._pdfViewer?._mainCont.current && new XMLSerializer().serializeToString(newDiv);
         const nativeWidth = this.layoutDoc[WidthSym]();
         const nativeHeight = this.layoutDoc[HeightSym]();
 
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index b7b8ce064..c31d38b0d 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -265,7 +265,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
             this.dataDoc.icon = new ImageField(returnedfilename);
             this.dataDoc["icon-nativeWidth"] = this.layoutDoc[WidthSym]();
             this.dataDoc["icon-nativeHeight"] = this.layoutDoc[HeightSym]();
-        }
+        };
         this.Snapshot(undefined, undefined, makeIcon);
     }
 
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index ec88b8d1d..b6713d878 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -364,7 +364,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
     }
 
     updateTitle = () => {
-        const title = StrCast(this.dataDoc.title)
+        const title = StrCast(this.dataDoc.title);
         if (!this.props.dontRegisterView &&  // (this.props.Document.isTemplateForField === "text" || !this.props.Document.isTemplateForField) && // only update the title if the data document's data field is changing
             (title.startsWith("-") || title.startsWith("@")) && this._editorView && !this.dataDoc["title-custom"] &&
             (Doc.LayoutFieldKey(this.rootDoc) === this.fieldKey || this.fieldKey === "text")) {
-- 
cgit v1.2.3-70-g09d2


From 594f585b74bf6ecec3795a4b780da619c66f341d Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Wed, 13 Apr 2022 10:57:08 -0400
Subject: added images to treeView bullets for docs with icons.  fixed
 following pushpin links to prototypes to  toggle delegates when shown.  gave
 groups a default padding.  fixed creating icons to not create unnecessary
 template docs.  fixed toggling isPushpin. made summaries simple links instead
 of templates.

---
 src/client/documents/Documents.ts                  | 38 ++++++++++++----------
 src/client/util/DocumentManager.ts                 |  5 +--
 src/client/views/DocumentDecorations.tsx           |  5 ++-
 src/client/views/StyleProvider.tsx                 | 13 ++++++--
 src/client/views/collections/TreeView.scss         |  2 +-
 src/client/views/collections/TreeView.tsx          |  5 +--
 .../collections/collectionFreeForm/MarqueeView.tsx |  9 ++---
 src/client/views/nodes/DocumentView.tsx            |  8 +++--
 src/client/views/nodes/LinkDocPreview.tsx          |  9 ++++-
 9 files changed, 59 insertions(+), 35 deletions(-)

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

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 652f8e7e0..465cdf3ec 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -223,6 +223,7 @@ export class DocumentOptions {
     dockingConfig?: string;
     annotationOn?: Doc;
     isPushpin?: boolean;
+    isGroup?: boolean; // whether a collection should use a grouping UI behavior
     _removeDropProperties?: List<string>; // list of properties that should be removed from a document when it is dropped.  e.g., a creator button may be forceActive to allow it be dragged, but the forceActive property can be removed from the dropped document
 
     // BACKGROUND GRID
@@ -807,7 +808,7 @@ export namespace Docs {
         }
 
         export function FreeformDocument(documents: Array<Doc>, options: DocumentOptions, id?: string) {
-            const inst = InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { ...options, _viewType: CollectionViewType.Freeform }, id);
+            const inst = InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _xPadding: 20, _yPadding: 20, ...options, _viewType: CollectionViewType.Freeform }, id);
             documents.map(d => d.context = inst);
             return inst;
         }
@@ -1317,22 +1318,25 @@ export namespace DocUtils {
         const _height = NumCast(doc._height);
         const options = { title: "data", backgroundColor: StrCast(doc.backgroundColor), _autoHeight: true, _width, x: -_width / 2, y: - _height / 2, _showSidebar: false };
 
-        let fieldTemplate: Opt<Doc>;
-        if (doc.data instanceof RichTextField || typeof (doc.data) === "string") {
-            fieldTemplate = Docs.Create.TextDocument("", options);
-        } else if (doc.data instanceof PdfField) {
-            fieldTemplate = Docs.Create.PdfDocument("http://www.msn.com", options);
-        } else if (doc.data instanceof VideoField) {
-            fieldTemplate = Docs.Create.VideoDocument("http://www.cs.brown.edu", options);
-        } else if (doc.data instanceof AudioField) {
-            fieldTemplate = Docs.Create.AudioDocument("http://www.cs.brown.edu", options);
-        } else if (doc.data instanceof ImageField) {
-            fieldTemplate = Docs.Create.ImageDocument("http://www.cs.brown.edu", options);
-        }
-        const docTemplate = docLayoutTemplate || creator?.(fieldTemplate ? [fieldTemplate] : [], { title: customName + "(" + doc.title + ")", isTemplateDoc: true, _width: _width + 20, _height: Math.max(100, _height + 45) });
-
-        fieldTemplate && Doc.MakeMetadataFieldTemplate(fieldTemplate, docTemplate ? Doc.GetProto(docTemplate) : docTemplate);
-        docTemplate && Doc.ApplyTemplateTo(docTemplate, doc, customName, undefined);
+        if (docLayoutTemplate) {
+            Doc.ApplyTemplateTo(docLayoutTemplate, doc, customName, undefined);
+        } else {
+            let fieldTemplate: Opt<Doc>;
+            if (doc.data instanceof RichTextField || typeof (doc.data) === "string") {
+                fieldTemplate = Docs.Create.TextDocument("", options);
+            } else if (doc.data instanceof PdfField) {
+                fieldTemplate = Docs.Create.PdfDocument("http://www.msn.com", options);
+            } else if (doc.data instanceof VideoField) {
+                fieldTemplate = Docs.Create.VideoDocument("http://www.cs.brown.edu", options);
+            } else if (doc.data instanceof AudioField) {
+                fieldTemplate = Docs.Create.AudioDocument("http://www.cs.brown.edu", options);
+            } else if (doc.data instanceof ImageField) {
+                fieldTemplate = Docs.Create.ImageDocument("http://www.cs.brown.edu", options);
+            }
+            const docTemplate = creator?.(fieldTemplate ? [fieldTemplate] : [], { title: customName + "(" + doc.title + ")", isTemplateDoc: true, _width: _width + 20, _height: Math.max(100, _height + 45) });
+            fieldTemplate && Doc.MakeMetadataFieldTemplate(fieldTemplate, docTemplate ? Doc.GetProto(docTemplate) : docTemplate);
+            docTemplate && Doc.ApplyTemplateTo(docTemplate, doc, customName, undefined);
+        }
     }
     export function makeCustomView(doc: Doc, custom: boolean, layout: string) {
         Doc.setNativeView(doc);
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index 1d603e18f..fb50ecb4a 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -176,12 +176,13 @@ export class DocumentManager {
             });  // if the target is hidden, un-hide it here.
         }
         const focusAndFinish = (didFocus: boolean) => {
+            const finalTargetDoc = docView?.Document ?? targetDoc;
             if (originatingDoc?.isPushpin) {
                 if (!didFocus && !wasHidden) {  // don't toggle the hidden state if the doc was already un-hidden as part of this document traversal
-                    targetDoc.hidden = !targetDoc.hidden;
+                    finalTargetDoc.hidden = !finalTargetDoc.hidden;
                 }
             } else {
-                targetDoc.hidden && (targetDoc.hidden = undefined);
+                finalTargetDoc.hidden && (finalTargetDoc.hidden = undefined);
                 !noSelect && docView?.select(false);
             }
             finished?.();
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 062ca1181..a8d91e0a2 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -453,6 +453,9 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number, P
             return (collectionAcl === AclAdmin || collectionAcl === AclEdit || GetEffectiveAcl(docView.rootDoc) === AclAdmin);
         });
     }
+    @computed get hasIcons() {
+        return SelectionManager.Views().some(docView => docView.rootDoc.layoutKey === "layout_icon");
+    }
 
     render() {
         const bounds = this.Bounds;
@@ -516,7 +519,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number, P
                     left: bounds.x - this._resizeBorderWidth / 2,
                     top: bounds.y - this._resizeBorderWidth / 2 - this._titleHeight,
                 }}>
-                    {!canDelete ? <div /> : topBtn("close", "times", undefined, this.onCloseClick, "Close")}
+                    {!canDelete ? <div /> : topBtn("close", this.hasIcons ? "times" : "window-maximize", undefined, this.onCloseClick, "Close")}
                     {titleArea}
                     {!canOpen ? (null) : topBtn("open", "external-link-alt", this.onMaximizeDown, undefined, "Open in Tab (ctrl: as alias, shift: in new collection)")}
                     {hideResizers ? (null) :
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index 9803f9782..dba290b46 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -3,10 +3,11 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import 'golden-layout/src/css/goldenlayout-base.css';
 import 'golden-layout/src/css/goldenlayout-dark-theme.css';
 import { action, runInAction } from 'mobx';
+import { extname } from 'path';
 import { Doc, Opt, StrListCast } from "../../fields/Doc";
 import { List } from '../../fields/List';
 import { listSpec } from '../../fields/Schema';
-import { BoolCast, Cast, NumCast, StrCast } from "../../fields/Types";
+import { BoolCast, Cast, ImageCast, NumCast, StrCast } from "../../fields/Types";
 import { DashColor, lightOrDark } from '../../Utils';
 import { DocumentType } from '../documents/DocumentTypes';
 import { CurrentUserUtils } from '../util/CurrentUserUtils';
@@ -88,7 +89,15 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
     const showTitle = () => props?.styleProvider?.(doc, props, StyleProp.ShowTitle);
     const random = (min: number, max: number, x: number, y: number) => /* min should not be equal to max */ min + ((Math.abs(x * y) * 9301 + 49297) % 233280 / 233280) * (max - min);
     switch (property.split(":")[0]) {
-        case StyleProp.TreeViewIcon: return Doc.toIcon(doc, isOpen);
+        case StyleProp.TreeViewIcon:
+            const icon = Cast(doc?.layout_icon, Doc, null) ? Doc.expandTemplateLayout(Cast(doc?.layout_icon, Doc, null), doc) : undefined;
+            if (icon && ImageCast(doc?.icon, ImageCast(doc?.data))) {
+                const img = ImageCast(doc?.icon, ImageCast(doc?.data));
+                const ext = extname(img.url.href);
+                const url = doc?.icon ? img.url.href : img.url.href.replace(ext, "_s" + ext);
+                return <img src={url} width={20} height={15} style={{ margin: "auto", display: "block", objectFit: "contain" }} />;
+            }
+            return Doc.toIcon(doc, isOpen);
         case StyleProp.DocContents: return undefined;
         case StyleProp.WidgetColor: return isAnnotated ? Colors.LIGHT_BLUE : darkScheme() ? "lightgrey" : "dimgrey";
         case StyleProp.Opacity: return Cast(doc?._opacity, "number", Cast(doc?.opacity, "number", null));
diff --git a/src/client/views/collections/TreeView.scss b/src/client/views/collections/TreeView.scss
index 2e33d3564..7c75810d3 100644
--- a/src/client/views/collections/TreeView.scss
+++ b/src/client/views/collections/TreeView.scss
@@ -47,7 +47,7 @@
         width: $TREE_BULLET_WIDTH;
         color: $medium-gray;
         margin-top: 3px;
-        transform: scale(1.3, 1.3);
+       // transform: scale(1.3, 1.3); // bcz: why was this here?  It makes displaying images in the treeView for documents that have icons harder.
         border: #80808030 1px solid;
         border-radius: 4px;
     }
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index ff5c4bab1..c2d0983da 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -31,6 +31,7 @@ import { CollectionTreeView } from './CollectionTreeView';
 import { CollectionView, CollectionViewType } from './CollectionView';
 import "./TreeView.scss";
 import React = require("react");
+import { IconProp } from '@fortawesome/fontawesome-svg-core';
 
 export interface TreeViewProps {
     treeView: CollectionTreeView;
@@ -471,7 +472,7 @@ export class TreeView extends React.Component<TreeViewProps> {
             onClick={this.bulletClick}
             style={this.props.treeView.outlineMode ? { opacity: this.titleStyleProvider?.(this.doc, this.props.treeView.props, StyleProp.Opacity) } : {
                 color: StrCast(this.doc.color, checked === "unchecked" ? "white" : "inherit"),
-                opacity: checked === "unchecked" ? undefined : 0.4
+                opacity: checked === "unchecked" || typeof iconType !== "string" ? undefined : 0.4
             }}>
             {this.props.treeView.outlineMode ?
                 !(this.doc.text as RichTextField)?.Text ? (null) :
@@ -484,7 +485,7 @@ export class TreeView extends React.Component<TreeViewProps> {
                                     checked === "unchecked" ? "square" :
                                         !this.treeViewOpen ? "caret-right" : "caret-down"} />
                     </div>
-                    {this.onCheckedClick ? (null) : <FontAwesomeIcon icon={iconType} />}
+                    {this.onCheckedClick ? (null) : typeof iconType === "string" ? <FontAwesomeIcon icon={iconType as IconProp} /> : iconType}
                 </div>
             }
         </div>;
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index b8f687489..5405ab500 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -519,13 +519,8 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
             d.y = NumCast(d.y) - this.Bounds.top;
             return d;
         });
-        const summary = Docs.Create.TextDocument("", { x: this.Bounds.left, y: this.Bounds.top, _width: 200, _height: 200, _fitToBox: true, _showSidebar: true, title: "overview" });
-        const portal = Doc.MakeAlias(summary);
-        Doc.GetProto(summary)[Doc.LayoutFieldKey(summary) + "-annotations"] = new List<Doc>(selected);
-        Doc.GetProto(summary).layout_portal = CollectionView.LayoutString(Doc.LayoutFieldKey(summary) + "-annotations");
-        summary._backgroundColor = "#e2ad32";
-        portal.layoutKey = "layout_portal";
-        portal.title = "document collection";
+        const summary = Docs.Create.TextDocument("", { _backgroundColor: "#e2ad32", x: this.Bounds.left, y: this.Bounds.top, _width: 200, _height: 200, _fitToBox: true, _showSidebar: true, title: "overview" });
+        const portal = Docs.Create.FreeformDocument(selected, { isGroup: true, backgroundColor: "transparent" });
         DocUtils.MakeLink({ doc: summary }, { doc: portal }, "summarizing", "");
 
         this.props.addLiveTextDocument(summary);
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 195f6c9e5..8bf9348c7 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -594,8 +594,12 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
     @undoBatch @action
     toggleFollowLink = (location: Opt<string>, zoom: boolean, setPushpin: boolean): void => {
         this.Document.ignoreClick = false;
-        this.Document._isLinkButton = !this.Document._isLinkButton;
-        setPushpin && (this.Document.isPushpin = this.Document._isLinkButton);
+        if (setPushpin) {
+            this.Document.isPushpin = !this.Document.isPushpin;
+            this.Document._isLinkButton = this.Document.isPushpin || this.Document._isLinkButton;
+        } else {
+            this.Document._isLinkButton = !this.Document._isLinkButton;
+        }
         if (this.Document._isLinkButton && !this.onClickHandler) {
             this.Document.followLinkZoom = zoom;
             this.Document.followLinkLocation = location;
diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx
index d5f3f3b4e..eca2e3cfd 100644
--- a/src/client/views/nodes/LinkDocPreview.tsx
+++ b/src/client/views/nodes/LinkDocPreview.tsx
@@ -15,6 +15,7 @@ import { DocumentView, DocumentViewSharedProps } from "./DocumentView";
 import './LinkDocPreview.scss';
 import React = require("react");
 import { DocumentType } from '../../documents/DocumentTypes';
+import { DragManager } from '../../util/DragManager';
 
 interface LinkDocPreviewProps {
     linkDoc?: Doc;
@@ -137,7 +138,13 @@ export class LinkDocPreview extends React.Component<LinkDocPreviewProps> {
     @computed get previewHeader() {
         return !this._linkDoc || !this._targetDoc || !this._linkSrc ? (null) :
             <div className="linkDocPreview-info" ref={this._infoRef}>
-                <div className="linkDocPreview-title">
+                <div className="linkDocPreview-title" style={{ pointerEvents: "all" }}
+                    onPointerDown={e => {
+                        DragManager.StartDocumentDrag([this._infoRef.current!],
+                            new DragManager.DocumentDragData([this._targetDoc!]), e.pageX, e.pageY);
+                        e.stopPropagation();
+                        LinkDocPreview.Clear();
+                    }}>
                     {StrCast(this._targetDoc.title).length > 16 ? StrCast(this._targetDoc.title).substr(0, 16) + "..." : this._targetDoc.title}
                     <p className="linkDocPreview-description"> {StrCast(this._linkDoc.description)}</p>
                 </div>
-- 
cgit v1.2.3-70-g09d2


From 85fca7ecd26236407e266d6aec051d1f5fb5feb9 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Thu, 14 Apr 2022 09:30:37 -0400
Subject: gave summary documents pushpin behaviors.  fixed following link to
 doc that is iconified to work.  fixed pushin visibility toggling for docs
 that are iconified.

---
 src/client/documents/Documents.ts                                   | 1 +
 src/client/views/StyleProvider.tsx                                  | 2 +-
 .../views/collections/collectionFreeForm/CollectionFreeFormView.tsx | 6 +++---
 src/client/views/collections/collectionFreeForm/MarqueeView.tsx     | 6 ++++--
 src/client/views/nodes/DocumentView.tsx                             | 5 ++++-
 5 files changed, 13 insertions(+), 7 deletions(-)

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

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 465cdf3ec..69ea21541 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -117,6 +117,7 @@ export class DocumentOptions {
     _lockedPosition?: boolean; // lock the x,y coordinates of the document so that it can't be dragged
     _lockedTransform?: boolean; // lock the panx,pany and scale parameters of the document so that it be panned/zoomed
     _freeformLOD?: boolean; // whether to use LOD to render a freeform document
+    _isPushpin?: boolean; // whether document, when clicked, toggles display of its link target
     _showTitle?: string; // field name to display in header (:hover is an optional suffix)
     _showCaption?: string; // which field to display in the caption area.  leave empty to have no caption
     _scrollTop?: number; // scroll location for pdfs
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index dba290b46..ba5aaf36a 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -117,7 +117,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
             const backColor = backgroundCol();
             if (!backColor) return undefined;
             return lightOrDark(backColor);
-        case StyleProp.Hidden: return BoolCast(doc?._hidden);
+        case StyleProp.Hidden: return BoolCast(doc?.hidden);
         case StyleProp.BorderRounding: return StrCast(doc?.[fieldKey + "borderRounding"], StrCast(doc?.borderRounding, doc?._viewType === CollectionViewType.Pile ? "50%" : ""));
         case StyleProp.TitleHeight: return 15;
         case StyleProp.BorderPath: return comicStyle() && props?.renderDepth && doc?.type !== DocumentType.INK ? { path: wavyBorderPath(props?.PanelWidth?.() || 0, props?.PanelHeight?.() || 0), fill: wavyBorderPath(props?.PanelWidth?.() || 0, props?.PanelHeight?.() || 0, .08), width: 3 } : { path: undefined, width: 0 };
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 9b0acffdf..99a6508a9 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1061,11 +1061,10 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
             this.props.focus(doc, options);
         } else {
             const xfToCollection = options?.docTransform ?? Transform.Identity();
-            const layoutdoc = Doc.Layout(doc);
             const savedState = { panX: NumCast(this.Document._panX), panY: NumCast(this.Document._panY), scale: this.Document[this.scaleFieldKey] };
             const newState = HistoryUtil.getState();
             const cantTransform = this.props.isAnnotationOverlay || ((this.rootDoc._isGroup || this.layoutDoc._lockedTransform) && !LightboxView.LightboxDoc);
-            const { panX, panY, scale } = cantTransform ? savedState : this.calculatePanIntoView(layoutdoc, xfToCollection, options?.willZoom ? options?.scale || .75 : undefined);
+            const { panX, panY, scale } = cantTransform ? savedState : this.calculatePanIntoView(doc, xfToCollection, options?.willZoom ? options?.scale || .75 : undefined);
             if (!cantTransform) {   // only pan and zoom to focus on a document if the document is not an annotation in an annotation overlay collection
                 newState.initializers![this.Document[Id]] = { panX: panX, panY: panY };
                 HistoryUtil.pushState(newState);
@@ -1112,10 +1111,11 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
     }
 
     calculatePanIntoView = (doc: Doc, xf: Transform, scale?: number) => {
+        const layoutdoc = Doc.Layout(doc);
         const pw = this.props.PanelWidth() / NumCast(this.layoutDoc._viewScale, 1);
         const ph = this.props.PanelHeight() / NumCast(this.layoutDoc._viewScale, 1);
         const pt = xf.transformPoint(NumCast(doc.x), NumCast(doc.y));
-        const pt2 = xf.transformPoint(NumCast(doc.x) + doc[WidthSym](), NumCast(doc.y) + doc[HeightSym]());
+        const pt2 = xf.transformPoint(NumCast(doc.x) + layoutdoc[WidthSym](), NumCast(doc.y) + layoutdoc[HeightSym]());
         const bounds = { left: pt[0], right: pt2[0], top: pt[1], bot: pt2[1] };
         const cx = NumCast(this.layoutDoc._panX);
         const cy = NumCast(this.layoutDoc._panY);
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index 5405ab500..2174aaf10 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -519,10 +519,12 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
             d.y = NumCast(d.y) - this.Bounds.top;
             return d;
         });
-        const summary = Docs.Create.TextDocument("", { _backgroundColor: "#e2ad32", x: this.Bounds.left, y: this.Bounds.top, _width: 200, _height: 200, _fitToBox: true, _showSidebar: true, title: "overview" });
-        const portal = Docs.Create.FreeformDocument(selected, { isGroup: true, backgroundColor: "transparent" });
+        const summary = Docs.Create.TextDocument("", { _backgroundColor: "#e2ad32", x: this.Bounds.left, y: this.Bounds.top, isPushpin: true, _width: 200, _height: 200, _fitToBox: true, _showSidebar: true, title: "overview" });
+        const portal = Docs.Create.FreeformDocument(selected, { x: this.Bounds.left + 200, y: this.Bounds.top, isGroup: true, backgroundColor: "transparent" });
         DocUtils.MakeLink({ doc: summary }, { doc: portal }, "summarizing", "");
 
+        portal.hidden = true;
+        this.props.addDocument?.(portal);
         this.props.addLiveTextDocument(summary);
         MarqueeOptionsMenu.Instance.fadeOut(true);
     }
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 8bf9348c7..0e22b1b3f 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -211,7 +211,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
     @computed get ShowTitle() { return this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.ShowTitle) as (Opt<string>); }
     @computed get ContentScale() { return this.props.ContentScaling?.() || 1; }
     @computed get thumb() { return ImageCast(this.layoutDoc["thumb-frozen"], ImageCast(this.layoutDoc.thumb))?.url.href.replace(".png", "_m.png"); }
-    @computed get hidden() { return this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.Hidden); }
+    @computed get hidden() { return this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Hidden); }
     @computed get opacity() { return this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.Opacity); }
     @computed get boxShadow() { return this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.BoxShadow); }
     @computed get borderRounding() { return this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.BorderRounding); }
@@ -1081,6 +1081,9 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
         TraceMobx();
         const thumb = ImageCast(this.layoutDoc["thumb-frozen"], ImageCast(this.layoutDoc.thumb))?.url.href.replace(".png", "_m.png");
         const isButton = this.props.Document.type === DocumentType.FONTICON;
+        if (this.props.Document.title === "myicon") {
+            console.log(this.hidden);
+        }
         if (!(this.props.Document instanceof Doc) || GetEffectiveAcl(this.props.Document[DataSym]) === AclPrivate || this.hidden) return null;
         return this.docContents ??
             <div className={`documentView-node${this.topMost ? "-topmost" : ""}`}
-- 
cgit v1.2.3-70-g09d2


From 239ff2c0423333bb7e154158c1f52ef688875ee7 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Sun, 24 Apr 2022 14:50:21 -0400
Subject: fixed treeViews to vertically span their containers.  fixed
 foreground coloring of nodes with transparent backgrounds to consider parent
 collection background color

---
 src/client/views/StyleProvider.tsx                 |  5 ++--
 src/client/views/collections/CollectionSubView.tsx | 34 +++++++++++-----------
 .../views/collections/CollectionTreeView.scss      |  6 ++++
 .../views/collections/CollectionTreeView.tsx       |  3 +-
 src/client/views/collections/TreeView.tsx          |  2 +-
 src/client/views/nodes/DocumentView.tsx            |  6 ++++
 .../views/nodes/formattedText/FormattedTextBox.tsx | 16 +++++-----
 7 files changed, 41 insertions(+), 31 deletions(-)

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

diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index ba5aaf36a..5c10c2344 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -81,7 +81,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
     const isAnchor = property.includes(":anchor");
     const isAnnotated = property.includes(":annotated");
     const isOpen = property.includes(":open");
-    const fieldKey = (props as any)?.fieldKey ? (props as any).fieldKey + "-" : isCaption ? "caption-" : "";
+    const fieldKey = props?.fieldKey ? props.fieldKey + "-" : isCaption ? "caption-" : "";
     const comicStyle = () => doc && !Doc.IsSystem(doc) && Doc.UserDoc().renderStyle === "comic";
     const isBackground = () => StrListCast(doc?._layerTags).includes(StyleLayers.Background);
     const backgroundCol = () => props?.styleProvider?.(doc, props, StyleProp.BackgroundColor);
@@ -114,7 +114,8 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
             if (MainView.Instance.LastButton === doc) return Colors.DARK_GRAY;
             const docColor: Opt<string> = StrCast(doc?.[fieldKey + "color"], StrCast(doc?._color));
             if (docColor) return docColor;
-            const backColor = backgroundCol();
+            const docView = props?.DocumentView?.();
+            const backColor = backgroundCol() || docView?.props.styleProvider?.(docView.props.treeViewDoc, docView.props, "backgroundColor");
             if (!backColor) return undefined;
             return lightOrDark(backColor);
         case StyleProp.Hidden: return BoolCast(doc?.hidden);
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index d8f1287cd..0eb94c394 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -1,23 +1,32 @@
-import { action, computed, IReactionDisposer, reaction, observable, runInAction } from "mobx";
+import { action, computed, observable } from "mobx";
+import ReactLoading from 'react-loading';
+import * as rp from 'request-promise';
 import CursorField from "../../../fields/CursorField";
-import { Doc, Opt, Field, DocListCast, AclPrivate, StrListCast } from "../../../fields/Doc";
-import { Id, ToString } from "../../../fields/FieldSymbols";
+import { AclPrivate, Doc, DocListCast, Field, Opt, StrListCast } from "../../../fields/Doc";
+import { Id } from "../../../fields/FieldSymbols";
 import { List } from "../../../fields/List";
 import { listSpec } from "../../../fields/Schema";
 import { ScriptField } from "../../../fields/ScriptField";
+import { Cast, NumCast, ScriptCast, StrCast } from "../../../fields/Types";
 import { WebField } from "../../../fields/URLField";
-import { Cast, ScriptCast, NumCast, StrCast } from "../../../fields/Types";
+import { GetEffectiveAcl, TraceMobx } from "../../../fields/util";
 import { GestureUtils } from "../../../pen-gestures/GestureUtils";
-import { Utils, returnFalse, returnEmptyFilter } from "../../../Utils";
+import { returnFalse, Utils } from "../../../Utils";
 import { DocServer } from "../../DocServer";
+import { Docs, DocumentOptions, DocUtils } from "../../documents/Documents";
+import { DocumentType } from "../../documents/DocumentTypes";
+import { Networking } from "../../Network";
+import { CurrentUserUtils } from "../../util/CurrentUserUtils";
+import { DragManager, dropActionType } from "../../util/DragManager";
 import { ImageUtils } from "../../util/Import & Export/ImageUtils";
 import { InteractionUtils } from "../../util/InteractionUtils";
+import { SelectionManager } from "../../util/SelectionManager";
 import { undoBatch, UndoManager } from "../../util/UndoManager";
 import { DocComponent } from "../DocComponent";
+import { FormattedTextBox } from "../nodes/formattedText/FormattedTextBox";
+import { OverlayView } from "../OverlayView";
+import { CollectionView, CollectionViewProps, CollectionViewType } from "./CollectionView";
 import React = require("react");
-import ReactLoading from 'react-loading';
-import * as rp from 'request-promise';
-import { Networking } from "../../Network";
 
 
 export interface SubCollectionViewProps extends CollectionViewProps {
@@ -472,13 +481,4 @@ export function CollectionSubView<X>(moreProps?: X) {
     return CollectionSubView;
 }
 
-import { DragManager, dropActionType } from "../../util/DragManager";
-import { Docs, DocumentOptions, DocUtils } from "../../documents/Documents";
-import { CurrentUserUtils } from "../../util/CurrentUserUtils";
-import { DocumentType } from "../../documents/DocumentTypes";
-import { FormattedTextBox, GoogleRef } from "../nodes/formattedText/FormattedTextBox";
-import { CollectionView, CollectionViewType, CollectionViewProps } from "./CollectionView";
-import { SelectionManager } from "../../util/SelectionManager";
-import { OverlayView } from "../OverlayView";
-import { GetEffectiveAcl, TraceMobx } from "../../../fields/util";
 
diff --git a/src/client/views/collections/CollectionTreeView.scss b/src/client/views/collections/CollectionTreeView.scss
index b664d9d82..a8eee9c19 100644
--- a/src/client/views/collections/CollectionTreeView.scss
+++ b/src/client/views/collections/CollectionTreeView.scss
@@ -2,6 +2,7 @@
 
 .collectionTreeView-container {
     transform-origin: top left;
+    height: 100%;
 }
 .collectionTreeView-dropTarget {
     border-width: $COLLECTION_BORDER_WIDTH;
@@ -71,6 +72,11 @@
     display: none;
 }
 
+.collectionTreeView-contents {
+    display: flex;
+    flex-direction: column;
+}
+
 .collectionTreeView-titleBar {
     display: inline-block;
     width: 100%;
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index e84517f40..76da96174 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -341,14 +341,13 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
             <div className="collectionTreeView-contents" key="tree" style={{
                 ...(!titleBar ? { paddingLeft: this.marginX(), paddingTop: this.marginTop() } : {}),
                 overflow: "auto",
-                height: this.layoutDoc._autoHeight ? "max-content" : "100%"
+                height: "100%"//this.layoutDoc._autoHeight ? "max-content" : "100%"
             }} >
                 {titleBar}
                 <div className="collectionTreeView-container"
                     style={{
                         transform: this.outlineMode ? `scale(${this.contentScaling})` : "",
                         paddingLeft: `${this.marginX()}px`,
-                        height: "max-content",
                         width: this.outlineMode ? `calc(${100 / this.contentScaling}%)` : ""
                     }}
                     onContextMenu={this.onContextMenu}>
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index 342424d41..61c7ff78e 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -225,7 +225,7 @@ export class TreeView extends React.Component<TreeViewProps> {
             title: "-title-",
             treeViewExpandedViewLock: true, treeViewExpandedView: "data",
             _viewType: CollectionViewType.Tree, hideLinkButton: true, _showSidebar: true, treeViewType: "outline",
-            x: 0, y: 0, _xMargin: 0, _yMargin: 0, _autoHeight: true, _singleLine: true, backgroundColor: "transparent", _width: 1000, _height: 10
+            x: 0, y: 0, _xMargin: 0, _yMargin: 0, _autoHeight: true, _singleLine: true, _width: 1000, _height: 10
         });
         Doc.GetProto(bullet).title = ComputedField.MakeFunction('self.text?.Text');
         Doc.GetProto(bullet).data = new List<Doc>([]);
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index bcf00e88d..504a3afb6 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -104,7 +104,10 @@ export interface DocComponentView {
     snapPt?: (pt: { X: number, Y: number }, excludeSegs?: number[]) => { nearestPt: { X: number, Y: number }, distance: number };
     search?: (str: string, bwd?: boolean, clear?: boolean) => boolean;
 }
+// These props are passed to both FieldViews and DocumentViews 
 export interface DocumentViewSharedProps {
+    fieldKey?: string; // only used by FieldViews but helpful here to allow styleProviders to access fieldKey of FieldViewProps.  In priniciple, passing a fieldKey to a documentView could override or be the default fieldKey for fieldViews
+    DocumentView?: () => DocumentView;
     renderDepth: number;
     Document: Doc;
     DataDoc?: Doc;
@@ -149,6 +152,8 @@ export interface DocumentViewSharedProps {
     createNewFilterDoc?: () => void;
     updateFilterDoc?: (doc: Doc) => void;
 }
+
+// these props are specific to DocuentViews
 export interface DocumentViewProps extends DocumentViewSharedProps {
     // properties specific to DocumentViews but not to FieldView
     freezeDimensions?: boolean;
@@ -173,6 +178,7 @@ export interface DocumentViewProps extends DocumentViewSharedProps {
     onPointerUp?: () => ScriptField;
 }
 
+// these props are only available in DocumentViewIntenral
 export interface DocumentViewInternalProps extends DocumentViewProps {
     NativeWidth: () => number;
     NativeHeight: () => number;
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index ac291801b..dc1c67bea 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -1,23 +1,23 @@
+import { IconProp } from '@fortawesome/fontawesome-svg-core';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { isEqual } from "lodash";
-import { action, computed, IReactionDisposer, reaction, runInAction, observable, trace } from "mobx";
+import { action, computed, IReactionDisposer, observable, reaction, runInAction } from "mobx";
 import { observer } from "mobx-react";
 import { baseKeymap, selectAll } from "prosemirror-commands";
 import { history } from "prosemirror-history";
 import { inputRules } from 'prosemirror-inputrules';
 import { keymap } from "prosemirror-keymap";
 import { Fragment, Mark, Node, Slice } from "prosemirror-model";
-import { ReplaceStep } from 'prosemirror-transform';
 import { EditorState, NodeSelection, Plugin, TextSelection, Transaction } from "prosemirror-state";
 import { EditorView } from "prosemirror-view";
 import { DateField } from '../../../../fields/DateField';
-import { AclAdmin, AclEdit, AclSelfEdit, DataSym, Doc, DocListCast, DocListCastAsync, Field, ForceServerWrite, HeightSym, Opt, UpdatingFromServer, WidthSym, AclAugment } from "../../../../fields/Doc";
+import { AclAdmin, AclAugment, AclEdit, AclSelfEdit, DataSym, Doc, DocListCast, DocListCastAsync, Field, ForceServerWrite, HeightSym, Opt, UpdatingFromServer, WidthSym } from "../../../../fields/Doc";
 import { Id } from '../../../../fields/FieldSymbols';
 import { InkTool } from '../../../../fields/InkField';
 import { PrefetchProxy } from '../../../../fields/Proxy';
 import { RichTextField } from "../../../../fields/RichTextField";
 import { RichTextUtils } from '../../../../fields/RichTextUtils';
-import { Cast, DateCast, NumCast, ScriptCast, StrCast } from "../../../../fields/Types";
+import { Cast, NumCast, ScriptCast, StrCast } from "../../../../fields/Types";
 import { GetEffectiveAcl, TraceMobx } from '../../../../fields/util';
 import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, emptyFunction, numberRange, OmitKeys, returnZero, setupMoveUpEvents, smoothScroll, Utils } from '../../../../Utils';
 import { GoogleApiClientUtils, Pulls, Pushes } from '../../../apis/google_docs/GoogleApiClientUtils';
@@ -29,6 +29,7 @@ import { DictationManager } from '../../../util/DictationManager';
 import { DocumentManager } from '../../../util/DocumentManager';
 import { DragManager } from "../../../util/DragManager";
 import { makeTemplate } from '../../../util/DropConverter';
+import { LinkManager } from '../../../util/LinkManager';
 import { SelectionManager } from "../../../util/SelectionManager";
 import { SnappingManager } from '../../../util/SnappingManager';
 import { undoBatch, UndoManager } from "../../../util/UndoManager";
@@ -38,10 +39,11 @@ import { ContextMenu } from '../../ContextMenu';
 import { ContextMenuProps } from '../../ContextMenuItem';
 import { ViewBoxAnnotatableComponent } from "../../DocComponent";
 import { DocumentButtonBar } from '../../DocumentButtonBar';
+import { Colors } from '../../global/globalEnums';
 import { LightboxView } from '../../LightboxView';
 import { AnchorMenu } from '../../pdf/AnchorMenu';
+import { SidebarAnnos } from '../../SidebarAnnos';
 import { StyleProp } from '../../StyleProvider';
-import { AudioBox } from '../AudioBox';
 import { FieldView, FieldViewProps } from "../FieldView";
 import { LinkDocPreview } from '../LinkDocPreview';
 import { DashDocCommentView } from "./DashDocCommentView";
@@ -60,10 +62,6 @@ import { schema } from "./schema_rts";
 import { SummaryView } from "./SummaryView";
 import applyDevTools = require("prosemirror-dev-tools");
 import React = require("react");
-import { SidebarAnnos } from '../../SidebarAnnos';
-import { Colors } from '../../global/globalEnums';
-import { IconProp } from '@fortawesome/fontawesome-svg-core';
-import { LinkManager } from '../../../util/LinkManager';
 const translateGoogleApi = require("translate-google-api");
 
 export interface FormattedTextBoxProps {
-- 
cgit v1.2.3-70-g09d2


From 9f3f64bb5bd3c7d5c97dfcbad39306cab465b822 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Wed, 27 Apr 2022 12:02:29 -0400
Subject: fixed double-click on file sys to lightbox the doc.  adjusted how
 aliases are chosen when opening file sys doc.  fixed sorting UI of treeviews

---
 src/client/views/StyleProvider.tsx                 |  2 +-
 .../views/collections/CollectionTreeView.scss      |  5 +-
 src/client/views/collections/TreeView.scss         | 11 ++++
 src/client/views/collections/TreeView.tsx          | 74 ++++++++++++++--------
 4 files changed, 63 insertions(+), 29 deletions(-)

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

diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index 5c10c2344..34418e170 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -213,7 +213,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
 }
 
 export function DashboardToggleButton(doc: Doc, field: string, onIcon: IconProp, offIcon: IconProp, clickFunc?: () => void) {
-    return <div className={`styleProvider-treeView-icon${doc[field] ? "-active" : ""}`}
+    return <div title={field} className={`styleProvider-treeView-icon${doc[field] ? "-active" : ""}`}
         onClick={undoBatch(action((e: React.MouseEvent) => {
             e.stopPropagation();
             clickFunc ? clickFunc() : (doc[field] = doc[field] ? undefined : true);
diff --git a/src/client/views/collections/CollectionTreeView.scss b/src/client/views/collections/CollectionTreeView.scss
index a8eee9c19..93523a6cf 100644
--- a/src/client/views/collections/CollectionTreeView.scss
+++ b/src/client/views/collections/CollectionTreeView.scss
@@ -1,5 +1,6 @@
 @import "../global/globalCssVariables";
 
+  
 .collectionTreeView-container {
     transform-origin: top left;
     height: 100%;
@@ -31,9 +32,11 @@
             width: unset;
             height: unset;
         }
+        &:hover {
+            cursor: ns-resize;
+        }
     }
 
-
     .no-indent {
         padding-left: 0;
         width: max-content;
diff --git a/src/client/views/collections/TreeView.scss b/src/client/views/collections/TreeView.scss
index 4707ebb80..b91737a1d 100644
--- a/src/client/views/collections/TreeView.scss
+++ b/src/client/views/collections/TreeView.scss
@@ -62,6 +62,17 @@
     }
 }
 
+.treeView-sorting {
+    position: absolute;
+    height: max-content;
+    pointer-events: none;
+    color: white;
+    border-radius: 4px;
+    font-size: 10px;
+}
+.treeView-container-active {
+    cursor: default;
+}
 .treeView-container-outline-active
 .treeView-container-active {
     z-index: 100;
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index 9108acfcf..3a49297f8 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -79,6 +79,7 @@ export class TreeView extends React.Component<TreeViewProps> {
     static _editTitleOnLoad: Opt<{ id: string, parent: TreeView | CollectionTreeView | undefined }>;
     static _openTitleScript: Opt<ScriptField | undefined>;
     static _openLevelScript: Opt<ScriptField | undefined>;
+    static _sortUIMap = [["up", "crimson", "↑"], ["down", "blue", "↓"], ["z", "green", "z"], ["x", "darkgray", '\u00A0\u00A0\u00A0']];
     private _header: React.RefObject<HTMLDivElement> = React.createRef();
     private _tref = React.createRef<HTMLDivElement>();
     @observable _docRef: Opt<DocumentView>;
@@ -156,6 +157,17 @@ export class TreeView extends React.Component<TreeViewProps> {
             docView.select(false);
         }
     }
+    @action
+    openLevel = (docView: DocumentView) => {
+        if (this.props.document.isFolder || Doc.IsSystem(this.props.document)) {
+            this.treeViewOpen = !this.treeViewOpen;
+        } else {
+            // choose an appropriate alias or make one. --- choose the first alias that (1) user owns,  (2) has no context field ... otherwise make a new alias
+            const bestAlias = docView.props.Document.author === Doc.CurrentUserEmail ? docView.props.Document : DocListCast(this.props.document.aliases).find(doc => !doc.context && doc.author === Doc.CurrentUserEmail);
+            const nextBestAlias = DocListCast(this.props.document.aliases).find(doc => doc.author === Doc.CurrentUserEmail);
+            this.props.addDocTab(bestAlias ?? nextBestAlias ?? Doc.MakeAlias(this.props.document), "lightbox");
+        }
+    }
 
     constructor(props: any) {
         super(props);
@@ -399,13 +411,16 @@ export class TreeView extends React.Component<TreeViewProps> {
         TraceMobx();
         const expandKey = this.treeViewExpandedView;
         if (["links", "annotations", "aliases", this.fieldKey].includes(expandKey)) {
+            const sorting = StrCast(this.doc.treeViewSortCriterion);
+            const color = (TreeView._sortUIMap.find((sortUIfields) => sortUIfields[0] === sorting) ?? TreeView._sortUIMap.lastElement())[1];
+            const label = (TreeView._sortUIMap.find((sortUIfields) => sortUIfields[0] === sorting) ?? TreeView._sortUIMap.lastElement())[2];
             const key = (expandKey === "annotations" ? `${this.fieldKey}-` : "") + expandKey;
             const remDoc = (doc: Doc | Doc[]) => this.remove(doc, key);
             const localAdd = (doc: Doc, addBefore?: Doc, before?: boolean) => {
                 // if there's a sort ordering specified that can be modified on drop (eg, zorder can be modified, alphabetical can't),
                 // then the modification would be done here
                 const ordering = StrCast(this.doc.treeViewSortCriterion);
-                if (ordering === "Z") {
+                if (ordering === "z") {
                     const docs = TreeView.sortDocs(this.childDocs || ([] as Doc[]), ordering);
                     doc.zIndex = addBefore ? NumCast(addBefore.zIndex) + (before ? -0.5 : 0.5) : 1000;
                     docs.push(doc);
@@ -418,24 +433,29 @@ export class TreeView extends React.Component<TreeViewProps> {
             const addDoc = (doc: Doc | Doc[], addBefore?: Doc, before?: boolean) => (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => flg && localAdd(doc, addBefore, before), true);
             const docs = expandKey === "aliases" ? this.childAliases : expandKey === "links" ? this.childLinks : expandKey === "annotations" ? this.childAnnos : this.childDocs;
             let downX = 0, downY = 0;
-            const sortings = ["up", "down", "Z", undefined];
+            const sortings = this.props.treeView.rootDoc === Doc.UserDoc().myFilesystem ? ["up", "down", "x"] : ["up", "down", "z", "x"];
             const curSort = Math.max(0, sortings.indexOf(Cast(this.doc.treeViewSortCriterion, "string", null)));
-            return <ul key={expandKey + "more"} title={"sort: " + sortings[curSort]} className={this.doc.treeViewHideTitle ? "no-indent" : ""}
-                onPointerDown={e => { downX = e.clientX; downY = e.clientY; e.stopPropagation(); }}
-                onClick={(e) => {
-                    if (this.props.isContentActive() && Math.abs(e.clientX - downX) < 3 && Math.abs(e.clientY - downY) < 3) {
-                        !this.props.treeView.outlineMode && (this.doc.treeViewSortCriterion = sortings[(curSort + 1) % sortings.length]);
-                        e.stopPropagation();
-                    }
-                }}>
-                {!docs ? (null) :
-                    TreeView.GetChildElements(docs, this.props.treeView, this, this.layoutDoc,
-                        this.dataDoc, this.props.containerCollection, this.props.prevSibling, addDoc, remDoc, this.move,
-                        StrCast(this.doc.childDropAction, this.props.dropAction) as dropActionType, this.props.addDocTab, this.titleStyleProvider, this.props.ScreenToLocalTransform,
-                        this.props.isContentActive, this.props.panelWidth, this.props.renderDepth, this.props.treeViewHideHeaderFields,
-                        [...this.props.renderedIds, this.doc[Id]], this.props.onCheckedClick, this.props.onChildClick, this.props.skipFields, false, this.props.whenChildContentsActiveChanged,
-                        this.props.dontRegisterView, emptyFunction, emptyFunction, this.childContextMenuItems())}
-            </ul >;
+            return <>
+                {!docs?.length ? (null) : <div className={'treeView-sorting'} style={{ background: color }} >
+                    {label}
+                </div>}
+                <ul key={expandKey + "more"} title="click to change sort order" className={this.doc.treeViewHideTitle ? "no-indent" : ""}
+                    onPointerDown={e => { downX = e.clientX; downY = e.clientY; e.stopPropagation(); }}
+                    onClick={(e) => {
+                        if (this.props.isContentActive() && Math.abs(e.clientX - downX) < 3 && Math.abs(e.clientY - downY) < 3) {
+                            !this.props.treeView.outlineMode && (this.doc.treeViewSortCriterion = sortings[(curSort + 1) % sortings.length]);
+                            e.stopPropagation();
+                        }
+                    }}>
+                    {!docs ? (null) :
+                        TreeView.GetChildElements(docs, this.props.treeView, this, this.layoutDoc,
+                            this.dataDoc, this.props.containerCollection, this.props.prevSibling, addDoc, remDoc, this.move,
+                            StrCast(this.doc.childDropAction, this.props.dropAction) as dropActionType, this.props.addDocTab, this.titleStyleProvider, this.props.ScreenToLocalTransform,
+                            this.props.isContentActive, this.props.panelWidth, this.props.renderDepth, this.props.treeViewHideHeaderFields,
+                            [...this.props.renderedIds, this.doc[Id]], this.props.onCheckedClick, this.props.onChildClick, this.props.skipFields, false, this.props.whenChildContentsActiveChanged,
+                            this.props.dontRegisterView, emptyFunction, emptyFunction, this.childContextMenuItems())}
+                </ul >
+            </>;
         } else if (this.treeViewExpandedView === "fields") {
             return <ul key={this.doc[Id] + this.doc.title}>
                 <div style={{ display: "inline-block" }} >
@@ -497,7 +517,7 @@ export class TreeView extends React.Component<TreeViewProps> {
         const data = () => this.childDocs || this.props.treeView.dashboardMode ? this.fieldKey : "";
         const aliases = () => this.props.treeView.dashboardMode ? "" : "aliases";
         const fields = () => Doc.UserDoc().noviceMode ? "" : "fields";
-        const layout = (this.props.treeView.dashboardMode && Doc.UserDoc().noviceMode) || this.doc.viewType === CollectionViewType.Docking ? [] : ["layout"];
+        const layout = (Doc.UserDoc().noviceMode) || this.doc.viewType === CollectionViewType.Docking ? [] : ["layout"];
         return [data(), ...layout, ...(this.props.treeView.fileSysMode ? [aliases(), links(), annos()] : []), fields()].filter(m => m);
     }
     @action
@@ -512,9 +532,9 @@ export class TreeView extends React.Component<TreeViewProps> {
     @computed get headerElements() {
         return this.props.treeViewHideHeaderFields() || this.doc.treeViewHideHeaderFields ? (null)
             : <>
-                {this.doc.hideContextMenu ? (null) : <FontAwesomeIcon key="bars" icon="bars" size="sm" onClick={e => { this.showContextMenu(e); e.stopPropagation(); }} />}
+                {this.doc.hideContextMenu ? (null) : <FontAwesomeIcon title="context menu" key="bars" icon="bars" size="sm" onClick={e => { this.showContextMenu(e); e.stopPropagation(); }} />}
                 {this.doc.treeViewExpandedViewLock || Doc.IsSystem(this.doc) ? (null) :
-                    <span className="collectionTreeView-keyHeader" key={this.treeViewExpandedView} onPointerDown={this.expandNextviewType}>
+                    <span className="collectionTreeView-keyHeader" title="type of expanded data" key={this.treeViewExpandedView} onPointerDown={this.expandNextviewType}>
                         {this.treeViewExpandedView}
                     </span>}
             </>;
@@ -771,9 +791,9 @@ export class TreeView extends React.Component<TreeViewProps> {
     }
 
     @computed get renderBorder() {
-        const sorting = this.doc[`${this.fieldKey}-sortCriterion`];
-        return <div className={`treeView-border${this.props.treeView.outlineMode ? "outline" : ""}`}
-            style={{ borderColor: sorting === undefined ? undefined : sorting === "up" ? "crimson" : sorting === "down" ? "blue" : "green" }}>
+        const sorting = StrCast(this.doc.treeViewSortCriterion);
+        const color = (TreeView._sortUIMap.find((sortUIfields) => sortUIfields[0] === sorting) ?? TreeView._sortUIMap.lastElement())[1];
+        return <div className={`treeView-border${this.props.treeView.outlineMode ? "outline" : ""}`} style={{ borderColor: color }}>
             {!this.treeViewOpen ? (null) : this.renderContent}
         </div>;
     }
@@ -822,9 +842,9 @@ export class TreeView extends React.Component<TreeViewProps> {
             };
             docs.sort(function (d1, d2): 0 | 1 | -1 {
                 const a = (criterion === "up" ? d2 : d1);
-                const b = (criterion === "up" ? d1 : d2);
-                const first = a[criterion === "Z" ? "zIndex" : "title"];
-                const second = b[criterion === "Z" ? "zIndex" : "title"];
+                const b = (criterion === "down" ? d1 : d2);
+                const first = a[criterion === "z" ? "zIndex" : "title"];
+                const second = b[criterion === "z" ? "zIndex" : "title"];
                 if (typeof first === 'number' && typeof second === 'number') return (first - second) > 0 ? 1 : -1;
                 if (typeof first === 'string' && typeof second === 'string') return sortAlphaNum(first, second);
                 return criterion ? 1 : -1;
-- 
cgit v1.2.3-70-g09d2


From 97141270061f67e6ea867ba0b30a5e5111ae8c51 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Wed, 27 Apr 2022 13:04:48 -0400
Subject: fixed tree view icons to not needlessly use the layout_icon doc

---
 src/client/views/StyleProvider.tsx | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

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

diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index 34418e170..a88c745b8 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -90,9 +90,8 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
     const random = (min: number, max: number, x: number, y: number) => /* min should not be equal to max */ min + ((Math.abs(x * y) * 9301 + 49297) % 233280 / 233280) * (max - min);
     switch (property.split(":")[0]) {
         case StyleProp.TreeViewIcon:
-            const icon = Cast(doc?.layout_icon, Doc, null) ? Doc.expandTemplateLayout(Cast(doc?.layout_icon, Doc, null), doc) : undefined;
-            if (icon && ImageCast(doc?.icon, ImageCast(doc?.data))) {
-                const img = ImageCast(doc?.icon, ImageCast(doc?.data));
+            const img = ImageCast(doc?.icon, ImageCast(doc?.data));
+            if (img) {
                 const ext = extname(img.url.href);
                 const url = doc?.icon ? img.url.href : img.url.href.replace(ext, "_s" + ext);
                 return <img src={url} width={20} height={15} style={{ margin: "auto", display: "block", objectFit: "contain" }} />;
-- 
cgit v1.2.3-70-g09d2


From 267d4d7c3f2a85f0df292dea9667293eee3358c5 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Wed, 27 Apr 2022 13:46:33 -0400
Subject: fixed links to ink being computed correctly on the inkStroke's links
 field.  fixed interacting with iconified ink.  fixed cycling through links on
 linkDocPreivew to not deselect

---
 src/client/documents/Documents.ts         | 2 +-
 src/client/views/StyleProvider.tsx        | 6 ++++--
 src/client/views/nodes/LinkDocPreview.tsx | 2 +-
 3 files changed, 6 insertions(+), 4 deletions(-)

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

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index a19530c92..0bb873667 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -770,7 +770,7 @@ export namespace Docs {
             I.data = new InkField(points);
             I["acl-Public"] = Doc.UserDoc()?.defaultAclPrivate ? SharingPermissions.None : SharingPermissions.Augment;
             I["acl-Override"] = "None";
-            I.links = "@links(self)";
+            I.links = ComputedField.MakeFunction("links(self)");
             I[Initializing] = false;
             return I;
         }
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index a88c745b8..a530ff90a 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -23,6 +23,7 @@ import { FieldViewProps } from './nodes/FieldView';
 import { SliderBox } from './nodes/SliderBox';
 import "./StyleProvider.scss";
 import React = require("react");
+import { InkingStroke } from './InkingStroke';
 
 export enum StyleLayers {
     Background = "background"
@@ -195,9 +196,10 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
             if (doc?.type === DocumentType.MARKER) return "none";
             if (props?.pointerEvents === "none") return "none";
             const layer = doc && props?.layerProvider?.(doc);
-            if (opacity() === 0 || (doc?.type === DocumentType.INK && !docProps?.treeViewDoc) || doc?.isInkMask) return "none";
+            const isInk = doc && StrCast(Doc.Layout(doc).layout).includes(InkingStroke.name);
+            if (opacity() === 0 || (isInk && !docProps?.treeViewDoc) || doc?.isInkMask) return "none";
             if (layer === false && !selected && !SnappingManager.GetIsDragging()) return "none";
-            if (doc?.type !== DocumentType.INK && layer === true) return "all";
+            if (!isInk && layer === true) return "all";
             return undefined;
         case StyleProp.Decorations:
             if (props?.ContainingCollectionDoc?._viewType === CollectionViewType.Freeform || doc?.x !== undefined || doc?.y !== undefined) {
diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx
index 55f6d6059..28915674d 100644
--- a/src/client/views/nodes/LinkDocPreview.tsx
+++ b/src/client/views/nodes/LinkDocPreview.tsx
@@ -110,7 +110,7 @@ export class LinkDocPreview extends React.Component<LinkDocPreviewProps> {
         setupMoveUpEvents(this, e, returnFalse, emptyFunction, action(() => {
             this._linkDoc = undefined;
             this._hrefInd = (this._hrefInd + 1) % (this.props.hrefs?.length || 1);
-        }));
+        }), true);
     }
 
     followLink = (e: React.PointerEvent) => {
-- 
cgit v1.2.3-70-g09d2

