aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/util/DocumentManager.ts22
-rw-r--r--src/client/views/MainView.tsx2
-rw-r--r--src/client/views/StyleProvider.tsx2
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx65
-rw-r--r--src/client/views/nodes/ComparisonBox.tsx44
-rw-r--r--src/client/views/nodes/DocumentIcon.tsx31
-rw-r--r--src/client/views/nodes/LinkAnchorBox.tsx26
-rw-r--r--src/client/views/nodes/LinkBox.tsx48
8 files changed, 150 insertions, 90 deletions
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index 7f82ff70a..17c915318 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -90,11 +90,11 @@ export class DocumentManager {
@action
public AddView = (view: DocumentView) => {
- if (view.props.LayoutTemplateString?.includes(KeyValueBox.name)) return;
- if (view.props.LayoutTemplateString?.includes(LinkAnchorBox.name)) {
- const viewAnchorIndex = view.props.LayoutTemplateString.includes('link_anchor_2') ? 'link_anchor_2' : 'link_anchor_1';
+ if (view._props.LayoutTemplateString?.includes(KeyValueBox.name)) return;
+ if (view._props.LayoutTemplateString?.includes(LinkAnchorBox.name)) {
+ const viewAnchorIndex = view._props.LayoutTemplateString.includes('link_anchor_2') ? 'link_anchor_2' : 'link_anchor_1';
const link = view.Document;
- this.LinkAnchorBoxViews?.filter(dv => Doc.AreProtosEqual(dv.Document, link) && !dv.props.LayoutTemplateString?.includes(viewAnchorIndex)).forEach(otherView =>
+ this.LinkAnchorBoxViews?.filter(dv => Doc.AreProtosEqual(dv.Document, link) && !dv._props.LayoutTemplateString?.includes(viewAnchorIndex)).forEach(otherView =>
this.LinkedDocumentViews.push({
a: viewAnchorIndex === 'link_anchor_2' ? otherView : view,
b: viewAnchorIndex === 'link_anchor_2' ? view : otherView,
@@ -117,7 +117,7 @@ export class DocumentManager {
})
);
- if (view.props.LayoutTemplateString?.includes(LinkAnchorBox.name)) {
+ if (view._props.LayoutTemplateString?.includes(LinkAnchorBox.name)) {
const index = this.LinkAnchorBoxViews.indexOf(view);
this.LinkAnchorBoxViews.splice(index, 1);
} else {
@@ -154,8 +154,8 @@ export class DocumentManager {
return passes.reduce(
(toReturn, pass) =>
toReturn ??
- docViewArray.filter(view => view.Document === target).find(view => !pass || view.props.docViewPath().lastElement() === preferredCollection) ??
- docViewArray.filter(view => Doc.AreProtosEqual(view.Document, target)).find(view => !pass || view.props.docViewPath().lastElement() === preferredCollection),
+ docViewArray.filter(view => view.Document === target).find(view => !pass || view._props.docViewPath().lastElement() === preferredCollection) ??
+ docViewArray.filter(view => Doc.AreProtosEqual(view.Document, target)).find(view => !pass || view._props.docViewPath().lastElement() === preferredCollection),
undefined as Opt<DocumentView>
);
}
@@ -163,12 +163,12 @@ export class DocumentManager {
public getLightboxDocumentView = (toFind: Doc, originatingDoc: Opt<Doc> = undefined): DocumentView | undefined => {
const views: DocumentView[] = [];
DocumentManager.Instance.DocumentViews.forEach(view => LightboxView.IsLightboxDocView(view.docViewPath) && Doc.AreProtosEqual(view.Document, toFind) && views.push(view));
- return views?.find(view => view.ContentDiv?.getBoundingClientRect().width /*&& view.props.focus !== returnFalse) || views?.find(view => view.props.focus !== returnFalse*/) || (views.length ? views[0] : undefined);
+ return views?.find(view => view.ContentDiv?.getBoundingClientRect().width /*&& view._props.focus !== returnFalse) || views?.find(view => view._props.focus !== returnFalse*/) || (views.length ? views[0] : undefined);
};
public getFirstDocumentView = (toFind: Doc, originatingDoc: Opt<Doc> = undefined): DocumentView | undefined => {
if (LightboxView.LightboxDoc) return DocumentManager.Instance.getLightboxDocumentView(toFind, originatingDoc);
const views = this.getDocumentViews(toFind); //.filter(view => view.Document !== originatingDoc);
- return views?.find(view => view.ContentDiv?.getBoundingClientRect().width /*&& view.props.focus !== returnFalse) || views?.find(view => view.props.focus !== returnFalse*/) || (views.length ? views[0] : undefined);
+ return views?.find(view => view.ContentDiv?.getBoundingClientRect().width /*&& view._props.focus !== returnFalse) || views?.find(view => view._props.focus !== returnFalse*/) || (views.length ? views[0] : undefined);
};
public getDocumentViews(toFindIn: Doc): DocumentView[] {
const toFind =
@@ -304,7 +304,7 @@ export class DocumentManager {
await new Promise<void>(res => docView.iconify(res));
options.didMove = true;
}
- const nextFocus = docView.props.focus(docView.Document, options); // focus the view within its container
+ const nextFocus = docView._props.focus(docView.Document, options); // focus the view within its container
focused = focused || (nextFocus === undefined ? false : true); // keep track of whether focusing on a view needed to actually change anything
const { childDocView, viewSpec } = await iterator(docView);
if (!childDocView) return { viewSpec: options.anchorDoc ?? viewSpec ?? docView.Document, docView, contextView, focused };
@@ -345,7 +345,7 @@ export function DocFocusOrOpen(doc: Doc, options: DocFocusOptions = { willZoomCe
const func = () => {
const cv = DocumentManager.Instance.getDocumentView(containingDoc);
const dv = DocumentManager.Instance.getDocumentView(doc, cv);
- if (dv && (!containingDoc || dv.props.docViewPath().lastElement()?.Document === containingDoc)) {
+ if (dv && (!containingDoc || dv._props.docViewPath().lastElement()?.Document === containingDoc)) {
DocumentManager.Instance.showDocumentView(dv, options).then(() => dv && Doc.linkFollowHighlight(dv.Document));
} else {
const container = DocCast(containingDoc ?? doc.embedContainer ?? Doc.BestEmbedding(doc));
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 1e4c1e1d3..de3c78e91 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -69,6 +69,7 @@ import { PreviewCursor } from './PreviewCursor';
import { PropertiesView } from './PropertiesView';
import { DashboardStyleProvider, DefaultStyleProvider } from './StyleProvider';
import { TopBar } from './topbar/TopBar';
+import { CollectionFreeFormLinksView } from './collections/collectionFreeForm';
const { default: { LEFT_MENU_WIDTH, TOPBAR_HEIGHT } } = require('./global/globalCssVariables.module.scss'); // prettier-ignore
const _global = (window /* browser */ || global) /* node */ as any;
@@ -1063,6 +1064,7 @@ export class MainView extends React.Component {
{/* <InkTranscription /> */}
{this.snapLines}
<LightboxView key="lightbox" PanelWidth={this._windowWidth} PanelHeight={this._windowHeight} maxBorder={[200, 50]} />
+ <CollectionFreeFormLinksView />
<OverlayView />
{this.mapBoxHack}
<GPTPopup key="gptpopup" />
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index f3d515364..3e7e4be90 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -170,7 +170,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
const docColor: Opt<string> = StrCast(doc?.[fieldKey + 'color'], StrCast(doc?._color));
if (docColor) return docColor;
const docView = props?.DocumentView?.();
- const backColor = backgroundCol() || docView?.props.styleProvider?.(docView.props.treeViewDoc, docView.props, StyleProp.BackgroundColor);
+ const backColor = backgroundCol() || docView?._props.styleProvider?.(docView._props.treeViewDoc, docView._props, StyleProp.BackgroundColor);
return backColor ? lightOrDark(backColor) : undefined;
case StyleProp.BorderRounding:
return StrCast(doc?.[fieldKey + 'borderRounding'], StrCast(doc?.layout_borderRounding, doc?._type_collection === CollectionViewType.Pile ? '50%' : ''));
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
index 5cbea4783..f89e2ba9a 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
@@ -1,11 +1,11 @@
-import { action, computed, IReactionDisposer, observable, reaction } from 'mobx';
+import { action, computed, IReactionDisposer, makeObservable, observable, reaction } from 'mobx';
import { observer } from 'mobx-react';
import { Doc, Field } from '../../../../fields/Doc';
import { Brushed, DocCss } from '../../../../fields/DocSymbols';
import { Id } from '../../../../fields/FieldSymbols';
import { List } from '../../../../fields/List';
import { Cast, NumCast, StrCast } from '../../../../fields/Types';
-import { emptyFunction, setupMoveUpEvents, Utils } from '../../../../Utils';
+import { copyProps, emptyFunction, setupMoveUpEvents, Utils } from '../../../../Utils';
import { LinkManager } from '../../../util/LinkManager';
import { SelectionManager } from '../../../util/SelectionManager';
import { SettingsManager } from '../../../util/SettingsManager';
@@ -29,6 +29,17 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo
@observable _start = 0;
_anchorDisposer: IReactionDisposer | undefined;
_timeout: NodeJS.Timeout | undefined;
+ _prevProps: CollectionFreeFormLinkViewProps;
+ @observable _props: CollectionFreeFormLinkViewProps;
+ constructor(props: CollectionFreeFormLinkViewProps) {
+ super(props);
+ this._props = this._prevProps = props;
+ makeObservable(this);
+ }
+
+ componentDidUpdate() {
+ copyProps(this);
+ }
componentWillUnmount() {
this._anchorDisposer?.();
}
@@ -36,12 +47,12 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo
componentDidMount() {
this._anchorDisposer = reaction(
() => [
- this.props.A.props.ScreenToLocalTransform(),
- Cast(Cast(Cast(this.props.A.Document, Doc, null)?.link_anchor_1, Doc, null)?.annotationOn, Doc, null)?.layout_scrollTop,
- Cast(Cast(Cast(this.props.A.Document, Doc, null)?.link_anchor_1, Doc, null)?.annotationOn, Doc, null)?.[DocCss],
- this.props.B.props.ScreenToLocalTransform(),
- Cast(Cast(Cast(this.props.A.Document, Doc, null)?.link_anchor_2, Doc, null)?.annotationOn, Doc, null)?.layout_scrollTop,
- Cast(Cast(Cast(this.props.A.Document, Doc, null)?.link_anchor_2, Doc, null)?.annotationOn, Doc, null)?.[DocCss],
+ this._props.A._props.ScreenToLocalTransform(),
+ Cast(Cast(Cast(this._props.A.Document, Doc, null)?.link_anchor_1, Doc, null)?.annotationOn, Doc, null)?.layout_scrollTop,
+ Cast(Cast(Cast(this._props.A.Document, Doc, null)?.link_anchor_1, Doc, null)?.annotationOn, Doc, null)?.[DocCss],
+ this._props.B._props.ScreenToLocalTransform(),
+ Cast(Cast(Cast(this._props.A.Document, Doc, null)?.link_anchor_2, Doc, null)?.annotationOn, Doc, null)?.layout_scrollTop,
+ Cast(Cast(Cast(this._props.A.Document, Doc, null)?.link_anchor_2, Doc, null)?.annotationOn, Doc, null)?.[DocCss],
],
action(() => {
this._start = Date.now();
@@ -53,7 +64,7 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo
);
}
placeAnchors = () => {
- const { A, B, LinkDocs } = this.props;
+ const { A, B, LinkDocs } = this._props;
const linkDoc = LinkDocs[0];
if (SnappingManager.GetIsDragging() || !A.ContentDiv || !B.ContentDiv) return;
setTimeout(
@@ -85,9 +96,9 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo
}
} else {
const m = targetAhyperlink.getBoundingClientRect();
- const mp = A.props.ScreenToLocalTransform().transformPoint(m.right, m.top + 5);
- const mpx = mp[0] / A.props.PanelWidth();
- const mpy = mp[1] / A.props.PanelHeight();
+ const mp = A._props.ScreenToLocalTransform().transformPoint(m.right, m.top + 5);
+ const mpx = mp[0] / A._props.PanelWidth();
+ const mpy = mp[1] / A._props.PanelHeight();
if (mpx >= 0 && mpx <= 1) linkDoc.link_anchor_1_x = mpx * 100;
if (mpy >= 0 && mpy <= 1) linkDoc.link_anchor_1_y = mpy * 100;
if (getComputedStyle(targetAhyperlink).fontSize === '0px') linkDoc.opacity = 0;
@@ -100,9 +111,9 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo
}
} else {
const m = targetBhyperlink.getBoundingClientRect();
- const mp = B.props.ScreenToLocalTransform().transformPoint(m.right, m.top + 5);
- const mpx = mp[0] / B.props.PanelWidth();
- const mpy = mp[1] / B.props.PanelHeight();
+ const mp = B._props.ScreenToLocalTransform().transformPoint(m.right, m.top + 5);
+ const mpx = mp[0] / B._props.PanelWidth();
+ const mpy = mp[1] / B._props.PanelHeight();
if (mpx >= 0 && mpx <= 1) linkDoc.link_anchor_2_x = mpx * 100;
if (mpy >= 0 && mpy <= 1) linkDoc.link_anchor_2_y = mpy * 100;
if (getComputedStyle(targetBhyperlink).fontSize === '0px') linkDoc.opacity = 0;
@@ -115,18 +126,18 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo
this,
e,
(e, down, delta) => {
- this.props.LinkDocs[0].link_relationship_OffsetX = NumCast(this.props.LinkDocs[0].link_relationship_OffsetX) + delta[0];
- this.props.LinkDocs[0].link_relationship_OffsetY = NumCast(this.props.LinkDocs[0].link_relationship_OffsetY) + delta[1];
+ this._props.LinkDocs[0].link_relationship_OffsetX = NumCast(this._props.LinkDocs[0].link_relationship_OffsetX) + delta[0];
+ this._props.LinkDocs[0].link_relationship_OffsetY = NumCast(this._props.LinkDocs[0].link_relationship_OffsetY) + delta[1];
return false;
},
emptyFunction,
action(() => {
SelectionManager.DeselectAll();
- SelectionManager.SelectSchemaViewDoc(this.props.LinkDocs[0], true);
- LinkManager.currentLink = this.props.LinkDocs[0];
+ SelectionManager.SelectSchemaViewDoc(this._props.LinkDocs[0], true);
+ LinkManager.currentLink = this._props.LinkDocs[0];
this.toggleProperties();
// OverlayView.Instance.addElement(
- // <LinkEditor sourceDoc={this.props.A.props.Document} linkDoc={this.props.LinkDocs[0]}
+ // <LinkEditor sourceDoc={this._props.A._props.Document} linkDoc={this._props.LinkDocs[0]}
// showLinks={action(() => { })}
// />, { x: 300, y: 300 });
})
@@ -179,15 +190,15 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo
@action
onClickLine = () => {
SelectionManager.DeselectAll();
- SelectionManager.SelectSchemaViewDoc(this.props.LinkDocs[0], true);
- LinkManager.currentLink = this.props.LinkDocs[0];
+ SelectionManager.SelectSchemaViewDoc(this._props.LinkDocs[0], true);
+ LinkManager.currentLink = this._props.LinkDocs[0];
this.toggleProperties();
};
@computed.struct get renderData() {
this._start;
SnappingManager.GetIsDragging();
- const { A, B, LinkDocs } = this.props;
+ const { A, B, LinkDocs } = this._props;
if (!A.ContentDiv || !B.ContentDiv || !LinkDocs.length) return undefined;
const acont = A.ContentDiv.getElementsByClassName('linkAnchorBox-cont');
const bcont = B.ContentDiv.getElementsByClassName('linkAnchorBox-cont');
@@ -200,8 +211,8 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo
const atop = this.visibleY(adiv);
const btop = this.visibleY(bdiv);
if (!a.width || !b.width) return undefined;
- const aDocBounds = (A.props as any).DocumentView?.().getBounds() || { left: 0, right: 0, top: 0, bottom: 0 };
- const bDocBounds = (B.props as any).DocumentView?.().getBounds() || { left: 0, right: 0, top: 0, bottom: 0 };
+ const aDocBounds = (A._props as any).DocumentView?.().getBounds() || { left: 0, right: 0, top: 0, bottom: 0 };
+ const bDocBounds = (B._props as any).DocumentView?.().getBounds() || { left: 0, right: 0, top: 0, bottom: 0 };
const aleft = this.visibleX(adiv);
const bleft = this.visibleX(bdiv);
const aclipped = aleft !== a.left || atop !== a.top;
@@ -228,7 +239,7 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo
const textX = (Math.min(pt1[0], pt2[0]) + Math.max(pt1[0], pt2[0])) / 2 + NumCast(LinkDocs[0].link_relationship_OffsetX);
const textY = (pt1[1] + pt2[1]) / 2 + NumCast(LinkDocs[0].link_relationship_OffsetY);
- const link = this.props.LinkDocs[0];
+ const link = this._props.LinkDocs[0];
return {
a,
b,
@@ -250,7 +261,7 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo
render() {
if (!this.renderData) return null;
- const link = this.props.LinkDocs[0];
+ const link = this._props.LinkDocs[0];
const { a, b, pt1norm, pt2norm, aActive, bActive, textX, textY, pt1, pt2 } = this.renderData;
const linkRelationship = Field.toString(link?.link_relationship as any as Field); //get string representing relationship
const linkRelationshipList = Doc.UserDoc().link_relationshipList as List<string>;
diff --git a/src/client/views/nodes/ComparisonBox.tsx b/src/client/views/nodes/ComparisonBox.tsx
index 72a473114..62523ba00 100644
--- a/src/client/views/nodes/ComparisonBox.tsx
+++ b/src/client/views/nodes/ComparisonBox.tsx
@@ -1,9 +1,9 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { action, computed, observable } from 'mobx';
+import { action, computed, makeObservable, observable, override } from 'mobx';
import { observer } from 'mobx-react';
import { Doc, Opt } from '../../../fields/Doc';
import { DocCast, NumCast, StrCast } from '../../../fields/Types';
-import { emptyFunction, returnFalse, returnNone, returnZero, setupMoveUpEvents } from '../../../Utils';
+import { copyProps, emptyFunction, returnFalse, returnNone, returnZero, setupMoveUpEvents } from '../../../Utils';
import { Docs, DocUtils } from '../../documents/Documents';
import { DragManager } from '../../util/DragManager';
import { undoBatch } from '../../util/UndoManager';
@@ -24,14 +24,26 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatabl
@observable _animating = '';
+ _prevProps: ViewBoxAnnotatableProps & FieldViewProps;
+ @override _props: ViewBoxAnnotatableProps & FieldViewProps;
+ constructor(props: ViewBoxAnnotatableProps & FieldViewProps) {
+ super(props);
+ this._props = this._prevProps = props;
+ makeObservable(this);
+ }
+
+ componentDidUpdate() {
+ copyProps(this);
+ }
+
@computed get clipWidth() {
return NumCast(this.layoutDoc[this.clipWidthKey], 50);
}
get clipWidthKey() {
- return '_' + this.props.fieldKey + '_clipWidth';
+ return '_' + this._props.fieldKey + '_clipWidth';
}
componentDidMount() {
- this.props.setContentView?.(this);
+ this._props.setContentView?.(this);
}
protected createDropTarget = (ele: HTMLDivElement | null, fieldKey: string, disposerId: number) => {
this._disposers[disposerId]?.();
@@ -72,7 +84,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatabl
if (this._isAnyChildContentActive) return;
this._animating = 'all 200ms';
// on click, animate slider movement to the targetWidth
- this.layoutDoc[this.clipWidthKey] = (targetWidth * 100) / this.props.PanelWidth();
+ this.layoutDoc[this.clipWidthKey] = (targetWidth * 100) / this._props.PanelWidth();
setTimeout(
action(() => (this._animating = '')),
200
@@ -84,9 +96,9 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatabl
@action
private onPointerMove = ({ movementX }: PointerEvent) => {
- const width = movementX * this.props.ScreenToLocalTransform().Scale + (this.clipWidth / 100) * this.props.PanelWidth();
- if (width && width > 5 && width < this.props.PanelWidth()) {
- this.layoutDoc[this.clipWidthKey] = (width * 100) / this.props.PanelWidth();
+ const width = movementX * this._props.ScreenToLocalTransform().Scale + (this.clipWidth / 100) * this._props.PanelWidth();
+ if (width && width > 5 && width < this._props.PanelWidth()) {
+ this.layoutDoc[this.clipWidthKey] = (width * 100) / this._props.PanelWidth();
}
return false;
};
@@ -146,7 +158,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatabl
};
docStyleProvider = (doc: Opt<Doc>, props: Opt<DocumentViewProps>, property: string): any => {
if (property === StyleProp.PointerEvents) return 'none';
- return this.props.styleProvider?.(doc, props, property);
+ return this._props.styleProvider?.(doc, props, property);
};
moveDoc1 = (doc: Doc | Doc[], targetCol: Doc | undefined, addDoc: any) => (doc instanceof Doc ? [doc] : doc).reduce((res, doc: Doc) => res && this.moveDoc(doc, addDoc, this.fieldKey + '_1'), true);
moveDoc2 = (doc: Doc | Doc[], targetCol: Doc | undefined, addDoc: any) => (doc instanceof Doc ? [doc] : doc).reduce((res, doc: Doc) => res && this.moveDoc(doc, addDoc, this.fieldKey + '_2'), true);
@@ -171,7 +183,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatabl
return targetDoc ? (
<>
<DocumentView
- {...this.props}
+ {...this._props}
Document={targetDoc}
TemplateDataDocument={undefined}
moveDocument={which.endsWith('1') ? this.moveDoc1 : this.moveDoc2}
@@ -181,7 +193,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatabl
isContentActive={emptyFunction}
isDocumentActive={returnFalse}
whenChildContentsActiveChanged={this.whenChildContentsActiveChanged}
- styleProvider={this._isAnyChildContentActive ? this.props.styleProvider : this.docStyleProvider}
+ styleProvider={this._isAnyChildContentActive ? this._props.styleProvider : this.docStyleProvider}
hideLinkButton={true}
pointerEvents={this._isAnyChildContentActive ? undefined : returnNone}
/>
@@ -195,15 +207,15 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatabl
};
const displayBox = (which: string, index: number, cover: number) => {
return (
- <div className={`${index === 0 ? 'before' : 'after'}Box-cont`} key={which} style={{ width: this.props.PanelWidth() }} onPointerDown={e => this.registerSliding(e, cover)} ref={ele => this.createDropTarget(ele, which, index)}>
+ <div className={`${index === 0 ? 'before' : 'after'}Box-cont`} key={which} style={{ width: this._props.PanelWidth() }} onPointerDown={e => this.registerSliding(e, cover)} ref={ele => this.createDropTarget(ele, which, index)}>
{displayDoc(which)}
</div>
);
};
return (
- <div className={`comparisonBox${this.props.isContentActive() ? '-interactive' : ''}` /* change className to easily disable/enable pointer events in CSS */}>
- {displayBox(`${this.fieldKey}_2`, 1, this.props.PanelWidth() - 3)}
+ <div className={`comparisonBox${this._props.isContentActive() ? '-interactive' : ''}` /* change className to easily disable/enable pointer events in CSS */}>
+ {displayBox(`${this.fieldKey}_2`, 1, this._props.PanelWidth() - 3)}
<div className="clip-div" style={{ width: this.clipWidth + '%', transition: this._animating, background: StrCast(this.layoutDoc._backgroundColor, 'gray') }}>
{displayBox(`${this.fieldKey}_1`, 0, 0)}
</div>
@@ -212,9 +224,9 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatabl
className="slide-bar"
style={{
left: `calc(${this.clipWidth + '%'} - 0.5px)`,
- cursor: this.clipWidth < 5 ? 'e-resize' : this.clipWidth / 100 > (this.props.PanelWidth() - 5) / this.props.PanelWidth() ? 'w-resize' : undefined,
+ cursor: this.clipWidth < 5 ? 'e-resize' : this.clipWidth / 100 > (this._props.PanelWidth() - 5) / this._props.PanelWidth() ? 'w-resize' : undefined,
}}
- onPointerDown={e => !this._isAnyChildContentActive && this.registerSliding(e, this.props.PanelWidth() / 2)} /* if clicked, return slide-bar to center */
+ onPointerDown={e => !this._isAnyChildContentActive && this.registerSliding(e, this._props.PanelWidth() / 2)} /* if clicked, return slide-bar to center */
>
<div className="slide-handle" />
</div>
diff --git a/src/client/views/nodes/DocumentIcon.tsx b/src/client/views/nodes/DocumentIcon.tsx
index e8d8c05e3..0c780af2a 100644
--- a/src/client/views/nodes/DocumentIcon.tsx
+++ b/src/client/views/nodes/DocumentIcon.tsx
@@ -5,20 +5,35 @@ import { DocumentManager } from '../../util/DocumentManager';
import { Transformer, ts } from '../../util/Scripting';
import { Field } from '../../../fields/Doc';
import { Tooltip } from '@mui/material';
-import { action, observable } from 'mobx';
+import { action, makeObservable, observable } from 'mobx';
import { Id } from '../../../fields/FieldSymbols';
import { factory } from 'typescript';
import { LightboxView } from '../LightboxView';
import { SettingsManager } from '../../util/SettingsManager';
+import { copyProps } from '../../../Utils';
-@observer
-export class DocumentIcon extends React.Component<{ view: DocumentView; index: number }> {
+interface DocumentIconProps {
+ view: DocumentView;
+ index: number;
+}
+export class DocumentIcon extends React.Component<DocumentIconProps> {
@observable _hovered = false;
+ _prevProps: DocumentIconProps;
+ @observable _props: DocumentIconProps;
+ constructor(props: DocumentIconProps) {
+ super(props);
+ this._props = this._prevProps = props;
+ makeObservable(this);
+ }
+ componentDidUpdate() {
+ copyProps(this);
+ }
+
static get DocViews() {
- return LightboxView.LightboxDoc ? DocumentManager.Instance.DocumentViews.filter(v => LightboxView.IsLightboxDocView(v.props.docViewPath())) : DocumentManager.Instance.DocumentViews;
+ return LightboxView.LightboxDoc ? DocumentManager.Instance.DocumentViews.filter(v => LightboxView.IsLightboxDocView(v._props.docViewPath())) : DocumentManager.Instance.DocumentViews;
}
render() {
- const view = this.props.view;
+ const view = this._props.view;
const { left, top, right, bottom } = view.getBounds() || { left: 0, top: 0, right: 0, bottom: 0 };
return (
@@ -33,8 +48,8 @@ export class DocumentIcon extends React.Component<{ view: DocumentView; index: n
background: SettingsManager.userBackgroundColor,
transform: `translate(${(left + right) / 2}px, ${top}px)`,
}}>
- <Tooltip title={<>{this.props.view.Document.title}</>}>
- <p>d{this.props.index}</p>
+ <Tooltip title={<>{this._props.view.Document.title}</>}>
+ <p>d{this._props.index}</p>
</Tooltip>
</div>
);
@@ -74,7 +89,7 @@ export class DocumentIconContainer extends React.Component {
getVars() {
const docs = DocumentIcon.DocViews;
const capturedVariables: { [name: string]: Field } = {};
- usedDocuments.forEach(index => (capturedVariables[`d${index}`] = docs.length > index ? docs[index].props.Document : `d${index}`));
+ usedDocuments.forEach(index => (capturedVariables[`d${index}`] = docs.length > index ? docs[index].Document : `d${index}`));
return capturedVariables;
},
};
diff --git a/src/client/views/nodes/LinkAnchorBox.tsx b/src/client/views/nodes/LinkAnchorBox.tsx
index 09ba0bc95..31aa15588 100644
--- a/src/client/views/nodes/LinkAnchorBox.tsx
+++ b/src/client/views/nodes/LinkAnchorBox.tsx
@@ -1,4 +1,4 @@
-import { action, computed, observable } from 'mobx';
+import { action, computed, makeObservable, observable, override } from 'mobx';
import { observer } from 'mobx-react';
import { Doc } from '../../../fields/Doc';
import { NumCast, StrCast } from '../../../fields/Types';
@@ -29,18 +29,26 @@ export class LinkAnchorBox extends ViewBoxBaseComponent<FieldViewProps>() {
@observable _x = 0;
@observable _y = 0;
+ _prevProps: FieldViewProps;
+ @override _props: FieldViewProps;
+ constructor(props: FieldViewProps) {
+ super(props);
+ this._props = this._prevProps = props;
+ makeObservable(this);
+ }
+
componentDidMount() {
- this.props.setContentView?.(this);
+ this._props.setContentView?.(this);
}
@computed get linkSource() {
- return this.props.docViewPath()[this.props.docViewPath().length - 2].Document; // this.props.styleProvider?.(this.dataDoc, this.props, StyleProp.LinkSource);
+ return this._props.docViewPath()[this._props.docViewPath().length - 2].Document; // this._props.styleProvider?.(this.dataDoc, this._props, StyleProp.LinkSource);
}
onPointerDown = (e: React.PointerEvent) => {
setupMoveUpEvents(this, e, this.onPointerMove, emptyFunction, (e, doubleTap) => {
if (doubleTap) LinkFollower.FollowLink(this.Document, this.linkSource, false);
- else this.props.select(false);
+ else this._props.select(false);
});
};
onPointerMove = action((e: PointerEvent, down: number[], delta: number[]) => {
@@ -68,16 +76,16 @@ export class LinkAnchorBox extends ViewBoxBaseComponent<FieldViewProps>() {
render() {
TraceMobx();
- const small = this.props.PanelWidth() <= 1; // this happens when rendered in a treeView
+ const small = this._props.PanelWidth() <= 1; // this happens when rendered in a treeView
const x = NumCast(this.layoutDoc[this.fieldKey + '_x'], 100);
const y = NumCast(this.layoutDoc[this.fieldKey + '_y'], 100);
- const background = this.props.styleProvider?.(this.dataDoc, this.props, StyleProp.BackgroundColor + ':anchor');
+ const background = this._props.styleProvider?.(this.dataDoc, this._props, StyleProp.BackgroundColor + ':anchor');
const anchor = this.fieldKey === 'link_anchor_1' ? 'link_anchor_2' : 'link_anchor_1';
const anchorScale = !this.dataDoc[this.fieldKey + '_useSmallAnchor'] && (x === 0 || x === 100 || y === 0 || y === 100) ? 1 : 0.25;
const targetTitle = StrCast((this.dataDoc[anchor] as Doc)?.title);
- const selView = SelectionManager.Views().lastElement()?.props.LayoutTemplateString?.includes('link_anchor_1')
+ const selView = SelectionManager.Views().lastElement()?._props.LayoutTemplateString?.includes('link_anchor_1')
? 'link_anchor_1'
- : SelectionManager.Views().lastElement()?.props.LayoutTemplateString?.includes('link_anchor_2')
+ : SelectionManager.Views().lastElement()?._props.LayoutTemplateString?.includes('link_anchor_2')
? 'link_anchor_2'
: '';
return (
@@ -87,7 +95,7 @@ export class LinkAnchorBox extends ViewBoxBaseComponent<FieldViewProps>() {
className={`linkAnchorBox-cont${small ? '-small' : ''}`}
onPointerEnter={e =>
LinkInfo.SetLinkInfo({
- docProps: this.props,
+ docProps: this._props,
linkSrc: this.linkSource,
linkDoc: this.Document,
showHeader: true,
diff --git a/src/client/views/nodes/LinkBox.tsx b/src/client/views/nodes/LinkBox.tsx
index ff2597fb4..acafd6d09 100644
--- a/src/client/views/nodes/LinkBox.tsx
+++ b/src/client/views/nodes/LinkBox.tsx
@@ -1,10 +1,10 @@
import * as React from 'react';
import { Bezier } from 'bezier-js';
-import { computed, IReactionDisposer, observable, reaction } from 'mobx';
+import { computed, IReactionDisposer, makeObservable, observable, override, reaction } from 'mobx';
import { observer } from 'mobx-react';
import { Id } from '../../../fields/FieldSymbols';
import { DocCast, NumCast, StrCast } from '../../../fields/Types';
-import { aggregateBounds, emptyFunction, returnAlways, returnFalse, Utils } from '../../../Utils';
+import { aggregateBounds, copyProps, emptyFunction, returnAlways, returnFalse, Utils } from '../../../Utils';
import { DocumentManager } from '../../util/DocumentManager';
import { Transform } from '../../util/Transform';
import { CollectionFreeFormView } from '../collections/collectionFreeForm';
@@ -20,21 +20,33 @@ export class LinkBox extends ViewBoxBaseComponent<FieldViewProps>() {
return FieldView.LayoutString(LinkBox, fieldKey);
}
+ _prevProps: FieldViewProps;
+ @override _props: FieldViewProps;
+ constructor(props: FieldViewProps) {
+ super(props);
+ this._props = this._prevProps = props;
+ makeObservable(this);
+ }
+
+ componentDidUpdate() {
+ copyProps(this);
+ }
+
onClickScriptDisable = returnAlways;
@computed get anchor1() {
const anchor1 = DocCast(this.dataDoc.link_anchor_1);
const anchor_1 = anchor1?.layout_unrendered ? DocCast(anchor1.annotationOn) : anchor1;
- return DocumentManager.Instance.getDocumentView(anchor_1, this.props.docViewPath()[this.props.docViewPath().length - 2]); // this.props.docViewPath().lastElement());
+ return DocumentManager.Instance.getDocumentView(anchor_1, this._props.docViewPath()[this._props.docViewPath().length - 2]); // this._props.docViewPath().lastElement());
}
@computed get anchor2() {
const anchor2 = DocCast(this.dataDoc.link_anchor_2);
const anchor_2 = anchor2?.layout_unrendered ? DocCast(anchor2.annotationOn) : anchor2;
- return DocumentManager.Instance.getDocumentView(anchor_2, this.props.docViewPath()[this.props.docViewPath().length - 2]); // this.props.docViewPath().lastElement());
+ return DocumentManager.Instance.getDocumentView(anchor_2, this._props.docViewPath()[this._props.docViewPath().length - 2]); // this._props.docViewPath().lastElement());
}
screenBounds = () => {
if (this.layoutDoc._layout_isSvg && this.anchor1 && this.anchor2 && this.anchor1.CollectionFreeFormView) {
- const a_invXf = this.anchor1.props.ScreenToLocalTransform().inverse();
- const b_invXf = this.anchor2.props.ScreenToLocalTransform().inverse();
+ const a_invXf = this.anchor1._props.ScreenToLocalTransform().inverse();
+ const b_invXf = this.anchor2._props.ScreenToLocalTransform().inverse();
const a_scrBds = { tl: a_invXf.transformPoint(0, 0), br: a_invXf.transformPoint(NumCast(this.anchor1.Document._width), NumCast(this.anchor1.Document._height)) };
const b_scrBds = { tl: b_invXf.transformPoint(0, 0), br: b_invXf.transformPoint(NumCast(this.anchor2.Document._width), NumCast(this.anchor2.Document._height)) };
@@ -54,17 +66,17 @@ export class LinkBox extends ViewBoxBaseComponent<FieldViewProps>() {
};
disposer: IReactionDisposer | undefined;
componentDidMount() {
- this.props.setContentView?.(this);
+ this._props.setContentView?.(this);
this.disposer = reaction(
() => {
if (this.layoutDoc._layout_isSvg && (this.anchor1 || this.anchor2)?.CollectionFreeFormView) {
const a = (this.anchor1 ?? this.anchor2)!;
const b = (this.anchor2 ?? this.anchor1)!;
- const parxf = this.props.docViewPath()[this.props.docViewPath().length - 2].ComponentView as CollectionFreeFormView;
- const this_xf = parxf?.screenToLocalXf ?? Transform.Identity; //this.props.ScreenToLocalTransform();
- const a_invXf = a.props.ScreenToLocalTransform().inverse();
- const b_invXf = b.props.ScreenToLocalTransform().inverse();
+ const parxf = this._props.docViewPath()[this._props.docViewPath().length - 2].ComponentView as CollectionFreeFormView;
+ const this_xf = parxf?.screenToLocalXf ?? Transform.Identity; //this._props.ScreenToLocalTransform();
+ const a_invXf = a._props.ScreenToLocalTransform().inverse();
+ const b_invXf = b._props.ScreenToLocalTransform().inverse();
const a_scrBds = { tl: a_invXf.transformPoint(0, 0), br: a_invXf.transformPoint(NumCast(a.Document._width), NumCast(a.Document._height)) };
const b_scrBds = { tl: b_invXf.transformPoint(0, 0), br: b_invXf.transformPoint(NumCast(b.Document._width), NumCast(b.Document._height)) };
const a_bds = { tl: this_xf.transformPoint(a_scrBds.tl[0], a_scrBds.tl[1]), br: this_xf.transformPoint(a_scrBds.br[0], a_scrBds.br[1]) };
@@ -106,7 +118,7 @@ export class LinkBox extends ViewBoxBaseComponent<FieldViewProps>() {
@observable renderProps: { lx: number; rx: number; ty: number; by: number; pts: number[][] } | undefined = undefined;
render() {
if (this.renderProps) {
- const highlight = this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.Highlighting);
+ const highlight = this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.Highlighting);
const highlightColor = highlight?.highlightIndex ? highlight?.highlightColor : undefined;
const bez = new Bezier(this.renderProps.pts.map(p => ({ x: p[0], y: p[1] })));
@@ -131,7 +143,7 @@ export class LinkBox extends ViewBoxBaseComponent<FieldViewProps>() {
<path
className="collectionfreeformlinkview-linkLine"
style={{
- pointerEvents: this.props.pointerEvents?.() === 'none' ? 'none' : 'visibleStroke', //
+ pointerEvents: this._props.pointerEvents?.() === 'none' ? 'none' : 'visibleStroke', //
stroke: highlightColor ?? 'lightblue',
strokeDasharray,
strokeWidth,
@@ -142,7 +154,7 @@ export class LinkBox extends ViewBoxBaseComponent<FieldViewProps>() {
/>
<text
filter={`url(#${this.Document[Id] + 'background'})`}
- style={{ pointerEvents: this.props.pointerEvents?.() === 'none' ? 'none' : 'all', textAnchor: 'middle', fontSize: '12', stroke: 'black' }}
+ style={{ pointerEvents: this._props.pointerEvents?.() === 'none' ? 'none' : 'all', textAnchor: 'middle', fontSize: '12', stroke: 'black' }}
x={text.x - lx}
y={text.y - ty}>
<tspan>&nbsp;</tspan>
@@ -154,14 +166,14 @@ export class LinkBox extends ViewBoxBaseComponent<FieldViewProps>() {
);
}
return (
- <div className={`linkBox-container${this.props.isContentActive() ? '-interactive' : ''}`} style={{ background: this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.BackgroundColor) }}>
+ <div className={`linkBox-container${this._props.isContentActive() ? '-interactive' : ''}`} style={{ background: this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.BackgroundColor) }}>
<ComparisonBox
- {...this.props}
+ {...this._props}
fieldKey="link_anchor"
setHeight={emptyFunction}
dontRegisterView={true}
- renderDepth={this.props.renderDepth + 1}
- isContentActive={this.props.isContentActive}
+ renderDepth={this._props.renderDepth + 1}
+ isContentActive={this._props.isContentActive}
addDocument={returnFalse}
removeDocument={returnFalse}
moveDocument={returnFalse}