aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/formattedText
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/nodes/formattedText')
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBox.tsx82
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx2
-rw-r--r--src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts2
-rw-r--r--src/client/views/nodes/formattedText/RichTextMenu.tsx29
4 files changed, 56 insertions, 59 deletions
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index f9982f747..e06a324d2 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\"");
@@ -359,7 +361,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
DocListCast(this.dataDoc.links).map((l, i) => {
let la1 = l.anchor1 as Doc;
let la2 = l.anchor2 as Doc;
- this._linkTime = NumCast(la1.audioStart, NumCast(la2.audioStart));
+ this._linkTime = NumCast(la1.anchorStartTime, NumCast(la2.anchorStartTime));
audioState = la2.audioState;
if (Doc.AreProtosEqual(la2, this.dataDoc)) {
la1 = l.anchor2 as Doc;
@@ -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/nodes/formattedText/FormattedTextBoxComment.tsx b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
index 8867595ff..5371bd10a 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
@@ -121,7 +121,7 @@ export class FormattedTextBoxComment {
}
}
} else if (textBox && (FormattedTextBoxComment.tooltipText as any).href) {
- textBox.props.addDocTab(Docs.Create.WebDocument((FormattedTextBoxComment.tooltipText as any).href, { title: (FormattedTextBoxComment.tooltipText as any).href, _fitWidth: true, _width: 200, _height: 400, useCors: true }), "add:right");
+ textBox.props.addDocTab(Docs.Create.WebDocument((FormattedTextBoxComment.tooltipText as any).href, { title: (FormattedTextBoxComment.tooltipText as any).href, _width: 200, _height: 400, useCors: true }), "add:right");
}
keep && textBox && FormattedTextBoxComment.start !== undefined && textBox.adoptAnnotation(
FormattedTextBoxComment.start, FormattedTextBoxComment.end, FormattedTextBoxComment.mark);
diff --git a/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts b/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts
index cb5823e86..8d9d36580 100644
--- a/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts
+++ b/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts
@@ -135,7 +135,7 @@ export function buildKeymap<S extends Schema<any>>(schema: S, props: any, mapKey
//Command to create a new Tab with a PDF of all the command shortcuts
bind("Mod-/", (state: EditorState<S>, dispatch: (tx: Transaction<S>) => void) => {
- const newDoc = Docs.Create.PdfDocument(Utils.prepend("/assets/cheat-sheet.pdf"), { _fitWidth: true, _width: 300, _height: 300 });
+ const newDoc = Docs.Create.PdfDocument(Utils.prepend("/assets/cheat-sheet.pdf"), { _width: 300, _height: 300 });
props.addDocTab(newDoc, "add:right");
});
diff --git a/src/client/views/nodes/formattedText/RichTextMenu.tsx b/src/client/views/nodes/formattedText/RichTextMenu.tsx
index 07439825f..dc630af74 100644
--- a/src/client/views/nodes/formattedText/RichTextMenu.tsx
+++ b/src/client/views/nodes/formattedText/RichTextMenu.tsx
@@ -56,7 +56,6 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> {
@observable private activeListType: string = "";
@observable private activeAlignment: string = "left";
- @observable private brushIsEmpty: boolean = true;
@observable private brushMarks: Set<Mark> = new Set();
@observable private showBrushDropdown: boolean = false;
@@ -600,12 +599,12 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> {
createBrushButton() {
const self = this;
- function onBrushClick(e: React.PointerEvent) {
+ const onBrushClick = (e: React.MouseEvent) => {
e.preventDefault();
e.stopPropagation();
self.TextView.endUndoTypingBatch();
UndoManager.RunInBatch(() => self.view && self.fillBrush(self.view.state, self.view.dispatch), "rt brush");
- }
+ };
let label = "Stored marks: ";
if (this.brushMarks && this.brushMarks.size > 0) {
@@ -622,8 +621,7 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> {
//onPointerDown={onBrushClick}
const button = <Tooltip title={<div className="dash-tooltip">style brush</div>} placement="bottom">
-
- <button className="antimodeMenu-button" style={this.brushMarks?.size > 0 ? { backgroundColor: "121212" } : {}}>
+ <button className="antimodeMenu-button" onClick={onBrushClick} style={this.brushMarks?.size > 0 ? { backgroundColor: "121212" } : {}}>
<FontAwesomeIcon icon="paint-roller" size="lg" style={{ transitionProperty: "transform", transitionDuration: "0.1s", transform: `rotate(${this.brushMarks?.size > 0 ? 45 : 0}deg)` }} />
</button>
</Tooltip>;
@@ -636,13 +634,12 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> {
</div>;
return (
- <ButtonDropdown view={this.view} key={"brush dropdown"} button={button} dropdownContent={dropdownContent} openDropdownOnButton={true} />
+ <ButtonDropdown view={this.view} key={"brush dropdown"} button={button} openDropdownOnButton={false} dropdownContent={dropdownContent} />
);
}
@action
clearBrush() {
- RichTextMenu.Instance.brushIsEmpty = true;
RichTextMenu.Instance.brushMarks = new Set();
}
@@ -650,26 +647,22 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> {
fillBrush(state: EditorState<any>, dispatch: any) {
if (!this.view) return;
- if (this.brushIsEmpty) {
+ if (!Array.from(this.brushMarks.keys()).length) {
const selected_marks = this.getMarksInSelection(this.view.state);
if (selected_marks.size >= 0) {
this.brushMarks = selected_marks;
- this.brushIsEmpty = !this.brushIsEmpty;
}
}
else {
const { from, to, $from } = this.view.state.selection;
if (!this.view.state.selection.empty && $from && $from.nodeAfter) {
- if (this.brushMarks && to - from > 0) {
+ if (to - from > 0) {
this.view.dispatch(this.view.state.tr.removeMark(from, to));
Array.from(this.brushMarks).filter(m => m.type !== schema.marks.user_mark).forEach((mark: Mark) => {
this.setMark(mark, this.view!.state, this.view!.dispatch);
});
}
}
- else {
- this.brushIsEmpty = !this.brushIsEmpty;
- }
}
}
@@ -817,8 +810,7 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> {
<button className="remove-button" onPointerDown={e => this.deleteLink()}>Remove link</button>
</div>;
- return <ButtonDropdown view={this.view} key={"link button"} button={button} dropdownContent={dropdownContent}
- openDropdownOnButton={true} link={true} />;
+ return <ButtonDropdown view={this.view} key={"link button"} button={button} dropdownContent={dropdownContent} openDropdownOnButton={true} link={true} />;
}
async getTextLinkTargetTitle() {
@@ -1027,6 +1019,7 @@ interface ButtonDropdownProps {
openDropdownOnButton?: boolean;
link?: boolean;
pdf?: boolean;
+
}
@observer
@@ -1071,9 +1064,11 @@ export class ButtonDropdown extends React.Component<ButtonDropdownProps> {
return (
<div className="button-dropdown-wrapper" ref={node => this.ref = node}>
{!this.props.pdf ?
- <div className="antimodeMenu-button dropdown-button-combined" onPointerDown={this.onDropdownClick}>
+ <div className="antimodeMenu-button dropdown-button-combined" onPointerDown={this.props.openDropdownOnButton ? this.onDropdownClick : undefined}>
{this.props.button}
- <div style={{ marginTop: "-8.5" }}><FontAwesomeIcon icon="caret-down" size="sm" /></div>
+ <div style={{ marginTop: "-8.5", position: "relative" }} onPointerDown={!this.props.openDropdownOnButton ? this.onDropdownClick : undefined}>
+ <FontAwesomeIcon icon="caret-down" size="sm" />
+ </div>
</div>
:
<>