diff options
Diffstat (limited to 'src/client/views/nodes')
40 files changed, 316 insertions, 521 deletions
diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx index 4697491e0..9deed4de4 100644 --- a/src/client/views/nodes/AudioBox.tsx +++ b/src/client/views/nodes/AudioBox.tsx @@ -18,14 +18,15 @@ import { DocumentType } from '../../documents/DocumentTypes'; import { DocUtils } from '../../documents/DocUtils'; import { Networking } from '../../Network'; import { DragManager } from '../../util/DragManager'; -import { LinkManager } from '../../util/LinkManager'; import { undoBatch } from '../../util/UndoManager'; import { CollectionStackedTimeline, TrimScope } from '../collections/CollectionStackedTimeline'; import { ContextMenu } from '../ContextMenu'; import { ContextMenuProps } from '../ContextMenuItem'; import { ViewBoxAnnotatableComponent } from '../DocComponent'; +import { DocViewUtils } from '../DocViewUtils'; import { PinDocView, PinProps } from '../PinFuncs'; import './AudioBox.scss'; +import { DocumentView } from './DocumentView'; import { FieldView, FieldViewProps } from './FieldView'; import { OpenWhere } from './OpenWhere'; @@ -99,7 +100,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { return this._props.PanelHeight() < 50; } // used to collapse timeline when node is shrunk @computed get links() { - return LinkManager.Links(this.dataDoc); + return Doc.Links(this.dataDoc); } @computed get mediaState() { return this.dataDoc.mediaState as mediaState; @@ -218,9 +219,9 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { @action removeCurrentlyPlaying = () => { const docView = this.DocumentView?.(); - if (CollectionStackedTimeline.CurrentlyPlaying && docView) { - const index = CollectionStackedTimeline.CurrentlyPlaying.indexOf(docView); - index !== -1 && CollectionStackedTimeline.CurrentlyPlaying.splice(index, 1); + if (DocumentView.CurrentlyPlaying && docView) { + const index = DocumentView.CurrentlyPlaying.indexOf(docView); + index !== -1 && DocumentView.CurrentlyPlaying.splice(index, 1); } }; @@ -228,11 +229,11 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { @action addCurrentlyPlaying = () => { const docView = this.DocumentView?.(); - if (!CollectionStackedTimeline.CurrentlyPlaying) { - CollectionStackedTimeline.CurrentlyPlaying = []; + if (!DocumentView.CurrentlyPlaying) { + DocumentView.CurrentlyPlaying = []; } - if (docView && CollectionStackedTimeline.CurrentlyPlaying.indexOf(docView) === -1) { - CollectionStackedTimeline.CurrentlyPlaying.push(docView); + if (docView && DocumentView.CurrentlyPlaying.indexOf(docView) === -1) { + DocumentView.CurrentlyPlaying.push(docView); } }; @@ -251,7 +252,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { this._stream = await navigator.mediaDevices.getUserMedia({ audio: true }); this._recorder = new MediaRecorder(this._stream); this.dataDoc[this.fieldKey + '_recordingStart'] = new DateField(); - DocUtils.ActiveRecordings.push(this); + DocViewUtils.ActiveRecordings.push(this); this._recorder.ondataavailable = async (e: any) => { const [{ result }] = await Networking.UploadFilesToServer({ file: e.data }); if (!(result instanceof Error)) { @@ -278,8 +279,8 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { this.dataDoc[this.fieldKey + '_duration'] = (now - this._recordStart - this._pausedTime) / 1000; this.mediaState = mediaState.Paused; this._stream?.getAudioTracks()[0].stop(); - const ind = DocUtils.ActiveRecordings.indexOf(this); - ind !== -1 && DocUtils.ActiveRecordings.splice(ind, 1); + const ind = DocViewUtils.ActiveRecordings.indexOf(this); + ind !== -1 && DocViewUtils.ActiveRecordings.splice(ind, 1); } }; diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 691d07e31..685a5aca4 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -5,18 +5,16 @@ import { OmitKeys } from '../../../ClientUtils'; import { numberRange } from '../../../Utils'; import { Doc, DocListCast, Opt } from '../../../fields/Doc'; import { TransitionTimer } from '../../../fields/DocSymbols'; +import { InkField } from '../../../fields/InkField'; import { List } from '../../../fields/List'; import { listSpec } from '../../../fields/Schema'; import { ComputedField } from '../../../fields/ScriptField'; import { Cast, NumCast, StrCast } from '../../../fields/Types'; import { TraceMobx } from '../../../fields/util'; -import { DocumentManager } from '../../util/DocumentManager'; import { DragManager } from '../../util/DragManager'; import { ScriptingGlobals } from '../../util/ScriptingGlobals'; -import { SelectionManager } from '../../util/SelectionManager'; import { DocComponent } from '../DocComponent'; -import { StyleProp } from '../StyleProvider'; -import { CollectionFreeFormView } from '../collections/collectionFreeForm/CollectionFreeFormView'; +import { StyleProp } from '../StyleProp'; import './CollectionFreeFormDocumentView.scss'; import { DocumentView, DocumentViewProps } from './DocumentView'; import { FieldViewProps } from './FieldView'; @@ -43,7 +41,8 @@ interface freeFormProps { export interface CollectionFreeFormDocumentViewProps extends DocumentViewProps { RenderCutoffProvider: (doc: Doc) => boolean; - CollectionFreeFormView: CollectionFreeFormView; + isAnyChildContentActive: () => boolean; + parent: any; } @observer export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeFormDocumentViewProps & freeFormProps>() { @@ -66,7 +65,7 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF ]; // fields that are configured to be animatable using animation frames public static animStringFields = ['backgroundColor', 'color', 'fillColor']; // fields that are configured to be animatable using animation frames public static animDataFields = (doc: Doc) => (Doc.LayoutFieldKey(doc) ? [Doc.LayoutFieldKey(doc)] : []); // fields that are configured to be animatable using animation frames - public static from(dv?: DocumentView) { + public static from(dv?: DocumentView): CollectionFreeFormDocumentView | undefined { return dv?._props.parent instanceof CollectionFreeFormDocumentView ? dv._props.parent : undefined; } @@ -120,7 +119,6 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF ); } - CollectionFreeFormView = this.props.CollectionFreeFormView; // needed for type checking // this way, downstream code only invalidates when it uses a specific prop, not when any prop changes DataTransition = () => this.Transition || StrCast(this.Document.dataTransition); // prettier-ignore RenderCutoffProvider = this.props.RenderCutoffProvider; // needed for type checking @@ -185,13 +183,32 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF const currentFrame = Cast(doc._currentFrame, 'number', null); if (currentFrame === undefined) { doc._currentFrame = 0; - CollectionFreeFormDocumentView.setupKeyframes(childDocs, 0); + this.setupKeyframes(childDocs, 0); } - CollectionFreeFormView.updateKeyframe(undefined, [...childDocs, doc], currentFrame || 0); + this.updateKeyframe(undefined, [...childDocs, doc], currentFrame || 0); doc._currentFrame = newFrame === undefined ? 0 : Math.max(0, newFrame); } } + public static updateKeyframe(timer: NodeJS.Timeout | undefined, docs: Doc[], time: number) { + const newTimer = DocumentView.SetViewTransition(docs, 'all', 1000, timer, undefined, true); + const timecode = Math.round(time); + docs.forEach(doc => { + this.animFields.forEach(val => { + const findexed = Cast(doc[`${val.key}_indexed`], listSpec('number'), null); + findexed?.length <= timecode + 1 && findexed.push(undefined as any as number); + }); + this.animStringFields.forEach(val => { + const findexed = Cast(doc[`${val}_indexed`], listSpec('string'), null); + findexed?.length <= timecode + 1 && findexed.push(undefined as any as string); + }); + this.animDataFields(doc).forEach(val => { + const findexed = Cast(doc[`${val}_indexed`], listSpec(InkField), null); + findexed?.length <= timecode + 1 && findexed.push(undefined as any); + }); + }); + return newTimer; + } public static setupKeyframes(docs: Doc[], currTimecode: number, makeAppear: boolean = false) { docs.forEach(doc => { if (doc.appearFrame === undefined) doc.appearFrame = currTimecode; @@ -220,7 +237,7 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF const containerDocView = this._props.containerViewPath?.().lastElement(); const screenXf = containerDocView?.screenToContentsTransform(); if (screenXf) { - SelectionManager.DeselectAll(); + DocumentView.DeselectAll(); if (topDoc.z) { const spt = screenXf.inverse().transformPoint(NumCast(topDoc.x), NumCast(topDoc.y)); topDoc.z = 0; @@ -233,7 +250,7 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF topDoc.z = 1; [topDoc.x, topDoc.y] = fpt; } - setTimeout(() => SelectionManager.SelectView(DocumentManager.Instance.getDocumentView(topDoc, containerDocView), false), 0); + setTimeout(() => DocumentView.SelectView(DocumentView.getDocumentView(topDoc, containerDocView), false), 0); } }; @@ -255,7 +272,7 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF // 'inactive' - this is a group child but it is not active // undefined - this is not activated by a group isGroupActive = () => { - if (this.CollectionFreeFormView.isAnyChildContentActive()) return undefined; + if (this._props.isAnyChildContentActive()) return undefined; const backColor = this.BackgroundColor; const isGroup = this.dataDoc.isGroup && (!backColor || backColor === 'transparent'); return isGroup ? (this._props.isDocumentActive?.() ? 'group' : this._props.isGroupActive?.() ? 'child' : 'inactive') : this._props.isGroupActive?.() ? 'child' : undefined; diff --git a/src/client/views/nodes/ComparisonBox.tsx b/src/client/views/nodes/ComparisonBox.tsx index c42ca4468..6ae6bb228 100644 --- a/src/client/views/nodes/ComparisonBox.tsx +++ b/src/client/views/nodes/ComparisonBox.tsx @@ -15,7 +15,7 @@ import { dropActionType } from '../../util/DropActionTypes'; import { undoBatch } from '../../util/UndoManager'; import { ViewBoxAnnotatableComponent, ViewBoxInterface } from '../DocComponent'; import { PinDocView, PinProps } from '../PinFuncs'; -import { StyleProp } from '../StyleProvider'; +import { StyleProp } from '../StyleProp'; import './ComparisonBox.scss'; import { DocumentView } from './DocumentView'; import { FieldView, FieldViewProps } from './FieldView'; diff --git a/src/client/views/nodes/DataVizBox/DataVizBox.tsx b/src/client/views/nodes/DataVizBox/DataVizBox.tsx index ecfdcc229..15187b4e4 100644 --- a/src/client/views/nodes/DataVizBox/DataVizBox.tsx +++ b/src/client/views/nodes/DataVizBox/DataVizBox.tsx @@ -16,7 +16,6 @@ import { TraceMobx } from '../../../../fields/util'; import { DocUtils } from '../../../documents/DocUtils'; import { DocumentType } from '../../../documents/DocumentTypes'; import { Docs } from '../../../documents/Documents'; -import { DocumentManager } from '../../../util/DocumentManager'; import { UndoManager, undoable } from '../../../util/UndoManager'; import { ContextMenu } from '../../ContextMenu'; import { ViewBoxAnnotatableComponent, ViewBoxInterface } from '../../DocComponent'; @@ -254,7 +253,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() im this.toggleSidebar(); } return new Promise<Opt<DocumentView>>(res => { - DocumentManager.Instance.AddViewRenderedCb(doc, dv => res(dv)); + DocumentView.addViewRenderedCb(doc, dv => res(dv)); }); }; @computed get sidebarWidthPercent() { diff --git a/src/client/views/nodes/DataVizBox/components/LineChart.tsx b/src/client/views/nodes/DataVizBox/components/LineChart.tsx index 1c3134185..bc35ab8c8 100644 --- a/src/client/views/nodes/DataVizBox/components/LineChart.tsx +++ b/src/client/views/nodes/DataVizBox/components/LineChart.tsx @@ -8,7 +8,6 @@ import { List } from '../../../../../fields/List'; import { listSpec } from '../../../../../fields/Schema'; import { Cast, DocCast, StrCast } from '../../../../../fields/Types'; import { Docs } from '../../../../documents/Documents'; -import { DocumentManager } from '../../../../util/DocumentManager'; import { undoable } from '../../../../util/UndoManager'; import {} from '../../../DocComponent'; import { ObservableReactComponent } from '../../../ObservableReactComponent'; @@ -16,6 +15,7 @@ import { PinProps, PinDocView } from '../../../PinFuncs'; import { DataVizBox } from '../DataVizBox'; import { createLineGenerator, drawLine, minMaxRange, scaleCreatorNumerical, xAxisCreator, xGrid, yAxisCreator, yGrid } from '../utils/D3Utils'; import './Chart.scss'; +import { DocumentView } from '../../DocumentView'; export interface DataPoint { x: number; @@ -71,7 +71,7 @@ export class LineChart extends ObservableReactComponent<LineChartProps> { } @computed get parentViz() { return DocCast(this._props.Document.dataViz_parentViz); - // return LinkManager.Instance.getAllRelatedLinks(this._props.Document) // out of all links + // return LinkManager.Links(this._props.Document) // out of all links // .filter(link => { // return link.link_anchor_1 == this._props.Document.dataViz_parentViz; // }) // get links where this chart doc is the target of the link @@ -80,7 +80,7 @@ export class LineChart extends ObservableReactComponent<LineChartProps> { @computed get incomingHighlited() { // return selected x and y axes // otherwise, use the selection of whatever is linked to us - const incomingVizBox = DocumentManager.Instance.getFirstDocumentView(this.parentViz)?.ComponentView as DataVizBox; + const incomingVizBox = DocumentView.getFirstDocumentView(this.parentViz)?.ComponentView as DataVizBox; const highlitedRowIds = NumListCast(incomingVizBox?.layoutDoc?.dataViz_highlitedRows); return this._tableData.filter((record, i) => highlitedRowIds.includes(this._tableDataIds[i])); // get all the datapoints they have selected field set by incoming anchor } diff --git a/src/client/views/nodes/DataVizBox/components/PieChart.tsx b/src/client/views/nodes/DataVizBox/components/PieChart.tsx index ffb2f528a..ef6d1d412 100644 --- a/src/client/views/nodes/DataVizBox/components/PieChart.tsx +++ b/src/client/views/nodes/DataVizBox/components/PieChart.tsx @@ -84,7 +84,7 @@ export class PieChart extends ObservableReactComponent<PieChartProps> { @computed get parentViz() { return DocCast(this._props.Document.dataViz_parentViz); - // return LinkManager.Instance.getAllRelatedLinks(this._props.Document) // out of all links + // return LinkManager.Links(this._props.Document) // out of all links // .filter(link => link.link_anchor_1 == this._props.Document.dataViz_parentViz) // get links where this chart doc is the target of the link // .map(link => DocCast(link.link_anchor_1)); // then return the source of the link } diff --git a/src/client/views/nodes/DataVizBox/components/TableBox.tsx b/src/client/views/nodes/DataVizBox/components/TableBox.tsx index 8038b2cd4..5cd77e274 100644 --- a/src/client/views/nodes/DataVizBox/components/TableBox.tsx +++ b/src/client/views/nodes/DataVizBox/components/TableBox.tsx @@ -7,6 +7,7 @@ import * as React from 'react'; import { ClientUtils, setupMoveUpEvents } from '../../../../../ClientUtils'; import { emptyFunction } from '../../../../../Utils'; import { Doc, Field, NumListCast } from '../../../../../fields/Doc'; +import { DocData } from '../../../../../fields/DocSymbols'; import { List } from '../../../../../fields/List'; import { listSpec } from '../../../../../fields/Schema'; import { Cast, DocCast } from '../../../../../fields/Types'; @@ -152,11 +153,9 @@ export class TableBox extends ObservableReactComponent<TableBoxProps> { DragManager.StartAnchorAnnoDrag(moveEv.target instanceof HTMLElement ? [moveEv.target] : [], new DragManager.AnchorAnnoDragData(this._props.docView()!, sourceAnchorCreator, targetCreator), downX, downY, { dragComplete: completeEv => { if (!completeEv.aborted && completeEv.annoDragData && completeEv.annoDragData.linkSourceDoc && completeEv.annoDragData.dropDocument && completeEv.linkDocument) { - completeEv.linkDocument.link_displayLine = true; - completeEv.linkDocument.link_matchEmbeddings = true; - completeEv.linkDocument.link_displayArrow = true; - // e.annoDragData.linkSourceDoc.followLinkToggle = e.annoDragData.dropDocument.annotationOn === this._props.Document; - // e.annoDragData.linkSourceDoc.followLinkZoom = false; + completeEv.linkDocument[DocData].link_matchEmbeddings = true; + completeEv.linkDocument[DocData].stroke_startMarker = true; + this._props.docView?.()?._props.addDocument?.(completeEv.linkDocument); } }, }); diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx index e902d1792..ec9db8480 100644 --- a/src/client/views/nodes/DocumentContentsView.tsx +++ b/src/client/views/nodes/DocumentContentsView.tsx @@ -31,7 +31,6 @@ import { FunctionPlotBox } from './FunctionPlotBox'; import { ImageBox } from './ImageBox'; import { KeyValueBox } from './KeyValueBox'; import { LabelBox } from './LabelBox'; -import { LinkAnchorBox } from './LinkAnchorBox'; import { LinkBox } from './LinkBox'; import { LoadingBox } from './LoadingBox'; import { MapBox } from './MapBox/MapBox'; @@ -87,18 +86,18 @@ interface HTMLtagProps { export class HTMLtag extends React.Component<HTMLtagProps> { click = () => { const clickScript = (this.props as any).onClick as Opt<ScriptField>; - clickScript?.script.run({ this: this.props.Document, self: this.props.Document, scale: this.props.scaling }); + clickScript?.script.run({ this: this.props.Document, scale: this.props.scaling }); }; onInput = (e: React.FormEvent<HTMLDivElement>) => { const onInputScript = (this.props as any).onInput as Opt<ScriptField>; - onInputScript?.script.run({ this: this.props.Document, self: this.props.Document, value: (e.target as any).textContent }); + onInputScript?.script.run({ this: this.props.Document, value: (e.target as any).textContent }); }; render() { const style: { [key: string]: any } = {}; const divKeys = OmitKeys(this.props, ['children', 'dragStarting', 'dragEnding', 'htmltag', 'scaling', 'Document', 'key', 'onInput', 'onClick', '__proto__']).omit; const replacer = (match: any, expr: string) => // bcz: this executes a script to convert a property expression string: { script } into a value - (ScriptField.MakeFunction(expr, { self: Doc.name, this: Doc.name, scale: 'number' })?.script.run({ self: this.props.Document, this: this.props.Document, scale: this.props.scaling }).result as string) || ''; + (ScriptField.MakeFunction(expr, { this: Doc.name, scale: 'number' })?.script.run({ this: this.props.Document, scale: this.props.scaling }).result as string) || ''; Object.keys(divKeys).forEach((prop: string) => { const p = (this.props as any)[prop] as string; style[prop] = p?.replace(/{([^.'][^}']+)}/g, replacer); @@ -121,7 +120,6 @@ export class DocumentContentsView extends ObservableReactComponent<DocumentConte super(props); makeObservable(this); } - @computed get layout(): string { TraceMobx(); if (this._props.LayoutTemplateString) return this._props.LayoutTemplateString; @@ -186,7 +184,7 @@ export class DocumentContentsView extends ObservableReactComponent<DocumentConte let layoutFrame = this.layout; // replace code content with a script >{content}< as in <HTMLdiv>{this.title}</HTMLdiv> - const replacer = (match: any, prefix: string, expr: string, postfix: string) => prefix + ((ScriptField.MakeFunction(expr, { self: Doc.name, this: Doc.name })?.script.run({ this: this._props.Document }).result as string) || '') + postfix; + const replacer = (match: any, prefix: string, expr: string, postfix: string) => prefix + ((ScriptField.MakeFunction(expr, { this: Doc.name })?.script.run({ this: this._props.Document }).result as string) || '') + postfix; layoutFrame = layoutFrame.replace(/(>[^{]*)[^=]\{([^.'][^<}]+)\}([^}]*<)/g, replacer); // replace HTML<tag> with corresponding HTML tag as in: <HTMLdiv> becomes <HTMLtag Document={props.Document} htmltag='div'> @@ -205,7 +203,7 @@ export class DocumentContentsView extends ObservableReactComponent<DocumentConte const code = XRegExp.matchRecursive(splits[1], '{', '}', '', { valueNames: ['between', 'left', 'match', 'right', 'between'] }); layoutFrame = splits[0] + ` ${func}={props.${func}} ` + splits[1].substring(code[1].end + 1); const script = code[1].value.replace(/^‘/, '').replace(/’$/, ''); // ‘’ are not valid quotes in javascript so get rid of them -- they may be present to make it easier to write complex scripts - see headerTemplate in currentUserUtils.ts - return ScriptField.MakeScript(script, { this: Doc.name, self: Doc.name, scale: 'number', value: 'string' }); + return ScriptField.MakeScript(script, { this: Doc.name, scale: 'number', value: 'string' }); } return undefined; // add input function to props @@ -247,7 +245,6 @@ export class DocumentContentsView extends ObservableReactComponent<DocumentConte PresElementBox, SearchBox, FunctionPlotBox, - LinkAnchorBox, InkingStroke, LinkBox, ScriptingBox, diff --git a/src/client/views/nodes/DocumentIcon.tsx b/src/client/views/nodes/DocumentIcon.tsx index 364406197..23d934edb 100644 --- a/src/client/views/nodes/DocumentIcon.tsx +++ b/src/client/views/nodes/DocumentIcon.tsx @@ -6,10 +6,8 @@ import { factory } from 'typescript'; import { FieldType } from '../../../fields/Doc'; import { Id } from '../../../fields/FieldSymbols'; import { StrCast } from '../../../fields/Types'; -import { DocumentManager } from '../../util/DocumentManager'; import { Transformer, ts } from '../../util/Scripting'; import { SnappingManager } from '../../util/SnappingManager'; -import { LightboxView } from '../LightboxView'; import { ObservableReactComponent } from '../ObservableReactComponent'; import { DocumentView } from './DocumentView'; @@ -25,9 +23,6 @@ export class DocumentIcon extends ObservableReactComponent<DocumentIconProps> { makeObservable(this); } - static get DocViews() { - return LightboxView.LightboxDoc ? DocumentManager.Instance.DocumentViews.filter(v => LightboxView.Contains(v)) : DocumentManager.Instance.DocumentViews; - } render() { const { view } = this._props; const { left, top, right } = view.getBounds || { left: 0, top: 0, right: 0, bottom: 0 }; @@ -69,7 +64,7 @@ export class DocumentIconContainer extends React.Component { const match = node.text.match(/d([0-9]+)/); if (match) { const m = parseInt(match[1]); - const doc = DocumentIcon.DocViews[m].Document; + const doc = DocumentView.allViews()[m].Document; usedDocuments.add(m); return factory.createIdentifier(`idToDoc("${doc[Id]}")`); } @@ -81,7 +76,7 @@ export class DocumentIconContainer extends React.Component { return ts.visitNode(root, visit); }, getVars() { - const docs = DocumentIcon.DocViews; + const docs = DocumentView.allViews(); const capturedVariables: { [name: string]: FieldType } = {}; usedDocuments.forEach(index => { capturedVariables[`d${index}`] = docs.length > index ? docs[index].Document : `d${index}`; @@ -91,6 +86,6 @@ export class DocumentIconContainer extends React.Component { }; } render() { - return DocumentIcon.DocViews.map((dv, i) => <DocumentIcon key={dv.DocUniqueId} index={i} view={dv} />); + return DocumentView.allViews().map((dv, i) => <DocumentIcon key={dv.DocUniqueId} index={i} view={dv} />); } } diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx index 977899589..0c5156339 100644 --- a/src/client/views/nodes/DocumentLinksButton.tsx +++ b/src/client/views/nodes/DocumentLinksButton.tsx @@ -8,11 +8,8 @@ import * as React from 'react'; import { StopEvent, returnFalse, setupMoveUpEvents } from '../../../ClientUtils'; import { emptyFunction } from '../../../Utils'; import { Doc } from '../../../fields/Doc'; -import { DocData } from '../../../fields/DocSymbols'; -import { StrCast } from '../../../fields/Types'; import { DocUtils } from '../../documents/DocUtils'; import { DragManager } from '../../util/DragManager'; -import { Hypothesis } from '../../util/HypothesisUtils'; import { LinkManager } from '../../util/LinkManager'; import { UndoManager, undoBatch } from '../../util/UndoManager'; import { ObservableReactComponent } from '../ObservableReactComponent'; @@ -169,16 +166,6 @@ export class DocumentLinksButton extends ObservableReactComponent<DocumentLinksB LinkManager.Instance.currentLink = linkDoc; if (linkDoc) { - if (DocumentLinksButton.AnnotationId && DocumentLinksButton.AnnotationUri) { - // if linking from a Hypothes.is annotation - const linkDocData = linkDoc[DocData]; - linkDocData.linksToAnnotation = true; - linkDocData.annotationId = DocumentLinksButton.AnnotationId; - linkDocData.annotationUri = DocumentLinksButton.AnnotationUri; - const dashHyperlink = Doc.globalServerPath(startIsAnnotation ? endLink : startLink); - Hypothesis.makeLink(StrCast(startIsAnnotation ? endLink.title : startLink.title), dashHyperlink, DocumentLinksButton.AnnotationId, startIsAnnotation ? startLink : endLink); // edit annotation to add a Dash hyperlink to the linked doc - } - TaskCompletionBox.textDisplayed = 'Link Created'; TaskCompletionBox.popupX = screenX; TaskCompletionBox.popupY = screenY - 133; diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 1e7f1015a..f8ce50c98 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -7,10 +7,10 @@ import { IReactionDisposer, action, computed, makeObservable, observable, reacti import { observer } from 'mobx-react'; import * as React from 'react'; import { Bounce, Fade, Flip, JackInTheBox, Roll, Rotate, Zoom } from 'react-awesome-reveal'; -import { ClientUtils, DivWidth, isTargetChildOf as isParentOf, lightOrDark, returnEmptyString, returnFalse, returnTrue, returnVal, simulateMouseClick } from '../../../ClientUtils'; +import { ClientUtils, DivWidth, isTargetChildOf as isParentOf, lightOrDark, returnFalse, returnVal, simulateMouseClick } from '../../../ClientUtils'; import { Utils, emptyFunction, emptyPath } from '../../../Utils'; import { Doc, DocListCast, Field, FieldType, Opt, StrListCast } from '../../../fields/Doc'; -import { AclPrivate, Animation, AudioPlay, DocData, DocViews } from '../../../fields/DocSymbols'; +import { AclAdmin, AclEdit, AclPrivate, Animation, AudioPlay, DocData, DocViews } from '../../../fields/DocSymbols'; import { Id } from '../../../fields/FieldSymbols'; import { InkTool } from '../../../fields/InkField'; import { List } from '../../../fields/List'; @@ -20,20 +20,17 @@ import { ScriptField } from '../../../fields/ScriptField'; import { BoolCast, Cast, DocCast, NumCast, ScriptCast, StrCast } from '../../../fields/Types'; import { AudioField } from '../../../fields/URLField'; import { GetEffectiveAcl, TraceMobx } from '../../../fields/util'; +import { AudioAnnoState } from '../../../server/SharedMediaTypes'; import { DocServer } from '../../DocServer'; -import { Networking } from '../../Network'; import { DocUtils, FollowLinkScript } from '../../documents/DocUtils'; import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes'; import { Docs } from '../../documents/Documents'; -import { DictationManager } from '../../util/DictationManager'; -import { DocumentManager } from '../../util/DocumentManager'; import { DragManager } from '../../util/DragManager'; import { dropActionType } from '../../util/DropActionTypes'; import { MakeTemplate, makeUserTemplateButton } from '../../util/DropConverter'; -import { LinkManager, UPDATE_SERVER_CACHE } from '../../util/LinkManager'; +import { UPDATE_SERVER_CACHE } from '../../util/LinkManager'; import { ScriptingGlobals } from '../../util/ScriptingGlobals'; import { SearchUtil } from '../../util/SearchUtil'; -import { SelectionManager } from '../../util/SelectionManager'; import { SharingManager } from '../../util/SharingManager'; import { SnappingManager } from '../../util/SnappingManager'; import { UndoManager, undoBatch, undoable } from '../../util/UndoManager'; @@ -42,16 +39,15 @@ import { ContextMenuProps } from '../ContextMenuItem'; import { DocComponent, ViewBoxInterface } from '../DocComponent'; import { EditableView } from '../EditableView'; import { FieldsDropdown } from '../FieldsDropdown'; -import { GestureOverlay } from '../GestureOverlay'; import { LightboxView } from '../LightboxView'; -import { AudioAnnoState, StyleProp } from '../StyleProvider'; +import { PinProps } from '../PinFuncs'; +import { StyleProp } from '../StyleProp'; import { DocumentContentsView, ObserverJsxParser } from './DocumentContentsView'; import { DocumentLinksButton } from './DocumentLinksButton'; import './DocumentView.scss'; import { FieldViewProps, FieldViewSharedProps } from './FieldView'; import { FocusViewOptions } from './FocusViewOptions'; import { KeyValueBox } from './KeyValueBox'; -import { LinkAnchorBox } from './LinkAnchorBox'; import { OpenWhere } from './OpenWhere'; import { FormattedTextBox } from './formattedText/FormattedTextBox'; import { PresEffect, PresEffectDirection } from './trails'; @@ -90,6 +86,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document // this makes mobx trace() statements more descriptive public get displayName() { return 'DocumentViewInternal(' + this.Document.title + ')'; } // prettier-ignore public static SelectAfterContextMenu = true; // whether a document should be selected after it's contextmenu is triggered. + /** * This function is filled in by MainView to allow non-viewBox views to add Docs as tabs without * needing to know about/reference MainView @@ -183,11 +180,10 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document // anchors that are not rendered as DocumentViews (marked as 'layout_unrendered' with their 'annotationOn' set to this document). e.g., // - PDF text regions are rendered as an Annotations without generating a DocumentView, ' // - RTF selections are rendered via Prosemirror and have a mark which contains the Document ID for the annotation link - // - and links to PDF/Web docs at a certain scroll location never create an explicit view. - // For each of these, we create LinkAnchorBox's on the border of the DocumentView. + // - and links to PDF/Web docs at a certain scroll location never create an explicit anchor view. @computed get directLinks() { TraceMobx(); - return LinkManager.Instance.getAllRelatedLinks(this.Document).filter( + return Doc.Links(this.Document).filter( link => (link.link_matchEmbeddings ? link.link_anchor_1 === this.Document : Doc.AreProtosEqual(link.link_anchor_1 as Doc, this.Document)) || (link.link_matchEmbeddings ? link.link_anchor_2 === this.Document : Doc.AreProtosEqual(link.link_anchor_2 as Doc, this.Document)) || @@ -197,11 +193,11 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document } @computed get _allLinks(): Doc[] { TraceMobx(); - return LinkManager.Instance.getAllRelatedLinks(this.Document).filter(link => !link.link_matchEmbeddings || link.link_anchor_1 === this.Document || link.link_anchor_2 === this.Document); + return Doc.Links(this.Document).filter(link => !link.link_matchEmbeddings || link.link_anchor_1 === this.Document || link.link_anchor_2 === this.Document); } @computed get filteredLinks() { - return DocUtils.FilterDocs(this.directLinks, this._props.childFilters?.() ?? [], []).filter(d => d.link_displayLine || Doc.UserDoc().showLinkLines); + return DocUtils.FilterDocs(this.directLinks, this._props.childFilters?.() ?? [], []); } componentWillUnmount() { @@ -259,7 +255,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document startDragging(x: number, y: number, dropAction: dropActionType, hideSource = false) { const docView = this._docView; if (this._mainCont.current && docView) { - const views = SelectionManager.Views.filter(dv => dv.ContentDiv); + const views = DocumentView.Selected().filter(dv => dv.ContentDiv); const selected = views.length > 1 && views.some(dv => dv.Document === this.Document) ? views : [docView]; const dragData = new DragManager.DocumentDragData(selected.map(dv => dv.Document)); const screenXf = docView.screenToViewTransform(); @@ -289,8 +285,8 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document }; onBrowseClick = (e: React.MouseEvent) => { const browseTransitionTime = 500; - SelectionManager.DeselectAll(); - DocumentManager.Instance.showDocument(this.Document, { zoomScale: 0.8, willZoomCentered: true }, (focused: boolean) => { + DocumentView.DeselectAll(); + DocumentView.showDocument(this.Document, { zoomScale: 0.8, willZoomCentered: true }, (focused: boolean) => { const options: FocusViewOptions = { pointFocus: { X: e.clientX, Y: e.clientY }, zoomTime: browseTransitionTime }; if (!focused && this._docView) { this._docView @@ -327,7 +323,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document UndoManager.RunInBatch(() => this.onDoubleClickHandler.script.run(scriptProps, console.log).result?.select && this._props.select(false), 'on double click: ' + this.Document.title); } else if (!Doc.IsSystem(this.Document) && defaultDblclick !== 'ignore') { UndoManager.RunInBatch(() => LightboxView.Instance.AddDocTab(this.Document, OpenWhere.lightbox), 'double tap'); - SelectionManager.DeselectAll(); + DocumentView.DeselectAll(); Doc.UnBrushDoc(this.Document); } else { this._singleClickFunc?.(); @@ -377,7 +373,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document if (this._props.isGroupActive?.() === 'child' && !this._props.isDocumentActive?.()) return; // eslint-disable-next-line no-use-before-define this._longPressSelector = setTimeout(() => DocumentView.LongPress && this._props.select(false), 1000); - if (!GestureOverlay.DownDocView) GestureOverlay.DownDocView = this._docView; + if (!DocumentView.DownDocView) DocumentView.DownDocView = this._docView; this._downX = e.clientX; this._downY = e.clientY; @@ -463,7 +459,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document }, 'set toggle detail'); drop = undoable((e: Event, de: DragManager.DropEvent) => { - if (this._props.dontRegisterView || this._props.LayoutTemplateString?.includes(LinkAnchorBox.name)) return false; + if (this._props.dontRegisterView) return false; if (this.Document === Doc.ActiveDashboard) { e.stopPropagation(); e.preventDefault(); @@ -484,7 +480,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document if (linkDoc) { de.complete.linkDocument = linkDoc; linkDoc.layout_isSvg = true; - DocumentManager.LinkCommonAncestor(linkDoc)?.ComponentView?.addDocument?.(linkDoc); + DocumentView.linkCommonAncestor(linkDoc)?.ComponentView?.addDocument?.(linkDoc); } } e.stopPropagation(); @@ -516,7 +512,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document if (e && this.layoutDoc.layout_hideContextMenu && Doc.noviceMode) { e.preventDefault(); e.stopPropagation(); - // !this._props.isSelected(true) && SelectionManager.SelectView(this.DocumentView(), false); + // !this._props.isSelected(true) && DocumentView.SelectView(this.DocumentView(), false); } // the touch onContextMenu is button 0, the pointer onContextMenu is button 2 if (e) { @@ -576,8 +572,8 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document if (this._props.bringToFront) { const zorders = cm.findByDescription('ZOrder...'); const zorderItems: ContextMenuProps[] = zorders && 'subitems' in zorders ? zorders.subitems : []; - zorderItems.push({ description: 'Bring to Front', event: () => SelectionManager.Views.forEach(dv => dv._props.bringToFront?.(dv.Document, false)), icon: 'arrow-up' }); - zorderItems.push({ description: 'Send to Back', event: () => SelectionManager.Views.forEach(dv => dv._props.bringToFront?.(dv.Document, true)), icon: 'arrow-down' }); + zorderItems.push({ description: 'Bring to Front', event: () => DocumentView.Selected().forEach(dv => dv._props.bringToFront?.(dv.Document, false)), icon: 'arrow-up' }); + zorderItems.push({ description: 'Send to Back', event: () => DocumentView.Selected().forEach(dv => dv._props.bringToFront?.(dv.Document, true)), icon: 'arrow-down' }); zorderItems.push({ description: !this.layoutDoc._keepZDragged ? 'Keep ZIndex when dragged' : 'Allow ZIndex to change when dragged', event: undoBatch( @@ -601,7 +597,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document onClicks.push({ description: this.onClickHandler ? 'Remove Click Behavior' : 'Follow Link', event: () => this.toggleFollowLink(false, false), icon: 'link' }); !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) { + } else if (Doc.Links(this.Document).length) { onClicks.push({ description: 'Restore On Click default', event: () => this.noOnClick(), icon: 'link' }); onClicks.push({ description: 'Follow Link on Click', event: () => this.followLinkOnClick(), icon: 'link' }); !existingOnClick && cm.addItem({ description: 'OnClick...', subitems: onClicks, icon: 'mouse-pointer' }); @@ -718,7 +714,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document case StyleProp.PointerEvents: return 'none'; case StyleProp.Highlighting: return undefined; case StyleProp.Opacity: { - const filtered = DocUtils.FilterDocs(this.directLinks, this._props.childFilters?.() ?? [], []).filter(d => d.link_displayLine || Doc.UserDoc().showLinkLines); + const filtered = DocUtils.FilterDocs(this.directLinks, this._props.childFilters?.() ?? [], []); return filtered.some(link => link._link_displayArrow) ? 0 : undefined; } default: @@ -726,34 +722,6 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document return this._props.styleProvider?.(doc, props, property); }; - // eslint-disable-next-line no-return-assign - removeLinkByHiding = (link: Doc) => () => link.link_displayLine = false; // prettier-ignore - @computed get allLinkEndpoints() { - // the small blue dots that mark the endpoints of links - if (this._componentView instanceof KeyValueBox || this._props.hideLinkAnchors || this.layoutDoc.layout_hideLinkAnchors || this._props.dontRegisterView || this.layoutDoc.layout_unrendered) return null; - return this.filteredLinks.map(link => ( - <div className="documentView-anchorCont" key={link[Id]}> - <DocumentView - {...this._props} - isContentActive={returnFalse} - Document={link} - containerViewPath={this._props.docViewPath} - PanelWidth={this.anchorPanelWidth} - PanelHeight={this.anchorPanelHeight} - dontRegisterView={false} - layout_showTitle={returnEmptyString} - hideCaptions - hideLinkAnchors - layout_fitWidth={returnTrue} - removeDocument={this.removeLinkByHiding(link)} - styleProvider={this.anchorStyleProvider} - LayoutTemplate={undefined} - LayoutTemplateString={LinkAnchorBox.LayoutString(`link_anchor_${LinkManager.anchorIndex(link, this.Document)}`)} - /> - </div> - )); - } - @computed get viewBoxContents() { TraceMobx(); const isInk = this.layoutDoc._layout_isSvg && !this._props.LayoutTemplateString; @@ -780,7 +748,6 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document setTitleFocus={this.setTitleFocus} hideClickBehaviors={BoolCast(this.Document.hideClickBehaviors)} /> - {this.layoutDoc.layout_hideAllLinks ? null : this.allLinkEndpoints} </div> ); } @@ -1008,50 +975,45 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document default: return renderDoc; } } - public static recordAudioAnnotation(dataDoc: Doc, field: string, onRecording?: (stop: () => void) => void, onEnd?: () => void) { - let gumStream: any; - let recorder: any; - navigator.mediaDevices.getUserMedia({ audio: true }).then(stream => { - let audioTextAnnos = Cast(dataDoc[field + '_audioAnnotations_text'], listSpec('string'), null); - if (audioTextAnnos) audioTextAnnos.push(''); - else audioTextAnnos = dataDoc[field + '_audioAnnotations_text'] = new List<string>(['']); - DictationManager.Controls.listen({ - interimHandler: value => { audioTextAnnos[audioTextAnnos.length - 1] = value; }, // prettier-ignore - continuous: { indefinite: false }, - }).then(results => { - if (results && [DictationManager.Controls.Infringed].includes(results)) { - DictationManager.Controls.stop(); - } - onEnd?.(); - }); - - gumStream = stream; - recorder = new MediaRecorder(stream); - recorder.ondataavailable = async (e: any) => { - const [{ result }] = await Networking.UploadFilesToServer({ file: e.data }); - if (!(result instanceof Error)) { - const audioField = new AudioField(result.accessPaths.agnostic.client); - const audioAnnos = Cast(dataDoc[field + '_audioAnnotations'], listSpec(AudioField), null); - if (audioAnnos) audioAnnos.push(audioField); - else dataDoc[field + '_audioAnnotations'] = new List([audioField]); - } - }; - recorder.start(); - const stopFunc = () => { - recorder.stop(); - DictationManager.Controls.stop(/* false */); - dataDoc.audioAnnoState = AudioAnnoState.stopped; - gumStream.getAudioTracks()[0].stop(); - }; - if (onRecording) onRecording(stopFunc); - else setTimeout(stopFunc, 5000); - }); - } } @observer export class DocumentView extends DocComponent<DocumentViewProps>() { public static ROOT_DIV = 'documentView-effectsWrapper'; + // LinkFollower + public static FollowLink: (linkDoc: Opt<Doc>, sourceDoc: Doc, altKey: boolean) => boolean; + // selection funcs + public static DeselectAll: (except?: Doc) => void | undefined; + public static DeselectView: (dv: DocumentView | undefined) => void | undefined; + public static SelectView: (dv: DocumentView | undefined, extendSelection: boolean) => void | undefined; + public static Selected: () => DocumentView[]; + public static SelectedDocs: () => Doc[]; + public static SelectSchemaDoc: (doc: Doc, deselectAllFirst?: boolean) => void; + public static SelectedSchemaDoc: () => Opt<Doc>; + // view mgr funcs + public static activateTabView: (tabDoc: Doc) => boolean; + public static allViews: () => DocumentView[]; + public static addView: (dv: DocumentView) => void | undefined; + public static removeView: (dv: DocumentView) => void | undefined; + public static addViewRenderedCb: (doc: Opt<Doc>, func: (dv: DocumentView) => any) => boolean; + public static getFirstDocumentView: (toFind: Doc) => DocumentView | undefined; + public static getDocumentView: (target: Doc | undefined, preferredCollection?: DocumentView) => Opt<DocumentView>; + public static getContextPath: (doc: Opt<Doc>, includeExistingViews?: boolean) => Doc[]; + public static getLightboxDocumentView: (toFind: Doc) => Opt<DocumentView>; + public static showDocumentView: (targetDocView: DocumentView, options: FocusViewOptions) => Promise<void>; + public static showDocument: ( + targetDoc: Doc, // document to display + optionsIn: FocusViewOptions, // options for how to navigate to target + finished?: (changed: boolean) => void // func called after focusing on target with flag indicating whether anything needed to be done. + ) => Promise<void>; + public static linkCommonAncestor: (link: Doc) => DocumentView | undefined; + // pin func + public static PinDoc: (docIn: Doc | Doc[], pinProps: PinProps) => void; + // gesture + public static DownDocView: DocumentView | undefined; // the first DocView that receives a pointerdown event. used by GestureOverlay to determine the doc a gesture should apply to. + // media playing + @observable public static CurrentlyPlaying: DocumentView[] = []; + public get displayName() { return 'DocumentView(' + (this.Document?.title??"") + ')'; } // prettier-ignore public ContentRef = React.createRef<HTMLDivElement>(); private _htmlOverlayEffect: Opt<Doc>; @@ -1138,14 +1100,14 @@ export class DocumentView extends DocComponent<DocumentViewProps>() { componentDidMount() { runInAction(() => this.Document[DocViews].add(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); + !BoolCast(this.Document.dontRegisterView, this._props.dontRegisterView) && DocumentView.addView(this); } componentWillUnmount() { this._viewTimer && clearTimeout(this._viewTimer); runInAction(() => this.Document[DocViews].delete(this)); Object.values(this._disposers).forEach(disposer => disposer?.()); - !BoolCast(this.Document.dontRegisterView, this._props.dontRegisterView) && DocumentManager.Instance.RemoveView(this); + !BoolCast(this.Document.dontRegisterView, this._props.dontRegisterView) && DocumentView.removeView(this); } public set IsSelected(val) { runInAction(() => { this._selected = val; }); } // prettier-ignore @@ -1176,10 +1138,6 @@ export class DocumentView extends DocComponent<DocumentViewProps>() { const xf = this.screenToContentsTransform().scale(this.nativeScaling).inverse(); const [[left, top], [right, bottom]] = [xf.transformPoint(0, 0), xf.transformPoint(this.panelWidth, this.panelHeight)]; - if (this._props.LayoutTemplateString?.includes(LinkAnchorBox.name)) { - const docuBox = this.ContentDiv.getElementsByClassName('linkAnchorBox-cont'); - if (docuBox.length) return { ...docuBox[0].getBoundingClientRect(), transition: undefined }; - } // transition is returned so that the bounds will 'update' at the end of an animated transition. This is needed by xAnchor in LinkBox const transition = this.docViewPath().find((parent: DocumentView) => parent.DataTransition?.() || parent.ComponentView?.viewTransition?.()); return { left, top, right, bottom, transition: transition?.DataTransition?.() || transition?.ComponentView?.viewTransition?.() }; @@ -1289,7 +1247,7 @@ export class DocumentView extends DocComponent<DocumentViewProps>() { if (checkResult) { return Doc.UserDoc().defaultTextLayout; } - const view = SelectionManager.Views[0]?._props.renderDepth > 0 ? SelectionManager.Views[0] : undefined; + const view = DocumentView.Selected()[0]?._props.renderDepth > 0 ? DocumentView.Selected()[0] : undefined; undoable(() => { let tempDoc: Opt<Doc>; if (view) { @@ -1359,11 +1317,11 @@ export class DocumentView extends DocComponent<DocumentViewProps>() { screenToLocalScale = () => this._props.ScreenToLocalTransform().Scale; isSelected = () => this.IsSelected; select = (extendSelection: boolean, focusSelection?: boolean) => { - if (this.IsSelected && SelectionManager.Views.length > 1) SelectionManager.DeselectView(this); + if (this.IsSelected && DocumentView.Selected().length > 1) DocumentView.DeselectView(this); else { - SelectionManager.SelectView(this, extendSelection); + DocumentView.SelectView(this, extendSelection); if (focusSelection) { - DocumentManager.Instance.showDocument(this.Document, { + DocumentView.showDocument(this.Document, { willZoomCentered: true, zoomScale: 0.9, zoomTime: 500, @@ -1506,6 +1464,37 @@ export function returnEmptyDocViewList() { return emptyPath; } +// eslint-disable-next-line default-param-last +export function DocFocusOrOpen(docIn: Doc, optionsIn: FocusViewOptions = { willZoomCentered: true, zoomScale: 0, openLocation: OpenWhere.toggleRight }, containingDoc?: Doc) { + let doc = docIn; + const options = optionsIn; + const func = () => { + const cv = DocumentView.getDocumentView(containingDoc); + const dv = DocumentView.getDocumentView(doc, cv); + if (dv && (!containingDoc || dv.containerViewPath?.().lastElement()?.Document === containingDoc)) { + DocumentView.showDocumentView(dv, options).then(() => dv && Doc.linkFollowHighlight(dv.Document)); + } else { + const container = DocCast(containingDoc ?? doc.embedContainer ?? Doc.BestEmbedding(doc)); + const showDoc = !Doc.IsSystem(container) && !cv ? container : doc; + options.toggleTarget = undefined; + DocumentView.showDocument(showDoc, options, () => DocumentView.showDocument(doc, { ...options, openLocation: undefined })).then(() => { + const cvFound = DocumentView.getDocumentView(containingDoc); + const dvFound = DocumentView.getDocumentView(doc, cvFound); + dvFound && Doc.linkFollowHighlight(dvFound.Document); + }); + } + }; + if (Doc.IsDataProto(doc) && Doc.GetEmbeddings(doc).some(embed => embed.hidden && [AclAdmin, AclEdit].includes(GetEffectiveAcl(embed)))) { + doc = Doc.GetEmbeddings(doc).find(embed => embed.hidden && [AclAdmin, AclEdit].includes(GetEffectiveAcl(embed)))!; + } + if (doc.hidden) { + doc.hidden = false; + options.toggleTarget = false; + setTimeout(func); + } else func(); +} +ScriptingGlobals.add(DocFocusOrOpen); + // eslint-disable-next-line prefer-arrow-callback ScriptingGlobals.add(function deiconifyView(documentView: DocumentView) { documentView.iconify(); @@ -1527,9 +1516,9 @@ ScriptingGlobals.add(function updateLinkCollection(linkCollection: Doc, linkSour const collectedLinks = DocListCast(linkCollection[DocData].data); let wid = NumCast(linkSource._width); let embedding: Doc | undefined; - const links = LinkManager.Links(linkSource); + const links = Doc.Links(linkSource); links.forEach(link => { - const other = LinkManager.getOppositeAnchor(link, linkSource); + const other = Doc.getOppositeAnchor(link, linkSource); const otherdoc = DocCast(other?.annotationOn ?? other); if (otherdoc && !collectedLinks?.some(d => Doc.AreProtosEqual(d, otherdoc))) { embedding = Doc.MakeEmbedding(otherdoc); diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx index 8d1617e66..5e3bb9fec 100644 --- a/src/client/views/nodes/FontIconBox/FontIconBox.tsx +++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx @@ -17,7 +17,7 @@ import { ContextMenu } from '../../ContextMenu'; import { ViewBoxBaseComponent } from '../../DocComponent'; import { EditableView } from '../../EditableView'; import { SelectedDocView } from '../../selectedDoc'; -import { StyleProp } from '../../StyleProvider'; +import { StyleProp } from '../../StyleProp'; import { FieldView, FieldViewProps } from '../FieldView'; import { OpenWhere } from '../OpenWhere'; import './FontIconBox.scss'; @@ -116,7 +116,7 @@ export class FontIconBox extends ViewBoxBaseComponent<ButtonProps>() { default: type = 'slider'; break; } // prettier-ignore - const numScript = (value?: number) => ScriptCast(this.Document.script).script.run({ this: this.Document, self: this.Document, value, _readOnly_: value === undefined }); + const numScript = (value?: number) => ScriptCast(this.Document.script).script.run({ this: this.Document, value, _readOnly_: value === undefined }); const color = this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.Color); // Script for checking the outcome of the toggle const checkResult = Number(Number(numScript().result ?? 0).toPrecision(NumCast(this.dataDoc.numPrecision, 3))); @@ -142,7 +142,7 @@ export class FontIconBox extends ViewBoxBaseComponent<ButtonProps>() { setupMoveUpEvents( this, e, - () => ScriptCast(this.Document.onDragScript)?.script.run({ this: this.Document, self: this.Document, value: { doc: value, e } }).result, + () => ScriptCast(this.Document.onDragScript)?.script.run({ this: this.Document, value: { doc: value, e } }).result, emptyFunction, emptyFunction ); // prettier-ignore @@ -162,7 +162,7 @@ export class FontIconBox extends ViewBoxBaseComponent<ButtonProps>() { const isViewDropdown = script?.script.originalScript.startsWith('{ return setView'); if (isViewDropdown) { const selected = Array.from(script?.script.run({ _readOnly_: true }).result) as Doc[]; - // const selected = SelectionManager.Docs; + // const selected = DocumentView.SelectedDocs(); if (selected.lastElement()) { if (StrCast(selected.lastElement().type) === DocumentType.COL) { text = StrCast(selected.lastElement()._type_collection); @@ -190,7 +190,7 @@ export class FontIconBox extends ViewBoxBaseComponent<ButtonProps>() { } noviceList = [CollectionViewType.Freeform, CollectionViewType.Schema, CollectionViewType.Carousel3D, CollectionViewType.Stacking, CollectionViewType.NoteTaking]; } else { - text = script?.script.run({ this: this.Document, self: this.Document, value: '', _readOnly_: true }).result; + text = script?.script.run({ this: this.Document, value: '', _readOnly_: true }).result; // text = StrCast((RichTextMenu.Instance?.TextView?.EditorView ? RichTextMenu.Instance : Doc.UserDoc()).fontFamily); getStyle = (val: string) => ({ fontFamily: val }); } @@ -208,7 +208,7 @@ export class FontIconBox extends ViewBoxBaseComponent<ButtonProps>() { return ( <Dropdown selectedVal={text} - setSelectedVal={undoable(value => script.script.run({ this: this.Document, self: this.Document, value }), `dropdown select ${this.label}`)} + setSelectedVal={undoable(value => script.script.run({ this: this.Document, value }), `dropdown select ${this.label}`)} color={SnappingManager.userColor} background={SnappingManager.userVariantColor} type={Type.TERT} @@ -232,17 +232,17 @@ export class FontIconBox extends ViewBoxBaseComponent<ButtonProps>() { */ @computed get colorButton() { const color = this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.Color); - const curColor = this.colorScript?.script.run({ this: this.Document, self: this.Document, value: undefined, _readOnly_: true }).result ?? 'transparent'; + const curColor = this.colorScript?.script.run({ this: this.Document, value: undefined, _readOnly_: true }).result ?? 'transparent'; const tooltip: string = StrCast(this.Document.toolTip); return ( <ColorPicker setSelectedColor={value => { if (!this.colorBatch) this.colorBatch = UndoManager.StartBatch(`Set ${tooltip} color`); - this.colorScript?.script.run({ this: this.Document, self: this.Document, value: value, _readOnly_: false }); + this.colorScript?.script.run({ this: this.Document, value: value, _readOnly_: false }); }} setFinalColor={value => { - this.colorScript?.script.run({ this: this.Document, self: this.Document, value: value, _readOnly_: false }); + this.colorScript?.script.run({ this: this.Document, value: value, _readOnly_: false }); this.colorBatch?.end(); this.colorBatch = undefined; }} @@ -262,7 +262,7 @@ export class FontIconBox extends ViewBoxBaseComponent<ButtonProps>() { const tooltip: string = StrCast(this.Document.toolTip); // const script = ScriptCast(this.Document.onClick); - // const toggleStatus = script ? script.script.run({ this: this.Document, self: this.Document, value: undefined, _readOnly_: true }).result : false; + // const toggleStatus = script ? script.script.run({ this: this.Document, value: undefined, _readOnly_: true }).result : false; // Colors const color = this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.Color); const items = DocListCast(this.dataDoc.data); @@ -278,10 +278,10 @@ export class FontIconBox extends ViewBoxBaseComponent<ButtonProps>() { tooltip: StrCast(item.toolTip), val: StrCast(item.toolType), }))} - selectedVal={StrCast(items.find(itemDoc => ScriptCast(itemDoc.onClick).script.run({ this: itemDoc, self: itemDoc, value: undefined, _readOnly_: true }).result)?.toolType)} + selectedVal={StrCast(items.find(itemDoc => ScriptCast(itemDoc.onClick).script.run({ this: itemDoc, value: undefined, _readOnly_: true }).result)?.toolType)} setSelectedVal={(val: string | number) => { const itemDoc = items.find(item => item.toolType === val); - itemDoc && ScriptCast(itemDoc.onClick).script.run({ this: itemDoc, self: itemDoc, value: val, _readOnly_: false }); + itemDoc && ScriptCast(itemDoc.onClick).script.run({ this: itemDoc, value: val, _readOnly_: false }); }} /> ); @@ -296,7 +296,7 @@ export class FontIconBox extends ViewBoxBaseComponent<ButtonProps>() { const script = ScriptCast(this.Document.onClick); const double = ScriptCast(this.Document.onDoubleClick); - const toggleStatus = script?.script.run({ this: this.Document, self: this.Document, value: undefined, _readOnly_: true }).result ?? false; + const toggleStatus = script?.script.run({ this: this.Document, value: undefined, _readOnly_: true }).result ?? false; // Colors const color = this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.Color); // const backgroundColor = this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.BackgroundColor); @@ -319,8 +319,8 @@ export class FontIconBox extends ViewBoxBaseComponent<ButtonProps>() { returnTrue, emptyFunction, action((clickEv, doubleTap) => { - (!doubleTap || !double) && script?.script.run({ this: this.Document, self: this.Document, value: !toggleStatus, _readOnly_: false }); - doubleTap && double?.script.run({ this: this.Document, self: this.Document, value: !toggleStatus, _readOnly_: false }); + (!doubleTap || !double) && script?.script.run({ this: this.Document, value: !toggleStatus, _readOnly_: false }); + doubleTap && double?.script.run({ this: this.Document, value: !toggleStatus, _readOnly_: false }); this._hackToRecompute += 1; }) ) @@ -341,15 +341,15 @@ export class FontIconBox extends ViewBoxBaseComponent<ButtonProps>() { @computed get editableText() { const script = ScriptCast(this.Document.script); - const checkResult = script?.script.run({ this: this.Document, self: this.Document, value: '', _readOnly_: true }).result; + const checkResult = script?.script.run({ this: this.Document, value: '', _readOnly_: true }).result; - const setValue = (value: string): boolean => script?.script.run({ this: this.Document, self: this.Document, value, _readOnly_: false }).result; + const setValue = (value: string): boolean => script?.script.run({ this: this.Document, value, _readOnly_: false }).result; return ( <div className="menuButton editableText"> <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon="lock" /> <div style={{ width: 'calc(100% - .875em)', paddingLeft: '4px' }}> - <EditableView GetValue={() => script?.script.run({ this: this.Document, self: this.Document, value: '', _readOnly_: true }).result} SetValue={setValue} oneLine contents={checkResult} /> + <EditableView GetValue={() => script?.script.run({ this: this.Document, value: '', _readOnly_: true }).result} SetValue={setValue} oneLine contents={checkResult} /> </div> </div> ); @@ -358,7 +358,7 @@ export class FontIconBox extends ViewBoxBaseComponent<ButtonProps>() { renderButton = () => { const color = this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.Color); const tooltip = StrCast(this.Document.toolTip); - const scriptFunc = () => ScriptCast(this.Document.onClick)?.script.run({ this: this.Document, self: this.Document, _readOnly_: false }); + const scriptFunc = () => ScriptCast(this.Document.onClick)?.script.run({ this: this.Document, _readOnly_: false }); const btnProps = { tooltip, icon: this.Icon(color)!, label: this.label }; // prettier-ignore switch (this.type) { diff --git a/src/client/views/nodes/FunctionPlotBox.tsx b/src/client/views/nodes/FunctionPlotBox.tsx index f32d39aaf..3d1bd7563 100644 --- a/src/client/views/nodes/FunctionPlotBox.tsx +++ b/src/client/views/nodes/FunctionPlotBox.tsx @@ -2,7 +2,7 @@ import functionPlot from 'function-plot'; import { computed, makeObservable, reaction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; -import { DocListCast } from '../../../fields/Doc'; +import { Doc, DocListCast } from '../../../fields/Doc'; import { List } from '../../../fields/List'; import { listSpec } from '../../../fields/Schema'; import { Cast, StrCast } from '../../../fields/Types'; @@ -11,7 +11,6 @@ import { DocUtils } from '../../documents/DocUtils'; import { DocumentType } from '../../documents/DocumentTypes'; import { Docs } from '../../documents/Documents'; import { DragManager } from '../../util/DragManager'; -import { LinkManager } from '../../util/LinkManager'; import { undoBatch } from '../../util/UndoManager'; import { ViewBoxAnnotatableComponent } from '../DocComponent'; import { PinDocView, PinProps } from '../PinFuncs'; @@ -49,8 +48,8 @@ export class FunctionPlotBox extends ViewBoxAnnotatableComponent<FieldViewProps> return anchor; }; @computed get graphFuncs() { - const links = LinkManager.Instance.getAllRelatedLinks(this.Document) - .map(d => LinkManager.getOppositeAnchor(d, this.Document)) + const links = Doc.Links(this.Document) + .map(d => Doc.getOppositeAnchor(d, this.Document)) .filter(d => d) .map(d => d!); const funcs = links.concat(DocListCast(this.dataDoc[this.fieldKey])).map(doc => diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index d317f46bb..3945da104 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -19,7 +19,6 @@ import { Docs } from '../../documents/Documents'; import { DocumentType } from '../../documents/DocumentTypes'; import { DocUtils } from '../../documents/DocUtils'; import { Networking } from '../../Network'; -import { DocumentManager } from '../../util/DocumentManager'; import { DragManager } from '../../util/DragManager'; import { undoBatch } from '../../util/UndoManager'; import { CollectionFreeFormView } from '../collections/collectionFreeForm/CollectionFreeFormView'; @@ -30,7 +29,8 @@ import { MarqueeAnnotator } from '../MarqueeAnnotator'; import { OverlayView } from '../OverlayView'; import { AnchorMenu } from '../pdf/AnchorMenu'; import { PinDocView, PinProps } from '../PinFuncs'; -import { StyleProp } from '../StyleProvider'; +import { StyleProp } from '../StyleProp'; +import { DocumentView } from './DocumentView'; import { FieldView, FieldViewProps } from './FieldView'; import { FocusViewOptions } from './FocusViewOptions'; import './ImageBox.scss'; @@ -254,7 +254,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() impl cropping.y = NumCast(this.Document.y); this._props.addDocTab(cropping, OpenWhere.inParent); } - DocumentManager.Instance.AddViewRenderedCb(cropping, dv => setTimeout(() => (dv.ComponentView as ImageBox).setNativeSize(), 200)); + DocumentView.addViewRenderedCb(cropping, dv => setTimeout(() => (dv.ComponentView as ImageBox).setNativeSize(), 200)); this._props.bringToFront?.(cropping); return cropping; }; diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx index 46bb16e50..cd591fa42 100644 --- a/src/client/views/nodes/KeyValueBox.tsx +++ b/src/client/views/nodes/KeyValueBox.tsx @@ -59,6 +59,8 @@ export class KeyValueBox extends ObservableReactComponent<FieldViewProps> { get fieldDocToLayout() { return DocCast(this._props.Document); } + isUnstyledView = returnTrue; // used by style provider via ViewBoxInterface + dontRegisterView = returnTrue; // used by ViewBoxInterface @action onEnterKey = (e: React.KeyboardEvent): void => { @@ -111,7 +113,7 @@ export class KeyValueBox extends ObservableReactComponent<FieldViewProps> { if (setResult) setResult?.(value); else target[key] = field; }; - const res = script.run({ this: Doc.Layout(doc), self: doc, _setCacheResult_ }, console.log); + const res = script.run({ this: Doc.Layout(doc), _setCacheResult_ }, console.log); if (!res.success) { if (key) target[key] = script.originalScript; return false; diff --git a/src/client/views/nodes/LabelBox.tsx b/src/client/views/nodes/LabelBox.tsx index 4dec3506c..f80ff5f94 100644 --- a/src/client/views/nodes/LabelBox.tsx +++ b/src/client/views/nodes/LabelBox.tsx @@ -13,7 +13,7 @@ import { ContextMenu } from '../ContextMenu'; import { ContextMenuProps } from '../ContextMenuItem'; import { ViewBoxBaseComponent } from '../DocComponent'; import { PinDocView, PinProps } from '../PinFuncs'; -import { StyleProp } from '../StyleProvider'; +import { StyleProp } from '../StyleProp'; import { FieldView, FieldViewProps } from './FieldView'; import BigText from './LabelBigText'; import './LabelBox.scss'; diff --git a/src/client/views/nodes/LinkAnchorBox.scss b/src/client/views/nodes/LinkAnchorBox.scss deleted file mode 100644 index caff369df..000000000 --- a/src/client/views/nodes/LinkAnchorBox.scss +++ /dev/null @@ -1,34 +0,0 @@ -.linkAnchorBox-cont, -.linkAnchorBox-cont-small { - cursor: default; - position: absolute; - width: 15; - height: 15; - border-radius: 20px; - user-select: none; - pointer-events: all; - - .linkAnchorBox-linkCloser { - position: absolute; - width: 18; - height: 18; - background: rgb(219, 21, 21); - top: -1px; - left: -1px; - border-radius: 5px; - display: flex; - justify-content: center; - align-items: center; - padding-left: 2px; - padding-top: 1px; - } - .linkAnchorBox-button { - position: relative; - display: inline-block; - } -} - -.linkAnchorBox-cont-small { - width: 5px; - height: 5px; -}
\ No newline at end of file diff --git a/src/client/views/nodes/LinkAnchorBox.tsx b/src/client/views/nodes/LinkAnchorBox.tsx deleted file mode 100644 index d43241de0..000000000 --- a/src/client/views/nodes/LinkAnchorBox.tsx +++ /dev/null @@ -1,118 +0,0 @@ -import { action, computed, makeObservable } from 'mobx'; -import { observer } from 'mobx-react'; -import * as React from 'react'; -import { setupMoveUpEvents } from '../../../ClientUtils'; -import { Utils, emptyFunction } from '../../../Utils'; -import { Doc } from '../../../fields/Doc'; -import { NumCast, StrCast } from '../../../fields/Types'; -import { TraceMobx } from '../../../fields/util'; -import { DragManager } from '../../util/DragManager'; -import { dropActionType } from '../../util/DropActionTypes'; -import { LinkFollower } from '../../util/LinkFollower'; -import { SelectionManager } from '../../util/SelectionManager'; -import { ViewBoxBaseComponent } from '../DocComponent'; -import { StyleProp } from '../StyleProvider'; -import { FieldView, FieldViewProps } from './FieldView'; -import './LinkAnchorBox.scss'; -import { LinkInfo } from './LinkDocPreview'; - -const { MEDIUM_GRAY } = require('../global/globalCssVariables.module.scss'); // prettier-ignore - -@observer -export class LinkAnchorBox extends ViewBoxBaseComponent<FieldViewProps>() { - public static LayoutString(fieldKey: string) { - return FieldView.LayoutString(LinkAnchorBox, fieldKey); - } - _doubleTap = false; - _lastTap: number = 0; - _ref = React.createRef<HTMLDivElement>(); - _isOpen = false; - _timeout: NodeJS.Timeout | undefined; - - constructor(props: FieldViewProps) { - super(props); - makeObservable(this); - } - - componentDidMount() { - this._props.setContentViewBox?.(this); - } - - @computed get linkSource() { - return this.DocumentView?.().containerViewPath?.().lastElement().Document; // this._props.styleProvider?.(this.dataDoc, this._props, StyleProp.LinkSource); - } - - onPointerDown = (e: React.PointerEvent) => { - const { linkSource } = this; - linkSource && - setupMoveUpEvents(this, e, this.onPointerMove, emptyFunction, (clickEv, doubleTap) => { - if (doubleTap) LinkFollower.FollowLink(this.Document, linkSource, false); - else this._props.select(false); - }); - }; - onPointerMove = action((e: PointerEvent) => { - const cdiv = this._ref?.current?.parentElement; - if (!this._isOpen && cdiv) { - const bounds = cdiv.getBoundingClientRect(); - const pt = Utils.getNearestPointInPerimeter(bounds.left, bounds.top, bounds.width, bounds.height, e.clientX, e.clientY); - const separation = Math.sqrt((pt[0] - e.clientX) * (pt[0] - e.clientX) + (pt[1] - e.clientY) * (pt[1] - e.clientY)); - if (separation > 100) { - const dragData = new DragManager.DocumentDragData([this.Document]); - dragData.dropAction = dropActionType.embed; - dragData.dropPropertiesToRemove = ['link_anchor_1_x', 'link_anchor_1_y', 'link_anchor_2_x', 'link_anchor_2_y', 'onClick']; - DragManager.StartDocumentDrag([this._ref.current!], dragData, pt[0], pt[1]); - return true; - } - this.layoutDoc[this.fieldKey + '_x'] = ((pt[0] - bounds.left) / bounds.width) * 100; - this.layoutDoc[this.fieldKey + '_y'] = ((pt[1] - bounds.top) / bounds.height) * 100; - this.layoutDoc.link_autoMoveAnchors = false; - } - return false; - }); - - specificContextMenu = (): void => {}; - - render() { - TraceMobx(); - const small = this._props.PanelWidth() <= 1; // this happens when rendered in a treeView - const x = NumCast(this.layoutDoc[this.fieldKey + '_x'], 100); - const y = NumCast(this.layoutDoc[this.fieldKey + '_y'], 100); - const background = this._props.styleProvider?.(this.dataDoc, this._props, StyleProp.BackgroundColor + ':anchor'); - const anchor = this.fieldKey === 'link_anchor_1' ? 'link_anchor_2' : 'link_anchor_1'; - const anchorScale = !this.dataDoc[this.fieldKey + '_useSmallAnchor'] && (x === 0 || x === 100 || y === 0 || y === 100) ? 1 : 0.25; - const targetTitle = StrCast((this.dataDoc[anchor] as Doc)?.title); - const selView = SelectionManager.Views.lastElement()?._props.LayoutTemplateString?.includes('link_anchor_1') - ? 'link_anchor_1' - : SelectionManager.Views.lastElement()?._props.LayoutTemplateString?.includes('link_anchor_2') - ? 'link_anchor_2' - : ''; - return ( - <div - ref={this._ref} - title={targetTitle} - className={`linkAnchorBox-cont${small ? '-small' : ''}`} - onPointerEnter={e => - LinkInfo.SetLinkInfo({ - DocumentView: this.DocumentView, - styleProvider: this._props.styleProvider, - linkSrc: this.linkSource, - linkDoc: this.Document, - showHeader: true, - location: [e.clientX, e.clientY + 20], - noPreview: false, - }) - } - onPointerDown={this.onPointerDown} - onContextMenu={this.specificContextMenu} - style={{ - border: selView && this.dataDoc[selView] === this.dataDoc[this.fieldKey] ? `solid ${MEDIUM_GRAY} 2px` : undefined, - background, - left: `calc(${x}% - ${small ? 2.5 : 7.5}px)`, - top: `calc(${y}% - ${small ? 2.5 : 7.5}px)`, - transform: `scale(${anchorScale})`, - cursor: 'grab', - }} - /> - ); - } -} diff --git a/src/client/views/nodes/LinkBox.tsx b/src/client/views/nodes/LinkBox.tsx index 559b1fcae..6caa38a7f 100644 --- a/src/client/views/nodes/LinkBox.tsx +++ b/src/client/views/nodes/LinkBox.tsx @@ -13,12 +13,11 @@ import { TraceMobx } from '../../../fields/util'; import { emptyFunction } from '../../../Utils'; import { Docs } from '../../documents/Documents'; import { DocumentType } from '../../documents/DocumentTypes'; -import { DocumentManager } from '../../util/DocumentManager'; import { SnappingManager } from '../../util/SnappingManager'; import { ViewBoxBaseComponent } from '../DocComponent'; import { EditableView } from '../EditableView'; import { LightboxView } from '../LightboxView'; -import { StyleProp } from '../StyleProvider'; +import { StyleProp } from '../StyleProp'; import { ComparisonBox } from './ComparisonBox'; import { DocumentView } from './DocumentView'; import { FieldView, FieldViewProps } from './FieldView'; @@ -43,7 +42,7 @@ export class LinkBox extends ViewBoxBaseComponent<FieldViewProps>() { anchor = (which: number) => { const anch = DocCast(this.dataDoc['link_anchor_' + which]); const anchor = anch?.layout_unrendered ? DocCast(anch.annotationOn) : anch; - return DocumentManager.Instance.getDocumentView(anchor, this.DocumentView?.().containerViewPath?.().lastElement()); + return DocumentView.getDocumentView(anchor, this.DocumentView?.().containerViewPath?.().lastElement()); }; _hackToSeeIfDeleted: any; componentWillUnmount() { diff --git a/src/client/views/nodes/LinkDescriptionPopup.tsx b/src/client/views/nodes/LinkDescriptionPopup.tsx index 23cb25962..ff95f8547 100644 --- a/src/client/views/nodes/LinkDescriptionPopup.tsx +++ b/src/client/views/nodes/LinkDescriptionPopup.tsx @@ -2,16 +2,17 @@ import { action, makeObservable, observable, reaction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { DocData } from '../../../fields/DocSymbols'; +import { StrCast } from '../../../fields/Types'; import { LinkManager } from '../../util/LinkManager'; import './LinkDescriptionPopup.scss'; import { TaskCompletionBox } from './TaskCompletedBox'; -import { StrCast } from '../../../fields/Types'; @observer export class LinkDescriptionPopup extends React.Component<{}> { // eslint-disable-next-line no-use-before-define public static Instance: LinkDescriptionPopup; @observable public display: boolean = false; + // eslint-disable-next-line react/no-unused-class-component-methods @observable public showDescriptions: string = 'ON'; @observable public popupX: number = 700; @observable public popupY: number = 350; diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx index 0936acc15..508008569 100644 --- a/src/client/views/nodes/LinkDocPreview.tsx +++ b/src/client/views/nodes/LinkDocPreview.tsx @@ -11,12 +11,10 @@ import { Cast, DocCast, NumCast, PromiseValue, StrCast } from '../../../fields/T import { DocServer } from '../../DocServer'; import { DocumentType } from '../../documents/DocumentTypes'; import { Docs } from '../../documents/Documents'; -import { DocumentManager } from '../../util/DocumentManager'; import { DragManager } from '../../util/DragManager'; -import { LinkFollower } from '../../util/LinkFollower'; import { LinkManager } from '../../util/LinkManager'; import { SearchUtil } from '../../util/SearchUtil'; -import { SettingsManager } from '../../util/SettingsManager'; +import { SnappingManager } from '../../util/SnappingManager'; import { Transform } from '../../util/Transform'; import { ObservableReactComponent } from '../ObservableReactComponent'; import { DocumentView } from './DocumentView'; @@ -134,17 +132,17 @@ export class LinkDocPreview extends ObservableReactComponent<LinkDocPreviewProps const anchorDoc = anchorDocId ? PromiseValue(DocCast(DocServer.GetCachedRefField(anchorDocId) ?? DocServer.GetRefField(anchorDocId))) : undefined; anchorDoc?.then?.( action(anchor => { - if (anchor instanceof Doc && LinkManager.Links(anchor).length) { - this._linkDoc = this._linkDoc ?? LinkManager.Links(anchor)[0]; + if (anchor instanceof Doc && Doc.Links(anchor).length) { + this._linkDoc = this._linkDoc ?? Doc.Links(anchor)[0]; const automaticLink = this._linkDoc.link_relationship === LinkManager.AutoKeywords; if (automaticLink) { // automatic links specify the target in the link info, not the source const linkTarget = anchor; - this._linkSrc = LinkManager.getOppositeAnchor(this._linkDoc, linkTarget); + this._linkSrc = Doc.getOppositeAnchor(this._linkDoc, linkTarget); this._markerTargetDoc = this._targetDoc = linkTarget; } else { this._linkSrc = anchor; - const linkTarget = LinkManager.getOppositeAnchor(this._linkDoc, this._linkSrc); + const linkTarget = Doc.getOppositeAnchor(this._linkDoc, this._linkSrc); this._markerTargetDoc = linkTarget; this._targetDoc = /* linkTarget?.type === DocumentType.MARKER && */ linkTarget?.annotationOn ? Cast(linkTarget.annotationOn, Doc, null) ?? linkTarget : linkTarget; } @@ -169,8 +167,8 @@ export class LinkDocPreview extends ObservableReactComponent<LinkDocPreviewProps LinkManager.Instance.currentLink = this._linkDoc; LinkManager.Instance.currentLinkAnchor = this._linkSrc; this._props.DocumentView?.().select(false); - if ((SettingsManager.Instance.propertiesWidth ?? 0) < 100) { - SettingsManager.Instance.propertiesWidth = 250; + if ((SnappingManager.PropertiesWidth ?? 0) < 100) { + SnappingManager.SetPropertiesWidth(250); } }) ); @@ -196,13 +194,13 @@ export class LinkDocPreview extends ObservableReactComponent<LinkDocPreviewProps followLink = () => { LinkInfo.Clear(); if (this._linkDoc && this._linkSrc) { - LinkFollower.FollowLink(this._linkDoc, this._linkSrc, false); + DocumentView.FollowLink(this._linkDoc, this._linkSrc, false); } else if (this._props.hrefs?.length) { const webDoc = Array.from(SearchUtil.SearchCollection(Doc.MyFilesystem, this._props.hrefs[0], false).keys()) .filter(doc => doc.type === DocumentType.WEB) .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, { + DocumentView.showDocument(webDoc, { openLocation: OpenWhere.lightbox, willPan: true, zoomTime: 500, @@ -229,7 +227,7 @@ export class LinkDocPreview extends ObservableReactComponent<LinkDocPreviewProps }; @computed get previewHeader() { return !this._linkDoc || !this._markerTargetDoc || !this._targetDoc || !this._linkSrc ? null : ( - <div className="linkDocPreview-info" style={{ background: SettingsManager.userBackgroundColor }}> + <div className="linkDocPreview-info" style={{ background: SnappingManager.userBackgroundColor }}> <div className="linkDocPreview-buttonBar" style={{ float: 'left' }}> <Tooltip title={<div className="dash-tooltip">Edit Link</div>} placement="top"> <div className="linkDocPreview-button" onPointerDown={this.editLink}> @@ -282,7 +280,7 @@ export class LinkDocPreview extends ObservableReactComponent<LinkDocPreviewProps ) : ( <DocumentView ref={r => { - const targetanchor = this._linkDoc && this._linkSrc && LinkManager.getOppositeAnchor(this._linkDoc, this._linkSrc); + const targetanchor = this._linkDoc && this._linkSrc && Doc.getOppositeAnchor(this._linkDoc, this._linkSrc); targetanchor && this._targetDoc !== targetanchor && r?._props.focus?.(targetanchor, {}); }} Document={this._targetDoc!} @@ -325,7 +323,7 @@ export class LinkDocPreview extends ObservableReactComponent<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: SnappingManager.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/LoadingBox.tsx b/src/client/views/nodes/LoadingBox.tsx index aa89398f3..5f343bdfe 100644 --- a/src/client/views/nodes/LoadingBox.tsx +++ b/src/client/views/nodes/LoadingBox.tsx @@ -6,12 +6,11 @@ import { Doc } from '../../../fields/Doc'; import { Id } from '../../../fields/FieldSymbols'; import { StrCast } from '../../../fields/Types'; import { Networking } from '../../Network'; -import { DocumentManager } from '../../util/DocumentManager'; +import { DocumentType } from '../../documents/DocumentTypes'; +import { Docs } from '../../documents/Documents'; import { ViewBoxAnnotatableComponent } from '../DocComponent'; import { FieldView, FieldViewProps } from './FieldView'; import './LoadingBox.scss'; -import { DocumentType } from '../../documents/DocumentTypes'; -import { Docs } from '../../documents/Documents'; /** * LoadingBox Class represents a placeholder doc for documents that are currently @@ -39,25 +38,11 @@ export class LoadingBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { public static LayoutString(fieldKey: string) { return FieldView.LayoutString(LoadingBox, fieldKey); } - // removes from currently loading display - public static removeCurrentlyLoading(doc: Doc) { - if (DocumentManager.Instance.CurrentlyLoading) { - const index = DocumentManager.Instance.CurrentlyLoading.indexOf(doc); - runInAction(() => index !== -1 && DocumentManager.Instance.CurrentlyLoading.splice(index, 1)); - } - } - - // adds doc to currently loading display - public static addCurrentlyLoading(doc: Doc) { - if (DocumentManager.Instance.CurrentlyLoading.indexOf(doc) === -1) { - runInAction(() => DocumentManager.Instance.CurrentlyLoading.push(doc)); - } - } _timer: any; @observable progress = ''; componentDidMount() { - if (!DocumentManager.Instance.CurrentlyLoading?.includes(this.Document)) { + if (!Doc.CurrentlyLoading?.includes(this.Document)) { this.Document.loadingError = 'Upload interrupted, please try again'; } else { const updateFunc = async () => { diff --git a/src/client/views/nodes/MapBox/DirectionsAnchorMenu.tsx b/src/client/views/nodes/MapBox/DirectionsAnchorMenu.tsx index f176317d2..b8fd8ac6a 100644 --- a/src/client/views/nodes/MapBox/DirectionsAnchorMenu.tsx +++ b/src/client/views/nodes/MapBox/DirectionsAnchorMenu.tsx @@ -8,9 +8,9 @@ import { returnFalse } from '../../../../ClientUtils'; import { unimplementedFunction } from '../../../../Utils'; import { Doc, Opt } from '../../../../fields/Doc'; import { NumCast, StrCast } from '../../../../fields/Types'; -import { SelectionManager } from '../../../util/SelectionManager'; import { SettingsManager } from '../../../util/SettingsManager'; import { AntimodeMenu, AntimodeMenuProps } from '../../AntimodeMenu'; +import { DocumentView } from '../DocumentView'; @observer export class DirectionsAnchorMenu extends AntimodeMenu<AntimodeMenuProps> { @@ -56,7 +56,7 @@ export class DirectionsAnchorMenu extends AntimodeMenu<AntimodeMenuProps> { componentDidMount() { this._disposer = reaction( - () => SelectionManager.Views.slice(), + () => DocumentView.Selected().slice(), () => DirectionsAnchorMenu.Instance.fadeOut(true) ); } diff --git a/src/client/views/nodes/MapBox/MapAnchorMenu.tsx b/src/client/views/nodes/MapBox/MapAnchorMenu.tsx index 174511e1a..103a35434 100644 --- a/src/client/views/nodes/MapBox/MapAnchorMenu.tsx +++ b/src/client/views/nodes/MapBox/MapAnchorMenu.tsx @@ -13,9 +13,9 @@ import { unimplementedFunction } from '../../../../Utils'; import { Doc, Opt } from '../../../../fields/Doc'; import { NumCast, StrCast } from '../../../../fields/Types'; import { CalendarManager } from '../../../util/CalendarManager'; -import { SelectionManager } from '../../../util/SelectionManager'; import { SettingsManager } from '../../../util/SettingsManager'; import { AntimodeMenu, AntimodeMenuProps } from '../../AntimodeMenu'; +import { DocumentView } from '../DocumentView'; import './MapAnchorMenu.scss'; import { MapboxApiUtility, TransportationType } from './MapboxApiUtility'; import { MarkerIcons } from './MarkerIcons'; @@ -126,7 +126,7 @@ export class MapAnchorMenu extends AntimodeMenu<AntimodeMenuProps> { componentDidMount() { this._disposer = reaction( - () => SelectionManager.Views.slice(), + () => DocumentView.Selected().slice(), () => MapAnchorMenu.Instance.fadeOut(true) ); } diff --git a/src/client/views/nodes/MapBox/MapBox.tsx b/src/client/views/nodes/MapBox/MapBox.tsx index 50831f8ea..ac8010f11 100644 --- a/src/client/views/nodes/MapBox/MapBox.tsx +++ b/src/client/views/nodes/MapBox/MapBox.tsx @@ -21,9 +21,7 @@ import { DocCast, NumCast, StrCast, toList } from '../../../../fields/Types'; import { DocUtils } from '../../../documents/DocUtils'; import { DocumentType } from '../../../documents/DocumentTypes'; import { Docs } from '../../../documents/Documents'; -import { DocumentManager } from '../../../util/DocumentManager'; import { DragManager } from '../../../util/DragManager'; -import { LinkManager } from '../../../util/LinkManager'; import { UndoManager, undoable } from '../../../util/UndoManager'; import { ViewBoxAnnotatableComponent, ViewBoxInterface } from '../../DocComponent'; import { PinDocView, PinProps } from '../../PinFuncs'; @@ -249,7 +247,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem if (existingPin) { setTimeout(() => { // we use a timeout in case this is called from the sidebar which may have just added a link that hasn't made its way into th elink manager yet - if (!LinkManager.Instance.getAllRelatedLinks(doc).some(link => DocCast(link.link_anchor_1)?.mapPin === existingPin || DocCast(link.link_anchor_2)?.mapPin === existingPin)) { + if (!Doc.Links(doc).some(link => DocCast(link.link_anchor_1)?.mapPin === existingPin || DocCast(link.link_anchor_2)?.mapPin === existingPin)) { const anchor = this.getAnchor(true, undefined, existingPin); anchor && DocUtils.MakeLink(anchor, doc, { link_relationship: 'link to map location' }); doc.latitude = existingPin?.latitude; @@ -438,7 +436,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem options.didMove = true; } return new Promise<Opt<DocumentView>>(res => { - DocumentManager.Instance.AddViewRenderedCb(doc, dv => res(dv)); + DocumentView.addViewRenderedCb(doc, dv => res(dv)); }); }; diff --git a/src/client/views/nodes/MapBox/MapBox2.tsx b/src/client/views/nodes/MapBox/MapBox2.tsx index 9825824bd..7697fd295 100644 --- a/src/client/views/nodes/MapBox/MapBox2.tsx +++ b/src/client/views/nodes/MapBox/MapBox2.tsx @@ -509,9 +509,9 @@ // // TODO: auto center on select a document in the sidebar // private handleMapCenter = (map: google.maps.Map) => { -// // console.log("print the selected views in selectionManager:") -// // if (SelectionManager.Views.lastElement()) { -// // console.log(SelectionManager.Views.lastElement()); +// // console.log("print the selected views in Document.Selected:") +// // if (DocumentView.Selected().lastElement()) { +// // console.log(DocumentView.Selected().lastElement()); // // } // }; diff --git a/src/client/views/nodes/MapboxMapBox/MapboxContainer.tsx b/src/client/views/nodes/MapboxMapBox/MapboxContainer.tsx index 3b4ffd4bd..bfd40692b 100644 --- a/src/client/views/nodes/MapboxMapBox/MapboxContainer.tsx +++ b/src/client/views/nodes/MapboxMapBox/MapboxContainer.tsx @@ -13,9 +13,7 @@ import { DocCast, NumCast, StrCast, toList } from '../../../../fields/Types'; import { DocUtils } from '../../../documents/DocUtils'; import { DocumentType } from '../../../documents/DocumentTypes'; import { Docs } from '../../../documents/Documents'; -import { DocumentManager } from '../../../util/DocumentManager'; import { DragManager } from '../../../util/DragManager'; -import { LinkManager } from '../../../util/LinkManager'; import { Transform } from '../../../util/Transform'; import { UndoManager, undoable } from '../../../util/UndoManager'; import { ViewBoxAnnotatableComponent } from '../../DocComponent'; @@ -130,7 +128,7 @@ export class MapBoxContainer extends ViewBoxAnnotatableComponent<FieldViewProps> if (existingPin) { setTimeout(() => { // we use a timeout in case this is called from the sidebar which may have just added a link that hasn't made its way into th elink manager yet - if (!LinkManager.Instance.getAllRelatedLinks(doc).some(link => DocCast(link.link_anchor_1)?.mapPin === existingPin || DocCast(link.link_anchor_2)?.mapPin === existingPin)) { + if (!Doc.Links(doc).some(link => DocCast(link.link_anchor_1)?.mapPin === existingPin || DocCast(link.link_anchor_2)?.mapPin === existingPin)) { const anchor = this.getAnchor(true, undefined, existingPin); anchor && DocUtils.MakeLink(anchor, doc, { link_relationship: 'link to map location' }); doc.latitude = existingPin?.latitude; @@ -390,7 +388,7 @@ export class MapBoxContainer extends ViewBoxAnnotatableComponent<FieldViewProps> options.didMove = true; } return new Promise<Opt<DocumentView>>(res => { - DocumentManager.Instance.AddViewRenderedCb(doc, dv => res(dv)); + DocumentView.addViewRenderedCb(doc, dv => res(dv)); }); }; /* diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index 5d1874aca..9038ed27a 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -19,9 +19,7 @@ import { emptyFunction } from '../../../Utils'; import { Docs } from '../../documents/Documents'; import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes'; import { DocUtils } from '../../documents/DocUtils'; -import { DocumentManager } from '../../util/DocumentManager'; import { KeyCodes } from '../../util/KeyCodes'; -import { SelectionManager } from '../../util/SelectionManager'; import { undoBatch, UndoManager } from '../../util/UndoManager'; import { CollectionFreeFormView } from '../collections/collectionFreeForm'; import { CollectionStackingView } from '../collections/CollectionStackingView'; @@ -251,7 +249,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem this.toggleSidebar(false); } return new Promise<Opt<DocumentView>>(res => { - DocumentManager.Instance.AddViewRenderedCb(doc, dv => res(dv)); + DocumentView.addViewRenderedCb(doc, dv => res(dv)); }); }; @@ -561,7 +559,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem removeDocument={this.removeDocument} /> ) : ( - <div onPointerDown={e => setupMoveUpEvents(this, e, returnFalse, emptyFunction, () => SelectionManager.SelectView(this.DocumentView?.()!, false), true)}> + <div onPointerDown={e => setupMoveUpEvents(this, e, returnFalse, emptyFunction, () => DocumentView.SelectView(this.DocumentView?.()!, false), true)}> <ComponentTag // eslint-disable-next-line react/jsx-props-no-spreading {...this._props} diff --git a/src/client/views/nodes/RecordingBox/RecordingBox.tsx b/src/client/views/nodes/RecordingBox/RecordingBox.tsx index ae6caf9f4..e46e40bfe 100644 --- a/src/client/views/nodes/RecordingBox/RecordingBox.tsx +++ b/src/client/views/nodes/RecordingBox/RecordingBox.tsx @@ -3,6 +3,7 @@ import { observer } from 'mobx-react'; import * as React from 'react'; import { DateField } from '../../../../fields/DateField'; import { Doc, DocListCast } from '../../../../fields/Doc'; +import { DocData } from '../../../../fields/DocSymbols'; import { Id } from '../../../../fields/FieldSymbols'; import { List } from '../../../../fields/List'; import { BoolCast, DocCast } from '../../../../fields/Types'; @@ -10,19 +11,18 @@ import { VideoField } from '../../../../fields/URLField'; import { Upload } from '../../../../server/SharedMediaTypes'; import { DocumentType } from '../../../documents/DocumentTypes'; import { Docs } from '../../../documents/Documents'; -import { DocumentManager } from '../../../util/DocumentManager'; import { DragManager } from '../../../util/DragManager'; +import { dropActionType } from '../../../util/DropActionTypes'; import { ScriptingGlobals } from '../../../util/ScriptingGlobals'; import { Presentation } from '../../../util/TrackMovements'; import { undoBatch } from '../../../util/UndoManager'; import { ViewBoxBaseComponent } from '../../DocComponent'; import { CollectionFreeFormView } from '../../collections/collectionFreeForm/CollectionFreeFormView'; import { mediaState } from '../AudioBox'; +import { DocumentView } from '../DocumentView'; import { FieldView, FieldViewProps } from '../FieldView'; import { VideoBox } from '../VideoBox'; import { RecordingView } from './RecordingView'; -import { DocData } from '../../../../fields/DocSymbols'; -import { dropActionType } from '../../../util/DropActionTypes'; @observer export class RecordingBox extends ViewBoxBaseComponent<FieldViewProps>() { @@ -102,7 +102,7 @@ export class RecordingBox extends ViewBoxBaseComponent<FieldViewProps>() { screengrabber.overlayY = 590; // was 0 screengrabber[DocData][Doc.LayoutFieldKey(screengrabber) + '_trackScreen'] = true; Doc.AddToMyOverlay(screengrabber); // just adds doc to overlay - DocumentManager.Instance.AddViewRenderedCb(screengrabber, docView => { + DocumentView.addViewRenderedCb(screengrabber, docView => { RecordingBox.screengrabber = docView.ComponentView as RecordingBox; RecordingBox.screengrabber.Record?.(); }); @@ -119,7 +119,7 @@ export class RecordingBox extends ViewBoxBaseComponent<FieldViewProps>() { value.overlayX = 70; value.overlayY = window.innerHeight - 180; Doc.AddToMyOverlay(value); - DocumentManager.Instance.AddViewRenderedCb(value, docView => { + DocumentView.addViewRenderedCb(value, docView => { Doc.UserDoc().currentRecording = docView.Document; docView.select(false); RecordingBox.resumeWorkspaceReplaying(value); @@ -132,7 +132,7 @@ export class RecordingBox extends ViewBoxBaseComponent<FieldViewProps>() { */ @undoBatch public static addRecToWorkspace(value: RecordingBox) { - const ffView = Array.from(DocumentManager.Instance.DocumentViews).find(view => view.ComponentView instanceof CollectionFreeFormView); + const ffView = DocumentView.allViews().find(view => view.ComponentView instanceof CollectionFreeFormView); (ffView?.ComponentView as CollectionFreeFormView)._props.addDocument?.(value.Document); Doc.RemoveDocFromList(Doc.UserDoc(), 'workspaceRecordings', value.Document); Doc.RemFromMyOverlay(value.Document); @@ -142,7 +142,7 @@ export class RecordingBox extends ViewBoxBaseComponent<FieldViewProps>() { } public static resumeWorkspaceReplaying(doc: Doc) { - const docView = DocumentManager.Instance.getDocumentView(doc); + const docView = DocumentView.getDocumentView(doc); if (docView?.ComponentView instanceof VideoBox) { docView.ComponentView.Play(); } @@ -150,7 +150,7 @@ export class RecordingBox extends ViewBoxBaseComponent<FieldViewProps>() { } public static pauseWorkspaceReplaying(doc: Doc) { - const docView = DocumentManager.Instance.getDocumentView(doc); + const docView = DocumentView.getDocumentView(doc); const videoBox = docView?.ComponentView as VideoBox; if (videoBox) { videoBox.Pause(); diff --git a/src/client/views/nodes/ScreenshotBox.tsx b/src/client/views/nodes/ScreenshotBox.tsx index 8eb55b2f8..3be50f5e6 100644 --- a/src/client/views/nodes/ScreenshotBox.tsx +++ b/src/client/views/nodes/ScreenshotBox.tsx @@ -24,6 +24,7 @@ import { SettingsManager } from '../../util/SettingsManager'; import { TrackMovements } from '../../util/TrackMovements'; import { ContextMenu } from '../ContextMenu'; import { ViewBoxAnnotatableComponent } from '../DocComponent'; +import { DocViewUtils } from '../DocViewUtils'; import { CollectionStackedTimeline } from '../collections/CollectionStackedTimeline'; import { CollectionFreeFormView } from '../collections/collectionFreeForm/CollectionFreeFormView'; import { mediaState } from './AudioBox'; @@ -161,8 +162,8 @@ export class ScreenshotBox extends ViewBoxAnnotatableComponent<FieldViewProps>() // }); } componentWillUnmount() { - const ind = DocUtils.ActiveRecordings.indexOf(this); - ind !== -1 && DocUtils.ActiveRecordings.splice(ind, 1); + const ind = DocViewUtils.ActiveRecordings.indexOf(this); + ind !== -1 && DocViewUtils.ActiveRecordings.splice(ind, 1); } specificContextMenu = (): void => { @@ -265,7 +266,7 @@ export class ScreenshotBox extends ViewBoxAnnotatableComponent<FieldViewProps>() this._screenCapture = true; this.dataDoc.mediaState = 'recording'; }); - DocUtils.ActiveRecordings.push(this); + DocViewUtils.ActiveRecordings.push(this); } else { this._audioRec?.stop(); this._videoRec?.stop(); @@ -273,8 +274,8 @@ export class ScreenshotBox extends ViewBoxAnnotatableComponent<FieldViewProps>() this._screenCapture = false; this.dataDoc.mediaState = 'paused'; }); - const ind = DocUtils.ActiveRecordings.indexOf(this); - ind !== -1 && DocUtils.ActiveRecordings.splice(ind, 1); + const ind = DocViewUtils.ActiveRecordings.indexOf(this); + ind !== -1 && DocViewUtils.ActiveRecordings.splice(ind, 1); CaptureManager.Instance.open(this.Document); } diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx index f32d00386..afd73cfe8 100644 --- a/src/client/views/nodes/VideoBox.tsx +++ b/src/client/views/nodes/VideoBox.tsx @@ -16,9 +16,7 @@ import { emptyFunction, formatTime } from '../../../Utils'; import { Docs } from '../../documents/Documents'; import { DocumentType } from '../../documents/DocumentTypes'; import { DocUtils, FollowLinkScript } from '../../documents/DocUtils'; -import { DocumentManager } from '../../util/DocumentManager'; import { dropActionType } from '../../util/DropActionTypes'; -import { LinkManager } from '../../util/LinkManager'; import { ReplayMovements } from '../../util/ReplayMovements'; import { undoBatch } from '../../util/UndoManager'; import { CollectionFreeFormView } from '../collections/collectionFreeForm/CollectionFreeFormView'; @@ -26,16 +24,16 @@ import { CollectionStackedTimeline, TrimScope } from '../collections/CollectionS import { ContextMenu } from '../ContextMenu'; import { ContextMenuProps } from '../ContextMenuItem'; import { ViewBoxAnnotatableComponent, ViewBoxInterface } from '../DocComponent'; +import { VideoThumbnails } from '../global/globalEnums'; import { MarqueeAnnotator } from '../MarqueeAnnotator'; import { AnchorMenu } from '../pdf/AnchorMenu'; import { PinDocView, PinProps } from '../PinFuncs'; -import { StyleProp } from '../StyleProvider'; +import { StyleProp } from '../StyleProp'; import { DocumentView } from './DocumentView'; import { FieldView, FieldViewProps } from './FieldView'; import { FocusViewOptions } from './FocusViewOptions'; import { RecordingBox } from './RecordingBox'; import './VideoBox.scss'; -import { VideoThumbnails } from '../global/globalEnums'; /** * VideoBox @@ -88,7 +86,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps>() impl @observable _scrubbing: boolean = false; @computed get links() { - return LinkManager.Links(this.dataDoc); + return Doc.Links(this.dataDoc); } @computed get heightPercent() { return NumCast(this.layoutDoc._layout_timelineHeightPercent, 100); @@ -347,7 +345,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps>() impl this._props.addDocument?.(imageSnapshot); DocUtils.MakeLink(imageSnapshot, this.getAnchor(true), { link_relationship: 'video snapshot' }); // link && (DocCast(link.link_anchor_2)[DocData].timecodeToHide = NumCast(DocCast(link.link_anchor_2).timecodeToShow) + 3); // do we need to set an end time? should default to +0.1 - setTimeout(() => downX !== undefined && downY !== undefined && DocumentManager.Instance.getFirstDocumentView(imageSnapshot)?.startDragging(downX, downY, dropActionType.move, true)); + setTimeout(() => downX !== undefined && downY !== undefined && DocumentView.getFirstDocumentView(imageSnapshot)?.startDragging(downX, downY, dropActionType.move, true)); }; getAnchor = (addAsAnnotation: boolean, pinProps?: PinProps) => { @@ -392,7 +390,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps>() impl return this._stackedTimeline.getView(doc, options); } return new Promise<Opt<DocumentView>>(res => { - DocumentManager.Instance.AddViewRenderedCb(doc, dv => res(dv)); + DocumentView.addViewRenderedCb(doc, dv => res(dv)); }); }; @@ -446,7 +444,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps>() impl { fireImmediately: true } ); - (!this.dataDoc[this.fieldKey + '_thumbnails'] || StrListCast(this.dataDoc[this.fieldKey + '_thumbnails']).length !== VideoBox.numThumbnails) && this.getVideoThumbnails(); + (!this.dataDoc[this.fieldKey + '_thumbnails'] || StrListCast(this.dataDoc[this.fieldKey + '_thumbnails']).length !== VideoThumbnails.DENSE) && this.getVideoThumbnails(); } }; @@ -652,20 +650,20 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps>() impl @action removeCurrentlyPlaying = () => { const docView = this.DocumentView?.(); - if (CollectionStackedTimeline.CurrentlyPlaying && docView) { - const index = CollectionStackedTimeline.CurrentlyPlaying.indexOf(docView); - index !== -1 && CollectionStackedTimeline.CurrentlyPlaying.splice(index, 1); + if (DocumentView.CurrentlyPlaying && docView) { + const index = DocumentView.CurrentlyPlaying.indexOf(docView); + index !== -1 && DocumentView.CurrentlyPlaying.splice(index, 1); } }; // adds doc to currently playing display @action addCurrentlyPlaying = () => { const docView = this.DocumentView?.(); - if (!CollectionStackedTimeline.CurrentlyPlaying) { - CollectionStackedTimeline.CurrentlyPlaying = []; + if (!DocumentView.CurrentlyPlaying) { + DocumentView.CurrentlyPlaying = []; } - if (docView && CollectionStackedTimeline.CurrentlyPlaying.indexOf(docView) === -1) { - CollectionStackedTimeline.CurrentlyPlaying.push(docView); + if (docView && DocumentView.CurrentlyPlaying.indexOf(docView) === -1) { + DocumentView.CurrentlyPlaying.push(docView); } }; diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index 54f246b20..1003bc473 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -21,7 +21,6 @@ import { emptyFunction, stringHash } from '../../../Utils'; import { Docs } from '../../documents/Documents'; import { DocumentType } from '../../documents/DocumentTypes'; import { DocUtils } from '../../documents/DocUtils'; -import { DocumentManager } from '../../util/DocumentManager'; import { ScriptingGlobals } from '../../util/ScriptingGlobals'; import { SnappingManager } from '../../util/SnappingManager'; import { undoBatch, UndoManager } from '../../util/UndoManager'; @@ -38,7 +37,7 @@ import { Annotation } from '../pdf/Annotation'; import { GPTPopup } from '../pdf/GPTPopup/GPTPopup'; import { PinDocView, PinProps } from '../PinFuncs'; import { SidebarAnnos } from '../SidebarAnnos'; -import { StyleProp } from '../StyleProvider'; +import { StyleProp } from '../StyleProp'; import { DocumentView } from './DocumentView'; import { FieldView, FieldViewProps } from './FieldView'; import { FocusViewOptions } from './FocusViewOptions'; @@ -324,7 +323,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem if (this._url && webUrl && webUrl.href !== this._url) this.setData(webUrl.href); if (this._sidebarRef?.current?.makeDocUnfiltered(doc) && !this.SidebarShown) this.toggleSidebar(false); return new Promise<Opt<DocumentView>>(res => { - DocumentManager.Instance.AddViewRenderedCb(doc, dv => res(dv)); + DocumentView.addViewRenderedCb(doc, dv => res(dv)); }); }; diff --git a/src/client/views/nodes/formattedText/DashFieldView.tsx b/src/client/views/nodes/formattedText/DashFieldView.tsx index 1c5ea2dd4..5d53a2a5f 100644 --- a/src/client/views/nodes/formattedText/DashFieldView.tsx +++ b/src/client/views/nodes/formattedText/DashFieldView.tsx @@ -293,7 +293,6 @@ export class DashFieldView { unclickable = () => !this.tbox._props.rootSelected?.() && this.node.marks.some((m: any) => m.type === this.tbox.EditorView?.state.schema.marks.linkAnchor && m.attrs.noPreview); constructor(node: any, view: any, getPos: any, tbox: FormattedTextBox) { makeObservable(this); - const self = this; this.node = node; this.tbox = tbox; this.getpos = getPos; @@ -305,14 +304,14 @@ export class DashFieldView { this.dom.onkeypress = function (e: KeyboardEvent) { e.stopPropagation(); }; - this.dom.onkeydown = function (e: KeyboardEvent) { + this.dom.onkeydown = (e: KeyboardEvent) => { e.stopPropagation(); if (e.key === 'Tab') { e.preventDefault(); const editor = tbox.EditorView; if (editor) { const { state } = editor; - for (let i = self.getpos() + 1; i < state.doc.content.size; i++) { + for (let i = this.getpos() + 1; i < state.doc.content.size; i++) { if (state.doc.nodeAt(i)?.type.name === state.schema.nodes.dashField.name) { editor.dispatch(state.tr.setSelection(new NodeSelection(state.doc.resolve(i)))); return; diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index ad6629fc9..8a4a7718a 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -32,16 +32,13 @@ import { Docs } from '../../../documents/Documents'; import { CollectionViewType, DocumentType } from '../../../documents/DocumentTypes'; import { DocUtils } from '../../../documents/DocUtils'; import { DictationManager } from '../../../util/DictationManager'; -import { DocumentManager } from '../../../util/DocumentManager'; import { DragManager } from '../../../util/DragManager'; import { dropActionType } from '../../../util/DropActionTypes'; import { MakeTemplate } from '../../../util/DropConverter'; import { LinkManager } from '../../../util/LinkManager'; import { RTFMarkup } from '../../../util/RTFMarkup'; -import { SelectionManager } from '../../../util/SelectionManager'; import { SnappingManager } from '../../../util/SnappingManager'; import { undoable, undoBatch, UndoManager } from '../../../util/UndoManager'; -import { CollectionFreeFormView } from '../../collections/collectionFreeForm/CollectionFreeFormView'; import { CollectionStackingView } from '../../collections/CollectionStackingView'; import { CollectionTreeView } from '../../collections/CollectionTreeView'; import { ContextMenu } from '../../ContextMenu'; @@ -53,9 +50,10 @@ import { AnchorMenu } from '../../pdf/AnchorMenu'; import { GPTPopup } from '../../pdf/GPTPopup/GPTPopup'; import { PinDocView, PinProps } from '../../PinFuncs'; import { SidebarAnnos } from '../../SidebarAnnos'; -import { styleFromLayoutString, StyleProp } from '../../StyleProvider'; +import { StyleProp } from '../../StyleProp'; +import { styleFromLayoutString } from '../../StyleProvider'; import { mediaState } from '../AudioBox'; -import { DocumentView, DocumentViewInternal } from '../DocumentView'; +import { DocumentView } from '../DocumentView'; import { FieldView, FieldViewProps } from '../FieldView'; import { FocusViewOptions } from '../FocusViewOptions'; import { LinkInfo } from '../LinkDocPreview'; @@ -260,7 +258,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB let stopFunc: any; const targetData = target[DocData]; targetData.mediaState = mediaState.Recording; - DocumentViewInternal.recordAudioAnnotation(targetData, Doc.LayoutFieldKey(target), stop => { stopFunc = stop }); // prettier-ignore + DictationManager.recordAudioAnnotation(targetData, Doc.LayoutFieldKey(target), stop => { stopFunc = stop }); // prettier-ignore const reactionDisposer = reaction( () => target.mediaState, @@ -271,7 +269,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB } } ); - target.title = ComputedField.MakeFunction(`self["text_audioAnnotations_text"].lastElement()`); + target.title = ComputedField.MakeFunction(`this.text_audioAnnotations_text.lastElement()`); } }); }; @@ -400,7 +398,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB insertTime = () => { let linkTime; let linkAnchor; - LinkManager.Links(this.dataDoc).forEach(l => { + Doc.Links(this.dataDoc).forEach(l => { const anchor = DocCast(l.link_anchor_1)?.annotationOn ? DocCast(l.link_anchor_1) : DocCast(l.link_anchor_2)?.annotationOn ? DocCast(l.link_anchor_2) : undefined; if (anchor && (anchor.annotationOn as Doc).mediaState === mediaState.Recording) { linkTime = NumCast(anchor._timecodeToShow /* audioStart */); @@ -423,7 +421,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB autoLink = () => { const newAutoLinks = new Set<Doc>(); - const oldAutoLinks = LinkManager.Links(this.Document).filter( + const oldAutoLinks = Doc.Links(this.Document).filter( link => ((!Doc.isTemplateForField(this.Document) && (!Doc.isTemplateForField(DocCast(link.link_anchor_1)) || !Doc.AreProtosEqual(DocCast(link.link_anchor_1), this.Document)) && @@ -442,7 +440,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB tr = tr.setSelection(new TextSelection(tr.doc.resolve(from), tr.doc.resolve(to))); this._editorView?.dispatch(tr); } - oldAutoLinks.filter(oldLink => !newAutoLinks.has(oldLink) && oldLink.link_anchor_2 !== this.Document).forEach(LinkManager.Instance.deleteLink); + oldAutoLinks.filter(oldLink => !newAutoLinks.has(oldLink) && oldLink.link_anchor_2 !== this.Document).forEach(doc => Doc.DeleteLink?.(doc)); }; updateTitle = () => { @@ -496,7 +494,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB if (node.firstChild === null && !node.marks.find((m: Mark) => m.type.name === schema.marks.noAutoLinkAnchor.name) && node.marks.find((m: Mark) => m.type.name === schema.marks.splitter.name)) { alink = alink ?? - (LinkManager.Links(this.Document).find( + (Doc.Links(this.Document).find( link => Doc.AreProtosEqual(Cast(link.link_anchor_1, Doc, null), this.Document) && // Doc.AreProtosEqual(Cast(link.link_anchor_2, Doc, null), target) @@ -787,7 +785,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB deleteAnnotation = (anchor: Doc) => { const batch = UndoManager.StartBatch('delete link'); - LinkManager.Instance.deleteLink(LinkManager.Links(anchor)[0]); + Doc.DeleteLink?.(Doc.Links(anchor)[0]); // const docAnnotations = DocListCast(this._props.dataDoc[this.fieldKey]); // this._props.dataDoc[this.fieldKey] = new List<Doc>(docAnnotations.filter(a => a !== this.annoTextRegion)); // AnchorMenu.Instance.fadeOut(true); @@ -837,7 +835,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB anchorDoc && DocServer.GetRefField(anchorDoc).then( action(anchor => { - anchor && SelectionManager.SelectSchemaViewDoc(anchor as Doc); + anchor && DocumentView.SelectSchemaDoc(anchor as Doc); AnchorMenu.Instance.Status = 'annotation'; AnchorMenu.Instance.Delete = !anchor && editor.state.selection.empty ? returnFalse : !anchor ? deleteMarkups : () => this.deleteAnnotation(anchor as Doc); AnchorMenu.Instance.Pinned = false; @@ -1124,7 +1122,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB setTimeout(() => this._sidebarRef?.current?.makeDocUnfiltered(doc)); } return new Promise<Opt<DocumentView>>(res => { - DocumentManager.Instance.AddViewRenderedCb(doc, dv => res(dv)); + DocumentView.addViewRenderedCb(doc, dv => res(dv)); }); }; focus = (textAnchor: Doc, options: FocusViewOptions) => { @@ -1206,7 +1204,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB } componentDidMount() { !this._props.dontSelectOnLoad && this._props.setContentViewBox?.(this); // this tells the DocumentView that this AudioBox is the "content" of the document. this allows the DocumentView to indirectly call getAnchor() on the AudioBox when making a link. - this._cachedLinks = LinkManager.Links(this.Document); + this._cachedLinks = Doc.Links(this.Document); this._disposers.breakupDictation = reaction(() => Doc.RecordingEvent, this.breakupDictation); this._disposers.layout_autoHeight = reaction( () => ({ autoHeight: this.layout_autoHeight, fontSize: this.fontSize, css: this.Document[DocCss] }), @@ -1244,7 +1242,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB { fireImmediately: !Array.from(FormattedTextBox._globalHighlights).includes('Bold Text') } ); this._disposers.links = reaction( - () => LinkManager.Links(this.dataDoc), // if a link is deleted, then remove all hyperlinks that reference it from the text's marks + () => Doc.Links(this.dataDoc), // if a link is deleted, then remove all hyperlinks that reference it from the text's marks newLinks => { this._cachedLinks.forEach(l => !newLinks.includes(l) && this.RemoveLinkFromDoc(l)); this._cachedLinks = newLinks; @@ -1556,7 +1554,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB // const timecode = NumCast(anchor.timecodeToShow, 0); const audiodoc = anchor.annotationOn as Doc; const func = () => { - const docView = DocumentManager.Instance.getDocumentView(audiodoc); + const docView = DocumentView.getDocumentView(audiodoc); if (!docView) { this._props.addDocTab(audiodoc, OpenWhere.addBottom); setTimeout(func); @@ -1769,7 +1767,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB case 'Escape': this._editorView!.dispatch(state.tr.setSelection(TextSelection.create(state.doc, state.selection.from, state.selection.from))); (document.activeElement as any).blur?.(); - SelectionManager.DeselectAll(); + DocumentView.DeselectAll(); RichTextMenu.Instance?.updateMenu(undefined, undefined, undefined, undefined); return; case 'Enter': @@ -1891,7 +1889,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB } @computed get sidebarCollection() { const renderComponent = (tag: string) => { - const ComponentTag: any = tag === CollectionViewType.Freeform ? CollectionFreeFormView : tag === CollectionViewType.Tree ? CollectionTreeView : tag === 'translation' ? FormattedTextBox : CollectionStackingView; + const ComponentTag: any = tag === CollectionViewType.Tree ? CollectionTreeView : tag === 'translation' ? FormattedTextBox : CollectionStackingView; return ComponentTag === CollectionStackingView ? ( <SidebarAnnos ref={this._sidebarRef} @@ -1913,7 +1911,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB setHeight={this.setSidebarHeight} /> ) : ( - <div onPointerDown={e => setupMoveUpEvents(this, e, returnFalse, emptyFunction, () => SelectionManager.SelectView(this.DocumentView?.()!, false), true)}> + <div onPointerDown={e => setupMoveUpEvents(this, e, returnFalse, emptyFunction, () => DocumentView.SelectView(this.DocumentView?.()!, false), true)}> <ComponentTag // eslint-disable-next-line react/jsx-props-no-spreading {...this._props} @@ -1998,11 +1996,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB @observable _isHovering = false; onPassiveWheel = (e: WheelEvent) => { if (e.clientX > this.ProseRef!.getBoundingClientRect().right) { - if (this.dataDoc[this.SidebarKey + '_type_collection'] === CollectionViewType.Freeform) { - // if the scrolled freeform is a child of the sidebar component, we need to let the event go through - // so react can let the freeform view handle it. We prevent default to stop any containing views from scrolling - e.preventDefault(); - } return; } @@ -2037,7 +2030,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB } render() { TraceMobx(); - const scale = this._props.NativeDimScaling?.() || 1; // * NumCast(this.layoutDoc._freeform_scale, 1); + const scale = this._props.NativeDimScaling?.() || 1; const rounded = StrCast(this.layoutDoc.layout_borderRounding) === '100%' ? '-rounded' : ''; setTimeout(() => !this._props.isContentActive() && FormattedTextBoxComment.textBox === this && FormattedTextBoxComment.Hide); const paddingX = NumCast(this.layoutDoc._xMargin, this._props.xPadding || 0); diff --git a/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts b/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts index bc6454146..7a8b72be0 100644 --- a/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts +++ b/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts @@ -11,7 +11,7 @@ import { AclAdmin, AclAugment, AclEdit, DocData } from '../../../../fields/DocSy import { GetEffectiveAcl } from '../../../../fields/util'; import { Docs } from '../../../documents/Documents'; import { RTFMarkup } from '../../../util/RTFMarkup'; -import { SelectionManager } from '../../../util/SelectionManager'; +import { DocumentView } from '../DocumentView'; import { OpenWhere } from '../OpenWhere'; const mac = typeof navigator !== 'undefined' ? /Mac/.test(navigator.platform) : false; @@ -172,7 +172,7 @@ export function buildKeymap<S extends Schema<any>>(schema: S, props: any): KeyMa bind('Escape', (state: EditorState, dispatch: (tx: Transaction) => void) => { dispatch(state.tr.setSelection(TextSelection.create(state.doc, state.selection.from, state.selection.from))); (document.activeElement as any).blur?.(); - SelectionManager.DeselectAll(); + DocumentView.DeselectAll(); }); bind('Alt-Enter', () => onKey() || true); diff --git a/src/client/views/nodes/formattedText/RichTextMenu.tsx b/src/client/views/nodes/formattedText/RichTextMenu.tsx index 6c12b9991..a612f3c65 100644 --- a/src/client/views/nodes/formattedText/RichTextMenu.tsx +++ b/src/client/views/nodes/formattedText/RichTextMenu.tsx @@ -11,11 +11,10 @@ import * as React from 'react'; import { Doc } from '../../../../fields/Doc'; import { BoolCast, Cast, StrCast } from '../../../../fields/Types'; import { DocServer } from '../../../DocServer'; -import { LinkManager } from '../../../util/LinkManager'; -import { SelectionManager } from '../../../util/SelectionManager'; import { undoBatch, UndoManager } from '../../../util/UndoManager'; import { AntimodeMenu, AntimodeMenuProps } from '../../AntimodeMenu'; import { ObservableReactComponent } from '../../ObservableReactComponent'; +import { DocumentView } from '../DocumentView'; import { EquationBox } from '../EquationBox'; import { FieldViewProps } from '../FieldView'; import { FormattedTextBox } from './FormattedTextBox'; @@ -116,7 +115,7 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> { _disposer: IReactionDisposer | undefined; componentDidMount() { this._disposer = reaction( - () => SelectionManager.Views.slice(), + () => DocumentView.Selected().slice(), () => this.updateMenu(undefined, undefined, undefined, undefined) ); } @@ -144,8 +143,8 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> { const { activeSizes } = active; const { activeColors } = active; const { activeHighlights } = active; - const refDoc = SelectionManager.Views.lastElement()?.layoutDoc ?? Doc.UserDoc(); - const refField = (pfx => (pfx ? pfx + '_' : ''))(SelectionManager.Views.lastElement()?.LayoutFieldKey); + const refDoc = DocumentView.Selected().lastElement()?.layoutDoc ?? Doc.UserDoc(); + const refField = (pfx => (pfx ? pfx + '_' : ''))(DocumentView.Selected().lastElement()?.LayoutFieldKey); const refVal = (field: string, dflt: string) => StrCast(refDoc[refField + field], StrCast(Doc.UserDoc()[field], dflt)); this._activeListType = this.getActiveListStyle(); @@ -237,8 +236,8 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> { m.type === state.schema.marks.pFontSize && activeSizes.add(m.attrs.fontSize); m.type === state.schema.marks.pFontHighlight && activeHighlights.add(String(m.attrs.fontHighlight)); }); - } else if (SelectionManager.Views.some(dv => dv.ComponentView instanceof EquationBox)) { - SelectionManager.Views.forEach(dv => StrCast(dv.Document._text_fontSize) && activeSizes.add(StrCast(dv.Document._text_fontSize))); + } else if (DocumentView.Selected().some(dv => dv.ComponentView instanceof EquationBox)) { + DocumentView.Selected().forEach(dv => StrCast(dv.Document._text_fontSize) && activeSizes.add(StrCast(dv.Document._text_fontSize))); } return { activeFamilies: Array.from(activeFamilies), activeSizes: Array.from(activeSizes), activeColors: Array.from(activeColors), activeHighlights: Array.from(activeHighlights) }; } @@ -566,7 +565,7 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> { if (linkDoc instanceof Doc) { const linkAnchor1 = await Cast(linkDoc.link_anchor_1, Doc); const linkAnchor2 = await Cast(linkDoc.link_anchor_2, Doc); - const currentDoc = SelectionManager.Docs.lastElement(); + const currentDoc = DocumentView.Selected().lastElement().Document; if (currentDoc && linkAnchor1 && linkAnchor2) { if (Doc.AreProtosEqual(currentDoc, linkAnchor1)) { return StrCast(linkAnchor2.title); @@ -605,7 +604,7 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> { .filter((aref: any) => aref?.href.indexOf(Doc.localServerPath()) === 0) .forEach((aref: any) => { const anchorId = aref.href.replace(Doc.localServerPath(), '').split('?')[0]; - anchorId && DocServer.GetRefField(anchorId).then(linkDoc => LinkManager.Instance.deleteLink(linkDoc as Doc)); + anchorId && DocServer.GetRefField(anchorId).then(linkDoc => Doc.DeleteLink?.(linkDoc as Doc)); }); } } diff --git a/src/client/views/nodes/formattedText/SummaryView.tsx b/src/client/views/nodes/formattedText/SummaryView.tsx index 2c366b49b..238267f6e 100644 --- a/src/client/views/nodes/formattedText/SummaryView.tsx +++ b/src/client/views/nodes/formattedText/SummaryView.tsx @@ -21,11 +21,10 @@ export class SummaryView { root: any; constructor(node: any, view: any, getPos: any) { - const self = this; this.dom = document.createElement('span'); this.dom.className = this.className(node.attrs.visibility); - this.dom.onpointerdown = function (e: any) { - self.onPointerDown(e, node, view, getPos); + this.dom.onpointerdown = (e: any) => { + this.onPointerDown(e, node, view, getPos); }; this.dom.onkeypress = function (e: any) { e.stopPropagation(); diff --git a/src/client/views/nodes/generativeFill/GenerativeFill.tsx b/src/client/views/nodes/generativeFill/GenerativeFill.tsx index d5fad296f..91b0ebd5c 100644 --- a/src/client/views/nodes/generativeFill/GenerativeFill.tsx +++ b/src/client/views/nodes/generativeFill/GenerativeFill.tsx @@ -16,7 +16,6 @@ import { NumCast } from '../../../../fields/Types'; import { Networking } from '../../../Network'; import { DocUtils } from '../../../documents/DocUtils'; import { Docs } from '../../../documents/Documents'; -import { DocumentManager } from '../../../util/DocumentManager'; import { CollectionDockingView } from '../../collections/CollectionDockingView'; import { CollectionFreeFormView } from '../../collections/collectionFreeForm'; import { ImageEditorData } from '../ImageBox'; @@ -28,6 +27,7 @@ import { APISuccess, ImageUtility } from './generativeFillUtils/ImageHandler'; import { PointerHandler } from './generativeFillUtils/PointerHandler'; import { activeColor, canvasSize, eraserColor, freeformRenderSize, newCollectionSize, offsetDistanceY, offsetX } from './generativeFillUtils/generativeFillConstants'; import { CursorData, ImageDimensions, Point } from './generativeFillUtils/generativeFillInterfaces'; +import { DocumentView } from '../DocumentView'; // enum BrushStyle { // ADD, @@ -295,7 +295,7 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD _height: newCollectionSize, title: 'Image edit collection', }); - DocUtils.MakeLink(imageRootDoc, newCollectionRef.current, { link_relationship: 'Image Edit Version History', link_displayLine: false }); + DocUtils.MakeLink(imageRootDoc, newCollectionRef.current, { link_relationship: 'Image Edit Version History' }); // opening new tab CollectionDockingView.AddSplit(newCollectionRef.current, OpenWhereMod.right); @@ -400,7 +400,7 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD parentDoc.current.gen_fill_children = new List<Doc>([newImg]); } - DocUtils.MakeLink(parentDoc.current, newImg, { link_relationship: `Image edit; Prompt: ${input}`, link_displayLine: true }); + DocUtils.MakeLink(parentDoc.current, newImg, { link_relationship: `Image edit; Prompt: ${input}` }); adjustImgPositions(); if (isNewCollection && newCollectionRef.current) { @@ -430,7 +430,7 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD ImageEditorData.Open = false; ImageEditorData.Source = ''; if (newCollectionRef.current) { - DocumentManager.Instance.AddViewRenderedCb(newCollectionRef.current, dv => (dv.ComponentView as CollectionFreeFormView)?.fitContentOnce()); + DocumentView.addViewRenderedCb(newCollectionRef.current, dv => (dv.ComponentView as CollectionFreeFormView)?.fitContentOnce()); } setEdits([]); }; diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx index 485ba7367..6b4f5e073 100644 --- a/src/client/views/nodes/trails/PresBox.tsx +++ b/src/client/views/nodes/trails/PresBox.tsx @@ -19,17 +19,14 @@ import { emptyFunction, emptyPath, stringHash } from '../../../../Utils'; import { DocServer } from '../../../DocServer'; import { Docs } from '../../../documents/Documents'; import { CollectionViewType, DocumentType } from '../../../documents/DocumentTypes'; -import { DocumentManager } from '../../../util/DocumentManager'; import { dropActionType } from '../../../util/DropActionTypes'; import { ScriptingGlobals } from '../../../util/ScriptingGlobals'; -import { SelectionManager } from '../../../util/SelectionManager'; import { SerializationHelper } from '../../../util/SerializationHelper'; -import { SettingsManager } from '../../../util/SettingsManager'; import { SnappingManager } from '../../../util/SnappingManager'; import { undoBatch, UndoManager } from '../../../util/UndoManager'; import { CollectionDockingView } from '../../collections/CollectionDockingView'; import { CollectionFreeFormView } from '../../collections/collectionFreeForm'; -import { CollectionStackedTimeline } from '../../collections/CollectionStackedTimeline'; +import { CollectionFreeFormPannableContents } from '../../collections/collectionFreeForm/CollectionFreeFormPannableContents'; import { CollectionView } from '../../collections/CollectionView'; import { TreeView } from '../../collections/TreeView'; import { ViewBoxBaseComponent } from '../../DocComponent'; @@ -55,8 +52,9 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { super(props); makeObservable(this); if (!PresBox.navigateToDocScript) { - PresBox.navigateToDocScript = ScriptField.MakeFunction('navigateToDoc(this.presentation_targetDoc, self)')!; + PresBox.navigateToDocScript = ScriptField.MakeFunction('navigateToDoc(this.presentation_targetDoc, this)')!; } + CollectionFreeFormPannableContents.SetOverlayPlugin((fform: Doc) => PresBox.Instance.pathLines(fform)); } private _disposers: { [name: string]: IReactionDisposer } = {}; @@ -122,8 +120,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { return false; } @computed get selectedDocumentView() { - if (SelectionManager.Views.length) return SelectionManager.Views[0]; - if (this.selectedArray.size) return DocumentManager.Instance.getDocumentView(this.Document); + if (DocumentView.Selected().length) return DocumentView.Selected()[0]; + if (this.selectedArray.size) return DocumentView.getDocumentView(this.Document); return undefined; } @computed get isPres() { @@ -175,7 +173,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { this._unmounting = false; this.turnOffEdit(true); this._disposers.selection = reaction( - () => SelectionManager.Views.slice(), + () => DocumentView.Selected().slice(), views => (!PresBox.Instance || views.some(view => view.Document === this.Document)) && this.updateCurrentPresentation(), { fireImmediately: true } ); @@ -200,7 +198,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { startTempMedia = (targetDoc: Doc, activeItem: Doc) => { const duration: number = NumCast(activeItem.config_clipEnd) - NumCast(activeItem.config_clipStart); if ([DocumentType.VID, DocumentType.AUDIO].includes(targetDoc.type as any)) { - const targMedia = DocumentManager.Instance.getDocumentView(targetDoc); + const targMedia = DocumentView.getDocumentView(targetDoc); targMedia?.ComponentView?.playFrom?.(NumCast(activeItem.config_clipStart), NumCast(activeItem.config_clipStart) + duration); } }; @@ -208,7 +206,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { stopTempMedia = (targetDocField: FieldResult) => { const targetDoc = DocCast(DocCast(targetDocField).annotationOn) ?? DocCast(targetDocField); if ([DocumentType.VID, DocumentType.AUDIO].includes(targetDoc.type as any)) { - const targMedia = DocumentManager.Instance.getDocumentView(targetDoc); + const targMedia = DocumentView.getDocumentView(targetDoc); targMedia?.ComponentView?.Pause?.(); } }; @@ -260,7 +258,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { // go to documents chain runSubroutines = (childrenToRun: Opt<Doc[]>, normallyNextSlide: Doc) => { if (childrenToRun && childrenToRun[0] !== normallyNextSlide) { - childrenToRun.forEach(child => DocumentManager.Instance.showDocument(child, {})); + childrenToRun.forEach(child => DocumentView.showDocument(child, {})); } }; @@ -280,7 +278,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { if (listItems && presIndexed < listItems.length) { if (!first) { const listItemDoc = listItems[presIndexed]; - const targetView = listItems && DocumentManager.Instance.getFirstDocumentView(listItemDoc); + const targetView = listItems && DocumentView.getFirstDocumentView(listItemDoc); Doc.linkFollowUnhighlight(); Doc.HighlightDoc(listItemDoc); listItemDoc.presentation_effect = this.activeItem.presBulletEffect; @@ -425,7 +423,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { const acontext = activeItem.config_activeFrame !== undefined ? DocCast(DocCast(activeItem.presentation_targetDoc).embedContainer) : DocCast(activeItem.presentation_targetDoc); const context = DocCast(acontext)?.annotationOn ? DocCast(DocCast(acontext).annotationOn) : acontext; if (context) { - const ffview = CollectionFreeFormView.from(DocumentManager.Instance.getFirstDocumentView(context)); + const ffview = CollectionFreeFormView.from(DocumentView.getFirstDocumentView(context)); if (ffview?.childDocs) { PresBox.Instance._keyTimer = CollectionFreeFormView.gotoKeyframe(PresBox.Instance._keyTimer, ffview.childDocs, frameTime); ffview.layoutDoc._currentFrame = NumCast(activeFrame); @@ -605,7 +603,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { const viewport = { panX: (contentBounds[0] + contentBounds[2]) / 2, panY: (contentBounds[1] + contentBounds[3]) / 2, width: contentBounds[2] - contentBounds[0], height: contentBounds[3] - contentBounds[1] }; bestTarget._freeform_panX = viewport.panX; bestTarget._freeform_panY = viewport.panY; - const dv = DocumentManager.Instance.getDocumentView(bestTarget); + const dv = DocumentView.getDocumentView(bestTarget); if (dv) { changed = true; const computedScale = NumCast(activeItem.config_zoom, 1) * Math.min(dv._props.PanelWidth() / viewport.width, dv._props.PanelHeight() / viewport.height); @@ -644,8 +642,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { const eleViewCache = Array.from(this._eleArray); const resetSelection = action(() => { if (!this._props.isSelected()) { - const presDocView = DocumentManager.Instance.getDocumentView(this.Document); - if (presDocView) SelectionManager.SelectView(presDocView, false); + const presDocView = DocumentView.getDocumentView(this.Document); + if (presDocView) DocumentView.SelectView(presDocView, false); this.clearSelectedArray(); selViewCache.forEach(doc => this.addToSelectedArray(doc)); this._dragArray.splice(0, this._dragArray.length, ...dragViewCache); @@ -660,7 +658,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { static NavigateToTarget(targetDoc: Doc, activeItem: Doc, finished?: () => void) { if (activeItem.presentation_movement === PresMovement.None && targetDoc.type === DocumentType.SCRIPTING) { - (DocumentManager.Instance.getFirstDocumentView(targetDoc)?.ComponentView as ScriptingBox)?.onRun?.(); + (DocumentView.getFirstDocumentView(targetDoc)?.ComponentView as ScriptingBox)?.onRun?.(); return; } const effect = activeItem.presentation_effect && activeItem.presentation_effect !== PresEffect.None ? activeItem.presentation_effect : undefined; @@ -680,19 +678,19 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { }; if (activeItem.presentation_openInLightbox) { const context = DocCast(targetDoc.annotationOn) ?? targetDoc; - if (!DocumentManager.Instance.getLightboxDocumentView(context)) { + if (!DocumentView.getLightboxDocumentView(context)) { LightboxView.Instance.SetLightboxDoc(context); } } if (targetDoc) { if (activeItem.presentation_targetDoc instanceof Doc) activeItem.presentation_targetDoc[Animation] = undefined; - DocumentManager.Instance.AddViewRenderedCb(LightboxView.LightboxDoc, () => { + DocumentView.addViewRenderedCb(LightboxView.LightboxDoc, () => { // if target or the doc it annotates is not in the lightbox, then close the lightbox - if (!DocumentManager.Instance.getLightboxDocumentView(DocCast(targetDoc.annotationOn) ?? targetDoc)) { + if (!DocumentView.getLightboxDocumentView(DocCast(targetDoc.annotationOn) ?? targetDoc)) { LightboxView.Instance.SetLightboxDoc(undefined); } - DocumentManager.Instance.showDocument(targetDoc, options, finished); + DocumentView.showDocument(targetDoc, options, finished); }); } else finished?.(); } @@ -1032,8 +1030,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { @action selectPres = () => { - const presDocView = DocumentManager.Instance.getDocumentView(this.Document); - presDocView && SelectionManager.SelectView(presDocView, false); + const presDocView = DocumentView.getDocumentView(this.Document); + presDocView && DocumentView.SelectView(presDocView, false); }; focusElement = (doc: Doc) => { @@ -1044,7 +1042,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { // Regular click @action selectElement = (doc: Doc, noNav = false) => { - CollectionStackedTimeline.CurrentlyPlaying?.map(clip => clip?.ComponentView?.Pause?.()); + DocumentView.CurrentlyPlaying?.map(clip => clip?.ComponentView?.Pause?.()); if (noNav) { const index = this.childDocs.indexOf(doc); if (index >= 0 && index < this.childDocs.length) { @@ -1200,7 +1198,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { const order: JSX.Element[] = []; const docs = new Set<Doc>(); const presCollection = collection; - const dv = DocumentManager.Instance.getDocumentView(presCollection); + const dv = DocumentView.getDocumentView(presCollection); this.childDocs.forEach((doc, index) => { const tagDoc = PresBox.targetRenderedDoc(doc); const srcContext = Cast(tagDoc.embedContainer, Doc, null); @@ -2206,7 +2204,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { if (doc) { const tabMap = CollectionDockingView.Instance?.tabMap; const docTab = tabMap && Array.from(tabMap).find(tab => tab.DashDoc.type === DocumentType.COL)?.DashDoc; - const presCollection = DocumentManager.GetContextPath(this.activeItem).reverse().lastElement().presentation_targetDoc ?? docTab; + const presCollection = DocumentView.getContextPath(this.activeItem).reverse().lastElement().presentation_targetDoc ?? docTab; const data = Cast(presCollection?.data, listSpec(Doc)); const configData = Cast(this.Document.data, listSpec(Doc)); if (data && configData) { @@ -2282,12 +2280,12 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { @action toggleProperties = () => { - SettingsManager.Instance.propertiesWidth = SettingsManager.Instance.propertiesWidth > 0 ? 0 : 250; + SnappingManager.SetPropertiesWidth(SnappingManager.PropertiesWidth > 0 ? 0 : 250); }; @computed get toolbar() { - const propIcon = SettingsManager.Instance.propertiesWidth > 0 ? 'angle-double-right' : 'angle-double-left'; - const propTitle = SettingsManager.Instance.propertiesWidth > 0 ? 'Close Presentation Panel' : 'Open Presentation Panel'; + const propIcon = SnappingManager.PropertiesWidth > 0 ? 'angle-double-right' : 'angle-double-left'; + const propTitle = SnappingManager.PropertiesWidth > 0 ? 'Close Presentation Panel' : 'Open Presentation Panel'; const mode = StrCast(this.Document._type_collection) as CollectionViewType; const isMini: boolean = this.toolbarWidth <= 100; const activeColor = SnappingManager.userVariantColor; @@ -2316,7 +2314,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { </Tooltip> <Tooltip title={<div className="dash-tooltip">{propTitle}</div>}> <div className="toolbar-button" style={{ position: 'absolute', right: 4, fontSize: 16 }} onClick={this.toggleProperties}> - <FontAwesomeIcon className="toolbar-thumbtack" icon={propIcon} style={{ color: SettingsManager.Instance.propertiesWidth > 0 ? activeColor : inactiveColor }} /> + <FontAwesomeIcon className="toolbar-thumbtack" icon={propIcon} style={{ color: SnappingManager.PropertiesWidth > 0 ? activeColor : inactiveColor }} /> </div> </Tooltip> </> diff --git a/src/client/views/nodes/trails/PresElementBox.tsx b/src/client/views/nodes/trails/PresElementBox.tsx index af0ab3b53..306b98190 100644 --- a/src/client/views/nodes/trails/PresElementBox.tsx +++ b/src/client/views/nodes/trails/PresElementBox.tsx @@ -13,9 +13,8 @@ import { BoolCast, Cast, DocCast, NumCast, StrCast } from '../../../../fields/Ty import { emptyFunction } from '../../../../Utils'; import { Docs } from '../../../documents/Documents'; import { CollectionViewType, DocumentType } from '../../../documents/DocumentTypes'; -import { DocumentManager } from '../../../util/DocumentManager'; import { DragManager } from '../../../util/DragManager'; -import { SettingsManager } from '../../../util/SettingsManager'; +import { SnappingManager } from '../../../util/SnappingManager'; import { Transform } from '../../../util/Transform'; import { undoable, undoBatch } from '../../../util/UndoManager'; import { TreeView } from '../../collections/TreeView'; @@ -23,7 +22,7 @@ import { ViewBoxBaseComponent } from '../../DocComponent'; import { EditableView } from '../../EditableView'; import { Colors } from '../../global/globalEnums'; import { PinDocView } from '../../PinFuncs'; -import { StyleProp } from '../../StyleProvider'; +import { StyleProp } from '../../StyleProp'; import { DocumentView } from '../DocumentView'; import { FieldView, FieldViewProps } from '../FieldView'; import { PresBox } from './PresBox'; @@ -282,8 +281,8 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() { @action toggleProperties = () => { - if (SettingsManager.Instance.propertiesWidth < 5) { - SettingsManager.Instance.propertiesWidth = 250; + if (SnappingManager.PropertiesWidth < 5) { + SnappingManager.SetPropertiesWidth(250); } }; @@ -417,7 +416,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() { @computed get toolbarWidth(): number { - const presBoxDocView = DocumentManager.Instance.getDocumentView(this.presBox); + const presBoxDocView = DocumentView.getDocumentView(this.presBox); const width = NumCast(this.presBox?._width); return presBoxDocView ? presBoxDocView._props.PanelWidth() : width || 300; } |
