aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/MarqueeAnnotator.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/MarqueeAnnotator.tsx')
-rw-r--r--src/client/views/MarqueeAnnotator.tsx57
1 files changed, 32 insertions, 25 deletions
diff --git a/src/client/views/MarqueeAnnotator.tsx b/src/client/views/MarqueeAnnotator.tsx
index d2074d653..1897572f8 100644
--- a/src/client/views/MarqueeAnnotator.tsx
+++ b/src/client/views/MarqueeAnnotator.tsx
@@ -1,6 +1,6 @@
import { action, observable, ObservableMap, runInAction } from "mobx";
import { observer } from "mobx-react";
-import { AclAddonly, AclAdmin, AclEdit, DataSym, Doc, Opt } from "../../fields/Doc";
+import { AclAugment, AclAdmin, AclEdit, DataSym, Doc, Opt, AclSelfEdit } from "../../fields/Doc";
import { Id } from "../../fields/FieldSymbols";
import { List } from "../../fields/List";
import { NumCast } from "../../fields/Types";
@@ -43,15 +43,13 @@ export class MarqueeAnnotator extends React.Component<MarqueeAnnotatorProps> {
@observable private _width: number = 0;
@observable private _height: number = 0;
- constructor(props: any) {
- super(props);
- runInAction(() => {
- AnchorMenu.Instance.Status = "marquee";
- AnchorMenu.Instance.fadeOut(true);
- // clear out old marquees and initialize menu for new selection
- Array.from(this.props.savedAnnotations.values()).forEach(v => v.forEach(a => a.remove()));
- this.props.savedAnnotations.clear();
- });
+ @action
+ static clearAnnotations(savedAnnotations: ObservableMap<number, HTMLDivElement[]>) {
+ AnchorMenu.Instance.Status = "marquee";
+ AnchorMenu.Instance.fadeOut(true);
+ // clear out old marquees and initialize menu for new selection
+ Array.from(savedAnnotations.values()).forEach(v => v.forEach(a => a.remove()));
+ savedAnnotations.clear();
}
@action componentDidMount() {
@@ -65,10 +63,11 @@ export class MarqueeAnnotator extends React.Component<MarqueeAnnotatorProps> {
doc.addEventListener("pointermove", this.onSelectMove);
doc.addEventListener("pointerup", this.onSelectEnd);
- AnchorMenu.Instance.OnClick = (e: PointerEvent) => {
- this.props.anchorMenuClick?.()?.(this.highlight("rgba(173, 216, 230, 0.75)", true));
- };
+ AnchorMenu.Instance.OnClick = (e: PointerEvent) => this.props.anchorMenuClick?.()?.(this.highlight("rgba(173, 216, 230, 0.75)", true));
AnchorMenu.Instance.Highlight = this.highlight;
+ AnchorMenu.Instance.GetAnchor = (savedAnnotations?: ObservableMap<number, HTMLDivElement[]>) => this.highlight("rgba(173, 216, 230, 0.75)", true, savedAnnotations);
+ AnchorMenu.Instance.onMakeAnchor = AnchorMenu.Instance.GetAnchor;
+
/**
* 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.
@@ -103,11 +102,13 @@ export class MarqueeAnnotator extends React.Component<MarqueeAnnotatorProps> {
@undoBatch
@action
- makeAnnotationDocument = (color: string, isLinkButton?: boolean): Opt<Doc> => {
- if (this.props.savedAnnotations.size === 0) return undefined;
- if ((Array.from(this.props.savedAnnotations.values())[0][0] as any).marqueeing) {
+ makeAnnotationDocument = (color: string, isLinkButton?: boolean, savedAnnotations?: ObservableMap<number, HTMLDivElement[]>): Opt<Doc> => {
+ const savedAnnoMap = savedAnnotations ?? this.props.savedAnnotations;
+ if (savedAnnoMap.size === 0) return undefined;
+ const savedAnnos = Array.from(savedAnnoMap.values())[0];
+ if (savedAnnos.length && (savedAnnos[0] as any).marqueeing) {
const scale = this.props.scaling?.() || 1;
- const anno = Array.from(this.props.savedAnnotations.values())[0][0];
+ const anno = savedAnnos[0];
const containerOffset = this.props.containerOffset?.() || [0, 0];
const marqueeAnno = Docs.Create.FreeformDocument([], { _isLinkButton: isLinkButton, backgroundColor: color, annotationOn: this.props.rootDoc, title: "Annotation on " + this.props.rootDoc.title });
marqueeAnno.x = (parseInt(anno.style.left || "0") - containerOffset[0]) / scale;
@@ -115,15 +116,17 @@ export class MarqueeAnnotator extends React.Component<MarqueeAnnotatorProps> {
marqueeAnno._height = parseInt(anno.style.height || "0") / scale;
marqueeAnno._width = parseInt(anno.style.width || "0") / scale;
anno.remove();
- this.props.savedAnnotations.clear();
+ savedAnnoMap.clear();
return marqueeAnno;
}
- const textRegionAnno = Docs.Create.HTMLAnchorDocument([], { annotationOn: this.props.rootDoc, title: "Selection on " + this.props.rootDoc.title, _width: 1, _height: 1 });
+ const textRegionAnno = Docs.Create.HTMLAnchorDocument([], { annotationOn: this.props.rootDoc, backgroundColor: "transparent", title: "Selection on " + this.props.rootDoc.title });
+ let minX = Number.MAX_VALUE;
let maxX = -Number.MAX_VALUE;
let minY = Number.MAX_VALUE;
+ let maxY = -Number.MIN_VALUE;
const annoDocs: Doc[] = [];
- this.props.savedAnnotations.forEach((value: HTMLDivElement[], key: number) => value.map(anno => {
+ savedAnnoMap.forEach((value: HTMLDivElement[], key: number) => value.map(anno => {
const textRegion = new Doc();
textRegion.x = parseInt(anno.style.left ?? "0");
textRegion.y = parseInt(anno.style.top ?? "0");
@@ -134,23 +137,27 @@ export class MarqueeAnnotator extends React.Component<MarqueeAnnotatorProps> {
annoDocs.push(textRegion);
anno.remove();
minY = Math.min(NumCast(textRegion.y), minY);
+ minX = Math.min(NumCast(textRegion.x), minX);
+ maxY = Math.max(NumCast(textRegion.y) + NumCast(textRegion._height), maxY);
maxX = Math.max(NumCast(textRegion.x) + NumCast(textRegion._width), maxX);
}));
const textRegionAnnoProto = Doc.GetProto(textRegionAnno);
textRegionAnnoProto.y = Math.max(minY, 0);
- textRegionAnnoProto.x = Math.max(maxX, 0);
+ textRegionAnnoProto.x = Math.max(minX, 0);
+ textRegionAnnoProto.height = Math.max(maxY, 0) - Math.max(minY, 0);
+ textRegionAnnoProto.width = Math.max(maxX, 0) - Math.max(minX, 0);
// mainAnnoDocProto.text = this._selectionText;
textRegionAnnoProto.textInlineAnnotations = new List<Doc>(annoDocs);
- this.props.savedAnnotations.clear();
+ savedAnnoMap.clear();
return textRegionAnno;
}
@action
- highlight = (color: string, isLinkButton: boolean) => {
+ highlight = (color: string, isLinkButton: boolean, savedAnnotations?: ObservableMap<number, HTMLDivElement[]>) => {
// creates annotation documents for current highlights
const effectiveAcl = GetEffectiveAcl(this.props.rootDoc[DataSym]);
- const annotationDoc = [AclAddonly, AclEdit, AclAdmin].includes(effectiveAcl) && this.makeAnnotationDocument(color, isLinkButton);
- annotationDoc && this.props.addDocument(annotationDoc);
+ const annotationDoc = [AclAugment, AclSelfEdit, AclEdit, AclAdmin].includes(effectiveAcl) && this.makeAnnotationDocument(color, isLinkButton, savedAnnotations);
+ !savedAnnotations && annotationDoc && this.props.addDocument(annotationDoc);
return annotationDoc as Doc ?? undefined;
}