From 10a89be0b184df2750a4b3eceb48db205cb83e95 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Tue, 5 Nov 2024 10:22:31 -0500
Subject:  fixed display of where control point will be added on mouse moves.
 fixed clickable ink line to not select fill area unless its actually painted.
 added end cap properties to ink stroke ui.  enabled more than one ink stroke
 to show editable control points when multiselected.

---
 src/client/views/InkingStroke.tsx | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

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

diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx
index 5199eb02b..f847db6c2 100644
--- a/src/client/views/InkingStroke.tsx
+++ b/src/client/views/InkingStroke.tsx
@@ -21,7 +21,7 @@
     Most of the operations that can be performed on an InkStroke (eg delete a point, rotate, stretch) are implemented in the InkStrokeProperties helper class
 */
 import { Property } from 'csstype';
-import { action, computed, IReactionDisposer, observable, reaction } from 'mobx';
+import { action, computed, IReactionDisposer, makeObservable, observable, reaction } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
 import { DashColor, returnFalse, setupMoveUpEvents } from '../../ClientUtils';
@@ -66,9 +66,14 @@ export class InkingStroke extends ViewBoxAnnotatableComponent<FieldViewProps>()
     private _handledClick = false; // flag denoting whether ink stroke has handled a psuedo-click onPointerUp so that the real onClick event can be stopPropagated
     private _disposers: { [key: string]: IReactionDisposer } = {};
 
+    constructor(props: FieldViewProps) {
+        super(props);
+        makeObservable(this);
+    }
+
     @observable _nearestSeg?: number = undefined; // nearest Bezier segment along the ink stroke to the cursor (used for displaying the Add Point highlight)
     @observable _nearestT?: number = undefined; // nearest t value within the nearest Bezier segment "
-    @observable _nearestScrPt?: { X: number; Y: number }; // nearst screen point on the ink stroke ""
+    @observable _nearestScrPt?: { X: number; Y: number } = { X: 0, Y: 0 }; // nearst screen point on the ink stroke ""
 
     componentDidMount() {
         this._props.setContentViewBox?.(this);
@@ -155,6 +160,7 @@ export class InkingStroke extends ViewBoxAnnotatableComponent<FieldViewProps>()
         const wasSelected = InkStrokeProperties.Instance._currentPoint === controlIndex;
         const isEditing = InkStrokeProperties.Instance._controlButton && this._props.isSelected();
         this.controlUndo = undefined;
+        this._nearestScrPt = undefined;
         setupMoveUpEvents(
             this,
             e,
@@ -275,7 +281,7 @@ export class InkingStroke extends ViewBoxAnnotatableComponent<FieldViewProps>()
             .map(p => ({ X: p[0], Y: p[1] }));
         const { distance, nearestT, nearestSeg, nearestPt } = InkStrokeProperties.nearestPtToStroke(screenPts, { X: e.clientX, Y: e.clientY });
 
-        if (distance < 40) {
+        if (distance < 40 && !e.buttons) {
             this._nearestT = nearestT;
             this._nearestSeg = nearestSeg;
             this._nearestScrPt = nearestPt;
@@ -427,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),
-                !closed || !fillColor || DashColor(fillColor).alpha() === 0 ? 'none' : fillColor,
+                'none',
                 startMarker,
                 endMarker,
                 markerScale,
-- 
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/InkingStroke.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

