aboutsummaryrefslogtreecommitdiff
path: root/src/client/util
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/util')
-rw-r--r--src/client/util/CurrentUserUtils.ts55
-rw-r--r--src/client/util/DocumentManager.ts64
-rw-r--r--src/client/util/DragManager.ts33
-rw-r--r--src/client/util/LinkManager.ts21
4 files changed, 108 insertions, 65 deletions
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index f02c5a5a1..3165e38a6 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -9,7 +9,7 @@ import { RichTextField } from "../../fields/RichTextField";
import { listSpec } from "../../fields/Schema";
import { ComputedField, ScriptField } from "../../fields/ScriptField";
import { BoolCast, Cast, DateCast, NumCast, PromiseValue, StrCast } from "../../fields/Types";
-import { nullAudio } from "../../fields/URLField";
+import { ImageField, nullAudio } from "../../fields/URLField";
import { SharingPermissions } from "../../fields/util";
import { Utils } from "../../Utils";
import { DocServer } from "../DocServer";
@@ -193,7 +193,6 @@ export class CurrentUserUtils {
const requiredTypes = [
doc["template-button-slides"] as Doc,
doc["template-mobile-button"] as Doc,
- doc["template-button-detail"] as Doc,
doc["template-button-link"] as Doc,
//doc["template-button-switch"] as Doc]
];
@@ -293,10 +292,10 @@ export class CurrentUserUtils {
if (doc["template-icon-view"] === undefined) {
const iconView = Docs.Create.LabelDocument({
title: "icon", textTransform: "unset", letterSpacing: "unset", layout: LabelBox.LayoutString("title"), _backgroundColor: "dimgray",
- _width: 150, _height: 70, _xPadding: 10, _yPadding: 10, isTemplateDoc: true, onDoubleClick: ScriptField.MakeScript("deiconifyView(self)"), system: true
+ _width: 150, _height: 70, _xPadding: 10, _yPadding: 10, isTemplateDoc: true, onClick: ScriptField.MakeScript("deiconifyView(documentView)", { documentView: "any" }), system: true
});
// Docs.Create.TextDocument("", {
- // title: "icon", _width: 150, _height: 30, isTemplateDoc: true, onDoubleClick: ScriptField.MakeScript("deiconifyView(self)")
+ // title: "icon", _width: 150, _height: 30, isTemplateDoc: true, onDoubleClick: ScriptField.MakeScript("deiconifyView(documentView)", { documentView: "any" })
// });
// Doc.GetProto(iconView).icon = new RichTextField('{"doc":{"type":"doc","content":[{"type":"paragraph","attrs":{"align":null,"color":null,"id":null,"indent":null,"inset":null,"lineSpacing":null,"paddingBottom":null,"paddingTop":null},"content":[{"type":"dashField","attrs":{"fieldKey":"title","docid":""}}]}]},"selection":{"type":"text","anchor":2,"head":2},"storedMarks":[]}', "");
iconView.isTemplateDoc = makeTemplate(iconView);
@@ -304,8 +303,9 @@ export class CurrentUserUtils {
}
if (doc["template-icon-view-rtf"] === undefined) {
const iconRtfView = Docs.Create.LabelDocument({
- title: "icon_" + DocumentType.RTF, textTransform: "unset", letterSpacing: "unset", layout: LabelBox.LayoutString("text"),
- _width: 150, _height: 70, _xPadding: 10, _yPadding: 10, isTemplateDoc: true, onDoubleClick: ScriptField.MakeScript("deiconifyView(self)"), system: true
+ title: "icon_" + DocumentType.RTF, _showTitle: "creationDate", textTransform: "unset", letterSpacing: "unset", layout: LabelBox.LayoutString("text"),
+ _singleLine: false, _minFontSize: 18, _maxFontSize: 24,
+ _width: 150, _height: 70, _xPadding: 10, _yPadding: 10, isTemplateDoc: true, onClick: ScriptField.MakeScript("deiconifyView(documentView)", { documentView: "any" }), system: true
});
iconRtfView.isTemplateDoc = makeTemplate(iconRtfView, true, "icon_" + DocumentType.RTF);
doc["template-icon-view-rtf"] = new PrefetchProxy(iconRtfView);
@@ -313,26 +313,48 @@ export class CurrentUserUtils {
if (doc["template-icon-view-button"] === undefined) {
const iconBtnView = Docs.Create.FontIconDocument({
title: "icon_" + DocumentType.BUTTON, _nativeHeight: 30, _nativeWidth: 30,
- _width: 30, _height: 30, isTemplateDoc: true, onDoubleClick: ScriptField.MakeScript("deiconifyView(self)"), system: true
+ _width: 30, _height: 30, isTemplateDoc: true, onDoubleClick: ScriptField.MakeScript("deiconifyView(documentView)", { documentView: "any" }), system: true
});
iconBtnView.isTemplateDoc = makeTemplate(iconBtnView, true, "icon_" + DocumentType.BUTTON);
doc["template-icon-view-button"] = new PrefetchProxy(iconBtnView);
}
if (doc["template-icon-view-img"] === undefined) {
const iconImageView = Docs.Create.ImageDocument("http://www.cs.brown.edu/~bcz/face.gif", {
- title: "data", _width: 50, isTemplateDoc: true, onDoubleClick: ScriptField.MakeScript("deiconifyView(self)"), system: true
+ title: "data", _width: 150, isTemplateDoc: true, _showTitle: "title", onClick: ScriptField.MakeScript("deiconifyView(documentView)", { documentView: "any" }), system: true
});
iconImageView.isTemplateDoc = makeTemplate(iconImageView, true, "icon_" + DocumentType.IMG);
doc["template-icon-view-img"] = new PrefetchProxy(iconImageView);
}
if (doc["template-icon-view-col"] === undefined) {
- const iconColView = Docs.Create.TreeDocument([], { title: "data", _width: 180, _height: 80, onDoubleClick: ScriptField.MakeScript("deiconifyView(self)"), system: true });
+ const iconColView = Docs.Create.ImageDocument("", { title: "icon", _showTitle: "title", _width: 360 / 4, _height: 270 / 4, onClick: ScriptField.MakeScript("deiconifyView(documentView)", { documentView: "any" }), system: true });
iconColView.isTemplateDoc = makeTemplate(iconColView, true, "icon_" + DocumentType.COL);
+ const proto = iconColView.proto as Doc;
+ proto["icon-nativeWidth"] = 360 / 4;
+ proto["icon-nativeHeight"] = 270 / 4;
+ proto.icon = new ImageField("http://www.cs.brown.edu/~bcz/noImage.png");
doc["template-icon-view-col"] = new PrefetchProxy(iconColView);
}
+ if (doc["template-icon-view-video"] === undefined) {
+ const iconVidView = Docs.Create.ImageDocument("", { title: "icon", _width: 360 / 4, _height: 270 / 4, _showTitle: "title", onClick: ScriptField.MakeScript("deiconifyView(documentView)", { documentView: "any" }), system: true });
+ iconVidView.isTemplateDoc = makeTemplate(iconVidView, true, "icon_" + DocumentType.VID);
+ const proto = iconVidView.proto as Doc;
+ proto["icon-nativeWidth"] = 360 / 4;
+ proto["icon-nativeHeight"] = 270 / 4;
+ proto.icon = new ImageField("http://www.cs.brown.edu/~bcz/noImage.png");
+ doc["template-icon-view-video"] = new PrefetchProxy(iconVidView);
+ }
+ if (doc["template-icon-view-pdf"] === undefined) {
+ const iconPdfView = Docs.Create.ImageDocument("", { title: "icon", _width: 360 / 4, _height: 270 / 4, _showTitle: "title", onClick: ScriptField.MakeScript("deiconifyView(documentView)", { documentView: "any" }), system: true });
+ iconPdfView.isTemplateDoc = makeTemplate(iconPdfView, true, "icon_" + DocumentType.PDF);
+ const proto = iconPdfView.proto as Doc;
+ proto["icon-nativeWidth"] = 360 / 4;
+ proto["icon-nativeHeight"] = 270 / 4;
+ proto.icon = new ImageField("http://www.cs.brown.edu/~bcz/noImage.png");
+ doc["template-icon-view-pdf"] = new PrefetchProxy(iconPdfView);
+ }
if (doc["template-icons"] === undefined) {
doc["template-icons"] = new PrefetchProxy(Docs.Create.TreeDocument([doc["template-icon-view"] as Doc, doc["template-icon-view-img"] as Doc, doc["template-icon-view-button"] as Doc,
- doc["template-icon-view-col"] as Doc, doc["template-icon-view-rtf"] as Doc, doc["template-icon-view-pdf"] as Doc], { title: "icon templates", _height: 75, system: true }));
+ doc["template-icon-view-col"] as Doc, doc["template-icon-view-rtf"] as Doc, doc["template-icon-view-video"] as Doc, doc["template-icon-view-pdf"] as Doc], { title: "icon templates", _height: 75, system: true }));
} else {
const templateIconsDoc = Cast(doc["template-icons"], Doc, null);
const requiredTypes = [doc["template-icon-view"] as Doc, doc["template-icon-view-img"] as Doc, doc["template-icon-view-button"] as Doc,
@@ -367,7 +389,7 @@ export class CurrentUserUtils {
const textDoc = Docs.Create.TreeDocument([], {
title: "Slide", _viewType: CollectionViewType.Tree, treeViewHasOverlay: true, _fontSize: "20px", _autoHeight: true,
allowOverlayDrop: true, treeViewType: "outline", _xMargin: 0, _yMargin: 0, _width: 300, _height: 200, _singleLine: true,
- backgroundColor: "transparent", system: true, cloneFieldFilter: new List<string>(["system"])
+ backgroundColor: "white", system: true, cloneFieldFilter: new List<string>(["system"])
});
Doc.GetProto(textDoc).title = ComputedField.MakeFunction('self.text?.Text');
FormattedTextBox.SelectOnLoad = textDoc[Id];
@@ -425,8 +447,8 @@ export class CurrentUserUtils {
doc.emptyScreenshot = Docs.Create.ScreenshotDocument("empty screenshot", { _fitWidth: true, title: "empty screenshot", _width: 400, _height: 200, system: true, cloneFieldFilter: new List<string>(["system"]) });
}
if (doc.emptyWall === undefined) {
- doc.emptyWall = Docs.Create.ScreenshotDocument("", { _fitWidth: true, _width: 400, _height: 200, title: "screen snapshot", system: true, cloneFieldFilter: new List<string>(["system"]) });
- (doc.emptyWall as Doc).videoWall = true;
+ doc.emptyWall = Docs.Create.WebCamDocument("", { _width: 400, _height: 200, title: "recording", system: true, cloneFieldFilter: new List<string>(["system"]) });
+ (doc.emptyWall as Doc).recording = true;
}
if (doc.emptyAudio === undefined) {
doc.emptyAudio = Docs.Create.AudioDocument(nullAudio, { _width: 200, _height: 100, title: "audio recording", system: true, cloneFieldFilter: new List<string>(["system"]) });
@@ -1142,6 +1164,9 @@ export class CurrentUserUtils {
// Sharing sidebar is where shared documents are contained
static async setupSharingSidebar(doc: Doc, sharingDocumentId: string, linkDatabaseId: string) {
+ if (doc.myPublishedDocs === undefined) {
+ doc.myPublishedDocs = new List<Doc>();
+ }
if (doc.myLinkDatabase === undefined) {
let linkDocs = Docs.newAccount ? undefined : await DocServer.GetRefField(linkDatabaseId);
if (!linkDocs) {
@@ -1319,9 +1344,6 @@ export class CurrentUserUtils {
// undefined means ColorScheme.Light until all CSS is updated with values for each color scheme (e.g., see MainView.scss, DocumentDecorations.scss)
doc.activeDashboard.colorScheme = doc.activeDashboard.colorScheme === ColorScheme.Light ? undefined : doc.activeDashboard.colorScheme;
}
- if (doc.activeCollectionBackground === "white") { // temporary to avoid having to rebuild the databse for old accounts that have this set by default.
- doc.activeCollectionBackground = undefined;
- }
return doc;
}
@@ -1502,6 +1524,7 @@ export class CurrentUserUtils {
return tbox;
}
+ public static get DockedBtns() { return Cast(Doc.UserDoc().dockedBtns, Doc, null); }
public static get MySearchPanelDoc() { return Cast(Doc.UserDoc().mySearchPanelDoc, Doc, null); }
public static get ActiveDashboard() { return Cast(Doc.UserDoc().activeDashboard, Doc, null); }
public static get ActivePresentation() { return Cast(Doc.UserDoc().activePresentation, Doc, null); }
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index 0a00ab6e0..b6c28d2fe 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -5,6 +5,7 @@ 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';
@@ -167,30 +168,43 @@ 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 annoContainerView = (!wasHidden || resolvedTarget !== annotatedDoc) && 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 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 ((!docView && targetDoc.type !== DocumentType.MARKER) && annoContainerView) {
+ if (annoContainerView.props.Document.layoutKey === "layout_icon") {
+ annoContainerView.iconify(() => this.jumpToDocument(
+ targetDoc, willZoom, createViewFunc, docContext, linkDoc, closeContextIfNotFound, originatingDoc,
+ finished, originalTarget, noSelect, presZoom));
+ return;
+ } else {
+ 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
@@ -206,10 +220,17 @@ export class DocumentManager {
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(
+ targetDoc, willZoom, createViewFunc, docContext, linkDoc, closeContextIfNotFound, originatingDoc,
+ finished, originalTarget, noSelect, presZoom));
+ }
return ViewAdjustment.doNothing;
}
});
@@ -220,27 +241,27 @@ 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 { // 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);
@@ -250,12 +271,12 @@ 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: any, 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 {
@@ -264,4 +285,5 @@ ScriptingGlobals.add(function DocFocusOrOpen(doc: any) {
CollectionDockingView.AddSplit(showDoc === Doc.GetProto(showDoc) ? Doc.MakeAlias(showDoc) : 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
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index db9986a41..8ac28bc89 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -1,3 +1,4 @@
+import { extend } from "lodash";
import { action } from "mobx";
import { DateField } from "../../fields/DateField";
import { Doc, Field, Opt } from "../../fields/Doc";
@@ -56,12 +57,7 @@ export function SetupDrag(
if (e.shiftKey) {
e.persist();
const dragDoc = await docFunc();
- dragDoc && DragManager.StartWindowDrag?.({
- pageX: e.pageX,
- pageY: e.pageY,
- preventDefault: emptyFunction,
- button: 0
- }, [dragDoc]);
+ dragDoc && DragManager.StartWindowDrag?.(e, [dragDoc]);
} else {
document.addEventListener("pointermove", onRowMove);
document.addEventListener("pointerup", onRowUp);
@@ -74,7 +70,8 @@ export function SetupDrag(
export namespace DragManager {
let dragDiv: HTMLDivElement;
let dragLabel: HTMLDivElement;
- export let StartWindowDrag: Opt<((e: any, dragDocs: Doc[]) => void)> = undefined;
+ export let StartWindowDrag: Opt<((e: { pageX: number, pageY: number }, dragDocs: Doc[], finishDrag?: (aborted: boolean) => void) => void)>;
+ export let CompleteWindowDrag: Opt<(aborted: boolean) => void>;
export function Root() {
const root = document.getElementById("root");
@@ -387,8 +384,8 @@ export namespace DragManager {
}
}
const rect = ele.getBoundingClientRect();
- const scaleX = rect.width / ele.offsetWidth;
- const scaleY = ele.offsetHeight ? rect.height / ele.offsetHeight : scaleX;
+ const scaleX = rect.width / (ele.offsetWidth || rect.width);
+ const scaleY = ele.offsetHeight ? rect.height / (ele.offsetHeight || rect.height) : scaleX;
elesCont.left = Math.min(rect.left, elesCont.left);
elesCont.top = Math.min(rect.top, elesCont.top);
@@ -412,7 +409,7 @@ export namespace DragManager {
Array.from(pdfBox).filter(pb => pb.width && pb.height).map((pb, i) => pb.getContext('2d')!.drawImage(pdfBoxSrc[i], 0, 0));
}
[dragElement, ...Array.from(dragElement.getElementsByTagName('*'))].forEach(ele =>
- ele.hasAttribute("style") && ((ele as any).style.pointerEvents = "none"));
+ (ele as any).style && ((ele as any).style.pointerEvents = "none"));
dragDiv.appendChild(dragElement);
if (dragElement !== ele) {
@@ -462,19 +459,15 @@ export namespace DragManager {
if (dragData instanceof DocumentDragData) {
dragData.userDropAction = e.ctrlKey && e.altKey ? "copy" : e.ctrlKey ? "alias" : dragData.defaultDropAction;
}
- if (e?.shiftKey && dragData.draggedDocuments.length === 1) {
+ if (((e.target as any)?.className === "lm_tabs" || e?.shiftKey) && dragData.draggedDocuments.length === 1) {
dragData.dropAction = dragData.userDropAction || "same";
- if (dragData.dropAction === "move") {
- dragData.removeDocument?.(dragData.draggedDocuments[0]);
- }
AbortDrag();
await finishDrag?.(new DragCompleteEvent(true, dragData));
- DragManager.StartWindowDrag?.({
- pageX: e.pageX,
- pageY: e.pageY,
- preventDefault: emptyFunction,
- button: 0
- }, dragData.droppedDocuments);
+ DragManager.StartWindowDrag?.(e, dragData.droppedDocuments, (aborted) => {
+ if (!aborted && (dragData.dropAction === "move" || dragData.dropAction === "same")) {
+ dragData.removeDocument?.(dragData.draggedDocuments[0]);
+ }
+ });
}
const target = document.elementFromPoint(e.x, e.y);
diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts
index df2c02a8d..9445533dc 100644
--- a/src/client/util/LinkManager.ts
+++ b/src/client/util/LinkManager.ts
@@ -29,6 +29,7 @@ export class LinkManager {
public static currentLink: Opt<Doc>;
public static get Instance() { return LinkManager._instance; }
public static addLinkDB = (linkDb: any) => LinkManager.userLinkDBs.push(linkDb);
+ public static AutoKeywords = "keywords:Usages";
static links: Doc[] = [];
constructor() {
LinkManager._instance = this;
@@ -149,9 +150,11 @@ export class LinkManager {
public getRelatedGroupedLinks(anchor: Doc): Map<string, Array<Doc>> {
const anchorGroups = new Map<string, Array<Doc>>();
this.relatedLinker(anchor).forEach(link => {
- if (!link.linkRelationship || link?.linkRelationship !== "-ungrouped-") {
- const group = anchorGroups.get(StrCast(link.linkRelationship));
- anchorGroups.set(StrCast(link.linkRelationship), group ? [...group, link] : [link]);
+ if (link.linkRelationship && link.linkRelationship !== "-ungrouped-") {
+ const relation = StrCast(link.linkRelationship);
+ const anchorRelation = relation.indexOf(":") !== -1 ? relation.split(":")[Doc.AreProtosEqual(Cast(link.anchor1, Doc, null), anchor) ? 0 : 1] : relation;
+ const group = anchorGroups.get(anchorRelation);
+ anchorGroups.set(anchorRelation, group ? [...group, link] : [link]);
} else {
// if link is in no groups then put it in default group
const group = anchorGroups.get("*");
@@ -221,7 +224,9 @@ export class LinkManager {
const backLinkWithoutTargetView = secondDocs.find(d => DocumentManager.Instance.getDocumentViews(d.anchor1 as Doc).length === 0);
const linkWithoutTargetDoc = traverseBacklink === undefined ? fwdLinkWithoutTargetView || backLinkWithoutTargetView : traverseBacklink ? backLinkWithoutTargetView : fwdLinkWithoutTargetView;
const linkDocList = linkWithoutTargetDoc ? [linkWithoutTargetDoc] : (traverseBacklink === undefined ? firstDocs.concat(secondDocs) : traverseBacklink ? secondDocs : firstDocs);
- const followLinks = linkDocList.length ? (sourceDoc.isPushpin ? linkDocList : [linkDocList[0]]) : [];
+ const followLinks = sourceDoc.isPushpin ? linkDocList : linkDocList.slice(0, 1);
+ var count = 0;
+ const allFinished = () => ++count === followLinks.length && finished?.();
followLinks.forEach(async linkDoc => {
if (linkDoc) {
const target = (sourceDoc === linkDoc.anchor1 ? linkDoc.anchor2 : sourceDoc === linkDoc.anchor2 ? linkDoc.anchor1 :
@@ -232,20 +237,20 @@ export class LinkManager {
const tour = DocListCast(target[fieldKey]).reverse();
LightboxView.SetLightboxDoc(currentContext, undefined, tour);
setTimeout(LightboxView.Next);
- finished?.();
+ allFinished();
} else {
const containerAnnoDoc = Cast(target.annotationOn, Doc, null);
const containerDoc = containerAnnoDoc || target;
const containerDocContext = Cast(containerDoc?.context, Doc, null);
const targetContext = LightboxView.LightboxDoc ? containerAnnoDoc || containerDocContext : containerDocContext;
const targetNavContext = !Doc.AreProtosEqual(targetContext, currentContext) ? targetContext : undefined;
- DocumentManager.Instance.jumpToDocument(target, zoom, (doc, finished) => createViewFunc(doc, StrCast(linkDoc.followLinkLocation, "lightbox"), finished), targetNavContext, linkDoc, undefined, sourceDoc, finished);
+ DocumentManager.Instance.jumpToDocument(target, zoom, (doc, finished) => createViewFunc(doc, StrCast(linkDoc.followLinkLocation, "lightbox"), finished), targetNavContext, linkDoc, undefined, sourceDoc, allFinished);
}
} else {
- finished?.();
+ allFinished();
}
} else {
- finished?.();
+ allFinished();
}
});
}