aboutsummaryrefslogtreecommitdiff
path: root/src/client/apis/hypothesis/HypothesisUtils.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/apis/hypothesis/HypothesisUtils.ts')
-rw-r--r--src/client/apis/hypothesis/HypothesisUtils.ts133
1 files changed, 67 insertions, 66 deletions
diff --git a/src/client/apis/hypothesis/HypothesisUtils.ts b/src/client/apis/hypothesis/HypothesisUtils.ts
index 5c6e4d31d..f3ff196a8 100644
--- a/src/client/apis/hypothesis/HypothesisUtils.ts
+++ b/src/client/apis/hypothesis/HypothesisUtils.ts
@@ -1,7 +1,7 @@
import { StrCast, Cast } from "../../../fields/Types";
import { SearchUtil } from "../../util/SearchUtil";
import { action, runInAction } from "mobx";
-import { Doc } from "../../../fields/Doc";
+import { Doc, Opt } from "../../../fields/Doc";
import { DocumentType } from "../../documents/DocumentTypes";
import { Docs, DocUtils } from "../../documents/Documents";
import { SelectionManager } from "../../util/SelectionManager";
@@ -10,17 +10,23 @@ import { DocumentManager } from "../../util/DocumentManager";
import { DocumentLinksButton } from "../../views/nodes/DocumentLinksButton";
import { LinkManager } from "../../util/LinkManager";
import { TaskCompletionBox } from "../../views/nodes/TaskCompletedBox";
-import { Utils } from "../../../Utils";
+import { Utils, simulateMouseClick } from "../../../Utils";
import { LinkDescriptionPopup } from "../../views/nodes/LinkDescriptionPopup";
import { Id } from "../../../fields/FieldSymbols";
+import { DocumentView } from "../../views/nodes/DocumentView";
export namespace Hypothesis {
- // Return web doc with the given uri, or create and create a new doc with the given uri
export const getSourceWebDoc = async (uri: string) => {
- const currentDoc = SelectionManager.SelectedDocuments()[0].props.Document;
- console.log(Cast(currentDoc.data, WebField)?.url.href === uri, uri, Cast(currentDoc.data, WebField)?.url.href);
- if (Cast(currentDoc.data, WebField)?.url.href === uri) return currentDoc; // always check first whether the current doc is the source, only resort to Search otherwise
+ const result = await findWebDoc(uri);
+ return result || Docs.Create.WebDocument(uri, { _nativeWidth: 850, _nativeHeight: 962, _width: 600, UseCors: true }); // create and return a new Web doc with given uri if no matching docs are found
+ };
+
+ // Search for a web Doc whose url field matches the given uri, return undefined if not found
+ export const findWebDoc = async (uri: string) => {
+ const currentDoc = SelectionManager.SelectedDocuments().length && SelectionManager.SelectedDocuments()[0].props.Document;
+ currentDoc && console.log(Cast(currentDoc.data, WebField)?.url.href === uri, uri, Cast(currentDoc.data, WebField)?.url.href);
+ if (currentDoc && Cast(currentDoc.data, WebField)?.url.href === uri) return currentDoc; // always check first whether the current doc is the source, only resort to Search otherwise
const results: Doc[] = [];
await SearchUtil.Search("web", true).then(action(async (res: SearchUtil.DocSearchResult) => {
@@ -34,17 +40,64 @@ export namespace Hypothesis {
results.forEach(doc => console.log(doc.title, StrCast(doc.data)));
- return results.length ? results[0] : Docs.Create.WebDocument(uri, { _nativeWidth: 850, _nativeHeight: 962, _width: 600, UseCors: true }); // create and return a new Web doc with given uri if no matching docs are found
+ return results.length ? results[0] : undefined;
};
- // Send Hypothes.is client request to edit an annotation to add a Dash hyperlink
- export const makeLink = async (title: string, url: string, annotationId: string) => {
+ // Ask Hypothes.is client to edit an annotation to add a Dash hyperlink
+ export const makeLink = async (title: string, url: string, annotationId: string, annotationSourceDoc: Doc) => {
+ // if the annotation's source webpage isn't currently loaded in Dash, we're not able to access and edit the annotation from the client
+ // so we're loading the webpage and its annotations invisibly in a WebBox in MainView.tsx, until the editing is done
+ !DocumentManager.Instance.getFirstDocumentView(annotationSourceDoc) && runInAction(() => DocumentLinksButton.invisibleWebDoc = annotationSourceDoc);
+
+ var success = false;
+ const onSuccess = action(() => {
+ console.log("EDITSUCCESS");
+ clearTimeout(interval);
+ DocumentLinksButton.invisibleWebDoc = undefined;
+ document.removeEventListener("editSuccess", onSuccess);
+ success = true;
+ });
+
console.log("SEND addLink");
const newHyperlink = `[${title}\n](${url})`;
- document.dispatchEvent(new CustomEvent<{ newHyperlink: string, id: string }>("addLink", {
- detail: { newHyperlink: newHyperlink, id: annotationId },
- bubbles: true
- }));
+ const interval = setInterval(() => // keep trying to scroll every 250ms until annotations have loaded and editing is successful
+ !success && document.dispatchEvent(new CustomEvent<{ newHyperlink: string, id: string }>("addLink", {
+ detail: { newHyperlink: newHyperlink, id: annotationId },
+ bubbles: true
+ })), 300);
+
+ setTimeout(action(() => {
+ if (!success) {
+ clearInterval(interval);
+ DocumentLinksButton.invisibleWebDoc = undefined;
+ }
+ }), 15000); // give up if no success after 15s
+
+ document.addEventListener("editSuccess", onSuccess);
+ };
+
+ export const scrollToAnnotation = (annotationId: string, target: Doc) => {
+ var success = false;
+ const onSuccess = () => {
+ console.log("scroll success!!");
+ document.removeEventListener('scrollSuccess', onSuccess);
+ clearInterval(interval);
+ success = true;
+ };
+
+ const interval = setInterval(() => { // keep trying to scroll every 250ms until annotations have loaded and scrolling is successful
+ console.log("send scroll");
+ document.dispatchEvent(new CustomEvent('scrollToAnnotation', {
+ detail: annotationId,
+ bubbles: true
+ }));
+ const targetView: Opt<DocumentView> = DocumentManager.Instance.getFirstDocumentView(target);
+ const position = targetView?.props.ScreenToLocalTransform().inverse().transformPoint(0, 0);
+ targetView && position && simulateMouseClick(targetView.ContentDiv!, position[0], position[1], position[0], position[1], false);
+ }, 300);
+
+ document.addEventListener('scrollSuccess', onSuccess); // listen for success message from client
+ setTimeout(() => !success && clearInterval(interval), 10000); // give up if no success after 10s
};
// Send Hypothes.is client request to edit an annotation to find and remove a dash hyperlink
@@ -80,7 +133,7 @@ export namespace Hypothesis {
Doc.GetProto(linkDoc as Doc).linksToAnnotation = true;
Doc.GetProto(linkDoc as Doc).annotationId = DocumentLinksButton.AnnotationId;
Doc.GetProto(linkDoc as Doc).annotationUri = DocumentLinksButton.AnnotationUri;
- makeLink(StrCast(DocumentLinksButton.StartLink.title), Utils.prepend("/doc/" + DocumentLinksButton.StartLink[Id]), StrCast(DocumentLinksButton.AnnotationId)); // update and link placeholder annotation
+ makeLink(StrCast(DocumentLinksButton.StartLink.title), Utils.prepend("/doc/" + DocumentLinksButton.StartLink[Id]), StrCast(DocumentLinksButton.AnnotationId), sourceDoc); // update and link placeholder annotation
runInAction(() => {
if (linkDoc) {
@@ -99,56 +152,4 @@ export namespace Hypothesis {
});
}
};
-
- // Return web doc with the given uri, or create and create a new doc with the given uri
- export const getSourceWebDocView = async (uri: string) => {
- const currentDoc = SelectionManager.SelectedDocuments()[0].props.Document;
- console.log(Cast(currentDoc.data, WebField)?.url.href === uri, uri, Cast(currentDoc.data, WebField)?.url.href);
- if (Cast(currentDoc.data, WebField)?.url.href === uri) return currentDoc; // always check first whether the current doc is the source, only resort to Search otherwise
-
- const results: Doc[] = [];
- await SearchUtil.Search("web", true).then(action(async (res: SearchUtil.DocSearchResult) => {
- const docs = await Promise.all(res.docs.map(async doc => (await Cast(doc.extendsDoc, Doc)) || doc));
- const filteredDocs = docs.filter(doc =>
- doc.author === Doc.CurrentUserEmail && doc.type === DocumentType.WEB && doc.data
- );
- filteredDocs.forEach(doc => console.log("web docs:", doc.title, Cast(doc.data, WebField)?.url.href));
- filteredDocs.forEach(doc => { uri === Cast(doc.data, WebField)?.url.href && results.push(doc); }); // TODO check history? imperfect matches?
- }));
-
- results.forEach(doc => {
- const docView = DocumentManager.Instance.getFirstDocumentView(doc);
- if (docView) {
- console.log(doc.title, StrCast(doc.data));
- return docView;
- }
- });
-
- return undefined;
- };
-
- export const createInvisibleDoc = (uri: string) => {
- const newDoc = Docs.Create.WebDocument(uri, { _nativeWidth: 0, _nativeHeight: 0, _width: 0, UseCors: true });
- };
-
- export const scrollToAnnotation = (annotationId: string) => {
- var success = false;
- const onSuccess = () => {
- console.log("scroll success!!");
- document.removeEventListener('scrollSuccess', onSuccess);
- clearTimeout(interval);
- success = true;
- };
-
- const interval = setInterval(() => { // keep trying to scroll every 200ms until annotations have loaded and scrolling is successful
- console.log("send scroll");
- document.dispatchEvent(new CustomEvent('scrollToAnnotation', {
- detail: annotationId,
- bubbles: true
- }));
- }, 250);
-
- document.addEventListener('scrollSuccess', onSuccess); // listen for success message from client
- setTimeout(() => !success && clearTimeout(interval), 10000); // give up if no success after 10s
- };
} \ No newline at end of file