aboutsummaryrefslogtreecommitdiff
path: root/src/client/util
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/util')
-rw-r--r--src/client/util/CurrentUserUtils.ts64
-rw-r--r--src/client/util/DictationManager.ts28
-rw-r--r--src/client/util/DocumentManager.ts9
-rw-r--r--src/client/util/DragManager.ts193
-rw-r--r--src/client/util/Import & Export/DirectoryImportBox.tsx1
-rw-r--r--src/client/util/LinkManager.ts118
6 files changed, 201 insertions, 212 deletions
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 993eba889..ea27b7327 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -203,7 +203,7 @@ export class CurrentUserUtils {
new SchemaHeaderField("[Long Description]", "dimGray", undefined, undefined, undefined, true),
new SchemaHeaderField("[Details]", "dimGray", undefined, undefined, undefined, true),
]);
- const detailView = Docs.Create.StackingDocument([carousel, descriptionWrapper], { ...shared, ...detailViewOpts, system: true });
+ const detailView = Docs.Create.StackingDocument([carousel, descriptionWrapper], { ...shared, ...detailViewOpts, _chromeHidden: true, system: true });
detailView.isTemplateDoc = makeTemplate(detailView);
details.title = "Details";
@@ -225,7 +225,7 @@ export class CurrentUserUtils {
];
if (doc["template-buttons"] === undefined) {
doc["template-buttons"] = new PrefetchProxy(Docs.Create.MasonryDocument(requiredTypes, {
- title: "Advanced Item Prototypes", _xMargin: 0, _showTitle: "title",
+ title: "Advanced Item Prototypes", _xMargin: 0, _showTitle: "title", _chromeHidden: true,
hidden: ComputedField.MakeFunction("IsNoviceMode()") as any,
_stayInCollection: true, _hideContextMenu: true,
_autoHeight: true, _width: 500, _height: 300, _fitWidth: true, _columnWidth: 35, ignoreClick: true, _lockedPosition: true,
@@ -367,7 +367,7 @@ export class CurrentUserUtils {
}[] {
if (doc.emptyPresentation === undefined) {
doc.emptyPresentation = Docs.Create.PresDocument(new List<Doc>(),
- { title: "Untitled Presentation", _viewType: CollectionViewType.Stacking, _fitWidth: true, _width: 400, _height: 500, targetDropAction: "alias", _chromeStatus: "replaced", boxShadow: "0 0", system: true, cloneFieldFilter: new List<string>(["system"]) });
+ { title: "Untitled Presentation", _viewType: CollectionViewType.Stacking, _fitWidth: true, _width: 400, _height: 500, targetDropAction: "alias", _chromeHidden: true, boxShadow: "0 0", system: true, cloneFieldFilter: new List<string>(["system"]) });
((doc.emptyPresentation as Doc).proto as Doc)["dragFactory-count"] = 0;
}
if (doc.emptyCollection === undefined) {
@@ -423,7 +423,7 @@ export class CurrentUserUtils {
((doc.emptyScript as Doc).proto as Doc)["dragFactory-count"] = 0;
}
if (doc.emptyScreenshot === undefined) {
- doc.emptyScreenshot = Docs.Create.ScreenshotDocument("", { _width: 400, _height: 200, title: "screen snapshot", system: true, cloneFieldFilter: new List<string>(["system"]) });
+ doc.emptyScreenshot = Docs.Create.ScreenshotDocument("", { _fitWidth: true, _width: 400, _height: 200, title: "screen snapshot", system: true, cloneFieldFilter: new List<string>(["system"]) });
}
if (doc.emptyAudio === undefined) {
doc.emptyAudio = Docs.Create.AudioDocument(nullAudio, { _width: 200, title: "audio recording", system: true, cloneFieldFilter: new List<string>(["system"]) });
@@ -453,7 +453,7 @@ export class CurrentUserUtils {
{ toolTip: "Tap to create a progressive slide", title: "Slide", icon: "file", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptySlide as Doc, noviceMode: true },
{ toolTip: "Tap to create a cat image in a new pane, drag for a cat image", title: "Image", icon: "cat", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyImage as Doc },
{ toolTip: "Tap to create a comparison box in a new pane, drag for a comparison box", title: "Compare", icon: "columns", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyComparison as Doc, noviceMode: true },
- { toolTip: "Tap to create a screen grabber in a new pane, drag for a screen grabber", title: "Grab", icon: "photo-video", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyScreenshot as Doc },
+ { toolTip: "Tap to create a screen grabber in a new pane, drag for a screen grabber", title: "Grab", icon: "photo-video", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyScreenshot as Doc, noviceMode: true },
{ toolTip: "Tap to create an audio recorder in a new pane, drag for an audio recorder", title: "Audio", icon: "microphone", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyAudio as Doc, noviceMode: true },
{ toolTip: "Tap to create a button in a new pane, drag for a button", title: "Button", icon: "bolt", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyButton as Doc },
{ toolTip: "Tap to create a presentation in a new pane, drag for a presentation", title: "Trails", icon: "pres-trail", click: 'openOnRight(Doc.UserDoc().activePresentation = copyDragFactory(this.dragFactory))', drag: `Doc.UserDoc().activePresentation = copyDragFactory(this.dragFactory)`, dragFactory: doc.emptyPresentation as Doc, noviceMode: true },
@@ -483,22 +483,22 @@ export class CurrentUserUtils {
title,
toolTip,
ignoreClick,
- dropAction: "alias",
+ _dropAction: "alias",
onDragStart: drag ? ScriptField.MakeFunction(drag) : undefined,
onClick: click ? ScriptField.MakeScript(click) : undefined,
backgroundColor,
_hideContextMenu: true,
- removeDropProperties: new List<string>(["_stayInCollection"]),
+ _removeDropProperties: new List<string>(["_stayInCollection"]),
_stayInCollection: true,
dragFactory,
clickFactory,
- hidden: noviceMode ? ComputedField.MakeFunction("IsNoviceMode()") as any : undefined,
+ hidden: !noviceMode ? ComputedField.MakeFunction("IsNoviceMode()") as any : undefined,
system: true,
}));
if (dragCreatorSet === undefined) {
doc.myItemCreators = new PrefetchProxy(Docs.Create.MasonryDocument(creatorBtns, {
- title: "Basic Item Creators", _showTitle: "title", _xMargin: 0, _stayInCollection: true, _hideContextMenu: true,
+ title: "Basic Item Creators", _showTitle: "title", _xMargin: 0, _stayInCollection: true, _hideContextMenu: true, _chromeHidden: true,
_autoHeight: true, _width: 500, _height: 300, _fitWidth: true, _columnWidth: 35, ignoreClick: true, _lockedPosition: true,
dropConverter: ScriptField.MakeScript("convertToButtons(dragData)", { dragData: DragManager.DocumentDragData.name }), system: true
}));
@@ -546,8 +546,8 @@ export class CurrentUserUtils {
title,
target,
backgroundColor: "black",
- dropAction: "alias",
- removeDropProperties: new List<string>(["dropAction", "_stayInCollection"]),
+ _dropAction: "alias",
+ _removeDropProperties: new List<string>(["dropAction", "_stayInCollection"]),
_width: 60,
_height: 60,
watchedDocuments,
@@ -559,6 +559,7 @@ export class CurrentUserUtils {
doc.menuStack = new PrefetchProxy(Docs.Create.StackingDocument(menuBtns, {
title: "menuItemPanel",
childDropAction: "alias",
+ _chromeHidden: true,
dropConverter: ScriptField.MakeScript("convertToButtons(dragData)", { dragData: DragManager.DocumentDragData.name }),
backgroundColor: "black", ignoreClick: true,
_gridGap: 0,
@@ -596,7 +597,7 @@ export class CurrentUserUtils {
// Sets up mobileMenu stacking document
static setupMobileMenu() {
const menu = new PrefetchProxy(Docs.Create.StackingDocument(this.setupMobileButtons(), {
- _width: 980, ignoreClick: true, _lockedPosition: false, title: "home", _yMargin: 100, system: true
+ _width: 980, ignoreClick: true, _lockedPosition: false, title: "home", _yMargin: 100, system: true, _chromeHidden: true,
}));
return menu;
}
@@ -626,27 +627,27 @@ export class CurrentUserUtils {
// sets up the main document for the mobile button
static mobileButton = (opts: DocumentOptions, docs: Doc[]) => Docs.Create.MulticolumnDocument(docs, {
...opts,
- dropAction: undefined, removeDropProperties: new List<string>(["dropAction"]), _nativeWidth: 900, _nativeHeight: 250, _width: 900, _height: 250, _yMargin: 15,
+ _removeDropProperties: new List<string>(["dropAction"]), _nativeWidth: 900, _nativeHeight: 250, _width: 900, _height: 250, _yMargin: 15,
borderRounding: "5px", boxShadow: "0 0", system: true
}) as any as Doc
// sets up the text container for the information contained within the mobile button
static mobileTextContainer = (opts: DocumentOptions, docs: Doc[]) => Docs.Create.MultirowDocument(docs, {
...opts,
- dropAction: undefined, removeDropProperties: new List<string>(["dropAction"]), _nativeWidth: 450, _nativeHeight: 250, _width: 450, _height: 250, _yMargin: 25,
+ _removeDropProperties: new List<string>(["dropAction"]), _nativeWidth: 450, _nativeHeight: 250, _width: 450, _height: 250, _yMargin: 25,
backgroundColor: "rgba(0,0,0,0)", borderRounding: "0", boxShadow: "0 0", ignoreClick: true, system: true
}) as any as Doc
// Sets up the title of the button
static mobileButtonText = (opts: DocumentOptions, buttonTitle: string) => Docs.Create.TextDocument(buttonTitle, {
...opts,
- dropAction: undefined, title: buttonTitle, _fontSize: "37px", _xMargin: 0, _yMargin: 0, ignoreClick: true, backgroundColor: "rgba(0,0,0,0)", system: true
+ title: buttonTitle, _fontSize: "37px", _xMargin: 0, _yMargin: 0, ignoreClick: true, backgroundColor: "rgba(0,0,0,0)", system: true
}) as any as Doc
// Sets up the description of the button
static mobileButtonInfo = (opts: DocumentOptions, buttonInfo: string) => Docs.Create.TextDocument(buttonInfo, {
...opts,
- dropAction: undefined, title: "info", _fontSize: "25px", _xMargin: 0, _yMargin: 0, ignoreClick: true, backgroundColor: "rgba(0,0,0,0)", _dimMagnitude: 2, system: true
+ title: "info", _fontSize: "25px", _xMargin: 0, _yMargin: 0, ignoreClick: true, backgroundColor: "rgba(0,0,0,0)", _dimMagnitude: 2, system: true
}) as any as Doc
@@ -660,11 +661,12 @@ export class CurrentUserUtils {
];
return docProtoData.map(data => Docs.Create.FontIconDocument({
_nativeWidth: 10, _nativeHeight: 10, _width: 10, _height: 10, title: data.title, icon: data.icon,
- dropAction: data.pointerDown ? "copy" : undefined, ignoreClick: data.ignoreClick,
+ _dropAction: data.pointerDown ? "copy" : undefined, ignoreClick: data.ignoreClick,
onDragStart: data.drag ? ScriptField.MakeFunction(data.drag) : undefined,
clipboard: data.clipboard,
onPointerUp: data.pointerUp ? ScriptField.MakeScript(data.pointerUp) : undefined, onPointerDown: data.pointerDown ? ScriptField.MakeScript(data.pointerDown) : undefined,
- backgroundColor: data.backgroundColor, removeDropProperties: new List<string>(["dropAction"]), dragFactory: data.dragFactory, system: true
+ backgroundColor: data.backgroundColor,
+ _removeDropProperties: new List<string>(["dropAction"]), dragFactory: data.dragFactory, system: true
}));
}
@@ -689,13 +691,13 @@ export class CurrentUserUtils {
static setupMobileUploadDoc(userDoc: Doc) {
// const addButton = Docs.Create.FontIconDocument({ onDragStart: ScriptField.MakeScript('addWebToMobileUpload()'), title: "Add Web Doc to Upload Collection", icon: "plus", backgroundColor: "black" })
const webDoc = Docs.Create.WebDocument("https://www.britannica.com/biography/Miles-Davis", {
- title: "Upload Images From the Web", _chromeStatus: "enabled", _lockedPosition: true, system: true
+ title: "Upload Images From the Web", _lockedPosition: true, system: true
});
const uploadDoc = Docs.Create.StackingDocument([], {
- title: "Mobile Upload Collection", backgroundColor: "white", _lockedPosition: true, system: true
+ title: "Mobile Upload Collection", backgroundColor: "white", _lockedPosition: true, system: true, _chromeHidden: true,
});
return Docs.Create.StackingDocument([webDoc, uploadDoc], {
- _width: screen.width, _lockedPosition: true, title: "Upload", _autoHeight: true, _yMargin: 80, backgroundColor: "lightgray", system: true
+ _width: screen.width, _lockedPosition: true, title: "Upload", _autoHeight: true, _yMargin: 80, backgroundColor: "lightgray", system: true, _chromeHidden: true,
});
}
@@ -715,20 +717,21 @@ export class CurrentUserUtils {
if (doc.myCreators === undefined) {
doc.myCreators = new PrefetchProxy(Docs.Create.StackingDocument([creatorBtns, templateBtns], {
title: "all Creators", _yMargin: 0, _autoHeight: true, _xMargin: 0, _fitWidth: true,
- _width: 500, _height: 300, ignoreClick: true, _lockedPosition: true, system: true
+ _width: 500, _height: 300, ignoreClick: true, _lockedPosition: true, system: true, _chromeHidden: true,
}));
}
// setup a color picker
if (doc.myColorPicker === undefined) {
const color = Docs.Create.ColorDocument({
- title: "color picker", _width: 300, dropAction: "alias", _hideContextMenu: true, _stayInCollection: true, _forceActive: true, removeDropProperties: new List<string>(["dropAction", "_stayInCollection", "_hideContextMenu", "forceActive"]), system: true
+ title: "color picker", _width: 220, _dropAction: "alias", _hideContextMenu: true, _stayInCollection: true, _forceActive: true, _removeDropProperties: new List<string>(["dropAction", "_stayInCollection", "_hideContextMenu", "forceActive"]), system: true
});
doc.myColorPicker = new PrefetchProxy(color);
}
if (doc.myTools === undefined) {
const toolsStack = new PrefetchProxy(Docs.Create.StackingDocument([doc.myCreators as Doc, doc.myColorPicker as Doc], {
- title: "My Tools", _width: 500, _yMargin: 20, ignoreClick: true, _lockedPosition: true, _forceActive: true, system: true, _stayInCollection: true, _hideContextMenu: true,
+ title: "My Tools", _width: 500, _yMargin: 20, ignoreClick: true, _lockedPosition: true, _forceActive: true,
+ system: true, _stayInCollection: true, _hideContextMenu: true, _chromeHidden: true,
})) as any as Doc;
doc.myTools = toolsStack;
@@ -856,16 +859,16 @@ export class CurrentUserUtils {
})) as any as Doc
static ficon = (opts: DocumentOptions) => new PrefetchProxy(Docs.Create.FontIconDocument({
- ...opts, dropAction: "alias", removeDropProperties: new List<string>(["dropAction", "stayInCollection"]), _nativeWidth: 40, _nativeHeight: 40, _width: 40, _height: 40, system: true
+ ...opts, _dropAction: "alias", _removeDropProperties: new List<string>(["_dropAction", "stayInCollection"]), _nativeWidth: 40, _nativeHeight: 40, _width: 40, _height: 40, system: true
})) as any as Doc
/// sets up the default list of buttons to be shown in the expanding button menu at the bottom of the Dash window
static setupDockedButtons(doc: Doc) {
if (doc["dockedBtn-undo"] === undefined) {
- doc["dockedBtn-undo"] = CurrentUserUtils.ficon({ onClick: ScriptField.MakeScript("undo()"), dontUndo: true, _stayInCollection: true, dropAction: "alias", _hideContextMenu: true, removeDropProperties: new List<string>(["dropAction", "_hideContextMenu", "stayInCollection"]), toolTip: "click to undo", title: "undo", icon: "undo-alt", system: true });
+ doc["dockedBtn-undo"] = CurrentUserUtils.ficon({ onClick: ScriptField.MakeScript("undo()"), dontUndo: true, _stayInCollection: true, _dropAction: "alias", _hideContextMenu: true, _removeDropProperties: new List<string>(["dropAction", "_hideContextMenu", "stayInCollection"]), toolTip: "click to undo", title: "undo", icon: "undo-alt", system: true });
}
if (doc["dockedBtn-redo"] === undefined) {
- doc["dockedBtn-redo"] = CurrentUserUtils.ficon({ onClick: ScriptField.MakeScript("redo()"), dontUndo: true, _stayInCollection: true, dropAction: "alias", _hideContextMenu: true, removeDropProperties: new List<string>(["dropAction", "_hideContextMenu", "stayInCollection"]), toolTip: "click to redo", title: "redo", icon: "redo-alt", system: true });
+ doc["dockedBtn-redo"] = CurrentUserUtils.ficon({ onClick: ScriptField.MakeScript("redo()"), dontUndo: true, _stayInCollection: true, _dropAction: "alias", _hideContextMenu: true, _removeDropProperties: new List<string>(["dropAction", "_hideContextMenu", "stayInCollection"]), toolTip: "click to redo", title: "redo", icon: "redo-alt", system: true });
}
if (doc.dockedBtns === undefined) {
doc.dockedBtns = CurrentUserUtils.blist({ title: "docked buttons", ignoreClick: true }, [doc["dockedBtn-undo"] as Doc, doc["dockedBtn-redo"] as Doc]);
@@ -906,9 +909,8 @@ export class CurrentUserUtils {
if (!sharedDocs) {
sharedDocs = Docs.Create.StackingDocument([], {
title: "My SharedDocs", childDropAction: "alias", system: true, contentPointerEvents: "none", childLimitHeight: 0, _yMargin: 50, _gridGap: 15,
- _showTitle: "title", ignoreClick: true, _lockedPosition: true,
+ _showTitle: "title", ignoreClick: true, _lockedPosition: true, "acl-Public": SharingPermissions.Add, "_acl-Public": SharingPermissions.Add, _chromeHidden: true,
}, sharingDocumentId + "outer", sharingDocumentId);
- (sharedDocs as Doc)["acl-Public"] = Doc.GetProto(sharedDocs as Doc)["acl-Public"] = SharingPermissions.Add;
}
if (sharedDocs instanceof Doc) {
sharedDocs.userColor = sharedDocs.userColor || "rgb(202, 202, 202)";
@@ -922,13 +924,13 @@ export class CurrentUserUtils {
if (doc.myImportDocs === undefined) {
doc.myImportDocs = new PrefetchProxy(Docs.Create.StackingDocument([], {
title: "My ImportDocuments", _forceActive: true, ignoreClick: true, _showTitle: "title", _stayInCollection: true, _hideContextMenu: true, childLimitHeight: 0,
- childDropAction: "alias", _autoHeight: true, _yMargin: 50, _gridGap: 15, _lockedPosition: true, system: true
+ childDropAction: "alias", _autoHeight: true, _yMargin: 50, _gridGap: 15, _lockedPosition: true, system: true, _chromeHidden: true,
}));
}
if (doc.myImportPanel === undefined) {
const uploads = Cast(doc.myImportDocs, Doc, null);
const newUpload = CurrentUserUtils.ficon({ onClick: ScriptField.MakeScript("importDocument()"), toolTip: "Import External document", _stayInCollection: true, _hideContextMenu: true, title: "Import", icon: "upload", system: true });
- doc.myImportPanel = new PrefetchProxy(Docs.Create.StackingDocument([newUpload, uploads], { title: "My ImportPanel", _yMargin: 20, ignoreClick: true, _stayInCollection: true, _hideContextMenu: true, _lockedPosition: true, system: true }));
+ doc.myImportPanel = new PrefetchProxy(Docs.Create.StackingDocument([newUpload, uploads], { title: "My ImportPanel", _yMargin: 20, ignoreClick: true, _chromeHidden: true, _stayInCollection: true, _hideContextMenu: true, _lockedPosition: true, system: true }));
}
}
diff --git a/src/client/util/DictationManager.ts b/src/client/util/DictationManager.ts
index c6b654dda..a93b2f573 100644
--- a/src/client/util/DictationManager.ts
+++ b/src/client/util/DictationManager.ts
@@ -84,7 +84,13 @@ export namespace DictationManager {
terminators: string[];
}
+ let pendingListen: Promise<string> | string | undefined;
+
export const listen = async (options?: Partial<ListeningOptions>) => {
+ if (pendingListen instanceof Promise) return pendingListen.then(pl => innerListen(options));
+ return innerListen(options);
+ };
+ const innerListen = async (options?: Partial<ListeningOptions>) => {
let results: string | undefined;
const overlay = options?.useOverlay;
@@ -94,7 +100,8 @@ export namespace DictationManager {
}
try {
- results = await listenImpl(options);
+ results = await (pendingListen = listenImpl(options));
+ pendingListen = undefined;
if (results) {
Utils.CopyText(results);
if (overlay) {
@@ -106,6 +113,7 @@ export namespace DictationManager {
options?.tryExecute && await DictationManager.Commands.execute(results);
}
} catch (e) {
+ console.log(e);
if (overlay) {
DictationOverlay.Instance.isListening = false;
DictationOverlay.Instance.dictatedPhrase = results = `dictation error: ${"error" in e ? e.error : "unknown error"}`;
@@ -146,7 +154,8 @@ export namespace DictationManager {
recognizer.onerror = (e: any) => { // e is SpeechRecognitionError but where is that defined?
if (!(indefinite && e.error === "no-speech")) {
recognizer.stop();
- reject(e);
+ resolve(e);
+ //reject(e);
}
};
@@ -158,8 +167,8 @@ export namespace DictationManager {
recognizer.abort();
return complete();
}
- handler && handler(current);
- isManuallyStopped && complete();
+ !isManuallyStopped && handler?.(current);
+ //isManuallyStopped && complete();
};
recognizer.onend = (e: Event) => {
@@ -168,7 +177,7 @@ export namespace DictationManager {
}
if (current) {
- sessionResults.push(current);
+ !isManuallyStopped && sessionResults.push(current);
current = undefined;
}
recognizer.start();
@@ -199,14 +208,7 @@ export namespace DictationManager {
}
isListening = false;
isManuallyStopped = true;
- salvageSession ? recognizer.stop() : recognizer.abort();
- // let main = MainView.Instance;
- // if (main.dictationOverlayVisible) {
- // main.cancelDictationFade();
- // main.dictationOverlayVisible = false;
- // main.dictationSuccess = undefined;
- // setTimeout(() => main.dictatedPhrase = placeholder, 500);
- // }
+ recognizer.stop(); // salvageSession ? recognizer.stop() : recognizer.abort();
};
const synthesize = (e: SpeechRecognitionEvent, delimiter?: string) => {
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index 8cb80ecf9..8b37c9a6e 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -14,6 +14,7 @@ export class DocumentManager {
//global holds all of the nodes (regardless of which collection they're in)
@observable public DocumentViews: DocumentView[] = [];
+ @observable public RecordingEvent = 0;
@observable public LinkedDocumentViews: { a: DocumentView, b: DocumentView, l: Doc }[] = [];
private static _instance: DocumentManager;
@@ -28,8 +29,7 @@ export class DocumentManager {
const whichOtherAnchor = view.props.LayoutTemplateString?.includes("anchor2") ? "anchor1" : "anchor2";
const otherDoc = link && (link[whichOtherAnchor] as Doc);
const otherDocAnno = otherDoc?.type === DocumentType.TEXTANCHOR ? otherDoc.annotationOn as Doc : undefined;
- otherDoc && DocumentManager.Instance.DocumentViews.
- filter(dv => Doc.AreProtosEqual(dv.rootDoc, otherDoc) || Doc.AreProtosEqual(dv.rootDoc, otherDocAnno)).
+ otherDoc && DocumentManager.Instance.DocumentViews?.filter(dv => Doc.AreProtosEqual(dv.rootDoc, otherDoc) || Doc.AreProtosEqual(dv.rootDoc, otherDocAnno)).
forEach(otherView => {
if (otherView.rootDoc.type !== DocumentType.LINK || otherView.props.LayoutTemplateString !== view.props.LayoutTemplateString) {
this.LinkedDocumentViews.push({ a: whichOtherAnchor === "anchor1" ? otherView : view, b: whichOtherAnchor === "anchor1" ? view : otherView, l: link });
@@ -229,7 +229,10 @@ export class DocumentManager {
}
Scripting.addGlobal(function DocFocusOrOpen(doc: any) {
const dv = DocumentManager.Instance.getDocumentView(doc);
- if (dv && dv?.props.Document === doc) dv.props.focus(doc, { willZoom: true });
+ if (dv && dv.props.Document === doc) {
+ dv.props.focus(doc, { willZoom: true });
+ Doc.linkFollowHighlight(dv?.props.Document, false);
+ }
else {
const context = doc.context !== Doc.UserDoc().myFilesystem && Cast(doc.context, Doc, null);
const showDoc = context || doc;
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index dc95193ea..38d0ecaa6 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -303,7 +303,7 @@ export namespace DragManager {
near = pt.pt;
}
});
- return { thisX: near[0], thisY: near[1] };
+ return { x: near[0], y: near[1] };
}
// snap to the active snap lines - if oneAxis is set (eg, for maintaining aspect ratios), then it only snaps to the nearest horizontal/vertical line
export function snapDrag(e: PointerEvent, xFromLeft: number, yFromTop: number, xFromRight: number, yFromBottom: number) {
@@ -320,8 +320,8 @@ export namespace DragManager {
return drag;
};
return {
- thisX: snapVal([xFromLeft, xFromRight], e.pageX, SnappingManager.vertSnapLines()),
- thisY: snapVal([yFromTop, yFromBottom], e.pageY, SnappingManager.horizSnapLines())
+ x: snapVal([xFromLeft, xFromRight], e.pageX, SnappingManager.vertSnapLines()),
+ y: snapVal([yFromTop, yFromBottom], e.pageY, SnappingManager.horizSnapLines())
};
}
export let docsBeingDragged: Doc[] = [];
@@ -344,28 +344,22 @@ export namespace DragManager {
dragDiv.appendChild(dragLabel);
DragManager.Root().appendChild(dragDiv);
}
- dragDiv.style.width = "";
- dragDiv.style.height = "";
- dragDiv.style.overflow = "";
+ Object.assign(dragDiv.style, { width: "", height: "", overflow: "" });
dragDiv.hidden = false;
- const scaleXs: number[] = [];
- const scaleYs: number[] = [];
- const xs: number[] = [];
- const ys: number[] = [];
+ const scaleXs: number[] = [], scaleYs: number[] = [], xs: number[] = [], ys: number[] = [];
docsBeingDragged = dragData instanceof DocumentDragData ? dragData.draggedDocuments : dragData instanceof AnchorAnnoDragData ? [dragData.dragDocument] : [];
const elesCont = {
- left: Number.MAX_SAFE_INTEGER,
- top: Number.MAX_SAFE_INTEGER,
- right: Number.MIN_SAFE_INTEGER,
- bottom: Number.MIN_SAFE_INTEGER
+ left: Number.MAX_SAFE_INTEGER, right: Number.MIN_SAFE_INTEGER,
+ top: Number.MAX_SAFE_INTEGER, bottom: Number.MIN_SAFE_INTEGER
};
const dragElements = eles.map(ele => {
if (!ele.parentNode) dragDiv.appendChild(ele);
const dragElement = ele.parentNode === dragDiv ? ele : ele.cloneNode(true) as HTMLElement;
const rect = ele.getBoundingClientRect();
- const scaleX = rect.width / ele.offsetWidth,
- scaleY = ele.offsetHeight ? rect.height / ele.offsetHeight : scaleX;
+ const scaleX = rect.width / ele.offsetWidth;
+ const scaleY = ele.offsetHeight ? rect.height / ele.offsetHeight : scaleX;
+
elesCont.left = Math.min(rect.left, elesCont.left);
elesCont.top = Math.min(rect.top, elesCont.top);
elesCont.right = Math.max(rect.right, elesCont.right);
@@ -374,44 +368,34 @@ export namespace DragManager {
ys.push(rect.top);
scaleXs.push(scaleX);
scaleYs.push(scaleY);
- dragElement.style.opacity = "0.7";
- dragElement.style.position = "absolute";
- dragElement.style.margin = "0";
- dragElement.style.top = "0";
- dragElement.style.bottom = "";
- dragElement.style.left = "0";
- dragElement.style.color = "black";
- dragElement.style.transition = "none";
- dragElement.style.transformOrigin = "0 0";
- dragElement.style.borderRadius = getComputedStyle(ele).borderRadius;
- dragElement.style.zIndex = globalCssVariables.contextMenuZindex;// "1000";
- dragElement.style.transform = `translate(${rect.left + (options?.offsetX || 0)}px, ${rect.top + (options?.offsetY || 0)}px) scale(${scaleX}, ${scaleY})`;
- dragElement.style.width = `${rect.width / scaleX}px`;
- dragElement.style.height = `${rect.height / scaleY}px`;
+ Object.assign(dragElement.style, {
+ opacity: "0.7", position: "absolute", margin: "0", top: "0", bottom: "", left: "0", color: "black", transition: "none",
+ borderRadius: getComputedStyle(ele).borderRadius, zIndex: globalCssVariables.contextMenuZindex,
+ transformOrigin: "0 0", width: `${rect.width / scaleX}px`, height: `${rect.height / scaleY}px`,
+ transform: `translate(${rect.left + (options?.offsetX || 0)}px, ${rect.top + (options?.offsetY || 0)}px) scale(${scaleX}, ${scaleY})`,
+ });
dragLabel.style.transform = `translate(${rect.left + (options?.offsetX || 0)}px, ${rect.top + (options?.offsetY || 0) - 20}px)`;
if (docsBeingDragged.length) {
const pdfBox = dragElement.getElementsByTagName("canvas");
const pdfBoxSrc = ele.getElementsByTagName("canvas");
Array.from(pdfBox).map((pb, i) => pb.getContext('2d')!.drawImage(pdfBoxSrc[i], 0, 0));
- const pdfView = dragElement.getElementsByClassName("pdfViewer-viewer");
- const pdfViewSrc = ele.getElementsByClassName("pdfViewer-viewer");
- const tops = Array.from(pdfViewSrc).map(p => p.scrollTop);
- const oldopacity = dragElement.style.opacity;
- dragElement.style.opacity = "0";
- setTimeout(() => {
- dragElement.style.opacity = oldopacity;
- Array.from(pdfView).map((v, i) => v.scrollTo({ top: tops[i] }));
- }, 0);
- }
- if (dragElement.hasAttribute("style")) (dragElement as any).style.pointerEvents = "none";
- const set = dragElement.getElementsByTagName('*');
- // tslint:disable-next-line: prefer-for-of
- for (let i = 0; i < set.length; i++) {
- set[i].hasAttribute("style") && ((set[i] as any).style.pointerEvents = "none");
}
+ [dragElement, ...Array.from(dragElement.getElementsByTagName('*'))].forEach(ele =>
+ ele.hasAttribute("style") && ((ele as any).style.pointerEvents = "none"));
dragDiv.appendChild(dragElement);
+ if (dragElement !== ele) {
+ const children = [Array.from(ele.children), Array.from(dragElement.children)];
+ while (children[0].length) {
+ const childs = [children[0].pop(), children[1].pop()];
+ if (childs[0]?.children) {
+ children[0].push(...Array.from(childs[0].children));
+ children[1].push(...Array.from(childs[1]!.children));
+ }
+ if (childs[0]?.scrollTop) childs[1]!.scrollTop = childs[0].scrollTop;
+ }
+ }
return dragElement;
});
@@ -423,13 +407,26 @@ export namespace DragManager {
options?.hideSource && hideDragShowOriginalElements(true);
SnappingManager.SetIsDragging(true);
- let lastX = downX;
- let lastY = downY;
+ let lastPt = { x: downX, y: downY };
const xFromLeft = downX - elesCont.left;
const yFromTop = downY - elesCont.top;
const xFromRight = elesCont.right - downX;
const yFromBottom = elesCont.bottom - downY;
let scrollAwaiter: Opt<NodeJS.Timeout>;
+
+ AbortDrag = () => {
+ options?.dragComplete?.(new DragCompleteEvent(true, dragData));
+ endDrag();
+ };
+
+ const endDrag = action(() => {
+ hideDragShowOriginalElements(false);
+ document.removeEventListener("pointermove", moveHandler, true);
+ document.removeEventListener("pointerup", upHandler);
+ SnappingManager.SetIsDragging(false);
+ SnappingManager.clearSnapLines();
+ batch.end();
+ });
const moveHandler = (e: PointerEvent) => {
e.preventDefault(); // required or dragging text menu link item ends up dragging the link button as native drag/drop
if (dragData instanceof DocumentDragData) {
@@ -503,93 +500,39 @@ export namespace DragManager {
scrollAwaiter = setTimeout(autoScrollHandler, 250);
}
- const { thisX, thisY } = snapDrag(e, xFromLeft, yFromTop, xFromRight, yFromBottom);
+ const { x, y } = snapDrag(e, xFromLeft, yFromTop, xFromRight, yFromBottom);
+ const moveVec = { x: x - lastPt.x, y: y - lastPt.y };
+ lastPt = { x, y };
- const moveX = thisX - lastX;
- const moveY = thisY - lastY;
- lastX = thisX;
- lastY = thisY;
- dragLabel.style.transform = `translate(${xs[0] + moveX + (options?.offsetX || 0)}px, ${ys[0] + moveY + (options?.offsetY || 0) - 20}px)`;
+ dragLabel.style.transform = `translate(${xs[0] + moveVec.x + (options?.offsetX || 0)}px, ${ys[0] + moveVec.y + (options?.offsetY || 0) - 20}px)`;
dragElements.map((dragElement, i) => (dragElement.style.transform =
- `translate(${(xs[i] += moveX) + (options?.offsetX || 0)}px, ${(ys[i] += moveY) + (options?.offsetY || 0)}px) scale(${scaleXs[i]}, ${scaleYs[i]})`)
+ `translate(${(xs[i] += moveVec.x) + (options?.offsetX || 0)}px, ${(ys[i] += moveVec.y) + (options?.offsetY || 0)}px) scale(${scaleXs[i]}, ${scaleYs[i]})`)
);
};
-
- const endDrag = action(() => {
- hideDragShowOriginalElements(false);
- document.removeEventListener("pointermove", moveHandler, true);
- document.removeEventListener("pointerup", upHandler);
- SnappingManager.SetIsDragging(false);
- SnappingManager.clearSnapLines();
- batch.end();
- });
-
- AbortDrag = () => {
- options?.dragComplete?.(new DragCompleteEvent(true, dragData));
- endDrag();
- };
const upHandler = (e: PointerEvent) => {
- const complete = new DragCompleteEvent(false, dragData);
- dispatchDrag(eles, e, complete, xFromLeft, yFromTop, xFromRight, yFromBottom, options, finishDrag);
- options?.dragComplete?.(complete);
+ dispatchDrag(document.elementFromPoint(e.x, e.y) || document.body, e, new DragCompleteEvent(false, dragData), snapDrag(e, xFromLeft, yFromTop, xFromRight, yFromBottom), finishDrag, options);
endDrag();
};
document.addEventListener("pointermove", moveHandler, true);
document.addEventListener("pointerup", upHandler);
}
- function dispatchDrag(dragEles: HTMLElement[], e: PointerEvent, complete: DragCompleteEvent,
- xFromLeft: number, yFromTop: number, xFromRight: number, yFromBottom: number, options?: DragOptions, finishDrag?: (e: DragCompleteEvent) => void) {
- const removed = dragEles.map(dragEle => {
- const ret = { ele: dragEle, w: dragEle.style.width, h: dragEle.style.height, o: dragEle.style.overflow };
- dragEle.style.width = "0";
- dragEle.style.height = "0";
- dragEle.style.overflow = "hidden";
- return ret;
- });
- dragDiv.hidden = true;
- dragDiv.style.width = "0";
- dragDiv.style.height = "0";
- dragDiv.style.overflow = "hidden";
- const target = document.elementFromPoint(e.x, e.y);
- removed.map(r => {
- r.ele.style.width = r.w;
- r.ele.style.height = r.h;
- r.ele.style.overflow = r.o;
- });
- const { thisX, thisY } = snapDrag(e, xFromLeft, yFromTop, xFromRight, yFromBottom);
- if (target) {
- target.dispatchEvent(
- new CustomEvent<DropEvent>("dashPreDrop", {
- bubbles: true,
- detail: {
- x: thisX,
- y: thisY,
- complete: complete,
- shiftKey: e.shiftKey,
- altKey: e.altKey,
- metaKey: e.metaKey,
- ctrlKey: e.ctrlKey,
- embedKey: CanEmbed
- }
- })
- );
- finishDrag?.(complete);
- target.dispatchEvent(
- new CustomEvent<DropEvent>("dashOnDrop", {
- bubbles: true,
- detail: {
- x: thisX,
- y: thisY,
- complete: complete,
- shiftKey: e.shiftKey,
- altKey: e.altKey,
- metaKey: e.metaKey,
- ctrlKey: e.ctrlKey,
- embedKey: CanEmbed
- }
- })
- );
- }
+ function dispatchDrag(target: Element, e: PointerEvent, complete: DragCompleteEvent, pos: { x: number, y: number }, finishDrag?: (e: DragCompleteEvent) => void, options?: DragOptions) {
+ const dropArgs = {
+ bubbles: true,
+ detail: {
+ ...pos,
+ complete,
+ shiftKey: e.shiftKey,
+ altKey: e.altKey,
+ metaKey: e.metaKey,
+ ctrlKey: e.ctrlKey,
+ embedKey: CanEmbed
+ }
+ };
+ target.dispatchEvent(new CustomEvent<DropEvent>("dashPreDrop", dropArgs));
+ finishDrag?.(complete);
+ target.dispatchEvent(new CustomEvent<DropEvent>("dashOnDrop", dropArgs));
+ options?.dragComplete?.(complete);
}
-}
+} \ No newline at end of file
diff --git a/src/client/util/Import & Export/DirectoryImportBox.tsx b/src/client/util/Import & Export/DirectoryImportBox.tsx
index d9f010557..925b74efa 100644
--- a/src/client/util/Import & Export/DirectoryImportBox.tsx
+++ b/src/client/util/Import & Export/DirectoryImportBox.tsx
@@ -145,6 +145,7 @@ export class DirectoryImportBox extends React.Component<FieldViewProps> {
title: `Import of ${directory}`,
_width: 1105,
_height: 500,
+ _chromeHidden: true,
x: NumCast(doc.x),
y: NumCast(doc.y) + offset
};
diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts
index 0512864df..3c3d5c3b8 100644
--- a/src/client/util/LinkManager.ts
+++ b/src/client/util/LinkManager.ts
@@ -1,22 +1,21 @@
-import { runInAction } from "mobx";
import { computedFn } from "mobx-utils";
-import { Doc, DocListCast, Opt } from "../../fields/Doc";
-import { BoolCast, Cast, StrCast } from "../../fields/Types";
+import { Doc, DocListCast, Opt, DirectLinksSym, Field } from "../../fields/Doc";
+import { BoolCast, Cast, StrCast, PromiseValue } from "../../fields/Types";
import { LightboxView } from "../views/LightboxView";
import { DocumentViewSharedProps, ViewAdjustment } from "../views/nodes/DocumentView";
import { DocumentManager } from "./DocumentManager";
import { SharingManager } from "./SharingManager";
import { UndoManager } from "./UndoManager";
+import { observe, observable, reaction } from "mobx";
+import { listSpec } from "../../fields/Schema";
+import { List } from "../../fields/List";
+import { ProxyField } from "../../fields/Proxy";
type CreateViewFunc = (doc: Doc, followLinkLocation: string, finished?: () => void) => void;
/*
* link doc:
- * - anchor1: doc
- * - anchor1page: number
- * - anchor1groups: list of group docs representing the groups anchor1 categorizes this link/anchor2 in
+ * - anchor1: doc
* - anchor2: doc
- * - anchor2page: number
- * - anchor2groups: list of group docs representing the groups anchor2 categorizes this link/anchor1 in
*
* group doc:
* - type: string representing the group type/name/category
@@ -27,38 +26,84 @@ type CreateViewFunc = (doc: Doc, followLinkLocation: string, finished?: () => vo
*/
export class LinkManager {
- private static _instance: LinkManager;
+ @observable static _instance: LinkManager;
+ @observable static userDocs: Doc[] = [];
public static currentLink: Opt<Doc>;
- public static get Instance(): LinkManager { return this._instance || (this._instance = new this()); }
+ public static get Instance() { return LinkManager._instance; }
+ constructor() {
+ LinkManager._instance = this;
+ setTimeout(() => {
+ LinkManager.userDocs = [Doc.LinkDBDoc().data as Doc, ...SharingManager.Instance.users.map(user => user.linkDatabase)];
+ const addLinkToDoc = (link: Doc): any => {
+ const a1 = link?.anchor1;
+ const a2 = link?.anchor2;
+ if (a1 instanceof Promise || a2 instanceof Promise) return PromiseValue(a1).then(a1 => PromiseValue(a2).then(a2 => addLinkToDoc(link)));
+ if (a1 instanceof Doc && a2 instanceof Doc && ((a1.author !== undefined && a2.author !== undefined) || link.author === Doc.CurrentUserEmail)) {
+ Doc.GetProto(a1)[DirectLinksSym].add(link);
+ Doc.GetProto(a2)[DirectLinksSym].add(link);
+ Doc.GetProto(link)[DirectLinksSym].add(link);
+ }
+ };
+ const remLinkFromDoc = (link: Doc): any => {
+ const a1 = link?.anchor1;
+ const a2 = link?.anchor2;
+ if (a1 instanceof Promise || a2 instanceof Promise) return PromiseValue(a1).then(a1 => PromiseValue(a2).then(a2 => remLinkFromDoc(link)));
+ if (a1 instanceof Doc && a2 instanceof Doc && ((a1.author !== undefined && a2.author !== undefined) || link.author === Doc.CurrentUserEmail)) {
+ Doc.GetProto(a1)[DirectLinksSym].delete(link);
+ Doc.GetProto(a2)[DirectLinksSym].delete(link);
+ Doc.GetProto(link)[DirectLinksSym].delete(link);
+ }
+ };
+ const watchUserLinks = (userLinks: List<Doc>) => {
+ 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
+ observe(userLinks, change => {
+ switch (change.type as any) {
+ case "splice":
+ (change as any).added.forEach((link: any) => addLinkToDoc(toRealField(link)));
+ (change as any).removed.forEach((link: any) => remLinkFromDoc(toRealField(link)));
+ break;
+ case "update": //let oldValue = change.oldValue;
+ }
+ }, true);
+ };
+ observe(LinkManager.userDocs, change => {
+ switch (change.type as any) {
+ case "splice": (change as any).added.forEach(watchUserLinks); break;
+ case "update": //let oldValue = change.oldValue;
+ }
+ }, true);
+ });
+ }
- public addLink(linkDoc: Doc) { return Doc.AddDocToList(Doc.LinkDBDoc(), "data", linkDoc); }
+ public addLink(linkDoc: Doc) {
+ return Doc.AddDocToList(Doc.LinkDBDoc(), "data", linkDoc);
+ }
public deleteLink(linkDoc: Doc) { return Doc.RemoveDocFromList(Doc.LinkDBDoc(), "data", linkDoc); }
public deleteAllLinksOnAnchor(anchor: Doc) { LinkManager.Instance.relatedLinker(anchor).forEach(linkDoc => LinkManager.Instance.deleteLink(linkDoc)); }
public getAllRelatedLinks(anchor: Doc) { return this.relatedLinker(anchor); } // finds all links that contain the given anchor
- public getAllDirectLinks(anchor: Doc): Doc[] { return this.directLinker(anchor); } // finds all links that contain the given anchor
- public getAllLinks(): Doc[] { return this.allLinks(); }
+ public getAllDirectLinks(anchor: Doc): Doc[] {
+ return Array.from(Doc.GetProto(anchor)[DirectLinksSym]);
+ } // finds all links that contain the given anchor
+ public getAllLinks(): Doc[] { return []; }//this.allLinks(); }
- allLinks = computedFn(function allLinks(this: any): Doc[] {
- const linkData = Doc.LinkDBDoc().data;
- const lset = new Set<Doc>(DocListCast(linkData));
- SharingManager.Instance.users.forEach(user => DocListCast(user.linkDatabase?.data).forEach(doc => lset.add(doc)));
- return Array.from(lset);
- }, true);
-
- directLinker = computedFn(function directLinker(this: any, anchor: Doc): Doc[] {
- return LinkManager.Instance.allLinks().filter(link => {
- const a1 = Cast(link?.anchor1, Doc, null);
- const a2 = Cast(link?.anchor2, Doc, null);
- return link && ((a1?.author !== undefined && a2?.author !== undefined) || link.author === Doc.CurrentUserEmail) && (Doc.AreProtosEqual(anchor, a1) || Doc.AreProtosEqual(anchor, a2) || Doc.AreProtosEqual(link, anchor));
- });
- }, true);
+ // allLinks = computedFn(function allLinks(this: any): Doc[] {
+ // const linkData = Doc.LinkDBDoc().data;
+ // const lset = new Set<Doc>(DocListCast(linkData));
+ // SharingManager.Instance.users.forEach(user => DocListCast(user.linkDatabase?.data).forEach(doc => lset.add(doc)));
+ // LinkManager.Instance.allLinks().filter(link => {
+ // const a1 = Cast(link?.anchor1, Doc, null);
+ // const a2 = Cast(link?.anchor2, Doc, null);
+ // return link && ((a1?.author !== undefined && a2?.author !== undefined) || link.author === Doc.CurrentUserEmail) && (Doc.AreProtosEqual(anchor, a1) || Doc.AreProtosEqual(anchor, a2) || Doc.AreProtosEqual(link, anchor));
+ // });
+ // return Array.from(lset);
+ // }, true);
relatedLinker = computedFn(function relatedLinker(this: any, anchor: Doc): Doc[] {
const lfield = Doc.LayoutFieldKey(anchor);
return DocListCast(anchor[lfield + "-annotations"]).concat(DocListCast(anchor[lfield + "-annotations-timeline"])).reduce((list, anno) =>
[...list, ...LinkManager.Instance.relatedLinker(anno)],
- LinkManager.Instance.directLinker(anchor).slice());
+ Array.from(Doc.GetProto(anchor)[DirectLinksSym]).slice());// LinkManager.Instance.directLinker(anchor).slice());
}, true);
// returns map of group type to anchor's links in that group type
@@ -77,13 +122,6 @@ export class LinkManager {
return anchorGroups;
}
- // checks if a link with the given anchors exists
- public doesLinkExist(anchor1: Doc, anchor2: Doc): boolean {
- return -1 !== LinkManager.Instance.allLinks().findIndex(linkDoc =>
- (Doc.AreProtosEqual(Cast(linkDoc.anchor1, Doc, null), anchor1) && Doc.AreProtosEqual(Cast(linkDoc.anchor2, Doc, null), anchor2)) ||
- (Doc.AreProtosEqual(Cast(linkDoc.anchor1, Doc, null), anchor2) && Doc.AreProtosEqual(Cast(linkDoc.anchor2, Doc, null), anchor1)));
- }
-
// 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
@@ -99,14 +137,14 @@ export class LinkManager {
// follows a link - if the target is on screen, it highlights/pans to it.
- // if the target isn't onscreen, then it will open up the target in a tab, on the right, or in place
+ // if the target isn't onscreen, then it will open up the target in the lightbox, or in place
// depending on the followLinkLocation property of the source (or the link itself as a fallback);
- public static FollowLink = (linkDoc: Opt<Doc>, sourceDoc: Doc, docViewProps: DocumentViewSharedProps, altKey: boolean) => {
+ public static FollowLink = (linkDoc: Opt<Doc>, sourceDoc: Doc, docViewProps: DocumentViewSharedProps, altKey: boolean, zoom: boolean = false) => {
const batch = UndoManager.StartBatch("follow link click");
// open up target if it's not already in view ...
const createViewFunc = (doc: Doc, followLoc: string, finished?: Opt<() => void>) => {
const createTabForTarget = (didFocus: boolean) => new Promise<ViewAdjustment>(res => {
- const where = LightboxView.LightboxDoc ? "lightbox" : StrCast(sourceDoc.followLinkLocation) || followLoc;
+ const where = LightboxView.LightboxDoc ? "lightbox" : StrCast(sourceDoc.followLinkLocation, followLoc);
docViewProps.addDocTab(doc, where);
setTimeout(() => {
const targDocView = DocumentManager.Instance.getFirstDocumentView(doc);
@@ -132,7 +170,7 @@ export class LinkManager {
docViewProps.focus(sourceDoc, { willZoom: BoolCast(sourceDoc.followLinkZoom, true), scale: 1, afterFocus: createTabForTarget });
}
};
- LinkManager.traverseLink(linkDoc, sourceDoc, createViewFunc, BoolCast(sourceDoc.followLinkZoom, false), docViewProps.ContainingCollectionDoc, batch.end, altKey ? true : undefined);
+ LinkManager.traverseLink(linkDoc, sourceDoc, createViewFunc, BoolCast(sourceDoc.followLinkZoom, zoom), docViewProps.ContainingCollectionDoc, batch.end, altKey ? true : undefined);
}
public static traverseLink(link: Opt<Doc>, sourceDoc: Doc, createViewFunc: CreateViewFunc, zoom = false, currentContext?: Doc, finished?: () => void, traverseBacklink?: boolean) {
@@ -159,7 +197,7 @@ export class LinkManager {
const containerDoc = Cast(target.annotationOn, Doc, null) || target;
const targetContext = Cast(containerDoc?.context, Doc, null);
const targetNavContext = !Doc.AreProtosEqual(targetContext, currentContext) ? targetContext : undefined;
- DocumentManager.Instance.jumpToDocument(target, zoom, (doc, finished) => createViewFunc(doc, StrCast(linkDoc.followLinkLocation, "add:right"), finished), targetNavContext, linkDoc, undefined, sourceDoc, finished);
+ DocumentManager.Instance.jumpToDocument(target, zoom, (doc, finished) => createViewFunc(doc, StrCast(linkDoc.followLinkLocation, "lightbox"), finished), targetNavContext, linkDoc, undefined, sourceDoc, finished);
}
} else {
finished?.();