diff options
Diffstat (limited to 'src/client/views/MarqueeAnnotator.tsx')
-rw-r--r-- | src/client/views/MarqueeAnnotator.tsx | 79 |
1 files changed, 39 insertions, 40 deletions
diff --git a/src/client/views/MarqueeAnnotator.tsx b/src/client/views/MarqueeAnnotator.tsx index 9fa20f642..a917a7d57 100644 --- a/src/client/views/MarqueeAnnotator.tsx +++ b/src/client/views/MarqueeAnnotator.tsx @@ -7,16 +7,14 @@ import { List } from '../../fields/List'; import { NumCast } from '../../fields/Types'; import { GetEffectiveAcl } from '../../fields/util'; import { unimplementedFunction, Utils } from '../../Utils'; -import { Docs, DocUtils } from '../documents/Documents'; +import { Docs } from '../documents/Documents'; +import { DocUtils, FollowLinkScript } from '../documents/DocUtils'; import { DragManager } from '../util/DragManager'; -import { FollowLinkScript } from '../util/LinkFollower'; import { undoable, undoBatch, UndoManager } from '../util/UndoManager'; import './MarqueeAnnotator.scss'; import { DocumentView } from './nodes/DocumentView'; -import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox'; -import { AnchorMenu } from './pdf/AnchorMenu'; import { ObservableReactComponent } from './ObservableReactComponent'; -const _global = (window /* browser */ || global) /* node */ as any; +import { AnchorMenu } from './pdf/AnchorMenu'; export interface MarqueeAnnotatorProps { Document: Doc; @@ -96,42 +94,41 @@ export class MarqueeAnnotator extends ObservableReactComponent<MarqueeAnnotatorP presentation_zoomText: true, title: '>' + this.props.Document.title, }); + const textRegionAnnoProto = textRegionAnno[DocData]; let minX = Number.MAX_VALUE; let maxX = -Number.MAX_VALUE; let minY = Number.MAX_VALUE; let maxY = -Number.MIN_VALUE; - const annoDocs: Doc[] = []; - 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'); - textRegion._height = parseInt(anno.style.height ?? '0'); - textRegion._width = parseInt(anno.style.width ?? '0'); - textRegion.annoTextRegion = textRegionAnno; - textRegion.backgroundColor = color; - annoDocs.push(textRegion); + const annoRects: string[] = []; + savedAnnoMap.forEach((value: HTMLDivElement[]) => + value.forEach(anno => { + const x = parseInt(anno.style.left ?? '0'); + const y = parseInt(anno.style.top ?? '0'); + const height = parseInt(anno.style.height ?? '0'); + const width = parseInt(anno.style.width ?? '0'); + annoRects.push(`${x}:${y}:${width}:${height}`); 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); + minY = Math.min(NumCast(y), minY); + minX = Math.min(NumCast(x), minX); + maxY = Math.max(NumCast(y) + NumCast(height), maxY); + maxX = Math.max(NumCast(x) + NumCast(width), maxX); }) ); - const textRegionAnnoProto = textRegionAnno[DocData]; textRegionAnnoProto.y = Math.max(minY, 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); + textRegionAnnoProto.backgroundColor = color; // mainAnnoDocProto.text = this._selectionText; - textRegionAnnoProto.text_inlineAnnotations = new List<Doc>(annoDocs); + textRegionAnnoProto.text_inlineAnnotations = new List<string>(annoRects); + textRegionAnnoProto.opacity = 0; textRegionAnnoProto.layout_unrendered = true; savedAnnoMap.clear(); return textRegionAnno; }; @action - highlight = (color: string, isLinkButton: boolean, savedAnnotations?: ObservableMap<number, HTMLDivElement[]>, addAsAnnotation?: boolean, summarize?: boolean) => { + highlight = (color: string, isLinkButton: boolean, savedAnnotations?: ObservableMap<number, HTMLDivElement[]>, addAsAnnotation?: boolean) => { // creates annotation documents for current highlights const effectiveAcl = GetEffectiveAcl(this.props.Document[DocData]); const annotationDoc = [AclAugment, AclSelfEdit, AclEdit, AclAdmin].includes(effectiveAcl) && this.makeAnnotationDocument(color, isLinkButton, savedAnnotations); @@ -157,7 +154,7 @@ export class MarqueeAnnotator extends ObservableReactComponent<MarqueeAnnotatorP // 3) localize the unrotated vector by scaling into the marquee container's coordinates // 4) reattach the vector to the center of the bounding box getTransformedScreenPt = (down: number[]) => { - const marqueeContainer = this.props.marqueeContainer; + const { marqueeContainer } = this.props; const containerXf = this.props.isNativeScaled ? this.props.docView().screenToContentsTransform() : this.props.docView().screenToViewTransform(); const boundingRect = marqueeContainer.getBoundingClientRect(); const center = { x: boundingRect.x + boundingRect.width / 2, y: boundingRect.y + boundingRect.height / 2 }; @@ -177,15 +174,15 @@ export class MarqueeAnnotator extends ObservableReactComponent<MarqueeAnnotatorP document.addEventListener('pointermove', this.onSelectMove); document.addEventListener('pointerup', this.onSelectEnd); - AnchorMenu.Instance.OnCrop = (e: PointerEvent) => { + AnchorMenu.Instance.OnCrop = () => { if (this.props.anchorMenuCrop) { UndoManager.RunInBatch(() => this.props.anchorMenuCrop?.(this.highlight('', true, undefined, false), true), 'cropping'); } }; - AnchorMenu.Instance.OnClick = undoable((e: PointerEvent) => this.props.anchorMenuClick?.()?.(this.highlight(this.props.highlightDragSrcColor ?? 'rgba(173, 216, 230, 0.75)', true, undefined, true)), 'make sidebar annotation'); + AnchorMenu.Instance.OnClick = undoable(() => this.props.anchorMenuClick?.()?.(this.highlight(this.props.highlightDragSrcColor ?? 'rgba(173, 216, 230, 0.75)', true, undefined, true)), 'make sidebar annotation'); AnchorMenu.Instance.OnAudio = unimplementedFunction; AnchorMenu.Instance.Highlight = (color: string) => this.highlight(color, false, undefined, true); - AnchorMenu.Instance.GetAnchor = (savedAnnotations?: ObservableMap<number, HTMLDivElement[]>, addAsAnnotation?: boolean) => this.highlight('rgba(173, 216, 230, 0.75)', true, savedAnnotations, true); + AnchorMenu.Instance.GetAnchor = (savedAnnotations?: ObservableMap<number, HTMLDivElement[]> /* , addAsAnnotation?: boolean */) => this.highlight('rgba(173, 216, 230, 0.75)', true, savedAnnotations, true); AnchorMenu.Instance.onMakeAnchor = () => AnchorMenu.Instance.GetAnchor(undefined, true); /** @@ -199,14 +196,14 @@ export class MarqueeAnnotator extends ObservableReactComponent<MarqueeAnnotatorP const targetCreator = (annotationOn: Doc | undefined) => { const target = DocUtils.GetNewTextDoc('Note linked to ' + this.props.Document.title, 0, 0, 100, 100, annotationOn, 'yellow'); - FormattedTextBox.SetSelectOnLoad(target); + Doc.SetSelectOnLoad(target); return target; }; DragManager.StartAnchorAnnoDrag([ele], new DragManager.AnchorAnnoDragData(this.props.docView(), sourceAnchorCreator, targetCreator), e.pageX, e.pageY, { - dragComplete: e => { - if (!e.aborted && e.annoDragData && e.annoDragData.linkSourceDoc && e.annoDragData.dropDocument && e.linkDocument) { - e.annoDragData.linkSourceDoc.followLinkToggle = e.annoDragData.dropDocument.annotationOn === this.props.Document; - e.annoDragData.linkSourceDoc.followLinkZoom = false; + dragComplete: dragEv => { + if (!dragEv.aborted && dragEv.annoDragData && dragEv.annoDragData.linkSourceDoc && dragEv.annoDragData.dropDocument && dragEv.linkDocument) { + dragEv.annoDragData.linkSourceDoc.followLinkToggle = dragEv.annoDragData.dropDocument.annotationOn === this.props.Document; + dragEv.annoDragData.linkSourceDoc.followLinkZoom = false; } }, }); @@ -220,16 +217,16 @@ export class MarqueeAnnotator extends ObservableReactComponent<MarqueeAnnotatorP : action((e: PointerEvent, ele: HTMLElement) => { e.preventDefault(); e.stopPropagation(); - var cropRegion: Doc | undefined; + let cropRegion: Doc | undefined; + // eslint-disable-next-line no-return-assign const sourceAnchorCreator = () => (cropRegion = this.highlight('', true, undefined, true)); // hyperlink color - const targetCreator = (annotationOn: Doc | undefined) => this.props.anchorMenuCrop!(cropRegion, false)!; + const targetCreator = (/* annotationOn: Doc | undefined */) => this.props.anchorMenuCrop!(cropRegion, false)!; DragManager.StartAnchorAnnoDrag([ele], new DragManager.AnchorAnnoDragData(this.props.docView(), sourceAnchorCreator, targetCreator), e.pageX, e.pageY, { - dragComplete: e => { - if (!e.aborted && e.linkDocument) { - const linkDocData = e.linkDocument[DocData]; + dragComplete: dragEx => { + if (!dragEx.aborted && dragEx.linkDocument) { + const linkDocData = dragEx.linkDocument[DocData]; linkDocData.link_relationship = 'cropped image'; linkDocData.title = 'crop: ' + this.props.Document.title; - linkDocData.link_displayLine = false; } }, }); @@ -252,7 +249,7 @@ export class MarqueeAnnotator extends ObservableReactComponent<MarqueeAnnotatorP const movLoc = this.getTransformedScreenPt([e.clientX, e.clientY]); this._width = movLoc.x - this._start.x; this._height = movLoc.y - this._start.y; - //e.stopPropagation(); // overlay documents are all 'active', yet they can be dragged. if we stop propagation, then they can be marqueed but not dragged. if we don't stop, then they will be marqueed and dragged, but the marquee will be zero width since the doc will move along with the cursor. + // e.stopPropagation(); // overlay documents are all 'active', yet they can be dragged. if we stop propagation, then they can be marqueed but not dragged. if we don't stop, then they will be marqueed and dragged, but the marquee will be zero width since the doc will move along with the cursor. }; onSelectEnd = (e: PointerEvent) => { @@ -268,7 +265,9 @@ export class MarqueeAnnotator extends ObservableReactComponent<MarqueeAnnotatorP // copy the temporary marquee to allow for multiple selections (not currently available though). const copy = document.createElement('div'); const scale = (this.props.scaling?.() || 1) * NumCast(this.props.Document._freeform_scale, 1); - ['border', 'opacity', 'top', 'left', 'width', 'height'].forEach(prop => (copy.style[prop as any] = marqueeStyle[prop as any])); + ['border', 'opacity', 'top', 'left', 'width', 'height'].forEach(prop => { + copy.style[prop as any] = marqueeStyle[prop as any]; + }); copy.className = 'marqueeAnnotator-annotationBox'; copy.style.top = parseInt(marqueeStyle.top.toString().replace('px', '')) / scale + this.props.scrollTop + 'px'; copy.style.left = parseInt(marqueeStyle.left.toString().replace('px', '')) / scale + 'px'; |