diff options
-rw-r--r-- | src/client/views/linking/LinkMenuItem.tsx | 3 | ||||
-rw-r--r-- | src/client/views/nodes/ImageBox.tsx | 1 | ||||
-rw-r--r-- | src/client/views/nodes/VideoBox.tsx | 1 | ||||
-rw-r--r-- | src/client/views/nodes/WebBox.tsx | 1 | ||||
-rw-r--r-- | src/client/views/nodes/formattedText/FormattedTextBox.tsx | 80 | ||||
-rw-r--r-- | src/client/views/pdf/AnchorMenu.tsx | 11 | ||||
-rw-r--r-- | src/client/views/pdf/Annotation.tsx | 6 | ||||
-rw-r--r-- | src/client/views/pdf/PDFViewer.tsx | 2 |
8 files changed, 56 insertions, 49 deletions
diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx index d6cefa5b0..19ef03a31 100644 --- a/src/client/views/linking/LinkMenuItem.tsx +++ b/src/client/views/linking/LinkMenuItem.tsx @@ -127,9 +127,10 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> { @undoBatch @action - deleteLink = (): void => { + deleteLink = (e: React.PointerEvent): void => { this.props.linkDoc.linksToAnnotation && Hypothesis.deleteLink(this.props.linkDoc, this.props.sourceDoc, this.props.destinationDoc); LinkManager.Instance.deleteLink(this.props.linkDoc); + e.stopPropagation(); runInAction(() => { LinkDocPreview.LinkInfo = undefined; diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index 47fa25951..649fe8f40 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -83,7 +83,6 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps, ImageD if (!selected) { this._savedAnnotations.values().forEach(v => v.forEach(a => a.remove())); this._savedAnnotations.clear(); - AnchorMenu.Instance.fadeOut(true); } }, { fireImmediately: true }); diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx index 55a9818ad..6354c677e 100644 --- a/src/client/views/nodes/VideoBox.tsx +++ b/src/client/views/nodes/VideoBox.tsx @@ -195,7 +195,6 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps, VideoD if (!selected) { this._savedAnnotations.values().forEach(v => v.forEach(a => a.remove())); this._savedAnnotations.clear(); - AnchorMenu.Instance.fadeOut(true); } }, { fireImmediately: true }); diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index c9c4ed159..69f797880 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -161,7 +161,6 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum if (!selected) { this._savedAnnotations.values().forEach(v => v.forEach(a => a.remove())); this._savedAnnotations.clear(); - 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 f9982f747..ac5ea66ff 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -59,7 +59,7 @@ import { FormattedTextBoxComment, formattedTextBoxCommentPlugin, findLinkMark } import React = require("react"); import { LinkManager } from '../../../util/LinkManager'; import { CollectionStackingView } from '../../collections/CollectionStackingView'; -import { CollectionViewType, CollectionViewProps } from '../../collections/CollectionView'; +import { CollectionViewType } from '../../collections/CollectionView'; import { SnappingManager } from '../../../util/SnappingManager'; import { LinkDocPreview } from '../LinkDocPreview'; import { SubCollectionViewProps } from '../../collections/CollectionSubView'; @@ -85,6 +85,7 @@ type PullHandler = (exportState: Opt<GoogleApiClientUtils.Docs.ImportResult>, da export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProps & FormattedTextBoxProps), RichTextDocument>(RichTextDocument) { public static LayoutString(fieldStr: string) { return FieldView.LayoutString(FormattedTextBox, fieldStr); } public static blankState = () => EditorState.create(FormattedTextBox.Instance.config); + public static CanAnnotate = true; public static Instance: FormattedTextBox; public ProseRef?: HTMLDivElement; public get EditorView() { return this._editorView; } @@ -211,6 +212,42 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp this.linkOnDeselect.clear(); } + @action + setupAnchorMenu = () => { + 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); + this.props.isSelected(true) && AnchorMenu.Instance.jumpTo(Math.min(coordsT.left, coordsB.left), Math.max(coordsT.bottom, coordsB.bottom)); + } + dispatchTransaction = (tx: Transaction) => { let timeStamp; clearTimeout(timeStamp); @@ -254,42 +291,7 @@ 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)); - } + if (!this._editorView.state.selection.empty && FormattedTextBox.CanAnnotate) this.setupAnchorMenu(); const removeSelection = (json: string | undefined) => { return json?.indexOf("\"storedMarks\"") === -1 ? json?.replace(/"selection":.*/, "") : json?.replace(/"selection":"\"storedMarks\""/, "\"storedMarks\""); @@ -658,6 +660,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp const uicontrols: ContextMenuProps[] = []; + uicontrols.push({ description: `${FormattedTextBox.CanAnnotate ? "Hide" : "Show"} Annotation Bar`, event: () => FormattedTextBox.CanAnnotate = !FormattedTextBox.CanAnnotate, icon: "expand-arrows-alt" }); uicontrols.push({ description: `${this.layoutDoc._showAudio ? "Hide" : "Show"} Dictation Icon`, event: () => this.layoutDoc._showAudio = !this.layoutDoc._showAudio, icon: "expand-arrows-alt" }); uicontrols.push({ description: "Show Highlights...", noexpand: true, subitems: highlighting, icon: "hand-point-right" }); !Doc.UserDoc().noviceMode && uicontrols.push({ description: `Create TimeStamp When ${this.layoutDoc._timeStampOnEnter ? "Pause" : "Enter"}`, event: () => this.layoutDoc._timeStampOnEnter = !this.layoutDoc._timeStampOnEnter, icon: "expand-arrows-alt" }); @@ -999,7 +1002,6 @@ 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); } @@ -1296,9 +1298,9 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp } componentWillUnmount() { + Object.values(this._disposers).forEach(disposer => disposer?.()); this.endUndoTypingBatch(); this.unhighlightSearchTerms(); - Object.values(this._disposers).forEach(disposer => disposer?.()); this._editorView?.destroy(); FormattedTextBoxComment.tooltip && (FormattedTextBoxComment.tooltip.style.display = "none"); } diff --git a/src/client/views/pdf/AnchorMenu.tsx b/src/client/views/pdf/AnchorMenu.tsx index e2bd5a73d..d1fdc6c44 100644 --- a/src/client/views/pdf/AnchorMenu.tsx +++ b/src/client/views/pdf/AnchorMenu.tsx @@ -1,7 +1,7 @@ import React = require("react"); import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { Tooltip } from "@material-ui/core"; -import { action, computed, observable } from "mobx"; +import { action, computed, observable, IReactionDisposer, reaction } from "mobx"; import { observer } from "mobx-react"; import { ColorState } from "react-color"; import { Doc, Opt } from "../../../fields/Doc"; @@ -9,6 +9,7 @@ import { returnFalse, setupMoveUpEvents, unimplementedFunction, Utils } from ".. import { AntimodeMenu, AntimodeMenuProps } from "../AntimodeMenu"; import { ButtonDropdown } from "../nodes/formattedText/RichTextMenu"; import "./AnchorMenu.scss"; +import { SelectionManager } from "../../util/SelectionManager"; @observer export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> { @@ -58,6 +59,14 @@ export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> { AnchorMenu.Instance._canFade = false; } + _disposer: IReactionDisposer | undefined; + componentDidMount() { + this._disposer = reaction(() => SelectionManager.Views(), + selected => { + AnchorMenu.Instance.fadeOut(true); + }); + } + pointerDown = (e: React.PointerEvent) => { setupMoveUpEvents(this, e, (e: PointerEvent) => { this.StartDrag(e, this._commentCont.current!); diff --git a/src/client/views/pdf/Annotation.tsx b/src/client/views/pdf/Annotation.tsx index 85dd65901..cd32c2c3a 100644 --- a/src/client/views/pdf/Annotation.tsx +++ b/src/client/views/pdf/Annotation.tsx @@ -67,8 +67,8 @@ class RegionAnnotation extends React.Component<IRegionAnnotationProps> { } componentWillUnmount() { - this._brushDisposer && this._brushDisposer(); - this._reactionDisposer && this._reactionDisposer(); + this._brushDisposer?.(); + this._reactionDisposer?.(); } @undoBatch @@ -83,8 +83,8 @@ class RegionAnnotation extends React.Component<IRegionAnnotationProps> { DocListCast(group.annotations).forEach(anno => anno.delete = true); } - AnchorMenu.Instance.fadeOut(true); + this.props.select(false); } @undoBatch diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index f2052d454..fa97bde3f 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -137,7 +137,6 @@ 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, [])); - AnchorMenu.Instance.fadeOut(true); } (SelectionManager.Views().length === 1) && this.setupPdfJsViewer(); }, @@ -389,7 +388,6 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu } else { // clear out old marquees and initialize menu for new selection 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" }); |