aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/client/util/LinkFollower.ts14
-rw-r--r--src/client/util/SnappingManager.ts15
-rw-r--r--src/client/views/DocumentDecorations.tsx20
-rw-r--r--src/client/views/nodes/formattedText/RichTextRules.ts11
-rw-r--r--src/fields/Doc.ts6
5 files changed, 39 insertions, 27 deletions
diff --git a/src/client/util/LinkFollower.ts b/src/client/util/LinkFollower.ts
index 146eed6c2..2df4d1ca8 100644
--- a/src/client/util/LinkFollower.ts
+++ b/src/client/util/LinkFollower.ts
@@ -10,6 +10,7 @@ import { LinkManager } from './LinkManager';
import { ScriptingGlobals } from './ScriptingGlobals';
import { SelectionManager } from './SelectionManager';
import { UndoManager } from './UndoManager';
+import { SnappingManager } from './SnappingManager';
/*
* link doc:
* - link_anchor_1: doc
@@ -23,19 +24,18 @@ import { UndoManager } from './UndoManager';
* - user defined kvps
*/
export class LinkFollower {
- @observable public static IsFollowing = false;
// 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 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, altKey: boolean) => {
const batch = UndoManager.StartBatch('Follow Link');
- runInAction(() => (LinkFollower.IsFollowing = true)); // turn off decoration bounds while following links since animations may occur, and DocDecorations is based on screenToLocal which is not always an observable value
+ runInAction(() => SnappingManager.SetIsLinkFollowing(true)); // turn off decoration bounds while following links since animations may occur, and DocDecorations is based on screenToLocal which is not always an observable value
return LinkFollower.traverseLink(
linkDoc,
sourceDoc,
action(() => {
batch.end();
- Doc.AddUnHighlightWatcher(action(() => (LinkFollower.IsFollowing = false)));
+ Doc.AddUnHighlightWatcher(() => SnappingManager.SetIsLinkFollowing(false));
}),
altKey ? true : undefined
);
@@ -63,10 +63,10 @@ export class LinkFollower {
sourceDoc === linkDoc.link_anchor_1
? linkDoc.link_anchor_2
: sourceDoc === linkDoc.link_anchor_2
- ? linkDoc.link_anchor_1
- : Doc.AreProtosEqual(sourceDoc, linkDoc.link_anchor_1 as Doc) || Doc.AreProtosEqual((linkDoc.link_anchor_1 as Doc).annotationOn as Doc, sourceDoc)
- ? linkDoc.link_anchor_2
- : linkDoc.link_anchor_1
+ ? linkDoc.link_anchor_1
+ : Doc.AreProtosEqual(sourceDoc, linkDoc.link_anchor_1 as Doc) || Doc.AreProtosEqual((linkDoc.link_anchor_1 as Doc).annotationOn as Doc, sourceDoc)
+ ? linkDoc.link_anchor_2
+ : linkDoc.link_anchor_1
) as Doc;
const srcAnchor = LinkManager.getOppositeAnchor(linkDoc, target) ?? sourceDoc;
if (target) {
diff --git a/src/client/util/SnappingManager.ts b/src/client/util/SnappingManager.ts
index c4d299fa1..40c3f76fb 100644
--- a/src/client/util/SnappingManager.ts
+++ b/src/client/util/SnappingManager.ts
@@ -9,6 +9,7 @@ export class SnappingManager {
@observable _shiftKey = false;
@observable _ctrlKey = false;
+ @observable _isLinkFollowing = false;
@observable _isDragging: boolean = false;
@observable _isResizing: Doc | undefined = undefined;
@observable _canEmbed: boolean = false;
@@ -31,14 +32,16 @@ export class SnappingManager {
public static get VertSnapLines() { return this.Instance._vertSnapLines; } // prettier-ignore
public static get ShiftKey() { return this.Instance._shiftKey; } // prettier-ignore
public static get CtrlKey() { return this.Instance._ctrlKey; } // prettier-ignore
+ public static get IsLinkFollowing(){ return this.Instance._isLinkFollowing; } // prettier-ignore
public static get IsDragging() { return this.Instance._isDragging; } // prettier-ignore
public static get IsResizing() { return this.Instance._isResizing; } // prettier-ignore
public static get CanEmbed() { return this.Instance._canEmbed; } // prettier-ignore
public static get ExploreMode() { return this.Instance._exploreMode; } // prettier-ignore
- public static SetShiftKey = (down: boolean) => runInAction(() => (this.Instance._shiftKey = down)); // prettier-ignore
- public static SetCtrlKey = (down: boolean) => runInAction(() => (this.Instance._ctrlKey = down)); // prettier-ignore
- public static SetIsDragging = (drag: boolean) => runInAction(() => (this.Instance._isDragging = drag)); // prettier-ignore
- public static SetIsResizing = (doc: Opt<Doc>) => runInAction(() => (this.Instance._isResizing = doc)); // prettier-ignore
- public static SetCanEmbed = (embed:boolean) => runInAction(() => (this.Instance._canEmbed = embed)); // prettier-ignore
- public static SetExploreMode= (state:boolean) => runInAction(() => (this.Instance._exploreMode = state)); // prettier-ignore
+ public static SetShiftKey = (down: boolean) => runInAction(() => (this.Instance._shiftKey = down)); // prettier-ignore
+ public static SetCtrlKey = (down: boolean) => runInAction(() => (this.Instance._ctrlKey = down)); // prettier-ignore
+ public static SetIsLinkFollowing= (follow: boolean) => runInAction(() => (this.Instance._isLinkFollowing = follow)); // prettier-ignore
+ public static SetIsDragging = (drag: boolean) => runInAction(() => (this.Instance._isDragging = drag)); // prettier-ignore
+ public static SetIsResizing = (doc: Opt<Doc>) => runInAction(() => (this.Instance._isResizing = doc)); // prettier-ignore
+ public static SetCanEmbed = (embed:boolean) => runInAction(() => (this.Instance._canEmbed = embed)); // prettier-ignore
+ public static SetExploreMode = (state:boolean) => runInAction(() => (this.Instance._exploreMode = state)); // prettier-ignore
}
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index ced8799bf..788e78ed2 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -3,7 +3,9 @@ import { Tooltip } from '@mui/material';
import { IconButton } from 'browndash-components';
import { action, computed, makeObservable, observable, runInAction } from 'mobx';
import { observer } from 'mobx-react';
+import * as React from 'react';
import { FaUndo } from 'react-icons/fa';
+import { Utils, emptyFunction, lightOrDark, numberValue, returnFalse, setupMoveUpEvents } from '../../Utils';
import { DateField } from '../../fields/DateField';
import { Doc, DocListCast, Field, HierarchyMapping, ReverseHierarchyMap } from '../../fields/Doc';
import { AclAdmin, AclAugment, AclEdit } from '../../fields/DocSymbols';
@@ -12,9 +14,8 @@ import { RichTextField } from '../../fields/RichTextField';
import { ScriptField } from '../../fields/ScriptField';
import { BoolCast, Cast, DocCast, NumCast, StrCast } from '../../fields/Types';
import { GetEffectiveAcl } from '../../fields/util';
-import { emptyFunction, lightOrDark, numberValue, returnFalse, setupMoveUpEvents, Utils } from '../../Utils';
-import { Docs } from '../documents/Documents';
import { DocumentType } from '../documents/DocumentTypes';
+import { Docs } from '../documents/Documents';
import { DocumentManager } from '../util/DocumentManager';
import { DragManager } from '../util/DragManager';
import { LinkFollower } from '../util/LinkFollower';
@@ -22,19 +23,18 @@ import { SelectionManager } from '../util/SelectionManager';
import { SettingsManager } from '../util/SettingsManager';
import { SnappingManager } from '../util/SnappingManager';
import { UndoManager } from '../util/UndoManager';
-import { CollectionDockingView } from './collections/CollectionDockingView';
-import { CollectionFreeFormView } from './collections/collectionFreeForm';
import { DocumentButtonBar } from './DocumentButtonBar';
import './DocumentDecorations.scss';
-import { Colors } from './global/globalEnums';
-import { InkingStroke } from './InkingStroke';
import { InkStrokeProperties } from './InkStrokeProperties';
+import { InkingStroke } from './InkingStroke';
import { LightboxView } from './LightboxView';
+import { ObservableReactComponent } from './ObservableReactComponent';
+import { CollectionDockingView } from './collections/CollectionDockingView';
+import { CollectionFreeFormView } from './collections/collectionFreeForm';
+import { Colors } from './global/globalEnums';
import { DocumentView, OpenWhereMod } from './nodes/DocumentView';
-import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox';
import { ImageBox } from './nodes/ImageBox';
-import * as React from 'react';
-import { ObservableReactComponent } from './ObservableReactComponent';
+import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox';
interface DocumentDecorationsProps {
PanelWidth: number;
@@ -97,7 +97,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
}
@computed get Bounds() {
- return (LinkFollower.IsFollowing || SnappingManager.ExploreMode) ?
+ return (SnappingManager.IsLinkFollowing || SnappingManager.ExploreMode) ?
{ x: 0, y: 0, r: 0, b: 0 }
: SelectionManager.Views
.filter(dv => dv._props.renderDepth > 0)
diff --git a/src/client/views/nodes/formattedText/RichTextRules.ts b/src/client/views/nodes/formattedText/RichTextRules.ts
index 701ee4053..d4bd18948 100644
--- a/src/client/views/nodes/formattedText/RichTextRules.ts
+++ b/src/client/views/nodes/formattedText/RichTextRules.ts
@@ -265,9 +265,16 @@ export class RichTextRules {
this.TextBox.EditorView?.dispatch(fstate.tr.setSelection(new TextSelection(fstate.doc.resolve(selection))));
}
};
+ const getTitledDoc = (docTitle: string) => {
+ if (!DocServer.FindDocByTitle(docTitle)) {
+ Doc.AddToMyPublished(Docs.Create.TextDocument('', { title: docTitle, _width: 400, _layout_autoHeight: true }));
+ }
+ const titledDoc = DocServer.FindDocByTitle(docTitle);
+ return titledDoc ? Doc.BestEmbedding(titledDoc) : titledDoc;
+ };
if (!fieldKey) {
if (docTitle) {
- const target = DocServer.FindDocByTitle(docTitle);
+ const target = getTitledDoc(docTitle);
if (target) {
setTimeout(() => linkToDoc(target));
return state.tr.deleteRange(end - 1, end).deleteRange(start, start + 3);
@@ -279,7 +286,7 @@ export class RichTextRules {
const num = value.match(/^[0-9.]$/);
this.Document[DocData][fieldKey] = value === 'true' ? true : value === 'false' ? false : num ? Number(value) : value;
}
- const target = DocServer.FindDocByTitle(docTitle);
+ const target = getTitledDoc(docTitle);
const fieldView = state.schema.nodes.dashField.create({ fieldKey, docId: target?.[Id], hideKey: false });
return state.tr.setSelection(new TextSelection(state.doc.resolve(start), state.doc.resolve(end))).replaceSelectionWith(fieldView, true);
}),
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts
index 9dc3c173d..d726f7064 100644
--- a/src/fields/Doc.ts
+++ b/src/fields/Doc.ts
@@ -574,8 +574,10 @@ export namespace Doc {
}
export function BestEmbedding(doc: Doc) {
- const bestEmbedding = Doc.GetProto(doc) ? [doc, ...DocListCast(doc.proto_embeddings)].find(doc => !doc.embedContainer && doc.author === Doc.CurrentUserEmail) : doc;
- bestEmbedding && Doc.AddDocToList(Doc.GetProto(doc), 'protoEmbeddings', doc);
+ const dataDoc = doc[DocData];
+ const availableEmbeddings = DocListCast(dataDoc.proto_embeddings);
+ const bestEmbedding = [...(dataDoc !== doc ? [doc] : []), ...availableEmbeddings].find(doc => !doc.embedContainer && doc.author === Doc.CurrentUserEmail);
+ bestEmbedding && Doc.AddDocToList(dataDoc, 'protoEmbeddings', doc);
return bestEmbedding ?? Doc.MakeEmbedding(doc);
}