aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/documents/Documents.ts2
-rw-r--r--src/client/util/CurrentUserUtils.ts2
-rw-r--r--src/client/util/DragManager.ts31
-rw-r--r--src/client/views/DocumentDecorations.tsx4
-rw-r--r--src/client/views/MarqueeAnnotator.tsx30
-rw-r--r--src/client/views/StyleProvider.tsx5
-rw-r--r--src/client/views/collections/CollectionMasonryViewFieldRow.tsx6
-rw-r--r--src/client/views/collections/CollectionSubView.tsx13
-rw-r--r--src/client/views/collections/TreeView.tsx2
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx23
-rw-r--r--src/client/views/nodes/DocumentLinksButton.tsx8
-rw-r--r--src/client/views/nodes/DocumentView.tsx19
-rw-r--r--src/client/views/nodes/ImageBox.tsx11
-rw-r--r--src/client/views/nodes/VideoBox.tsx11
-rw-r--r--src/client/views/nodes/WebBox.tsx11
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBox.tsx45
-rw-r--r--src/client/views/pdf/AnchorMenu.tsx4
-rw-r--r--src/fields/Doc.ts6
18 files changed, 106 insertions, 127 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 3791dbc5c..3f03d39da 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -658,7 +658,7 @@ export namespace Docs {
viewDoc["acl-Public"] = dataDoc["acl-Public"] = Doc.UserDoc()?.defaultAclPrivate ? SharingPermissions.None : SharingPermissions.Add;
viewDoc["acl-Override"] = dataDoc["acl-Override"] = "None";
- !Doc.IsSystem(dataDoc) && proto.type !== DocumentType.PDFANNO && proto.type !== DocumentType.LINK && proto.type !== DocumentType.LINKANCHOR &&
+ !Doc.IsSystem(dataDoc) && ![DocumentType.PDFANNO, DocumentType.LINK, DocumentType.LINKANCHOR, DocumentType.TEXTANCHOR].includes(proto.type as any) &&
!protoProps.annotationOn && Doc.AddDocToList(Cast(Doc.UserDoc().myFileOrphans, Doc, null), "data", dataDoc);
return Doc.assign(viewDoc, delegateProps, true);
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 3304de9a1..cd9905be6 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -428,7 +428,7 @@ export class CurrentUserUtils {
((doc.emptyAudio as Doc).proto as Doc)["dragFactory-count"] = 0;
}
if (doc.emptyNote === undefined) {
- doc.emptyNote = Docs.Create.TextDocument("", { _width: 200, title: "text note", system: true, cloneFieldFilter: new List<string>(["system"]) });
+ doc.emptyNote = Docs.Create.TextDocument("", { _width: 200, title: "text note", _autoHeight: true, system: true, cloneFieldFilter: new List<string>(["system"]) });
((doc.emptyNote as Doc).proto as Doc)["dragFactory-count"] = 0;
}
if (doc.emptyImage === undefined) {
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 9baefd247..437fea0ea 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -138,13 +138,13 @@ export namespace DragManager {
isSelectionMove?: boolean; // indicates that an explicitly selected Document is being dragged. this will suppress onDragStart scripts
}
export class LinkDragData {
- constructor(linkSourceDoc: Doc) {
- this.linkSourceDocument = linkSourceDoc;
+ constructor(dragDoc: Doc, linkSourceGetAnchor: () => Doc) {
+ this.dragDocument = dragDoc;
+ this.linkSourceGetAnchor = linkSourceGetAnchor;
}
- droppedDocuments: Doc[] = [];
- linkSourceDocument: Doc;
- dontClearTextBox?: boolean;
- linkDropCallback?: (data: { linkDocument: Doc }) => void;
+ dragDocument: Doc;
+ linkSourceGetAnchor: () => Doc;
+ linkSourceDoc?: Doc;
}
export class ColumnDragData {
constructor(colKey: SchemaHeaderField) {
@@ -154,23 +154,18 @@ export namespace DragManager {
}
// used by PDFs,Text,Image,Video,Web to conditionally (if the drop completes) create a text annotation when dragging the annotate button from the AnchorMenu when a text/region selection has been made.
// this is pretty clunky and should be rethought out using linkDrag or DocumentDrag
- export class AnchorAnnoDragData {
- constructor(dragDoc: Doc, annotationDocCreator: () => Doc, dropDocCreator: (annotationOn?: Doc) => Doc) {
- this.dragDocument = dragDoc;
+ export class AnchorAnnoDragData extends LinkDragData {
+ constructor(dragDoc: Doc, linkSourceGetAnchor: () => Doc, dropDocCreator: (annotationOn: Doc | undefined) => Doc) {
+ super(dragDoc, linkSourceGetAnchor);
this.dropDocCreator = dropDocCreator;
- this.annotationDocCreator = annotationDocCreator;
this.offset = [0, 0];
}
- targetContext: Doc | undefined;
- dragDocument: Doc;
- annotationDocCreator: () => Doc;
- dropDocCreator: (asAnnotation?: Doc) => Doc;
+ linkSourceDoc?: Doc;
+ dropDocCreator: (annotationOn: Doc | undefined) => Doc;
dropDocument?: Doc;
- annotationDocument?: Doc;
offset: number[];
dropAction: dropActionType;
userDropAction: dropActionType;
- linkDropCallback?: (data: { linkDocument: Doc }) => void;
}
export function MakeDropTarget(
@@ -258,8 +253,8 @@ export namespace DragManager {
}
// drags a linker button and creates a link on drop
- export function StartLinkDrag(ele: HTMLElement, sourceDoc: Doc, downX: number, downY: number, options?: DragOptions) {
- StartDrag([ele], new DragManager.LinkDragData(sourceDoc), downX, downY, options);
+ export function StartLinkDrag(ele: HTMLElement, sourceDoc: Doc, sourceDocGetAnchor: undefined | (() => Doc), downX: number, downY: number, options?: DragOptions) {
+ StartDrag([ele], new DragManager.LinkDragData(sourceDoc, () => sourceDocGetAnchor?.() ?? sourceDoc), downX, downY, options);
}
// drags a column from a schema view
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 92f5b79bd..357bff36d 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -414,8 +414,8 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b
if (e.ctrlKey && !Doc.NativeHeight(docView.props.Document)) docView.toggleNativeDimensions();
if (dX !== 0 || dY !== 0 || dW !== 0 || dH !== 0) {
const doc = Document(docView.rootDoc);
- let nwidth = docView.nativeWidth;
- let nheight = docView.nativeHeight;
+ const nwidth = docView.nativeWidth;
+ const nheight = docView.nativeHeight;
const width = (doc._width || 0);
let height = (doc._height || (nheight / nwidth * width));
height = !height || isNaN(height) ? 20 : height;
diff --git a/src/client/views/MarqueeAnnotator.tsx b/src/client/views/MarqueeAnnotator.tsx
index 1fb87f522..f03e1dd9d 100644
--- a/src/client/views/MarqueeAnnotator.tsx
+++ b/src/client/views/MarqueeAnnotator.tsx
@@ -64,27 +64,24 @@ export class MarqueeAnnotator extends React.Component<MarqueeAnnotatorProps> {
* This function is used by the AnchorMenu to create an anchor highlight and a new linked text annotation.
* It also initiates a Drag/Drop interaction to place the text annotation.
*/
- AnchorMenu.Instance.StartDrag = action(async (e: PointerEvent, ele: HTMLElement) => {
+ AnchorMenu.Instance.StartDrag = action((e: PointerEvent, ele: HTMLElement) => {
e.preventDefault();
e.stopPropagation();
- const targetCreator = (asAnnotation?: Doc) => {
- const target = CurrentUserUtils.GetNewTextDoc("Note linked to " + this.props.rootDoc.title, 0, 0, 100, 100, undefined, asAnnotation);
- FormattedTextBox.SelectOnLoad = target[Id];
- return target;
- };
- const anchorCreator = () => {
- const annoDoc = this.highlight("rgba(173, 216, 230, 0.75)"); // hyperlink color
- annoDoc.isLinkButton = true; // prevents link button from showing up --- maybe not a good thing?
+ const sourceAnchorCreator = () => {
+ const annoDoc = this.highlight("rgba(173, 216, 230, 0.75)", true); // hyperlink color
this.props.addDocument(annoDoc);
return annoDoc;
};
- DragManager.StartAnchorAnnoDrag([ele], new DragManager.AnchorAnnoDragData(this.props.rootDoc, anchorCreator, targetCreator), e.pageX, e.pageY, {
+ const targetCreator = (annotationOn: Doc | undefined) => {
+ const target = CurrentUserUtils.GetNewTextDoc("Note linked to " + this.props.rootDoc.title, 0, 0, 100, 100, undefined, annotationOn);
+ FormattedTextBox.SelectOnLoad = target[Id];
+ return target;
+ };
+ DragManager.StartAnchorAnnoDrag([ele], new DragManager.AnchorAnnoDragData(this.props.rootDoc, sourceAnchorCreator, targetCreator), e.pageX, e.pageY, {
dragComplete: e => {
- if (!e.aborted && e.annoDragData && e.annoDragData.annotationDocument && e.annoDragData.dropDocument && !e.linkDocument) {
- e.linkDocument = DocUtils.MakeLink({ doc: e.annoDragData.annotationDocument }, { doc: e.annoDragData.dropDocument }, "Annotation");
- e.annoDragData.annotationDocument.isPushpin = e.annoDragData?.dropDocument.annotationOn === this.props.rootDoc;
+ if (!e.aborted && e.annoDragData && e.annoDragData.linkSourceDoc && e.annoDragData.dropDocument && e.linkDocument) {
+ e.annoDragData.linkSourceDoc.isPushpin = e.annoDragData.dropDocument.annotationOn === this.props.rootDoc;
}
- e.linkDocument && e.annoDragData?.linkDropCallback?.(e as { linkDocument: Doc });// bcz: typescript can't figure out that this is valid even though we tested e.linkDocument
}
});
});
@@ -141,11 +138,12 @@ export class MarqueeAnnotator extends React.Component<MarqueeAnnotatorProps> {
}
}
@action
- highlight = (color: string) => {
+ highlight = (color: string, isLinkButton: boolean) => {
// creates annotation documents for current highlights
const effectiveAcl = GetEffectiveAcl(this.props.rootDoc[DataSym]);
const annotationDoc = [AclAddonly, AclEdit, AclAdmin].includes(effectiveAcl) && this.makeAnnotationDocument(color);
annotationDoc && this.props.addDocument(annotationDoc);
+ annotationDoc && (annotationDoc.isLinkButton = isLinkButton);
return annotationDoc as Doc ?? undefined;
}
@@ -197,7 +195,7 @@ export class MarqueeAnnotator extends React.Component<MarqueeAnnotatorProps> {
AnchorMenu.Instance.jumpTo(e.clientX, e.clientY);
if (AnchorMenu.Instance.Highlighting) {// when highlighter has been toggled when menu is pinned, we auto-highlight immediately on mouse up
- this.highlight("rgba(245, 230, 95, 0.75)"); // yellowish highlight color for highlighted text (should match AnchorMenu's highlight color)
+ this.highlight("rgba(245, 230, 95, 0.75)", false); // yellowish highlight color for highlighted text (should match AnchorMenu's highlight color)
}
} else {
runInAction(() => this._width = this._height = 0);
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index e5b2a332a..5a2fb285b 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -65,13 +65,14 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<FieldViewProps |
const selected = property.includes(":selected");
const isCaption = property.includes(":caption");
const isAnchor = property.includes(":anchor");
+ const isAnnotated = property.includes(":annotated");
const isBackground = () => StrListCast(doc?._layerTags).includes(StyleLayers.Background);
const backgroundCol = () => props?.styleProvider?.(doc, props, StyleProp.BackgroundColor);
const opacity = () => props?.styleProvider?.(doc, props, StyleProp.Opacity);
switch (property.split(":")[0]) {
case StyleProp.DocContents: return undefined;
- case StyleProp.WidgetColor: return darkScheme() ? "lightgrey" : "dimgrey";
+ case StyleProp.WidgetColor: return isAnnotated ? "lightBlue" : darkScheme() ? "lightgrey" : "dimgrey";
case StyleProp.Opacity: return Cast(doc?._opacity, "number", Cast(doc?.opacity, "number", null));
case StyleProp.HideLinkButton: return isAnchor || props?.dontRegisterView || (!selected && (doc?.isLinkButton || doc?.hideLinkButton));
case StyleProp.ShowTitle: return doc && !doc.presentationTargetDoc && StrCast(doc._showTitle,
@@ -157,7 +158,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<FieldViewProps |
if (isAnchor && docProps) return "none";
if (props?.pointerEvents === "none") return "none";
const layer = doc && props?.layerProvider?.(doc);
- if (opacity() === 0 || doc?.type === DocumentType.INK || doc?.isInkMask) return "none";
+ if (opacity() === 0 || (doc?.type === DocumentType.INK && !docProps?.treeViewDoc) || doc?.isInkMask) return "none";
if (layer === false && !selected && !SnappingManager.GetIsDragging()) return "none";
if (doc?.type !== DocumentType.INK && layer === true) return "all";
return undefined;
diff --git a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx
index 4bdd39194..077e50dd2 100644
--- a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx
+++ b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx
@@ -16,6 +16,8 @@ import { EditableView } from "../EditableView";
import { CollectionStackingView } from "./CollectionStackingView";
import "./CollectionStackingView.scss";
import { SnappingManager } from "../../util/SnappingManager";
+import { FormattedTextBox } from "../nodes/formattedText/FormattedTextBox";
+import { Id } from "../../../fields/FieldSymbols";
const higflyout = require("@hig/flyout");
export const { anchorPoints } = higflyout;
export const Flyout = higflyout.default;
@@ -142,8 +144,10 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr
if (!value && !forceEmptyNote) return false;
this._createAliasSelected = false;
const key = StrCast(this.props.parent.props.Document._pivotField);
- const newDoc = Docs.Create.TextDocument(value, { _autoHeight: true, _width: 200, title: value });
+ const newDoc = Docs.Create.TextDocument("", { _autoHeight: true, _width: 200, title: value });
const onLayoutDoc = this.onLayoutDoc(key);
+ FormattedTextBox.SelectOnLoad = newDoc[Id];
+ FormattedTextBox.SelectOnLoadChar = value;
(onLayoutDoc ? newDoc : newDoc[DataSym])[key] = this.getValue(this.props.heading);
const docs = this.props.parent.childDocList;
return docs ? (docs.splice(0, 0, newDoc) ? true : false) : this.props.parent.props.addDocument?.(newDoc) || false;
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index b0c665aa8..639650b94 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -224,11 +224,14 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
e.stopPropagation();
return added;
}
- else if (de.complete.annoDragData && (!this.props.isAnnotationOverlay || de.complete.annoDragData.dragDocument === this.props.Document)) {
- e.stopPropagation();
- de.complete.annoDragData.annotationDocument = de.complete.annoDragData.annotationDocCreator();
- de.complete.annoDragData.dropDocument = de.complete.annoDragData.dropDocCreator(this.props.isAnnotationOverlay ? this.props.Document : undefined);
- return de.complete.annoDragData.dropDocument && this.addDocument(de.complete.annoDragData.dropDocument);
+ else if (de.complete.annoDragData) {
+ const dropCreator = de.complete.annoDragData.dropDocCreator;
+ de.complete.annoDragData.dropDocCreator = () => {
+ const dropped = dropCreator(this.props.isAnnotationOverlay ? this.rootDoc : undefined);
+ this.addDocument(dropped);
+ return dropped;
+ }
+ return true;
}
return false;
}
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index 6975c24d1..18d515552 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -254,7 +254,7 @@ export class TreeView extends React.Component<TreeViewProps> {
const before = pt[1] < rect.top + rect.height / 2;
const inside = this.fileSysMode && !this.doc.isFolder ? false : pt[0] > Math.min(rect.left + 75, rect.left + rect.width * .75) || (!before && this.treeViewOpen && this.childDocList.length);
if (de.complete.linkDragData) {
- const sourceDoc = de.complete.linkDragData.linkSourceDocument;
+ const sourceDoc = de.complete.linkDragData.linkSourceGetAnchor();
const destDoc = this.doc;
DocUtils.MakeLink({ doc: sourceDoc }, { doc: destDoc }, "tree link", "");
e.stopPropagation();
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 02f148eb0..af8ccb9c5 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -275,16 +275,23 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
@undoBatch
internalAnchorAnnoDrop(e: Event, annoDragData: DragManager.AnchorAnnoDragData, xp: number, yp: number) {
- annoDragData.dropDocument!.x = xp - annoDragData.offset[0];
- annoDragData.dropDocument!.y = yp - annoDragData.offset[1];
- this.bringToFront(annoDragData.dropDocument!);
+ const dropCreator = annoDragData.dropDocCreator;
+ annoDragData.dropDocCreator = (annotationOn: Doc | undefined) => {
+ const dropDoc = dropCreator(annotationOn);
+ if (dropDoc) {
+ dropDoc.x = xp - annoDragData.offset[0];
+ dropDoc.y = yp - annoDragData.offset[1];
+ this.bringToFront(dropDoc);
+ }
+ return dropDoc || this.rootDoc;
+ }
return true;
}
@undoBatch
internalLinkDrop(e: Event, de: DragManager.DropEvent, linkDragData: DragManager.LinkDragData, xp: number, yp: number) {
- if (linkDragData.linkSourceDocument === this.props.Document || this.props.Document.annotationOn) return false;
- if (!linkDragData.linkSourceDocument.context || StrCast(Cast(linkDragData.linkSourceDocument.context, Doc, null)?.type) === DocumentType.COL) {
+ if (linkDragData.dragDocument === this.props.Document || this.props.Document.annotationOn) return false;
+ if (!linkDragData.dragDocument.context || StrCast(Cast(linkDragData.dragDocument.context, Doc, null)?.type) === DocumentType.COL) {
// const source = Docs.Create.TextDocument("", { _width: 200, _height: 75, x: xp, y: yp, title: "dropped annotation" });
// this.props.addDocument(source);
// linkDragData.linkDocument = DocUtils.MakeLink({ doc: source }, { doc: linkDragData.linkSourceDocument }, "doc annotation"); // TODODO this is where in text links get passed
@@ -292,7 +299,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
} else {
const source = Docs.Create.TextDocument("", { _width: 200, _height: 75, x: xp, y: yp, title: "dropped annotation" });
this.props.addDocument?.(source);
- de.complete.linkDocument = DocUtils.MakeLink({ doc: source }, { doc: linkDragData.linkSourceDocument }, "doc annotation", ""); // TODODO this is where in text links get passed
+ de.complete.linkDocument = DocUtils.MakeLink({ doc: source }, { doc: linkDragData.linkSourceGetAnchor() }, "doc annotation", ""); // TODODO this is where in text links get passed
e.stopPropagation();
return true;
}
@@ -300,9 +307,9 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
onInternalDrop = (e: Event, de: DragManager.DropEvent) => {
const [xp, yp] = this.getTransform().transformPoint(de.x, de.y);
- if (this.isAnnotationOverlay !== true && de.complete.linkDragData) return this.internalLinkDrop(e, de, de.complete.linkDragData, xp, yp);
if (de.complete.annoDragData?.dragDocument && super.onInternalDrop(e, de)) return this.internalAnchorAnnoDrop(e, de.complete.annoDragData, xp, yp);
- if (de.complete.docDragData?.droppedDocuments.length) return this.internalDocDrop(e, de, de.complete.docDragData, xp, yp);
+ else if (this.isAnnotationOverlay !== true && de.complete.linkDragData) return this.internalLinkDrop(e, de, de.complete.linkDragData, xp, yp);
+ else if (de.complete.docDragData?.droppedDocuments.length) return this.internalDocDrop(e, de, de.complete.docDragData, xp, yp);
return false;
}
diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx
index 96b6bea8c..085ffae26 100644
--- a/src/client/views/nodes/DocumentLinksButton.tsx
+++ b/src/client/views/nodes/DocumentLinksButton.tsx
@@ -51,16 +51,10 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
if (this.props.InMenu && this.props.StartLink) {
if (this._linkButton.current !== null) {
const linkDrag = UndoManager.StartBatch("Drag Link");
- this.props.View && DragManager.StartLinkDrag(this._linkButton.current, this.props.View.props.Document, e.pageX, e.pageY, {
+ this.props.View && DragManager.StartLinkDrag(this._linkButton.current, this.props.View.props.Document, this.props.View.ComponentView?.getAnchor, e.pageX, e.pageY, {
dragComplete: dropEv => {
if (this.props.View && dropEv.linkDocument) {// dropEv.linkDocument equivalent to !dropEve.aborted since linkDocument is only assigned on a completed drop
!dropEv.linkDocument.linkRelationship && (Doc.GetProto(dropEv.linkDocument).linkRelationship = "hyperlink");
-
- // we want to allow specific views to handle the link creation in their own way (e.g., rich text makes text hyperlinks)
- // the dragged view can regiser a linkDropCallback to be notified that the link was made and to update their data structures
- // however, the dropped document isn't so accessible. What we do is set the newly created link document on the documentView
- // The documentView passes a function prop returning this link doc to its descendants who can react to changes to it.
- dropEv.linkDragData?.linkDropCallback?.(dropEv as { linkDocument: Doc }); // bcz: typescript can't figure out that this is valid even though we tested dropEv.linkDocument above
}
linkDrag?.end();
},
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 848287fcc..e5bd14809 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -605,13 +605,17 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
"linking to document tabs not yet supported. Drop link on document content.");
return;
}
- if (de.complete.annoDragData) de.complete.annoDragData.annotationDocument = de.complete.annoDragData.annotationDocCreator();
- const linkSource = de.complete.annoDragData ? de.complete.annoDragData.annotationDocument : de.complete.linkDragData ? de.complete.linkDragData.linkSourceDocument : undefined;
- if (linkSource && linkSource !== this.props.Document) {
+ const linkdrag = de.complete.annoDragData ?? de.complete.linkDragData;
+ if (linkdrag) linkdrag.linkSourceDoc = linkdrag.linkSourceGetAnchor();
+ if (linkdrag?.linkSourceDoc) {
e.stopPropagation();
- const dropDoc = this._componentView?.getAnchor?.() || this.rootDoc;
- if (de.complete.annoDragData) de.complete.annoDragData.dropDocument = dropDoc;
- de.complete.linkDocument = DocUtils.MakeLink({ doc: linkSource }, { doc: dropDoc }, "link", undefined, undefined, undefined, [de.x, de.y]);
+ if (de.complete.annoDragData && !de.complete.annoDragData.dropDocument) {
+ de.complete.annoDragData.dropDocument = de.complete.annoDragData.dropDocCreator(undefined);
+ }
+ if (de.complete.annoDragData || this.rootDoc !== linkdrag.linkSourceDoc.context) {
+ const dropDoc = de.complete.annoDragData?.dropDocument ?? this._componentView?.getAnchor?.() ?? this.props.Document;
+ de.complete.linkDocument = DocUtils.MakeLink({ doc: linkdrag.linkSourceDoc }, { doc: dropDoc }, "link", undefined, undefined, undefined, [de.x, de.y]);
+ }
}
}
@@ -947,7 +951,8 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
["transparent", "#65350c", "#65350c", "yellow", "magenta", "cyan", "orange"] :
["transparent", "maroon", "maroon", "yellow", "magenta", "cyan", "orange"])[highlightIndex];
const highlightStyle = ["solid", "dashed", "solid", "solid", "solid", "solid", "solid"][highlightIndex];
- let highlighting = !this.props.cantBrush && highlightIndex && ![DocumentType.FONTICON, DocumentType.INK].includes(this.layoutDoc.type as any) && this.layoutDoc._viewType !== CollectionViewType.Linear;
+ const excludeTypes = !this.props.treeViewDoc ? [DocumentType.FONTICON, DocumentType.INK] : [DocumentType.FONTICON];
+ let highlighting = !this.props.cantBrush && highlightIndex && !excludeTypes.includes(this.layoutDoc.type as any) && this.layoutDoc._viewType !== CollectionViewType.Linear;
highlighting = highlighting && this.props.focus !== emptyFunction && this.layoutDoc.title !== "[pres element template]"; // bcz: hack to turn off highlighting onsidebar panel documents. need to flag a document as not highlightable in a more direct way
const boxShadow = highlighting && this.borderRounding && highlightStyle !== "dashed" ? `0 0 0 ${highlightIndex}px ${highlightColor}` :
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index 4c3031ae2..240aa1659 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -62,13 +62,10 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps, ImageD
componentDidMount() {
this._disposers.selection = reaction(() => this.props.isSelected(),
- selected => {
- if (!selected) {
- this._savedAnnotations.values().forEach(v => v.forEach(a => a.remove()));
- this._savedAnnotations.clear();
- }
- },
- { fireImmediately: true });
+ selected => !selected && setTimeout(() => {
+ this._savedAnnotations.values().forEach(v => v.forEach(a => a.remove()));
+ this._savedAnnotations.clear();
+ }));
this._disposers.path = reaction(() => ({ nativeSize: this.nativeSize, width: this.layoutDoc[WidthSym]() }),
action(({ nativeSize, width }) => {
if (!this.layoutDoc._height) {
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index ac67949f9..589a6dd24 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -204,13 +204,10 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps, VideoD
componentDidMount() {
this.props.setContentView?.(this); // this tells the DocumentView that this AudioBox is the "content" of the document. this allows the DocumentView to indirectly call getAnchor() on the AudioBox when making a link.
this._disposers.selection = reaction(() => this.props.isSelected(),
- selected => {
- if (!selected) {
- this._savedAnnotations.values().forEach(v => v.forEach(a => a.remove()));
- this._savedAnnotations.clear();
- }
- },
- { fireImmediately: true });
+ selected => !selected && setTimeout(() => {
+ this._savedAnnotations.values().forEach(v => v.forEach(a => a.remove()));
+ this._savedAnnotations.clear();
+ }));
this._disposers.triggerVideo = reaction(
() => !LinkDocPreview.LinkInfo && this.props.renderDepth !== -1 ? NumCast(this.Document._triggerVideo, null) : undefined,
time => time !== undefined && setTimeout(() => {
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx
index 2cd6f5f33..0cf052501 100644
--- a/src/client/views/nodes/WebBox.tsx
+++ b/src/client/views/nodes/WebBox.tsx
@@ -140,13 +140,10 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
runInAction(() => this._url = urlField?.url.toString() || "");
this._disposers.selection = reaction(() => this.props.isSelected(),
- selected => {
- if (!selected) {
- this._savedAnnotations.values().forEach(v => v.forEach(a => a.remove()));
- this._savedAnnotations.clear();
- }
- },
- { fireImmediately: true });
+ selected => !selected && setTimeout(() => {
+ this._savedAnnotations.values().forEach(v => v.forEach(a => a.remove()));
+ this._savedAnnotations.clear();
+ }));
document.addEventListener("pointerup", this.onLongPressUp);
document.addEventListener("pointermove", this.onLongPressMove);
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index 59147061a..288cd14c9 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -185,7 +185,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
@action
setupAnchorMenu = () => {
AnchorMenu.Instance.Status = "marquee";
- AnchorMenu.Instance.Highlight = action((color: string) => {
+ AnchorMenu.Instance.Highlight = action((color: string, isLinkButton: boolean) => {
this._editorView?.state && RichTextMenu.Instance.insertHighlight(color, this._editorView.state, this._editorView?.dispatch);
return undefined;
});
@@ -202,16 +202,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
return target;
};
- DragManager.StartAnchorAnnoDrag([ele], new DragManager.AnchorAnnoDragData(this.rootDoc, () => this.rootDoc, targetCreator), e.pageX, e.pageY, {
- dragComplete: e => {
- const anchor = this.makeLinkAnchor(undefined, "add:right", undefined, "a link");
- if (!e.aborted && e.annoDragData && e.annoDragData.annotationDocument && e.annoDragData.dropDocument && !e.linkDocument) {
- e.linkDocument = DocUtils.MakeLink({ doc: anchor }, { doc: e.annoDragData.dropDocument }, "hyperlink", "link to note");
- e.annoDragData.annotationDocument.isPushpin = e.annoDragData?.dropDocument.annotationOn === this.rootDoc;
- }
- e.linkDocument && e.annoDragData?.linkDropCallback?.(e as { linkDocument: Doc });// bcz: typescript can't figure out that this is valid even though we tested e.linkDocument
- }
- });
+ DragManager.StartAnchorAnnoDrag([ele], new DragManager.AnchorAnnoDragData(this.rootDoc, this.getAnchor, targetCreator), e.pageX, e.pageY);
});
const coordsT = this._editorView!.coordsAtPos(this._editorView!.state.selection.to);
const coordsB = this._editorView!.coordsAtPos(this._editorView!.state.selection.to);
@@ -401,7 +392,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
@undoBatch
@action
- drop = async (e: Event, de: DragManager.DropEvent) => {
+ drop = (e: Event, de: DragManager.DropEvent) => {
+ if (de.complete.annoDragData) de.complete.annoDragData.dropDocCreator = this.getAnchor;
const dragData = de.complete.docDragData;
if (dragData) {
const draggedDoc = dragData.draggedDocuments.length && dragData.draggedDocuments[0];
@@ -427,18 +419,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
e.stopPropagation();
// }
} // otherwise, fall through to outer collection to handle drop
- } else if (de.complete.linkDragData) {
- de.complete.linkDragData.linkDropCallback = this.linkDrop;
- }
- else if (de.complete.annoDragData) {
- de.complete.annoDragData.linkDropCallback = this.linkDrop;
}
}
- linkDrop = (data: { linkDocument: Doc }) => {
- const anchor1Title = data.linkDocument.anchor1 instanceof Doc ? StrCast(data.linkDocument.anchor1.title) : "-untitled-";
- const anchor1 = data.linkDocument.anchor1 instanceof Doc ? data.linkDocument.anchor1 : undefined;
- this.makeLinkAnchor(anchor1, "add:right", undefined, anchor1Title);
- }
getNodeEndpoints(context: Node, node: Node): { from: number, to: number } | null {
let offset = 0;
@@ -875,6 +857,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
}, { fireImmediately: true }
);
quickScroll = undefined;
+ this.tryUpdateScrollHeight();
}
pushToGoogleDoc = async () => {
@@ -1457,11 +1440,11 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
}
@computed get sidebarHandle() {
const annotated = DocListCast(this.dataDoc[this.SidebarKey]).filter(d => d?.author).length;
- return this.props.noSidebar || (!this.props.isSelected() && !(annotated && !this.sidebarWidth())) ? (null) :
- <div className="formattedTextBox-sidebar-handle"
- style={{ left: `max(0px, calc(100% - ${this.sidebarWidthPercent} ${this.sidebarWidth() ? "- 5px" : "- 10px"}))`, background: annotated ? "lightblue" : this.props.styleProvider?.(this.props.Document, this.props, StyleProp.WidgetColor) }}
- onPointerDown={this.sidebarDown}
- />;
+ return <div className="formattedTextBox-sidebar-handle" onPointerDown={this.sidebarDown}
+ style={{
+ left: `max(0px, calc(100% - ${this.sidebarWidthPercent} ${this.sidebarWidth() ? "- 5px" : "- 10px"}))`,
+ background: this.props.styleProvider?.(this.props.Document, this.props, StyleProp.WidgetColor + (annotated ? ":annotated" : ""))
+ }} />;
}
@computed get sidebarCollection() {
const renderComponent = (tag: string) => {
@@ -1490,8 +1473,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
ScreenToLocalTransform={this.sidebarScreenToLocal}
renderDepth={this.props.renderDepth + 1}
noSidebar={true}
- fieldKey={this.layoutDoc.sidebarViewType === "translation" ? `${this.fieldKey}-translation` : this.SidebarKey} />
- }
+ fieldKey={this.layoutDoc.sidebarViewType === "translation" ? `${this.fieldKey}-translation` : this.SidebarKey} />;
+ };
return <div className={"formattedTextBox-sidebar" + (Doc.GetSelectedTool() !== InkTool.None ? "-inking" : "")}
style={{ width: `${this.sidebarWidthPercent}`, backgroundColor: `${this.sidebarColor}` }}>
{renderComponent(StrCast(this.layoutDoc.sidebarViewType))}
@@ -1557,8 +1540,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
}}
/>
</div>
- {this.sidebarCollection}
- {this.props.noSidebar || !this.layoutDoc._showSidebar || this.sidebarWidthPercent === "0%" ? (null) : this.sidebarHandle}
+ {this.props.noSidebar || !this.layoutDoc._showSidebar || this.sidebarWidthPercent === "0%" ? (null) : this.sidebarCollection}
+ {this.sidebarHandle}
{!this.layoutDoc._showAudio ? (null) : this.audioHandle}
</div>
</div>
diff --git a/src/client/views/pdf/AnchorMenu.tsx b/src/client/views/pdf/AnchorMenu.tsx
index d1fdc6c44..e3d14d620 100644
--- a/src/client/views/pdf/AnchorMenu.tsx
+++ b/src/client/views/pdf/AnchorMenu.tsx
@@ -43,7 +43,7 @@ export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
@observable public Status: "marquee" | "annotation" | "" = "";
public StartDrag: (e: PointerEvent, ele: HTMLElement) => void = unimplementedFunction;
- public Highlight: (color: string) => Opt<Doc> = (color: string) => undefined;
+ public Highlight: (color: string, isPushpin: boolean) => Opt<Doc> = (color: string, isPushpin: boolean) => undefined;
public Delete: () => void = unimplementedFunction;
public AddTag: (key: string, value: string) => boolean = returnFalse;
public PinToPres: () => void = unimplementedFunction;
@@ -76,7 +76,7 @@ export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
@action
highlightClicked = (e: React.MouseEvent) => {
- if (!this.Highlight(this.highlightColor) && this.Pinned) {
+ if (!this.Highlight(this.highlightColor, false) && this.Pinned) {
this.Highlighting = !this.Highlighting;
}
}
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts
index bc50d70de..e24821116 100644
--- a/src/fields/Doc.ts
+++ b/src/fields/Doc.ts
@@ -1119,14 +1119,12 @@ export namespace Doc {
export function isDocPinned(doc: Doc) {
//add this new doc to props.Document
const curPres = Cast(Doc.UserDoc().activePresentation, Doc) as Doc;
- if (curPres) {
- return DocListCast(curPres.data).findIndex((val) => Doc.AreProtosEqual(val, doc)) !== -1;
- }
- return false;
+ return !curPres ? false : DocListCast(curPres.data).findIndex((val) => Doc.AreProtosEqual(val, doc)) !== -1;
}
export function copyDragFactory(dragFactory: Doc) {
const ndoc = dragFactory.isTemplateDoc ? Doc.ApplyTemplate(dragFactory) : Doc.MakeCopy(dragFactory, true);
+ ndoc && Doc.AddDocToList(Cast(Doc.UserDoc().myFileOrphans, Doc, null), "data", Doc.GetProto(ndoc));
if (ndoc && dragFactory["dragFactory-count"] !== undefined) {
dragFactory["dragFactory-count"] = NumCast(dragFactory["dragFactory-count"]) + 1;
Doc.SetInPlace(ndoc, "title", ndoc.title + " " + NumCast(dragFactory["dragFactory-count"]).toString(), true);