From 358f9e266ef264442aea1e2c7d5d959a19f7624c Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Fri, 22 Jul 2022 14:11:30 -0400
Subject: adjusted native dim scaling slightly combining props.scaling and
 props.ContentScaling into props.NativeDimScaling and fixing some resizing
 behaviors for fitWidth freeformviews and native-sized text boxes.   Also
 fixed clicking on presboxe elements to not drag.

---
 src/client/views/pdf/PDFViewer.tsx | 17 +++++------------
 1 file changed, 5 insertions(+), 12 deletions(-)

(limited to 'src/client/views/pdf/PDFViewer.tsx')

diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index 837734edf..2c83082b7 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -41,7 +41,6 @@ interface IViewerProps extends FieldViewProps {
     url: string;
     loaded?: (nw: number, nh: number, np: number) => void;
     setPdfViewer: (view: PDFViewer) => void;
-    ContentScaling?: () => number;
     anchorMenuClick?: () => undefined | ((anchor: Doc) => void);
     crop: (region: Doc | undefined, addCrop?: boolean) => Doc | undefined;
 }
@@ -97,7 +96,7 @@ export class PDFViewer extends React.Component<IViewerProps> {
             autoHeight => {
                 if (autoHeight) {
                     this.props.layoutDoc._nativeHeight = NumCast(this.props.Document[this.props.fieldKey + '-nativeHeight']);
-                    this.props.setHeight?.(NumCast(this.props.Document[this.props.fieldKey + '-nativeHeight']) * (this.props.scaling?.() || 1));
+                    this.props.setHeight?.(NumCast(this.props.Document[this.props.fieldKey + '-nativeHeight']) * (this.props.NativeDimScaling?.() || 1));
                 }
             }
         );
@@ -162,7 +161,7 @@ export class PDFViewer extends React.Component<IViewerProps> {
         const mainCont = this._mainCont.current;
         let focusSpeed: Opt<number>;
         if (doc !== this.props.rootDoc && mainCont) {
-            const windowHeight = this.props.PanelHeight() / (this.props.scaling?.() || 1);
+            const windowHeight = this.props.PanelHeight() / (this.props.NativeDimScaling?.() || 1);
             const scrollTo = doc.unrendered ? NumCast(doc.y) : Utils.scrollIntoView(NumCast(doc.y), doc[HeightSym](), NumCast(this.props.layoutDoc._scrollTop), windowHeight, 0.1 * windowHeight, NumCast(this.props.Document.scrollHeight));
             if (scrollTo !== undefined && scrollTo !== this.props.layoutDoc._scrollTop) {
                 focusSpeed = 500;
@@ -486,8 +485,8 @@ export class PDFViewer extends React.Component<IViewerProps> {
 
     showInfo = action((anno: Opt<Doc>) => (this._overlayAnnoInfo = anno));
     overlayTransform = () => this.scrollXf().scale(1 / NumCast(this.props.layoutDoc._viewScale, 1));
-    panelWidth = () => this.props.PanelWidth() / (this.props.scaling?.() || 1); // (this.Document.scrollHeight || Doc.NativeHeight(this.Document) || 0);
-    panelHeight = () => this.props.PanelHeight() / (this.props.scaling?.() || 1); // () => this._pageSizes.length && this._pageSizes[0] ? this._pageSizes[0].width : Doc.NativeWidth(this.Document);
+    panelWidth = () => this.props.PanelWidth() / (this.props.NativeDimScaling?.() || 1); // (this.Document.scrollHeight || Doc.NativeHeight(this.Document) || 0);
+    panelHeight = () => this.props.PanelHeight() / (this.props.NativeDimScaling?.() || 1); // () => this._pageSizes.length && this._pageSizes[0] ? this._pageSizes[0].width : Doc.NativeWidth(this.Document);
     basicFilter = () => [...this.props.docFilters(), Utils.PropUnsetFilter('textInlineAnnotations')];
     transparentFilter = () => [...this.props.docFilters(), Utils.IsTransparentFilter()];
     opaqueFilter = () => [...this.props.docFilters(), Utils.IsOpaqueFilter()];
@@ -509,7 +508,6 @@ export class PDFViewer extends React.Component<IViewerProps> {
             PanelWidth={this.panelWidth}
             dropAction={'alias'}
             select={emptyFunction}
-            ContentScaling={this.contentZoom}
             bringToFront={emptyFunction}
             docFilters={docFilters || this.basicFilter}
             styleProvider={this.childStyleProvider}
@@ -556,10 +554,6 @@ export class PDFViewer extends React.Component<IViewerProps> {
     @computed get pdfViewerDiv() {
         return <div className={'pdfViewerDash-text' + (this.props.pointerEvents?.() !== 'none' && this._textSelecting && this.props.isContentActive() ? '-selected' : '')} ref={this._viewer} />;
     }
-    @computed get contentScaling() {
-        return this.props.ContentScaling?.() || 1;
-    }
-    contentZoom = () => NumCast(this.props.layoutDoc._viewScale, 1);
     savedAnnotations = () => this._savedAnnotations;
     render() {
         TraceMobx();
@@ -574,8 +568,7 @@ export class PDFViewer extends React.Component<IViewerProps> {
                     onClick={this.onClick}
                     style={{
                         overflowX: NumCast(this.props.layoutDoc._viewScale, 1) !== 1 ? 'scroll' : undefined,
-                        height: !this.props.Document._fitWidth && window.screen.width > 600 ? Doc.NativeHeight(this.props.Document) : `${100 / this.contentScaling}%`,
-                        transform: `scale(${this.contentScaling})`,
+                        height: !this.props.Document._fitWidth && window.screen.width > 600 ? Doc.NativeHeight(this.props.Document) : `100%`,
                     }}>
                     {this.pdfViewerDiv}
                     {this.annotationLayer}
-- 
cgit v1.2.3-70-g09d2


From 0178de4ab9ffd11630b700f9c02468b74beabd14 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Wed, 17 Aug 2022 12:31:26 -0400
Subject: fixed dragging docs on web and pdf to work better by temporarily
 adding transparent docs to the opaque layer so they can get drop events.  
 cleaned eraser and pen interaction code and made erasing strokes work faster
 and avoid hanging by not intersecting strokes that are already partially
 deleted.

---
 src/Utils.ts                                       |   3 +-
 src/client/documents/Documents.ts                  |  26 +---
 src/client/views/collections/CollectionSubView.tsx |  12 +-
 .../collectionFreeForm/CollectionFreeFormView.tsx  | 140 ++++++---------------
 .../views/nodes/CollectionFreeFormDocumentView.tsx |   5 +-
 src/client/views/nodes/DocumentView.tsx            |   6 +-
 src/client/views/nodes/VideoBox.tsx                |  11 +-
 src/client/views/nodes/WebBox.scss                 |  17 +--
 src/client/views/nodes/WebBox.tsx                  | 110 ++++++++--------
 src/client/views/pdf/PDFViewer.tsx                 |  75 +++++------
 10 files changed, 153 insertions(+), 252 deletions(-)

(limited to 'src/client/views/pdf/PDFViewer.tsx')

diff --git a/src/Utils.ts b/src/Utils.ts
index 528a429d0..9e002ebd4 100644
--- a/src/Utils.ts
+++ b/src/Utils.ts
@@ -111,6 +111,7 @@ export namespace Utils {
 
     const isTransparentFunctionHack = 'isTransparent(__value__)';
     export const noRecursionHack = '__noRecursion';
+    export const noDragsDocFilter = 'noDragDocs:any:check';
     export function IsRecursiveFilter(val: string) {
         return !val.includes(noRecursionHack);
     }
@@ -125,7 +126,7 @@ export namespace Utils {
         // bcz: isTransparent(__value__) is a hack.  it would be nice to have acual functions be parsed, but now Doc.matchFieldValue is hardwired to recognize just this one
         return `backgroundColor:${isTransparentFunctionHack},${noRecursionHack}:x`; // bcz: hack.  noRecursion should probably be either another ':' delimited field, or it should be a modifier to the comparision (eg., check, x, etc) field
     }
-    export function PropUnsetFilter(prop: string) {
+    export function IsPropUnsetFilter(prop: string) {
         return `${prop}:any,${noRecursionHack}:unset`;
     }
 
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index cf9ed43e1..e579bfd8a 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -1143,30 +1143,6 @@ export namespace Docs {
 }
 
 export namespace DocUtils {
-    export function Excluded(d: Doc, docFilters: string[]) {
-        const filterFacets: { [key: string]: { [value: string]: string } } = {}; // maps each filter key to an object with value=>modifier fields
-        docFilters.forEach(filter => {
-            const fields = filter.split(':');
-            const key = fields[0];
-            const value = fields[1];
-            const modifiers = fields[2];
-            if (!filterFacets[key]) {
-                filterFacets[key] = {};
-            }
-            filterFacets[key][value] = modifiers;
-        });
-
-        if (d.z) return false;
-        for (const facetKey of Object.keys(filterFacets)) {
-            const facet = filterFacets[facetKey];
-            const xs = Object.keys(facet).filter(value => facet[value] === 'x');
-            const failsNotEqualFacets = xs?.some(value => Doc.matchFieldValue(d, facetKey, value));
-            if (failsNotEqualFacets) {
-                return true;
-            }
-        }
-        return false;
-    }
     /**
      * @param docs
      * @param docFilters
@@ -1200,7 +1176,7 @@ export namespace DocUtils {
                       return false;
                   }
 
-                  for (const facetKey of Object.keys(filterFacets).filter(fkey => fkey !== 'cookies')) {
+                  for (const facetKey of Object.keys(filterFacets).filter(fkey => fkey !== 'cookies' && fkey !== Utils.noDragsDocFilter.split(':')[0])) {
                       const facet = filterFacets[facetKey];
 
                       // facets that match some value in the field of the document (e.g. some text field)
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 5479929bd..e33bb77de 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -88,11 +88,11 @@ export function CollectionSubView<X>(moreProps?: X) {
         }
         collectionFilters = () => this._focusFilters ?? StrListCast(this.props.Document._docFilters);
         collectionRangeDocFilters = () => this._focusRangeFilters ?? Cast(this.props.Document._docRangeFilters, listSpec('string'), []);
+        // child filters apply to the descendants of the documents in this collection
         childDocFilters = () => [...(this.props.docFilters?.().filter(f => Utils.IsRecursiveFilter(f)) || []), ...this.collectionFilters()];
+        // unrecursive filters apply to the documents in the collection, but no their children.  See Utils.noRecursionHack
         unrecursiveDocFilters = () => [...(this.props.docFilters?.().filter(f => !Utils.IsRecursiveFilter(f)) || [])];
         childDocRangeFilters = () => [...(this.props.docRangeFilters?.() || []), ...this.collectionRangeDocFilters()];
-        IsFiltered = () =>
-            this.collectionFilters().length || this.collectionRangeDocFilters().length ? 'hasFilter' : this.props.docFilters?.().filter(f => Utils.IsRecursiveFilter(f)).length || this.props.docRangeFilters().length ? 'inheritsFilter' : undefined;
         searchFilterDocs = () => this.props.searchFilterDocs?.() ?? DocListCast(this.props.Document._searchFilterDocs);
         @computed.struct get childDocs() {
             TraceMobx();
@@ -122,13 +122,11 @@ export function CollectionSubView<X>(moreProps?: X) {
                 return childDocs.filter(cd => !cd.cookies); // remove any documents that require a cookie if there are no filters to provide one
             }
 
-            // console.log(Doc.ActiveDashboard._docFilters);
-            // if (!this.props.Document._docFilters && this.props.Document.currentFilter) {
-            //     (this.props.Document.currentFilter as Doc).filterBoolean = (this.props.ContainingCollectionDoc?.currentFilter as Doc)?.filterBoolean;
-            // }
             const docsforFilter: Doc[] = [];
             childDocs.forEach(d => {
-                // if (DocUtils.Excluded(d, docFilters)) return;
+                // dragging facets
+                const dragged = this.props.docFilters?.().some(f => f.includes(Utils.noDragsDocFilter));
+                if (dragged && DragManager.docsBeingDragged.includes(d)) return false;
                 let notFiltered = d.z || Doc.IsSystem(d) || DocUtils.FilterDocs([d], this.unrecursiveDocFilters(), docRangeFilters, viewSpecScript, this.props.Document).length > 0;
                 if (notFiltered) {
                     notFiltered = (!searchDocs.length || searchDocs.includes(d)) && DocUtils.FilterDocs([d], childDocFilters, docRangeFilters, viewSpecScript, this.props.Document).length > 0;
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index f3074543b..45a5e30ff 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -109,8 +109,6 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
     @observable _hLines: number[] | undefined;
     @observable _vLines: number[] | undefined;
     @observable _firstRender = true; // this turns off rendering of the collection's content so that there's instant feedback when a tab is switched of what content will be shown.
-    @observable _pullCoords: number[] = [0, 0];
-    @observable _pullDirection: string = '';
     @observable _showAnimTimeline = false;
     @observable _clusterSets: Doc[][] = [];
     @observable _deleteList: DocumentView[] = [];
@@ -465,20 +463,23 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
 
     getClusterColor = (doc: Opt<Doc>, props: Opt<DocumentViewProps>, property: string) => {
         let styleProp = this.props.styleProvider?.(doc, props, property); // bcz: check 'props'  used to be renderDepth + 1
-        if (property !== StyleProp.BackgroundColor) return styleProp;
-        const cluster = NumCast(doc?.cluster);
-        if (this.Document._useClusters) {
-            if (this._clusterSets.length <= cluster) {
-                setTimeout(() => doc && this.updateCluster(doc));
-            } else {
-                // choose a cluster color from a palette
-                const colors = ['#da42429e', '#31ea318c', 'rgba(197, 87, 20, 0.55)', '#4a7ae2c4', 'rgba(216, 9, 255, 0.5)', '#ff7601', '#1dffff', 'yellow', 'rgba(27, 130, 49, 0.55)', 'rgba(0, 0, 0, 0.268)'];
-                styleProp = colors[cluster % colors.length];
-                const set = this._clusterSets[cluster]?.filter(s => s.backgroundColor);
-                // override the cluster color with an explicitly set color on a non-background document.  then override that with an explicitly set color on a background document
-                set?.map(s => (styleProp = StrCast(s.backgroundColor)));
-            }
-        } //else if (doc && NumCast(doc.group, -1) !== -1) styleProp = "gray";
+        switch (property) {
+            case StyleProp.BackgroundColor:
+                const cluster = NumCast(doc?.cluster);
+                if (this.Document._useClusters) {
+                    if (this._clusterSets.length <= cluster) {
+                        setTimeout(() => doc && this.updateCluster(doc));
+                    } else {
+                        // choose a cluster color from a palette
+                        const colors = ['#da42429e', '#31ea318c', 'rgba(197, 87, 20, 0.55)', '#4a7ae2c4', 'rgba(216, 9, 255, 0.5)', '#ff7601', '#1dffff', 'yellow', 'rgba(27, 130, 49, 0.55)', 'rgba(0, 0, 0, 0.268)'];
+                        styleProp = colors[cluster % colors.length];
+                        const set = this._clusterSets[cluster]?.filter(s => s.backgroundColor);
+                        // override the cluster color with an explicitly set color on a non-background document.  then override that with an explicitly set color on a background document
+                        set?.map(s => (styleProp = StrCast(s.backgroundColor)));
+                    }
+                }
+                break;
+        }
         return styleProp;
     };
 
@@ -523,17 +524,13 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
                     case InkTool.Pen:
                         break; // the GestureOverlay handles ink stroke input -- either as gestures, or drying as ink strokes that are added to document views
                     case InkTool.Eraser:
-                        document.addEventListener('pointermove', this.onEraserMove);
-                        document.addEventListener('pointerup', this.onEraserUp);
                         this._batch = UndoManager.StartBatch('collectionErase');
-                        e.stopPropagation();
-                        e.preventDefault();
+                        setupMoveUpEvents(this, e, this.onEraserMove, this.onEraserUp, emptyFunction);
                         break;
                     case InkTool.None:
                         if (!(this.props.layoutEngine?.() || StrCast(this.layoutDoc._layoutEngine))) {
                             this._hitCluster = this.pickCluster(this.getTransform().transformPoint(e.clientX, e.clientY));
-                            document.addEventListener('pointermove', this.onPointerMove);
-                            document.addEventListener('pointerup', this.onPointerUp);
+                            setupMoveUpEvents(this, e, this.onPointerMove, emptyFunction, emptyFunction, false);
                         }
                         break;
                 }
@@ -698,23 +695,9 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
     };
     @action
     onEraserUp = (e: PointerEvent): void => {
-        if (!InteractionUtils.IsType(e, InteractionUtils.TOUCHTYPE)) {
-            document.removeEventListener('pointermove', this.onEraserMove);
-            document.removeEventListener('pointerup', this.onEraserUp);
-            this._deleteList.forEach(ink => ink.props.removeDocument?.(ink.rootDoc));
-            this._deleteList = [];
-            this._batch?.end();
-        }
-    };
-
-    @action
-    onPointerUp = (e: PointerEvent): void => {
-        if (!InteractionUtils.IsType(e, InteractionUtils.TOUCHTYPE)) {
-            document.removeEventListener('pointermove', this.onPointerMove);
-            document.removeEventListener('pointerup', this.onPointerUp);
-            this.removeMoveListeners();
-            this.removeEndListeners();
-        }
+        this._deleteList.forEach(ink => ink.props.removeDocument?.(ink.rootDoc));
+        this._deleteList = [];
+        this._batch?.end();
     };
 
     onClick = (e: React.MouseEvent) => {
@@ -752,46 +735,42 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
      *  However, if Shift is held, then no segmentation is done -- instead any intersected stroke is deleted in its entirety.
      */
     @action
-    onEraserMove = (e: PointerEvent) => {
+    onEraserMove = (e: PointerEvent, down: number[], delta: number[]) => {
         const currPoint = { X: e.clientX, Y: e.clientY };
-        this.getEraserIntersections({ X: this._lastX, Y: this._lastY }, currPoint).forEach(intersect => {
+        this.getEraserIntersections({ X: currPoint.X - delta[0], Y: currPoint.Y - delta[1] }, currPoint).forEach(intersect => {
             if (!this._deleteList.includes(intersect.inkView)) {
                 this._deleteList.push(intersect.inkView);
                 SetActiveInkWidth(StrCast(intersect.inkView.rootDoc.strokeWidth?.toString()) || '1');
                 SetActiveInkColor(StrCast(intersect.inkView.rootDoc.color?.toString()) || 'black');
                 // create a new curve by appending all curves of the current segment together in order to render a single new stroke.
-                !e.shiftKey &&
+                if (!e.shiftKey) {
                     this.segmentInkStroke(intersect.inkView, intersect.t).forEach(segment =>
                         GestureOverlay.Instance.dispatchGesture(
                             GestureUtils.Gestures.Stroke,
                             segment.reduce((data, curve) => [...data, ...curve.points.map(p => intersect.inkView.ComponentView?.ptToScreen?.({ X: p.x, Y: p.y }) ?? { X: 0, Y: 0 })], [] as PointData[])
                         )
                     );
+                }
                 // Lower ink opacity to give the user a visual indicator of deletion.
                 intersect.inkView.layoutDoc.opacity = 0.5;
+                intersect.inkView.layoutDoc.dontIntersect = true;
             }
         });
-        this._lastX = currPoint.X;
-        this._lastY = currPoint.Y;
-
-        e.stopPropagation(); // doesn't actually stop propagation since all our listeners are listening to events on 'document'  however it does mark the event as cancelBubble=true which we test for in the move event handlers
-        e.preventDefault();
+        return false;
     };
 
     @action
-    onPointerMove = (e: PointerEvent): void => {
-        if (InteractionUtils.IsType(e, InteractionUtils.PENTYPE)) return;
+    onPointerMove = (e: PointerEvent): boolean => {
+        if (InteractionUtils.IsType(e, InteractionUtils.PENTYPE)) return false;
         if (InteractionUtils.IsType(e, InteractionUtils.TOUCHTYPE)) {
             Doc.ActiveTool = InkTool.None;
             if (this.props.isContentActive(true)) e.stopPropagation();
         } else if (!e.cancelBubble) {
             if (this.tryDragCluster(e, this._hitCluster)) {
-                document.removeEventListener('pointermove', this.onPointerMove);
-                document.removeEventListener('pointerup', this.onPointerUp);
+                return true;
             } else this.pan(e);
-            e.stopPropagation(); // doesn't actually stop propagation since all our listeners are listening to events on 'document'  however it does mark the event as cancelBubble=true which we test for in the move event handlers
-            e.preventDefault();
         }
+        return false;
     };
 
     /**
@@ -801,6 +780,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
     getEraserIntersections = (lastPoint: { X: number; Y: number }, currPoint: { X: number; Y: number }) => {
         const eraserMin = { X: Math.min(lastPoint.X, currPoint.X), Y: Math.min(lastPoint.Y, currPoint.Y) };
         const eraserMax = { X: Math.max(lastPoint.X, currPoint.X), Y: Math.max(lastPoint.Y, currPoint.Y) };
+
         return this.childDocs
             .map(doc => DocumentManager.Instance.getDocumentView(doc, this.props.CollectionView))
             .filter(inkView => inkView?.ComponentView instanceof InkingStroke)
@@ -888,7 +868,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
         const tVals: number[] = [];
         // Iterating through all ink strokes in the current freeform collection.
         this.childDocs
-            .filter(doc => doc.type === DocumentType.INK)
+            .filter(doc => doc.type === DocumentType.INK && !doc.dontIntersect)
             .forEach(doc => {
                 const otherInk = DocumentManager.Instance.getDocumentView(doc, this.props.CollectionView)?.ComponentView as InkingStroke;
                 const { inkData: otherInkData } = otherInk?.inkScaledData() ?? { inkData: [] };
@@ -919,7 +899,6 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
                         e.stopPropagation(); // doesn't actually stop propagation since all our listeners are listening to events on 'document'  however it does mark the event as cancelBubble=true which we test for in the move event handlers
                         e.preventDefault();
                         document.removeEventListener('pointermove', this.onPointerMove);
-                        document.removeEventListener('pointerup', this.onPointerUp);
                         return;
                     }
                     // TODO: nda - this allows us to pan collections with finger -> only want to do this when collection is selected'
@@ -967,13 +946,6 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
                         const centerY = Math.min(pt1.clientY, pt2.clientY) + Math.abs(pt2.clientY - pt1.clientY) / 2;
                         // const transformed = this.getTransform().inverse().transformPoint(centerX, centerY);
 
-                        if (!this._pullDirection) {
-                            // if we are not bezel movement
-                            this.pan({ clientX: centerX, clientY: centerY });
-                        } else {
-                            this._pullCoords = [centerX, centerY];
-                        }
-
                         this._lastX = centerX;
                         this._lastY = centerY;
                     }
@@ -998,24 +970,6 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
                 const centerY = Math.min(pt1.clientY, pt2.clientY) + Math.abs(pt2.clientY - pt1.clientY) / 2;
                 this._lastX = centerX;
                 this._lastY = centerY;
-                const screenBox = this._mainCont?.getBoundingClientRect();
-
-                // determine if we are using a bezel movement
-                if (screenBox) {
-                    if (screenBox.right - centerX < 100) {
-                        this._pullCoords = [centerX, centerY];
-                        this._pullDirection = 'right';
-                    } else if (centerX - screenBox.left < 100) {
-                        this._pullCoords = [centerX, centerY];
-                        this._pullDirection = 'left';
-                    } else if (screenBox.bottom - centerY < 100) {
-                        this._pullCoords = [centerX, centerY];
-                        this._pullDirection = 'bottom';
-                    } else if (centerY - screenBox.top < 100) {
-                        this._pullCoords = [centerX, centerY];
-                        this._pullDirection = 'top';
-                    }
-                }
 
                 this.removeMoveListeners();
                 this.addMoveListeners();
@@ -1027,19 +981,6 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
     };
 
     cleanUpInteractions = () => {
-        switch (this._pullDirection) {
-            case 'left':
-            case 'right':
-            case 'top':
-            case 'bottom':
-                CollectionDockingView.AddSplit(Docs.Create.FreeformDocument([], { title: 'New Collection' }), this._pullDirection);
-        }
-
-        this._pullDirection = '';
-        this._pullCoords = [0, 0];
-
-        document.removeEventListener('pointermove', this.onPointerMove);
-        document.removeEventListener('pointerup', this.onPointerUp);
         this.removeMoveListeners();
         this.removeEndListeners();
     };
@@ -1380,7 +1321,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
         const { z, color, zIndex } = params.pair.layout;
         const { x, y, opacity } =
             this.Document._currentFrame === undefined
-                ? { x: params.pair.layout.x, y: params.pair.layout.y, opacity: this.props.styleProvider?.(params.pair.layout, this.props, StyleProp.Opacity) }
+                ? { x: params.pair.layout.x, y: params.pair.layout.y, opacity: this.props.childOpacity ? this.props.childOpacity() : this.props.styleProvider?.(params.pair.layout, this.props, StyleProp.Opacity) }
                 : CollectionFreeFormDocumentView.getValues(params.pair.layout, NumCast(this.Document._currentFrame));
         return {
             x: NumCast(x),
@@ -1915,7 +1856,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
                 getContainerTransform={this.getContainerTransform}
                 getTransform={this.getTransform}
                 isAnnotationOverlay={this.isAnnotationOverlay}>
-                <div className="marqueeView-div" ref={this._marqueeRef} style={{ opacity: this.props.dontRenderDocuments ? 0 : undefined }}>
+                <div className="marqueeView-div" ref={this._marqueeRef} style={{ opacity: this.props.dontRenderDocuments ? 0.7 : undefined }}>
                     {this.layoutDoc._backgroundGridShow ? (
                         <div>
                             <CollectionFreeFormBackgroundGrid // bcz : UGHH  don't know why, but if we don't wrap in a div, then PDF's don't render whenn taking snapshot of a dashboard and the background grid is on!!?
@@ -1996,15 +1937,6 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
                 {this._firstRender ? this.placeholder : this.marqueeView}
                 {this.props.noOverlay ? null : <CollectionFreeFormOverlayView elements={this.elementFunc} />}
 
-                <div
-                    className={'pullpane-indicator'}
-                    style={{
-                        display: this._pullDirection ? 'block' : 'none',
-                        top: clientRect ? (this._pullDirection === 'bottom' ? this._pullCoords[1] - clientRect.y : 0) : 'auto',
-                        left: clientRect ? (this._pullDirection === 'right' ? this._pullCoords[0] - clientRect.x : 0) : 'auto',
-                        width: clientRect ? (this._pullDirection === 'left' ? this._pullCoords[0] - clientRect.left : this._pullDirection === 'right' ? clientRect.right - this._pullCoords[0] : clientRect.width) : 0,
-                        height: clientRect ? (this._pullDirection === 'top' ? this._pullCoords[1] - clientRect.top : this._pullDirection === 'bottom' ? clientRect.bottom - this._pullCoords[1] : clientRect.height) : 0,
-                    }}></div>
                 {
                     // uncomment to show snap lines
                     <div className="snapLines" style={{ position: 'absolute', top: 0, left: 0, width: '100%', height: '100%', pointerEvents: 'none' }}>
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index 78f351f4f..e19e2d525 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -1,4 +1,4 @@
-import { action, computed, observable, trace } from 'mobx';
+import { action, computed, observable } from 'mobx';
 import { observer } from 'mobx-react';
 import { Doc, Opt } from '../../../fields/Doc';
 import { List } from '../../../fields/List';
@@ -6,13 +6,12 @@ import { listSpec } from '../../../fields/Schema';
 import { ComputedField } from '../../../fields/ScriptField';
 import { Cast, NumCast, StrCast } from '../../../fields/Types';
 import { TraceMobx } from '../../../fields/util';
-import { DashColor, numberRange, OmitKeys } from '../../../Utils';
+import { numberRange } from '../../../Utils';
 import { DocumentManager } from '../../util/DocumentManager';
 import { SelectionManager } from '../../util/SelectionManager';
 import { Transform } from '../../util/Transform';
 import { CollectionFreeFormView } from '../collections/collectionFreeForm/CollectionFreeFormView';
 import { DocComponent } from '../DocComponent';
-import { InkingStroke } from '../InkingStroke';
 import { StyleProp } from '../StyleProvider';
 import './CollectionFreeFormDocumentView.scss';
 import { DocumentView, DocumentViewProps } from './DocumentView';
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index bcc55eab4..172adcafe 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -970,7 +970,11 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
     collectionFilters = () => StrListCast(this.props.Document._docFilters);
     collectionRangeDocFilters = () => StrListCast(this.props.Document._docRangeFilters);
     @computed get showFilterIcon() {
-        return this.collectionFilters().length || this.collectionRangeDocFilters().length ? 'hasFilter' : this.props.docFilters?.().filter(f => Utils.IsRecursiveFilter(f)).length || this.props.docRangeFilters().length ? 'inheritsFilter' : undefined;
+        return this.collectionFilters().length || this.collectionRangeDocFilters().length
+            ? 'hasFilter'
+            : this.props.docFilters?.().filter(f => Utils.IsRecursiveFilter(f) && f !== Utils.noDragsDocFilter).length || this.props.docRangeFilters().length
+            ? 'inheritsFilter'
+            : undefined;
     }
     rootSelected = (outsideReaction?: boolean) => this.props.isSelected(outsideReaction) || (this.props.Document.rootDocument && this.props.rootSelected?.(outsideReaction)) || false;
     panelHeight = () => this.props.PanelHeight() - this.headerMargin;
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index a3d501153..0ff15f93b 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -831,16 +831,15 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
     // stretches vertically or horizontally depending on video orientation so video fits full screen
     fullScreenSize() {
         if (this._videoRef && this._videoRef.videoHeight / this._videoRef.videoWidth > 1) {
-            return { height: '100%' };
-        } else {
-            return { width: '100%' };
+            //prettier-ignore
+            return ({ height: '100%' });
         }
+        //prettier-ignore
+        return ({ width: '100%' });
     }
 
     // for zoom slider, sets timeline waveform zoom
-    zoom = (zoom: number) => {
-        this.timeline?.setZoom(zoom);
-    };
+    zoom = (zoom: number) => this.timeline?.setZoom(zoom);
 
     // plays link
     playLink = (doc: Doc) => {
diff --git a/src/client/views/nodes/WebBox.scss b/src/client/views/nodes/WebBox.scss
index d8dd074a5..85986ff27 100644
--- a/src/client/views/nodes/WebBox.scss
+++ b/src/client/views/nodes/WebBox.scss
@@ -1,9 +1,11 @@
-@import "../global/globalCssVariables.scss";
-
+@import '../global/globalCssVariables.scss';
 
 .webBox {
     height: 100%;
-    position: relative;
+    width: 100%;
+    top: 0;
+    left: 0;
+    position: absolute;
     display: flex;
 
     .webBox-sideResizer {
@@ -84,7 +86,6 @@
             background: none;
         }
 
-
         .webBox-overlayCont {
             position: absolute;
             width: calc(100% - 40px);
@@ -95,7 +96,7 @@
             justify-content: center;
             align-items: center;
             overflow: hidden;
-            transition: left .5s;
+            transition: left 0.5s;
             pointer-events: all;
 
             .webBox-searchBar {
@@ -158,7 +159,7 @@
             left: 0;
             cursor: text;
             padding: 15px;
-            height: 100%
+            height: 100%;
         }
 
         .webBox-cont {
@@ -235,7 +236,7 @@
         height: 25px;
         align-items: center;
 
-        >svg {
+        > svg {
             margin: auto;
         }
     }
@@ -257,4 +258,4 @@
             }
         }
     }
-}
\ No newline at end of file
+}
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx
index ca9f363c1..6c2e42f86 100644
--- a/src/client/views/nodes/WebBox.tsx
+++ b/src/client/views/nodes/WebBox.tsx
@@ -1,5 +1,5 @@
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { action, computed, IReactionDisposer, observable, ObservableMap, reaction, runInAction } from 'mobx';
+import { action, computed, IReactionDisposer, observable, ObservableMap, reaction, runInAction, trace } from 'mobx';
 import { observer } from 'mobx-react';
 import * as WebRequest from 'web-request';
 import { Doc, DocListCast, HeightSym, Opt, WidthSym } from '../../../fields/Doc';
@@ -11,7 +11,7 @@ import { listSpec } from '../../../fields/Schema';
 import { Cast, ImageCast, NumCast, StrCast } from '../../../fields/Types';
 import { ImageField, WebField } from '../../../fields/URLField';
 import { TraceMobx } from '../../../fields/util';
-import { emptyFunction, getWordAtPoint, OmitKeys, returnFalse, returnOne, setupMoveUpEvents, smoothScroll, Utils } from '../../../Utils';
+import { emptyFunction, getWordAtPoint, OmitKeys, returnFalse, returnOne, setupMoveUpEvents, smoothScroll, StopEvent, Utils } from '../../../Utils';
 import { Docs, DocUtils } from '../../documents/Documents';
 import { ScriptingGlobals } from '../../util/ScriptingGlobals';
 import { SnappingManager } from '../../util/SnappingManager';
@@ -35,6 +35,7 @@ import { LinkDocPreview } from './LinkDocPreview';
 import { VideoBox } from './VideoBox';
 import './WebBox.scss';
 import React = require('react');
+import { DragManager } from '../../util/DragManager';
 const { CreateImage } = require('./WebBoxRenderer');
 const _global = (window /* browser */ || global) /* node */ as any;
 const htmlToText = require('html-to-text');
@@ -818,6 +819,56 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
         return this._showSidebar || this.layoutDoc._showSidebar ? true : false;
     }
 
+    @computed get webpage() {
+        const previewScale = this._previewNativeWidth ? 1 - this.sidebarWidth() / this._previewNativeWidth : 1;
+        const pointerEvents = this.layoutDoc._lockedPosition ? 'none' : (this.props.pointerEvents?.() as any);
+        const scale = previewScale * (this.props.NativeDimScaling?.() || 1);
+        const renderAnnotations = (docFilters?: () => string[]) => (
+            <CollectionFreeFormView
+                {...OmitKeys(this.props, ['NativeWidth', 'NativeHeight', 'setContentView']).omit}
+                renderDepth={this.props.renderDepth + 1}
+                isAnnotationOverlay={true}
+                fieldKey={this.annotationKey}
+                CollectionView={undefined}
+                setPreviewCursor={this.setPreviewCursor}
+                PanelWidth={this.panelWidth}
+                PanelHeight={this.panelHeight}
+                ScreenToLocalTransform={this.scrollXf}
+                NativeDimScaling={returnOne}
+                dropAction={'alias'}
+                docFilters={docFilters}
+                select={emptyFunction}
+                bringToFront={emptyFunction}
+                styleProvider={this.childStyleProvider}
+                whenChildContentsActiveChanged={this.whenChildContentsActiveChanged}
+                removeDocument={this.removeDocument}
+                moveDocument={this.moveDocument}
+                addDocument={this.addDocument}
+                childPointerEvents={this.props.isContentActive() ? 'all' : undefined}
+                pointerEvents={this.annotationPointerEvents}
+            />
+        );
+        return (
+            <div
+                className={'webBox-outerContent'}
+                ref={this._outerRef}
+                style={{
+                    height: `${100 / scale}%`,
+                    pointerEvents,
+                }}
+                onWheel={StopEvent} // block wheel events from propagating since they're handled by the iframe
+                onScroll={e => this.setDashScrollTop(this._outerRef.current?.scrollTop || 0)}
+                onPointerDown={this.onMarqueeDown}>
+                <div className={'webBox-innerContent'} style={{ height: this._webPageHasBeenRendered ? NumCast(this.scrollHeight, 50) : '100%', pointerEvents }}>
+                    {this.content}
+                    {<div style={{ display: DragManager.docsBeingDragged.length ? 'none' : undefined, mixBlendMode: 'multiply' }}>{renderAnnotations(this.transparentFilter)}</div>}
+                    {renderAnnotations(this.opaqueFilter)}
+                    {this.annotationLayer}
+                </div>
+            </div>
+        );
+    }
+
     @computed get searchUI() {
         return (
             <div className="webBox-ui" onPointerDown={e => e.stopPropagation()} style={{ display: this.props.isContentActive() ? 'flex' : 'none' }}>
@@ -859,9 +910,8 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
     panelHeight = () => this.props.PanelHeight() / (this.props.NativeDimScaling?.() || 1); // () => this._pageSizes.length && this._pageSizes[0] ? this._pageSizes[0].width : Doc.NativeWidth(this.Document);
     scrollXf = () => this.props.ScreenToLocalTransform().translate(0, NumCast(this.layoutDoc._scrollTop));
     anchorMenuClick = () => this._sidebarRef.current?.anchorMenuClick;
-    basicFilter = () => [...this.props.docFilters(), Utils.PropUnsetFilter('textInlineAnnotations')];
     transparentFilter = () => [...this.props.docFilters(), Utils.IsTransparentFilter()];
-    opaqueFilter = () => [...this.props.docFilters(), Utils.IsOpaqueFilter()];
+    opaqueFilter = () => [...this.props.docFilters(), Utils.noDragsDocFilter, ...(DragManager.docsBeingDragged.length ? [] : [Utils.IsOpaqueFilter()])];
     childStyleProvider = (doc: Doc | undefined, props: Opt<DocumentViewProps>, property: string): any => {
         if (doc instanceof Doc && property === StyleProp.PointerEvents) {
             if (doc.textInlineAnnotations) return 'none';
@@ -871,37 +921,11 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
     pointerEvents = () => (!this._draggingSidebar && this.props.isContentActive() && this.props.pointerEvents?.() !== 'none' && !MarqueeOptionsMenu.Instance.isShown() ? 'all' : SnappingManager.GetIsDragging() ? undefined : 'none');
     annotationPointerEvents = () => (this._isAnnotating || SnappingManager.GetIsDragging() ? 'all' : 'none');
     render() {
-        const pointerEvents = this.layoutDoc._lockedPosition ? 'none' : (this.props.pointerEvents?.() as any);
         const previewScale = this._previewNativeWidth ? 1 - this.sidebarWidth() / this._previewNativeWidth : 1;
+        const pointerEvents = this.layoutDoc._lockedPosition ? 'none' : (this.props.pointerEvents?.() as any);
         const scale = previewScale * (this.props.NativeDimScaling?.() || 1);
-        const renderAnnotations = (docFilters?: () => string[]) => (
-            <CollectionFreeFormView
-                {...OmitKeys(this.props, ['NativeWidth', 'NativeHeight', 'setContentView']).omit}
-                renderDepth={this.props.renderDepth + 1}
-                isAnnotationOverlay={true}
-                fieldKey={this.annotationKey}
-                CollectionView={undefined}
-                setPreviewCursor={this.setPreviewCursor}
-                PanelWidth={this.panelWidth}
-                PanelHeight={this.panelHeight}
-                ScreenToLocalTransform={this.scrollXf}
-                NativeDimScaling={returnOne}
-                dropAction={'alias'}
-                docFilters={docFilters || this.basicFilter}
-                dontRenderDocuments={docFilters ? false : true}
-                select={emptyFunction}
-                bringToFront={emptyFunction}
-                whenChildContentsActiveChanged={this.whenChildContentsActiveChanged}
-                removeDocument={this.removeDocument}
-                moveDocument={this.moveDocument}
-                addDocument={this.addDocument}
-                styleProvider={this.childStyleProvider}
-                childPointerEvents={this.props.isContentActive() ? 'all' : undefined}
-                pointerEvents={this.annotationPointerEvents}
-            />
-        );
         return (
-            <div className="webBox" ref={this._mainCont} style={{ pointerEvents: this.pointerEvents(), display: this.props.thumbShown?.() ? 'none' : undefined }}>
+            <div className="webBox" ref={this._mainCont} style={{ pointerEvents: this.pointerEvents(), display: !SnappingManager.GetIsDragging() && this.props.thumbShown?.() ? 'none' : undefined }}>
                 <div className="webBox-background" style={{ backgroundColor: this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor) }} />
                 <div
                     className="webBox-container"
@@ -911,27 +935,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
                         pointerEvents,
                     }}
                     onContextMenu={this.specificContextMenu}>
-                    <div
-                        className={'webBox-outerContent'}
-                        ref={this._outerRef}
-                        style={{
-                            height: `${100 / scale}%`,
-                            pointerEvents,
-                        }}
-                        onWheel={e => {
-                            e.stopPropagation();
-                            e.preventDefault();
-                        }} // block wheel events from propagating since they're handled by the iframe
-                        onScroll={e => this.setDashScrollTop(this._outerRef.current?.scrollTop || 0)}
-                        onPointerDown={this.onMarqueeDown}>
-                        <div className={'webBox-innerContent'} style={{ height: this._webPageHasBeenRendered ? NumCast(this.scrollHeight, 50) : '100%', pointerEvents }}>
-                            {this.content}
-                            <div style={{ mixBlendMode: 'multiply' }}>{renderAnnotations(this.transparentFilter)}</div>
-                            {renderAnnotations(this.opaqueFilter)}
-                            {SnappingManager.GetIsDragging() ? null : renderAnnotations()}
-                            {this.annotationLayer}
-                        </div>
-                    </div>
+                    {this.webpage}
                     {!this._marqueeing || !this._mainCont.current || !this._annotationLayer.current ? null : (
                         <div style={{ transformOrigin: 'top left', transform: `scale(${1 / scale})` }}>
                             <MarqueeAnnotator
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index 2c83082b7..a45edfbca 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -9,6 +9,7 @@ import { Cast, NumCast, StrCast } from '../../../fields/Types';
 import { TraceMobx } from '../../../fields/util';
 import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, emptyFunction, OmitKeys, smoothScroll, Utils } from '../../../Utils';
 import { DocUtils } from '../../documents/Documents';
+import { DragManager } from '../../util/DragManager';
 import { SelectionManager } from '../../util/SelectionManager';
 import { SharingManager } from '../../util/SharingManager';
 import { SnappingManager } from '../../util/SnappingManager';
@@ -487,9 +488,8 @@ export class PDFViewer extends React.Component<IViewerProps> {
     overlayTransform = () => this.scrollXf().scale(1 / NumCast(this.props.layoutDoc._viewScale, 1));
     panelWidth = () => this.props.PanelWidth() / (this.props.NativeDimScaling?.() || 1); // (this.Document.scrollHeight || Doc.NativeHeight(this.Document) || 0);
     panelHeight = () => this.props.PanelHeight() / (this.props.NativeDimScaling?.() || 1); // () => this._pageSizes.length && this._pageSizes[0] ? this._pageSizes[0].width : Doc.NativeWidth(this.Document);
-    basicFilter = () => [...this.props.docFilters(), Utils.PropUnsetFilter('textInlineAnnotations')];
     transparentFilter = () => [...this.props.docFilters(), Utils.IsTransparentFilter()];
-    opaqueFilter = () => [...this.props.docFilters(), Utils.IsOpaqueFilter()];
+    opaqueFilter = () => [...this.props.docFilters(), Utils.noDragsDocFilter, ...(DragManager.docsBeingDragged.length ? [] : [Utils.IsOpaqueFilter()])];
     childStyleProvider = (doc: Doc | undefined, props: Opt<DocumentViewProps>, property: string): any => {
         if (doc instanceof Doc && property === StyleProp.PointerEvents) {
             if (doc.textInlineAnnotations) return 'none';
@@ -498,56 +498,43 @@ export class PDFViewer extends React.Component<IViewerProps> {
         return this.props.styleProvider?.(doc, props, property);
     };
 
-    renderAnnotations = (docFilters?: () => string[], dontRender?: boolean) => (
-        <CollectionFreeFormView
-            {...OmitKeys(this.props, ['NativeWidth', 'NativeHeight', 'setContentView']).omit}
-            isAnnotationOverlay={true}
-            fieldKey={this.props.fieldKey + '-annotations'}
-            setPreviewCursor={this.setPreviewCursor}
-            PanelHeight={this.panelHeight}
-            PanelWidth={this.panelWidth}
-            dropAction={'alias'}
-            select={emptyFunction}
-            bringToFront={emptyFunction}
-            docFilters={docFilters || this.basicFilter}
-            styleProvider={this.childStyleProvider}
-            dontRenderDocuments={dontRender}
-            CollectionView={undefined}
-            ScreenToLocalTransform={this.overlayTransform}
-            renderDepth={this.props.renderDepth + 1}
-        />
+    renderAnnotations = (docFilters?: () => string[], mixBlendMode?: any, display?: string) => (
+        <div
+            className="pdfViewerDash-overlay"
+            style={{
+                mixBlendMode: mixBlendMode,
+                display: display,
+                transform: `scale(${NumCast(this.props.layoutDoc._viewScale, 1)})`,
+            }}>
+            <CollectionFreeFormView
+                {...OmitKeys(this.props, ['NativeWidth', 'NativeHeight', 'setContentView']).omit}
+                renderDepth={this.props.renderDepth + 1}
+                isAnnotationOverlay={true}
+                fieldKey={this.props.fieldKey + '-annotations'}
+                CollectionView={undefined}
+                setPreviewCursor={this.setPreviewCursor}
+                PanelHeight={this.panelHeight}
+                PanelWidth={this.panelWidth}
+                ScreenToLocalTransform={this.overlayTransform}
+                dropAction={'alias'}
+                docFilters={docFilters}
+                select={emptyFunction}
+                bringToFront={emptyFunction}
+                styleProvider={this.childStyleProvider}
+            />
+        </div>
     );
     @computed get overlayTransparentAnnotations() {
-        return this.renderAnnotations(this.transparentFilter, false);
+        return this.renderAnnotations(this.transparentFilter, 'multiply', DragManager.docsBeingDragged.length ? 'none' : undefined);
     }
     @computed get overlayOpaqueAnnotations() {
-        return this.renderAnnotations(this.opaqueFilter, false);
-    }
-    @computed get overlayClickableAnnotations() {
-        return <div style={{ height: NumCast(this.props.rootDoc.scrollHeight) }}>{this.renderAnnotations(undefined, true)}</div>;
+        return this.renderAnnotations(this.opaqueFilter, this.allAnnotations.some(anno => anno.mixBlendMode) ? 'hard-light' : undefined);
     }
     @computed get overlayLayer() {
         return (
             <div style={{ pointerEvents: SnappingManager.GetIsDragging() ? 'all' : 'none' }}>
-                <div
-                    className="pdfViewerDash-overlay"
-                    style={{
-                        pointerEvents: SnappingManager.GetIsDragging() ? 'all' : 'none',
-                        mixBlendMode: 'multiply',
-                        transform: `scale(${NumCast(this.props.layoutDoc._viewScale, 1)})`,
-                    }}>
-                    {this.overlayTransparentAnnotations}
-                </div>
-                <div
-                    className="pdfViewerDash-overlay"
-                    style={{
-                        pointerEvents: SnappingManager.GetIsDragging() ? 'all' : 'none',
-                        mixBlendMode: this.allAnnotations.some(anno => anno.mixBlendMode) ? 'hard-light' : undefined,
-                        transform: `scale(${NumCast(this.props.layoutDoc._viewScale, 1)})`,
-                    }}>
-                    {this.overlayOpaqueAnnotations}
-                    {this.overlayClickableAnnotations}
-                </div>
+                {this.overlayTransparentAnnotations}
+                {this.overlayOpaqueAnnotations}
             </div>
         );
     }
-- 
cgit v1.2.3-70-g09d2


From 3f5cbb9ae99b7ed33fa09c1d3cf5f27414881c00 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Fri, 26 Aug 2022 16:34:15 -0400
Subject: from last

---
 src/client/views/nodes/WebBox.tsx  | 2 +-
 src/client/views/pdf/PDFViewer.tsx | 4 +---
 2 files changed, 2 insertions(+), 4 deletions(-)

(limited to 'src/client/views/pdf/PDFViewer.tsx')

diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx
index 6c2e42f86..b9e8e7c6e 100644
--- a/src/client/views/nodes/WebBox.tsx
+++ b/src/client/views/nodes/WebBox.tsx
@@ -285,7 +285,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
             const windowHeight = this.props.PanelHeight() / (this.props.NativeDimScaling?.() || 1);
             const scrollTo = Utils.scrollIntoView(NumCast(doc.y), doc[HeightSym](), NumCast(this.layoutDoc._scrollTop), windowHeight, windowHeight * 0.1, Math.max(NumCast(doc.y) + doc[HeightSym](), this.getScrollHeight()));
             if (scrollTo !== undefined && this._initialScroll === undefined) {
-                const focusSpeed = smooth ? 500 : 0;
+                const focusSpeed = smooth ? NumCast(doc.focusSpeed, 500) : 0;
                 this.goTo(scrollTo, focusSpeed);
                 return focusSpeed;
             } else if (!this._webPageHasBeenRendered || !this.getScrollHeight() || this._initialScroll !== undefined) {
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index a45edfbca..f1f3bfc57 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -165,10 +165,8 @@ export class PDFViewer extends React.Component<IViewerProps> {
             const windowHeight = this.props.PanelHeight() / (this.props.NativeDimScaling?.() || 1);
             const scrollTo = doc.unrendered ? NumCast(doc.y) : Utils.scrollIntoView(NumCast(doc.y), doc[HeightSym](), NumCast(this.props.layoutDoc._scrollTop), windowHeight, 0.1 * windowHeight, NumCast(this.props.Document.scrollHeight));
             if (scrollTo !== undefined && scrollTo !== this.props.layoutDoc._scrollTop) {
-                focusSpeed = 500;
-
                 if (!this._pdfViewer) this._initialScroll = scrollTo;
-                else if (smooth) smoothScroll(focusSpeed, mainCont, scrollTo);
+                else if (smooth) smoothScroll((focusSpeed = NumCast(doc.focusSpeed, 500)), mainCont, scrollTo);
                 else this._mainCont.current?.scrollTo({ top: Math.abs(scrollTo || 0) });
             }
         } else {
-- 
cgit v1.2.3-70-g09d2


From fb873aed085f8e11231a231aac94d6fb3bd27683 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Mon, 29 Aug 2022 13:31:22 -0400
Subject: fixed being able to draw on web/pdfs.  adjusted default margins of
 stacking views.

---
 src/client/views/GlobalKeyHandler.ts                    | 8 ++++----
 src/client/views/collections/CollectionStackingView.tsx | 9 +++++----
 src/client/views/nodes/DocumentView.tsx                 | 1 +
 src/client/views/nodes/WebBox.tsx                       | 2 +-
 src/client/views/pdf/PDFViewer.tsx                      | 1 +
 5 files changed, 12 insertions(+), 9 deletions(-)

(limited to 'src/client/views/pdf/PDFViewer.tsx')

diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts
index 85f579975..88ce457c6 100644
--- a/src/client/views/GlobalKeyHandler.ts
+++ b/src/client/views/GlobalKeyHandler.ts
@@ -160,16 +160,16 @@ export class KeyManager {
                 break;
             case 'arrowleft':
                 UndoManager.RunInBatch(() => SelectionManager.Views().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge(-1, 0)), 'nudge left');
-                break;
+                return { stopPropagation: true, preventDefault: true };
             case 'arrowright':
                 UndoManager.RunInBatch(() => SelectionManager.Views().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge?.(1, 0)), 'nudge right');
-                break;
+                return { stopPropagation: true, preventDefault: true };
             case 'arrowup':
                 UndoManager.RunInBatch(() => SelectionManager.Views().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge?.(0, -1)), 'nudge up');
-                break;
+                return { stopPropagation: true, preventDefault: true };
             case 'arrowdown':
                 UndoManager.RunInBatch(() => SelectionManager.Views().map(dv => dv.props.CollectionFreeFormDocumentView?.().nudge?.(0, 1)), 'nudge down');
-                break;
+                return { stopPropagation: true, preventDefault: true };
         }
 
         return {
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index 7f142727c..cc006c734 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -80,13 +80,14 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
         return this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.HeaderMargin);
     }
     @computed get xMargin() {
-        return NumCast(this.layoutDoc._xMargin, 2 * Math.min(this.gridGap, 0.05 * this.props.PanelWidth()));
+        return NumCast(this.layoutDoc._xMargin, Math.min(3, 0.05 * this.props.PanelWidth()));
     }
     @computed get yMargin() {
-        return this.props.yPadding || NumCast(this.layoutDoc._yMargin, 5);
-    } // 2 * this.gridGap)); }
+        return this.props.yPadding || NumCast(this.layoutDoc._yMargin, Math.min(5, 0.05 * this.props.PanelWidth()));
+    }
+
     @computed get gridGap() {
-        return NumCast(this.layoutDoc._gridGap, 10);
+        return NumCast(this.layoutDoc._gridGap, 5);
     }
     // are we stacking or masonry?
     @computed get isStackingView() {
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 74143a731..01fadb48d 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -1346,6 +1346,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
                     style={{
                         background: isButton || thumb ? undefined : this.backgroundColor,
                         opacity: this.opacity,
+                        cursor: Doc.ActiveTool === InkTool.None ? 'grab' : 'crosshair',
                         color: StrCast(this.layoutDoc.color, 'inherit'),
                         fontFamily: StrCast(this.Document._fontFamily, 'inherit'),
                         fontSize: Cast(this.Document._fontSize, 'string', null),
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx
index b9e8e7c6e..2c5deba88 100644
--- a/src/client/views/nodes/WebBox.tsx
+++ b/src/client/views/nodes/WebBox.tsx
@@ -919,7 +919,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
         return this.props.styleProvider?.(doc, props, property);
     };
     pointerEvents = () => (!this._draggingSidebar && this.props.isContentActive() && this.props.pointerEvents?.() !== 'none' && !MarqueeOptionsMenu.Instance.isShown() ? 'all' : SnappingManager.GetIsDragging() ? undefined : 'none');
-    annotationPointerEvents = () => (this._isAnnotating || SnappingManager.GetIsDragging() ? 'all' : 'none');
+    annotationPointerEvents = () => (this._isAnnotating || SnappingManager.GetIsDragging() || Doc.ActiveTool !== InkTool.None ? 'all' : 'none');
     render() {
         const previewScale = this._previewNativeWidth ? 1 - this.sidebarWidth() / this._previewNativeWidth : 1;
         const pointerEvents = this.layoutDoc._lockedPosition ? 'none' : (this.props.pointerEvents?.() as any);
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index f1f3bfc57..53d969c0a 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -503,6 +503,7 @@ export class PDFViewer extends React.Component<IViewerProps> {
                 mixBlendMode: mixBlendMode,
                 display: display,
                 transform: `scale(${NumCast(this.props.layoutDoc._viewScale, 1)})`,
+                pointerEvents: Doc.ActiveTool !== InkTool.None ? 'all' : undefined,
             }}>
             <CollectionFreeFormView
                 {...OmitKeys(this.props, ['NativeWidth', 'NativeHeight', 'setContentView']).omit}
-- 
cgit v1.2.3-70-g09d2

