aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2021-01-20 18:35:58 -0500
committerbobzel <zzzman@gmail.com>2021-01-20 18:35:58 -0500
commit68785a97178d229935c0429791081d7c09312dc3 (patch)
tree8260fb1c23ad3f145146b3102cd294fb85ca1044 /src
parent8538a83baf57d7015b62b4ebc22d2bd7318f9d16 (diff)
moved PDFMenu to AnchorMenu. added AnchorMenu to formattedTextBox. Fixed following links from text box huyperlinks when there are multiple different huypertext links on the document.
Diffstat (limited to 'src')
-rw-r--r--src/client/util/DragManager.ts24
-rw-r--r--src/client/views/GlobalKeyHandler.ts4
-rw-r--r--src/client/views/MainView.tsx4
-rw-r--r--src/client/views/MarqueeAnnotator.tsx53
-rw-r--r--src/client/views/collections/CollectionSubView.tsx4
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx9
-rw-r--r--src/client/views/nodes/DocumentView.tsx14
-rw-r--r--src/client/views/nodes/ImageBox.tsx4
-rw-r--r--src/client/views/nodes/VideoBox.tsx4
-rw-r--r--src/client/views/nodes/WebBox.tsx4
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBox.tsx40
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx2
-rw-r--r--src/client/views/pdf/AnchorMenu.scss (renamed from src/client/views/pdf/PDFMenu.scss)2
-rw-r--r--src/client/views/pdf/AnchorMenu.tsx (renamed from src/client/views/pdf/PDFMenu.tsx)12
-rw-r--r--src/client/views/pdf/Annotation.tsx20
-rw-r--r--src/client/views/pdf/PDFViewer.tsx18
16 files changed, 136 insertions, 82 deletions
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 52ccfda74..7b4d43793 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -105,14 +105,14 @@ export namespace DragManager {
constructor(aborted: boolean, dragData: { [id: string]: any }) {
this.aborted = aborted;
this.docDragData = dragData instanceof DocumentDragData ? dragData : undefined;
- this.annoDragData = dragData instanceof PdfAnnoDragData ? dragData : undefined;
+ this.annoDragData = dragData instanceof AnchorAnnoDragData ? dragData : undefined;
this.linkDragData = dragData instanceof LinkDragData ? dragData : undefined;
this.columnDragData = dragData instanceof ColumnDragData ? dragData : undefined;
}
linkDocument?: Doc;
aborted: boolean;
docDragData?: DocumentDragData;
- annoDragData?: PdfAnnoDragData;
+ annoDragData?: AnchorAnnoDragData;
linkDragData?: LinkDragData;
columnDragData?: ColumnDragData;
}
@@ -152,19 +152,21 @@ export namespace DragManager {
}
colKey: SchemaHeaderField;
}
- // used by PDFs to conditionally (if the drop completes) create a text annotation when dragging from the PDF toolbar when a text region has been selected.
+ // 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 PdfAnnoDragData {
- constructor(dragDoc: Doc, annotationDoc: Doc, dropDoc: Doc) {
+ export class AnchorAnnoDragData {
+ constructor(dragDoc: Doc, annotationDocCreator: () => Doc, dropDocCreator: () => Doc) {
this.dragDocument = dragDoc;
- this.dropDocument = dropDoc;
- this.annotationDocument = annotationDoc;
+ this.dropDocCreator = dropDocCreator;
+ this.annotationDocCreator = annotationDocCreator;
this.offset = [0, 0];
}
targetContext: Doc | undefined;
dragDocument: Doc;
- annotationDocument: Doc;
- dropDocument: Doc;
+ annotationDocCreator: () => Doc;
+ dropDocCreator: () => Doc;
+ dropDocument?: Doc;
+ annotationDocument?: Doc;
offset: number[];
dropAction: dropActionType;
userDropAction: dropActionType;
@@ -250,7 +252,7 @@ export namespace DragManager {
}
// drag&drop the pdf annotation anchor which will create a text note on drop via a dropCompleted() DragOption
- export function StartPdfAnnoDrag(eles: HTMLElement[], dragData: PdfAnnoDragData, downX: number, downY: number, options?: DragOptions) {
+ export function StartAnchorAnnoDrag(eles: HTMLElement[], dragData: AnchorAnnoDragData, downX: number, downY: number, options?: DragOptions) {
StartDrag(eles, dragData, downX, downY, options);
}
@@ -353,7 +355,7 @@ export namespace DragManager {
const xs: number[] = [];
const ys: number[] = [];
- docsBeingDragged = dragData instanceof DocumentDragData ? dragData.draggedDocuments : dragData instanceof PdfAnnoDragData ? [dragData.dragDocument] : [];
+ docsBeingDragged = dragData instanceof DocumentDragData ? dragData.draggedDocuments : dragData instanceof AnchorAnnoDragData ? [dragData.dragDocument] : [];
const elesCont = {
left: Number.MAX_SAFE_INTEGER,
top: Number.MAX_SAFE_INTEGER,
diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts
index 8a07c5321..1c5277de0 100644
--- a/src/client/views/GlobalKeyHandler.ts
+++ b/src/client/views/GlobalKeyHandler.ts
@@ -22,7 +22,7 @@ import { DocumentDecorations } from "./DocumentDecorations";
import { InkStrokeProperties } from "./InkStrokeProperties";
import { MainView } from "./MainView";
import { DocumentLinksButton } from "./nodes/DocumentLinksButton";
-import { PDFMenu } from "./pdf/PDFMenu";
+import { AnchorMenu } from "./pdf/AnchorMenu";
import { SnappingManager } from "../util/SnappingManager";
import { SearchBox } from "./search/SearchBox";
import { random } from "lodash";
@@ -261,7 +261,7 @@ export class KeyManager {
}
break;
case "c":
- if (!PDFMenu.Instance.Active && DocumentDecorations.Instance.Bounds.r - DocumentDecorations.Instance.Bounds.x > 2) {
+ if (!AnchorMenu.Instance.Active && DocumentDecorations.Instance.Bounds.r - DocumentDecorations.Instance.Bounds.x > 2) {
const bds = DocumentDecorations.Instance.Bounds;
const pt = SelectionManager.Views()[0].props.ScreenToLocalTransform().transformPoint(bds.x + (bds.r - bds.x) / 2, bds.y + (bds.b - bds.y) / 2);
const text = `__DashCloneId(${pt?.[0] || 0},${pt?.[1] || 0}):` + SelectionManager.Views().map(dv => dv.Document[Id]).join(":");
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index c1fafe3e6..bd5db62ef 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -55,7 +55,7 @@ import { RadialMenu } from './nodes/RadialMenu';
import { TaskCompletionBox } from './nodes/TaskCompletedBox';
import { WebBox } from './nodes/WebBox';
import { OverlayView } from './OverlayView';
-import { PDFMenu } from './pdf/PDFMenu';
+import { AnchorMenu } from './pdf/AnchorMenu';
import { PreviewCursor } from './PreviewCursor';
import { PropertiesView } from './PropertiesView';
import { SearchBox } from './search/SearchBox';
@@ -615,7 +615,7 @@ export class MainView extends React.Component {
<TaskCompletionBox />
<ContextMenu />
<RadialMenu />
- <PDFMenu />
+ <AnchorMenu />
<MarqueeOptionsMenu />
<OverlayView />
<TimelineMenu />
diff --git a/src/client/views/MarqueeAnnotator.tsx b/src/client/views/MarqueeAnnotator.tsx
index 21048ebe2..0ab2d1ecf 100644
--- a/src/client/views/MarqueeAnnotator.tsx
+++ b/src/client/views/MarqueeAnnotator.tsx
@@ -8,7 +8,7 @@ import { DocUtils, Docs } from "../documents/Documents";
import { CurrentUserUtils } from "../util/CurrentUserUtils";
import { DragManager } from "../util/DragManager";
import { FormattedTextBox } from "./nodes/formattedText/FormattedTextBox";
-import { PDFMenu } from "./pdf/PDFMenu";
+import { AnchorMenu } from "./pdf/AnchorMenu";
import "./MarqueeAnnotator.scss";
import React = require("react");
import { undoBatch } from "../util/UndoManager";
@@ -40,8 +40,8 @@ export class MarqueeAnnotator extends React.Component<MarqueeAnnotatorProps> {
constructor(props: any) {
super(props);
runInAction(() => {
- PDFMenu.Instance.Status = "marquee";
- PDFMenu.Instance.fadeOut(true);
+ AnchorMenu.Instance.Status = "marquee";
+ AnchorMenu.Instance.fadeOut(true);
// clear out old marquees and initialize menu for new selection
this.props.savedAnnotations.values().forEach(v => v.forEach(a => a.remove()));
this.props.savedAnnotations.clear();
@@ -148,32 +148,37 @@ export class MarqueeAnnotator extends React.Component<MarqueeAnnotatorProps> {
onSelectEnd = (e: PointerEvent) => {
if (!e.ctrlKey) {
- PDFMenu.Instance.Marquee = { left: this._left, top: this._top, width: this._width, height: this._height };
+ AnchorMenu.Instance.Marquee = { left: this._left, top: this._top, width: this._width, height: this._height };
}
- PDFMenu.Instance.Highlight = this.highlight;
+ AnchorMenu.Instance.Highlight = this.highlight;
/**
- * This function is used by the PDFmenu to create an anchor highlight and a new linked text annotation.
+ * 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.
*/
- PDFMenu.Instance.StartDrag = action(async (e: PointerEvent, ele: HTMLElement) => {
+ AnchorMenu.Instance.StartDrag = action(async (e: PointerEvent, ele: HTMLElement) => {
e.preventDefault();
e.stopPropagation();
- const targetDoc = CurrentUserUtils.GetNewTextDoc("Note linked to " + this.props.rootDoc.title, 0, 0, 100, 100);
- FormattedTextBox.SelectOnLoad = targetDoc[Id];
- const anchorHighlightDoc = this.highlight("rgba(173, 216, 230, 0.75)"); // hyperlink color
- if (anchorHighlightDoc) {
- DragManager.StartPdfAnnoDrag([ele], new DragManager.PdfAnnoDragData(this.props.rootDoc, anchorHighlightDoc, targetDoc), e.pageX, e.pageY, {
- dragComplete: e => {
- if (!e.aborted && e.annoDragData && !e.linkDocument) {
- e.linkDocument = DocUtils.MakeLink({ doc: anchorHighlightDoc }, { doc: e.annoDragData.dropDocument }, "Annotation");
- anchorHighlightDoc.isLinkButton = true; // prevents link button from showing up --- maybe not a good thing?
- anchorHighlightDoc.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
- }
- });
+ const targetCreator = () => {
+ const target = CurrentUserUtils.GetNewTextDoc("Note linked to " + this.props.rootDoc.title, 0, 0, 100, 100);
+ 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?
+ this.props.addDocument(annoDoc);
+ return annoDoc;
}
+ DragManager.StartAnchorAnnoDrag([ele], new DragManager.AnchorAnnoDragData(this.props.rootDoc, anchorCreator, 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;
+ }
+ 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
+ }
+ });
});
if (this._width > 10 || this._height > 10) { // configure and show the annotation/link menu if a the drag region is big enough
@@ -186,10 +191,10 @@ export class MarqueeAnnotator extends React.Component<MarqueeAnnotatorProps> {
MarqueeAnnotator.previewNewAnnotation(this.props.savedAnnotations, this.props.annotationLayer, copy, this.props.getPageFromScroll?.(this._top) || 0);
}
- PDFMenu.Instance.jumpTo(e.clientX, e.clientY);
+ AnchorMenu.Instance.jumpTo(e.clientX, e.clientY);
- if (PDFMenu.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 PDFMenu's highlight color)
+ 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)
}
} else {
runInAction(() => this._width = this._height = 0);
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index d7b9d9745..26cb4d156 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -224,7 +224,9 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
}
else if (de.complete.annoDragData && (!this.props.isAnnotationOverlay || de.complete.annoDragData.dragDocument === this.props.Document)) {
e.stopPropagation();
- return this.addDocument(de.complete.annoDragData.dropDocument);
+ de.complete.annoDragData.annotationDocument = de.complete.annoDragData.annotationDocCreator();
+ de.complete.annoDragData.dropDocument = de.complete.annoDragData.dropDocCreator();
+ return de.complete.annoDragData.dropDocument && this.addDocument(de.complete.annoDragData.dropDocument);
}
return false;
}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 588ba6922..2bc716928 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -43,7 +43,6 @@ import { CollectionViewType } from "../CollectionView";
import { computePivotLayout, computerPassLayout, computerStarburstLayout, computeTimelineLayout, PoolData, ViewDefBounds, ViewDefResult } from "./CollectionFreeFormLayoutEngines";
import { CollectionFreeFormRemoteCursors } from "./CollectionFreeFormRemoteCursors";
import "./CollectionFreeFormView.scss";
-import { MarqueeOptionsMenu } from "./MarqueeOptionsMenu";
import { MarqueeView } from "./MarqueeView";
import React = require("react");
import { CurrentUserUtils } from "../../../util/CurrentUserUtils";
@@ -267,8 +266,8 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
@undoBatch
@action
- internalPdfAnnoDrop(e: Event, annoDragData: DragManager.PdfAnnoDragData, xp: number, yp: number) {
- const dragDoc = annoDragData.dropDocument;
+ internalPdfAnnoDrop(e: Event, annoDragData: DragManager.AnchorAnnoDragData, xp: number, yp: number) {
+ const dragDoc = annoDragData.dropDocument!;
const dropPos = [NumCast(dragDoc.x), NumCast(dragDoc.y)];
dragDoc.x = xp - annoDragData.offset[0] + (NumCast(dragDoc.x) - dropPos[0]);
dragDoc.y = yp - annoDragData.offset[1] + (NumCast(dragDoc.y) - dropPos[1]);
@@ -299,7 +298,7 @@ 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?.dropDocument && super.onInternalDrop(e, de)) return this.internalPdfAnnoDrop(e, de.complete.annoDragData, xp, yp);
+ if (de.complete.annoDragData?.dragDocument && super.onInternalDrop(e, de)) return this.internalPdfAnnoDrop(e, de.complete.annoDragData, xp, yp);
if (de.complete.docDragData?.droppedDocuments.length) return this.internalDocDrop(e, de, de.complete.docDragData, xp, yp);
return false;
}
@@ -813,7 +812,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
else if (this.props.active(true)) {
e.stopPropagation();
if (!e.ctrlKey && MarqueeView.DragMarquee) this.setPan(this.panX() + e.deltaX, this.panY() + e.deltaY, "None", true);
- else this.zoom(e.clientX, e.clientY, e.deltaY);
+ else if (!this.props.isAnnotationOverlay) this.zoom(e.clientX, e.clientY, e.deltaY);
}
this.props.Document.targetScale = NumCast(this.props.Document[this.scaleFieldKey]);
}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 6371ae5fb..13e1f3d54 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -550,10 +550,13 @@ 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) {
e.stopPropagation();
- de.complete.linkDocument = DocUtils.MakeLink({ doc: linkSource }, { doc: this._componentView?.getAnchor() || this.rootDoc }, "link", undefined, undefined, undefined, [de.x, de.y]);
+ 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]);
}
}
@@ -873,10 +876,11 @@ export class DocumentView extends React.Component<DocumentViewProps> {
@computed get panelWidth() { return this.nativeWidth ? this.nativeWidth * this.nativeScaling : this.props.PanelWidth(); }
@computed get panelHeight() {
if (this.nativeHeight) {
- if (this.props.Document._fitWidth) {
- return Math.min(this.props.PanelHeight(), NumCast(this.props.Document.scrollHeight, this.props.PanelHeight()));
- }
- return Math.min(this.props.PanelHeight(), this.nativeHeight * this.nativeScaling);
+ return Math.min(this.props.PanelHeight(),
+ this.props.Document._fitWidth ?
+ Math.max(NumCast(this.props.Document._height), NumCast((this.props.Document.scrollHeight as number) * this.props.PanelWidth() / this.nativeWidth, this.props.PanelHeight())) :
+ this.nativeHeight * this.nativeScaling
+ );
}
return this.props.PanelHeight();
}
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index e202749aa..47fa25951 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -27,7 +27,7 @@ import { FieldView, FieldViewProps } from './FieldView';
import "./ImageBox.scss";
import React = require("react");
import { StyleProp } from '../StyleProvider';
-import { PDFMenu } from '../pdf/PDFMenu';
+import { AnchorMenu } from '../pdf/AnchorMenu';
import { Dictionary } from 'typescript-collections';
import { MarqueeAnnotator } from '../MarqueeAnnotator';
import { Annotation } from '../pdf/Annotation';
@@ -83,7 +83,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps, ImageD
if (!selected) {
this._savedAnnotations.values().forEach(v => v.forEach(a => a.remove()));
this._savedAnnotations.clear();
- PDFMenu.Instance.fadeOut(true);
+ AnchorMenu.Instance.fadeOut(true);
}
},
{ fireImmediately: true });
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index f1ef6d10b..55a9818ad 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -27,7 +27,7 @@ import { Transform } from "../../util/Transform";
import { StyleProp } from "../StyleProvider";
import { Dictionary } from "typescript-collections";
import { MarqueeAnnotator } from "../MarqueeAnnotator";
-import { PDFMenu } from "../pdf/PDFMenu";
+import { AnchorMenu } from "../pdf/AnchorMenu";
const path = require('path');
export const timeSchema = createSchema({
@@ -195,7 +195,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps, VideoD
if (!selected) {
this._savedAnnotations.values().forEach(v => v.forEach(a => a.remove()));
this._savedAnnotations.clear();
- PDFMenu.Instance.fadeOut(true);
+ AnchorMenu.Instance.fadeOut(true);
}
},
{ fireImmediately: true });
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx
index ca3d4448d..c9c4ed159 100644
--- a/src/client/views/nodes/WebBox.tsx
+++ b/src/client/views/nodes/WebBox.tsx
@@ -25,7 +25,7 @@ import { ContextMenuProps } from "../ContextMenuItem";
import { ViewBoxAnnotatableComponent } from "../DocComponent";
import { DocumentDecorations } from "../DocumentDecorations";
import { Annotation } from "../pdf/Annotation";
-import { PDFMenu } from "../pdf/PDFMenu";
+import { AnchorMenu } from "../pdf/AnchorMenu";
import { FieldView, FieldViewProps } from './FieldView';
import "./WebBox.scss";
import React = require("react");
@@ -161,7 +161,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
if (!selected) {
this._savedAnnotations.values().forEach(v => v.forEach(a => a.remove()));
this._savedAnnotations.clear();
- PDFMenu.Instance.fadeOut(true);
+ AnchorMenu.Instance.fadeOut(true);
}
},
{ fireImmediately: true });
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index c129d0204..f9982f747 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -64,6 +64,8 @@ import { SnappingManager } from '../../../util/SnappingManager';
import { LinkDocPreview } from '../LinkDocPreview';
import { SubCollectionViewProps } from '../../collections/CollectionSubView';
import { StyleProp } from '../../StyleProvider';
+import { AnchorMenu } from '../../pdf/AnchorMenu';
+import { CurrentUserUtils } from '../../../util/CurrentUserUtils';
export interface FormattedTextBoxProps {
makeLink?: () => Opt<Doc>; // bcz: hack: notifies the text document when the container has made a link. allows the text doc to react and setup a hyeprlink for any selected text
@@ -252,6 +254,43 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
let unchanged = true;
const effectiveAcl = GetEffectiveAcl(this.dataDoc);
+ if (!this._editorView.state.selection.empty) {
+ runInAction(() => {
+ AnchorMenu.Instance.Status = "marquee";
+ AnchorMenu.Instance.Highlight = action((color: string) => {
+ this._editorView?.state && RichTextMenu.Instance.insertHighlight(color, this._editorView?.state, this._editorView?.dispatch);
+ return undefined;
+ });
+ /**
+ * This function is used by the PDFmenu 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) => {
+ e.preventDefault();
+ e.stopPropagation();
+ const targetCreator = () => {
+ const target = CurrentUserUtils.GetNewTextDoc("Note linked to " + this.rootDoc.title, 0, 0, 100, 100);
+ FormattedTextBox.SelectOnLoad = target[Id];
+ return target;
+ }
+
+ DragManager.StartAnchorAnnoDrag([ele], new DragManager.AnchorAnnoDragData(this.rootDoc, () => this.rootDoc, 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 }, "hyperlink", "link to note");
+ e.annoDragData.annotationDocument.isPushpin = e.annoDragData?.dropDocument.annotationOn === this.rootDoc;
+ }
+ e.linkDocument && e.annoDragData?.dropDocument && this.makeLinkToSelection(e.linkDocument[Id], "a link", "add:right", e.annoDragData.dropDocument[Id]);
+ 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
+ }
+ });
+ });
+ });
+ const coordsT = this._editorView!.coordsAtPos(this._editorView!.state.selection.to);
+ const coordsB = this._editorView!.coordsAtPos(this._editorView!.state.selection.to);
+ AnchorMenu.Instance.jumpTo(Math.min(coordsT.left, coordsB.left), Math.max(coordsT.bottom, coordsB.bottom));
+ }
+
const removeSelection = (json: string | undefined) => {
return json?.indexOf("\"storedMarks\"") === -1 ? json?.replace(/"selection":.*/, "") : json?.replace(/"selection":"\"storedMarks\""/, "\"storedMarks\"");
};
@@ -960,6 +999,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
this._disposers.selected = reaction(() => this.props.isSelected(),
action((selected) => {
this._recording = false;
+ AnchorMenu.Instance.fadeOut(true);
if (RichTextMenu.Instance?.view === this._editorView && !selected) {
RichTextMenu.Instance?.updateMenu(undefined, undefined, undefined);
}
diff --git a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
index 038a91aa3..8867595ff 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
@@ -255,7 +255,7 @@ export class FormattedTextBoxComment {
docTarget && DocServer.GetRefField(docTarget).then(async linkDoc => {
if (linkDoc instanceof Doc) {
(FormattedTextBoxComment.tooltipText as any).href = href;
- FormattedTextBoxComment.linkDoc = DocListCast(textBox.props.Document.links).find(link => link.anchor1 === textBox.props.Document || link.anchor2 === textBox.props.Document ? link : undefined) || linkDoc;
+ FormattedTextBoxComment.linkDoc = linkDoc;
const anchor = FieldValue(Doc.AreProtosEqual(FieldValue(Cast(linkDoc.anchor1, Doc)), textBox.dataDoc) ? Cast(linkDoc.anchor2, Doc) : (Cast(linkDoc.anchor1, Doc)) || linkDoc);
const target = anchor?.annotationOn ? await DocCastAsync(anchor.annotationOn) : anchor;
if (anchor !== target && anchor && target) {
diff --git a/src/client/views/pdf/PDFMenu.scss b/src/client/views/pdf/AnchorMenu.scss
index fa43a99b2..b7afb26a5 100644
--- a/src/client/views/pdf/PDFMenu.scss
+++ b/src/client/views/pdf/AnchorMenu.scss
@@ -1,4 +1,4 @@
-.pdfMenu-addTag {
+.anchorMenu-addTag {
display: grid;
width: 200px;
padding: 5px;
diff --git a/src/client/views/pdf/PDFMenu.tsx b/src/client/views/pdf/AnchorMenu.tsx
index 603e26021..e2bd5a73d 100644
--- a/src/client/views/pdf/PDFMenu.tsx
+++ b/src/client/views/pdf/AnchorMenu.tsx
@@ -8,11 +8,11 @@ import { Doc, Opt } from "../../../fields/Doc";
import { returnFalse, setupMoveUpEvents, unimplementedFunction, Utils } from "../../../Utils";
import { AntimodeMenu, AntimodeMenuProps } from "../AntimodeMenu";
import { ButtonDropdown } from "../nodes/formattedText/RichTextMenu";
-import "./PDFMenu.scss";
+import "./AnchorMenu.scss";
@observer
-export class PDFMenu extends AntimodeMenu<AntimodeMenuProps> {
- static Instance: PDFMenu;
+export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
+ static Instance: AnchorMenu;
private _commentCont = React.createRef<HTMLButtonElement>();
private _palette = [
@@ -54,8 +54,8 @@ export class PDFMenu extends AntimodeMenu<AntimodeMenuProps> {
constructor(props: Readonly<{}>) {
super(props);
- PDFMenu.Instance = this;
- PDFMenu.Instance._canFade = false;
+ AnchorMenu.Instance = this;
+ AnchorMenu.Instance._canFade = false;
}
pointerDown = (e: React.PointerEvent) => {
@@ -144,7 +144,7 @@ export class PDFMenu extends AntimodeMenu<AntimodeMenuProps> {
<FontAwesomeIcon icon="thumbtack" size="lg" />
</button>
</Tooltip>,
- // <div key="7" className="pdfMenu-addTag" >
+ // <div key="7" className="anchorMenu-addTag" >
// <input onChange={this.keyChanged} placeholder="Key" style={{ gridColumn: 1 }} />
// <input onChange={this.valueChanged} placeholder="Value" style={{ gridColumn: 3 }} />
// </div>,
diff --git a/src/client/views/pdf/Annotation.tsx b/src/client/views/pdf/Annotation.tsx
index 5ef57f986..85dd65901 100644
--- a/src/client/views/pdf/Annotation.tsx
+++ b/src/client/views/pdf/Annotation.tsx
@@ -8,7 +8,7 @@ import { BoolCast, Cast, FieldValue, NumCast, PromiseValue, StrCast } from "../.
import { LinkManager } from "../../util/LinkManager";
import { undoBatch } from "../../util/UndoManager";
import "./Annotation.scss";
-import { PDFMenu } from "./PDFMenu";
+import { AnchorMenu } from "./AnchorMenu";
interface IAnnotationProps {
anno: Doc;
@@ -84,7 +84,7 @@ class RegionAnnotation extends React.Component<IRegionAnnotationProps> {
DocListCast(group.annotations).forEach(anno => anno.delete = true);
}
- PDFMenu.Instance.fadeOut(true);
+ AnchorMenu.Instance.fadeOut(true);
}
@undoBatch
@@ -105,14 +105,14 @@ class RegionAnnotation extends React.Component<IRegionAnnotationProps> {
@action
onPointerDown = (e: React.PointerEvent) => {
if (e.button === 2 || e.ctrlKey) {
- PDFMenu.Instance.Status = "annotation";
- PDFMenu.Instance.Delete = this.deleteAnnotation.bind(this);
- PDFMenu.Instance.Pinned = false;
- PDFMenu.Instance.AddTag = this.addTag.bind(this);
- PDFMenu.Instance.PinToPres = this.pinToPres;
- PDFMenu.Instance.MakePushpin = this.makePushpin;
- PDFMenu.Instance.IsPushpin = this.isPushpin;
- PDFMenu.Instance.jumpTo(e.clientX, e.clientY, true);
+ AnchorMenu.Instance.Status = "annotation";
+ AnchorMenu.Instance.Delete = this.deleteAnnotation.bind(this);
+ AnchorMenu.Instance.Pinned = false;
+ AnchorMenu.Instance.AddTag = this.addTag.bind(this);
+ AnchorMenu.Instance.PinToPres = this.pinToPres;
+ AnchorMenu.Instance.MakePushpin = this.makePushpin;
+ AnchorMenu.Instance.IsPushpin = this.isPushpin;
+ AnchorMenu.Instance.jumpTo(e.clientX, e.clientY, true);
e.stopPropagation();
}
else if (e.button === 0) {
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index f9139220b..f2052d454 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -26,7 +26,7 @@ import { FieldViewProps } from "../nodes/FieldView";
import { FormattedTextBoxComment } from "../nodes/formattedText/FormattedTextBoxComment";
import { LinkDocPreview } from "../nodes/LinkDocPreview";
import { Annotation } from "./Annotation";
-import { PDFMenu } from "./PDFMenu";
+import { AnchorMenu } from "./AnchorMenu";
import "./PDFViewer.scss";
const pdfjs = require('pdfjs-dist/es5/build/pdf.js');
import React = require("react");
@@ -137,7 +137,7 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu
if (!selected) {
this._savedAnnotations.values().forEach(v => v.forEach(a => a.remove()));
this._savedAnnotations.keys().forEach(k => this._savedAnnotations.setValue(k, []));
- PDFMenu.Instance.fadeOut(true);
+ AnchorMenu.Instance.fadeOut(true);
}
(SelectionManager.Views().length === 1) && this.setupPdfJsViewer();
},
@@ -384,30 +384,32 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu
this._setPreviewCursor?.(e.clientX, e.clientY, true);
}
if (!e.altKey && e.button === 0 && this.active(true)) {
- if (e.target && (e.target as any).parentElement.className !== "textLayer") {
+ if (e.target && ((e.target as any).className.includes("endOfContent") || ((e.target as any).parentElement.className !== "textLayer"))) {
this._marqueeing = [e.clientX, e.clientY]; // if texLayer is hit, then we select text instead of using a marquee
} else {
// clear out old marquees and initialize menu for new selection
- PDFMenu.Instance.Status = "marquee";
- PDFMenu.Instance.fadeOut(true);
+ AnchorMenu.Instance.Status = "marquee";
+ AnchorMenu.Instance.fadeOut(true);
this._savedAnnotations.values().forEach(v => v.forEach(a => a.remove()));
this._savedAnnotations.clear();
this._styleRule = addStyleSheetRule(PDFViewer._annotationStyle, "pdfAnnotation", { "pointer-events": "none" });
- document.addEventListener("pointermove", this.onSelectMove);
document.addEventListener("pointerup", this.onSelectEnd);
}
+ document.addEventListener("pointermove", this.onSelectMove);
}
}
@action
finishMarquee = () => {
this._marqueeing = undefined;
+ document.removeEventListener("pointermove", this.onSelectMove);
this.props.select(false);
}
@action
onSelectMove = (e: PointerEvent): void => {
- if (e.target && (e.target as any).parentElement === this._mainCont.current) e.stopPropagation();
+ // if (e.target && (e.target as any).parentElement === this._mainCont.current)
+ e.stopPropagation();
}
@action
@@ -421,7 +423,7 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu
if (sel?.type === "Range") {
const selRange = sel.getRangeAt(0);
this.createTextAnnotation(sel, selRange);
- PDFMenu.Instance.jumpTo(e.clientX, e.clientY);
+ AnchorMenu.Instance.jumpTo(e.clientX, e.clientY);
}
}