diff options
Diffstat (limited to 'src/client/views/nodes')
| -rw-r--r-- | src/client/views/nodes/DocumentView.tsx | 2 | ||||
| -rw-r--r-- | src/client/views/nodes/LinkAnchorBox.tsx | 4 | ||||
| -rw-r--r-- | src/client/views/nodes/LinkDocPreview.tsx | 96 | ||||
| -rw-r--r-- | src/client/views/nodes/PDFBox.tsx | 3 | ||||
| -rw-r--r-- | src/client/views/nodes/WebBox.tsx | 154 | ||||
| -rw-r--r-- | src/client/views/nodes/formattedText/DashFieldView.tsx | 49 | ||||
| -rw-r--r-- | src/client/views/nodes/formattedText/FormattedTextBox.tsx | 4 | ||||
| -rw-r--r-- | src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx | 4 |
8 files changed, 170 insertions, 146 deletions
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index b3acb08e2..abe59feb5 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -136,7 +136,7 @@ export interface DocComponentView { componentUI?: (boundsLeft: number, boundsTop: number) => JSX.Element | null; dragStarting?: (snapToDraggedDoc: boolean, showGroupDragTarget: boolean, visited: Set<Doc>) => void; incrementalRendering?: () => void; - infoUI?: () => JSX.Element; + infoUI?: () => JSX.Element | null; getCenter?: (xf: Transform) => { X: number; Y: number }; screenBounds?: () => Opt<{ left: number; top: number; right: number; bottom: number; center?: { X: number; Y: number } }>; ptToScreen?: (pt: { X: number; Y: number }) => { X: number; Y: number }; diff --git a/src/client/views/nodes/LinkAnchorBox.tsx b/src/client/views/nodes/LinkAnchorBox.tsx index 1b5161e47..33c9b2e08 100644 --- a/src/client/views/nodes/LinkAnchorBox.tsx +++ b/src/client/views/nodes/LinkAnchorBox.tsx @@ -11,7 +11,7 @@ import { ViewBoxBaseComponent } from '../DocComponent'; import { StyleProp } from '../StyleProvider'; import { FieldView, FieldViewProps } from './FieldView'; import './LinkAnchorBox.scss'; -import { LinkDocPreview } from './LinkDocPreview'; +import { LinkDocPreview, LinkInfo } from './LinkDocPreview'; import * as React from 'react'; // import globalCssVariables = require('../global/globalCssVariables.scss'); const MEDIUM_GRAY = 'lightGray'; @@ -85,7 +85,7 @@ export class LinkAnchorBox extends ViewBoxBaseComponent<FieldViewProps>() { title={targetTitle} className={`linkAnchorBox-cont${small ? '-small' : ''}`} onPointerEnter={e => - LinkDocPreview.SetLinkInfo({ + LinkInfo.SetLinkInfo({ docProps: this.props, linkSrc: this.linkSource, linkDoc: this.Document, diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx index dd102edef..108930ad9 100644 --- a/src/client/views/nodes/LinkDocPreview.tsx +++ b/src/client/views/nodes/LinkDocPreview.tsx @@ -1,11 +1,11 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Tooltip } from '@mui/material'; -import { action, computed, observable } from 'mobx'; +import { action, computed, makeObservable, observable, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import wiki from 'wikijs'; import { Doc, Opt } from '../../../fields/Doc'; import { Cast, DocCast, NumCast, PromiseValue, StrCast } from '../../../fields/Types'; -import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnEmptyString, returnFalse, returnNone, setupMoveUpEvents } from '../../../Utils'; +import { copyProps, emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnEmptyString, returnFalse, returnNone, setupMoveUpEvents } from '../../../Utils'; import { DocServer } from '../../DocServer'; import { Docs } from '../../documents/Documents'; import { DocumentType } from '../../documents/DocumentTypes'; @@ -20,6 +20,25 @@ import { DocumentView, DocumentViewSharedProps, OpenWhere } from './DocumentView import './LinkDocPreview.scss'; import * as React from 'react'; +export class LinkInfo { + private static _instance: Opt<LinkInfo>; + constructor() { + LinkInfo._instance = this; + makeObservable(this); + } + @observable public LinkInfo: Opt<LinkDocPreviewProps> = undefined; + + public static get Instance() { + return LinkInfo._instance ?? new LinkInfo(); + } + public static Clear() { + runInAction(() => LinkInfo.Instance && (LinkInfo.Instance.LinkInfo = undefined)); + } + public static SetLinkInfo(info?: LinkDocPreviewProps) { + runInAction(() => LinkInfo.Instance && (LinkInfo.Instance.LinkInfo = info)); + } +} + interface LinkDocPreviewProps { linkDoc?: Doc; linkSrc?: Doc; @@ -31,35 +50,28 @@ interface LinkDocPreviewProps { } @observer export class LinkDocPreview extends React.Component<LinkDocPreviewProps> { - @action public static Clear() { - LinkDocPreview.LinkInfo = undefined; - } - @action public static SetLinkInfo(info?: LinkDocPreviewProps) { - LinkDocPreview.LinkInfo !== info && (LinkDocPreview.LinkInfo = info); + _prevProps: LinkDocPreviewProps; + @observable _props: LinkDocPreviewProps; + constructor(props: LinkDocPreviewProps) { + super(props); + this._props = this._prevProps = props; + makeObservable(this); } - static _instance: Opt<LinkDocPreview>; - _infoRef = React.createRef<HTMLDivElement>(); _linkDocRef = React.createRef<HTMLDivElement>(); - @observable public static LinkInfo: Opt<LinkDocPreviewProps>; - @observable _targetDoc: Opt<Doc>; - @observable _markerTargetDoc: Opt<Doc>; - @observable _linkDoc: Opt<Doc>; - @observable _linkSrc: Opt<Doc>; + @observable _targetDoc: Opt<Doc> = undefined; + @observable _markerTargetDoc: Opt<Doc> = undefined; + @observable _linkDoc: Opt<Doc> = undefined; + @observable _linkSrc: Opt<Doc> = undefined; @observable _toolTipText = ''; @observable _hrefInd = 0; - constructor(props: any) { - super(props); - LinkDocPreview._instance = this; - } - @action init() { - var linkTarget = this.props.linkDoc; - this._linkSrc = this.props.linkSrc; - this._linkDoc = this.props.linkDoc; + var linkTarget = this._props.linkDoc; + this._linkSrc = this._props.linkSrc; + this._linkDoc = this._props.linkDoc; const link_anchor_1 = DocCast(this._linkDoc?.link_anchor_1); const link_anchor_2 = DocCast(this._linkDoc?.link_anchor_2); if (link_anchor_1 && link_anchor_2) { @@ -73,27 +85,27 @@ export class LinkDocPreview extends React.Component<LinkDocPreviewProps> { this.updateHref(); } componentDidUpdate(props: any) { - if (props.linkSrc !== this.props.linkSrc || props.linkDoc !== this.props.linkDoc || props.hrefs !== this.props.hrefs) this.init(); + copyProps(this); + if (props.linkSrc !== this._props.linkSrc || props.linkDoc !== this._props.linkDoc || props.hrefs !== this._props.hrefs) this.init(); } componentDidMount() { this.init(); document.addEventListener('pointerdown', this.onPointerDown, true); } - @action componentWillUnmount() { - LinkDocPreview.SetLinkInfo(undefined); + LinkInfo.Clear(); document.removeEventListener('pointerdown', this.onPointerDown, true); } onPointerDown = (e: PointerEvent) => { - !this._linkDocRef.current?.contains(e.target as any) && LinkDocPreview.Clear(); // close preview when not clicking anywhere other than the info bar of the preview + !this._linkDocRef.current?.contains(e.target as any) && LinkInfo.Clear(); // close preview when not clicking anywhere other than the info bar of the preview }; @action updateHref() { - if (this.props.hrefs?.length) { - const href = this.props.hrefs[this._hrefInd]; + if (this._props.hrefs?.length) { + const href = this._props.hrefs[this._hrefInd]; if (href.indexOf(Doc.localServerPath()) !== 0) { // link to a web page URL -- try to show a preview if (href.startsWith('https://en.wikipedia.org/wiki/')) { @@ -123,7 +135,7 @@ export class LinkDocPreview extends React.Component<LinkDocPreviewProps> { this._markerTargetDoc = linkTarget; this._targetDoc = /*linkTarget?.type === DocumentType.MARKER &&*/ linkTarget?.annotationOn ? Cast(linkTarget.annotationOn, Doc, null) ?? linkTarget : linkTarget; } - if (LinkDocPreview.LinkInfo?.noPreview || this._linkSrc?.followLinkToggle || this._markerTargetDoc?.type === DocumentType.PRES) this.followLink(); + if (LinkInfo.Instance?.LinkInfo?.noPreview || this._linkSrc?.followLinkToggle || this._markerTargetDoc?.type === DocumentType.PRES) this.followLink(); } }) ); @@ -143,7 +155,7 @@ export class LinkDocPreview extends React.Component<LinkDocPreviewProps> { action(() => { LinkManager.currentLink = this._linkDoc; LinkManager.currentLinkAnchor = this._linkSrc; - this.props.docProps.DocumentView?.().select(false); + this._props.docProps.DocumentView?.().select(false); if ((SettingsManager.Instance.propertiesWidth ?? 0) < 100) { SettingsManager.Instance.propertiesWidth = 250; } @@ -157,7 +169,7 @@ export class LinkDocPreview extends React.Component<LinkDocPreviewProps> { returnFalse, emptyFunction, action(() => { - const nextHrefInd = (this._hrefInd + 1) % (this.props.hrefs?.length || 1); + const nextHrefInd = (this._hrefInd + 1) % (this._props.hrefs?.length || 1); if (nextHrefInd !== this._hrefInd) { this._linkDoc = undefined; this._hrefInd = nextHrefInd; @@ -168,19 +180,19 @@ export class LinkDocPreview extends React.Component<LinkDocPreviewProps> { }; followLink = () => { - LinkDocPreview.Clear(); + LinkInfo.Clear(); if (this._linkDoc && this._linkSrc) { LinkFollower.FollowLink(this._linkDoc, this._linkSrc, false); - } else if (this.props.hrefs?.length) { + } else if (this._props.hrefs?.length) { const webDoc = - Array.from(SearchUtil.SearchCollection(Doc.MyFilesystem, this.props.hrefs[0]).keys()).lastElement() ?? - Docs.Create.WebDocument(this.props.hrefs[0], { title: this.props.hrefs[0], _nativeWidth: 850, _width: 200, _height: 400, data_useCors: true }); + Array.from(SearchUtil.SearchCollection(Doc.MyFilesystem, this._props.hrefs[0]).keys()).lastElement() ?? + Docs.Create.WebDocument(this._props.hrefs[0], { title: this._props.hrefs[0], _nativeWidth: 850, _width: 200, _height: 400, data_useCors: true }); DocumentManager.Instance.showDocument(webDoc, { openLocation: OpenWhere.lightbox, willPan: true, zoomTime: 500, }); - //this.props.docProps?.addDocTab(webDoc, OpenWhere.lightbox); + //this._props.docProps?.addDocTab(webDoc, OpenWhere.lightbox); } }; @@ -216,7 +228,7 @@ export class LinkDocPreview extends React.Component<LinkDocPreviewProps> { </div> <div className="linkDocPreview-buttonBar" style={{ float: 'right' }}> <Tooltip title={<div className="dash-tooltip">Next Link</div>} placement="top"> - <div className="linkDocPreview-button" style={{ background: (this.props.hrefs?.length || 0) <= 1 ? 'gray' : 'green' }} onPointerDown={this.nextHref}> + <div className="linkDocPreview-button" style={{ background: (this._props.hrefs?.length || 0) <= 1 ? 'gray' : 'green' }} onPointerDown={this.nextHref}> <FontAwesomeIcon className="linkDocPreview-fa-icon" icon="chevron-right" color="white" size="sm" /> </div> </Tooltip> @@ -228,7 +240,7 @@ export class LinkDocPreview extends React.Component<LinkDocPreviewProps> { @computed get docPreview() { return (!this._linkDoc || !this._targetDoc || !this._linkSrc) && !this._toolTipText ? null : ( <div className="linkDocPreview-inner"> - {!this.props.showHeader ? null : this.previewHeader} + {!this._props.showHeader ? null : this.previewHeader} <div className="linkDocPreview-preview-wrapper" onPointerDown={e => @@ -238,7 +250,7 @@ export class LinkDocPreview extends React.Component<LinkDocPreviewProps> { (e, down, delta) => { if (Math.abs(e.clientX - down[0]) + Math.abs(e.clientY - down[1]) > 100) { DragManager.StartDocumentDrag([this._infoRef.current!], new DragManager.DocumentDragData([this._targetDoc!]), e.pageX, e.pageY); - LinkDocPreview.Clear(); + LinkInfo.Clear(); return true; } return false; @@ -256,11 +268,11 @@ export class LinkDocPreview extends React.Component<LinkDocPreviewProps> { <DocumentView ref={r => { const targetanchor = this._linkDoc && this._linkSrc && LinkManager.getOppositeAnchor(this._linkDoc, this._linkSrc); - targetanchor && this._targetDoc !== targetanchor && r?.props.focus?.(targetanchor, {}); + targetanchor && this._targetDoc !== targetanchor && r?._props.focus?.(targetanchor, {}); }} Document={this._targetDoc!} moveDocument={returnFalse} - styleProvider={this.props.docProps?.styleProvider} + styleProvider={this._props.docProps?.styleProvider} docViewPath={returnEmptyDoclist} ScreenToLocalTransform={Transform.Identity} isDocumentActive={returnFalse} @@ -299,7 +311,7 @@ export class LinkDocPreview extends React.Component<LinkDocPreviewProps> { className="linkDocPreview" ref={this._linkDocRef} onPointerDown={this.followLinkPointerDown} - style={{ borderColor: SettingsManager.userColor, left: this.props.location[0], top: this.props.location[1], width: this.width() + borders, height: this.height() + borders + (this.props.showHeader ? 37 : 0) }}> + style={{ borderColor: SettingsManager.userColor, left: this._props.location[0], top: this._props.location[1], width: this.width() + borders, height: this.height() + borders + (this._props.showHeader ? 37 : 0) }}> {this.docPreview} </div> ); diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index 2a884cef8..a453210eb 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -611,8 +611,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps static pdfpromise = new Map<string, Promise<Pdfjs.PDFDocumentProxy>>(); render() { TraceMobx(); - const pdfView = this.renderPdfView; - + const pdfView = !this._pdf ? null : this.renderPdfView; const href = this.pdfUrl?.url.href; if (!pdfView && href) { if (PDFBox.pdfcache.get(href)) setTimeout(action(() => (this._pdf = PDFBox.pdfcache.get(href)))); diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index c722399c1..d74af9b27 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -1,6 +1,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { action, computed, IReactionDisposer, observable, ObservableMap, reaction, runInAction, trace } from 'mobx'; +import { action, computed, IReactionDisposer, makeObservable, observable, ObservableMap, override, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; +import * as React from 'react'; import * as WebRequest from 'web-request'; import { Doc, DocListCast, Field, Opt } from '../../../fields/Doc'; import { Id } from '../../../fields/FieldSymbols'; @@ -12,7 +13,7 @@ import { listSpec } from '../../../fields/Schema'; import { Cast, NumCast, StrCast, WebCast } from '../../../fields/Types'; import { ImageField, WebField } from '../../../fields/URLField'; import { TraceMobx } from '../../../fields/util'; -import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, emptyFunction, getWordAtPoint, lightOrDark, returnFalse, returnOne, returnZero, setupMoveUpEvents, smoothScroll, Utils } from '../../../Utils'; +import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, copyProps, emptyFunction, getWordAtPoint, lightOrDark, returnFalse, returnOne, returnZero, setupMoveUpEvents, smoothScroll, Utils } from '../../../Utils'; import { Docs, DocUtils } from '../../documents/Documents'; import { DocumentManager } from '../../util/DocumentManager'; import { ScriptingGlobals } from '../../util/ScriptingGlobals'; @@ -33,10 +34,9 @@ import { SidebarAnnos } from '../SidebarAnnos'; import { StyleProp } from '../StyleProvider'; import { DocComponentView, DocFocusOptions, DocumentView, DocumentViewProps, OpenWhere } from './DocumentView'; import { FieldView, FieldViewProps } from './FieldView'; -import { LinkDocPreview } from './LinkDocPreview'; +import { LinkInfo } from './LinkDocPreview'; import { PinProps, PresBox } from './trails'; import './WebBox.scss'; -import * as React from 'react'; const { CreateImage } = require('./WebBoxRenderer'); const _global = (window /* browser */ || global) /* node */ as any; const htmlToText = require('html-to-text'); @@ -95,12 +95,20 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps return this.allAnnotations.filter(a => a.text_inlineAnnotations); } @computed get webField() { - return Cast(this.Document[this.props.fieldKey], WebField)?.url; + return Cast(this.Document[this._props.fieldKey], WebField)?.url; } - constructor(props: any) { + _prevProps: ViewBoxAnnotatableProps & FieldViewProps; + @override _props: ViewBoxAnnotatableProps & FieldViewProps; + constructor(props: ViewBoxAnnotatableProps & FieldViewProps) { super(props); - runInAction(() => (this._webUrl = this._url)); // setting the weburl will change the src parameter of the embedded iframe and force a navigation to it. + this._props = this._prevProps = props; + makeObservable(this); + this._webUrl = this._url; // setting the weburl will change the src parameter of the embedded iframe and force a navigation to it. + } + + componentDidUpdate() { + copyProps(this); } @action @@ -139,7 +147,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps if (!this._iframe) return; const scrollTop = NumCast(this.layoutDoc._layout_scrollTop); const nativeWidth = NumCast(this.layoutDoc.nativeWidth); - const nativeHeight = (nativeWidth * this.props.PanelHeight()) / this.props.PanelWidth(); + const nativeHeight = (nativeWidth * this._props.PanelHeight()) / this._props.PanelWidth(); var htmlString = this._iframe.contentDocument && new XMLSerializer().serializeToString(this._iframe.contentDocument); if (!htmlString) { htmlString = await (await fetch(Utils.CorsProxy(this.webField!.href))).text(); @@ -170,8 +178,8 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps }); }; - async componentDidMount() { - this.props.setContentView?.(this); // this tells the DocumentView that this WebBox is the "content" of the document. this allows the DocumentView to call WebBox relevant methods to configure the UI (eg, show back/forward buttons) + componentDidMount() { + this._props.setContentView?.(this); // this tells the DocumentView that this WebBox is the "content" of the document. this allows the DocumentView to call WebBox relevant methods to configure the UI (eg, show back/forward buttons) runInAction(() => { this._annotationKeySuffix = () => (this._urlHash ? this._urlHash + '_' : '') + 'annotations'; @@ -200,8 +208,8 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps () => this.layoutDoc._layout_autoHeight, layout_autoHeight => { if (layout_autoHeight) { - this.layoutDoc._nativeHeight = NumCast(this.props.Document[this.props.fieldKey + '_nativeHeight']); - this.props.setHeight?.(NumCast(this.props.Document[this.props.fieldKey + '_nativeHeight']) * (this.props.NativeDimScaling?.() || 1)); + this.layoutDoc._nativeHeight = NumCast(this.Document[this._props.fieldKey + '_nativeHeight']); + this._props.setHeight?.(NumCast(this.Document[this._props.fieldKey + '_nativeHeight']) * (this._props.NativeDimScaling?.() || 1)); } } ); @@ -218,10 +226,8 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps } } // else it's an HTMLfield } else if (this.webField && !this.dataDoc.text) { - const result = await WebRequest.get(Utils.CorsProxy(this.webField.href)); - if (result) { - this.dataDoc.text = htmlToText.fromString(result.content); - } + WebRequest.get(Utils.CorsProxy(this.webField.href)) // + .then(result => result && (this.dataDoc.text = htmlToText.convert(result.content))); } this._disposers.scrollReaction = reaction( @@ -236,7 +242,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps { fireImmediately: true } ); } - @action componentWillUnmount() { + componentWillUnmount() { this._iframetimeout && clearTimeout(this._iframetimeout); this._iframetimeout = undefined; Object.values(this._disposers).forEach(disposer => disposer?.()); @@ -251,7 +257,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps @action createTextAnnotation = (sel: Selection, selRange: Range | undefined) => { if (this._mainCont.current && selRange) { - if (this.dataDoc[this.props.fieldKey] instanceof HtmlField) this._mainCont.current.style.transform = `rotate(${NumCast(this.props.DocumentView!().screenToLocalTransform().RotateDeg)}deg)`; + if (this.dataDoc[this._props.fieldKey] instanceof HtmlField) this._mainCont.current.style.transform = `rotate(${NumCast(this._props.DocumentView!().screenToLocalTransform().RotateDeg)}deg)`; const clientRects = selRange.getClientRects(); for (let i = 0; i < clientRects.length; i++) { const rect = clientRects.item(i); @@ -259,7 +265,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps if (rect && rect.width !== this._mainCont.current.clientWidth) { const annoBox = document.createElement('div'); annoBox.className = 'marqueeAnnotator-annotationBox'; - const scale = this._url ? 1 : this.props.ScreenToLocalTransform().Scale; + const scale = this._url ? 1 : this._props.ScreenToLocalTransform().Scale; // transforms the positions from screen onto the pdf div annoBox.style.top = ((rect.top - mainrect.translateY) * scale + (this._url ? this._mainCont.current.scrollTop : NumCast(this.layoutDoc.layout_scrollTop))).toString(); annoBox.style.left = ((rect.left - mainrect.translateX) * scale).toString(); @@ -282,7 +288,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps focus = (anchor: Doc, options: DocFocusOptions) => { if (anchor !== this.Document && this._outerRef.current) { - const windowHeight = this.props.PanelHeight() / (this.props.NativeDimScaling?.() || 1); + const windowHeight = this._props.PanelHeight() / (this._props.NativeDimScaling?.() || 1); const scrollTo = Utils.scrollIntoView(NumCast(anchor.y), NumCast(anchor._height), NumCast(this.layoutDoc._layout_scrollTop), windowHeight, windowHeight * 0.1, Math.max(NumCast(anchor.y) + NumCast(anchor._height), this._scrollHeight)); if (scrollTo !== undefined) { if (this._initialScroll === undefined) { @@ -298,8 +304,8 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps @action getView = (doc: Doc) => { - if (Doc.AreProtosEqual(doc, this.Document)) return new Promise<Opt<DocumentView>>(res => res(this.props.DocumentView?.())); - if (this.Document.layout_fieldKey === 'layout_icon') this.props.DocumentView?.().iconify(); + if (Doc.AreProtosEqual(doc, this.Document)) return new Promise<Opt<DocumentView>>(res => res(this._props.DocumentView?.())); + if (this.Document.layout_fieldKey === 'layout_icon') this._props.DocumentView?.().iconify(); const webUrl = WebCast(doc.config_data)?.url; if (this._url && webUrl && webUrl.href !== this._url) this.setData(webUrl.href); if (this._sidebarRef?.current?.makeDocUnfiltered(doc) && !this.SidebarShown) this.toggleSidebar(false); @@ -307,11 +313,11 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps }; sidebarAddDocTab = (doc: Doc, where: OpenWhere) => { - if (DocListCast(this.props.Document[this.props.fieldKey + '_sidebar']).includes(doc) && !this.SidebarShown) { + if (DocListCast(this.Document[this._props.fieldKey + '_sidebar']).includes(doc) && !this.SidebarShown) { this.toggleSidebar(false); return true; } - return this.props.addDocTab(doc, where); + return this._props.addDocTab(doc, where); }; getAnchor = (addAsAnnotation: boolean, pinProps?: PinProps) => { let ele: Opt<HTMLDivElement> = undefined; @@ -344,10 +350,10 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps iframeUp = (e: PointerEvent) => { this._getAnchor = AnchorMenu.Instance?.GetAnchor; // need to save AnchorMenu's getAnchor since a subsequent selection on another doc will overwrite this value this._textAnnotationCreator = undefined; - this.props.docViewPath().lastElement()?.docView?.cleanupPointerEvents(); // pointerup events aren't generated on containing document view, so we have to invoke it here. + this._props.docViewPath().lastElement()?.docView?.cleanupPointerEvents(); // pointerup events aren't generated on containing document view, so we have to invoke it here. if (this._iframe?.contentWindow && this._iframe.contentDocument && !this._iframe.contentWindow.getSelection()?.isCollapsed) { const mainContBounds = Utils.GetScreenTransform(this._mainCont.current!); - const scale = (this.props.NativeDimScaling?.() || 1) * mainContBounds.scale; + const scale = (this._props.NativeDimScaling?.() || 1) * mainContBounds.scale; const sel = this._iframe.contentWindow.getSelection(); if (sel) { this._selectionText = sel.toString(); @@ -355,7 +361,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps this._textAnnotationCreator = () => this.createTextAnnotation(sel, !sel.isCollapsed ? sel.getRangeAt(0) : undefined); AnchorMenu.Instance.jumpTo(e.clientX * scale + mainContBounds.translateX, e.clientY * scale + mainContBounds.translateY - NumCast(this.layoutDoc._layout_scrollTop) * scale); // Changing which document to add the annotation to (the currently selected WebBox) - GPTPopup.Instance.setSidebarId(`${this.props.fieldKey}_${this._urlHash ? this._urlHash + '_' : ''}sidebar`); + GPTPopup.Instance.setSidebarId(`${this._props.fieldKey}_${this._urlHash ? this._urlHash + '_' : ''}sidebar`); GPTPopup.Instance.addDoc = this.sidebarAddDocument; } } @@ -393,23 +399,23 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps this._textAnnotationCreator = () => this.createTextAnnotation(sel, selRange); (!sel.isCollapsed || this.marqueeing) && AnchorMenu.Instance.jumpTo(e.clientX, e.clientY); // Changing which document to add the annotation to (the currently selected WebBox) - GPTPopup.Instance.setSidebarId(`${this.props.fieldKey}_${this._urlHash ? this._urlHash + '_' : ''}sidebar`); + GPTPopup.Instance.setSidebarId(`${this._props.fieldKey}_${this._urlHash ? this._urlHash + '_' : ''}sidebar`); GPTPopup.Instance.addDoc = this.sidebarAddDocument; } }; @action iframeDown = (e: PointerEvent) => { - this.props.select(false); + this._props.select(false); const locpt = { - x: (e.clientX / NumCast(this.Document.nativeWidth)) * this.props.PanelWidth(), - y: ((e.clientY - NumCast(this.layoutDoc.layout_scrollTop))/ NumCast(this.Document.nativeHeight)) * this.props.PanelHeight() }; // prettier-ignore - const scrclick = this.props.DocumentView?.()._props.ScreenToLocalTransform().inverse().transformPoint(locpt.x, locpt.y)!; - const scrcent = this.props + x: (e.clientX / NumCast(this.Document.nativeWidth)) * this._props.PanelWidth(), + y: ((e.clientY - NumCast(this.layoutDoc.layout_scrollTop))/ NumCast(this.Document.nativeHeight)) * this._props.PanelHeight() }; // prettier-ignore + const scrclick = this._props.DocumentView?.()._props.ScreenToLocalTransform().inverse().transformPoint(locpt.x, locpt.y)!; + const scrcent = this._props .DocumentView?.() - .props.ScreenToLocalTransform() + ._props.ScreenToLocalTransform() .inverse() .transformPoint(NumCast(this.Document.width) / 2, NumCast(this.Document.height) / 2)!; - const theclickoff = Utils.rotPt(scrclick[0] - scrcent[0], scrclick[1] - scrcent[1], -this.props.ScreenToLocalTransform().Rotate); + const theclickoff = Utils.rotPt(scrclick[0] - scrcent[0], scrclick[1] - scrcent[1], -this._props.ScreenToLocalTransform().Rotate); const theclick = [theclickoff.x + scrcent[0], theclickoff.y + scrcent[1]]; MarqueeAnnotator.clearAnnotations(this._savedAnnotations); const word = getWordAtPoint(e.target, e.clientX, e.clientY); @@ -489,7 +495,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps this._scrollHeight = Math.max(this._scrollHeight, iframeContent.body.scrollHeight || 0); if (this._scrollHeight) { this.Document.nativeHeight = Math.min(NumCast(this.Document.nativeHeight), this._scrollHeight); - this.layoutDoc.height = Math.min(NumCast(this.layoutDoc._height), (NumCast(this.layoutDoc._width) * NumCast(this.dataDoc.nativeHeight)) / NumCast(this.dataDoc.nativeWidth)); + this.layoutDoc.height = Math.min(NumCast(this.layoutDoc._height), (NumCast(this.layoutDoc._width) * NumCast(this.Document.nativeHeight)) / NumCast(this.Document.nativeWidth)); } }; const swidth = Math.max(NumCast(this.layoutDoc.nativeWidth), iframeContent.body.scrollWidth || 0); @@ -564,7 +570,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps clearStyleSheetRules(WebBox.webStyleSheet); this._scrollTimer = undefined; const newScrollTop = scrollTop > iframeHeight ? iframeHeight : scrollTop; - if (!LinkDocPreview.LinkInfo && this._outerRef.current && newScrollTop !== this.layoutDoc.thumbScrollTop && (!LightboxView.LightboxDoc || LightboxView.IsLightboxDocView(this.props.docViewPath()))) { + if (!LinkInfo.Instance?.LinkInfo && this._outerRef.current && newScrollTop !== this.layoutDoc.thumbScrollTop && (!LightboxView.LightboxDoc || LightboxView.IsLightboxDocView(this._props.docViewPath()))) { this.layoutDoc.thumb = undefined; this.layoutDoc.thumbScrollTop = undefined; this.layoutDoc.thumbNativeWidth = undefined; @@ -709,7 +715,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps funcs.push({ description: (!this.layoutDoc.layout_reflowHorizontal ? 'Force' : 'Prevent') + ' Reflow', event: () => { - const nw = !this.layoutDoc.layout_reflowHorizontal ? undefined : Doc.NativeWidth(this.layoutDoc) - this.sidebarWidth() / (this.props.NativeDimScaling?.() || 1); + const nw = !this.layoutDoc.layout_reflowHorizontal ? undefined : Doc.NativeWidth(this.layoutDoc) - this.sidebarWidth() / (this._props.NativeDimScaling?.() || 1); this.layoutDoc.layout_reflowHorizontal = !nw; if (nw) { Doc.SetInPlace(this.layoutDoc, this.fieldKey + '_nativeWidth', nw, true); @@ -734,7 +740,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps if (sel?.empty) sel.empty(); // Chrome else if (sel?.removeAllRanges) sel.removeAllRanges(); // Firefox this.marqueeing = [e.clientX, e.clientY]; - if (!e.altKey && e.button === 0 && this.props.isContentActive(true) && ![InkTool.Highlighter, InkTool.Pen, InkTool.Write].includes(Doc.ActiveTool)) { + if (!e.altKey && e.button === 0 && this._props.isContentActive(true) && ![InkTool.Highlighter, InkTool.Pen, InkTool.Write].includes(Doc.ActiveTool)) { setupMoveUpEvents( this, e, @@ -770,7 +776,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps setTimeout(() => { // if menu comes up right away, the down event can still be active causing a menu item to be selected this.specificContextMenu(undefined as any); - this.props.docViewPath().lastElement().docView?.onContextMenu(undefined, x, y); + this._props.docViewPath().lastElement().docView?.onContextMenu(undefined, x, y); }); } } @@ -779,7 +785,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps @observable lighttext = false; @computed get urlContent() { - if (this.props.ScreenToLocalTransform().Scale > 25) return <div></div>; + if (this._props.ScreenToLocalTransform().Scale > 25) return <div></div>; setTimeout( action(() => { if (this._initialScroll === undefined && !this._webPageHasBeenRendered) { @@ -788,7 +794,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps this._webPageHasBeenRendered = true; }) ); - const field = this.dataDoc[this.props.fieldKey]; + const field = this.dataDoc[this._props.fieldKey]; if (field instanceof HtmlField) { return ( <span @@ -845,14 +851,14 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps e, action((e, down, delta) => { this._draggingSidebar = true; - const localDelta = this.props + const localDelta = this._props .ScreenToLocalTransform() - .scale(this.props.NativeDimScaling?.() || 1) + .scale(this._props.NativeDimScaling?.() || 1) .transformDirection(delta[0], delta[1]); const nativeWidth = NumCast(this.layoutDoc[this.fieldKey + '_nativeWidth']); const nativeHeight = NumCast(this.layoutDoc[this.fieldKey + '_nativeHeight']); const curNativeWidth = NumCast(this.layoutDoc.nativeWidth, nativeWidth); - const ratio = (curNativeWidth + ((onButton ? 1 : -1) * localDelta[0]) / (this.props.NativeDimScaling?.() || 1)) / nativeWidth; + const ratio = (curNativeWidth + ((onButton ? 1 : -1) * localDelta[0]) / (this._props.NativeDimScaling?.() || 1)) / nativeWidth; if (ratio >= 1) { this.layoutDoc.nativeWidth = nativeWidth * ratio; this.layoutDoc.nativeHeight = nativeHeight * (1 + ratio); @@ -916,7 +922,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps }); @action onZoomWheel = (e: React.WheelEvent) => { - if (this.props.isContentActive(true)) { + if (this._props.isContentActive(true)) { e.stopPropagation(); } }; @@ -924,14 +930,14 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps if (!this.SidebarShown) return 0; if (this._previewWidth) return WebBox.sidebarResizerWidth + WebBox.openSidebarWidth; // return default sidebar if previewing (as in viewing a link target) const nativeDiff = NumCast(this.layoutDoc.nativeWidth) - Doc.NativeWidth(this.dataDoc); - return WebBox.sidebarResizerWidth + nativeDiff * (this.props.NativeDimScaling?.() || 1); + return WebBox.sidebarResizerWidth + nativeDiff * (this._props.NativeDimScaling?.() || 1); }; _innerCollectionView: CollectionFreeFormView | undefined; zoomScaling = () => this._innerCollectionView?.zoomScaling() ?? 1; setInnerContent = (component: DocComponentView) => (this._innerCollectionView = component as CollectionFreeFormView); @computed get content() { - const interactive = this.props.isContentActive() && this.props.pointerEvents?.() !== 'none' && Doc.ActiveTool === InkTool.None; + const interactive = this._props.isContentActive() && this._props.pointerEvents?.() !== 'none' && Doc.ActiveTool === InkTool.None; return ( <div className={'webBox-cont' + (interactive ? '-interactive' : '')} @@ -959,7 +965,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps {this.inlineTextAnnotations .sort((a, b) => NumCast(a.y) - NumCast(b.y)) .map(anno => ( - <Annotation {...this.props} fieldKey={this.annotationKey} pointerEvents={this.pointerEvents} dataDoc={this.dataDoc} anno={anno} key={`${anno[Id]}-annotation`} /> + <Annotation {...this._props} fieldKey={this.annotationKey} pointerEvents={this.pointerEvents} dataDoc={this.dataDoc} anno={anno} key={`${anno[Id]}-annotation`} /> ))} </div> ); @@ -969,13 +975,13 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps } renderAnnotations = (childFilters: () => string[]) => ( <CollectionFreeFormView - {...this.props} + {...this._props} setContentView={this.setInnerContent} NativeWidth={returnZero} NativeHeight={returnZero} originTopLeft={false} isAnnotationOverlayScrollable={true} - renderDepth={this.props.renderDepth + 1} + renderDepth={this._props.renderDepth + 1} isAnnotationOverlay={true} fieldKey={this.annotationKey} setPreviewCursor={this.setPreviewCursor} @@ -1004,11 +1010,11 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps @computed get renderTransparentAnnotations() { return this.renderAnnotations(this.transparentFilter); } - childPointerEvents = () => (this.props.isContentActive() ? 'all' : undefined); + childPointerEvents = () => (this._props.isContentActive() ? 'all' : undefined); @computed get webpage() { const previewScale = this._previewNativeWidth ? 1 - this.sidebarWidth() / this._previewNativeWidth : 1; - const pointerEvents = this.layoutDoc._lockedPosition ? 'none' : (this.props.pointerEvents?.() as any); - const scale = previewScale * (this.props.NativeDimScaling?.() || 1); + const pointerEvents = this.layoutDoc._lockedPosition ? 'none' : (this._props.pointerEvents?.() as any); + const scale = previewScale * (this._props.NativeDimScaling?.() || 1); return ( <div className="webBox-outerContent" @@ -1021,7 +1027,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps onWheel={this.onZoomWheel} onScroll={e => this.setDashScrollTop(this._outerRef.current?.scrollTop || 0)} onPointerDown={this.onMarqueeDown}> - <div className="webBox-innerContent" style={{ height: (this._webPageHasBeenRendered && this._scrollHeight > this.props.PanelHeight() && this._scrollHeight) || '100%', pointerEvents }}> + <div className="webBox-innerContent" style={{ height: (this._webPageHasBeenRendered && this._scrollHeight > this._props.PanelHeight() && this._scrollHeight) || '100%', pointerEvents }}> {this.content} <div style={{ display: SnappingManager.GetCanEmbed() ? 'none' : undefined, mixBlendMode: 'multiply' }}>{this.renderTransparentAnnotations}</div> {this.renderOpaqueAnnotations} @@ -1033,7 +1039,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps @computed get searchUI() { return ( - <div className="webBox-ui" onPointerDown={e => e.stopPropagation()} style={{ display: this.props.isContentActive() ? 'flex' : 'none' }}> + <div className="webBox-ui" onPointerDown={e => e.stopPropagation()} style={{ display: this._props.isContentActive() ? 'flex' : 'none' }}> <div className="webBox-overlayCont" onPointerDown={e => e.stopPropagation()} style={{ left: `${this._searching ? 0 : 100}%` }}> <button className="webBox-overlayButton" title={'search'} /> <input @@ -1067,27 +1073,27 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps } searchStringChanged = (e: React.ChangeEvent<HTMLInputElement>) => (this._searchString = e.currentTarget.value); setPreviewCursor = (func?: (x: number, y: number, drag: boolean, hide: boolean, doc: Opt<Doc>) => void) => (this._setPreviewCursor = func); - panelWidth = () => this.props.PanelWidth() / (this.props.NativeDimScaling?.() || 1) - this.sidebarWidth() + WebBox.sidebarResizerWidth; - panelHeight = () => this.props.PanelHeight() / (this.props.NativeDimScaling?.() || 1); - scrollXf = () => this.props.ScreenToLocalTransform().translate(0, NumCast(this.layoutDoc._layout_scrollTop)); + panelWidth = () => this._props.PanelWidth() / (this._props.NativeDimScaling?.() || 1) - this.sidebarWidth() + WebBox.sidebarResizerWidth; + panelHeight = () => this._props.PanelHeight() / (this._props.NativeDimScaling?.() || 1); + scrollXf = () => this._props.ScreenToLocalTransform().translate(0, NumCast(this.layoutDoc._layout_scrollTop)); anchorMenuClick = () => this._sidebarRef.current?.anchorMenuClick; - transparentFilter = () => [...this.props.childFilters(), Utils.TransparentBackgroundFilter]; - opaqueFilter = () => [...this.props.childFilters(), Utils.noDragDocsFilter, ...(SnappingManager.GetCanEmbed() ? [] : [Utils.OpaqueBackgroundFilter])]; + transparentFilter = () => [...this._props.childFilters(), Utils.TransparentBackgroundFilter]; + opaqueFilter = () => [...this._props.childFilters(), Utils.noDragDocsFilter, ...(SnappingManager.GetCanEmbed() ? [] : [Utils.OpaqueBackgroundFilter])]; childStyleProvider = (doc: Doc | undefined, props: Opt<DocumentViewProps>, property: string): any => { if (doc instanceof Doc && property === StyleProp.PointerEvents) { if (this.inlineTextAnnotations.includes(doc)) return 'none'; } - return this.props.styleProvider?.(doc, props, property); + return this._props.styleProvider?.(doc, props, property); }; pointerEvents = () => - !this._draggingSidebar && this.props.isContentActive() && !MarqueeOptionsMenu.Instance?.isShown() + !this._draggingSidebar && this._props.isContentActive() && !MarqueeOptionsMenu.Instance?.isShown() ? 'all' // : 'none'; - annotationPointerEvents = () => (this.props.isContentActive() && (SnappingManager.GetIsDragging() || Doc.ActiveTool !== InkTool.None) ? 'all' : 'none'); + annotationPointerEvents = () => (this._props.isContentActive() && (SnappingManager.GetIsDragging() || Doc.ActiveTool !== InkTool.None) ? 'all' : 'none'); render() { const previewScale = this._previewNativeWidth ? 1 - this.sidebarWidth() / this._previewNativeWidth : 1; - const pointerEvents = this.layoutDoc._lockedPosition ? 'none' : (this.props.pointerEvents?.() as any); - const scale = previewScale * (this.props.NativeDimScaling?.() || 1); + const pointerEvents = this.layoutDoc._lockedPosition ? 'none' : (this._props.pointerEvents?.() as any); + const scale = previewScale * (this._props.NativeDimScaling?.() || 1); return ( <div className="webBox" @@ -1096,7 +1102,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps pointerEvents: this.pointerEvents(), // position: SnappingManager.GetIsDragging() ? 'absolute' : undefined, }}> - <div className="webBox-background" style={{ backgroundColor: this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.BackgroundColor) }} /> + <div className="webBox-background" style={{ backgroundColor: this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.BackgroundColor) }} /> <div className="webBox-container" style={{ @@ -1115,9 +1121,9 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps anchorMenuClick={this.anchorMenuClick} scrollTop={NumCast(this.layoutDoc.layout_scrollTop)} annotationLayerScrollTop={0} - scaling={this.props.NativeDimScaling} + scaling={this._props.NativeDimScaling} addDocument={this.addDocumentWrapper} - docView={this.props.DocumentView!} + docView={this._props.DocumentView!} finishMarquee={this.finishMarquee} savedAnnotations={this.savedAnnotationsCreator} selectionText={this.selectionText} @@ -1135,25 +1141,25 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps }} onPointerDown={e => this.sidebarBtnDown(e, false)} /> - <div style={{ position: 'absolute', height: '100%', right: 0, top: 0, width: `calc(100 * ${this.sidebarWidth() / this.props.PanelWidth()}%` }}> + <div style={{ position: 'absolute', height: '100%', right: 0, top: 0, width: `calc(100 * ${this.sidebarWidth() / this._props.PanelWidth()}%` }}> <SidebarAnnos ref={this._sidebarRef} - {...this.props} + {...this._props} whenChildContentsActiveChanged={this.whenChildContentsActiveChanged} fieldKey={this.fieldKey + '_' + this._urlHash} Document={this.Document} layoutDoc={this.layoutDoc} dataDoc={this.dataDoc} setHeight={emptyFunction} - nativeWidth={this._previewNativeWidth ?? NumCast(this.layoutDoc._nativeWidth) - WebBox.sidebarResizerWidth / (this.props.NativeDimScaling?.() || 1)} + nativeWidth={this._previewNativeWidth ?? NumCast(this.layoutDoc._nativeWidth) - WebBox.sidebarResizerWidth / (this._props.NativeDimScaling?.() || 1)} showSidebar={this.SidebarShown} sidebarAddDocument={this.sidebarAddDocument} moveDocument={this.moveDocument} removeDocument={this.removeDocument} /> </div> - {!this.props.isContentActive() || SnappingManager.GetIsDragging() ? null : this.sidebarHandle} - {!this.props.isContentActive() || SnappingManager.GetIsDragging() ? null : this.searchUI} + {!this._props.isContentActive() || SnappingManager.GetIsDragging() ? null : this.sidebarHandle} + {!this._props.isContentActive() || SnappingManager.GetIsDragging() ? null : this.searchUI} </div> ); } diff --git a/src/client/views/nodes/formattedText/DashFieldView.tsx b/src/client/views/nodes/formattedText/DashFieldView.tsx index 19e14d5a7..e2cceb906 100644 --- a/src/client/views/nodes/formattedText/DashFieldView.tsx +++ b/src/client/views/nodes/formattedText/DashFieldView.tsx @@ -1,6 +1,6 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Tooltip } from '@mui/material'; -import { action, computed, IReactionDisposer, observable } from 'mobx'; +import { action, computed, IReactionDisposer, makeObservable, observable } from 'mobx'; import { observer } from 'mobx-react'; import * as ReactDOM from 'react-dom/client'; import { Doc } from '../../../../fields/Doc'; @@ -8,7 +8,7 @@ import { List } from '../../../../fields/List'; import { listSpec } from '../../../../fields/Schema'; import { SchemaHeaderField } from '../../../../fields/SchemaHeaderField'; import { Cast, StrCast } from '../../../../fields/Types'; -import { emptyFunction, returnFalse, returnZero, setupMoveUpEvents } from '../../../../Utils'; +import { copyProps, emptyFunction, returnFalse, returnZero, setupMoveUpEvents } from '../../../../Utils'; import { DocServer } from '../../../DocServer'; import { CollectionViewType } from '../../../documents/DocumentTypes'; import { AntimodeMenu, AntimodeMenuProps } from '../../AntimodeMenu'; @@ -70,10 +70,10 @@ export class DashFieldView { } catch {} }); } - @action deselectNode() { + deselectNode() { this.dom.classList.remove('ProseMirror-selectednode'); } - @action selectNode() { + selectNode() { this.dom.classList.add('ProseMirror-selectednode'); } } @@ -100,17 +100,24 @@ export class DashFieldViewInternal extends React.Component<IDashFieldViewInterna @observable _dashDoc: Doc | undefined = undefined; @observable _expanded = false; + _prevProps: IDashFieldViewInternal; + @observable _props: IDashFieldViewInternal; constructor(props: IDashFieldViewInternal) { super(props); - this._fieldKey = this.props.fieldKey; - this._textBoxDoc = this.props.tbox.Document; + this._props = this._prevProps = props; + makeObservable(this); + this._fieldKey = this._props.fieldKey; + this._textBoxDoc = this._props.tbox.Document; - if (this.props.docId) { - DocServer.GetRefField(this.props.docId).then(action(dashDoc => dashDoc instanceof Doc && (this._dashDoc = dashDoc))); + if (this._props.docId) { + DocServer.GetRefField(this._props.docId).then(action(dashDoc => dashDoc instanceof Doc && (this._dashDoc = dashDoc))); } else { - this._dashDoc = this.props.tbox.Document; + this._dashDoc = this._props.tbox.Document; } } + componentDidUpdate(prevProps: Readonly<IDashFieldViewInternal>, prevState: Readonly<{}>, snapshot?: any): void { + copyProps(this); + } componentWillUnmount() { this._reactionDisposer?.(); } @@ -119,18 +126,18 @@ export class DashFieldViewInternal extends React.Component<IDashFieldViewInterna // set the display of the field's value (checkbox for booleans, span of text for strings) @computed get fieldValueContent() { return !this._dashDoc ? null : ( - <div onClick={action(e => (this._expanded = !this.props.editable ? !this._expanded : true))} style={{ fontSize: 'smaller', width: this.props.hideKey ? this.props.tbox.props.PanelWidth() - 20 : undefined }}> + <div onClick={action(e => (this._expanded = !this._props.editable ? !this._expanded : true))} style={{ fontSize: 'smaller', width: this._props.hideKey ? this._props.tbox._props.PanelWidth() - 20 : undefined }}> <SchemaTableCell Document={this._dashDoc} col={0} deselectCell={emptyFunction} selectCell={emptyFunction} - maxWidth={this.props.hideKey ? undefined : this.return100} - columnWidth={this.props.hideKey ? () => this.props.tbox._props.PanelWidth() - 20 : returnZero} + maxWidth={this._props.hideKey ? undefined : this.return100} + columnWidth={this._props.hideKey ? () => this._props.tbox._props.PanelWidth() - 20 : returnZero} selectedCell={() => [this._dashDoc!, 0]} fieldKey={this._fieldKey} rowHeight={returnZero} - isRowActive={() => this._expanded && this.props.editable} + isRowActive={() => this._expanded && this._props.editable} padding={0} getFinfo={emptyFunction} setColumnValues={returnFalse} @@ -145,7 +152,7 @@ export class DashFieldViewInternal extends React.Component<IDashFieldViewInterna } createPivotForField = (e: React.MouseEvent) => { - let container = this.props.tbox._props.DocumentView?.()._props.docViewPath().lastElement(); + let container = this._props.tbox._props.DocumentView?.()._props.docViewPath().lastElement(); if (container) { const embedding = Doc.MakeEmbedding(container.Document); embedding._type_collection = CollectionViewType.Time; @@ -157,7 +164,7 @@ export class DashFieldViewInternal extends React.Component<IDashFieldViewInterna list.map(c => c.heading).indexOf(this._fieldKey) === -1 && list.push(new SchemaHeaderField(this._fieldKey, '#f1efeb')); list.map(c => c.heading).indexOf('text') === -1 && list.push(new SchemaHeaderField('text', '#f1efeb')); embedding._pivotField = this._fieldKey.startsWith('#') ? 'tags' : this._fieldKey; - this.props.tbox._props.addDocTab(embedding, OpenWhere.addRight); + this._props.tbox._props.addDocTab(embedding, OpenWhere.addRight); } }; @@ -175,17 +182,17 @@ export class DashFieldViewInternal extends React.Component<IDashFieldViewInterna <div className="dashFieldView" style={{ - width: this.props.width, - height: this.props.height, - pointerEvents: this.props.tbox._props.isSelected() || this.props.tbox.isAnyChildContentActive?.() ? undefined : 'none', + width: this._props.width, + height: this._props.height, + pointerEvents: this._props.tbox._props.isSelected() || this._props.tbox.isAnyChildContentActive?.() ? undefined : 'none', }}> - {this.props.hideKey ? null : ( + {this._props.hideKey ? null : ( <span className="dashFieldView-labelSpan" title="click to see related tags" onPointerDown={this.onPointerDownLabelSpan}> {this._fieldKey} </span> )} - {this.props.fieldKey.startsWith('#') ? null : this.fieldValueContent} + {this._props.fieldKey.startsWith('#') ? null : this.fieldValueContent} </div> ); } @@ -198,7 +205,7 @@ export class DashFieldViewMenu extends AntimodeMenu<AntimodeMenuProps> { super(props); DashFieldViewMenu.Instance = this; } - @action + showFields = (e: React.MouseEvent) => { DashFieldViewMenu.createFieldView(e); DashFieldViewMenu.Instance.fadeOut(true); diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 244de7849..6b1df4560 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -55,7 +55,7 @@ import { StyleProp } from '../../StyleProvider'; import { media_state } from '../AudioBox'; import { DocFocusOptions, DocumentView, DocumentViewInternal, OpenWhere } from '../DocumentView'; import { FieldView, FieldViewProps } from '../FieldView'; -import { LinkDocPreview } from '../LinkDocPreview'; +import { LinkDocPreview, LinkInfo } from '../LinkDocPreview'; import { PinProps, PresBox } from '../trails'; import { DashDocCommentView } from './DashDocCommentView'; import { DashDocView } from './DashDocView'; @@ -1855,7 +1855,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps e.stopPropagation(); // drag n drop of text within text note will generate a new note if not caughst, as will dragging in from outside of Dash. }; onScroll = (e: React.UIEvent) => { - if (!LinkDocPreview.LinkInfo && this._scrollRef.current) { + if (!LinkInfo.Instance?.LinkInfo && this._scrollRef.current) { if (!this._props.dontSelectOnLoad) { this._ignoreScroll = true; this.layoutDoc._layout_scrollTop = this._scrollRef.current.scrollTop; diff --git a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx index 4212d46eb..be8736525 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx @@ -3,7 +3,7 @@ import { EditorState, NodeSelection } from 'prosemirror-state'; import { EditorView } from 'prosemirror-view'; import { Doc } from '../../../../fields/Doc'; import { DocServer } from '../../../DocServer'; -import { LinkDocPreview } from '../LinkDocPreview'; +import { LinkDocPreview, LinkInfo } from '../LinkDocPreview'; import { FormattedTextBox } from './FormattedTextBox'; import './FormattedTextBoxComment.scss'; import { schema } from './schema_rts'; @@ -133,7 +133,7 @@ export class FormattedTextBoxComment { const naft = findEndOfMark(state.selection.$from, view, findLinkMark) || nbef; //nbef && naft && - LinkDocPreview.SetLinkInfo({ + LinkInfo.SetLinkInfo({ docProps: textBox.props, linkSrc: textBox.Document, linkDoc: linkDoc ? (DocServer.GetCachedRefField(linkDoc) as Doc) : undefined, |
