aboutsummaryrefslogtreecommitdiff
path: root/src/client/util/DocumentManager.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/util/DocumentManager.ts')
-rw-r--r--src/client/util/DocumentManager.ts145
1 files changed, 79 insertions, 66 deletions
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index 1b63b615b..d2368f4f6 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -1,19 +1,19 @@
import { action, observable, runInAction } from 'mobx';
-import { Doc, DocListCast, DocListCastAsync, Opt } from '../../fields/Doc';
+import { Doc, Opt } from '../../fields/Doc';
import { Id } from '../../fields/FieldSymbols';
-import { Cast, DocCast } from '../../fields/Types';
+import { listSpec } from '../../fields/Schema';
+import { Cast } from '../../fields/Types';
+import { AudioField } from '../../fields/URLField';
import { returnFalse } from '../../Utils';
import { DocumentType } from '../documents/DocumentTypes';
-import { LightboxView } from '../views/LightboxView';
-import { DocFocusOptions, DocumentView, OpenWhereMod, ViewAdjustment } from '../views/nodes/DocumentView';
-import { LinkAnchorBox } from '../views/nodes/LinkAnchorBox';
import { CollectionDockingView } from '../views/collections/CollectionDockingView';
import { CollectionFreeFormView } from '../views/collections/collectionFreeForm';
import { CollectionView } from '../views/collections/CollectionView';
+import { LightboxView } from '../views/LightboxView';
+import { DocFocusOptions, DocumentView, OpenWhereMod, ViewAdjustment } from '../views/nodes/DocumentView';
+import { LinkAnchorBox } from '../views/nodes/LinkAnchorBox';
import { ScriptingGlobals } from './ScriptingGlobals';
import { SelectionManager } from './SelectionManager';
-import { listSpec } from '../../fields/Schema';
-import { AudioField } from '../../fields/URLField';
const { Howl } = require('howler');
export class DocumentManager {
@@ -31,6 +31,30 @@ export class DocumentManager {
//private constructor so no other class can create a nodemanager
private constructor() {}
+ private _viewRenderedCbs: { doc: Doc; func: (dv: DocumentView) => any }[] = [];
+ public AddViewRenderedCb = (doc: Doc, func: (dv: DocumentView) => any) => {
+ const dv = this.getDocumentViewById(doc[Id]);
+ this._viewRenderedCbs.push({ doc, func });
+ if (dv) {
+ this.callAddViewFuncs(dv);
+ }
+ };
+ callAddViewFuncs = (view: DocumentView) => {
+ const callFuncs = this._viewRenderedCbs.filter(vc => vc.doc === view.rootDoc);
+ if (callFuncs.length) {
+ this._viewRenderedCbs = this._viewRenderedCbs.filter(vc => callFuncs.includes(vc));
+ const intTimer = setInterval(
+ () => {
+ if (!view.ComponentView?.incrementalRendering?.()) {
+ callFuncs.forEach(cf => cf.func(view));
+ clearInterval(intTimer);
+ }
+ },
+ view.ComponentView?.incrementalRendering?.() ? 0 : 100
+ );
+ }
+ };
+
@action
public AddView = (view: DocumentView) => {
//console.log("MOUNT " + view.props.Document.title + "/" + view.props.LayoutTemplateString);
@@ -50,6 +74,7 @@ export class DocumentManager {
} else {
this.DocumentViews.add(view);
}
+ this.callAddViewFuncs(view);
};
public RemoveView = action((view: DocumentView) => {
this.LinkedDocumentViews.slice().forEach(
@@ -173,7 +198,7 @@ export class DocumentManager {
targetDoc: Doc, // document to display
options: DocFocusOptions, // options for how to navigate to target
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
+ docContextPath: Doc[], // context to load that should contain the target
finished?: () => void
): void => {
const originalTarget = options.originalTarget ?? targetDoc;
@@ -201,29 +226,20 @@ export class DocumentManager {
finished?.();
};
const annoContainerView = (!wasHidden || resolvedTarget !== annotatedDoc) && annotatedDoc && this.getFirstDocumentView(annotatedDoc);
- const contextDocs = docContext.length ? DocListCast(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 && this.getFirstDocumentView(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 (annoContainerView) {
if (annoContainerView.props.Document.layoutKey === 'layout_icon') {
- annoContainerView.iconify(() =>
- annoContainerView.focus(targetDoc, {
- ...options,
- originalTarget,
- afterFocus: (didFocus: boolean) =>
- new Promise<ViewAdjustment>(res => {
- focusAndFinish(true);
- res(ViewAdjustment.doNothing);
- }),
- })
- );
- return;
- } else if (!docView && targetDoc.type !== DocumentType.MARKER) {
+ return annoContainerView.iconify(() => DocumentManager.Instance.AddViewRenderedCb(targetDoc, () => this.jumpToDocument(resolvedTarget ?? targetDoc, { ...options, toggleTarget: false }, createViewFunc, docContextPath, finished)), 30);
+ }
+ 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
}
}
+
+ const contextDoc = docContextPath.length ? docContextPath[0] : undefined;
+ const remainingDocContext = docContextPath.length ? docContextPath.slice(1) : [];
+ const targetDocContext = contextDoc || annotatedDoc;
+ const targetDocContextView = (targetDocContext && this.getFirstDocumentView(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 (focusView) {
!options.noSelect && Doc.linkFollowHighlight(focusView.rootDoc, undefined, targetDoc); //TODO:glr make this a setting in PresBox
if (options.playAudio) DocumentManager.playAudioAnno(focusView.rootDoc);
@@ -252,56 +268,53 @@ export class DocumentManager {
// 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';
+
+ if (targetDocContext.layoutKey === 'layout_icon') {
+ return targetDocContextView.iconify(
+ () => DocumentManager.Instance.AddViewRenderedCb(targetDoc, () => this.jumpToDocument(resolvedTarget ?? targetDoc, { ...options /* originalTarget - needed? */ }, createViewFunc, docContextPath, finished)),
+ 30
+ );
+ }
+
+ const contextFocusTime = options.zoomTime ? options.zoomTime / 2 : 500;
+ const remainingFocustime = options.zoomTime ? options.zoomTime - contextFocusTime : undefined;
+ targetDocContextView.setViewTransition('transform', contextFocusTime);
+ // this makes focusing on contexts run in parallel -- jutmp to document below makes them run sequentially
+ this.AddViewRenderedCb(targetDoc, () => this.jumpToDocument(targetDoc, { ...options, zoomTime: remainingFocustime }, createViewFunc, remainingDocContext, finished));
targetDocContextView.props.focus(targetDocContextView.rootDoc, {
...options,
+ zoomTime: contextFocusTime,
// originalTarget, // needed?
afterFocus: async () => {
- targetDocContext._viewTransition = undefined;
- if (targetDocContext.layoutKey === 'layout_icon') {
- targetDocContextView.iconify(() => this.jumpToDocument(resolvedTarget ?? targetDoc, { ...options /* originalTarget - needed?*/ }, createViewFunc, docContext, finished));
+ // 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;
+ targetDocContext._currentTimecode = targetDoc.anchorTimecodeToShow;
+ finished?.();
+ } else {
+ // otherwise, just look for the target document in this context view now that we've focused the context view
+ if (this.getFirstDocumentView(resolvedTarget)) {
+ // test again for the target view snce we presumably created the context above by focusing on it
+ this.jumpToDocument(targetDoc, { ...options, zoomTime: remainingFocustime }, createViewFunc, remainingDocContext, finished);
+ } else if (targetDoc.layout) {
+ // there will no layout for a TEXTANCHOR type document
+ createViewFunc(Doc.BrushDoc(targetDoc), finished); // create a new view of the target
+ }
}
return ViewAdjustment.doNothing;
},
});
-
- // 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;
- targetDocContext._currentTimecode = targetDoc.anchorTimecodeToShow;
- finished?.();
- } else {
- // no timecode means we need to find the context view and focus on our target
- const retryDocView = this.getFirstDocumentView(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.focus(targetDoc, {
- ...options,
- // originalTarget -- needed?
- afterFocus: (didFocus: boolean) =>
- new Promise<ViewAdjustment>(res => {
- !options.noSelect && focusAndFinish(true);
- res(ViewAdjustment.doNothing);
- }),
- }); // focus on the target in the context
- } else 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 {
- if (docContext.length && docContext[0]?.layoutKey === 'layout_icon') {
- const docContextView = this.getFirstDocumentView(docContext[0]);
- if (docContextView) {
- return docContextView.iconify(() => this.jumpToDocument(targetDoc, { ...options, originalTarget }, createViewFunc, docContext.slice(1, docContext.length), finished));
- }
+ if (docContextPath.length && docContextPath[0]?.layoutKey === 'layout_icon') {
+ Doc.deiconifyView(docContextPath[0]);
+ this.jumpToDocument(targetDoc, options, createViewFunc, docContextPath, finished);
+ } 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, { ...options }, (doc: Doc, finished?: () => void) => doc !== targetDocContext && createViewFunc(doc, finished), remainingDocContext, finished)
+ );
}
- // 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, { ...options, originalTarget }, (doc: Doc, finished?: () => void) => doc !== targetDocContext && createViewFunc(doc, finished), docContext, finished)
- );
}
}
}