aboutsummaryrefslogtreecommitdiff
path: root/src/client/util/LinkManager.ts
diff options
context:
space:
mode:
authorSophie Zhang <sophie_zhang@brown.edu>2024-01-25 11:35:26 -0500
committerSophie Zhang <sophie_zhang@brown.edu>2024-01-25 11:35:26 -0500
commitf3dab2a56db5e4a6a3dca58185d94e1ff7d1dc32 (patch)
treea7bc895266b53bb620dbd2dd71bad2e83b555446 /src/client/util/LinkManager.ts
parentb5c5410b4af5d2c68d2107d3f064f6e3ec4ac3f2 (diff)
parent136f3d9f349d54e8bdd73b6380ea47c19e5edebf (diff)
Merge branch 'master' into sophie-ai-images
Diffstat (limited to 'src/client/util/LinkManager.ts')
-rw-r--r--src/client/util/LinkManager.ts68
1 files changed, 42 insertions, 26 deletions
diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts
index ba53a760f..353f28a92 100644
--- a/src/client/util/LinkManager.ts
+++ b/src/client/util/LinkManager.ts
@@ -1,7 +1,7 @@
-import { action, observable, observe, runInAction } from 'mobx';
+import { action, makeObservable, observable, observe, runInAction } from 'mobx';
import { computedFn } from 'mobx-utils';
import { Doc, DocListCast, DocListCastAsync, Field, Opt } from '../../fields/Doc';
-import { DirectLinks } from '../../fields/DocSymbols';
+import { DirectLinks, DocData } from '../../fields/DocSymbols';
import { FieldLoader } from '../../fields/FieldLoader';
import { List } from '../../fields/List';
import { ProxyField } from '../../fields/Proxy';
@@ -22,9 +22,9 @@ import { ScriptingGlobals } from './ScriptingGlobals';
*/
export class LinkManager {
@observable static _instance: LinkManager;
- @observable static userLinkDBs: Doc[] = [];
- @observable public static currentLink: Opt<Doc>;
- @observable public static currentLinkAnchor: Opt<Doc>;
+ @observable.shallow userLinkDBs: Doc[] = [];
+ @observable public static currentLink: Opt<Doc> = undefined;
+ @observable public static currentLinkAnchor: Opt<Doc> = undefined;
public static get Instance() {
return LinkManager._instance;
}
@@ -32,21 +32,20 @@ export class LinkManager {
public static Links(doc: Doc | undefined) {
return doc ? LinkManager.Instance.getAllRelatedLinks(doc) : [];
}
- public static addLinkDB = async (linkDb: any) => {
+ public addLinkDB = async (linkDb: any) => {
await Promise.all(
((await DocListCastAsync(linkDb.data)) ?? []).map(link =>
// makes sure link anchors are loaded to avoid incremental updates to computedFns in LinkManager
[PromiseValue(link?.link_anchor_1), PromiseValue(link?.link_anchor_2)]
)
);
- LinkManager.userLinkDBs.push(linkDb);
+ this.userLinkDBs.push(linkDb);
};
public static AutoKeywords = 'keywords:Usages';
- static _links: Doc[] = [];
constructor() {
+ makeObservable(this);
LinkManager._instance = this;
this.createlink_relationshipLists();
- LinkManager.userLinkDBs = [];
// since this is an action, not a reaction, we get only one shot to add this link to the Anchor docs
// Thus make sure all promised values are resolved from link -> link.proto -> link.link_anchor_[1,2] -> link.link_anchor_[1,2].proto
// Then add the link to the anchor protos.
@@ -59,8 +58,8 @@ export class LinkManager {
link &&
action(lAnchProtoProtos => {
Doc.AddDocToList(Doc.UserDoc(), 'links', link);
- lAnchs[0] && Doc.GetProto(lAnchs[0])[DirectLinks].add(link);
- lAnchs[1] && Doc.GetProto(lAnchs[1])[DirectLinks].add(link);
+ lAnchs[0] && lAnchs[0][DocData][DirectLinks].add(link);
+ lAnchs[1] && lAnchs[1][DocData][DirectLinks].add(link);
})
)
)
@@ -75,8 +74,8 @@ export class LinkManager {
Promise.all(lAnchs.map(lAnch => PromiseValue(lAnch?.proto as Doc))).then((lAnchProtos: Opt<Doc>[]) =>
Promise.all(lAnchProtos.map(lAnchProto => PromiseValue(lAnchProto?.proto as Doc))).then(
action(lAnchProtoProtos => {
- link && lAnchs[0] && Doc.GetProto(lAnchs[0])[DirectLinks].delete(link);
- link && lAnchs[1] && Doc.GetProto(lAnchs[1])[DirectLinks].delete(link);
+ link && lAnchs[0] && lAnchs[0][DocData][DirectLinks].delete(link);
+ link && lAnchs[1] && lAnchs[1][DocData][DirectLinks].delete(link);
})
)
)
@@ -85,7 +84,6 @@ export class LinkManager {
);
const watchUserLinkDB = (userLinkDBDoc: Doc) => {
- LinkManager._links.push(...DocListCast(userLinkDBDoc.data));
const toRealField = (field: Field) => (field instanceof ProxyField ? field.value : field); // see List.ts. data structure is not a simple list of Docs, but a list of ProxyField/Fields
if (userLinkDBDoc.data) {
observe(
@@ -124,7 +122,7 @@ export class LinkManager {
}
};
observe(
- LinkManager.userLinkDBs,
+ this.userLinkDBs,
change => {
switch (change.type as any) {
case 'splice':
@@ -135,8 +133,8 @@ export class LinkManager {
},
true
);
- runInAction(() => (FieldLoader.ServerLoadStatus.message = 'links'));
- LinkManager.addLinkDB(Doc.LinkDBDoc());
+ FieldLoader.ServerLoadStatus.message = 'links';
+ this.addLinkDB(Doc.LinkDBDoc());
}
public createlink_relationshipLists = () => {
@@ -163,8 +161,8 @@ export class LinkManager {
public getAllRelatedLinks(anchor: Doc) {
return this.relatedLinker(anchor);
} // finds all links that contain the given anchor
- public getAllDirectLinks(anchor: Doc): Doc[] {
- return Array.from(Doc.GetProto(anchor)[DirectLinks]);
+ public getAllDirectLinks(anchor?: Doc): Doc[] {
+ return anchor ? Array.from(anchor[DirectLinks]) : [];
} // finds all links that contain the given anchor
relatedLinker = computedFn(function relatedLinker(this: any, anchor: Doc): Doc[] {
@@ -197,14 +195,32 @@ export class LinkManager {
}
// finds the opposite anchor of a given anchor in a link
- //TODO This should probably return undefined if there isn't an opposite anchor
- //TODO This should also await the return value of the anchor so we don't filter out promises
public static getOppositeAnchor(linkDoc: Doc, anchor: Doc): Doc | undefined {
- const a1 = Cast(linkDoc.link_anchor_1, Doc, null);
- const a2 = Cast(linkDoc.link_anchor_2, Doc, null);
- if (Doc.AreProtosEqual(DocCast(anchor.annotationOn, anchor), DocCast(a1?.annotationOn, a1))) return a2;
- if (Doc.AreProtosEqual(DocCast(anchor.annotationOn, anchor), DocCast(a2?.annotationOn, a2))) return a1;
- if (Doc.AreProtosEqual(anchor, linkDoc)) return linkDoc;
+ const id = LinkManager.anchorIndex(linkDoc, anchor);
+ const a1 = DocCast(linkDoc.link_anchor_1);
+ const a2 = DocCast(linkDoc.link_anchor_2);
+ return id === '1' ? a2 : id === '2' ? a1 : id === '0' ? linkDoc : undefined;
+ // if (Doc.AreProtosEqual(DocCast(anchor.annotationOn, anchor), DocCast(a1?.annotationOn, a1))) return a2;
+ // if (Doc.AreProtosEqual(DocCast(anchor.annotationOn, anchor), DocCast(a2?.annotationOn, a2))) return a1;
+ // if (Doc.AreProtosEqual(anchor, linkDoc)) return linkDoc;
+ }
+ public static anchorIndex(linkDoc: Doc, anchor: Doc) {
+ const a1 = DocCast(linkDoc.link_anchor_1);
+ const a2 = DocCast(linkDoc.link_anchor_2);
+ if (linkDoc.link_matchEmbeddings) {
+ return [a2, a2.annotationOn].includes(anchor) ? '2' : '1';
+ }
+ if (Doc.AreProtosEqual(DocCast(anchor.annotationOn, anchor), DocCast(a1?.annotationOn, a1))) return '1';
+ if (Doc.AreProtosEqual(DocCast(anchor.annotationOn, anchor), DocCast(a2?.annotationOn, a2))) return '2';
+ if (Doc.AreProtosEqual(anchor, linkDoc)) return '0';
+
+ // const a1 = DocCast(linkDoc.link_anchor_1);
+ // const a2 = DocCast(linkDoc.link_anchor_2);
+ // if (linkDoc.link_matchEmbeddings) {
+ // return [a2, a2.annotationOn].includes(anchor) ? '2' : '1';
+ // }
+ // if (Doc.AreProtosEqual(a2, anchor) || Doc.AreProtosEqual(a2.annotationOn as Doc, anchor)) return '2';
+ // return Doc.AreProtosEqual(a1, anchor) || Doc.AreProtosEqual(a1.annotationOn as Doc, anchor) ? '1' : '2';
}
}