From 0a66b0f369a13d5f399bf125727aff73cd6fd1b4 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Wed, 19 Apr 2023 13:01:37 -0400
Subject: fixed image importing metadata for gpt. fixed showTitle UI to be able
 to turn off titles on templates (like icon views). added ui for choosing
 primary/alternate image and a drop target for setting alternate.

---
 src/client/views/nodes/trails/PresBox.tsx | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'src/client/views/nodes/trails/PresBox.tsx')

diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx
index 807a19771..f8c47aafe 100644
--- a/src/client/views/nodes/trails/PresBox.tsx
+++ b/src/client/views/nodes/trails/PresBox.tsx
@@ -527,7 +527,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
             bestTarget._dataTransition = `all ${transTime}ms`;
             const fkey = Doc.LayoutFieldKey(bestTarget);
             Doc.GetProto(bestTarget)[fkey] = activeItem.presData instanceof ObjectField ? activeItem.presData[Copy]() : activeItem.presData;
-            bestTarget[fkey + '-useAlt'] = activeItem.presUseAlt;
+            bestTarget[fkey + '-usePath'] = activeItem.presUsePath;
             setTimeout(() => (bestTarget._dataTransition = undefined), transTime + 10);
         }
         if ((pinDataTypes?.textview && activeItem.presData !== undefined) || (!pinDataTypes && activeItem.presData !== undefined)) {
@@ -613,7 +613,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                 pinProps?.activeFrame !== undefined;
             const fkey = Doc.LayoutFieldKey(targetDoc);
             if (pinProps.pinData.dataview) {
-                pinDoc.presUseAlt = targetDoc[fkey + '-useAlt'];
+                pinDoc.presUsePath = targetDoc[fkey + '-usePath'];
                 pinDoc.presData = targetDoc[fkey] instanceof ObjectField ? (targetDoc[fkey] as ObjectField)[Copy]() : targetDoc.data;
             }
             if (pinProps.pinData.dataannos) {
-- 
cgit v1.2.3-70-g09d2


From 7342eb81f241ce0b2a5a33ddfb0c865eab6a492f Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Thu, 27 Apr 2023 09:10:36 -0400
Subject: added proper scaling of multi-selections and groups.  fixed
 pinViewport to work again.

---
 src/client/util/CurrentUserUtils.ts                |   2 +-
 src/client/views/DocumentButtonBar.tsx             |   4 -
 src/client/views/DocumentDecorations.tsx           | 112 ++++++++++++---------
 src/client/views/collections/TabDocView.tsx        |   1 +
 .../collections/collectionFreeForm/MarqueeView.tsx |   5 +-
 src/client/views/nodes/DocumentView.tsx            |  10 +-
 src/client/views/nodes/button/FontIconBox.tsx      |   6 +-
 .../views/nodes/formattedText/RichTextRules.ts     |   2 +-
 src/client/views/nodes/formattedText/marks_rts.ts  |   2 +-
 src/client/views/nodes/trails/PresBox.tsx          |   1 +
 10 files changed, 80 insertions(+), 65 deletions(-)

(limited to 'src/client/views/nodes/trails/PresBox.tsx')

diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 5475873a9..479fcd011 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -621,8 +621,8 @@ export class CurrentUserUtils {
     }
     static viewTools(): Button[] {
         return [
-            { title: "Grid",          icon: "border-all",   toolTip: "Show Grid",           btnType: ButtonType.ToggleButton, expertMode: false, toolType:"grid",       funcs: {}, scripts: { onClick: 'showFreeform(self.toolType, _readOnly_)'}}, // Only when floating document is selected in freeform
             { title: "Snap\xA0Lines", icon: "th",           toolTip: "Show Snap Lines",     btnType: ButtonType.ToggleButton, expertMode: false, toolType:"snap lines", funcs: {}, scripts: { onClick: 'showFreeform(self.toolType, _readOnly_)'}}, // Only when floating document is selected in freeform
+            { title: "Grid",          icon: "border-all",   toolTip: "Show Grid",           btnType: ButtonType.ToggleButton, expertMode: false, toolType:"grid",       funcs: {}, scripts: { onClick: 'showFreeform(self.toolType, _readOnly_)'}}, // Only when floating document is selected in freeform
             { title: "View\xA0All",   icon: "object-group", toolTip: "Fit all Docs to View",btnType: ButtonType.ToggleButton, expertMode: false, toolType:"viewAll",    funcs: {}, scripts: { onClick: 'showFreeform(self.toolType, _readOnly_)'}}, // Only when floating document is selected in freeform
             { title: "Clusters",      icon: "braille",      toolTip: "Show Doc Clusters",   btnType: ButtonType.ToggleButton, expertMode: false, toolType:"clusters",   funcs: {}, scripts: { onClick: 'showFreeform(self.toolType, _readOnly_)'}}, // Only when floating document is selected in freeform
             { title: "Arrange",icon: "arrow-down-short-wide",toolTip: "Toggle Auto Arrange",btnType: ButtonType.ToggleButton, expertMode: false, toolType:"arrange",    funcs: {hidden: 'IsNoviceMode()'}, scripts: { onClick: 'showFreeform(self.toolType, _readOnly_)'}}, // Only when floating document is selected in freeform
diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx
index 8c2ced55a..30e41b06c 100644
--- a/src/client/views/DocumentButtonBar.tsx
+++ b/src/client/views/DocumentButtonBar.tsx
@@ -303,10 +303,6 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
                             onPointerEnter={action(e => (this.subEndLink = (pinLayout ? 'Layout' : '') + (pinLayout && pinContent ? ' &' : '') + (pinContent ? ' Content' : '')))}
                             onPointerLeave={action(e => (this.subEndLink = ''))}
                             onClick={e => {
-                                const docs = this.props
-                                    .views()
-                                    .filter(v => v)
-                                    .map(dv => dv!.rootDoc);
                                 this.view0 &&
                                     DocumentLinksButton.finishLinkClick(e.clientX, e.clientY, DocumentLinksButton.StartLink, this.view0.props.Document, true, this.view0, {
                                         pinDocLayout: pinLayout,
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 042e8f6d0..2811c96eb 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -12,7 +12,7 @@ import { InkField } from '../../fields/InkField';
 import { ScriptField } from '../../fields/ScriptField';
 import { Cast, NumCast, StrCast } from '../../fields/Types';
 import { GetEffectiveAcl } from '../../fields/util';
-import { emptyFunction, numberValue, returnFalse, setupMoveUpEvents, Utils } from '../../Utils';
+import { aggregateBounds, emptyFunction, numberValue, returnFalse, setupMoveUpEvents, Utils } from '../../Utils';
 import { Docs } from '../documents/Documents';
 import { DocumentType } from '../documents/DocumentTypes';
 import { DragManager } from '../util/DragManager';
@@ -34,6 +34,7 @@ import React = require('react');
 import { RichTextField } from '../../fields/RichTextField';
 import { LinkFollower } from '../util/LinkFollower';
 import _ = require('lodash');
+import { DocumentManager } from '../util/DocumentManager';
 
 @observer
 export class DocumentDecorations extends React.Component<{ PanelWidth: number; PanelHeight: number; boundsLeft: number; boundsTop: number }, { value: string }> {
@@ -509,73 +510,86 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
             dragRight = false,
             dragBotRight = false,
             dragTop = false;
-        let dX = 0,
-            dY = 0,
-            dW = 0,
-            dH = 0;
+        let dXin = 0,
+            dYin = 0,
+            dWin = 0,
+            dHin = 0;
         switch (this._resizeHdlId.split(' ')[0]) {
             case '':
                 break;
             case 'documentDecorations-topLeftResizer':
-                dX = -1;
-                dY = -1;
-                dW = -move[0];
-                dH = -move[1];
+                dXin = -1;
+                dYin = -1;
+                dWin = -move[0];
+                dHin = -move[1];
                 break;
             case 'documentDecorations-topRightResizer':
-                dW = move[0];
-                dY = -1;
-                dH = -move[1];
+                dWin = move[0];
+                dYin = -1;
+                dHin = -move[1];
                 break;
             case 'documentDecorations-topResizer':
-                dY = -1;
-                dH = -move[1];
+                dYin = -1;
+                dHin = -move[1];
                 dragTop = true;
                 break;
             case 'documentDecorations-bottomLeftResizer':
-                dX = -1;
-                dW = -move[0];
-                dH = move[1];
+                dXin = -1;
+                dWin = -move[0];
+                dHin = move[1];
                 break;
             case 'documentDecorations-bottomRightResizer':
-                dW = move[0];
-                dH = move[1];
+                dWin = move[0];
+                dHin = move[1];
                 dragBotRight = true;
                 break;
             case 'documentDecorations-bottomResizer':
-                dH = move[1];
+                dHin = move[1];
                 dragBottom = true;
                 break;
             case 'documentDecorations-leftResizer':
-                dX = -1;
-                dW = -move[0];
+                dXin = -1;
+                dWin = -move[0];
                 break;
             case 'documentDecorations-rightResizer':
-                dW = move[0];
+                dWin = move[0];
                 dragRight = true;
                 break;
         }
 
-        SelectionManager.Views().forEach(
+        const isGroup = first.rootDoc._isGroup ? first.rootDoc : undefined;
+        const scaleViews = isGroup ? DocListCast(isGroup.data).map(doc => DocumentManager.Instance.getFirstDocumentView(doc)!) : SelectionManager.Views();
+        const aggBounds = aggregateBounds(scaleViews.map(view => view.rootDoc) as any, 0, 0);
+        const refWidth = aggBounds.r - aggBounds.x;
+        const refHeight = aggBounds.b - aggBounds.y;
+        const scaleRefPt = first.props
+            .ScreenToLocalTransform()
+            .inverse()
+            .transformPoint(
+                NumCast(isGroup?._xPadding) + (dXin ? refWidth : 0), //
+                NumCast(isGroup?._yPadding) + (dYin ? refHeight : 0)
+            );
+        scaleViews.forEach(
             action((docView: DocumentView) => {
                 if (e.ctrlKey && !Doc.NativeHeight(docView.props.Document)) docView.toggleNativeDimensions();
-                if (dX !== 0 || dY !== 0 || dW !== 0 || dH !== 0) {
-                    const doc = Document(docView.rootDoc);
+                if (dXin !== 0 || dYin !== 0 || dWin !== 0 || dHin !== 0) {
+                    const doc = docView.rootDoc;
+                    const refCent = docView.props.ScreenToLocalTransform().transformPoint(scaleRefPt[0], scaleRefPt[1]);
+
                     if (doc.nativeHeightUnfrozen && !NumCast(doc.nativeHeight)) {
                         doc._nativeHeight = (NumCast(doc._height) / NumCast(doc._width, 1)) * docView.nativeWidth;
                     }
                     const nwidth = docView.nativeWidth;
                     const nheight = docView.nativeHeight;
-                    let docheight = doc._height || 0;
-                    let docwidth = doc._width || 0;
-                    const width = docwidth;
-                    let height = docheight || (nheight / nwidth) * width;
-                    height = !height || isNaN(height) ? 20 : height;
+                    const docwidth = NumCast(doc._width);
+                    let docheight = (hgt => (!hgt || isNaN(hgt) ? 20 : hgt))(NumCast(doc._height) || (nheight / nwidth) * docwidth);
+                    let dW = docwidth * (dWin / refWidth);
+                    let dH = docheight * (dHin / refHeight);
                     const scale = docView.props.ScreenToLocalTransform().Scale;
                     const modifyNativeDim = (e.ctrlKey || doc.forceReflow) && doc.nativeDimModifiable && ((!dragBottom && !dragTop) || e.ctrlKey || doc.nativeHeightUnfrozen);
                     if (nwidth && nheight) {
-                        if (nwidth / nheight !== width / height && !dragBottom && !dragTop) {
-                            height = (nheight / nwidth) * width;
+                        if (nwidth / nheight !== docwidth / docheight && !dragBottom && !dragTop) {
+                            docheight = (nheight / nwidth) * docwidth;
                         }
                         if (modifyNativeDim && !dragBottom && !dragTop) {
                             // ctrl key enables modification of the nativeWidth or nativeHeight durin the interaction
@@ -583,21 +597,25 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
                             else dW = (dH * nwidth) / nheight;
                         }
                     }
-                    let actualdW = Math.max(width + dW * scale, 20);
-                    let actualdH = Math.max(height + dH * scale, 20);
+                    let actualdW = Math.max(docwidth + dW * scale, 20);
+                    let actualdH = Math.max(docheight + dH * scale, 20);
+                    let dX = !dWin ? 0 : scale * refCent[0] * (1 - (1 + dWin / refWidth));
+                    let dY = !dHin ? 0 : scale * refCent[1] * (1 - (1 + dHin / refHeight));
                     const preserveNativeDim = doc._nativeHeightUnfrozen === false && doc._nativeDimModifiable === false;
                     const fixedAspect = nwidth && nheight && (!doc._fitWidth || preserveNativeDim || e.ctrlKey || doc.nativeHeightUnfrozen || doc.nativeDimModifiable);
                     if (fixedAspect) {
                         if ((Math.abs(dW) > Math.abs(dH) && ((!dragBottom && !dragTop) || !modifyNativeDim)) || dragRight) {
                             if (dragRight && modifyNativeDim) {
                                 if (Doc.NativeWidth(doc)) {
-                                    doc._nativeWidth = (actualdW / (doc._width || 1)) * Doc.NativeWidth(doc);
+                                    doc._nativeWidth = (actualdW / (docwidth || 1)) * Doc.NativeWidth(doc);
                                 }
                             } else {
                                 if (!doc._fitWidth || preserveNativeDim) {
                                     actualdH = (nheight / nwidth) * actualdW;
                                     doc._height = actualdH;
-                                } else if (!modifyNativeDim || dragBotRight) doc._height = actualdH;
+                                } else if (!modifyNativeDim || dragBotRight) {
+                                    doc._height = actualdH;
+                                }
                             }
                             doc._width = actualdW;
                         } else {
@@ -605,21 +623,23 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
                                 // frozen web pages, PDFs, and some RTFS have frozen nativewidth/height.  But they are marked to allow their nativeHeight
                                 // to be explicitly modified with fitWidth and vertical resizing. (ie, with fitWidth they can't grow horizontally to match
                                 // a vertical resize so it makes more sense to change their nativeheight even if the ctrl key isn't used)
-                                doc._nativeHeight = (actualdH / (doc._height || 1)) * Doc.NativeHeight(doc);
+                                doc._nativeHeight = (actualdH / (docheight || 1)) * Doc.NativeHeight(doc);
                                 doc._autoHeight = false;
                             } else {
                                 if (!doc._fitWidth || preserveNativeDim) {
                                     actualdW = (nwidth / nheight) * actualdH;
                                     doc._width = actualdW;
-                                } else if (!modifyNativeDim || dragBotRight) doc._width = actualdW;
+                                } else if (!modifyNativeDim || dragBotRight) {
+                                    doc._width = actualdW;
+                                }
                             }
                             if (!modifyNativeDim) {
-                                actualdH = Math.min((nheight / nwidth) * NumCast(doc._width), actualdH);
-                                doc._height = actualdH;
-                            } else doc._height = actualdH;
+                                actualdH = Math.min((nheight / nwidth) * docwidth, actualdH);
+                            }
+                            doc._height = actualdH;
                         }
                     } else {
-                        const rotCtr = [NumCast(doc._width) / 2, NumCast(doc._height) / 2];
+                        const rotCtr = [docwidth / 2, docheight / 2];
                         const tlRotated = Utils.rotPt(-rotCtr[0], -rotCtr[1], (NumCast(doc._rotation) / 180) * Math.PI);
 
                         const maxHeight = doc.nativeHeightUnfrozen || !nheight ? 0 : Math.max(nheight, NumCast(doc.scrollHeight, NumCast(doc[docView.LayoutFieldKey + '-scrollHeight']))) * docView.NativeDimScaling();
@@ -632,8 +652,8 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
                         doc.x = NumCast(doc.x) + tlRotated.x + rotCtr[0] - (tlRotated2.x + rotCtr2[0]); // doc shifts by amount topleft moves because rotation is about center of doc
                         doc.y = NumCast(doc.y) + tlRotated.y + rotCtr[1] - (tlRotated2.y + rotCtr2[1]);
                     }
-                    doc.x = (doc.x || 0) + dX * (actualdW - docwidth);
-                    doc.y = (doc.y || 0) + (dragBottom ? 0 : dY * (actualdH - docheight));
+                    doc.x = NumCast(doc.x) + dX;
+                    doc.y = NumCast(doc.y) + dY;
                     doc._lastModified = new DateField();
                 }
                 const val = this._dragHeights.get(docView.layoutDoc);
@@ -726,7 +746,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
         }
         // hide the decorations if the parent chooses to hide it or if the document itself hides it
         const hideDecorations = seldocview.props.hideDecorations || seldocview.rootDoc.hideDecorations;
-        const hideResizers = hideDecorations || seldocview.props.hideResizeHandles || seldocview.rootDoc.hideResizeHandles || seldocview.rootDoc._isGroup || this._isRounding || this._isRotating;
+        const hideResizers = hideDecorations || seldocview.props.hideResizeHandles || seldocview.rootDoc.hideResizeHandles || this._isRounding || this._isRotating;
         const hideTitle = hideDecorations || seldocview.props.hideDecorationTitle || seldocview.rootDoc.hideDecorationTitle || this._isRounding || this._isRotating;
         const hideDocumentButtonBar = hideDecorations || seldocview.props.hideDocumentButtonBar || seldocview.rootDoc.hideDocumentButtonBar || this._isRounding || this._isRotating;
         // if multiple documents have been opened at the same time, then don't show open button
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index 4bbc3bb44..45604c1bf 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -266,6 +266,7 @@ export class TabDocView extends React.Component<TabDocViewProps> {
             pinDoc.treeViewHideHeaderIfTemplate = true; // this will force the document to render itself as the tree view header
             const duration = NumCast(doc[`${Doc.LayoutFieldKey(pinDoc)}-duration`], null);
 
+            if (pinProps.pinViewport) PresBox.pinDocView(pinDoc, pinProps, anchorDoc ?? doc);
             if (!pinProps?.audioRange && duration !== undefined) {
                 pinDoc.mediaStart = 'manual';
                 pinDoc.mediaStop = 'manual';
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index eaeb5f933..e5f47823c 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -425,9 +425,8 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
      */
     @undoBatch
     @action
-    pinWithView = async () => {
-        const doc = this.props.Document;
-        TabDocView.PinDoc(doc, { pinViewport: this.Bounds });
+    pinWithView = () => {
+        TabDocView.PinDoc(this.props.Document, { pinViewport: this.Bounds });
         MarqueeOptionsMenu.Instance.fadeOut(true);
         this.hideMarquee();
     };
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index c957bc778..a25e5c42d 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -765,9 +765,8 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
             !more && moreItems.length && cm.addItem({ description: 'More...', subitems: moreItems, icon: 'compass' });
         }
         const constantItems: ContextMenuProps[] = [];
-
+        constantItems.push({ description: 'Show Metadata', event: () => this.props.addDocTab(this.props.Document, (OpenWhere.addRight.toString() + 'KeyValue') as OpenWhere), icon: 'layer-group' });
         if (!Doc.IsSystem(this.rootDoc)) {
-            constantItems.push({ description: 'Show Metadata', event: () => this.props.addDocTab(this.props.Document, (OpenWhere.addRight.toString() + 'KeyValue') as OpenWhere), icon: 'layer-group' });
             constantItems.push({ description: 'Export as Zip file', icon: 'download', event: async () => Doc.Zip(this.props.Document) });
             constantItems.push({ description: 'Import Zipped file', icon: 'upload', event: ({ x, y }) => this.importDocument() });
             (this.rootDoc._viewType !== CollectionViewType.Docking || !Doc.noviceMode) && constantItems.push({ description: 'Share', event: () => SharingManager.Instance.open(this.props.DocumentView()), icon: 'users' });
@@ -775,8 +774,9 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
                 // need option to gray out menu items ... preferably with a '?' that explains why they're grayed out (eg., no permissions)
                 constantItems.push({ description: 'Close', event: this.deleteClicked, icon: 'times' });
             }
-            cm.addItem({ description: 'General...', noexpand: true, subitems: constantItems, icon: 'question' });
         }
+        cm.addItem({ description: 'General...', noexpand: !Doc.IsSystem(this.rootDoc), subitems: constantItems, icon: 'question' });
+
         const help = cm.findByDescription('Help...');
         const helpItems: ContextMenuProps[] = help && 'subitems' in help ? help.subitems : [];
         !Doc.noviceMode && helpItems.push({ description: 'Text Shortcuts Ctrl+/', event: () => this.props.addDocTab(Docs.Create.PdfDocument('/assets/cheat-sheet.pdf', { _width: 300, _height: 300 }), OpenWhere.addRight), icon: 'keyboard' });
@@ -819,9 +819,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
         if (documentationDescription && documentationLink) {
             helpItems.push({
                 description: documentationDescription,
-                event: () => {
-                    window.open(documentationLink, '_blank');
-                },
+                event: () => window.open(documentationLink, '_blank'),
                 icon: 'book',
             });
         }
diff --git a/src/client/views/nodes/button/FontIconBox.tsx b/src/client/views/nodes/button/FontIconBox.tsx
index 1a75a7e76..4f570b5fc 100644
--- a/src/client/views/nodes/button/FontIconBox.tsx
+++ b/src/client/views/nodes/button/FontIconBox.tsx
@@ -610,16 +610,16 @@ ScriptingGlobals.add(function toggleOverlay(checkResult?: boolean) {
     selected ? selected.props.CollectionFreeFormDocumentView?.().float() : console.log('[FontIconBox.tsx] toggleOverlay failed');
 });
 
-ScriptingGlobals.add(function showFreeform(attr: 'grid' | 'snap lines' | 'clusters' | 'arrange' | 'viewAll', checkResult?: boolean) {
+ScriptingGlobals.add(function showFreeform(attr: 'grid' | 'snapline' | 'clusters' | 'arrange' | 'viewAll', checkResult?: boolean) {
     const selected = SelectionManager.Docs().lastElement();
     // prettier-ignore
-    const map: Map<'grid' | 'snap lines' | 'clusters' | 'arrange'| 'viewAll', { undo: boolean, checkResult: (doc:Doc) => any; setDoc: (doc:Doc) => void;}> = new Map([
+    const map: Map<'grid' | 'snapline' | 'clusters' | 'arrange'| 'viewAll', { undo: boolean, checkResult: (doc:Doc) => any; setDoc: (doc:Doc) => void;}> = new Map([
         ['grid', {
             undo: false,
             checkResult: (doc:Doc) => doc._backgroundGridShow,
             setDoc: (doc:Doc) => doc._backgroundGridShow = !doc._backgroundGridShow,
         }],
-        ['snap lines', {
+        ['snapline', {
             undo: false,
             checkResult: (doc:Doc) => doc.showSnapLines,
             setDoc: (doc:Doc) => doc._showSnapLines = !doc._showSnapLines,
diff --git a/src/client/views/nodes/formattedText/RichTextRules.ts b/src/client/views/nodes/formattedText/RichTextRules.ts
index 20ce929ad..e5943f257 100644
--- a/src/client/views/nodes/formattedText/RichTextRules.ts
+++ b/src/client/views/nodes/formattedText/RichTextRules.ts
@@ -391,7 +391,7 @@ export class RichTextRules {
                 const content = selected.selection.content();
                 const replaced = node ? selected.replaceRangeWith(start, end, schema.nodes.summary.create({ visibility: true, text: content, textslice: content.toJSON() })) : state.tr;
 
-                return replaced.setSelection(new TextSelection(replaced.doc.resolve(end + 1))).setStoredMarks([...node.marks, ...sm]);
+                return replaced.setSelection(new TextSelection(replaced.doc.resolve(end))).setStoredMarks([...node.marks, ...sm]);
             }),
 
             new InputRule(new RegExp(/%\)/), (state, match, start, end) => {
diff --git a/src/client/views/nodes/formattedText/marks_rts.ts b/src/client/views/nodes/formattedText/marks_rts.ts
index 3898490d3..5b47e8a70 100644
--- a/src/client/views/nodes/formattedText/marks_rts.ts
+++ b/src/client/views/nodes/formattedText/marks_rts.ts
@@ -349,7 +349,7 @@ export const marks: { [index: string]: MarkSpec } = {
         group: 'inline',
         toDOM(node: any) {
             const uid = node.attrs.userid.replace('.', '').replace('@', '');
-            const min = Math.round(node.attrs.modified / 12);
+            const min = Math.round(node.attrs.modified / 60);
             const hr = Math.round(min / 60);
             const day = Math.round(hr / 60 / 24);
             const remote = node.attrs.userid !== Doc.CurrentUserEmail ? ' UM-remote' : '';
diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx
index f8c47aafe..0b780f589 100644
--- a/src/client/views/nodes/trails/PresBox.tsx
+++ b/src/client/views/nodes/trails/PresBox.tsx
@@ -567,6 +567,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                 bestTarget._panY = viewport.panY;
                 const dv = DocumentManager.Instance.getDocumentView(bestTarget);
                 if (dv) {
+                    changed = true;
                     const computedScale = NumCast(activeItem.presZoom, 1) * Math.min(dv.props.PanelWidth() / viewport.width, dv.props.PanelHeight() / viewport.height);
                     activeItem.presMovement === PresMovement.Zoom && (bestTarget._viewScale = computedScale);
                     dv.ComponentView?.brushView?.(viewport);
-- 
cgit v1.2.3-70-g09d2


From 1c24114bbe8f69f61948f7531277305457926498 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Wed, 3 May 2023 10:11:06 -0400
Subject: fixed pinning template text documents with content to save and
 restore the actual text.

---
 src/client/util/DocumentManager.ts                  |  2 +-
 src/client/views/DocComponent.tsx                   |  2 +-
 src/client/views/collections/CollectionTimeView.tsx |  7 +++----
 src/client/views/nodes/trails/PresBox.tsx           | 11 ++---------
 src/fields/Doc.ts                                   |  2 +-
 5 files changed, 8 insertions(+), 16 deletions(-)

(limited to 'src/client/views/nodes/trails/PresBox.tsx')

diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index 4542c1c05..3a192f712 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -180,7 +180,7 @@ export class DocumentManager {
 
     static GetContextPath(doc: Opt<Doc>, includeExistingViews?: boolean) {
         if (!doc) return [];
-        const srcContext = Cast(doc.context, Doc, null) ?? Cast(doc.annotationOn, Doc, null);
+        const srcContext = DocCast(doc.annotationOn, DocCast(doc.context));
         var containerDocContext = srcContext ? [srcContext, doc] : [doc];
         while (
             containerDocContext.length &&
diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx
index d60ad68c6..eba55e30c 100644
--- a/src/client/views/DocComponent.tsx
+++ b/src/client/views/DocComponent.tsx
@@ -216,7 +216,7 @@ export function ViewBoxAnnotatableComponent<P extends ViewBoxAnnotatableProps>()
                             //DocUtils.LeavePushpin(doc);
                             doc._stayInCollection = undefined;
                             doc.context = this.props.Document;
-                            if (annotationKey ?? this._annotationKeySuffix()) Doc.GetProto(doc).annotationOn = this.props.Document;
+                            if (annotationKey ?? this._annotationKeySuffix()) Doc.GetProto(doc).annotationOn = this.rootDoc;
 
                             Doc.ActiveDashboard && inheritParentAcls(Doc.ActiveDashboard, doc);
                         });
diff --git a/src/client/views/collections/CollectionTimeView.tsx b/src/client/views/collections/CollectionTimeView.tsx
index d0f3f2ca5..c3f77205a 100644
--- a/src/client/views/collections/CollectionTimeView.tsx
+++ b/src/client/views/collections/CollectionTimeView.tsx
@@ -7,22 +7,21 @@ import { ObjectField } from '../../../fields/ObjectField';
 import { RichTextField } from '../../../fields/RichTextField';
 import { listSpec } from '../../../fields/Schema';
 import { ComputedField, ScriptField } from '../../../fields/ScriptField';
-import { BoolCast, Cast, NumCast, StrCast } from '../../../fields/Types';
+import { Cast, NumCast, StrCast } from '../../../fields/Types';
 import { emptyFunction, returnEmptyString, returnFalse, returnTrue, setupMoveUpEvents } from '../../../Utils';
 import { Docs } from '../../documents/Documents';
-import { DocumentType } from '../../documents/DocumentTypes';
 import { DocumentManager } from '../../util/DocumentManager';
 import { ScriptingGlobals } from '../../util/ScriptingGlobals';
 import { ContextMenu } from '../ContextMenu';
 import { ContextMenuProps } from '../ContextMenuItem';
 import { EditableView } from '../EditableView';
+import { DocFocusOptions, DocumentView } from '../nodes/DocumentView';
+import { PresBox } from '../nodes/trails';
 import { computePivotLayout, computeTimelineLayout, ViewDefBounds } from './collectionFreeForm/CollectionFreeFormLayoutEngines';
 import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormView';
 import { CollectionSubView } from './CollectionSubView';
 import './CollectionTimeView.scss';
 import React = require('react');
-import { DocFocusOptions, DocumentView } from '../nodes/DocumentView';
-import { PresBox } from '../nodes/trails';
 
 @observer
 export class CollectionTimeView extends CollectionSubView() {
diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx
index 0b780f589..bd2be8f11 100644
--- a/src/client/views/nodes/trails/PresBox.tsx
+++ b/src/client/views/nodes/trails/PresBox.tsx
@@ -49,7 +49,6 @@ export interface pinDataTypes {
     clippable?: boolean;
     datarange?: boolean;
     dataview?: boolean;
-    textview?: boolean;
     poslayoutview?: boolean;
     dataannos?: boolean;
 }
@@ -382,14 +381,13 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
         const temporal = [DocumentType.AUDIO, DocumentType.VID].includes(targetType);
         const clippable = [DocumentType.COMPARISON].includes(targetType);
         const datarange = [DocumentType.FUNCPLOT].includes(targetType);
-        const dataview = [DocumentType.INK, DocumentType.COL, DocumentType.IMG].includes(targetType) && target?.activeFrame === undefined;
+        const dataview = [DocumentType.INK, DocumentType.COL, DocumentType.IMG, DocumentType.RTF].includes(targetType) && target?.activeFrame === undefined;
         const poslayoutview = [DocumentType.COL].includes(targetType) && target?.activeFrame === undefined;
-        const textview = [DocumentType.RTF].includes(targetType) && target?.activeFrame === undefined;
         const viewType = targetType === DocumentType.COL;
         const filters = true;
         const pivot = true;
         const dataannos = false;
-        return { scrollable, pannable, inkable, viewType, pivot, filters, temporal, clippable, dataview, datarange, textview, poslayoutview, dataannos };
+        return { scrollable, pannable, inkable, viewType, pivot, filters, temporal, clippable, dataview, datarange, poslayoutview, dataannos };
     }
 
     @action
@@ -530,9 +528,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
             bestTarget[fkey + '-usePath'] = activeItem.presUsePath;
             setTimeout(() => (bestTarget._dataTransition = undefined), transTime + 10);
         }
-        if ((pinDataTypes?.textview && activeItem.presData !== undefined) || (!pinDataTypes && activeItem.presData !== undefined)) {
-            Doc.GetProto(bestTarget)[Doc.LayoutFieldKey(bestTarget)] = activeItem.presData instanceof ObjectField ? activeItem.presData[Copy]() : activeItem.presData;
-        }
         if (pinDataTypes?.poslayoutview || (!pinDataTypes && activeItem.presPinLayoutData !== undefined)) {
             changed = true;
             const layoutField = Doc.LayoutFieldKey(bestTarget);
@@ -609,7 +604,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                 pinProps.pinData.clippable ||
                 pinProps.pinData.datarange ||
                 pinProps.pinData.dataview ||
-                pinProps.pinData.textview ||
                 pinProps.pinData.poslayoutview ||
                 pinProps?.activeFrame !== undefined;
             const fkey = Doc.LayoutFieldKey(targetDoc);
@@ -621,7 +615,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                 const fkey = Doc.LayoutFieldKey(targetDoc);
                 pinDoc.presAnnotations = new List<Doc>(DocListCast(Doc.GetProto(targetDoc)[fkey + '-annotations']).filter(doc => !doc.unrendered));
             }
-            if (pinProps.pinData.textview) pinDoc.presData = targetDoc[Doc.LayoutFieldKey(targetDoc)] instanceof ObjectField ? (targetDoc[Doc.LayoutFieldKey(targetDoc)] as ObjectField)[Copy]() : targetDoc.text;
             if (pinProps.pinData.inkable) {
                 pinDoc.presFillColor = targetDoc.fillColor;
                 pinDoc.presColor = targetDoc.color;
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts
index 0ec881c48..a9be24c8b 100644
--- a/src/fields/Doc.ts
+++ b/src/fields/Doc.ts
@@ -1181,7 +1181,7 @@ export namespace Doc {
         return doc[StrCast(doc.layoutKey, 'layout')];
     }
     export function LayoutFieldKey(doc: Doc): string {
-        return StrCast(Doc.Layout(doc)[StrCast(doc.layoutKey, 'layout')]).split("'")[1]; // bcz: TODO check on this .  used to always reference 'layout', now it uses the layout speicfied by the current layoutKey
+        return StrCast(Doc.Layout(doc).layout).split("'")[1]; // bcz: TODO check on this .  used to always reference 'layout', now it uses the layout speicfied by the current layoutKey
     }
     export function NativeAspect(doc: Doc, dataDoc?: Doc, useDim?: boolean) {
         return Doc.NativeWidth(doc, dataDoc, useDim) / (Doc.NativeHeight(doc, dataDoc, useDim) || 1);
-- 
cgit v1.2.3-70-g09d2

