From 9e809f8748d1812bb03ec6471aa6f97467f8f75a Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Tue, 23 Apr 2024 16:20:08 -0400
Subject: fixes for rich text menu updates and setting parameters on text doc
 vs within in RTF. Lots of lint cleanup.

---
 .../views/nodes/formattedText/RichTextMenu.tsx     | 56 ++++++++++------------
 1 file changed, 26 insertions(+), 30 deletions(-)

(limited to 'src/client/views/nodes/formattedText/RichTextMenu.tsx')

diff --git a/src/client/views/nodes/formattedText/RichTextMenu.tsx b/src/client/views/nodes/formattedText/RichTextMenu.tsx
index 6108383c2..6c12b9991 100644
--- a/src/client/views/nodes/formattedText/RichTextMenu.tsx
+++ b/src/client/views/nodes/formattedText/RichTextMenu.tsx
@@ -10,7 +10,6 @@ import { EditorView } from 'prosemirror-view';
 import * as React from 'react';
 import { Doc } from '../../../../fields/Doc';
 import { BoolCast, Cast, StrCast } from '../../../../fields/Types';
-import { numberRange } from '../../../../Utils';
 import { DocServer } from '../../../DocServer';
 import { LinkManager } from '../../../util/LinkManager';
 import { SelectionManager } from '../../../util/SelectionManager';
@@ -147,12 +146,13 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> {
         const { activeHighlights } = active;
         const refDoc = SelectionManager.Views.lastElement()?.layoutDoc ?? Doc.UserDoc();
         const refField = (pfx => (pfx ? pfx + '_' : ''))(SelectionManager.Views.lastElement()?.LayoutFieldKey);
+        const refVal = (field: string, dflt: string) => StrCast(refDoc[refField + field], StrCast(Doc.UserDoc()[field], dflt));
 
         this._activeListType = this.getActiveListStyle();
         this._activeAlignment = this.getActiveAlignment();
-        this._activeFontFamily = !activeFamilies.length ? StrCast(this.TextView?.Document._text_fontFamily, StrCast(refDoc[refField + 'fontFamily'], 'Arial')) : activeFamilies.length === 1 ? String(activeFamilies[0]) : 'various';
-        this._activeFontSize = !activeSizes.length ? StrCast(this.TextView?.Document.fontSize, StrCast(refDoc[refField + 'fontSize'], '10px')) : activeSizes[0];
-        this._activeFontColor = !activeColors.length ? StrCast(this.TextView?.Document.fontColor, StrCast(refDoc[refField + 'fontColor'], 'black')) : activeColors.length > 0 ? String(activeColors[0]) : '...';
+        this._activeFontFamily = !activeFamilies.length ? StrCast(this.TextView?.Document._text_fontFamily, refVal('fontFamily', 'Arial')) : activeFamilies.length === 1 ? String(activeFamilies[0]) : 'various';
+        this._activeFontSize = !activeSizes.length ? StrCast(this.TextView?.Document.fontSize, refVal('fontSize', '10px')) : activeSizes[0];
+        this._activeFontColor = !activeColors.length ? StrCast(this.TextView?.Document.fontColor, refVal('fontColor', 'black')) : activeColors.length > 0 ? String(activeColors[0]) : '...';
         this._activeHighlightColor = !activeHighlights.length ? '' : activeHighlights.length > 0 ? String(activeHighlights[0]) : '...';
 
         // update link in current selection
@@ -161,12 +161,7 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> {
 
     setMark = (mark: Mark, state: EditorState, dispatch: any, dontToggle: boolean = false) => {
         if (mark) {
-            const liFirst = numberRange(state.selection.$from.depth + 1).find(i => state.selection.$from.node(i)?.type === state.schema.nodes.list_item);
-            const liTo = numberRange(state.selection.$to.depth + 1).find(i => state.selection.$to.node(i)?.type === state.schema.nodes.list_item);
-            const olFirst = numberRange(state.selection.$from.depth + 1).find(i => state.selection.$from.node(i)?.type === state.schema.nodes.ordered_list);
-            const nodeOl = (liFirst && liTo && state.selection.$from.node(liFirst) !== state.selection.$to.node(liTo) && olFirst) || (!liFirst && !liTo && olFirst);
-            const fromRange = numberRange(state.selection.from).reverse();
-            const newPos = nodeOl ? fromRange.find(i => state.doc.nodeAt(i)?.type === state.schema.nodes.ordered_list) ?? state.selection.from : state.selection.from;
+            const newPos = state.selection.$anchor.node()?.type === schema.nodes.ordered_list ? state.selection.from : state.selection.from;
             const node = (state.selection as NodeSelection).node ?? (newPos >= 0 ? state.doc.nodeAt(newPos) : undefined);
             if (node?.type === schema.nodes.ordered_list || node?.type === schema.nodes.list_item) {
                 const hasMark = node.marks.some(m => m.type === mark.type);
@@ -174,18 +169,16 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> {
                 const addAnyway = node.marks.filter(m => m.type === mark.type && Object.keys(m.attrs).some(akey => m.attrs[akey] !== mark.attrs[akey]));
                 const markup = state.tr.setNodeMarkup(newPos, node.type, node.attrs, hasMark && !addAnyway ? otherMarks : [...otherMarks, mark]);
                 dispatch(updateBullets(markup, state.schema));
-            } else {
-                const state = this.view?.state;
-                if (state) {
-                    const { tr } = state;
-                    if (dontToggle) {
-                        tr.addMark(state.selection.from, state.selection.to, mark);
-                        dispatch(tr.setSelection(new TextSelection(tr.doc.resolve(state.selection.from), tr.doc.resolve(state.selection.to)))); // bcz: need to redo the selection because ctrl-a selections disappear otherwise
-                    } else {
-                        toggleMark(mark.type, mark.attrs)(state, dispatch);
-                    }
+            } else if (state) {
+                const { tr } = state;
+                if (dontToggle) {
+                    tr.addMark(state.selection.from, state.selection.to, mark);
+                    dispatch(tr.setSelection(new TextSelection(tr.doc.resolve(state.selection.from), tr.doc.resolve(state.selection.to)))); // bcz: need to redo the selection because ctrl-a selections disappear otherwise
+                } else {
+                    toggleMark(mark.type, mark.attrs)(state, dispatch);
                 }
             }
+            this.updateMenu(this.view, undefined, undefined, this.layoutDoc);
         }
     };
 
@@ -242,7 +235,7 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> {
                 m.type === state.schema.marks.pFontFamily && activeFamilies.add(m.attrs.fontFamily);
                 m.type === state.schema.marks.pFontColor && activeColors.add(m.attrs.fontColor);
                 m.type === state.schema.marks.pFontSize && activeSizes.add(m.attrs.fontSize);
-                m.type === state.schema.marks.pFontHighlight && activeHighlights.add(String(m.attrs.fontHigh));
+                m.type === state.schema.marks.pFontHighlight && activeHighlights.add(String(m.attrs.fontHighlight));
             });
         } else if (SelectionManager.Views.some(dv => dv.ComponentView instanceof EquationBox)) {
             SelectionManager.Views.forEach(dv => StrCast(dv.Document._text_fontSize) && activeSizes.add(StrCast(dv.Document._text_fontSize)));
@@ -359,18 +352,21 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> {
 
     setFontField = (value: string, fontField: 'fontSize' | 'fontFamily' | 'fontColor' | 'fontHighlight') => {
         if (this.view) {
-            if (this.view.state.selection.from === 1 && this.view.state.selection.empty && (!this.view.state.doc.nodeAt(1) || !this.view.state.doc.nodeAt(1)?.marks.some(m => m.type.name === value))) {
+            const { text, paragraph } = this.view.state.schema.nodes;
+            const selNode = this.view.state.selection.$anchor.node();
+            if (this.view.state.selection.from === 1 && this.view.state.selection.empty && [undefined, text, paragraph].includes(selNode?.type)) {
                 this.TextView.dataDoc[this.TextView.fieldKey + `_${fontField}`] = value;
                 this.view.focus();
-            } else {
-                const attrs: { [key: string]: string } = {};
-                attrs[fontField] = value;
-                const fmark = this.view?.state.schema.marks['pF' + fontField.substring(1)].create(attrs);
-                this.setMark(fmark, this.view.state, (tx: any) => this.view!.dispatch(tx.addStoredMark(fmark)), true);
-                this.view.focus();
             }
-        } else Doc.UserDoc()[fontField] = value;
-        this.updateMenu(this.view, undefined, this.props, this.layoutDoc);
+            const attrs: { [key: string]: string } = {};
+            attrs[fontField] = value;
+            const fmark = this.view?.state.schema.marks['pF' + fontField.substring(1)].create(attrs);
+            this.setMark(fmark, this.view.state, (tx: any) => this.view!.dispatch(tx.addStoredMark(fmark)), true);
+            this.view.focus();
+        } else {
+            Doc.UserDoc()[fontField] = value;
+            this.updateMenu(this.view, undefined, this.props, this.layoutDoc);
+        }
     };
 
     // TODO: remove doesn't work
-- 
cgit v1.2.3-70-g09d2

