diff options
Diffstat (limited to 'src/client/util')
-rw-r--r-- | src/client/util/CurrentUserUtils.ts | 64 | ||||
-rw-r--r-- | src/client/util/DictationManager.ts | 28 | ||||
-rw-r--r-- | src/client/util/DocumentManager.ts | 9 | ||||
-rw-r--r-- | src/client/util/DragManager.ts | 193 | ||||
-rw-r--r-- | src/client/util/Import & Export/DirectoryImportBox.tsx | 1 | ||||
-rw-r--r-- | src/client/util/LinkManager.ts | 118 |
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?.(); |