aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
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);
}
}