diff options
author | bobzel <zzzman@gmail.com> | 2022-06-30 15:13:54 -0400 |
---|---|---|
committer | bobzel <zzzman@gmail.com> | 2022-06-30 15:13:54 -0400 |
commit | cf6de0bb501c2e3b64269494d6c0e0305c775eb3 (patch) | |
tree | e041e9fd5136ae4d359b6d476bc9ae172e109f6b /src/client/util/DocumentManager.ts | |
parent | bb02d3a052efdbf25d1069059a92b7a9d9cc1708 (diff) | |
parent | ea6e63648b21c46672b1b7cb1da0cbaa6857d0c1 (diff) |
Merge branch 'master' into parker
Diffstat (limited to 'src/client/util/DocumentManager.ts')
-rw-r--r-- | src/client/util/DocumentManager.ts | 123 |
1 files changed, 82 insertions, 41 deletions
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index 0a00ab6e0..0435cd535 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -5,17 +5,19 @@ import { Cast } from '../../fields/Types'; import { returnFalse } from '../../Utils'; import { DocumentType } from '../documents/DocumentTypes'; import { CollectionDockingView } from '../views/collections/CollectionDockingView'; +import { CollectionFreeFormView } from '../views/collections/collectionFreeForm'; import { CollectionView } from '../views/collections/CollectionView'; import { LightboxView } from '../views/LightboxView'; import { DocumentView, ViewAdjustment } from '../views/nodes/DocumentView'; import { LinkAnchorBox } from '../views/nodes/LinkAnchorBox'; +import { CurrentUserUtils } from './CurrentUserUtils'; import { ScriptingGlobals } from './ScriptingGlobals'; import { SelectionManager } from './SelectionManager'; export class DocumentManager { //global holds all of the nodes (regardless of which collection they're in) - @observable public DocumentViews: DocumentView[] = []; + @observable public DocumentViews = new Set<DocumentView>(); @observable public LinkAnchorBoxViews: DocumentView[] = []; @observable public RecordingEvent = 0; @observable public LinkedDocumentViews: { a: DocumentView, b: DocumentView, l: Doc }[] = []; @@ -45,7 +47,7 @@ export class DocumentManager { // this.LinkedDocumentViews.forEach(view => console.log(" LV = " + view.a.props.Document.title + "/" + view.a.props.LayoutTemplateString + " --> " + // view.b.props.Document.title + "/" + view.b.props.LayoutTemplateString)); } else { - this.DocumentViews.push(view); + this.DocumentViews.add(view); } } public RemoveView = action((view: DocumentView) => { @@ -60,8 +62,7 @@ export class DocumentManager { const index = this.LinkAnchorBoxViews.indexOf(view); this.LinkAnchorBoxViews.splice(index, 1); } else { - const index = this.DocumentViews.indexOf(view); - index !== -1 && this.DocumentViews.splice(index, 1); + this.DocumentViews.delete(view); } SelectionManager.DeselectView(view); }); @@ -69,13 +70,13 @@ export class DocumentManager { //gets all views public getDocumentViewsById(id: string) { const toReturn: DocumentView[] = []; - DocumentManager.Instance.DocumentViews.map(view => { + Array.from(DocumentManager.Instance.DocumentViews).map(view => { if (view.rootDoc[Id] === id) { toReturn.push(view); } }); if (toReturn.length === 0) { - DocumentManager.Instance.DocumentViews.map(view => { + Array.from(DocumentManager.Instance.DocumentViews).map(view => { const doc = view.rootDoc.proto; if (doc && doc[Id] && doc[Id] === id) { toReturn.push(view); @@ -95,14 +96,14 @@ export class DocumentManager { const passes = preferredCollection ? [preferredCollection, undefined] : [undefined]; for (const pass of passes) { - DocumentManager.Instance.DocumentViews.map(view => { + Array.from(DocumentManager.Instance.DocumentViews).map(view => { if (view.rootDoc[Id] === id && (!pass || view.props.ContainingCollectionView === preferredCollection)) { toReturn = view; return; } }); if (!toReturn) { - DocumentManager.Instance.DocumentViews.map(view => { + Array.from(DocumentManager.Instance.DocumentViews).map(view => { const doc = view.rootDoc.proto; if (doc && doc[Id] === id && (!pass || view.props.ContainingCollectionView === preferredCollection)) { toReturn = view; @@ -121,9 +122,8 @@ export class DocumentManager { } 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) && Doc.AreProtosEqual(view.rootDoc, toFind) && views.push(view)); + Array.from(DocumentManager.Instance.DocumentViews).map(view => LightboxView.IsLightboxDocView(view.docViewPath) && Doc.AreProtosEqual(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 => { @@ -132,8 +132,8 @@ export class DocumentManager { } public getDocumentViews(toFind: Doc): DocumentView[] { const toReturn: DocumentView[] = []; - const docViews = DocumentManager.Instance.DocumentViews.filter(view => !LightboxView.IsLightboxDocView(view.docViewPath)); - const lightViews = DocumentManager.Instance.DocumentViews.filter(view => LightboxView.IsLightboxDocView(view.docViewPath)); + const docViews = Array.from(DocumentManager.Instance.DocumentViews).filter(view => !LightboxView.IsLightboxDocView(view.docViewPath)); + const lightViews = Array.from(DocumentManager.Instance.DocumentViews).filter(view => LightboxView.IsLightboxDocView(view.docViewPath)); // heuristic to return the "best" documents first: // choose a document in the lightbox first @@ -155,7 +155,7 @@ export class DocumentManager { targetDoc: Doc, // document to display willZoom: boolean, // whether to zoom doc to take up most of screen createViewFunc = DocumentManager.addView, // how to create a view of the doc if it doesn't exist - docContext?: Doc, // context to load that should contain the target + docContext: Doc[], // context to load that should contain the target linkDoc?: Doc, // link that's being followed closeContextIfNotFound: boolean = false, // after opening a context where the document should be, this determines whether the context should be closed if the Doc isn't actually there originatingDoc: Opt<Doc> = undefined, // doc that initiated the display of the target odoc @@ -167,49 +167,78 @@ export class DocumentManager { originalTarget = originalTarget ?? targetDoc; const getFirstDocView = LightboxView.LightboxDoc ? DocumentManager.Instance.getLightboxDocumentView : DocumentManager.Instance.getFirstDocumentView; const docView = getFirstDocView(targetDoc, originatingDoc); - const wasHidden = targetDoc.hidden; // - if (wasHidden) runInAction(() => targetDoc.hidden = false); // if the target is hidden, un-hide it here. + const annotatedDoc = Cast(targetDoc.annotationOn, Doc, null); + const resolvedTarget = targetDoc.type === DocumentType.MARKER ? annotatedDoc ?? targetDoc : targetDoc; // if target is a marker, then focus toggling should apply to the document it's on since the marker itself doesn't have a hidden field + var wasHidden = resolvedTarget.hidden; + if (wasHidden) { + runInAction(() => { + resolvedTarget.hidden = false; // if the target is hidden, un-hide it here. + docView?.props.bringToFront(resolvedTarget); + }); + } const focusAndFinish = (didFocus: boolean) => { + const finalTargetDoc = resolvedTarget; if (originatingDoc?.isPushpin) { if (!didFocus && !wasHidden) { // don't toggle the hidden state if the doc was already un-hidden as part of this document traversal - targetDoc.hidden = !targetDoc.hidden; + finalTargetDoc.hidden = !finalTargetDoc.hidden; } } else { - targetDoc.hidden && (targetDoc.hidden = undefined); + finalTargetDoc.hidden && (finalTargetDoc.hidden = undefined); !noSelect && docView?.select(false); } finished?.(); - return false; }; - const annotatedDoc = Cast(targetDoc.annotationOn, Doc, null); - const annoContainerView = annotatedDoc && getFirstDocView(annotatedDoc); - const contextDocs = docContext ? await DocListCastAsync(docContext.data) : undefined; - const contextDoc = contextDocs?.find(doc => Doc.AreProtosEqual(doc, targetDoc) || Doc.AreProtosEqual(doc, annotatedDoc)) ? docContext : undefined; + const annoContainerView = (!wasHidden || resolvedTarget !== annotatedDoc) && annotatedDoc && getFirstDocView(annotatedDoc); + const contextDocs = docContext.length ? await DocListCastAsync(docContext[0].data) : undefined; + const contextDoc = contextDocs?.find(doc => Doc.AreProtosEqual(doc, targetDoc) || Doc.AreProtosEqual(doc, annotatedDoc)) ? docContext.lastElement() : undefined; const targetDocContext = contextDoc || annotatedDoc; const targetDocContextView = (targetDocContext && getFirstDocView(targetDocContext)) || (wasHidden && annoContainerView);// if we have an annotation container and the target was hidden, then try again because we just un-hid the document above const focusView = !docView && targetDoc.type === DocumentType.MARKER && annoContainerView ? annoContainerView : docView; - if (!docView && annoContainerView) { - annoContainerView.focus(targetDoc); // this allows something like a PDF view to remove its doc filters to expose the target so that it can be found in the retry code below + if (annoContainerView) { + if (annoContainerView.props.Document.layoutKey === "layout_icon") { + annoContainerView.iconify(() => annoContainerView.focus(targetDoc, { + originalTarget, willZoom, scale: presZoom, afterFocus: (didFocus: boolean) => + new Promise<ViewAdjustment>(res => { + focusAndFinish(true); + res(ViewAdjustment.doNothing); + }) + })); + return; + } else if (!docView && targetDoc.type !== DocumentType.MARKER) { + annoContainerView.focus(targetDoc); // this allows something like a PDF view to remove its doc filters to expose the target so that it can be found in the retry code below + } } if (focusView) { !noSelect && Doc.linkFollowHighlight(focusView.rootDoc); //TODO:glr make this a setting in PresBox - focusView.focus(targetDoc, { + const doFocus = (forceDidFocus: boolean) => focusView.focus(originalTarget ?? targetDoc, { originalTarget, willZoom, scale: presZoom, afterFocus: (didFocus: boolean) => new Promise<ViewAdjustment>(res => { - focusAndFinish(didFocus); + focusAndFinish(forceDidFocus || didFocus); res(ViewAdjustment.doNothing); }) }); + if (focusView.props.Document.layoutKey === "layout_icon") { + focusView.iconify(() => doFocus(true)); + } else { + doFocus(false); + } } else { 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))); } else { // otherwise try to get a view of the context of the target if (targetDocContextView) { // we found a context view and aren't forced to create a new one ... focus on the context first.. + wasHidden = wasHidden || targetDocContextView.rootDoc.hidden; + targetDocContextView.rootDoc.hidden = false; // make sure context isn't hidden targetDocContext._viewTransition = "transform 500ms"; targetDocContextView.props.focus(targetDocContextView.rootDoc, { willZoom, afterFocus: async () => { targetDocContext._viewTransition = undefined; + if (targetDocContext.layoutKey === "layout_icon") { + targetDocContextView.iconify(() => this.jumpToDocument( + resolvedTarget ?? targetDoc, willZoom, createViewFunc, docContext, linkDoc, closeContextIfNotFound, originatingDoc, + finished, originalTarget, noSelect, presZoom)); + } return ViewAdjustment.doNothing; } }); @@ -220,29 +249,38 @@ export class DocumentManager { finished?.(); } else { // no timecode means we need to find the context view and focus on our target 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 + const retryDocView = getFirstDocView(resolvedTarget); // 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. Doc.linkFollowHighlight(retryDocView.rootDoc); - retryDocView.props.focus(targetDoc, { + retryDocView.focus(targetDoc, { willZoom, afterFocus: (didFocus: boolean) => new Promise<ViewAdjustment>(res => { !noSelect && focusAndFinish(didFocus); res(ViewAdjustment.doNothing); }) }); // focus on the target in the context - } else if (delay > 1500) { + } else if (delay > 1000) { // 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.rootDoc); if (targetDoc.layout) { // there will no layout for a TEXTANCHOR type document createViewFunc(Doc.BrushDoc(targetDoc), finished); // create a new view of the target } } else { - setTimeout(() => findView(delay + 250), 250); + setTimeout(() => findView(delay + 200), 200); } }; - findView(0); + setTimeout(() => findView(0), 0); + } + } else { + if (docContext.length && docContext[0]?.layoutKey === "layout_icon") { + const docContextView = this.getFirstDocumentView(docContext[0]); + if (docContextView) { + return docContextView.iconify(() => this.jumpToDocument( + targetDoc, willZoom, createViewFunc, docContext.slice(1, docContext.length), linkDoc, closeContextIfNotFound, originatingDoc, + finished, originalTarget, noSelect, presZoom)); + } } - } else { // there's no context view so we need to create one first and try again when that finishes + // there's no context view so we need to create one first and try again when that finishes const finishFunc = () => this.jumpToDocument(targetDoc, true, createViewFunc, docContext, linkDoc, true /* if we don't find the target, we want to get rid of the context just created */, undefined, finished, originalTarget); createViewFunc(targetDocContext, // after creating the context, this calls the finish function that will retry looking for the target finishFunc); @@ -250,18 +288,21 @@ export class DocumentManager { } } } - } -ScriptingGlobals.add(function DocFocusOrOpen(doc: any) { - const dv = DocumentManager.Instance.getDocumentView(doc); - if (dv && dv.props.Document === doc) { - dv.props.focus(doc, { willZoom: true }); +export function DocFocusOrOpen(doc: Doc, collectionDoc?: Doc) { + const cv = collectionDoc && DocumentManager.Instance.getDocumentView(collectionDoc); + const dv = DocumentManager.Instance.getDocumentView(doc, (cv?.ComponentView as CollectionFreeFormView)?.props.CollectionView); + if (dv && Doc.AreProtosEqual(dv.props.Document, doc)) { + dv.props.focus(dv.props.Document, { willZoom: true }); Doc.linkFollowHighlight(dv?.props.Document, false); } else { - const context = doc.context !== Doc.UserDoc().myFilesystem && Cast(doc.context, Doc, null); + const context = doc.context !== CurrentUserUtils.MyFilesystem && Cast(doc.context, Doc, null); const showDoc = context || doc; - CollectionDockingView.AddSplit(showDoc === Doc.GetProto(showDoc) ? Doc.MakeAlias(showDoc) : showDoc, "right") && context && + const bestAlias = showDoc === Doc.GetProto(showDoc) ? DocListCast(showDoc.aliases).find(doc => !doc.context && doc.author === Doc.CurrentUserEmail) : showDoc; + + CollectionDockingView.AddSplit(bestAlias ? bestAlias : Doc.MakeAlias(showDoc), "right") && context && setTimeout(() => DocumentManager.Instance.getDocumentView(Doc.GetProto(doc))?.focus(doc)); } -});
\ No newline at end of file +} +ScriptingGlobals.add(DocFocusOrOpen);
\ No newline at end of file |