From 5b5730a7df073659cbb6c326f748f7fcbe6625e8 Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 18 Jan 2024 15:05:53 -0500 Subject: lots of changes to try to simplify API for viewPaths and related --- src/client/views/nodes/AudioBox.tsx | 4 +- .../views/nodes/CollectionFreeFormDocumentView.tsx | 8 +- src/client/views/nodes/ComparisonBox.tsx | 5 +- src/client/views/nodes/DataVizBox/DataVizBox.tsx | 41 +-- src/client/views/nodes/DocumentContentsView.tsx | 11 +- src/client/views/nodes/DocumentIcon.tsx | 2 +- src/client/views/nodes/DocumentLinksButton.tsx | 4 +- src/client/views/nodes/DocumentView.tsx | 308 +++++++++++---------- src/client/views/nodes/EquationBox.tsx | 2 +- src/client/views/nodes/FieldView.tsx | 9 +- src/client/views/nodes/ImageBox.tsx | 8 +- src/client/views/nodes/KeyValuePair.tsx | 65 ++--- src/client/views/nodes/LinkAnchorBox.tsx | 14 +- src/client/views/nodes/LinkBox.tsx | 9 +- src/client/views/nodes/LinkDocPreview.tsx | 12 +- src/client/views/nodes/MapBox/MapBox.tsx | 4 +- src/client/views/nodes/MapBox/MapPushpinBox.tsx | 4 +- .../views/nodes/MapboxMapBox/MapboxContainer.tsx | 4 +- src/client/views/nodes/PDFBox.tsx | 8 +- src/client/views/nodes/VideoBox.tsx | 18 +- src/client/views/nodes/WebBox.tsx | 36 +-- .../views/nodes/formattedText/DashDocView.tsx | 4 +- .../views/nodes/formattedText/DashFieldView.tsx | 2 +- .../views/nodes/formattedText/FormattedTextBox.tsx | 16 +- .../formattedText/FormattedTextBoxComment.tsx | 3 +- src/client/views/nodes/trails/PresBox.tsx | 12 +- src/client/views/nodes/trails/PresElementBox.tsx | 10 +- 27 files changed, 331 insertions(+), 292 deletions(-) (limited to 'src/client/views/nodes') diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx index 908cd5dc0..1729af191 100644 --- a/src/client/views/nodes/AudioBox.tsx +++ b/src/client/views/nodes/AudioBox.tsx @@ -211,7 +211,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent() { // removes from currently playing display @action removeCurrentlyPlaying = () => { - const docView = this._props.DocumentView?.(); + const docView = this.DocumentView?.(); if (CollectionStackedTimeline.CurrentlyPlaying && docView) { const index = CollectionStackedTimeline.CurrentlyPlaying.indexOf(docView); index !== -1 && CollectionStackedTimeline.CurrentlyPlaying.splice(index, 1); @@ -221,7 +221,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent() { // adds doc to currently playing display @action addCurrentlyPlaying = () => { - const docView = this._props.DocumentView?.(); + const docView = this.DocumentView?.(); if (!CollectionStackedTimeline.CurrentlyPlaying) { CollectionStackedTimeline.CurrentlyPlaying = []; } diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index ad5aabc21..83cabf355 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -15,7 +15,7 @@ import { DocComponent } from '../DocComponent'; import { StyleProp } from '../StyleProvider'; import { CollectionFreeFormView } from '../collections/collectionFreeForm/CollectionFreeFormView'; import './CollectionFreeFormDocumentView.scss'; -import { DocumentView, DocumentViewInternalProps, DocumentViewProps, OpenWhere } from './DocumentView'; +import { DocumentView, DocumentViewProps, OpenWhere } from './DocumentView'; import { FieldViewProps } from './FieldView'; export interface CollectionFreeFormDocumentViewWrapperProps extends DocumentViewProps { @@ -149,7 +149,7 @@ export class CollectionFreeFormDocumentView extends DocComponent, property: string) => { + styleProvider = (doc: Doc | undefined, props: Opt, property: string) => { if (doc === this.layoutDoc) { switch (property) { case StyleProp.Opacity: return this._props.w_Opacity(); // only change the opacity for this specific document, not its children @@ -229,7 +229,7 @@ export class CollectionFreeFormDocumentView extends DocComponent { const topDoc = this.Document; - const containerDocView = this._props.docViewPath().lastElement(); + const containerDocView = this._props.containerViewPath?.().lastElement(); const screenXf = containerDocView?.screenToContentsTransform(); if (screenXf) { SelectionManager.DeselectAll(); @@ -252,7 +252,7 @@ export class CollectionFreeFormDocumentView extends DocComponent { - const [locX, locY] = this.ScreenToLocalBoxXf().transformDirection(x, y); + const [locX, locY] = this._props.ScreenToLocalTransform().transformDirection(x, y); this._props.Document.x = this._props.w_X() + locX; this._props.Document.y = this._props.w_Y() + locY; }; diff --git a/src/client/views/nodes/ComparisonBox.tsx b/src/client/views/nodes/ComparisonBox.tsx index 5e7e568b0..b171db17c 100644 --- a/src/client/views/nodes/ComparisonBox.tsx +++ b/src/client/views/nodes/ComparisonBox.tsx @@ -11,7 +11,7 @@ import { undoBatch } from '../../util/UndoManager'; import { ViewBoxAnnotatableComponent, ViewBoxAnnotatableProps } from '../DocComponent'; import { StyleProp } from '../StyleProvider'; import './ComparisonBox.scss'; -import { DocumentView, DocumentViewInternalProps, DocumentViewProps } from './DocumentView'; +import { DocumentView } from './DocumentView'; import { FieldView, FieldViewProps } from './FieldView'; import { PinProps, PresBox } from './trails'; @@ -148,7 +148,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent this.clearDoc(which) ); }; - docStyleProvider = (doc: Opt, props: Opt, property: string): any => { + docStyleProvider = (doc: Opt, props: Opt, property: string): any => { if (property === StyleProp.PointerEvents) return 'none'; return this._props.styleProvider?.(doc, props, property); }; @@ -178,6 +178,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent() { +export class DataVizBox extends ViewBoxAnnotatableComponent() { private _mainCont: React.RefObject = React.createRef(); - private _ffref = React.createRef(); private _marqueeref = React.createRef(); private _annotationLayer: React.RefObject = React.createRef(); anchorMenuClick?: () => undefined | ((anchor: Doc) => void); crop: ((region: Doc | undefined, addCrop?: boolean) => Doc | undefined) | undefined; - @observable schemaDataVizChildren: any = undefined; + @observable _schemaDataVizChildren: any = undefined; @observable _marqueeing: number[] | undefined = undefined; @observable _savedAnnotations = new ObservableMap(); + + constructor(props: ViewBoxAnnotatableProps & FieldViewProps) { + super(props); + makeObservable(this); + this._props.setContentView?.(this); + } + @computed get annotationLayer() { TraceMobx(); return
; } marqueeDown = (e: React.PointerEvent) => { - if (!e.altKey && e.button === 0 && NumCast(this.Document._freeform_scale, 1) <= NumCast(this.Document.freeform_scaleMin, 1) && this._props.isContentActive(true) && ![InkTool.Highlighter, InkTool.Pen, InkTool.Write].includes(Doc.ActiveTool)) { + if (!e.altKey && e.button === 0 && NumCast(this.Document._freeform_scale, 1) <= NumCast(this.Document.freeform_scaleMin, 1) && this._props.isContentActive() && ![InkTool.Highlighter, InkTool.Pen, InkTool.Write].includes(Doc.ActiveTool)) { setupMoveUpEvents( this, e, @@ -211,12 +216,12 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { .ScreenToLocalTransform() .scale(this._props.NativeDimScaling?.() || 1) .transformDirection(delta[0], delta[1]); - const fullWidth = this._props.width; - const mapWidth = fullWidth! - this.sidebarWidth(); + const fullWidth = NumCast(this.layoutDoc._width); + const mapWidth = fullWidth - this.sidebarWidth(); if (this.sidebarWidth() + localDelta[0] > 0) { this.layoutDoc._layout_showSidebar = true; - this.layoutDoc._width = fullWidth! + localDelta[0]; - this.layoutDoc._layout_sidebarWidthPercent = ((100 * (this.sidebarWidth() + localDelta[0])) / (fullWidth! + localDelta[0])).toString() + '%'; + this.layoutDoc._layout_sidebarWidthPercent = ((100 * (this.sidebarWidth() + localDelta[0])) / (fullWidth + localDelta[0])).toString() + '%'; + this.layoutDoc._width = fullWidth + localDelta[0]; } else { this.layoutDoc._layout_showSidebar = false; this.layoutDoc._width = mapWidth; @@ -269,12 +274,12 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { axes: this.axes, //width: this.SidebarShown? this._props.PanelWidth()*.9/1.2: this._props.PanelWidth() * 0.9, height: (this._props.PanelHeight() / scale - 32) /* height of 'change view' button */ * 0.9, - width: (this._props.PanelWidth() / scale) * 0.9, + width: ((this._props.PanelWidth() - this.sidebarWidth()) / scale) * 0.9, margin: { top: 10, right: 25, bottom: 75, left: 45 }, }; if (!this.records.length) return 'no data/visualization'; switch (this.dataVizView) { - case DataVizView.TABLE: return ; + case DataVizView.TABLE: return ; case DataVizView.LINECHART: return (this._vizRenderer = r ?? undefined)} vizBox={this} />; case DataVizView.HISTOGRAM: return (this._vizRenderer = r ?? undefined)} />; case DataVizView.PIECHART: return (this._vizRenderer = r ?? undefined)} @@ -285,7 +290,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { @action onPointerDown = (e: React.PointerEvent): void => { if ((this.Document._freeform_scale || 1) !== 1) return; - 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() && ![InkTool.Highlighter, InkTool.Pen, InkTool.Write].includes(Doc.ActiveTool)) { this._props.select(false); MarqueeAnnotator.clearAnnotations(this._savedAnnotations); this._marqueeing = [e.clientX, e.clientY]; @@ -345,7 +350,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { render() { if (this.layoutDoc && this.layoutDoc.dataViz_asSchema) { - this.schemaDataVizChildren = DocListCast(DocCast(this.layoutDoc.dataViz_asSchema)[Doc.LayoutFieldKey(DocCast(this.layoutDoc.dataViz_asSchema))]).length; + this._schemaDataVizChildren = DocListCast(DocCast(this.layoutDoc.dataViz_asSchema)[Doc.LayoutFieldKey(DocCast(this.layoutDoc.dataViz_asSchema))]).length; this.updateSchemaViz(); } @@ -366,7 +371,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { }} onWheel={e => e.stopPropagation()} ref={this._mainCont}> -
+
(this.layoutDoc._dataViz = DataVizView.TABLE)} toggleStatus={this.layoutDoc._dataViz === DataVizView.TABLE} /> (this.layoutDoc._dataViz = DataVizView.LINECHART)} toggleStatus={this.layoutDoc._dataViz === DataVizView.LINECHART} /> (this.layoutDoc._dataViz = DataVizView.HISTOGRAM)} toggleStatus={this.layoutDoc._dataViz === DataVizView.HISTOGRAM} /> @@ -414,7 +419,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() {
{this.sidebarHandle} {this.annotationLayer} - {!this._mainCont.current || !this._annotationLayer.current ? null : ( + {!this._mainCont.current || !this.DocumentView || !this._annotationLayer.current ? null : ( () { scrollTop={0} annotationLayerScrollTop={NumCast(this.Document._layout_scrollTop)} scaling={returnOne} - docView={this._props.DocumentView!} + docView={this.DocumentView} addDocument={this.sidebarAddDocument} finishMarquee={this.finishMarquee} savedAnnotations={this.savedAnnotations} diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx index 4cc7fe4c8..0d76959af 100644 --- a/src/client/views/nodes/DocumentContentsView.tsx +++ b/src/client/views/nodes/DocumentContentsView.tsx @@ -116,11 +116,12 @@ export class HTMLtag extends React.Component { @observer export class DocumentContentsView extends ObservableReactComponent< - DocumentViewProps & - FieldViewProps & { - setHeight?: (height: number) => void; - layout_fieldKey: string; - } + FieldViewProps & { + layout_fieldKey: string; + LayoutTemplateString?: string; + onClick?: () => ScriptField; + LayoutTemplate?: () => Opt; + } > { constructor(props: any) { super(props); diff --git a/src/client/views/nodes/DocumentIcon.tsx b/src/client/views/nodes/DocumentIcon.tsx index dfd610581..25f56e69a 100644 --- a/src/client/views/nodes/DocumentIcon.tsx +++ b/src/client/views/nodes/DocumentIcon.tsx @@ -25,7 +25,7 @@ export class DocumentIcon extends ObservableReactComponent { } 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.docViewPath)) : DocumentManager.Instance.DocumentViews; } render() { const view = this._props.view; diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx index c549a146a..f5949a451 100644 --- a/src/client/views/nodes/DocumentLinksButton.tsx +++ b/src/client/views/nodes/DocumentLinksButton.tsx @@ -152,8 +152,8 @@ export class DocumentLinksButton extends ObservableReactComponent Opt; -export type StyleProviderFunc = (doc: Opt, props: Opt, property: string) => any; +export type StyleProviderFunc = (doc: Opt, props: Opt, property: string) => any; export interface DocComponentView { fieldKey?: string; annotationKey?: string; @@ -143,20 +143,31 @@ export interface DocComponentView { snapPt?: (pt: { X: number; Y: number }, excludeSegs?: number[]) => { nearestPt: { X: number; Y: number }; distance: number }; search?: (str: string, bwd?: boolean, clear?: boolean) => boolean; } -// These props are passed to both FieldViews and DocumentViews +/** + * props that DocumentViews, DocumentInternalViews and FieldViews all can use + * */ export interface DocumentViewSharedProps { - renderDepth: number; Document: Doc; TemplateDataDocument?: Doc; + renderDepth: number; scriptContext?: any; // can be assigned anything and will be passed as 'scriptContext' to any OnClick script that executes on this document - DocumentView?: () => DocumentView; + treeViewDoc?: Doc; + xPadding?: number; + yPadding?: number; + dontRegisterView?: boolean; + dropAction?: dropActionType; + dragAction?: dropActionType; + forceAutoHeight?: boolean; + ignoreAutoHeight?: boolean; + disableBrushing?: boolean; // should highlighting for this view be disabled when same document in another view is hovered over. CollectionFreeFormDocumentView?: () => CollectionFreeFormDocumentView; fitContentsToBox?: () => boolean; // used by freeformview to fit its contents to its panel. corresponds to _freeform_fitContentsToBox property on a Document isGroupActive?: () => string | undefined; // is this document part of a group that is active setContentView?: (view: DocComponentView) => any; PanelWidth: () => number; PanelHeight: () => number; - docViewPath: () => DocumentView[]; + isDocumentActive?: () => boolean | undefined; // whether a document should handle pointer events + isContentActive: () => boolean | undefined; // whether document contents should handle pointer events childFilters: () => string[]; childFiltersByRanges: () => string[]; styleProvider: Opt; @@ -178,29 +189,12 @@ export interface DocumentViewSharedProps { waitForDoubleClickToClick?: () => 'never' | 'always' | undefined; defaultDoubleClick?: () => 'default' | 'ignore' | undefined; pointerEvents?: () => Opt; - treeViewDoc?: Doc; - xPadding?: number; - yPadding?: number; - dontRegisterView?: boolean; - childHideDecorationTitle?: boolean; - childHideResizeHandles?: boolean; - childDragAction?: dropActionType; // allows child documents to be dragged out of collection without holding the embedKey or dragging the doc decorations title bar. - dropAction?: dropActionType; - dragAction?: dropActionType; - dragWhenActive?: boolean; - dontHideOnDrag?: boolean; - hideLinkButton?: boolean; - hideCaptions?: boolean; - ignoreAutoHeight?: boolean; - forceAutoHeight?: boolean; - suppressSetHeight?: boolean; - disableBrushing?: boolean; // should highlighting for this view be disabled when same document in another view is hovered over. - onClickScriptDisable?: 'never' | 'always'; // undefined = only when selected } -// these props are specific to DocuentViews +/** + * props that are used by DocumentViews and DocumentInternalViews but not by the contents of those views (FieldViews). + */ export interface DocumentViewProps extends DocumentViewSharedProps { - // properties specific to DocumentViews but not to FieldView hideDecorations?: boolean; // whether to suppress all DocumentDecorations when doc is selected hideResizeHandles?: boolean; // whether to suppress resized handles on doc decorations when this document is selected hideTitle?: boolean; // forces suppression of title. e.g, treeView document labels suppress titles in case they are globally active via settings @@ -209,15 +203,22 @@ export interface DocumentViewProps extends DocumentViewSharedProps { hideOpenButton?: boolean; hideDeleteButton?: boolean; hideLinkAnchors?: boolean; + hideLinkButton?: boolean; + hideCaptions?: boolean; contentPointerEvents?: 'none' | 'all' | undefined; // pointer events allowed for content of a document view. eg. set to "none" in menuSidebar for sharedDocs so that you can select a document, but not interact with its contents LayoutTemplateString?: string; dontCenter?: 'x' | 'y' | 'xy'; - isDocumentActive?: () => boolean | undefined; // whether a document should handle pointer events - isContentActive: () => boolean | undefined; // whether document contents should handle pointer events + childHideDecorationTitle?: boolean; + childHideResizeHandles?: boolean; + childDragAction?: dropActionType; // allows child documents to be dragged out of collection without holding the embedKey or dragging the doc decorations title bar. + dragWhenActive?: boolean; + dontHideOnDrag?: boolean; + suppressSetHeight?: boolean; + onClickScriptDisable?: 'never' | 'always'; // undefined = only when selected NativeWidth?: () => number; NativeHeight?: () => number; - NativeDimScaling?: () => number; // scaling the DocumentView does to transform its contents into its panel & needed by ScreenToLocal NOTE: Must also be added to FieldViewProps LayoutTemplate?: () => Opt; + containerViewPath?: () => DocumentView[]; contextMenuItems?: () => { script: ScriptField; filter?: ScriptField; label: string; icon: string }[]; onClick?: () => ScriptField; onDoubleClick?: () => ScriptField; @@ -229,12 +230,18 @@ export interface DocumentViewProps extends DocumentViewSharedProps { dragEnding?: () => void; } -// these props are only available in DocumentViewIntenral -export interface DocumentViewInternalProps extends DocumentViewProps { - isSelected: () => boolean; +/** + * props used by DocInternalViews and FieldViews but not DocumentViews + * these props correspond to things that the DocumentView creates and thus doesn't need to receive as a prop + */ +export interface DocumentViewInternalSharedProps { + DocumentView?: () => DocumentView; select: (ctrlPressed: boolean, shiftPress?: boolean) => void; - DocumentView: () => DocumentView; - viewPath: () => DocumentView[]; + isSelected: () => boolean; + NativeDimScaling?: () => number; // scaling the DocumentView does to transform its contents into its panel & needed by ScreenToLocal +} +export interface DocumentViewInternalProps extends DocumentViewProps, DocumentViewInternalSharedProps { + docViewPath: () => DocumentView[]; } @observer @@ -265,17 +272,24 @@ export class DocumentViewInternal extends DocComponent; + return this._props.styleProvider?.(this.layoutDoc, this.styleProps, StyleProp.ShowTitle) as Opt; } @computed get NativeDimScaling() { return this._props.NativeDimScaling?.() || 1; @@ -284,32 +298,32 @@ export class DocumentViewInternal extends DocComponent this._props.styleProvider?.(this.Document, this._props, StyleProp.PointerEvents), + () => this._props.styleProvider?.(this.Document, this.styleProps, StyleProp.PointerEvents), pointerevents => (this._pointerEvents = pointerevents), { fireImmediately: true } ); @@ -378,32 +392,32 @@ export class DocumentViewInternal extends DocComponent disposer?.()); } startDragging(x: number, y: number, dropAction: dropActionType, hideSource = false) { if (this._mainCont.current) { - const views = SelectionManager.Views.filter(dv => dv.docView?._mainCont.current); - const selected = views.length > 1 && views.some(dv => dv.Document === this.Document) ? views : [this._props.DocumentView()]; + const views = SelectionManager.Views.filter(dv => dv.ContentDiv); + const selected = views.length > 1 && views.some(dv => dv.Document === this.Document) ? views : [this.DocumentView()]; const dragData = new DragManager.DocumentDragData(selected.map(dv => dv.Document)); - const screenXf = this.props.DocumentView().screenToViewTransform(); + const screenXf = this.DocumentView().screenToViewTransform(); const [left, top] = screenXf.inverse().transformPoint(0, 0); dragData.offset = screenXf.transformDirection(x - left, y - top); dragData.dropAction = dropAction; dragData.treeViewDoc = this._props.treeViewDoc; dragData.removeDocument = this._props.removeDocument; dragData.moveDocument = this._props.moveDocument; - dragData.draggedViews = [this._props.DocumentView()]; + dragData.draggedViews = [this.DocumentView()]; dragData.canEmbed = this.Document.dragAction ?? this._props.dragAction ? true : false; DragManager.StartDocumentDrag( - selected.map(dv => dv.docView!._mainCont.current!), + selected.map(dv => dv.ContentDiv!), dragData, x, y, @@ -443,7 +457,7 @@ export class DocumentViewInternal extends DocComponent this.onDoubleClickHandler.script.run( { this: this.Document, scriptContext: this._props.scriptContext, - documentView: this._props.DocumentView(), + documentView: this.DocumentView(), clientX, clientY, altKey, shiftKey, ctrlKey, value: undefined, }, console.log ); @@ -451,7 +465,7 @@ export class DocumentViewInternal extends DocComponent LightboxView.Instance.AddDocTab(this.Document, OpenWhere.lightbox), 'double tap'); SelectionManager.DeselectAll(); - Doc.UnBrushDoc(this._props.Document); + Doc.UnBrushDoc(this.Document); } else { this._singleClickFunc?.(); } @@ -474,7 +488,7 @@ export class DocumentViewInternal extends DocComponent (sendToBack ? this._props.DocumentView()._props.bringToFront(this.Document, true) : + clickFunc ?? (() => (sendToBack ? this.DocumentView()._props.bringToFront(this.Document, true) : this._componentView?.select?.(e.ctrlKey || e.metaKey, e.shiftKey) ?? this._props.select(e.ctrlKey||e.shiftKey, e.metaKey))); const waitFordblclick = this._props.waitForDoubleClickToClick?.() ?? this.Document.waitForDoubleClickToClick; @@ -522,7 +536,7 @@ export class DocumentViewInternal extends DocComponent this._props.removeDocument?.(this._props.Document); + @undoBatch deleteClicked = () => this._props.removeDocument?.(this.Document); @undoBatch setToggleDetail = () => (this.Document.onClick = ScriptField.MakeScript( `toggleDetail(documentView, "${StrCast(this.Document.layout_fieldKey) @@ -612,7 +626,7 @@ export class DocumentViewInternal extends DocComponent { if (this._props.dontRegisterView || this._props.LayoutTemplateString?.includes(LinkAnchorBox.name)) return false; - if (this._props.Document === Doc.ActiveDashboard) { + if (this.Document === Doc.ActiveDashboard) { e.stopPropagation(); e.preventDefault(); alert( @@ -634,7 +648,7 @@ export class DocumentViewInternal extends DocComponent { - const portalLink = this.allLinks.find(d => d.link_anchor_1 === this._props.Document && d.link_relationship === 'portal to:portal from'); + const portalLink = this.allLinks.find(d => d.link_anchor_1 === this.Document && d.link_relationship === 'portal to:portal from'); if (!portalLink) { DocUtils.MakeLink( - this._props.Document, + this.Document, Docs.Create.FreeformDocument([], { _width: NumCast(this.layoutDoc._width) + 10, _height: Math.max(NumCast(this.layoutDoc._height), NumCast(this.layoutDoc._width) + 10), _isLightbox: true, _layout_fitWidth: true, - title: StrCast(this._props.Document.title) + ' [Portal]', + title: StrCast(this.Document.title) + ' [Portal]', }), { link_relationship: 'portal to:portal from' } ); @@ -686,7 +700,7 @@ export class DocumentViewInternal extends DocComponent { - if (this.Document.type !== DocumentType.MAP) DocumentViewInternal.SelectAfterContextMenu && !this._props.isSelected() && SelectionManager.SelectView(this._props.DocumentView(), false); // on a mac, the context menu is triggered on mouse down, but a YouTube video becaomes interactive when selected which means that the context menu won't show up. by delaying the selection until hopefully after the pointer up, the context menu will appear. + if (this.Document.type !== DocumentType.MAP) DocumentViewInternal.SelectAfterContextMenu && !this._props.isSelected() && SelectionManager.SelectView(this.DocumentView(), false); // on a mac, the context menu is triggered on mouse down, but a YouTube video becaomes interactive when selected which means that the context menu won't show up. by delaying the selection until hopefully after the pointer up, the context menu will appear. setTimeout(() => simulateMouseClick(document.elementFromPoint(e.clientX, e.clientY), e.clientX, e.clientY, e.screenX, e.screenY)); }; if (navigator.userAgent.includes('Macintosh')) { @@ -719,14 +733,14 @@ export class DocumentViewInternal extends DocComponent cm.addItem({ description: label, event: () => customScripts[i]?.script.run({ documentView: this, this: this.Document, scriptContext: this._props.scriptContext }), icon: 'sticky-note' }) ); this._props.contextMenuItems?.().forEach(item => item.label && cm.addItem({ description: item.label, event: () => item.script.script.run({ this: this.Document, scriptContext: this._props.scriptContext }), icon: item.icon as IconProp })); - if (!this._props.Document.isFolder) { - const templateDoc = Cast(this._props.Document[StrCast(this._props.Document.layout_fieldKey)], Doc, null); + if (!this.Document.isFolder) { + const templateDoc = Cast(this.Document[StrCast(this.Document.layout_fieldKey)], Doc, null); const appearance = cm.findByDescription('Appearance...'); const appearanceItems: ContextMenuProps[] = appearance && 'subitems' in appearance ? appearance.subitems : []; @@ -764,7 +778,7 @@ export class DocumentViewInternal extends DocComponent this.toggleFollowLink(false, false), icon: 'link' }); - !Doc.noviceMode && onClicks.push({ description: 'Edit onClick Script', event: () => UndoManager.RunInBatch(() => DocUtils.makeCustomViewClicked(this._props.Document, undefined, 'onClick'), 'edit onClick'), icon: 'terminal' }); + !Doc.noviceMode && onClicks.push({ description: 'Edit onClick Script', event: () => UndoManager.RunInBatch(() => DocUtils.makeCustomViewClicked(this.Document, undefined, 'onClick'), 'edit onClick'), icon: 'terminal' }); !existingOnClick && cm.addItem({ description: 'OnClick...', noexpand: true, subitems: onClicks, icon: 'mouse-pointer' }); } else if (LinkManager.Links(this.Document).length) { onClicks.push({ description: 'Restore On Click default', event: () => this.noOnClick(), icon: 'link' }); @@ -786,15 +800,15 @@ export class DocumentViewInternal extends DocComponent Doc.MakeMetadataFieldTemplate(this._props.Document, this._props.TemplateDataDocument), icon: 'concierge-bell' }); + moreItems.push({ description: 'Make View of Metadata Field', event: () => Doc.MakeMetadataFieldTemplate(this.Document, this._props.TemplateDataDocument), icon: 'concierge-bell' }); moreItems.push({ description: `${this.Document._chromeHidden ? 'Show' : 'Hide'} Chrome`, event: () => (this.Document._chromeHidden = !this.Document._chromeHidden), icon: 'project-diagram' }); - if (Cast(Doc.GetProto(this._props.Document).data, listSpec(Doc))) { - moreItems.push({ description: 'Export to Google Photos Album', event: () => GooglePhotos.Export.CollectionToAlbum({ collection: this._props.Document }).then(console.log), icon: 'caret-square-right' }); - moreItems.push({ description: 'Tag Child Images via Google Photos', event: () => GooglePhotos.Query.TagChildImages(this._props.Document), icon: 'caret-square-right' }); - moreItems.push({ description: 'Write Back Link to Album', event: () => GooglePhotos.Transactions.AddTextEnrichment(this._props.Document), icon: 'caret-square-right' }); + if (Cast(Doc.GetProto(this.Document).data, listSpec(Doc))) { + moreItems.push({ description: 'Export to Google Photos Album', event: () => GooglePhotos.Export.CollectionToAlbum({ collection: this.Document }).then(console.log), icon: 'caret-square-right' }); + moreItems.push({ description: 'Tag Child Images via Google Photos', event: () => GooglePhotos.Query.TagChildImages(this.Document), icon: 'caret-square-right' }); + moreItems.push({ description: 'Write Back Link to Album', event: () => GooglePhotos.Transactions.AddTextEnrichment(this.Document), icon: 'caret-square-right' }); } - moreItems.push({ description: 'Copy ID', event: () => Utils.CopyText(Doc.globalServerPath(this._props.Document)), icon: 'fingerprint' }); + moreItems.push({ description: 'Copy ID', event: () => Utils.CopyText(Doc.globalServerPath(this.Document)), icon: 'fingerprint' }); } } @@ -802,14 +816,14 @@ export class DocumentViewInternal extends DocComponent Doc.Zip(this._props.Document) }); - (this.Document._type_collection !== CollectionViewType.Docking || !Doc.noviceMode) && constantItems.push({ description: 'Share', event: () => SharingManager.Instance.open(this._props.DocumentView()), icon: 'users' }); - if (this._props.removeDocument && Doc.ActiveDashboard !== this._props.Document) { + constantItems.push({ description: 'Zip Export', icon: 'download', event: async () => Doc.Zip(this.Document) }); + (this.Document._type_collection !== CollectionViewType.Docking || !Doc.noviceMode) && constantItems.push({ description: 'Share', event: () => SharingManager.Instance.open(this.DocumentView()), icon: 'users' }); + if (this._props.removeDocument && Doc.ActiveDashboard !== this.Document) { // need option to gray out menu items ... preferably with a '?' that explains why they're grayed out (eg., no permissions) constantItems.push({ description: 'Close', event: this.deleteClicked, icon: 'times' }); } } - constantItems.push({ description: 'Show Metadata', event: () => this._props.addDocTab(this._props.Document, OpenWhere.addRightKeyvalue), icon: 'table-columns' }); + constantItems.push({ description: 'Show Metadata', event: () => this._props.addDocTab(this.Document, OpenWhere.addRightKeyvalue), icon: 'table-columns' }); cm.addItem({ description: 'General...', noexpand: false, subitems: constantItems, icon: 'question' }); const help = cm.findByDescription('Help...'); @@ -820,7 +834,7 @@ export class DocumentViewInternal extends DocComponent this._rootSelected; panelHeight = () => this._props.PanelHeight() - this.headerMargin; - screenToLocalContent = () => this.ScreenToLocalBoxXf().translate(0, -this.headerMargin); + screenToLocalContent = () => this._props.ScreenToLocalTransform().translate(0, -this.headerMargin); onClickFunc: any = () => (this.disableClickScriptFunc ? undefined : this.onClickHandler); setHeight = (height: number) => !this._props.suppressSetHeight && (this.layoutDoc._height = height); setContentView = action((view: { getAnchor?: (addAsAnnotation: boolean) => Doc; forward?: () => boolean; back?: () => boolean }) => (this._componentView = view)); @@ -912,7 +926,6 @@ export class DocumentViewInternal extends DocComponent this._props.PanelWidth() || 1; anchorPanelHeight = () => this._props.PanelHeight() || 1; - anchorStyleProvider = (doc: Opt, props: Opt, property: string): any => { + anchorStyleProvider = (doc: Opt, props: Opt, property: string): any => { // prettier-ignore switch (property.split(':')[0]) { case StyleProp.ShowTitle: return ''; @@ -976,7 +989,7 @@ export class DocumentViewInternal extends DocComponent, props: Opt, property: string) => this._props?.styleProvider?.(doc, props, property + ':caption'); + captionStyleProvider = (doc: Opt, props: Opt, property: string) => this._props?.styleProvider?.(doc, props, property + ':caption'); @observable _changingTitleField = false; @observable _dropDownInnerWidth = 0; fieldsDropdown = (inputOptions: string[], dropdownWidth: number, placeholder: string, onChange: (val: string | number) => void, onClose: () => void) => { @@ -1266,10 +1279,10 @@ export class DocumentViewInternal extends DocComponent { @computed public static get exploreMode() { return () => (SnappingManager.ExploreMode ? ScriptField.MakeScript('CollectionBrowseClick(documentView, clientX, clientY)', { documentView: 'any', clientX: 'number', clientY: 'number' })! : undefined); } - @observable public docView: DocumentViewInternal | undefined | null = undefined; - @observable public textHtmlOverlay: Opt = undefined; - @observable public textHtmlOverlayTime: Opt = undefined; + @observable private _docViewInternal: DocumentViewInternal | undefined | null = undefined; + @observable private _htmlOverlayText: Opt = undefined; @observable private _isHovering = false; + private _htmlOverlayEffect: Opt; - public htmlOverlayEffect: Opt; public get displayName() { - return 'DocumentView(' + this._props.Document?.title + ')'; + return 'DocumentView(' + this.Document?.title + ')'; } // this makes mobx trace() statements more descriptive public ContentRef = React.createRef(); public ViewTimer: NodeJS.Timeout | undefined; // timer for res @@ -1349,10 +1361,26 @@ export class DocumentView extends ObservableReactComponent { this.ViewTimer && clearTimeout(this.ViewTimer); this.layoutDoc._viewTransition = undefined; }; - public startDragging = (x: number, y: number, dropAction: dropActionType, hideSource = false) => this.docView?.startDragging(x, y, dropAction, hideSource); - - public showContextMenu = (pageX: number, pageY: number) => this.docView?.onContextMenu(undefined, pageX, pageY); - + playAnnotation = () => this._docViewInternal?.playAnnotation(); + noOnClick = () => this._docViewInternal?.noOnClick(); + makeIntoPortal = () => this._docViewInternal?.makeIntoPortal(); + setToggleDetail = () => this._docViewInternal?.setToggleDetail(); + onContextMenu = (e?: React.MouseEvent, pageX?: number, pageY?: number) => this._docViewInternal?.onContextMenu?.(e, pageX, pageY); + cleanupPointerEvents = () => this._docViewInternal?.cleanupPointerEvents(); + public startDragging = (x: number, y: number, dropAction: dropActionType, hideSource = false) => this._docViewInternal?.startDragging(x, y, dropAction, hideSource); + + public showContextMenu = (pageX: number, pageY: number) => this._docViewInternal?.onContextMenu(undefined, pageX, pageY); + + public setTextHtmlOverlay = action((text: string | undefined, effect?: Doc) => { + this._htmlOverlayText = text; + this._htmlOverlayEffect = effect; + }); + public setAnimateScaling = action((scale: number, time?: number) => { + if (this._docViewInternal) { + this._docViewInternal._animateScalingTo = scale; + this._docViewInternal._animateScaleTime = time; + } + }); public setAnimEffect = (presEffect: Doc, timeInMs: number, afterTrans?: () => void) => { this.AnimEffectTimer && clearTimeout(this.AnimEffectTimer); this.Document[Animation] = presEffect; @@ -1391,10 +1419,11 @@ export class DocumentView extends ObservableReactComponent { DocServer.GetRefField(docId).then(docx => LightboxView.Instance.SetLightboxDoc( (docx as Doc) ?? // reuse existing pivot view of documents, or else create a new collection - Docs.Create.StackingDocument([], { title: linkAnchor.title + '-pivot', _width: 500, _height: 500, target: linkAnchor, updateContentsScript: ScriptField.MakeScript('updateLinkCollection(this, this.target)') }, docId) + Docs.Create.StackingDocument([], { title: linkAnchor.title + '-pivot', _width: 500, _height: 500, target: linkAnchor, onViewMounted: ScriptField.MakeScript('updateLinkCollection(this, this.target)') }, docId) ) ); } + toggleFollowLink = (zoom?: boolean, setTargetToggle?: boolean): void => this._docViewInternal?.toggleFollowLink(zoom, setTargetToggle); get Document() { return this._props.Document; @@ -1403,19 +1432,19 @@ export class DocumentView extends ObservableReactComponent { return this._props.renderDepth === 0; } get dataDoc() { - return this.docView?.dataDoc ?? this.Document; + return this._docViewInternal?.dataDoc ?? this.Document; } get ContentDiv() { - return this.docView?.ContentDiv; + return this._docViewInternal?.ContentDiv; } get ComponentView() { - return this.docView?._componentView; + return this._docViewInternal?._componentView; } get allLinks() { - return (this.docView?.allLinks || []).filter(link => !link.link_matchEmbeddings || link.link_anchor_1 === this.Document || link.link_anchor_2 === this.Document); + return (this._docViewInternal?.allLinks || []).filter(link => !link.link_matchEmbeddings || link.link_anchor_1 === this.Document || link.link_anchor_2 === this.Document); } get LayoutFieldKey() { - return this.docView?.LayoutFieldKey || 'layout'; + return this._docViewInternal?.LayoutFieldKey || 'layout'; } @computed get layout_fitWidth() { return this._props.layout_fitWidth?.(this.layoutDoc) ?? this.layoutDoc?.layout_fitWidth; @@ -1439,8 +1468,17 @@ export class DocumentView extends ObservableReactComponent { @computed get linkCountView() { return ; } + /** + * path of DocumentViews terminating in the DocumentView that contains this DocumentView + */ + @computed get containerViewPath() { + return this._props.containerViewPath; + } + /** + * path of DocumentViews terminating in this DocumentView + */ @computed get docViewPath(): DocumentView[] { - return this._props.docViewPath ? [...this._props.docViewPath(), this] : [this]; + return this.containerViewPath ? [...this.containerViewPath(), this] : [this]; } @computed get layoutDoc() { return Doc.Layout(this.Document, this._props.LayoutTemplate?.()); @@ -1502,19 +1540,19 @@ export class DocumentView extends ObservableReactComponent { return this._props.CollectionFreeFormDocumentView?.(); } - public toggleNativeDimensions = () => this.docView && this.Document.type !== DocumentType.INK && Doc.toggleNativeDimensions(this.layoutDoc, this.docView.NativeDimScaling, this._props.PanelWidth(), this._props.PanelHeight()); + public toggleNativeDimensions = () => this._docViewInternal && this.Document.type !== DocumentType.INK && Doc.toggleNativeDimensions(this.layoutDoc, this._docViewInternal.NativeDimScaling, this._props.PanelWidth(), this._props.PanelHeight()); public getBounds = () => { - if (!this.docView?.ContentDiv || this._props.treeViewDoc || Doc.AreProtosEqual(this._props.Document, Doc.UserDoc())) { + if (!this._docViewInternal?.ContentDiv || this._props.treeViewDoc || Doc.AreProtosEqual(this.Document, Doc.UserDoc())) { return undefined; } - if (this.docView._componentView?.screenBounds?.()) { - return this.docView._componentView.screenBounds(); + if (this._docViewInternal._componentView?.screenBounds?.()) { + return this._docViewInternal._componentView.screenBounds(); } - const xf = this.docView.ScreenToLocalBoxXf().scale(this.nativeScaling).inverse(); + const xf = this._docViewInternal._props.ScreenToLocalTransform().scale(this.nativeScaling).inverse(); const [[left, top], [right, bottom]] = [xf.transformPoint(0, 0), xf.transformPoint(this.panelWidth, this.panelHeight)]; - if (this.docView._props.LayoutTemplateString?.includes(LinkAnchorBox.name)) { - const docuBox = this.docView.ContentDiv.getElementsByClassName('linkAnchorBox-cont'); + if (this._docViewInternal._props.LayoutTemplateString?.includes(LinkAnchorBox.name)) { + const docuBox = this._docViewInternal.ContentDiv.getElementsByClassName('linkAnchorBox-cont'); if (docuBox.length) return { ...docuBox[0].getBoundingClientRect(), center: undefined }; } return { left, top, right, bottom }; @@ -1522,11 +1560,11 @@ export class DocumentView extends ObservableReactComponent { public iconify(finished?: () => void, animateTime?: number) { this.ComponentView?.updateIcon?.(); - const animTime = this.docView?._animateScaleTime; - runInAction(() => this.docView && animateTime !== undefined && (this.docView._animateScaleTime = animateTime)); + const animTime = this._docViewInternal?._animateScaleTime; + runInAction(() => this._docViewInternal && animateTime !== undefined && (this._docViewInternal._animateScaleTime = animateTime)); const finalFinished = action(() => { finished?.(); - this.docView && (this.docView._animateScaleTime = animTime); + this._docViewInternal && (this._docViewInternal._animateScaleTime = animTime); }); const layout_fieldKey = Cast(this.Document.layout_fieldKey, 'string', null); if (layout_fieldKey !== 'layout_icon') { @@ -1541,12 +1579,12 @@ export class DocumentView extends ObservableReactComponent { } @undoBatch setCustomView = (custom: boolean, layout: string): void => { - Doc.setNativeView(this._props.Document); - custom && DocUtils.makeCustomViewClicked(this._props.Document, Docs.Create.StackingDocument, layout, undefined); + Doc.setNativeView(this.Document); + custom && DocUtils.makeCustomViewClicked(this.Document, Docs.Create.StackingDocument, layout, undefined); }; switchViews = (custom: boolean, view: string, finished?: () => void, useExistingLayout = false) => { - runInAction(() => this.docView && (this.docView._animateScalingTo = 0.1)); // shrink doc + runInAction(() => this._docViewInternal && (this._docViewInternal._animateScalingTo = 0.1)); // shrink doc setTimeout( action(() => { if (useExistingLayout && custom && this.Document['layout_' + view]) { @@ -1554,16 +1592,16 @@ export class DocumentView extends ObservableReactComponent { } else { this.setCustomView(custom, view); } - this.docView && (this.docView._animateScalingTo = 1); // expand it + this._docViewInternal && (this._docViewInternal._animateScalingTo = 1); // expand it setTimeout( action(() => { - this.docView && (this.docView._animateScalingTo = 0); + this._docViewInternal && (this._docViewInternal._animateScalingTo = 0); finished?.(); }), - this.docView ? Math.max(0, this.docView.animateScaleTime - 10) : 0 + this._docViewInternal ? Math.max(0, this._docViewInternal.animateScaleTime - 10) : 0 ); }), - this.docView ? Math.max(0, this.docView?.animateScaleTime - 10) : 0 + this._docViewInternal ? Math.max(0, this._docViewInternal?.animateScaleTime - 10) : 0 ); }; @@ -1606,29 +1644,21 @@ export class DocumentView extends ObservableReactComponent { componentDidMount() { runInAction(() => this.Document[DocViews].add(this)); - this._disposers.updateContentsScript = reaction(() => ScriptCast(this.Document.updateContentsScript)?.script?.run({ this: this.Document }).result, emptyFunction); - this._disposers.height = reaction( - // increase max auto height if document has been resized to be greater than current max - () => NumCast(this.layoutDoc._height), - action(height => { - const docMax = NumCast(this.layoutDoc.layout_maxAutoHeight); - if (docMax && docMax < height) this.layoutDoc.layout_maxAutoHeight = height; - }) - ); - !BoolCast(this._props.Document.dontRegisterView, this._props.dontRegisterView) && DocumentManager.Instance.AddView(this); + this._disposers.onViewMounted = reaction(() => ScriptCast(this.Document.onViewMounted)?.script?.run({ this: this.Document }).result, emptyFunction); + !BoolCast(this.Document.dontRegisterView, this._props.dontRegisterView) && DocumentManager.Instance.AddView(this); } componentWillUnmount() { - this.Document[DocViews].delete(this); + runInAction(() => this.Document[DocViews].delete(this)); Object.values(this._disposers).forEach(disposer => disposer?.()); - !BoolCast(this._props.Document.dontRegisterView, this._props.dontRegisterView) && DocumentManager.Instance.RemoveView(this); + !BoolCast(this.Document.dontRegisterView, this._props.dontRegisterView) && DocumentManager.Instance.RemoveView(this); } // want the htmloverlay to be able to fade in but we also want it to be display 'none' until it is needed. // unfortunately, CSS can't transition animate any properties for something that is display 'none'. // so we need to first activate the div, then, after a render timeout, start the opacity transition. @observable enableHtmlOverlayTransitions: boolean = false; @computed get htmlOverlay() { - const effect = StrCast(this.htmlOverlayEffect?.presentation_effect, StrCast(this.htmlOverlayEffect?.followLinkAnimEffect)); + const effect = StrCast(this._htmlOverlayEffect?.presentation_effect, StrCast(this._htmlOverlayEffect?.followLinkAnimEffect)); return (
{ setTimeout(action(() => (this.enableHtmlOverlayTransitions = val))); } }} - style={{ display: !this.textHtmlOverlay ? 'none' : undefined }}> + style={{ display: !this._htmlOverlayText ? 'none' : undefined }}>
{DocumentViewInternal.AnimationEffect(
- console.log('PARSE error', e)} renderInWrapper={false} jsx={StrCast(this.textHtmlOverlay)} /> + console.log('PARSE error', e)} renderInWrapper={false} jsx={StrCast(this._htmlOverlayText)} />
, - { ...(this.htmlOverlayEffect ?? {}), presentation_effect: effect ?? PresEffect.Zoom } as any as Doc, + { ...(this._htmlOverlayEffect ?? {}), presentation_effect: effect ?? PresEffect.Zoom } as any as Doc, this.Document )}
@@ -1663,7 +1693,7 @@ export class DocumentView extends ObservableReactComponent { return (
(this._isHovering = true))} onPointerLeave={action(() => (this._isHovering = false))}> - {!this._props.Document || !this._props.PanelWidth() ? null : ( + {!this.Document || !this._props.PanelWidth() ? null : (
{ { layout_fitWidth={this.layout_fitWidthFunc} ScreenToLocalTransform={this.screenToContentsTransform} focus={this._props.focus || emptyFunction} - ref={action((r: DocumentViewInternal | null) => r && (this.docView = r))} + ref={action((r: DocumentViewInternal | null) => r && (this._docViewInternal = r))} /> {this.htmlOverlay} {this.infoUI} diff --git a/src/client/views/nodes/EquationBox.tsx b/src/client/views/nodes/EquationBox.tsx index ff92c701f..ebad257ac 100644 --- a/src/client/views/nodes/EquationBox.tsx +++ b/src/client/views/nodes/EquationBox.tsx @@ -27,7 +27,7 @@ export class EquationBox extends ViewBoxBaseComponent() { componentDidMount() { this._props.setContentView?.(this); - if (EquationBox.SelectOnLoad === this.Document[Id] && (!LightboxView.LightboxDoc || LightboxView.IsLightboxDocView(this._props.docViewPath()))) { + if (EquationBox.SelectOnLoad === this.Document[Id] && (!LightboxView.LightboxDoc || LightboxView.IsLightboxDocView(this.docViewPath))) { this._props.select(false); this._ref.current!.mathField.focus(); diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index 008f10f26..b456807d7 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -6,23 +6,18 @@ import { Doc, Field, FieldResult, Opt } from '../../../fields/Doc'; import { List } from '../../../fields/List'; import { ScriptField } from '../../../fields/ScriptField'; import { WebField } from '../../../fields/URLField'; -import { DocumentViewSharedProps } from './DocumentView'; +import { DocumentView, DocumentViewInternalSharedProps, DocumentViewSharedProps } from './DocumentView'; // // these properties get assigned through the render() method of the DocumentView when it creates this node. // However, that only happens because the properties are "defined" in the markup for the field view. // See the LayoutString method on each field view : ImageBox, FormattedTextBox, etc. // -export interface FieldViewProps extends DocumentViewSharedProps { +export interface FieldViewProps extends DocumentViewSharedProps, DocumentViewInternalSharedProps { // FieldView specific props that are not part of DocumentView props fieldKey: string; - select: (isCtrlPressed: boolean) => void; - isContentActive: (outsideReaction?: boolean) => boolean | undefined; - isDocumentActive?: () => boolean | undefined; - isSelected: () => boolean; setHeight?: (height: number) => void; - NativeDimScaling?: () => number; // scaling the DocumentView does to transform its contents into its panel & needed by ScreenToLocal NOTE: Must also be added to DocumentViewInternalsProps onBrowseClick?: () => ScriptField | undefined; onKey?: (e: React.KeyboardEvent, fieldProps: FieldViewProps) => boolean | undefined; pointerEvents?: () => Opt; diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index a5853499f..4483d12ce 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -158,7 +158,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent { - const scaling = (this._props.DocumentView?.().screenToViewTransform().Scale || 1) / NumCast(this.layoutDoc._freeform_scale, 1); + const scaling = (this.DocumentView?.().screenToViewTransform().Scale || 1) / NumCast(this.layoutDoc._freeform_scale, 1); const nscale = NumCast(this._props.PanelWidth()) / scaling; const nw = nscale / NumCast(this.dataDoc[this.fieldKey + '_nativeWidth']); this.dataDoc[this.fieldKey + '_nativeHeight'] = NumCast(this.dataDoc[this.fieldKey + '_nativeHeight']) * nw; @@ -368,7 +368,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent this.ScreenToLocalBoxXf().translate(0, NumCast(this.layoutDoc._layout_scrollTop) * this.ScreenToLocalBoxXf().Scale); marqueeDown = (e: React.PointerEvent) => { - if (!e.altKey && e.button === 0 && NumCast(this.layoutDoc._freeform_scale, 1) <= NumCast(this.dataDoc.freeform_scaleMin, 1) && this._props.isContentActive(true) && ![InkTool.Highlighter, InkTool.Pen, InkTool.Write].includes(Doc.ActiveTool)) { + if (!e.altKey && e.button === 0 && NumCast(this.layoutDoc._freeform_scale, 1) <= NumCast(this.dataDoc.freeform_scaleMin, 1) && this._props.isContentActive() && ![InkTool.Highlighter, InkTool.Pen, InkTool.Write].includes(Doc.ActiveTool)) { setupMoveUpEvents( this, e, @@ -444,7 +444,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent {this.annotationLayer} - {!this._mainCont.current || !this._annotationLayer.current ? null : ( + {!this._mainCont.current || !this.DocumentView || !this._annotationLayer.current ? null : ( { }; render() { - const props: FieldViewProps = { - Document: this._props.doc, - childFilters: returnEmptyFilter, - childFiltersByRanges: returnEmptyFilter, - searchFilterDocs: returnEmptyDoclist, - styleProvider: DefaultStyleProvider, - docViewPath: returnEmptyDoclist, - fieldKey: this._props.keyName, - isSelected: returnFalse, - setHeight: returnFalse, - select: emptyFunction, - bringToFront: emptyFunction, - renderDepth: 1, - isContentActive: returnFalse, - whenChildContentsActiveChanged: emptyFunction, - ScreenToLocalTransform: Transform.Identity, - focus: emptyFunction, - PanelWidth: this._props.PanelWidth, - PanelHeight: this._props.PanelHeight, - addDocTab: returnFalse, - pinToPres: returnZero, - }; // let fieldKey = Object.keys(props.Document).indexOf(props.fieldKey) !== -1 ? props.fieldKey : "(" + props.fieldKey + ")"; let protoCount = 0; - let doc: Doc | undefined = props.Document; + let doc = this._props.doc; while (doc) { - if (Object.keys(doc).includes(props.fieldKey)) { + if (Object.keys(doc).includes(this._props.keyName)) { break; } protoCount++; @@ -106,17 +84,17 @@ export class KeyValuePair extends ObservableReactComponent { style={hover} className="keyValuePair-td-key-delete" onClick={undoBatch(() => { - if (Object.keys(props.Document).indexOf(props.fieldKey) !== -1) { - delete props.Document[props.fieldKey]; - } else delete DocCast(props.Document.proto)?.[props.fieldKey]; + if (Object.keys(this._props.doc).indexOf(this._props.keyName) !== -1) { + delete this._props.doc[this._props.keyName]; + } else delete DocCast(this._props.doc.proto)?.[this._props.keyName]; })}> X - pair[0].replace(/^_/, '') === props.fieldKey)?.[1].description ?? ''}> -
+ pair[0].replace(/^_/, '') === this._props.keyName)?.[1].description ?? ''}> +
{'('.repeat(parenCount)} - {props.fieldKey} + {this._props.keyName} {')'.repeat(parenCount)}
@@ -124,7 +102,32 @@ export class KeyValuePair extends ObservableReactComponent {
- Field.toKeyValueString(props.Document, props.fieldKey)} SetValue={(value: string) => KeyValueBox.SetField(props.Document, props.fieldKey, value)} /> + Field.toKeyValueString(this._props.doc, this._props.keyName)} + SetValue={(value: string) => KeyValueBox.SetField(this._props.doc, this._props.keyName, value)} + />
diff --git a/src/client/views/nodes/LinkAnchorBox.tsx b/src/client/views/nodes/LinkAnchorBox.tsx index b86ba72a0..864c1955b 100644 --- a/src/client/views/nodes/LinkAnchorBox.tsx +++ b/src/client/views/nodes/LinkAnchorBox.tsx @@ -7,13 +7,13 @@ import { TraceMobx } from '../../../fields/util'; import { DragManager } from '../../util/DragManager'; import { LinkFollower } from '../../util/LinkFollower'; import { SelectionManager } from '../../util/SelectionManager'; -import { ViewBoxBaseComponent } from '../DocComponent'; +import { ViewBoxBaseComponent, ViewBoxBaseProps } from '../DocComponent'; import { StyleProp } from '../StyleProvider'; import { FieldView, FieldViewProps } from './FieldView'; import './LinkAnchorBox.scss'; import { LinkInfo } from './LinkDocPreview'; const { default: { MEDIUM_GRAY }, } = require('../global/globalCssVariables.module.scss'); // prettier-ignore -export class LinkAnchorBox extends ViewBoxBaseComponent() { +export class LinkAnchorBox extends ViewBoxBaseComponent() { public static LayoutString(fieldKey: string) { return FieldView.LayoutString(LinkAnchorBox, fieldKey); } @@ -33,12 +33,13 @@ export class LinkAnchorBox extends ViewBoxBaseComponent() { } @computed get linkSource() { - return this._props.docViewPath()[this._props.docViewPath().length - 2].Document; // this._props.styleProvider?.(this.dataDoc, this._props, StyleProp.LinkSource); + return this.containerViewPath?.().lastElement().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); + const linkSource = this.linkSource; + linkSource && setupMoveUpEvents(this, e, this.onPointerMove, emptyFunction, (e, doubleTap) => { + if (doubleTap) LinkFollower.FollowLink(this.Document, linkSource, false); else this._props.select(false); }); }; @@ -86,7 +87,8 @@ export class LinkAnchorBox extends ViewBoxBaseComponent() { className={`linkAnchorBox-cont${small ? '-small' : ''}`} onPointerEnter={e => LinkInfo.SetLinkInfo({ - docProps: this._props, + DocumentView: this.DocumentView, + styleProvider: this._props.styleProvider, 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 7f1d41547..4221f464d 100644 --- a/src/client/views/nodes/LinkBox.tsx +++ b/src/client/views/nodes/LinkBox.tsx @@ -29,12 +29,12 @@ export class LinkBox extends ViewBoxBaseComponent() { @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.containerViewPath?.().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.containerViewPath?.().lastElement()); } screenBounds = () => { if (this.layoutDoc._layout_isSvg && this.anchor1 && this.anchor2 && this.anchor1.CollectionFreeFormView) { @@ -66,7 +66,7 @@ export class LinkBox extends ViewBoxBaseComponent() { 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 parxf = this.containerViewPath?.().lastElement().ComponentView as CollectionFreeFormView; const this_xf = parxf?.screenToFreeformContentsXf ?? Transform.Identity; //this.ScreenToLocalTransform(); const a_invXf = a.screenToViewTransform().inverse(); const b_invXf = b.screenToViewTransform().inverse(); @@ -161,12 +161,11 @@ export class LinkBox extends ViewBoxBaseComponent() { return (
; @@ -43,7 +44,8 @@ export class LinkInfo { interface LinkDocPreviewProps { linkDoc?: Doc; linkSrc?: Doc; - docProps: DocumentViewSharedProps; + DocumentView?: () => DocumentView; + styleProvider?: StyleProviderFunc; location: number[]; hrefs?: string[]; showHeader?: boolean; @@ -152,7 +154,7 @@ export class LinkDocPreview extends ObservableReactComponent { LinkManager.currentLink = this._linkDoc; LinkManager.currentLinkAnchor = this._linkSrc; - this._props.docProps.DocumentView?.().select(false); + this._props.DocumentView?.().select(false); if ((SettingsManager.Instance.propertiesWidth ?? 0) < 100) { SettingsManager.Instance.propertiesWidth = 250; } @@ -269,8 +271,8 @@ export class LinkDocPreview extends ObservableReactComponent { - const target = DocUtils.GetNewTextDoc('Note linked to ' + this.Document.title, 0, 0, 100, 100, undefined, annotationOn, undefined, 'yellow'); + const target = DocUtils.GetNewTextDoc('Note linked to ' + this.Document.title, 0, 0, 100, 100, undefined, annotationOn, 'yellow'); FormattedTextBox.SetSelectOnLoad(target); return target; }; - const docView = this._props.DocumentView?.(); + const docView = this.DocumentView?.(); docView && DragManager.StartAnchorAnnoDrag([ele], new DragManager.AnchorAnnoDragData(docView, sourceAnchorCreator, targetCreator), e.pageX, e.pageY, { dragComplete: e => { diff --git a/src/client/views/nodes/MapBox/MapPushpinBox.tsx b/src/client/views/nodes/MapBox/MapPushpinBox.tsx index 34e237007..fc5b4dd18 100644 --- a/src/client/views/nodes/MapBox/MapPushpinBox.tsx +++ b/src/client/views/nodes/MapBox/MapPushpinBox.tsx @@ -18,10 +18,10 @@ export class MapPushpinBox extends ViewBoxBaseComponent() { } get mapBoxView() { - return this._props.DocumentView?.()?._props.docViewPath().lastElement()?.ComponentView as MapBox; + return this.DocumentView?.()?.containerViewPath?.().lastElement()?.ComponentView as MapBox; } get mapBox() { - return this._props.DocumentView?.()._props.docViewPath().lastElement()?.Document; + return this.DocumentView?.().containerViewPath?.().lastElement()?.Document; } render() { diff --git a/src/client/views/nodes/MapboxMapBox/MapboxContainer.tsx b/src/client/views/nodes/MapboxMapBox/MapboxContainer.tsx index ea8496c99..e079f7457 100644 --- a/src/client/views/nodes/MapboxMapBox/MapboxContainer.tsx +++ b/src/client/views/nodes/MapboxMapBox/MapboxContainer.tsx @@ -228,11 +228,11 @@ export class MapBoxContainer extends ViewBoxAnnotatableComponent { - const target = DocUtils.GetNewTextDoc('Note linked to ' + this.Document.title, 0, 0, 100, 100, undefined, annotationOn, undefined, 'yellow'); + const target = DocUtils.GetNewTextDoc('Note linked to ' + this.Document.title, 0, 0, 100, 100, undefined, annotationOn, 'yellow'); FormattedTextBox.SetSelectOnLoad(target); return target; }; - const docView = this._props.DocumentView?.(); + const docView = this.DocumentView?.(); docView && DragManager.StartAnchorAnnoDrag([ele], new DragManager.AnchorAnnoDragData(docView, sourceAnchorCreator, targetCreator), e.pageX, e.pageY, { dragComplete: e => { diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index 959d5d88d..71c1b6a4c 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -102,7 +102,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent { // currently we render pdf icons as text labels - const docViewContent = this._props.docViewPath().lastElement().ContentDiv!; + const docViewContent = this.DocumentView?.().ContentDiv!; const filename = this.layoutDoc[Id] + '-icon' + new Date().getTime(); this._pdfViewer?._mainCont.current && CollectionFreeFormView.UpdateIcon( @@ -304,7 +304,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent { this._pdfViewer = pdfViewer; - const docView = this._props.DocumentView?.(); + const docView = this.DocumentView?.(); if (this._initialScrollTarget && docView) { this.focus(this._initialScrollTarget, { instant: true }); this._initialScrollTarget = undefined; @@ -525,7 +525,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent ) : ( -
setupMoveUpEvents(this, e, returnFalse, emptyFunction, () => SelectionManager.SelectView(this._props.DocumentView?.()!, false), true)}> +
setupMoveUpEvents(this, e, returnFalse, emptyFunction, () => SelectionManager.SelectView(this.DocumentView?.()!, false), true)}> () { +export class VideoBox extends ViewBoxAnnotatableComponent() { public static LayoutString(fieldKey: string) { return FieldView.LayoutString(VideoBox, fieldKey); } @@ -608,7 +608,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent() { // removes from currently playing display @action removeCurrentlyPlaying = () => { - const docView = this._props.DocumentView?.(); + const docView = this.DocumentView?.(); if (CollectionStackedTimeline.CurrentlyPlaying && docView) { const index = CollectionStackedTimeline.CurrentlyPlaying.indexOf(docView); index !== -1 && CollectionStackedTimeline.CurrentlyPlaying.splice(index, 1); @@ -617,7 +617,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent() { // adds doc to currently playing display @action addCurrentlyPlaying = () => { - const docView = this._props.DocumentView?.(); + const docView = this.DocumentView?.(); if (!CollectionStackedTimeline.CurrentlyPlaying) { CollectionStackedTimeline.CurrentlyPlaying = []; } @@ -749,7 +749,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent() { // starts marquee selection marqueeDown = (e: React.PointerEvent) => { - if (!e.altKey && e.button === 0 && NumCast(this.layoutDoc._freeform_scale, 1) === 1 && this._props.isContentActive(true) && ![InkTool.Highlighter, InkTool.Pen].includes(Doc.ActiveTool)) { + if (!e.altKey && e.button === 0 && NumCast(this.layoutDoc._freeform_scale, 1) === 1 && this._props.isContentActive() && ![InkTool.Highlighter, InkTool.Pen].includes(Doc.ActiveTool)) { setupMoveUpEvents( this, e, @@ -941,7 +941,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent() { style={{ pointerEvents: this.layoutDoc._lockedPosition ? 'none' : undefined, borderRadius, - overflow: this._props.docViewPath?.().slice(-1)[0].layout_fitWidth ? 'auto' : undefined, + overflow: this.DocumentView?.().layout_fitWidth ? 'auto' : undefined, }}>
() {
{this.annotationLayer} - {!this._mainCont.current || !this._annotationLayer.current ? null : ( + {!this._mainCont.current || !this.DocumentView || !this._annotationLayer.current ? null : ( () { annotationLayerScrollTop={0} scaling={returnOne} annotationLayerScaling={this._props.NativeDimScaling} - docView={this._props.DocumentView!} + docView={this.DocumentView} containerOffset={this.marqueeOffset} addDocument={this.addDocWithTimecode} finishMarquee={this.finishMarquee} @@ -1004,7 +1004,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent() { } @computed get UIButtons() { - const bounds = this._props.docViewPath().lastElement().getBounds(); + const bounds = this.DocumentView?.().getBounds(); const width = (bounds?.right || 0) - (bounds?.left || 0); const curTime = NumCast(this.layoutDoc._layout_currentTimecode); return ( diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index c3be2b390..86709e4d7 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -33,7 +33,7 @@ import { Annotation } from '../pdf/Annotation'; import { GPTPopup } from '../pdf/GPTPopup/GPTPopup'; import { SidebarAnnos } from '../SidebarAnnos'; import { StyleProp } from '../StyleProvider'; -import { DocComponentView, DocFocusOptions, DocumentView, DocumentViewInternalProps, DocumentViewProps, OpenWhere } from './DocumentView'; +import { DocComponentView, DocFocusOptions, DocumentView, OpenWhere } from './DocumentView'; import { FieldView, FieldViewProps } from './FieldView'; import { LinkInfo } from './LinkDocPreview'; import { PinProps, PresBox } from './trails'; @@ -250,7 +250,7 @@ export class WebBox extends ViewBoxAnnotatableComponent { if (this._mainCont.current && selRange) { - if (this.dataDoc[this._props.fieldKey] instanceof HtmlField) this._mainCont.current.style.transform = `rotate(${NumCast(this._props.DocumentView!().screenToContentsTransform().RotateDeg)}deg)`; + if (this.dataDoc[this._props.fieldKey] instanceof HtmlField) this._mainCont.current.style.transform = `rotate(${NumCast(this.DocumentView!().screenToContentsTransform().RotateDeg)}deg)`; const clientRects = selRange.getClientRects(); for (let i = 0; i < clientRects.length; i++) { const rect = clientRects.item(i); @@ -274,7 +274,8 @@ export class WebBox extends ViewBoxAnnotatableComponent { - if (Doc.AreProtosEqual(doc, this.Document)) return new Promise>(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>(res => res(this.DocumentView?.())); + if (this.Document.layout_fieldKey === 'layout_icon') this.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); @@ -343,7 +344,7 @@ export class WebBox extends ViewBoxAnnotatableComponent { 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.DocumentView?.()?.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; @@ -364,7 +365,8 @@ export class WebBox extends ViewBoxAnnotatableComponent iframeHeight ? iframeHeight : scrollTop; - if (!LinkInfo.Instance?.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.docViewPath))) { this.layoutDoc.thumb = undefined; this.layoutDoc.thumbScrollTop = undefined; this.layoutDoc.thumbNativeWidth = undefined; @@ -723,10 +725,11 @@ export class WebBox extends ViewBoxAnnotatableComponent { const sel = this._url ? this._iframe?.contentDocument?.getSelection() : window.document.getSelection(); this._textAnnotationCreator = undefined; - if (sel?.empty) sel.empty(); // Chrome + 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() && ![InkTool.Highlighter, InkTool.Pen, InkTool.Write].includes(Doc.ActiveTool)) { setupMoveUpEvents( this, e, @@ -750,7 +753,8 @@ export class WebBox extends ViewBoxAnnotatableComponent { // 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.DocumentView?.().onContextMenu(undefined, x, y); }); } } @@ -908,7 +912,7 @@ export class WebBox extends ViewBoxAnnotatableComponent { - if (this._props.isContentActive(true)) { + if (this._props.isContentActive()) { e.stopPropagation(); } }; @@ -1065,7 +1069,7 @@ export class WebBox extends ViewBoxAnnotatableComponent this._sidebarRef.current?.anchorMenuClick; transparentFilter = () => [...this._props.childFilters(), Utils.TransparentBackgroundFilter]; opaqueFilter = () => [...this._props.childFilters(), Utils.noDragDocsFilter, ...(SnappingManager.CanEmbed ? [] : [Utils.OpaqueBackgroundFilter])]; - childStyleProvider = (doc: Doc | undefined, props: Opt, property: string): any => { + childStyleProvider = (doc: Doc | undefined, props: Opt, property: string): any => { if (doc instanceof Doc && property === StyleProp.PointerEvents) { if (this.inlineTextAnnotations.includes(doc)) return 'none'; } @@ -1099,7 +1103,7 @@ export class WebBox extends ViewBoxAnnotatableComponent {this.webpage}
- {!this._mainCont.current || !this._annotationLayer.current ? null : ( + {!this._mainCont.current || !this.DocumentView || !this._annotationLayer.current ? null : (
{ - let container = this._props.tbox._props.DocumentView?.()._props.docViewPath().lastElement(); + let container = this._props.tbox.containerViewPath?.().lastElement(); if (container) { const embedding = Doc.MakeEmbedding(container.Document); embedding._type_collection = CollectionViewType.Time; diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index ae26f170b..6a6cec094 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -42,7 +42,7 @@ import { CollectionStackingView } from '../../collections/CollectionStackingView import { CollectionTreeView } from '../../collections/CollectionTreeView'; import { ContextMenu } from '../../ContextMenu'; import { ContextMenuProps } from '../../ContextMenuItem'; -import { ViewBoxAnnotatableComponent } from '../../DocComponent'; +import { ViewBoxAnnotatableComponent, ViewBoxAnnotatableProps } from '../../DocComponent'; import { Colors } from '../../global/globalEnums'; import { LightboxView } from '../../LightboxView'; import { AnchorMenu } from '../../pdf/AnchorMenu'; @@ -71,7 +71,7 @@ import { SummaryView } from './SummaryView'; export interface FormattedTextBoxProps {} @observer -export class FormattedTextBox extends ViewBoxAnnotatableComponent() { +export class FormattedTextBox extends ViewBoxAnnotatableComponent() { public static LayoutString(fieldStr: string) { return FieldView.LayoutString(FormattedTextBox, fieldStr); } @@ -123,7 +123,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent this.getAnchor(true), targetCreator), e.pageX, e.pageY); + DragManager.StartAnchorAnnoDrag([ele], new DragManager.AnchorAnnoDragData(this.DocumentView?.()!, () => this.getAnchor(true), targetCreator), e.pageX, e.pageY); }); const coordsB = this._editorView!.coordsAtPos(this._editorView!.state.selection.to); this._props.rootSelected?.() && AnchorMenu.Instance.jumpTo(coordsB.left, coordsB.bottom); @@ -1410,7 +1410,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent 0 && !state.doc.resolve(xpos).node()?.isTextblock) { @@ -1764,7 +1764,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent p + toHgt(child), margins); - const scrollHeight = this.ProseRef && Math.min(NumCast(this.layoutDoc.layout_maxAutoHeight, proseHeight), proseHeight); + const scrollHeight = this.ProseRef && proseHeight; if (this._props.setHeight && scrollHeight && !this._props.dontRegisterView) { // if top === 0, then the text box is growing upward (as the overlay caption) which doesn't contribute to the height computation const setScrollHeight = () => (this.dataDoc[this.fieldKey + '_scrollHeight'] = scrollHeight); @@ -1852,7 +1852,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent ) : ( -
setupMoveUpEvents(this, e, returnFalse, emptyFunction, () => SelectionManager.SelectView(this._props.DocumentView?.()!, false), true)}> +
setupMoveUpEvents(this, e, returnFalse, emptyFunction, () => SelectionManager.SelectView(this.DocumentView?.()!, false), true)}> [pos.left, pos.top + 25])(view.coordsAtPos(state.selection.from - Math.max(0, nbef - 1))), diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx index 6fa64a765..645ac08e1 100644 --- a/src/client/views/nodes/trails/PresBox.tsx +++ b/src/client/views/nodes/trails/PresBox.tsx @@ -294,13 +294,9 @@ export class PresBox extends ViewBoxBaseComponent() { listItemDoc.presentation_effect = this.activeItem.presBulletEffect; listItemDoc.presentation_transition = 500; targetView?.setAnimEffect(listItemDoc, 500); - if (targetView?.docView && this.activeItem.presBulletExpand) { - targetView.docView._animateScalingTo = 1.2; - targetView.docView._animateScaleTime = 400; - Doc.AddUnHighlightWatcher(() => { - targetView.docView!._animateScaleTime = undefined; - targetView!.docView!._animateScalingTo = 0; - }); + if (targetView && this.activeItem.presBulletExpand) { + targetView.setAnimateScaling(1.2, 400); + Doc.AddUnHighlightWatcher(() => targetView?.setAnimateScaling(0, undefined)); } listItemDoc.opacity = undefined; this.activeItem.presentation_indexed = presIndexed + 1; @@ -2622,7 +2618,7 @@ export class PresBox extends ViewBoxBaseComponent() { ScreenToLocalTransform={this.getTransform} AddToMap={this.AddToMap} RemFromMap={this.RemFromMap} - hierarchyIndex={emptyPath} + hierarchyIndex={emptyPath as any as number[]} /> ) : null}
diff --git a/src/client/views/nodes/trails/PresElementBox.tsx b/src/client/views/nodes/trails/PresElementBox.tsx index 4945d66c8..8cf01b9de 100644 --- a/src/client/views/nodes/trails/PresElementBox.tsx +++ b/src/client/views/nodes/trails/PresElementBox.tsx @@ -19,7 +19,7 @@ import { TreeView } from '../../collections/TreeView'; import { ViewBoxBaseComponent } from '../../DocComponent'; import { EditableView } from '../../EditableView'; import { Colors } from '../../global/globalEnums'; -import { DocumentView, DocumentViewInternalProps, DocumentViewProps } from '../../nodes/DocumentView'; +import { DocumentView } from '../../nodes/DocumentView'; import { FieldView, FieldViewProps } from '../../nodes/FieldView'; import { StyleProp } from '../../StyleProvider'; import { PresBox } from './PresBox'; @@ -50,7 +50,7 @@ export class PresElementBox extends ViewBoxBaseComponent() { // the presentation view that renders this slide @computed get presBoxView() { - return this._props.DocumentView?.()?._props.docViewPath().lastElement()?.ComponentView as PresBox; + return this.containerViewPath?.().lastElement()?.ComponentView as PresBox; } // the presentation view document that renders this slide @@ -97,7 +97,7 @@ export class PresElementBox extends ViewBoxBaseComponent() { presExpandDocumentClick = () => (this.slideDoc.presentation_expandInlineButton = !this.slideDoc.presentation_expandInlineButton); embedHeight = () => this.collapsedHeight + this.expandViewHeight; embedWidth = () => this._props.PanelWidth() / 2; - styleProvider = (doc: Doc | undefined, props: Opt, property: string): any => { + styleProvider = (doc: Doc | undefined, props: Opt, property: string): any => { return property === StyleProp.Opacity ? 1 : this._props.styleProvider?.(doc, props, property); }; /** @@ -116,7 +116,7 @@ export class PresElementBox extends ViewBoxBaseComponent() { hideLinkButton={true} ScreenToLocalTransform={Transform.Identity} renderDepth={this._props.renderDepth + 1} - docViewPath={returnEmptyDoclist} + containerViewPath={returnEmptyDoclist} childFilters={this._props.childFilters} childFiltersByRanges={this._props.childFiltersByRanges} searchFilterDocs={this._props.searchFilterDocs} @@ -196,7 +196,7 @@ export class PresElementBox extends ViewBoxBaseComponent() { const dragArray = this.presBoxView?._dragArray ?? []; const dragData = new DragManager.DocumentDragData(this.presBoxView?.sortArray() ?? []); if (!dragData.draggedDocuments.length) dragData.draggedDocuments.push(this.slideDoc); - dragData.treeViewDoc = this.presBox?._type_collection === CollectionViewType.Tree ? this.presBox : undefined; // this._props.DocumentView?.()?._props.treeViewDoc; + dragData.treeViewDoc = this.presBox?._type_collection === CollectionViewType.Tree ? this.presBox : undefined; // this.DocumentView?.()?._props.treeViewDoc; dragData.moveDocument = this._props.moveDocument; const dragItem: HTMLElement[] = []; const classesToRestore = new Map(); -- cgit v1.2.3-70-g09d2