diff options
author | usodhi <61431818+usodhi@users.noreply.github.com> | 2021-02-11 16:43:46 -0500 |
---|---|---|
committer | usodhi <61431818+usodhi@users.noreply.github.com> | 2021-02-11 16:43:46 -0500 |
commit | 546540013de0a7cb647f30f1fcb513ce52048b72 (patch) | |
tree | 12b78ea0e29fba23b8557864540984daf9680942 /src/client/util/DocumentManager.ts | |
parent | 77b7c3927c454a829d7dbb2748ad322b146265a7 (diff) | |
parent | 890337b525ea460f9986562c047135bc5ca203a6 (diff) |
merging
Diffstat (limited to 'src/client/util/DocumentManager.ts')
-rw-r--r-- | src/client/util/DocumentManager.ts | 157 |
1 files changed, 83 insertions, 74 deletions
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index 41c7a1409..816f7f6be 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -1,13 +1,13 @@ -import { action, observable } from 'mobx'; +import { action, observable, runInAction } from 'mobx'; import { Doc, DocListCast, DocListCastAsync, Opt } from '../../fields/Doc'; import { Id } from '../../fields/FieldSymbols'; -import { Cast, NumCast } from '../../fields/Types'; +import { Cast, NumCast, StrCast } from '../../fields/Types'; import { returnFalse } from '../../Utils'; import { DocumentType } from '../documents/DocumentTypes'; import { CollectionDockingView } from '../views/collections/CollectionDockingView'; import { CollectionView } from '../views/collections/CollectionView'; +import { LightboxView } from '../views/LightboxView'; import { DocumentView } from '../views/nodes/DocumentView'; -import { LinkManager } from './LinkManager'; import { Scripting } from './Scripting'; export type CreateViewFunc = (doc: Doc, followLinkLocation: string, finished?: () => void) => void; @@ -15,32 +15,28 @@ export type CreateViewFunc = (doc: Doc, followLinkLocation: string, finished?: ( export class DocumentManager { //global holds all of the nodes (regardless of which collection they're in) - @observable - public DocumentViews: DocumentView[] = []; - @observable LinkedDocumentViews: { a: DocumentView, b: DocumentView, l: Doc }[] = []; + @observable public DocumentViews: DocumentView[] = []; + @observable public LinkedDocumentViews: { a: DocumentView, b: DocumentView, l: Doc }[] = []; - // singleton instance private static _instance: DocumentManager; - - // create one and only one instance of NodeManager - public static get Instance(): DocumentManager { - return this._instance || (this._instance = new this()); - } + public static get Instance(): DocumentManager { return this._instance || (this._instance = new this()); } //private constructor so no other class can create a nodemanager - private constructor() { - } + private constructor() { } @action public AddView = (view: DocumentView) => { - const linksList = DocListCast(view.props.Document.links); - linksList.forEach(link => { - const linkToDoc = link && LinkManager.getOppositeAnchor(link, view.props.Document); - linkToDoc && DocumentManager.Instance.DocumentViews.filter(dv => Doc.AreProtosEqual(dv.props.Document, linkToDoc)).forEach(dv => { - if (dv.props.Document.type !== DocumentType.LINK || dv.props.LayoutTemplateString !== view.props.LayoutTemplateString) { - this.LinkedDocumentViews.push({ a: dv, b: view, l: link }); - } - }); + DocListCast(view.rootDoc.links).forEach(link => { + const whichOtherAnchor = view.props.LayoutTemplateString?.includes("anchor2") ? "anchor1" : "anchor2"; + const otherDoc = link && (link[whichOtherAnchor] as Doc); + const otherDocAnno = otherDoc?.type === DocumentType.TEXTANCHOR ? otherDoc.annotationOn as Doc : undefined; + otherDoc && DocumentManager.Instance.DocumentViews. + filter(dv => Doc.AreProtosEqual(dv.rootDoc, otherDoc) || Doc.AreProtosEqual(dv.rootDoc, otherDocAnno)). + forEach(otherView => { + if (otherView.rootDoc.type !== DocumentType.LINK || otherView.props.LayoutTemplateString !== view.props.LayoutTemplateString) { + this.LinkedDocumentViews.push({ a: whichOtherAnchor === "anchor1" ? otherView : view, b: whichOtherAnchor === "anchor1" ? view : otherView, l: link }); + } + }); }); this.DocumentViews.push(view); } @@ -55,13 +51,13 @@ export class DocumentManager { public getDocumentViewsById(id: string) { const toReturn: DocumentView[] = []; DocumentManager.Instance.DocumentViews.map(view => { - if (view.props.Document[Id] === id) { + if (view.rootDoc[Id] === id) { toReturn.push(view); } }); if (toReturn.length === 0) { DocumentManager.Instance.DocumentViews.map(view => { - const doc = view.props.Document.proto; + const doc = view.rootDoc.proto; if (doc && doc[Id] && doc[Id] === id) { toReturn.push(view); } @@ -81,14 +77,14 @@ export class DocumentManager { for (const pass of passes) { DocumentManager.Instance.DocumentViews.map(view => { - if (view.props.Document[Id] === id && (!pass || view.props.ContainingCollectionView === preferredCollection)) { + if (view.rootDoc[Id] === id && (!pass || view.props.ContainingCollectionView === preferredCollection)) { toReturn = view; return; } }); if (!toReturn) { DocumentManager.Instance.DocumentViews.map(view => { - const doc = view.props.Document.proto; + const doc = view.rootDoc.proto; if (doc && doc[Id] === id && (!pass || view.props.ContainingCollectionView === preferredCollection)) { toReturn = view; } @@ -105,21 +101,28 @@ export class DocumentManager { return this.getDocumentViewById(toFind[Id], preferredCollection); } + public getLightboxDocumentView = (toFind: Doc, originatingDoc: Opt<Doc> = undefined): DocumentView | undefined => { + const docViews = DocumentManager.Instance.DocumentViews; + const views: DocumentView[] = []; + docViews.map(view => LightboxView.IsLightboxDocView(view.docViewPath) && view.rootDoc === toFind && views.push(view)); + return views?.find(view => view.ContentDiv?.getBoundingClientRect().width && view.props.focus !== returnFalse) || views?.find(view => view.props.focus !== returnFalse) || (views.length ? views[0] : undefined); + } public getFirstDocumentView = (toFind: Doc, originatingDoc: Opt<Doc> = undefined): DocumentView | undefined => { - const views = this.getDocumentViews(toFind).filter(view => view.props.Document !== originatingDoc); + const views = this.getDocumentViews(toFind).filter(view => view.rootDoc !== originatingDoc); return views?.find(view => view.ContentDiv?.getBoundingClientRect().width && view.props.focus !== returnFalse) || views?.find(view => view.props.focus !== returnFalse) || (views.length ? views[0] : undefined); } public getDocumentViews(toFind: Doc): DocumentView[] { const toReturn: DocumentView[] = []; - const docViews = DocumentManager.Instance.DocumentViews; + const docViews = DocumentManager.Instance.DocumentViews.filter(view => !LightboxView.IsLightboxDocView(view.docViewPath)); + const lightViews = DocumentManager.Instance.DocumentViews.filter(view => LightboxView.IsLightboxDocView(view.docViewPath)); // heuristic to return the "best" documents first: + // choose a document in the lightbox first // choose an exact match over an alias match - // choose documents that have a PanelWidth() over those that don't (the treeview documents have no panelWidth) - docViews.map(view => view.props.PanelWidth() > 1 && view.props.Document === toFind && toReturn.push(view)); - docViews.map(view => view.props.PanelWidth() <= 1 && view.props.Document === toFind && toReturn.push(view)); - docViews.map(view => view.props.PanelWidth() > 1 && view.props.Document !== toFind && Doc.AreProtosEqual(view.props.Document, toFind) && toReturn.push(view)); - docViews.map(view => view.props.PanelWidth() <= 1 && view.props.Document !== toFind && Doc.AreProtosEqual(view.props.Document, toFind) && toReturn.push(view)); + lightViews.map(view => view.rootDoc === toFind && toReturn.push(view)); + lightViews.map(view => view.rootDoc !== toFind && Doc.AreProtosEqual(view.rootDoc, toFind) && toReturn.push(view)); + docViews.map(view => view.rootDoc === toFind && toReturn.push(view)); + docViews.map(view => view.rootDoc !== toFind && Doc.AreProtosEqual(view.rootDoc, toFind) && toReturn.push(view)); return toReturn; } @@ -139,56 +142,51 @@ export class DocumentManager { originatingDoc: Opt<Doc> = undefined, // doc that initiated the display of the target odoc finished?: () => void, ): Promise<void> => { - const getFirstDocView = DocumentManager.Instance.getFirstDocumentView; - const focusAndFinish = () => { finished?.(); return false; }; + const getFirstDocView = LightboxView.LightboxDoc ? DocumentManager.Instance.getLightboxDocumentView : DocumentManager.Instance.getFirstDocumentView; + const docView = getFirstDocView(targetDoc, originatingDoc); const highlight = () => { const finalDocView = getFirstDocView(targetDoc); - if (finalDocView) { - finalDocView.layoutDoc.scrollToLinkID = linkDoc?.[Id]; - Doc.linkFollowHighlight(finalDocView.props.Document); + finalDocView && Doc.linkFollowHighlight(finalDocView.rootDoc); + }; + const focusAndFinish = (didFocus: boolean) => { + if (originatingDoc?.isPushpin) { + if (!didFocus || targetDoc.hidden) { + targetDoc.hidden = !targetDoc.hidden; + } + } else { + targetDoc.hidden && (targetDoc.hidden = undefined); + docView?.select(false); } + highlight(); + finished?.(); + return false; }; - const docView = getFirstDocView(targetDoc, originatingDoc); - let annotatedDoc = await Cast(targetDoc.annotationOn, Doc); - if (annotatedDoc && annotatedDoc !== originatingDoc?.context && !targetDoc?.isPushpin) { + let annotatedDoc = Cast(targetDoc.annotationOn, Doc, null); + const contextDocs = docContext ? await DocListCastAsync(docContext.data) : undefined; + const contextDoc = contextDocs?.find(doc => Doc.AreProtosEqual(doc, targetDoc) || Doc.AreProtosEqual(doc, annotatedDoc)) ? docContext : undefined; + const targetDocContext = contextDoc || annotatedDoc; + const targetDocContextView = targetDocContext && getFirstDocView(targetDocContext); + if (!docView && annotatedDoc && annotatedDoc !== originatingDoc?.context && targetDoc.type === DocumentType.TEXTANCHOR) { const first = getFirstDocView(annotatedDoc); if (first) { - annotatedDoc = first.props.Document; - first.props.focus(annotatedDoc, false); + annotatedDoc = first.rootDoc; + first.focus(targetDoc, false); } - } - if (docView) { // we have a docView already and aren't forced to create a new one ... just focus on the document. TODO move into view if necessary otherwise just highlight? - const sameContext = annotatedDoc && annotatedDoc === originatingDoc?.context; - if (originatingDoc?.isPushpin) { - docView.props.focus(docView.props.Document, willZoom, undefined, (didFocus: boolean) => { - if (!didFocus || docView.props.Document.hidden) { - docView.props.Document.hidden = !docView.props.Document.hidden; - } - return focusAndFinish(); - }, sameContext, false);// don't want to focus the container if the source and target are in the same container, so pass 'sameContext' for dontCenter parameter - //finished?.(); - } - else { - docView.select(false); - docView.props.Document.hidden && (docView.props.Document.hidden = undefined); - // @ts-ignore - docView.props.focus(docView.props.Document, willZoom, undefined, focusAndFinish, sameContext, false); - } - highlight(); + } else if (docView && (targetDocContextView || !targetDocContext)) { // we have a docView already and aren't forced to create a new one ... just focus on the document. TODO move into view if necessary otherwise just highlight? + docView.props.focus(docView.rootDoc, willZoom, undefined, (didFocus: boolean) => + new Promise<boolean>(res => { + focusAndFinish(didFocus); + res(); + }) + ); } else { - const contextDocs = docContext ? await DocListCastAsync(docContext.data) : undefined; - const contextDoc = contextDocs?.find(doc => Doc.AreProtosEqual(doc, targetDoc)) ? docContext : undefined; - const targetDocContext = annotatedDoc || contextDoc; - if (!targetDocContext) { // we don't have a view and there's no context specified ... create a new view of the target using the dockFunc or default createViewFunc(Doc.BrushDoc(targetDoc), finished); // bcz: should we use this?: Doc.MakeAlias(targetDoc))); highlight(); } else { // otherwise try to get a view of the context of the target - const targetDocContextView = getFirstDocView(targetDocContext); - targetDocContext._scrollY = targetDocContext._scrollPreviewY = NumCast(targetDocContext._scrollTop, 0); // this will force PDFs to activate and load their annotations / allow scrolling if (targetDocContextView) { // we found a context view and aren't forced to create a new one ... focus on the context first.. targetDocContext._viewTransition = "transform 500ms"; - targetDocContextView.props.focus(targetDocContextView.props.Document, willZoom); + targetDocContextView.props.focus(targetDocContextView.rootDoc, willZoom); // now find the target document within the context if (targetDoc._timecodeToShow) { // if the target has a timecode, it should show up once the (presumed) video context scrubs to the display timecode; @@ -198,12 +196,17 @@ export class DocumentManager { const findView = (delay: number) => { const retryDocView = getFirstDocView(targetDoc); // test again for the target view snce we presumably created the context above by focusing on it if (retryDocView) { // we found the target in the context - retryDocView.props.focus(targetDoc, willZoom, undefined, focusAndFinish); // focus on the target in the context + retryDocView.props.focus(targetDoc, willZoom, undefined, (didFocus: boolean) => + new Promise<boolean>(res => { + focusAndFinish(didFocus); + res(); + }) + ); // focus on the target in the context highlight(); } else if (delay > 1500) { // we didn't find the target, so it must have moved out of the context. Go back to just creating it. - if (closeContextIfNotFound) targetDocContextView.props.removeDocument?.(targetDocContextView.props.Document); - if (targetDoc.layout) { + if (closeContextIfNotFound) targetDocContextView.props.removeDocument?.(targetDocContextView.rootDoc); + if (targetDoc.layout) { // there will no layout for a TEXTANCHOR type document Doc.SetInPlace(targetDoc, "annotationOn", undefined, false); createViewFunc(Doc.BrushDoc(targetDoc), finished); // create a new view of the target } @@ -214,8 +217,14 @@ export class DocumentManager { findView(0); } } else { // there's no context view so we need to create one first and try again when that finishes - createViewFunc(targetDocContext, // after creating the context, this calls the finish function that will retry looking for the target - () => this.jumpToDocument(targetDoc, willZoom, createViewFunc, docContext, linkDoc, true /* if we don't find the target, we want to get rid of the context just created */, undefined, finished)); + const finishFunc = () => this.jumpToDocument(targetDoc, willZoom, createViewFunc, docContext, linkDoc, true /* if we don't find the target, we want to get rid of the context just created */, undefined, finished); + if (LightboxView.LightboxDoc) { + runInAction(() => LightboxView.LightboxDoc = targetDocContext); + setTimeout(() => finishFunc, 250); + } else { + createViewFunc(targetDocContext, // after creating the context, this calls the finish function that will retry looking for the target + finishFunc); + } } } } |