aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/formattedText/RichTextMenu.tsx
diff options
context:
space:
mode:
authorBob Zeleznik <zzzman@gmail.com>2020-07-01 11:37:48 -0400
committerBob Zeleznik <zzzman@gmail.com>2020-07-01 11:37:48 -0400
commit9b8b6f79bef78be68a9982ea008e308bba4872b3 (patch)
tree28465274ff5483228c62dcfc0fe09ddbc4fe3e62 /src/client/views/nodes/formattedText/RichTextMenu.tsx
parenta3ce7e180110df7e5908b93418b2dbff80aa89b5 (diff)
fixed text menu to make button commands undoable. fixed hiding of menu to not disappear after pulldown command selection in a cleaner way
Diffstat (limited to 'src/client/views/nodes/formattedText/RichTextMenu.tsx')
-rw-r--r--src/client/views/nodes/formattedText/RichTextMenu.tsx61
1 files changed, 39 insertions, 22 deletions
diff --git a/src/client/views/nodes/formattedText/RichTextMenu.tsx b/src/client/views/nodes/formattedText/RichTextMenu.tsx
index a06fcec9a..7c7a76e1b 100644
--- a/src/client/views/nodes/formattedText/RichTextMenu.tsx
+++ b/src/client/views/nodes/formattedText/RichTextMenu.tsx
@@ -2,7 +2,7 @@ import React = require("react");
import { IconProp, library } from '@fortawesome/fontawesome-svg-core';
import { faBold, faCaretDown, faChevronLeft, faEyeDropper, faHighlighter, faIndent, faItalic, faLink, faPaintRoller, faPalette, faStrikethrough, faSubscript, faSuperscript, faUnderline } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-import { action, observable } from "mobx";
+import { action, observable, IReactionDisposer, reaction } from "mobx";
import { observer } from "mobx-react";
import { lift, wrapIn } from "prosemirror-commands";
import { Mark, MarkType, Node as ProsNode, NodeType, ResolvedPos } from "prosemirror-model";
@@ -23,6 +23,7 @@ import { updateBullets } from "./ProsemirrorExampleTransfer";
import "./RichTextMenu.scss";
import { schema } from "./schema_rts";
import { TraceMobx } from "../../../../fields/util";
+import { UndoManager } from "../../../util/UndoManager";
const { toggleMark } = require("prosemirror-commands");
library.add(faBold, faItalic, faChevronLeft, faUnderline, faStrikethrough, faSuperscript, faSubscript, faIndent, faEyeDropper, faCaretDown, faPalette, faHighlighter, faLink, faPaintRoller);
@@ -68,6 +69,8 @@ export default class RichTextMenu extends AntimodeMenu {
@observable private currentLink: string | undefined = "";
@observable private showLinkDropdown: boolean = false;
+ _reaction: IReactionDisposer | undefined;
+ _delayHide = false;
constructor(props: Readonly<{}>) {
super(props);
RichTextMenu.Instance = this;
@@ -138,6 +141,16 @@ export default class RichTextMenu extends AntimodeMenu {
];
}
+ componentDidMount() {
+ this._reaction = reaction(() => SelectionManager.SelectedDocuments(),
+ () => this._delayHide && !(this._delayHide = false) && this.fadeOut(true));
+ }
+ componentWillUnmount() {
+ this._reaction?.();
+ }
+
+ public delayHide = () => { this._delayHide = true; }
+
@action
changeView(view: EditorView) {
this.view = view;
@@ -147,16 +160,6 @@ export default class RichTextMenu extends AntimodeMenu {
this.updateFromDash(view, lastState, this.editorProps);
}
- public MakeLinkToSelection = (linkDocId: string, title: string, location: string, targetDocId: string): string => {
- if (this.view) {
- const link = this.view.state.schema.marks.link.create({ href: Utils.prepend("/doc/" + linkDocId), title: title, location: location, linkId: linkDocId, targetId: targetDocId });
- this.view.dispatch(this.view.state.tr.removeMark(this.view.state.selection.from, this.view.state.selection.to, this.view.state.schema.marks.link).
- addMark(this.view.state.selection.from, this.view.state.selection.to, link));
- return this.view.state.selection.$from.nodeAfter?.text || "";
- }
- return "";
- }
-
@action
public async updateFromDash(view: EditorView, lastState: EditorState | undefined, props: any) {
if (!view) {
@@ -310,8 +313,11 @@ export default class RichTextMenu extends AntimodeMenu {
function onClick(e: React.PointerEvent) {
e.preventDefault();
e.stopPropagation();
- self.view && command && command(self.view.state, self.view.dispatch, self.view);
- self.view && onclick && onclick(self.view.state, self.view.dispatch, self.view);
+ self.TextView.endUndoTypingBatch();
+ UndoManager.RunInBatch(() => {
+ self.view && command && command(self.view.state, self.view.dispatch, self.view);
+ self.view && onclick && onclick(self.view.state, self.view.dispatch, self.view);
+ }, "rich text menu command");
self.setActiveMarkButtons(self.getActiveMarksOnSelection());
}
@@ -338,9 +344,10 @@ export default class RichTextMenu extends AntimodeMenu {
function onChange(e: React.ChangeEvent<HTMLSelectElement>) {
e.stopPropagation();
e.preventDefault();
+ self.TextView.endUndoTypingBatch();
options.forEach(({ label, mark, command }) => {
if (e.target.value === label) {
- self.view && mark && command(mark, self.view);
+ UndoManager.RunInBatch(() => self.view && mark && command(mark, self.view), "text mark dropdown");
}
});
}
@@ -361,9 +368,10 @@ export default class RichTextMenu extends AntimodeMenu {
const self = this;
function onChange(val: string) {
+ self.TextView.endUndoTypingBatch();
options.forEach(({ label, node, command }) => {
if (val === label) {
- self.view && node && command(node);
+ UndoManager.RunInBatch(() => self.view && node && command(node), "nodes dropdown");
}
});
}
@@ -461,7 +469,8 @@ export default class RichTextMenu extends AntimodeMenu {
function onBrushClick(e: React.PointerEvent) {
e.preventDefault();
e.stopPropagation();
- self.view && self.fillBrush(self.view.state, self.view.dispatch);
+ self.TextView.endUndoTypingBatch();
+ UndoManager.RunInBatch(() => self.view && self.fillBrush(self.view.state, self.view.dispatch), "rt brush");
}
let label = "Stored marks: ";
@@ -528,19 +537,24 @@ export default class RichTextMenu extends AntimodeMenu {
@action toggleColorDropdown() { this.showColorDropdown = !this.showColorDropdown; }
@action setActiveColor(color: string) { this.activeFontColor = color; }
+ get TextView() { return (this.view as any).TextView as FormattedTextBox }
createColorButton() {
const self = this;
function onColorClick(e: React.PointerEvent) {
e.preventDefault();
e.stopPropagation();
- self.view && self.insertColor(self.activeFontColor, self.view.state, self.view.dispatch);
+ self.TextView.endUndoTypingBatch();
+ UndoManager.RunInBatch(() => self.view && self.insertColor(self.activeFontColor, self.view.state, self.view.dispatch), "rt menu color");
+ self.TextView.EditorView!.focus()
}
function changeColor(e: React.PointerEvent, color: string) {
e.preventDefault();
e.stopPropagation();
self.setActiveColor(color);
- self.view && self.insertColor(self.activeFontColor, self.view.state, self.view.dispatch);
+ self.TextView.endUndoTypingBatch();
+ UndoManager.RunInBatch(() => self.view && self.insertColor(self.activeFontColor, self.view.state, self.view.dispatch), "rt menu color");
+ self.TextView.EditorView!.focus()
}
const button =
@@ -585,13 +599,15 @@ export default class RichTextMenu extends AntimodeMenu {
function onHighlightClick(e: React.PointerEvent) {
e.preventDefault();
e.stopPropagation();
- self.view && self.insertHighlight(self.activeHighlightColor, self.view.state, self.view.dispatch);
+ self.TextView.endUndoTypingBatch();
+ UndoManager.RunInBatch(() => self.view && self.insertHighlight(self.activeHighlightColor, self.view.state, self.view.dispatch), "rt highligher");
}
function changeHighlight(e: React.PointerEvent, color: string) {
e.preventDefault();
e.stopPropagation();
self.setActiveHighlight(color);
- self.view && self.insertHighlight(self.activeHighlightColor, self.view.state, self.view.dispatch);
+ self.TextView.endUndoTypingBatch();
+ UndoManager.RunInBatch(() => self.view && self.insertHighlight(self.activeHighlightColor, self.view.state, self.view.dispatch), "rt highlighter");
}
const button =
@@ -631,7 +647,8 @@ export default class RichTextMenu extends AntimodeMenu {
const self = this;
function onLinkChange(e: React.ChangeEvent<HTMLInputElement>) {
- self.setCurrentLink(e.target.value);
+ self.TextView.endUndoTypingBatch();
+ UndoManager.RunInBatch(() => self.setCurrentLink(e.target.value), "link change");
}
const link = this.currentLink ? this.currentLink : "";
@@ -766,7 +783,7 @@ export default class RichTextMenu extends AntimodeMenu {
return ref_node;
}
- @action onPointerEnter(e: React.PointerEvent) { RichTextMenu.Instance.overMenu = true; }
+ @action onPointerEnter(e: React.PointerEvent) { RichTextMenu.Instance.overMenu = false; }
@action onPointerLeave(e: React.PointerEvent) { RichTextMenu.Instance.overMenu = false; }
@action