aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/documents/Documents.ts6
-rw-r--r--src/client/util/DocumentManager.ts2
-rw-r--r--src/client/views/DocumentDecorations.tsx6
-rw-r--r--src/client/views/MarqueeAnnotator.tsx6
-rw-r--r--src/client/views/OverlayView.tsx5
-rw-r--r--src/client/views/PropertiesView.tsx8
-rw-r--r--src/client/views/collections/CollectionDockingView.tsx2
-rw-r--r--src/client/views/collections/CollectionMenu.tsx1
-rw-r--r--src/client/views/collections/TabDocView.tsx5
-rw-r--r--src/client/views/collections/TreeView.tsx2
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx71
-rw-r--r--src/client/views/collections/collectionSchema/CollectionSchemaView.tsx21
-rw-r--r--src/client/views/nodes/AudioBox.tsx4
-rw-r--r--src/client/views/nodes/DocumentView.tsx2
-rw-r--r--src/client/views/nodes/KeyValuePair.scss4
-rw-r--r--src/client/views/nodes/KeyValuePair.tsx2
-rw-r--r--src/client/views/nodes/VideoBox.tsx12
-rw-r--r--src/client/views/nodes/WebBox.tsx1
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBox.tsx29
-rw-r--r--src/client/views/nodes/trails/PresBox.scss1
-rw-r--r--src/client/views/nodes/trails/PresBox.tsx24
-rw-r--r--src/client/views/nodes/trails/PresElementBox.tsx18
-rw-r--r--src/fields/Doc.ts9
23 files changed, 124 insertions, 117 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 5aa69e499..35747f746 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -450,7 +450,7 @@ export namespace Docs {
DocumentType.IMG,
{
layout: { view: ImageBox, dataField: defaultDataKey },
- options: {},
+ options: {freeform: '',},
},
],
[
@@ -464,7 +464,7 @@ export namespace Docs {
DocumentType.COL,
{
layout: { view: CollectionView, dataField: defaultDataKey },
- options: { _layout_fitWidth: true, _freeform_panX: 0, _freeform_panY: 0, _freeform_scale: 1 },
+ options: { _layout_fitWidth: true, freeform: '', _freeform_panX: 0, _freeform_panY: 0, _freeform_scale: 1 },
},
],
[
@@ -1035,7 +1035,7 @@ export namespace Docs {
// }
export function FreeformDocument(documents: Array<Doc>, options: DocumentOptions, id?: string) {
- const inst = InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _xPadding: 20, _yPadding: 20, freeform: '', ...options, _type_collection: CollectionViewType.Freeform }, id);
+ const inst = InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _xPadding: 20, _yPadding: 20, ...options, _type_collection: CollectionViewType.Freeform }, id);
documents.forEach(d => (d.embedContainer = inst));
return inst;
}
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index ea5770b6a..642ea26da 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -318,7 +318,7 @@ export function DocFocusOrOpen(doc: Doc, options: DocFocusOptions = { willZoomCe
if (dv && (!containingDoc || dv.props.docViewPath().lastElement()?.Document === containingDoc)) {
DocumentManager.Instance.showDocumentView(dv, options).then(() => dv && Doc.linkFollowHighlight(dv.rootDoc));
} else {
- const container = DocCast(containingDoc ?? doc.embedContainer);
+ const container = DocCast(containingDoc ?? doc.embedContainer ?? doc);
const showDoc = !Doc.IsSystem(container) ? container : doc;
options.toggleTarget = undefined;
DocumentManager.Instance.showDocument(showDoc, options, () => DocumentManager.Instance.showDocument(doc, { ...options, openLocation: undefined })).then(() => {
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 8077b9af1..beddc0e8a 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -10,7 +10,7 @@ import { AclAdmin, AclEdit, DataSym, Doc, DocListCast, Field, HeightSym, WidthSy
import { InkField } from '../../fields/InkField';
import { RichTextField } from '../../fields/RichTextField';
import { ScriptField } from '../../fields/ScriptField';
-import { Cast, NumCast, StrCast } from '../../fields/Types';
+import { Cast, DocCast, NumCast, StrCast } from '../../fields/Types';
import { GetEffectiveAcl } from '../../fields/util';
import { aggregateBounds, emptyFunction, numberValue, returnFalse, setupMoveUpEvents, Utils } from '../../Utils';
import { Docs } from '../documents/Documents';
@@ -189,7 +189,9 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
@action
onBackgroundMove = (dragTitle: boolean, e: PointerEvent): boolean => {
const dragDocView = SelectionManager.Views()[0];
- if (DocListCast(Doc.MyOverlayDocs.data).includes(dragDocView.rootDoc)) return false;
+ const containers = new Set<Doc|undefined>();
+ SelectionManager.Views().forEach(v => containers.add(DocCast(v.rootDoc.embedContainer)));
+ if (containers.size > 1) return false;
const { left, top } = dragDocView.getBounds() || { left: 0, top: 0 };
const dragData = new DragManager.DocumentDragData(
SelectionManager.Views().map(dv => dv.props.Document),
diff --git a/src/client/views/MarqueeAnnotator.tsx b/src/client/views/MarqueeAnnotator.tsx
index 1d6c94c13..c9555ab91 100644
--- a/src/client/views/MarqueeAnnotator.tsx
+++ b/src/client/views/MarqueeAnnotator.tsx
@@ -153,8 +153,8 @@ export class MarqueeAnnotator extends React.Component<MarqueeAnnotatorProps> {
annotationOn: this.props.rootDoc,
title: 'Annotation on ' + this.props.rootDoc.title,
});
- marqueeAnno.x = NumCast(this.props.docView.props.Document.freeform_panXMin) + (parseInt(anno.style.left || '0') - containerOffset[0]) / scale / NumCast(this.props.docView.props.Document._freeform_scale, 1);
- marqueeAnno.y = NumCast(this.props.docView.props.Document.freeform_panYMin) + (parseInt(anno.style.top || '0') - containerOffset[1]) / scale / NumCast(this.props.docView.props.Document._freeform_scale, 1) + NumCast(this.props.scrollTop);
+ marqueeAnno.x = NumCast(this.props.docView.props.Document.freeform_panX_min) + (parseInt(anno.style.left || '0') - containerOffset[0]) / scale / NumCast(this.props.docView.props.Document._freeform_scale, 1);
+ marqueeAnno.y = NumCast(this.props.docView.props.Document.freeform_panY_min) + (parseInt(anno.style.top || '0') - containerOffset[1]) / scale / NumCast(this.props.docView.props.Document._freeform_scale, 1) + NumCast(this.props.scrollTop);
marqueeAnno._height = parseInt(anno.style.height || '0') / scale / NumCast(this.props.docView.props.Document._freeform_scale, 1);
marqueeAnno._width = parseInt(anno.style.width || '0') / scale / NumCast(this.props.docView.props.Document._freeform_scale, 1);
anno.remove();
@@ -243,7 +243,7 @@ export class MarqueeAnnotator extends React.Component<MarqueeAnnotatorProps> {
this._top = Math.min(this._startY, this._startY + this._height);
this._width = Math.abs(this._width);
this._height = Math.abs(this._height);
- e.stopPropagation();
+ //e.stopPropagation(); // overlay documents are all 'active', yet they can be dragged. if we stop propagation, then they can be marqueed but not dragged. if we don't stop, then they will be marqueed and dragged, but the marquee will be zero width since the doc will move along with the cursor.
};
onSelectEnd = (e: PointerEvent) => {
diff --git a/src/client/views/OverlayView.tsx b/src/client/views/OverlayView.tsx
index 9baedae6d..00f9aa879 100644
--- a/src/client/views/OverlayView.tsx
+++ b/src/client/views/OverlayView.tsx
@@ -159,7 +159,7 @@ export class OverlayView extends React.Component {
}
removeOverlayDoc = (doc: Doc | Doc[]) => {
- (doc instanceof Doc ? [doc] : doc).forEach(doc => Doc.RemoveDocFromList(Doc.MyOverlayDocs, undefined, doc));
+ (doc instanceof Doc ? [doc] : doc).forEach(Doc.RemFromMyOverlay);
return true;
};
@@ -177,6 +177,7 @@ export class OverlayView extends React.Component {
offsety = 0;
const dref = React.createRef<HTMLDivElement>();
const onPointerMove = action((e: PointerEvent, down: number[]) => {
+ if (e.cancelBubble) return false; // if the overlay doc processed the move event (e.g., to pan its contents), then the event should be marked as canceled since propagation can't be stopped
if (e.buttons === 1) {
d.overlayX = e.clientX + offsetx;
d.overlayY = e.clientY + offsety;
@@ -196,7 +197,7 @@ export class OverlayView extends React.Component {
});
const onPointerDown = (e: React.PointerEvent) => {
- setupMoveUpEvents(this, e, onPointerMove, emptyFunction, emptyFunction);
+ setupMoveUpEvents(this, e, onPointerMove, emptyFunction, emptyFunction, false);
offsetx = NumCast(d.overlayX) - e.clientX;
offsety = NumCast(d.overlayY) - e.clientY;
};
diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx
index 75514a090..0c89f1a27 100644
--- a/src/client/views/PropertiesView.tsx
+++ b/src/client/views/PropertiesView.tsx
@@ -1623,8 +1623,8 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
</div>
);
}
- if (this.isPres) {
- const selectedItem: boolean = PresBox.Instance?.selectedArray.size > 0;
+ if (this.isPres && PresBox.Instance) {
+ const selectedItem: boolean = PresBox.Instance.selectedArray.size > 0;
const type = [DocumentType.AUDIO, DocumentType.VID].includes(DocCast(PresBox.Instance.activeItem?.annotationOn)?.type as any as DocumentType)
? (DocCast(PresBox.Instance.activeItem?.annotationOn)?.type as any as DocumentType)
: PresBox.targetRenderedDoc(PresBox.Instance.activeItem)?.type;
@@ -1636,8 +1636,8 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
<div className="propertiesView-name" style={{ borderBottom: 0 }}>
{this.editableTitle}
<div className="propertiesView-presSelected">
- <div className="propertiesView-selectedCount">{PresBox.Instance?.selectedArray.size} selected</div>
- <div className="propertiesView-selectedList">{PresBox.Instance?.listOfSelected}</div>
+ <div className="propertiesView-selectedCount">{PresBox.Instance.selectedArray.size} selected</div>
+ <div className="propertiesView-selectedList">{PresBox.Instance.listOfSelected}</div>
</div>
</div>
{!selectedItem ? null : (
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 76dadc76d..e9cc2c894 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -593,7 +593,7 @@ ScriptingGlobals.add(
case '<ScriptingRepl />': return OverlayView.Instance.addWindow(<ScriptingRepl />, { x: 300, y: 100, width: 200, height: 200, title: 'Scripting REPL' });
case "<UndoStack>": return OverlayView.Instance.addWindow(<UndoStack />, { x: 300, y: 100, width: 200, height: 200, title: 'Scripting REPL' });
}
- Doc.AddDocToList(Doc.MyOverlayDocs, undefined, doc);
+ Doc.AddToMyOverlay(doc);
}
},
'opens up document in location specified',
diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index 570d9c8fb..d2338d742 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -549,7 +549,6 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewMenu
@action
startRecording = () => {
const doc = Docs.Create.ScreenshotDocument({ title: 'screen recording', _layout_fitWidth: true, _width: 400, _height: 200, mediaState: 'pendingRecording' });
- //Doc.AddDocToList(Doc.MyOverlayDocs, undefined, doc);
CollectionDockingView.AddSplit(doc, OpenWhereMod.right);
};
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index 33fa434e1..b20d05433 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -292,13 +292,12 @@ export class TabDocView extends React.Component<TabDocViewProps> {
PresBox.Instance?.clearSelectedArray();
pinDoc && PresBox.Instance?.addToSelectedArray(pinDoc); //Update selected array
});
- if (
+ if ( // open the presentation trail if it's not already opened
!Array.from(CollectionDockingView.Instance?.tabMap ?? [])
.map(d => d.DashDoc)
.includes(curPres)
) {
- const docs = Cast(Doc.MyOverlayDocs.data, listSpec(Doc), []);
- if (docs.includes(curPres)) docs.splice(docs.indexOf(curPres), 1);
+ if (Doc.IsInMyOverlay(curPres)) Doc.RemFromMyOverlay(curPres);
CollectionDockingView.AddSplit(curPres, OpenWhereMod.right);
setTimeout(() => DocumentManager.Instance.showDocument(docList.lastElement(), { willPan: true }), 100); // keeps the pinned doc in view since the sidebar shifts things
}
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index f56eaee07..abbb0df4c 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -761,7 +761,7 @@ export class TreeView extends React.Component<TreeViewProps> {
const makeFolder = { script: ScriptField.MakeFunction(`scriptContext.makeFolder()`, { scriptContext: 'any' })!, icon: 'folder-plus', label: 'New Folder' };
const deleteItem = { script: ScriptField.MakeFunction(`scriptContext.deleteItem()`, { scriptContext: 'any' })!, icon: 'folder-plus', label: 'Delete' };
const folderOp = this.childDocs?.length ? [makeFolder] : [];
- const openEmbedding = { script: ScriptField.MakeFunction(`openDoc(getEmbedding(self), ${OpenWhere.addRight})`)!, icon: 'copy', label: 'Open Embedding' };
+ const openEmbedding = { script: ScriptField.MakeFunction(`openDoc(getEmbedding(self), ${OpenWhere.addRight})`)!, icon: 'copy', label: 'Open New Embedding' };
const focusDoc = { script: ScriptField.MakeFunction(`DocFocusOrOpen(self)`)!, icon: 'eye', label: 'Focus or Open' };
return [
...(this.props.contextMenuItems ?? []).filter(mi => (!mi.filter ? true : mi.filter.script.run({ doc: this.doc })?.result)),
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 9bf071cc0..3b5dd45d9 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -635,7 +635,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
case InkTool.None:
if (!(this.props.layoutEngine?.() || StrCast(this.layoutDoc._layoutEngine))) {
this._hitCluster = this.pickCluster(this.getTransform().transformPoint(e.clientX, e.clientY));
- setupMoveUpEvents(this, e, this.onPointerMove, emptyFunction, emptyFunction, this._hitCluster !== -1 ? true : false);
+ setupMoveUpEvents(this, e, this.onPointerMove, emptyFunction, emptyFunction, this._hitCluster !== -1 ? true : false, false);
}
break;
}
@@ -868,9 +868,14 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
Doc.ActiveTool = InkTool.None;
} else {
if (this.tryDragCluster(e, this._hitCluster)) {
+ e.stopPropagation(); // we're moving a cluster, so stop propagation and return true to end panning and let the document drag take over
return true;
}
- this.pan(e);
+ // pan the view if this is a regular collection, or it's an overlay and the overlay is zoomed (otherwise, there's nothing to pan)
+ if (!this.props.isAnnotationOverlay || (1 - NumCast(this.rootDoc._freeform_scale_min, 1)/ this.getLocalTransform().inverse().Scale)) {
+ this.pan(e);
+ e.stopPropagation(); // if we are actually panning, stop propagation -- this will preven things like the overlayView from dragging the document while we're panning
+ }
}
return false;
};
@@ -1023,12 +1028,12 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
if (deltaScale * invTransform.Scale > 20) {
deltaScale = 20 / invTransform.Scale;
}
- if (deltaScale < 1 && invTransform.Scale <= NumCast(this.rootDoc._freeform_scaleMin, 1) && this.isAnnotationOverlay) {
+ if (deltaScale < 1 && invTransform.Scale <= NumCast(this.rootDoc._freeform_scale_min, 1) && this.isAnnotationOverlay) {
this.setPan(0, 0);
return;
}
- if (deltaScale * invTransform.Scale < NumCast(this.rootDoc._freeform_scaleMin, 1) && this.isAnnotationOverlay) {
- deltaScale = NumCast(this.rootDoc._freeform_scaleMin, 1) / invTransform.Scale;
+ if (deltaScale * invTransform.Scale < NumCast(this.rootDoc._freeform_scale_min, 1) && this.isAnnotationOverlay) {
+ deltaScale = NumCast(this.rootDoc._freeform_scale_min, 1) / invTransform.Scale;
}
const localTransform = invTransform.scaleAbout(deltaScale, x, y);
@@ -1040,36 +1045,25 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
};
@action
- onPointerWheel = (e: React.WheelEvent): void => {
+ onPointerWheel = (e:React.WheelEvent): void => {
if (this.Document._isGroup || !this.isContentActive()) return; // group style collections neither pan nor zoom
PresBox.Instance?.pauseAutoPres();
- if (this.layoutDoc._Transform || DocListCast(Doc.MyOverlayDocs?.data).includes(this.props.Document) || this.props.Document.treeViewOutlineMode === TreeViewType.outline) return;
+ if (this.layoutDoc._Transform || this.props.Document.treeViewOutlineMode === TreeViewType.outline) return;
e.stopPropagation();
+ const docHeight = NumCast(this.rootDoc[Doc.LayoutFieldKey(this.rootDoc)+"_nativeHeight"], this.nativeHeight);
+ const scrollable = NumCast(this.layoutDoc[this.scaleFieldKey],1) ===1 && docHeight > this.props.PanelHeight() / this.nativeDimScaling ;
switch (!e.ctrlKey ? Doc.UserDoc().freeformScrollMode : freeformScrollMode.Pan) {
case freeformScrollMode.Pan:
// if ctrl is selected then zoom
- if (e.ctrlKey) {
- if (this.props.isContentActive(true)) {
- if (this.props.isAnnotationOverlayScrollable) {
- // bcz: zooming on a webbox doesn't get the correct coordinates here for unknown reasons.
- // so better to do nothing than having things jump around.
- } else this.zoom(e.screenX, e.screenY, e.deltaY);
- }
- } // otherwise pan
- else if (this.props.isContentActive(true)) {
- const dx = -e.deltaX;
- const dy = -e.deltaY;
- if (e.shiftKey) {
- !this.props.isAnnotationOverlayScrollable && this.scrollPan({ deltaX: dy, deltaY: 0 });
- } else {
- !this.props.isAnnotationOverlayScrollable && this.scrollPan({ deltaX: dx, deltaY: dy });
- }
+ if (!e.ctrlKey && this.props.isContentActive(true)) {
+ this.scrollPan({ deltaX: -e.deltaX, deltaY: e.shiftKey ? 0 :-Math.max(-1, Math.min(1,e.deltaY)) });
+ break;
}
- break;
default:
case freeformScrollMode.Zoom:
- if (this.props.isContentActive(true)) {
- !this.props.isAnnotationOverlayScrollable && this.zoom(e.clientX, e.clientY, e.deltaY); // if (!this.props.isAnnotationOverlay) // bcz: do we want to zoom in on images/videos/etc?
+ if ((e.ctrlKey || !scrollable) && this.props.isContentActive(true)) {
+ this.zoom(e.clientX, e.clientY,Math.max(-1, Math.min(1,e.deltaY))); // if (!this.props.isAnnotationOverlay) // bcz: do we want to zoom in on images/videos/etc?
+ e.preventDefault();
}
break;
}
@@ -1112,19 +1106,20 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
else if (ranges.yrange.max <= panY - panelHgtMin / 2) panY = ranges.yrange.min - (this.props.originTopLeft ? panelHgtMax / 2 : panelHgtMin / 2);
}
}
- if (!this.layoutDoc._lockedTransform || LightboxView.LightboxDoc || DocListCast(Doc.MyOverlayDocs?.data).includes(this.Document)) {
+ if (!this.layoutDoc._lockedTransform || LightboxView.LightboxDoc) {
this.setPanZoomTransition(panTime);
- const scale = this.getLocalTransform().inverse().Scale;
- const minScale = NumCast(this.rootDoc._freeform_scaleMin, 1);
- const minPanX = NumCast(this.rootDoc._freeform_panXMin, 0);
- const minPanY = NumCast(this.rootDoc._freeform_panYMin, 0);
- const newPanX = Math.min(minPanX + (1 - minScale / scale) * NumCast(this.rootDoc._freeform_panXMax, this.nativeWidth), Math.max(minPanX, panX));
+ const minScale = NumCast(this.rootDoc._freeform_scale_min, 1);
+ const scale = (1 - minScale/ this.getLocalTransform().inverse().Scale);
+ const minPanX = NumCast(this.rootDoc._freeform_panX_min, 0);
+ const minPanY = NumCast(this.rootDoc._freeform_panY_min, 0);
+ const maxPanX = NumCast(this.rootDoc._freeform_panX_max, this.nativeWidth);
+ const newPanX = Math.min(minPanX + scale *maxPanX, Math.max(minPanX, panX));
const fitYscroll = (((this.nativeHeight / this.nativeWidth) * this.props.PanelWidth() - this.props.PanelHeight()) * this.props.ScreenToLocalTransform().Scale) / minScale;
const nativeHeight = (this.props.PanelHeight() / this.props.PanelWidth() / (this.nativeHeight / this.nativeWidth)) * this.nativeHeight;
const maxScrollTop = this.nativeHeight / this.props.ScreenToLocalTransform().Scale - this.props.PanelHeight();
const maxPanY =
minPanY + // minPanY + scrolling introduced by view scaling + scrolling introduced by layout_fitWidth
- (1 - minScale / scale) * NumCast(this.rootDoc._panYMax, nativeHeight) +
+ scale* NumCast(this.rootDoc._panY_max, nativeHeight) +
(!this.props.getScrollHeight?.() ? fitYscroll : 0); // when not zoomed, scrolling is handled via a scrollbar, not panning
let newPanY = Math.max(minPanY, Math.min(maxPanY, panY));
if (false && NumCast(this.rootDoc.layout_scrollTop) && NumCast(this.rootDoc._freeform_scale, minScale) !== minScale) {
@@ -1971,6 +1966,12 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
lightboxPanelWidth = () => Math.max(0, this.props.PanelWidth() - 30);
lightboxPanelHeight = () => Math.max(0, this.props.PanelHeight() - 30);
lightboxScreenToLocal = () => this.props.ScreenToLocalTransform().translate(-15, -15);
+ onPassiveWheel = (e:WheelEvent) => {
+ const docHeight = NumCast(this.rootDoc[Doc.LayoutFieldKey(this.rootDoc)+"_nativeHeight"], this.nativeHeight);
+ const scrollable = NumCast(this.layoutDoc[this.scaleFieldKey],1) ===1 && docHeight > this.props.PanelHeight() / this.nativeDimScaling ;
+ this.props.isSelected() && !scrollable && e.preventDefault()
+ }
+ _oldWheel:any;
render() {
TraceMobx();
return (
@@ -1978,8 +1979,10 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
className="collectionfreeformview-container"
ref={r => {
this.createDashEventsTarget(r);
+ this._oldWheel?.removeEventListener('wheel', this.onPassiveWheel);
+ this._oldWheel= r;
// prevent wheel events from passivly propagating up through containers
- !this.props.isAnnotationOverlay && r?.addEventListener('wheel', (e: WheelEvent) => this.props.isSelected() && e.preventDefault(), { passive: false });
+ r?.addEventListener('wheel', this.onPassiveWheel, { passive: false });
}}
onWheel={this.onPointerWheel}
onClick={this.onClick}
diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
index 2a68f9b58..1cc48bebe 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
@@ -686,6 +686,12 @@ export class CollectionSchemaView extends CollectionSubView() {
);
}
+ onPassiveWheel = (e:WheelEvent) => {
+ // if scrollTop is 0, then don't let wheel trigger scroll on any container (which it would since onScroll won't be triggered on this)
+ if (!this._oldWheel.scrollTop && e.deltaY <= 0) e.preventDefault();
+ e.stopPropagation();
+ }
+ _oldWheel:any;
@computed get keysDropdown() {
return (
<div className="schema-key-search">
@@ -699,16 +705,11 @@ export class CollectionSchemaView extends CollectionSubView() {
</div>
<div
className="schema-key-list"
- ref={r =>
- r?.addEventListener(
- 'wheel', // if scrollTop is 0, then don't let wheel trigger scroll on any container (which it would since onScroll won't be triggered on this)
- (e: WheelEvent) => {
- if (!r.scrollTop && e.deltaY <= 0) e.preventDefault();
- e.stopPropagation();
- },
- { passive: false }
- )
- }>
+ ref={r => {
+ this._oldWheel?.removeEventListener('wheel', this.onPassiveWheel);
+ this._oldWheel= r;
+ r?.addEventListener('wheel', this.onPassiveWheel, { passive: false } );
+ }}>
{this._menuKeys.map(key => (
<div
className="schema-search-result"
diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx
index 410e0bbdc..0cb849923 100644
--- a/src/client/views/nodes/AudioBox.tsx
+++ b/src/client/views/nodes/AudioBox.tsx
@@ -362,10 +362,10 @@ export class AudioBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
Doc.GetProto(newDoc).recordingSource = this.dataDoc;
Doc.GetProto(newDoc).recordingStart = ComputedField.MakeFunction(`self.recordingSource["${this.fieldKey}-recordingStart"]`);
Doc.GetProto(newDoc).mediaState = ComputedField.MakeFunction('self.recordingSource.mediaState');
- if (DocListCast(Doc.MyOverlayDocs?.data).includes(this.rootDoc)) {
+ if (Doc.IsInMyOverlay(this.rootDoc)) {
newDoc.overlayX = this.rootDoc.x;
newDoc.overlayY = NumCast(this.rootDoc.y) + NumCast(this.rootDoc._height);
- Doc.AddDocToList(Doc.MyOverlayDocs, undefined, newDoc);
+ Doc.AddToMyOverlay(newDoc);
} else {
this.props.addDocument?.(newDoc);
}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 10ef1e6af..84f82a4b9 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -527,7 +527,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
!this.Document.ignoreClick &&
e.button === 0 &&
this.pointerEvents !== 'none' &&
- !DocListCast(Doc.MyOverlayDocs?.data).includes(this.layoutDoc)
+ !Doc.IsInMyOverlay(this.layoutDoc)
) {
e.stopPropagation();
// don't preventDefault anymore. Goldenlayout, PDF text selection and RTF text selection all need it to go though
diff --git a/src/client/views/nodes/KeyValuePair.scss b/src/client/views/nodes/KeyValuePair.scss
index 2b4867321..57d36932e 100644
--- a/src/client/views/nodes/KeyValuePair.scss
+++ b/src/client/views/nodes/KeyValuePair.scss
@@ -19,7 +19,6 @@
position: relative;
margin: 0;
}
- .keyValuePair-keyFieldMod,
.keyValuePair-keyField {
width: 100%;
margin-left: 20px;
@@ -28,9 +27,6 @@
overflow: auto;
display: inline;
}
- .keyValuePair-keyFieldMod {
- margin-left: 35px;
- }
}
}
.keyValuePair-td-value {
diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx
index 509bb667e..91df928c4 100644
--- a/src/client/views/nodes/KeyValuePair.tsx
+++ b/src/client/views/nodes/KeyValuePair.tsx
@@ -109,7 +109,7 @@ export class KeyValuePair extends React.Component<KeyValuePairProps> {
X
</button>
<input className="keyValuePair-td-key-check" type="checkbox" style={hover} onChange={this.handleCheck} ref={this.checkbox} />
- <div className={`keyValuePair-keyField${props.fieldKey.includes('_') ? 'Mod' : ''}`} style={{ color: keyStyle }}>
+ <div className='keyValuePair-keyField' style={{ marginLeft: 35 * (props.fieldKey.match(/_/g)?.length ||0), color: keyStyle }}>
{'('.repeat(parenCount)}
{props.fieldKey}
{')'.repeat(parenCount)}
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index 3cfc3d696..9cf929679 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -870,7 +870,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
}),
returnFalse,
() => MarqueeAnnotator.clearAnnotations(this._savedAnnotations),
- false
+ false, false
);
}
};
@@ -1026,13 +1026,13 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
croppingProto.videoCrop = true;
croppingProto.layout_currentTimecode = this.layoutDoc._layout_currentTimecode;
croppingProto.freeform_scale = viewScale;
- croppingProto.freeform_scaleMin = viewScale;
+ croppingProto.freeform_scale_min = viewScale;
croppingProto.freeform_ = anchx / viewScale;
croppingProto.freeform_panY = anchy / viewScale;
- croppingProto.freeform_panXMin = anchx / viewScale;
- croppingProto.freeform_panXMax = anchw / viewScale;
- croppingProto.freeform_panYMin = anchy / viewScale;
- croppingProto.freeform_panYMax = anchh / viewScale;
+ croppingProto.freeform_panX_min = anchx / viewScale;
+ croppingProto.freeform_panX_max = anchw / viewScale;
+ croppingProto.freeform_panY_min = anchy / viewScale;
+ croppingProto.freeform_panY_max = anchh / viewScale;
if (addCrop) {
DocUtils.MakeLink(region, cropping, { link_relationship: 'cropped image' });
}
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx
index 437079ca4..48808dbad 100644
--- a/src/client/views/nodes/WebBox.tsx
+++ b/src/client/views/nodes/WebBox.tsx
@@ -745,6 +745,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
ref={action((r: HTMLIFrameElement | null) => (this._iframe = r))}
src={url}
onLoad={this.iframeLoaded}
+ scrolling="no" // ugh.. on windows, I get an inner scroll bar for the iframe's body even though the scrollHeight should be set to the full height of the document.
// the 'allow-top-navigation' and 'allow-top-navigation-by-user-activation' attributes are left out to prevent iframes from redirecting the top-level Dash page
// sandbox={"allow-forms allow-modals allow-orientation-lock allow-pointer-lock allow-popups allow-popups-to-escape-sandbox allow-presentation allow-same-origin allow-scripts"} />;
sandbox={`${this.layoutDoc.allowScripts ? 'allow-scripts' : ''} allow-forms allow-modals allow-orientation-lock allow-pointer-lock allow-popups allow-popups-to-escape-sandbox allow-presentation allow-same-origin`}
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index e85835002..fb0c0d2ab 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -917,10 +917,10 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
data_nativeWidth: result.nativeWidth,
data_nativeHeight: result.nativeHeight,
});
- if (DocListCast(Doc.MyOverlayDocs?.data).includes(this.rootDoc)) {
+ if (Doc.IsInMyOverlay(this.rootDoc)) {
newDoc.overlayX = this.rootDoc.x;
newDoc.overlayY = NumCast(this.rootDoc.y) + NumCast(this.rootDoc._height);
- Doc.AddDocToList(Doc.MyOverlayDocs, undefined, newDoc);
+ Doc.AddToMyOverlay(newDoc);
} else {
this.props.addDocument?.(newDoc);
}
@@ -2000,6 +2000,14 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
return this.props.fieldKey + (usePath && (!usePath.includes(':hover') || this._isHovering) ? `_${usePath.replace(':hover', '')}` : '');
}
@observable _isHovering = false;
+ onPassiveWheel = (e:WheelEvent) => {
+ // if scrollTop is 0, then don't let wheel trigger scroll on any container (which it would since onScroll won't be triggered on this)
+ if (this.props.isContentActive() && !this.props.allowScroll) {
+ if (!NumCast(this.layoutDoc._layout_scrollTop) && e.deltaY <= 0) e.preventDefault();
+ e.stopPropagation();
+ }
+ }
+ _oldWheel:any;
render() {
TraceMobx();
const active = this.props.isContentActive() || this.props.isSelected();
@@ -2019,18 +2027,11 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
className="formattedTextBox"
onPointerEnter={action(() => (this._isHovering = true))}
onPointerLeave={action(() => (this._isHovering = false))}
- ref={r =>
- r?.addEventListener(
- 'wheel', // if scrollTop is 0, then don't let wheel trigger scroll on any container (which it would since onScroll won't be triggered on this)
- (e: WheelEvent) => {
- if (this.props.isContentActive() && !this.props.allowScroll) {
- if (!NumCast(this.layoutDoc._layout_scrollTop) && e.deltaY <= 0) e.preventDefault();
- e.stopPropagation();
- }
- },
- { passive: false }
- )
- }
+ ref={r => {
+ this._oldWheel?.removeEventListener('wheel', this.onPassiveWheel);
+ this._oldWheel= r;
+ r?.addEventListener('wheel', this.onPassiveWheel, { passive: false } );
+ }}
style={{
...(this.props.dontScale
? {}
diff --git a/src/client/views/nodes/trails/PresBox.scss b/src/client/views/nodes/trails/PresBox.scss
index eb91c82f3..bf56b4d9e 100644
--- a/src/client/views/nodes/trails/PresBox.scss
+++ b/src/client/views/nodes/trails/PresBox.scss
@@ -951,6 +951,7 @@
margin-right: unset;
height: 100%;
position: relative;
+ user-select: none;
}
select {
diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx
index 14d463a6b..913018b69 100644
--- a/src/client/views/nodes/trails/PresBox.tsx
+++ b/src/client/views/nodes/trails/PresBox.tsx
@@ -196,7 +196,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
this.turnOffEdit(true);
this._disposers.selection = reaction(
() => SelectionManager.Views(),
- views => views.some(view => view.props.Document === this.rootDoc) && this.updateCurrentPresentation()
+ views => (!PresBox.Instance || views.some(view => view.props.Document === this.rootDoc)) && this.updateCurrentPresentation(),
+ {fireImmediately:true}
);
this._disposers.editing = reaction(
() => this.layoutDoc.presStatus === PresStatus.Edit,
@@ -832,7 +833,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
}
});
LightboxView.SetLightboxDoc(undefined);
- Doc.RemoveDocFromList(Doc.MyOverlayDocs, undefined, this.rootDoc);
+ Doc.RemFromMyOverlay(this.rootDoc);
return PresStatus.Edit;
};
};
@@ -928,8 +929,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
return PresBox.OpenPresMinimized(this.rootDoc, [pt[0] + (this.props.PanelWidth() - 250), pt[1] + 10]);
};
exitMinimize = () => {
- if (DocListCast(Doc.MyOverlayDocs?.data).includes(this.layoutDoc)) {
- Doc.RemoveDocFromList(Doc.MyOverlayDocs, undefined, this.rootDoc);
+ if (Doc.IsInMyOverlay(this.layoutDoc)) {
+ Doc.RemFromMyOverlay(this.rootDoc);
CollectionDockingView.AddSplit(this.rootDoc, OpenWhereMod.right);
}
return PresStatus.Edit;
@@ -941,7 +942,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
doc.overlayY = pt[1];
doc._height = 30;
doc._width = PresBox.minimizedWidth;
- Doc.AddDocToList(Doc.MyOverlayDocs, undefined, doc);
+ Doc.AddToMyOverlay(doc);
PresBox.Instance?.initializePresState(PresBox.Instance.itemIndex);
return (doc.presStatus = PresStatus.Manual);
}
@@ -1158,7 +1159,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
}
break;
case 'Escape':
- if (DocListCast(Doc.MyOverlayDocs?.data).includes(this.layoutDoc)) {
+ if (Doc.IsInMyOverlay(this.layoutDoc)) {
this.exitClicked();
} else if (this.layoutDoc.presStatus === PresStatus.Edit) {
this.clearSelectedArray();
@@ -2130,10 +2131,9 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
const propTitle = SettingsManager.propertiesWidth > 0 ? 'Close Presentation Panel' : 'Open Presentation Panel';
const mode = StrCast(this.rootDoc._type_collection) as CollectionViewType;
const isMini: boolean = this.toolbarWidth <= 100;
- const inOverlay = DocListCast(Doc.MyOverlayDocs?.data).includes(this.layoutDoc);
const activeColor = Colors.LIGHT_BLUE;
const inactiveColor = Colors.WHITE;
- return mode === CollectionViewType.Carousel3D || inOverlay ? null : (
+ return mode === CollectionViewType.Carousel3D || Doc.IsInMyOverlay(this.rootDoc) ? null : (
<div id="toolbarContainer" className={'presBox-toolbar'}>
{/* <Tooltip title={<><div className="dash-tooltip">{"Add new slide"}</div></>}><div className={`toolbar-button ${this.newDocumentTools ? "active" : ""}`} onClick={action(() => this.newDocumentTools = !this.newDocumentTools)}>
<FontAwesomeIcon icon={"plus"} />
@@ -2174,9 +2174,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
@computed get topPanel() {
const mode = StrCast(this.rootDoc._type_collection) as CollectionViewType;
const isMini: boolean = this.toolbarWidth <= 100;
- const inOverlay = DocListCast(Doc.MyOverlayDocs?.data).includes(this.layoutDoc);
return (
- <div className={`presBox-buttons${inOverlay ? ' inOverlay' : ''}`} style={{ background: Doc.ActivePresentation === this.rootDoc ? Colors.LIGHT_BLUE : undefined, display: !this.rootDoc._chromeHidden ? 'none' : undefined }}>
+ <div className={`presBox-buttons${Doc.IsInMyOverlay(this.rootDoc) ? ' inOverlay' : ''}`} style={{ background: Doc.ActivePresentation === this.rootDoc ? Colors.LIGHT_BLUE : undefined, display: !this.rootDoc._chromeHidden ? 'none' : undefined }}>
{isMini ? null : (
<select className="presBox-viewPicker" style={{ display: this.layoutDoc.presStatus === 'edit' ? 'block' : 'none' }} onPointerDown={e => e.stopPropagation()} onChange={this.viewChanged} value={mode}>
<option onPointerDown={StopEvent} value={CollectionViewType.Stacking}>
@@ -2226,7 +2225,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
@computed get playButtons() {
const presEnd = !this.layoutDoc.presLoop && this.itemIndex === this.childDocs.length - 1 && (this.activeItem.presIndexed === undefined || NumCast(this.activeItem.presIndexed) === (this.progressivizedItems(this.activeItem)?.length ?? 0));
const presStart: boolean = !this.layoutDoc.presLoop && this.itemIndex === 0;
- const inOverlay = DocListCast(Doc.MyOverlayDocs?.data).includes(this.layoutDoc);
+ const inOverlay = Doc.IsInMyOverlay(this.rootDoc);
// Case 1: There are still other frames and should go through all frames before going to next slide
return (
<div className="presPanelOverlay" style={{ display: this.layoutDoc.presStatus !== 'edit' ? 'inline-flex' : 'none' }}>
@@ -2400,7 +2399,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
const mode = StrCast(this.rootDoc._type_collection) as CollectionViewType;
const presEnd = !this.layoutDoc.presLoop && this.itemIndex === this.childDocs.length - 1 && (this.activeItem.presIndexed === undefined || NumCast(this.activeItem.presIndexed) === (this.progressivizedItems(this.activeItem)?.length ?? 0));
const presStart = !this.layoutDoc.presLoop && this.itemIndex === 0;
- const inOverlay = DocListCast(Doc.MyOverlayDocs?.data).includes(this.layoutDoc);
return this.props.addDocTab === returnFalse ? ( // bcz: hack!! - addDocTab === returnFalse only when this is being rendered by the OverlayView which means the doc is a mini player
<div className="miniPres" onClick={e => e.stopPropagation()} onPointerEnter={action(e => (this._forceKeyEvents = true))}>
<div
@@ -2443,7 +2441,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
</div>
</div>
) : (
- <div className="presBox-cont" style={{ minWidth: inOverlay ? PresBox.minimizedWidth : undefined }}>
+ <div className="presBox-cont" style={{ minWidth: Doc.IsInMyOverlay(this.rootDoc) ? PresBox.minimizedWidth : undefined }}>
{this.topPanel}
{this.toolbar}
{this.newDocumentToolbarDropdown}
diff --git a/src/client/views/nodes/trails/PresElementBox.tsx b/src/client/views/nodes/trails/PresElementBox.tsx
index 2279ffe84..1f40b82a3 100644
--- a/src/client/views/nodes/trails/PresElementBox.tsx
+++ b/src/client/views/nodes/trails/PresElementBox.tsx
@@ -322,11 +322,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
};
removeAllRecordingInOverlay = () => {
- DocListCast(Doc.MyOverlayDocs.data).forEach(doc => {
- if (doc.slides === this.rootDoc) {
- Doc.RemoveDocFromList(Doc.MyOverlayDocs, undefined, doc);
- }
- });
+ DocListCast(Doc.MyOverlayDocs.data).filter(doc => doc.slides === this.rootDoc).forEach(Doc.RemFromMyOverlay);
};
static removeEveryExistingRecordingInOverlay = () => {
@@ -334,9 +330,9 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
DocListCast(Doc.MyOverlayDocs.data).forEach(doc => {
if (doc.slides !== null) {
// if it's a recording video, don't remove from overlay (user can lose data)
- if (!PresElementBox.videoIsRecorded(DocCast(doc.slides))) return;
-
- Doc.RemoveDocFromList(Doc.MyOverlayDocs, undefined, doc);
+ if (PresElementBox.videoIsRecorded(DocCast(doc.slides))) {
+ Doc.RemFromMyOverlay(doc);
+ }
}
});
};
@@ -356,7 +352,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
if (!iconClick) PresElementBox.removeEveryExistingRecordingInOverlay();
if (activeItem.recording) {
- Doc.AddDocToList(Doc.MyOverlayDocs, undefined, DocCast(activeItem.recording));
+ Doc.AddToMyOverlay(DocCast(activeItem.recording));
}
};
@@ -368,7 +364,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
// if we already have an existing recording
this.showRecording(activeItem, true);
// // if we already have an existing recording
- // Doc.AddDocToList(Doc.MyOverlayDocs, undefined, Cast(activeItem.recording, Doc, null));
+ // Doc.AddToMyOverlay(Cast(activeItem.recording, Doc, null));
} else {
// Remove every recording that already exists in overlay view
// this is a design decision to clear to focus in on the recoding mode
@@ -392,7 +388,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
// make recording box appear in the bottom right corner of the screen
recording.overlayX = window.innerWidth - recording[WidthSym]() - 20;
recording.overlayY = window.innerHeight - recording[HeightSym]() - 20;
- Doc.AddDocToList(Doc.MyOverlayDocs, undefined, recording);
+ Doc.AddToMyOverlay(recording);
}
};
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts
index d8447deb6..128cfffb2 100644
--- a/src/fields/Doc.ts
+++ b/src/fields/Doc.ts
@@ -211,6 +211,15 @@ export class Doc extends RefField {
public static get MyTrails() {
return DocCast(Doc.ActiveDashboard?.myTrails);
}
+ public static IsInMyOverlay(doc:Doc) {
+ return DocListCast(Doc.MyOverlayDocs?.data).includes(doc);
+ }
+ public static AddToMyOverlay(doc:Doc) {
+ Doc.AddDocToList(Doc.MyOverlayDocs, undefined, doc);
+ }
+ public static RemFromMyOverlay(doc:Doc) {
+ Doc.RemoveDocFromList(Doc.MyOverlayDocs, undefined, doc)
+ }
public static get MyOverlayDocs() {
return DocCast(Doc.UserDoc().myOverlayDocs);
}