From 20611e69b3f4afca5d35a440278f4dcbbda523c7 Mon Sep 17 00:00:00 2001
From: alyssaf16 <alyssa_feinberg@brown.edu>
Date: Mon, 24 Jun 2024 13:05:02 -0400
Subject: language menu

---
 src/client/views/ContextMenu.tsx | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

(limited to 'src/client/views/ContextMenu.tsx')

diff --git a/src/client/views/ContextMenu.tsx b/src/client/views/ContextMenu.tsx
index d784a14b8..348d248c8 100644
--- a/src/client/views/ContextMenu.tsx
+++ b/src/client/views/ContextMenu.tsx
@@ -182,7 +182,8 @@ export class ContextMenu extends ObservableReactComponent<{}> {
 
     @computed get menuItems() {
         if (!this._searchString) {
-            return this._items.map((item, ind) => <ContextMenuItem key={item.description + ind} {...item} noexpand={this.itemsNeedSearch ? true : (item as any).noexpand} closeMenu={this.closeMenu} />);
+            console.log('HERESDF');
+            return this._items.map((item, ind) => <ContextMenuItem key={item.description + ind} {...item} selected={ind === this._selectedIndex} noexpand={this.itemsNeedSearch ? true : (item as any).noexpand} closeMenu={this.closeMenu} />);
         }
         return this.filteredItems.map((value, index) =>
             Array.isArray(value) ? (
@@ -249,6 +250,11 @@ export class ContextMenu extends ObservableReactComponent<{}> {
         );
     }
 
+    @action
+    setLangIndex = (ind: number) => {
+        this._selectedIndex = ind;
+    };
+
     @action
     onKeyDown = (e: React.KeyboardEvent) => {
         if (e.key === 'ArrowDown') {
-- 
cgit v1.2.3-70-g09d2


From 07f525dc8eef3fdedc476af1a98b5bb35314b6c6 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Mon, 30 Sep 2024 15:03:57 -0400
Subject: cleaned up some lint errors.

---
 src/client/views/ContextMenu.tsx                         |  3 ---
 src/client/views/nodes/AudioBox.tsx                      |  3 +--
 src/client/views/nodes/ImageBox.tsx                      | 11 ++++-------
 src/client/views/nodes/PDFBox.tsx                        |  5 +----
 .../views/nodes/formattedText/FormattedTextBox.tsx       | 16 +++++-----------
 src/client/views/pdf/AnchorMenu.tsx                      |  5 ++---
 src/client/views/pdf/PDFViewer.tsx                       |  2 --
 src/fields/Doc.ts                                        |  4 ----
 8 files changed, 13 insertions(+), 36 deletions(-)

(limited to 'src/client/views/ContextMenu.tsx')

diff --git a/src/client/views/ContextMenu.tsx b/src/client/views/ContextMenu.tsx
index 0e98d2e35..e0eeb3f53 100644
--- a/src/client/views/ContextMenu.tsx
+++ b/src/client/views/ContextMenu.tsx
@@ -1,6 +1,3 @@
-/* eslint-disable react/no-array-index-key */
-/* eslint-disable react/jsx-props-no-spreading */
-/* eslint-disable default-param-last */
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { action, computed, IReactionDisposer, makeObservable, observable, runInAction } from 'mobx';
 import { observer } from 'mobx-react';
diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx
index 8056ced1e..aaeb1eb31 100644
--- a/src/client/views/nodes/AudioBox.tsx
+++ b/src/client/views/nodes/AudioBox.tsx
@@ -8,7 +8,7 @@ import { DateField } from '../../../fields/DateField';
 import { Doc, Opt } from '../../../fields/Doc';
 import { DocData } from '../../../fields/DocSymbols';
 import { ComputedField } from '../../../fields/ScriptField';
-import { Cast, DateCast, DocCast, NumCast } from '../../../fields/Types';
+import { Cast, DateCast, NumCast } from '../../../fields/Types';
 import { AudioField, nullAudio } from '../../../fields/URLField';
 import { formatTime } from '../../../Utils';
 import { Docs } from '../../documents/Documents';
@@ -741,7 +741,6 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
                 ref={action((r: CollectionStackedTimeline | null) => {
                     this._stackedTimeline = r;
                 })}
-                // eslint-disable-next-line react/jsx-props-no-spreading
                 {...this._props}
                 dataFieldKey={this.fieldKey}
                 fieldKey={this.annotationKey}
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index 91e51d24e..ae9e70e8d 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -316,7 +316,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
         return cropping;
     };
 
-    createCanvas = async (downX?: number, downY?: number, cb?: (filename: string, x: number | undefined, y: number | undefined) => void) => {
+    createCanvas = async () => {
         const canvas = document.createElement('canvas');
         const scaling = 1 / (this._props.NativeDimScaling?.() || 1);
         const w = AnchorMenu.Instance.marqueeWidth * scaling;
@@ -393,9 +393,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
      * @param texts
      */
     createBoxes = (boxes: [[[number, number]]], texts: [string]) => {
-        const nscale = NumCast(this._props.PanelWidth()) * NumCast(this.layoutDoc._freeform_scale, 1);
-        const nw = nscale / NumCast(this.dataDoc[this.fieldKey + '_nativeWidth']);
-        for (var i = 0; i < boxes.length; i++) {
+        for (let i = 0; i < boxes.length; i++) {
             const coords = boxes[i] ? boxes[i] : [];
             const width = coords[1][0] - coords[0][0];
             const height = coords[2][1] - coords[0][1];
@@ -432,7 +430,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
             const response = await gptImageLabel(hrefBase64, 'Make flashcards out of this image with each question and answer labeled as "question" and "answer". Do not label each flashcard and do not include asterisks: ');
             AnchorMenu.Instance.transferToFlashcard(response, NumCast(this.layoutDoc['x']), NumCast(this.layoutDoc['y']));
         } catch (error) {
-            console.log('Error');
+            console.log('Error', error);
         }
         this._loading = false;
     };
@@ -442,7 +440,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
             const hrefBase64 = await this.createCanvas();
             this.pushInfo(quizMode.NORMAL, hrefBase64);
         } catch (error) {
-            console.log('Error');
+            console.log('Error', error);
         }
     };
 
@@ -824,7 +822,6 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
                 }}>
                 <CollectionFreeFormView
                     ref={this._ffref}
-                    // eslint-disable-next-line react/jsx-props-no-spreading
                     {...this._props}
                     setContentViewBox={emptyFunction}
                     NativeWidth={returnZero}
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index cb0b0d71f..596975062 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -10,7 +10,7 @@ import { DocData } from '../../../fields/DocSymbols';
 import { Id } from '../../../fields/FieldSymbols';
 import { InkTool } from '../../../fields/InkField';
 import { ComputedField } from '../../../fields/ScriptField';
-import { Cast, FieldValue, ImageCast, NumCast, StrCast, toList } from '../../../fields/Types';
+import { Cast, FieldValue, NumCast, StrCast, toList } from '../../../fields/Types';
 import { ImageField, PdfField } from '../../../fields/URLField';
 import { TraceMobx } from '../../../fields/util';
 import { emptyFunction } from '../../../Utils';
@@ -540,7 +540,6 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
             return ComponentTag === CollectionStackingView ? (
                 <SidebarAnnos
                     ref={this._sidebarRef}
-                    // eslint-disable-next-line react/jsx-props-no-spreading
                     {...this._props}
                     Document={this.Document}
                     layoutDoc={this.layoutDoc}
@@ -556,7 +555,6 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
             ) : (
                 <div onPointerDown={e => setupMoveUpEvents(this, e, returnFalse, emptyFunction, () => this._props.select(false), true)}>
                     <ComponentTag
-                        // eslint-disable-next-line react/jsx-props-no-spreading
                         {...this._props}
                         setContentViewBox={emptyFunction} // override setContentView to do nothing
                         NativeWidth={this.sidebarNativeWidthFunc}
@@ -610,7 +608,6 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
                         top: 0,
                     }}>
                     <PDFViewer
-                        // eslint-disable-next-line react/jsx-props-no-spreading
                         {...this._props}
                         pdfBox={this}
                         sidebarAddDoc={this.sidebarAddDocument}
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index 07a4d1093..9b3e1ca39 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -141,6 +141,9 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
     set _recordingDictation(value) {
         !this.dataDoc[`${this.fieldKey}_recordingSource`] && (this.dataDoc.mediaState = value ? mediaState.Recording : undefined);
     }
+
+    // eslint-disable-next-line no-return-assign
+    @computed get config()                     { return FormattedTextBox.MakeConfig(this._rules = new RichTextRules(this.Document, this), this._props); } // prettier-ignore
     @computed get _recordingDictation()        { return this.dataDoc?.mediaState === mediaState.Recording; } // prettier-ignore
     @computed get SidebarShown()               {  return !!(this._showSidebar || this.layoutDoc._layout_showSidebar);  } // prettier-ignore
     @computed get allSidebarDocs()             { return DocListCast(this.dataDoc[this.sidebarKey]); } // prettier-ignore
@@ -153,7 +156,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
     @computed get sidebarHeight()              { return !this.sidebarWidth() ? 0 : NumCast(this.dataDoc[this.sidebarKey + '_height']); } // prettier-ignore
     @computed get titleHeight()                { return this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.HeaderMargin) as number || 0; } // prettier-ignore
     @computed get layout_autoHeightMargins()   { return this.titleHeight + NumCast(this.layoutDoc._layout_autoHeightMargins); } // prettier-ignore
-    @computed get config()                     { return FormattedTextBox.MakeConfig(this._rules = new RichTextRules(this.Document, this), this._props); } // prettier-ignore
     @computed get sidebarKey()                 { return this.fieldKey + '_sidebar'; } // prettier-ignore
 
     constructor(props: FormattedTextBoxProps) {
@@ -663,7 +665,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
                         textContent += node.child(i).textContent;
                         i++;
                     }
-                    // eslint-disable-next-line no-cond-assign
                     while (ep && (foundAt = textContent.slice(index).search(regexp)) > -1) {
                         const sel = new TextSelection(pm.state.doc.resolve(ep.from + index + blockOffset + foundAt + 1), pm.state.doc.resolve(ep.from + index + blockOffset + foundAt + find.length + 1));
                         ret.push(sel);
@@ -722,7 +723,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
             const hr = Math.round(Date.now() / 1000 / 60 / 60);
             numberRange(10).map(i => addStyleSheetRule(FormattedTextBox._userStyleSheet, 'UM-hr-' + (hr - i), { opacity: ((10 - i - 1) / 10).toString() }));
         }
-        // eslint-disable-next-line operator-assignment
         this.layoutDoc[DocCss] = this.layoutDoc[DocCss] + 1; // css changes happen outside of react/mobx.  so we need to set a flag that will notify anyone interested in layout changes triggered by css changes (eg., CollectionLinkView)
     };
 
@@ -987,7 +987,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
     findImageTags = async () => {
         const c = this.ProseRef?.getElementsByTagName('img');
         if (c) {
-            for (let i of c) {
+            for (const i of c) {
                 console.log(i);
 
                 // console.log(canvas.toDataURL());
@@ -1034,7 +1034,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
             // this.Document[DocData].description = response.trim();
             // return response; // Return the response
         } catch (error) {
-            console.log('Error');
+            console.log('Error', error);
         }
         // return '';
     };
@@ -1195,7 +1195,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
             const nodes: Node[] = [];
             let hadStart = start !== 0;
             frag.forEach((node, index) => {
-                // eslint-disable-next-line no-use-before-define
                 const examinedNode = findAnchorNode(node, editor);
                 if (examinedNode?.node && (examinedNode.node.textContent || examinedNode.node.type === this._editorView?.state.schema.nodes.dashDoc || examinedNode.node.type === this._editorView?.state.schema.nodes.audiotag)) {
                     nodes.push(examinedNode.node);
@@ -1349,7 +1348,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
             action(selected => {
                 this.prepareForTyping();
                 if (FormattedTextBox._globalHighlights.has('Bold Text')) {
-                    // eslint-disable-next-line operator-assignment
                     this.layoutDoc[DocCss] = this.layoutDoc[DocCss] + 1; // css change happens outside of mobx/react, so this will notify anyone interested in the layout that it has changed
                 }
                 if (RichTextMenu.Instance?.view === this._editorView && !selected) {
@@ -1800,7 +1798,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
         const match = RTFCast(this.Document[this.fieldKey])?.Text.match(/^(@[a-zA-Z][a-zA-Z_0-9 -]*[a-zA-Z_0-9-]+)/);
         if (match) {
             this.dataDoc.title_custom = true;
-            // eslint-disable-next-line prefer-destructuring
             this.dataDoc.title = match[1]; // this triggers the collectionDockingView to publish this Doc
             this.EditorView?.dispatch(this.EditorView?.state.tr.deleteRange(0, match[1].length + 1));
         }
@@ -1882,7 +1879,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
         const margins = 2 * NumCast(this.layoutDoc._yMargin, this._props.yPadding || 0);
         const children = this.ProseRef?.children.length ? Array.from(this.ProseRef.children[0].children) : undefined;
         if (children && !SnappingManager.IsDragging) {
-            // eslint-disable-next-line no-use-before-define
             const getChildrenHeights = (kids: Element[] | undefined) => kids?.reduce((p, child) => p + toHgt(child), margins) ?? 0;
             const toNum = (val: string) => Number(val.replace('px', ''));
             const toHgt = (node: Element): number => {
@@ -1969,7 +1965,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
             return ComponentTag === CollectionStackingView ? (
                 <SidebarAnnos
                     ref={this._sidebarRef}
-                    // eslint-disable-next-line react/jsx-props-no-spreading
                     {...this._props}
                     Document={this.Document}
                     layoutDoc={this.layoutDoc}
@@ -1989,7 +1984,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
             ) : (
                 <div onPointerDown={e => setupMoveUpEvents(this, e, returnFalse, emptyFunction, () => DocumentView.SelectView(this.DocumentView?.(), false), true)}>
                     <ComponentTag
-                        // eslint-disable-next-line react/jsx-props-no-spreading
                         {...this._props}
                         ref={this._sidebarTagRef}
                         setContentView={emptyFunction}
diff --git a/src/client/views/pdf/AnchorMenu.tsx b/src/client/views/pdf/AnchorMenu.tsx
index 6dd036cf6..a212cbd91 100644
--- a/src/client/views/pdf/AnchorMenu.tsx
+++ b/src/client/views/pdf/AnchorMenu.tsx
@@ -15,7 +15,6 @@ import { LinkPopup } from '../linking/LinkPopup';
 import { DocumentView } from '../nodes/DocumentView';
 import './AnchorMenu.scss';
 import { GPTPopup, GPTPopupMode } from './GPTPopup/GPTPopup';
-import ReactLoading from 'react-loading';
 
 @observer
 export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
@@ -137,8 +136,8 @@ export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
 
     transferToFlashcard = (text: string, x: number, y: number) => {
         // put each question generated by GPT on the front of the flashcard
-        var senArr = text.trim().split('Question: ');
-        var collectionArr: Doc[] = [];
+        const senArr = text.trim().split('Question: ');
+        const collectionArr: Doc[] = [];
         for (let i = 1; i < senArr.length; i++) {
             console.log('Arr ' + i + ': ' + senArr[i]);
             const newDoc = Docs.Create.ComparisonDocument(senArr[i], { _layout_isFlashcard: true, _width: 300, _height: 300 });
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index 02d310f7d..477157cce 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -660,7 +660,6 @@ export class PDFViewer extends ObservableReactComponent<IViewerProps> {
         return (
             <div className="pdfViewerDash-annotationLayer" style={{ height: Doc.NativeHeight(this._props.Document), transform: `scale(${NumCast(this._props.layoutDoc._freeform_scale, 1)})` }} ref={this._annotationLayer}>
                 {inlineAnnos.map(anno => (
-                    // eslint-disable-next-line react/jsx-props-no-spreading
                     <Annotation {...this._props} fieldKey={this._props.fieldKey + '_annotations'} pointerEvents={this.pointerEvents} containerDataDoc={this._props.dataDoc} annoDoc={anno} key={`${anno[Id]}-annotation`} />
                 ))}
             </div>
@@ -694,7 +693,6 @@ export class PDFViewer extends ObservableReactComponent<IViewerProps> {
                 pointerEvents: Doc.ActiveTool !== InkTool.None ? 'all' : undefined,
             }}>
             <CollectionFreeFormView
-                // eslint-disable-next-line react/jsx-props-no-spreading
                 {...this._props}
                 NativeWidth={returnZero}
                 NativeHeight={returnZero}
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts
index b8025cac4..90ecc7f56 100644
--- a/src/fields/Doc.ts
+++ b/src/fields/Doc.ts
@@ -335,7 +335,6 @@ export class Doc extends RefField {
         if (!id || forceSave) {
             DocServer.CreateDocField(docProxy);
         }
-        // eslint-disable-next-line no-constructor-return
         return docProxy; // need to return the proxy from the constructor so that all our added fields will get called
     }
 
@@ -463,7 +462,6 @@ export class Doc extends RefField {
     }
 }
 
-// eslint-disable-next-line no-redeclare
 export namespace Doc {
     export let SelectOnLoad: Doc | undefined;
     export function SetSelectOnLoad(doc: Doc | undefined) {
@@ -659,7 +657,6 @@ export namespace Doc {
                     if (reversed) list.splice(0, 0, doc);
                     else list.push(doc);
                 } else {
-                    // eslint-disable-next-line no-lonely-if
                     if (reversed) list.splice(before ? list.length - ind + 1 : list.length - ind, 0, doc);
                     else list.splice(before ? ind : ind + 1, 0, doc);
                 }
@@ -1191,7 +1188,6 @@ export namespace Doc {
         return Cast(Doc.UserDoc().myLinkDatabase, Doc, null);
     }
     export function SetUserDoc(doc: Doc) {
-        // eslint-disable-next-line no-return-assign
         return (manager._user_doc = doc);
     }
 
-- 
cgit v1.2.3-70-g09d2


From fc06a98deec3fa2b173f8ea30a4f4b1781447b19 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Thu, 10 Oct 2024 20:23:53 -0400
Subject: fixed contextMenu for menus with only a default item

---
 src/client/views/ContextMenu.tsx | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'src/client/views/ContextMenu.tsx')

diff --git a/src/client/views/ContextMenu.tsx b/src/client/views/ContextMenu.tsx
index 2eb3e5565..1931d7c2a 100644
--- a/src/client/views/ContextMenu.tsx
+++ b/src/client/views/ContextMenu.tsx
@@ -254,9 +254,9 @@ export class ContextMenu extends ObservableReactComponent<{ noexpand?: boolean }
                 this._selectedIndex--;
             }
             e.preventDefault();
-        } else if ((e.key === 'Enter' || e.key === 'Tab') && this._selectedIndex >= 0) {
+        } else if (e.key === 'Enter' || e.key === 'Tab') {
             const item = this.flatItems[this._selectedIndex];
-            if (item.event) {
+            if (item?.event) {
                 item.event({ x: this.pageX, y: this.pageY });
             } else {
                 // if (this._searchString.startsWith(this._defaultPrefix)) {
-- 
cgit v1.2.3-70-g09d2


From 6201fb8595729d049885d91278e990e49588f6f5 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Tue, 12 Nov 2024 12:47:15 -0500
Subject: fixed clicking on filled closed strokes to select them.. fixed
 equationBox initial width.  fixed line mode for ink to always create lines. 
 fixed contextMenu to reset selectedIndex after being  hidden.  added reveal
 options for comparisonbox to contexst menu.

---
 src/client/views/ContextMenu.tsx         |  1 +
 src/client/views/GestureOverlay.tsx      |  2 +-
 src/client/views/InkingStroke.tsx        |  4 ++--
 src/client/views/nodes/ComparisonBox.tsx | 39 ++++++++++++++++++++++++--------
 src/client/views/nodes/EquationBox.scss  |  4 +++-
 src/client/views/nodes/EquationBox.tsx   |  1 -
 6 files changed, 36 insertions(+), 15 deletions(-)

(limited to 'src/client/views/ContextMenu.tsx')

diff --git a/src/client/views/ContextMenu.tsx b/src/client/views/ContextMenu.tsx
index 1931d7c2a..eae45221c 100644
--- a/src/client/views/ContextMenu.tsx
+++ b/src/client/views/ContextMenu.tsx
@@ -142,6 +142,7 @@ export class ContextMenu extends ObservableReactComponent<{ noexpand?: boolean }
         this.clearItems();
         this._display = false;
         this._shouldDisplay = false;
+        this._selectedIndex = -1;
         return wasOpen;
     };
 
diff --git a/src/client/views/GestureOverlay.tsx b/src/client/views/GestureOverlay.tsx
index 2d6cd03e0..b0a750a9a 100644
--- a/src/client/views/GestureOverlay.tsx
+++ b/src/client/views/GestureOverlay.tsx
@@ -256,7 +256,7 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil
             const actionPerformed = ((name: Gestures) => {
                 switch (name) {
                     case Gestures.Line:
-                        if (cuspArray.length > 2) return undefined;
+                        if (cuspArray.length > 2 && Score < 1) return undefined;
                     // eslint-disable-next-line no-fallthrough
                     case Gestures.Triangle:
                     case Gestures.Rectangle:
diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx
index f847db6c2..f555808ef 100644
--- a/src/client/views/InkingStroke.tsx
+++ b/src/client/views/InkingStroke.tsx
@@ -315,7 +315,7 @@ export class InkingStroke extends ViewBoxAnnotatableComponent<FieldViewProps>()
     componentUI = (boundsLeft: number, boundsTop: number): null | JSX.Element => {
         const inkDoc = this.Document;
         const { inkData, inkStrokeWidth } = this.inkScaledData();
-        const screenSpaceCenterlineStrokeWidth = Math.min(3, inkStrokeWidth * this.ScreenToLocalBoxXf().inverse().Scale); // the width of the blue line widget that shows the centerline of the ink stroke
+        const screenSpaceCenterlineStrokeWidth = 3; //Math.min(3, inkStrokeWidth * this.ScreenToLocalBoxXf().inverse().Scale); // the width of the blue line widget that shows the centerline of the ink stroke
 
         const screenInkWidth = this.ScreenToLocalBoxXf().inverse().transformDirection(inkStrokeWidth, inkStrokeWidth);
 
@@ -433,7 +433,7 @@ export class InkingStroke extends ViewBoxAnnotatableComponent<FieldViewProps>()
                 StrCast(this.layoutDoc.stroke_lineJoin) as Property.StrokeLinejoin,
                 StrCast(this.layoutDoc.stroke_lineCap) as Property.StrokeLinecap,
                 StrCast(this.layoutDoc.stroke_bezier),
-                'none',
+                closed && fillColor && DashColor(fillColor).alpha() ? fillColor : 'none',
                 startMarker,
                 endMarker,
                 markerScale,
diff --git a/src/client/views/nodes/ComparisonBox.tsx b/src/client/views/nodes/ComparisonBox.tsx
index 672c189ba..e0c360132 100644
--- a/src/client/views/nodes/ComparisonBox.tsx
+++ b/src/client/views/nodes/ComparisonBox.tsx
@@ -1,7 +1,7 @@
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { Tooltip } from '@mui/material';
 import axios from 'axios';
-import { IReactionDisposer, action, computed, makeObservable, observable, reaction, runInAction } from 'mobx';
+import { IReactionDisposer, action, computed, makeObservable, observable, reaction, runInAction, trace } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
 import ReactLoading from 'react-loading';
@@ -30,6 +30,7 @@ import './ComparisonBox.scss';
 import { DocumentView } from './DocumentView';
 import { FieldView, FieldViewProps } from './FieldView';
 import { FormattedTextBox } from './formattedText/FormattedTextBox';
+import { TraceMobx } from '../../../fields/util';
 
 const API_URL = 'https://api.unsplash.com/search/photos';
 
@@ -143,19 +144,28 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
         this._reactDisposer.select = reaction(
             () => this._props.isSelected(),
             selected => {
-                if (selected && this.revealOp !== flashcardRevealOp.SLIDE) this.activateContent();
-                !selected && (this._childActive = false);
+                if (selected) {
+                    switch (this.revealOp) {
+                        default:
+                        case flashcardRevealOp.FLIP: this.activateContent(); break;
+                        case flashcardRevealOp.SLIDE: break;
+                    } // prettier-ignore
+                } else {
+                    this._childActive = false;
+                }
             }, // what it should update to
             { fireImmediately: true }
         );
-        this._reactDisposer.hover = reaction(
-            () => this._props.isContentActive(),
-            hover => {
-                if (!hover) {
-                    this.revealOp === flashcardRevealOp.FLIP && this.animateFlipping(this.frontKey);
-                    this.revealOp === flashcardRevealOp.SLIDE && this.animateSliding(this._props.PanelWidth() - 3);
+        this._reactDisposer.inactive = reaction(
+            () => !this._props.isContentActive(),
+            inactive => {
+                if (inactive) {
+                    switch (this.revealOp) {
+                        case flashcardRevealOp.FLIP: this.animateFlipping(this.frontKey); break;
+                        case flashcardRevealOp.SLIDE: this.animateSliding(this._props.PanelWidth() - 3); break;
+                    } // prettier-ignore
                 }
-            }, // what it should update to
+            },
             { fireImmediately: true }
         );
     }
@@ -197,7 +207,9 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
     @computed get clipWidth()     { return NumCast(this.layoutDoc[this.clipWidthKey], this.isFlashcard ? 100: 50); } // prettier-ignore
     @computed get clipHeight()    { return NumCast(this.layoutDoc[this.clipHeightKey], 200);  } // prettier-ignore
     @computed get revealOp()      { return StrCast(this.layoutDoc[this.revealOpKey], StrCast(this.containerDoc?.revealOp, this.isFlashcard ? flashcardRevealOp.FLIP : flashcardRevealOp.SLIDE)) as flashcardRevealOp; } // prettier-ignore
+    set revealOp(op:flashcardRevealOp) { this.layoutDoc[this.revealOpKey] =  op; } // prettier-ignore
     @computed get revealOpHover() { return BoolCast(this.layoutDoc[this.revealOpKey+"_hover"], BoolCast(this.containerDoc?.revealOp_hover)); } // prettier-ignore
+    set revealOpHover(on:boolean) { this.layoutDoc[this.revealOpKey+"_hover"] = on; } // prettier-ignore
     @computed get loading()       { return this._loading; } // prettier-ignore
     set loading(value)            { runInAction(() => { this._loading = value; })} // prettier-ignore
 
@@ -616,6 +628,12 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
         const appearance = ContextMenu.Instance.findByDescription('Appearance...');
         const appearanceItems = appearance?.subitems ?? [];
         appearanceItems.push({ description: 'Create ChatCard', event: () => this.askGPT(GPTCallType.CHATCARD), icon: 'id-card' });
+        appearanceItems.push({
+            description: 'Reveal by ' + (this.revealOp === flashcardRevealOp.FLIP ? 'Sliding' : 'Flipping'),
+            event: () => (this.revealOp = this.revealOp === flashcardRevealOp.FLIP ? flashcardRevealOp.SLIDE : flashcardRevealOp.FLIP),
+            icon: 'id-card',
+        });
+        appearanceItems.push({ description: (this.revealOpHover ? 'Click ' : 'Hover ') + ' to reveal', event: () => (this.revealOpHover = !this.revealOpHover), icon: 'id-card' });
         !appearance && ContextMenu.Instance.addItem({ description: 'Appearance...', subitems: appearanceItems, icon: 'eye' });
     };
 
@@ -792,6 +810,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
     );
 
     render() {
+        TraceMobx();
         const renderMode = new Map<flashcardRevealOp, () => JSX.Element>([
             [flashcardRevealOp.FLIP, this.renderAsFlip],
             [flashcardRevealOp.SLIDE, this.renderAsBeforeAfter]]); // prettier-ignore
diff --git a/src/client/views/nodes/EquationBox.scss b/src/client/views/nodes/EquationBox.scss
index 5009ec7a7..cbd13d924 100644
--- a/src/client/views/nodes/EquationBox.scss
+++ b/src/client/views/nodes/EquationBox.scss
@@ -3,7 +3,9 @@
 .equationBox-cont {
     transform-origin: center;
     background-color: #e7e7e7;
+    width: fit-content;
+    min-width: 100%;
     > span {
-        width: 100%;
+        width: fit-content;
     }
 }
diff --git a/src/client/views/nodes/EquationBox.tsx b/src/client/views/nodes/EquationBox.tsx
index 290c90d6e..472fa56a0 100644
--- a/src/client/views/nodes/EquationBox.tsx
+++ b/src/client/views/nodes/EquationBox.tsx
@@ -119,7 +119,6 @@ export class EquationBox extends ViewBoxBaseComponent<FieldViewProps>() {
                 onPointerDown={e => !e.ctrlKey && e.stopPropagation()}
                 style={{
                     transform: `scale(${scale})`,
-                    width: 'fit-content', // `${100 / scale}%`,
                     height: `${100 / scale}%`,
                     pointerEvents: !this._props.isSelected() ? 'none' : undefined,
                     fontSize: StrCast(this.Document._text_fontSize),
-- 
cgit v1.2.3-70-g09d2

