aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/collections
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/collections')
-rw-r--r--src/client/views/collections/CollectionLinearView.tsx4
-rw-r--r--src/client/views/collections/CollectionMenu.tsx45
-rw-r--r--src/client/views/collections/CollectionSchemaHeaders.tsx14
-rw-r--r--src/client/views/collections/CollectionStackingView.tsx5
-rw-r--r--src/client/views/collections/CollectionStackingViewFieldColumn.tsx12
-rw-r--r--src/client/views/collections/CollectionSubView.tsx5
-rw-r--r--src/client/views/collections/CollectionView.tsx5
-rw-r--r--src/client/views/collections/TabDocView.tsx14
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx28
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx59
10 files changed, 123 insertions, 68 deletions
diff --git a/src/client/views/collections/CollectionLinearView.tsx b/src/client/views/collections/CollectionLinearView.tsx
index 859ee9362..0eac5136a 100644
--- a/src/client/views/collections/CollectionLinearView.tsx
+++ b/src/client/views/collections/CollectionLinearView.tsx
@@ -38,8 +38,8 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) {
componentDidMount() {
// is there any reason this needs to exist? -syip. yes, it handles autoHeight for stacking views (masonry isn't yet supported).
- this._widthDisposer = reaction(() => this.props.Document[HeightSym]() + this.childDocs.length + (this.props.Document.linearViewIsExpanded ? 1 : 0),
- () => this.props.Document._width = 5 + (this.props.Document.linearViewIsExpanded ? this.childDocs.length * (this.props.Document[HeightSym]()) : 10),
+ this._widthDisposer = reaction(() => 5 + (this.props.Document.linearViewIsExpanded ? this.childDocs.length * (this.props.Document[HeightSym]()) : 10),
+ width => this.childDocs.length && (this.props.Document._width = width),
{ fireImmediately: true }
);
diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index 429764154..d9924c299 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -394,28 +394,39 @@ export class CollectionViewBaseChrome extends React.Component<CollectionMenuProp
</Tooltip>;
}
+ @undoBatch
+ @action
+ pinWithView = (targetDoc: Opt<Doc>) => {
+ if (targetDoc) {
+ TabDocView.PinDoc(targetDoc, false);
+ const activeDoc = PresBox.Instance.childDocs[PresBox.Instance.childDocs.length - 1];
+ if (targetDoc.type === DocumentType.PDF) {
+ const scroll = targetDoc._scrollTop;
+ activeDoc.presPinView = true;
+ activeDoc.presPinViewScroll = scroll;
+ } else {
+ const x = targetDoc._panX;
+ const y = targetDoc._panY;
+ const scale = targetDoc._viewScale;
+ activeDoc.presPinView = true;
+ activeDoc.presPinViewX = x;
+ activeDoc.presPinViewY = y;
+ activeDoc.presPinViewScale = scale;
+ }
+ }
+ }
+
@computed
get pinWithViewButton() {
const presPinWithViewIcon = <img src={`/assets/pinWithView.png`} style={{ margin: "auto", width: 19 }} />;
const targetDoc = this.selectedDoc;
- return (!targetDoc || (targetDoc._viewType !== CollectionViewType.Freeform && targetDoc.type !== DocumentType.IMG)) ? (null) : <Tooltip title={<><div className="dash-tooltip">{"Pin to presentation trail with current view"}</div></>} placement="top">
+ {/* return (!targetDoc || (targetDoc._viewType !== CollectionViewType.Freeform && targetDoc.type !== DocumentType.IMG)) ? (null) : <Tooltip title={<><div className="dash-tooltip">{"Pin to presentation trail with current view"}</div></>} placement="top"> */ }
+ return (targetDoc && (targetDoc._viewType === CollectionViewType.Freeform || targetDoc.type === DocumentType.IMG || targetDoc.type === DocumentType.PDF || targetDoc.type === DocumentType.WEB || targetDoc.type === DocumentType.RTF)) ? <Tooltip title={<><div className="dash-tooltip">{"Pin to presentation trail with current view"}</div></>} placement="top">
<button className="antimodeMenu-button" style={{ borderRight: "1px solid gray", borderLeft: "1px solid gray", justifyContent: 'center' }}
- onClick={e => {
- if (targetDoc) {
- TabDocView.PinDoc(targetDoc, false);
- const activeDoc = PresBox.Instance.childDocs[PresBox.Instance.childDocs.length - 1];
- const x = targetDoc._panX;
- const y = targetDoc._panY;
- const scale = targetDoc._viewScale;
- activeDoc.presPinView = true;
- activeDoc.presPinViewX = x;
- activeDoc.presPinViewY = y;
- activeDoc.presPinViewScale = scale;
- }
- }}>
+ onClick={() => this.pinWithView(targetDoc)}>
{presPinWithViewIcon}
</button>
- </Tooltip>;
+ </Tooltip> : (null);
}
@@ -528,7 +539,9 @@ export class CollectionFreeFormViewChrome extends React.Component<CollectionMenu
return SelectionManager.SelectedDocuments().length ? SelectionManager.SelectedDocuments()[0] : undefined;
}
@computed get selectedDoc() { return this.selectedDocumentView?.rootDoc; }
- @computed get isText() { return this.selectedDoc?.type === DocumentType.RTF || RichTextMenu.Instance?.view ? true : false; }
+ @computed get isText() {
+ return this.selectedDoc?.type === DocumentType.RTF || (RichTextMenu.Instance?.view as any)?.focused ? true : false;
+ }
@undoBatch
@action
diff --git a/src/client/views/collections/CollectionSchemaHeaders.tsx b/src/client/views/collections/CollectionSchemaHeaders.tsx
index dbf7488ec..b408fd680 100644
--- a/src/client/views/collections/CollectionSchemaHeaders.tsx
+++ b/src/client/views/collections/CollectionSchemaHeaders.tsx
@@ -261,7 +261,7 @@ export class KeysDropdown extends React.Component<KeysDropdownProps> {
componentDidMount() {
document.addEventListener("pointerdown", this.detectClick);
const filters = Cast(this.props.Document._docFilters, listSpec("string"));
- if (filters?.includes(this._key)) {
+ if (filters?.some(filter => filter.split(":")[0] === this._key)) {
runInAction(() => this.closeResultsVisibility = "contents");
}
}
@@ -396,19 +396,21 @@ export class KeysDropdown extends React.Component<KeysDropdownProps> {
});
const filters = Cast(this.props.Document._docFilters, listSpec("string"));
- if (filters === undefined || filters.length === 0 || filters.includes(this._key) === false) {
+ if (filters === undefined || filters.length === 0 || filters.some(filter => filter.split(":")[0] === this._key) === false) {
this.props.col.setColor("rgb(241, 239, 235)");
this.closeResultsVisibility = "none";
}
- for (let i = 0; i < (filters?.length ?? 0) - 1; i += 3) {
- if (filters![i] === this.props.col.heading && keyOptions.includes(filters![i + 1]) === false) {
+ for (let i = 0; i < (filters?.length ?? 0) - 1; i++) {
+ if (filters![i] === this.props.col.heading && keyOptions.includes(filters![i].split(":")[1]) === false) {
keyOptions.push(filters![i + 1]);
}
}
const options = keyOptions.map(key => {
let bool = false;
if (filters !== undefined) {
- bool = filters.includes(key) && filters[filters.indexOf(key) + 1] === "check";
+ const ind = filters.findIndex(filter => filter.split(":")[0] === key);
+ const fields = ind === -1 ? undefined : filters[ind].split(":");
+ bool = fields ? fields[1] === "check" : false;
}
return <div key={key} className="key-option" style={{
border: "1px solid lightgray", paddingLeft: 5, textAlign: "left",
@@ -453,7 +455,7 @@ export class KeysDropdown extends React.Component<KeysDropdownProps> {
updateFilter() {
const filters = Cast(this.props.Document._docFilters, listSpec("string"));
- if (filters === undefined || filters.length === 0 || filters.includes(this._key) === false) {
+ if (filters === undefined || filters.length === 0 || filters.some(filter => filter.split(":")[0] === this._key) === false) {
this.props.col.setColor("rgb(241, 239, 235)");
this.closeResultsVisibility = "none";
}
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index daaee67dc..3607b97d0 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -294,14 +294,17 @@ export class CollectionStackingView extends CollectionSubView<StackingDocument,
const docs = this.childDocList;
if (docs) {
newDocs.map((doc, i) => {
- console.log(doc.title);
if (i === 0) {
+ if (doc.presentationTargetDoc) doc.dragging = false; //glr: so it only applies to items in presentation
+ DragManager.docsBeingDragged = [];
if (targInd === -1) targInd = docs.length;
else targInd = docs.indexOf(this.filteredChildren[targInd]);
const srcInd = docs.indexOf(doc);
docs.splice(srcInd, 1);
docs.splice((targInd > srcInd ? targInd - 1 : targInd) + plusOne, 0, doc);
} else if (i < (newDocs.length / 2)) { //glr: for some reason dragged documents are duplicated
+ if (doc.presentationTargetDoc) doc.dragging = false;
+ DragManager.docsBeingDragged = [];
if (targInd === -1) targInd = docs.length;
else targInd = docs.indexOf(newDocs[0]) + 1;
const srcInd = docs.indexOf(doc);
diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
index 1bc989e83..b7562c45e 100644
--- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
+++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
@@ -131,8 +131,13 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
}
@action
- addDocument = (value: string, shiftDown?: boolean) => {
- if (!value) return false;
+ textCallback = (char: string) => {
+ return this.addDocument("", false, true);
+ }
+
+ @action
+ addDocument = (value: string, shiftDown?: boolean, forceEmptyNote?: boolean) => {
+ if (!value && !forceEmptyNote) return false;
const key = StrCast(this.props.parent.props.Document._pivotField);
const newDoc = Docs.Create.TextDocument(value, { _height: 18, _width: 200, title: value, _autoHeight: true });
newDoc[key] = this.getValue(this.props.heading);
@@ -140,7 +145,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
const heading = maxHeading === 0 || this.props.docList.length === 0 ? 1 : maxHeading === 1 ? 2 : 3;
newDoc.heading = heading;
FormattedTextBox.SelectOnLoad = newDoc[Id];
- FormattedTextBox.SelectOnLoadChar = " ";
+ FormattedTextBox.SelectOnLoadChar = forceEmptyNote ? "" : " ";
return this.props.parent.props.addDocument(newDoc);
}
@@ -300,6 +305,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
const newEditableViewProps = {
GetValue: () => "",
SetValue: this.addDocument,
+ textCallback: this.textCallback,
contents: "+ NEW",
HeadingObject: this.props.headingObject,
toggle: this.toggleVisibility,
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index fa80c8062..f3e563422 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -103,7 +103,7 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
const { Document, DataDoc } = this.props;
const validPairs = this.childDocs.map(doc => Doc.GetLayoutDataDocPair(Document, !this.props.annotationsKey ? DataDoc : undefined, doc)).
filter(pair => { // filter out any documents that have a proto that we don't have permissions to (which we determine by not having any keys
- return pair.layout && (!pair.layout.proto || (pair.layout.proto instanceof Doc && Object.keys(pair.layout.proto).length));
+ return pair.layout && (!pair.layout.proto || (pair.layout.proto instanceof Doc && GetEffectiveAcl(pair.layout.proto) !== AclPrivate));// Object.keys(pair.layout.proto).length));
});
return validPairs.map(({ data, layout }) => ({ data: data as Doc, layout: layout! })); // this mapping is a bit of a hack to coerce types
}
@@ -134,7 +134,7 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
rawdocs = rootDoc && !this.props.annotationsKey ? [Doc.GetProto(rootDoc)] : [];
}
- const docs = rawdocs.filter(d => !(d instanceof Promise)).map(d => d as Doc);
+ const docs = rawdocs.filter(d => !(d instanceof Promise) && GetEffectiveAcl(Doc.GetProto(d)) !== AclPrivate).map(d => d as Doc);
const viewSpecScript = Cast(this.props.Document.viewSpecScript, ScriptField);
const childDocs = viewSpecScript ? docs.filter(d => viewSpecScript.script.run({ doc: d }, console.log).result) : docs;
@@ -502,4 +502,5 @@ import { SelectionManager } from "../../util/SelectionManager";
import { OverlayView } from "../OverlayView";
import { setTimeout } from "timers";
import { Hypothesis } from "../../util/HypothesisUtils";
+import { GetEffectiveAcl } from "../../../fields/util";
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 80e9b41ad..a27fa5a66 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -140,7 +140,7 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
return false;
}
else {
- if (this.props.Document[AclSym]) {
+ if (this.props.Document[AclSym] && Object.keys(this.props.Document[AclSym])) {
added.forEach(d => {
for (const [key, value] of Object.entries(this.props.Document[AclSym])) {
if (d.author === denormalizeEmail(key.substring(4)) && !d.aliasOf) distributeAcls(key, SharingPermissions.Admin, d, true);
@@ -159,7 +159,8 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
else {
added.filter(doc => [AclAdmin, AclEdit].includes(GetEffectiveAcl(doc))).map(doc => { // only make a pushpin if we have acl's to edit the document
const context = Cast(doc.context, Doc, null);
- if (context && (context.type === DocumentType.VID || context.type === DocumentType.WEB || context.type === DocumentType.PDF || context.type === DocumentType.IMG)) {
+ const hasContextAnchor = DocListCast(doc.links).some(l => (l.anchor2 === doc && Cast(l.anchor1, Doc, null)?.annotationOn === context) || (l.anchor1 === doc && Cast(l.anchor2, Doc, null)?.annotationOn === context));
+ if (context && !hasContextAnchor && (context.type === DocumentType.VID || context.type === DocumentType.WEB || context.type === DocumentType.PDF || context.type === DocumentType.IMG)) {
const pushpin = Docs.Create.FontIconDocument({
title: "pushpin", label: "",
icon: "map-pin", x: Cast(doc.x, "number", null), y: Cast(doc.y, "number", null), _backgroundColor: "#0000003d", color: "#ACCEF7",
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index 8c1a003b9..0c7f39dc7 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -45,6 +45,8 @@ export class TabDocView extends React.Component<TabDocViewProps> {
@observable private _document: Doc | undefined;
@observable private _view: DocumentView | undefined;
+ @computed get contentScaling() { return this.ContentScaling(); }
+
get stack(): any { return (this.props as any).glContainer.parent.parent; }
get tab() { return (this.props as any).glContainer.tab; }
get view() { return this._view; }
@@ -123,7 +125,7 @@ export class TabDocView extends React.Component<TabDocViewProps> {
@undoBatch
@action
public static PinDoc(doc: Doc, unpin = false, audioRange?: boolean) {
- if (unpin) console.log('remove unpin');
+ if (unpin) console.log('TODO: Remove UNPIN from this location');
//add this new doc to props.Document
const curPres = CurrentUserUtils.ActivePresentation;
if (curPres) {
@@ -194,7 +196,7 @@ export class TabDocView extends React.Component<TabDocViewProps> {
panelHeight = () => this.nativeAspect() && this.nativeAspect() > this._panelWidth / this._panelHeight ? this._panelWidth / this.nativeAspect() : this._panelHeight;
nativeWidth = () => !this.layoutDoc?._fitWidth ? NumCast(this.layoutDoc?._nativeWidth) || this._panelWidth : 0;
nativeHeight = () => !this.layoutDoc?._fitWidth ? NumCast(this.layoutDoc?._nativeHeight) || this._panelHeight : 0;
- contentScaling = () => {
+ ContentScaling = () => {
const nativeH = NumCast(this.layoutDoc?._nativeHeight);
const nativeW = NumCast(this.layoutDoc?._nativeWidth);
let scaling = 1;
@@ -210,12 +212,12 @@ export class TabDocView extends React.Component<TabDocViewProps> {
if (this._mainCont?.children) {
const { translateX, translateY } = Utils.GetScreenTransform(this._mainCont.children[0]?.firstChild as HTMLElement);
const scale = Utils.GetScreenTransform(this._mainCont).scale;
- return CollectionDockingView.Instance?.props.ScreenToLocalTransform().translate(-translateX, -translateY).scale(1 / this.contentScaling() / scale);
+ return CollectionDockingView.Instance?.props.ScreenToLocalTransform().translate(-translateX, -translateY).scale(1 / this.ContentScaling() / scale);
}
return Transform.Identity();
}
- @computed get previewPanelCenteringOffset() { return this.nativeWidth() ? (this._panelWidth - this.nativeWidth() * this.contentScaling()) / 2 : 0; }
- @computed get widthpercent() { return this.nativeWidth() ? `${(this.nativeWidth() * this.contentScaling()) / this._panelWidth * 100}% ` : undefined; }
+ @computed get previewPanelCenteringOffset() { return this.nativeWidth() ? (this._panelWidth - this.nativeWidth() * this.ContentScaling()) / 2 : 0; }
+ @computed get widthpercent() { return this.nativeWidth() ? `${(this.nativeWidth() * this.ContentScaling()) / this._panelWidth * 100}% ` : undefined; }
@computed get layoutDoc() { return this._document && Doc.Layout(this._document); }
// adds a tab to the layout based on the locaiton parameter which can be:
@@ -337,7 +339,7 @@ export class TabDocView extends React.Component<TabDocViewProps> {
rootSelected={returnTrue}
addDocument={undefined}
removeDocument={undefined}
- ContentScaling={this.contentScaling}
+ ContentScaling={this.ContentScaling}
PanelWidth={this.panelWidth}
PanelHeight={this.panelHeight}
NativeHeight={this.nativeHeight() ? this.nativeHeight : undefined}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
index f051d5f8d..4cf257640 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
@@ -100,13 +100,15 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo
let rect = el.getBoundingClientRect();
const top = rect.top, height = rect.height;
var el = el.parentNode;
- do {
- rect = el.getBoundingClientRect();
- if (top <= rect.bottom === false && getComputedStyle(el).overflow === "hidden") return rect.bottom;
- // Check if the element is out of view due to a container scrolling
- if ((top + height) <= rect.top && getComputedStyle(el).overflow === "hidden") return rect.top;
+ while (el && el !== document.body) {
+ if (el.hasOwnProperty("getBoundingClientRect")) {
+ rect = el.getBoundingClientRect();
+ if (top <= rect.bottom === false && getComputedStyle(el).overflow === "hidden") return rect.bottom;
+ // Check if the element is out of view due to a container scrolling
+ if ((top + height) <= rect.top && getComputedStyle(el).overflow === "hidden") return rect.top;
+ }
el = el.parentNode;
- } while (el !== document.body);
+ }
// Check its within the document viewport
return top; //top <= document.documentElement.clientHeight && getComputedStyle(document.documentElement).overflow === "hidden";
}
@@ -114,13 +116,15 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo
let rect = el.getBoundingClientRect();
const left = rect.left, width = rect.width;
var el = el.parentNode;
- do {
- rect = el.getBoundingClientRect();
- if (left <= rect.right === false && getComputedStyle(el).overflow === "hidden") return rect.right;
- // Check if the element is out of view due to a container scrolling
- if ((left + width) <= rect.left && getComputedStyle(el).overflow === "hidden") return rect.left;
+ while (el && el !== document.body) {
+ if (el.hasOwnProperty("getBoundingClientRect")) {
+ rect = el.getBoundingClientRect();
+ if (left <= rect.right === false && getComputedStyle(el).overflow === "hidden") return rect.right;
+ // Check if the element is out of view due to a container scrolling
+ if ((left + width) <= rect.left && getComputedStyle(el).overflow === "hidden") return rect.left;
+ }
el = el.parentNode;
- } while (el !== document.body);
+ }
// Check its within the document viewport
return left; //top <= document.documentElement.clientHeight && getComputedStyle(document.documentElement).overflow === "hidden";
}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 5236fab27..8b9e84bd6 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -7,7 +7,7 @@ import { Id } from "../../../../fields/FieldSymbols";
import { InkData, InkField, InkTool } from "../../../../fields/InkField";
import { List } from "../../../../fields/List";
import { RichTextField } from "../../../../fields/RichTextField";
-import { createSchema, makeInterface } from "../../../../fields/Schema";
+import { createSchema, makeInterface, listSpec } from "../../../../fields/Schema";
import { ScriptField } from "../../../../fields/ScriptField";
import { BoolCast, Cast, FieldValue, NumCast, ScriptCast, StrCast } from "../../../../fields/Types";
import { TraceMobx } from "../../../../fields/util";
@@ -88,6 +88,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
private _clusterDistance: number = 75;
private _hitCluster = false;
private _layoutComputeReaction: IReactionDisposer | undefined;
+ private _boundsReaction: IReactionDisposer | undefined;
private _layoutPoolData = new ObservableMap<string, PoolData>();
private _layoutSizeData = new ObservableMap<string, { width?: number, height?: number }>();
private _cachedPool: Map<string, PoolData> = new Map();
@@ -782,10 +783,17 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
let deltaScale = deltaY > 0 ? (1 / 1.05) : 1.05;
if (deltaScale < 0) deltaScale = -deltaScale;
const [x, y] = this.getTransform().transformPoint(pointX, pointY);
+ const invTransform = this.getLocalTransform().inverse();
+ if (deltaScale * invTransform.Scale > 20) {
+ deltaScale = 20 / invTransform.Scale;
+ }
+ if (deltaScale * invTransform.Scale < 1 && this.isAnnotationOverlay) {
+ deltaScale = 1 / invTransform.Scale;
+ }
const localTransform = this.getLocalTransform().inverse().scaleAbout(deltaScale, x, y);
if (localTransform.Scale >= 0.15 || localTransform.Scale > this.zoomScaling()) {
- const safeScale = Math.min(Math.max(0.15, localTransform.Scale), 40);
+ const safeScale = Math.min(Math.max(0.15, localTransform.Scale), 20);
this.props.Document[this.scaleFieldKey] = Math.abs(safeScale);
this.setPan(-localTransform.TranslateX / safeScale, -localTransform.TranslateY / safeScale);
}
@@ -892,57 +900,62 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
afterFocus && setTimeout(afterFocus, delay);
} else {
const contextHgt = Doc.AreProtosEqual(annotOn, this.props.Document) && this.props.VisibleHeight ? this.props.VisibleHeight() : NumCast(annotOn._height);
- const offset = annotOn && (contextHgt / 2);
const curScroll = NumCast(this.props.Document._scrollTop);
let scrollTo = curScroll;
if (curScroll + contextHgt < NumCast(doc.y)) {
- scrollTo = NumCast(doc.y) + NumCast(doc._height) - contextHgt;
+ scrollTo = NumCast(doc.y) + Math.max(NumCast(doc._height), 100) - contextHgt;
} else if (curScroll > NumCast(doc.y)) {
- scrollTo = NumCast(doc.y);
+ scrollTo = Math.max(0, NumCast(doc.y) - 50);
}
- if (curScroll !== scrollTo) {
+ if (curScroll !== scrollTo || this.props.Document._viewTransition) {
this.props.Document._scrollPY = this.props.Document._scrollY = scrollTo;
delay = Math.abs(scrollTo - curScroll) > 5 ? 1000 : 0;
- !dontCenter && delay && this.props.focus(this.props.Document);
+ !dontCenter && this.props.focus(this.props.Document);
afterFocus && setTimeout(afterFocus, delay);
+ } else {
+ !dontCenter && delay && this.props.focus(this.props.Document);
// @ts-ignore
- } else afterFocus(true); // bcz: TODO Aragh -- need to add a parameter to afterFocus() functions to indicate whether the focus function didn't need to scroll
+ afterFocus(true); // bcz: TODO Aragh -- need to add a parameter to afterFocus() functions to indicate whether the focus function didn't need to scroll
+
+ }
}
} else {
const layoutdoc = Doc.Layout(doc);
- const newPanX = NumCast(doc.x) + NumCast(layoutdoc._width) / 2;
- const newPanY = NumCast(doc.y) + NumCast(layoutdoc._height) / 2;
+
+ willZoom && this.setScaleToZoom(layoutdoc, scale);
+ const newPanX = (NumCast(doc.x) + doc[WidthSym]() / 2) - (this.isAnnotationOverlay ? (NumCast(this.props.Document._nativeWidth)) / 2 / this.zoomScaling() : 0);
+ const newPanY = (NumCast(doc.y) + doc[HeightSym]() / 2) - (this.isAnnotationOverlay ? (NumCast(this.props.Document._nativeHeight)) / 2 / this.zoomScaling() : 0);
const newState = HistoryUtil.getState();
newState.initializers![this.Document[Id]] = { panX: newPanX, panY: newPanY };
HistoryUtil.pushState(newState);
const savedState = { px: this.Document._panX, py: this.Document._panY, s: this.Document[this.scaleFieldKey], pt: this.Document._viewTransition };
-
- if (DocListCast(this.dataDoc[this.props.fieldKey]).includes(doc)) {
+ if (DocListCast(this.dataDoc[this.props.annotationsKey || this.props.fieldKey]).includes(doc)) {
// glr: freeform transform speed can be set by adjusting presTransition field - needs a way of knowing when presentation is not active...
if (!doc.z) this.setPan(newPanX, newPanY, doc.focusSpeed || doc.focusSpeed === 0 ? `transform ${doc.focusSpeed}ms` : "transform 500ms", true); // docs that are floating in their collection can't be panned to from their collection -- need to propagate the pan to a parent freeform somehow
}
Doc.BrushDoc(this.props.Document);
this.props.focus(this.props.Document);
- willZoom && this.setScaleToZoom(layoutdoc, scale);
Doc.linkFollowHighlight(doc);
+ const notFocused = newPanX === savedState.px && newPanY === savedState.py;
afterFocus && setTimeout(() => {
- if (afterFocus?.()) {
+ // @ts-ignore
+ if (afterFocus?.(notFocused)) { // bcz: TODO Aragh -- need to add a parameter to afterFocus() functions to indicate whether the focus function didn't need to scroll
this.Document._panX = savedState.px;
this.Document._panY = savedState.py;
this.Document[this.scaleFieldKey] = savedState.s;
this.Document._viewTransition = savedState.pt;
}
- }, 500);
+ }, notFocused ? 0 : 500);
}
}
setScaleToZoom = (doc: Doc, scale: number = 0.75) => {
- const pw = this.props.PanelWidth();
- const ph = this.props.PanelHeight();
+ const pw = this.isAnnotationOverlay ? NumCast(this.props.Document._nativeWidth) : this.props.PanelWidth();
+ const ph = this.isAnnotationOverlay ? NumCast(this.props.Document._nativeHeight) : this.props.PanelHeight();
pw && ph && (this.Document[this.scaleFieldKey] = scale * Math.min(pw / NumCast(doc._width), ph / NumCast(doc._height)));
}
@@ -1159,12 +1172,22 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
this._layoutComputeReaction = reaction(() => this.doLayoutComputation,
(elements) => this._layoutElements = elements || [],
{ fireImmediately: true, name: "doLayout" });
+ if (!this.props.annotationsKey) {
+ this._boundsReaction = reaction(() => this.contentBounds,
+ bounds => (!this.fitToContent && this._layoutElements?.length) && setTimeout(() => {
+ const rbounds = Cast(this.Document._renderContentBounds, listSpec("number"), [0, 0, 0, 0]);
+ if (rbounds[0] !== bounds.x || rbounds[1] !== bounds.y || rbounds[2] !== bounds.r || rbounds[3] !== bounds.b) {
+ this.Document._renderContentBounds = new List<number>([bounds.x, bounds.y, bounds.r, bounds.b]);
+ }
+ }));
+ }
this._marqueeRef.current?.addEventListener("dashDragAutoScroll", this.onDragAutoScroll as any);
}
componentWillUnmount() {
this._layoutComputeReaction?.();
+ this._boundsReaction?.();
this._marqueeRef.current?.removeEventListener("dashDragAutoScroll", this.onDragAutoScroll as any);
}
@@ -1438,10 +1461,10 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
return wscale < hscale ? wscale : hscale;
}
@computed get backgroundEvents() { return this.layoutDoc._isBackground && SnappingManager.GetIsDragging(); }
+
render() {
TraceMobx();
const clientRect = this._mainCont?.getBoundingClientRect();
- !this.fitToContent && this._layoutElements?.length && setTimeout(() => this.Document._renderContentBounds = new List<number>([this.contentBounds.x, this.contentBounds.y, this.contentBounds.r, this.contentBounds.b]), 0);
return <div className={"collectionfreeformview-container"} ref={this.createDashEventsTarget}
onPointerOver={this.onPointerOver}
onWheel={this.onPointerWheel}