From 647b66c965f5896d784de0f321d31cc712937e1c Mon Sep 17 00:00:00 2001
From: eleanor-park <eleanor_park@brown.edu>
Date: Fri, 26 Jul 2024 01:23:06 -0400
Subject: Revert "Merge branch 'master' into eleanor-gptdraw"

This reverts commit decbefe23a1da35c838222bafe8a2c029c6ea794, reversing
changes made to 8ca26551622d36b7856f5c1865498fa9e5d888b5.
---
 src/client/views/nodes/PDFBox.tsx | 37 ++++++++++++++++++++++++++-----------
 1 file changed, 26 insertions(+), 11 deletions(-)

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

diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index 8db68ddfe..782df99f6 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -1,6 +1,8 @@
 /* eslint-disable jsx-a11y/no-static-element-interactions */
 /* eslint-disable jsx-a11y/control-has-associated-label */
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { IconButton } from 'browndash-components';
+import { black } from 'colors';
 import { action, computed, IReactionDisposer, makeObservable, observable, reaction, runInAction } from 'mobx';
 import { observer } from 'mobx-react';
 import * as Pdfjs from 'pdfjs-dist';
@@ -503,17 +505,30 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
     }
     @computed get sidebarHandle() {
         return (
-            <div
-                className="pdfBox-sidebarBtn"
-                key="sidebar"
-                title="Toggle Sidebar"
-                style={{
-                    display: !this._props.isContentActive() ? 'none' : undefined,
-                    top: StrCast(this.layoutDoc._layout_showTitle) === 'title' ? 20 : 5,
-                    backgroundColor: this.SidebarShown ? Colors.MEDIUM_BLUE : Colors.BLACK,
-                }}
-                onPointerDown={e => this.sidebarBtnDown(e, true)}>
-                <FontAwesomeIcon style={{ color: Colors.WHITE }} icon="comment-alt" size="sm" />
+            <div className="pdfBox-sidebarBtn-container">
+                <div
+                    className="pdfBox-sidebarBtn"
+                    key="sidebar"
+                    title="Toggle Sidebar"
+                    style={{
+                        display: !this._props.isContentActive() ? 'none' : undefined,
+                        top: StrCast(this.layoutDoc._layout_showTitle) === 'title' ? 20 : 5,
+                        backgroundColor: this.SidebarShown ? Colors.MEDIUM_BLUE : Colors.BLACK,
+                    }}>
+                    {/* // onPointerDown={e => this.sidebarBtnDown(e, true)} */}
+                    <IconButton tooltip="Toggle Annotation Palette" icon={<FontAwesomeIcon style={{ color: Colors.WHITE }} icon="palette" />} onPointerDown={e => this.sidebarBtnDown(e, true)} />
+                </div>
+                <div
+                    className="pdfBox-sidebarBtn"
+                    key="sidebar"
+                    title="Toggle Sidebar"
+                    style={{
+                        display: !this._props.isContentActive() ? 'none' : undefined,
+                        top: StrCast(this.layoutDoc._layout_showTitle) === 'title' ? 20 : 5,
+                        backgroundColor: this.SidebarShown ? Colors.MEDIUM_BLUE : Colors.BLACK,
+                    }}>
+                    <IconButton tooltip="Toggle Sidebar" icon={<FontAwesomeIcon style={{ color: Colors.WHITE }} icon="comment-alt" size="sm" />} onPointerDown={e => this.sidebarBtnDown(e, true)} />
+                </div>
             </div>
         );
     }
-- 
cgit v1.2.3-70-g09d2


From f7cdcb654e83d7fdbfd0b1cfc80c485bb9554f08 Mon Sep 17 00:00:00 2001
From: eleanor-park <eleanor_park@brown.edu>
Date: Wed, 28 Aug 2024 22:03:12 -0400
Subject: final changes, ready for pull request

---
 eslint.config.mjs                                | 67 +++++-------------------
 package-lock.json                                | 15 ++++--
 package.json                                     | 10 ++--
 src/client/util/Scripting.ts                     |  4 +-
 src/client/views/nodes/PDFBox.scss               | 16 +-----
 src/client/views/nodes/PDFBox.tsx                | 37 ++++---------
 src/client/views/smartdraw/AnnotationPalette.tsx | 14 +++--
 src/client/views/smartdraw/SmartDrawHandler.tsx  | 15 ++++--
 8 files changed, 59 insertions(+), 119 deletions(-)

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

diff --git a/eslint.config.mjs b/eslint.config.mjs
index 619966f20..12ad3300a 100644
--- a/eslint.config.mjs
+++ b/eslint.config.mjs
@@ -1,57 +1,14 @@
-import pluginJs from '@eslint/js';
-import pluginReactConfig from 'eslint-plugin-react/configs/recommended.js';
-import globals from 'globals';
-import tseslint from 'typescript-eslint';
+import globals from "globals";
+import pluginJs from "@eslint/js";
+import tseslint from "typescript-eslint";
+import pluginReact from "eslint-plugin-react";
 
-export default [
-    {
-        languageOptions: { globals: { ...globals.browser, ...globals.node } },
-    },
-    pluginJs.configs.recommended,
-    ...tseslint.configs.recommended,
-    {
-        rules: {
-            'node/no-missing-import': 0,
-            'no-console': 'off',
-            'func-names': 'off',
-            'no-process-exit': 'off',
-            'object-shorthand': 'off',
-            'class-methods-use-this': 'off',
-            'single-quote': 'off',
-            'max-classes-per-file': 0,
-
-            'react/jsx-filename-extension': [
-                2,
-                {
-                    extensions: ['.js', '.jsx', '.ts', '.tsx'],
-                },
-            ],
 
-            'import/prefer-default-export': 'off',
-            'no-unused-expressions': 'off',
-            '@typescript-eslint/no-unused-expressions': 'off',
-            'prefer-template': 'off',
-            'no-inner-declarations': 'off',
-            'no-plusplus': 'off',
-            'no-multi-assign': 'off',
-            'no-underscore-dangle': 'off',
-            'no-nested-ternary': 'off',
-            'lines-between-class-members': 'off',
-            'no-shadow': 'off',
-            '@typescript-eslint/no-shadow': 'warn',
-            'no-unused-vars': 'off',
-            '@typescript-eslint/no-unused-vars': 'error',
-            '@typescript-eslint/no-namespace': 'off',
-            'react/destructuring-assignment': 0,
-            'prefer-arrow-callback': 'error',
-            'no-return-assign': 'error',
-            'no-await-in-loop': 'error',
-            'no-loop-func': 'error',
-            'no-cond-assign': 'error',
-            'no-use-before-define': 'error',
-            'no-explicit-any': 'error',
-            'no-restricted-globals': ['error', 'event'],
-        },
-    },
-    pluginReactConfig,
-];
+export default [
+  {files: ["**/*.{js,mjs,cjs,ts,jsx,tsx}"]},
+  {files: ["**/*.js"], languageOptions: {sourceType: "commonjs"}},
+  {languageOptions: { globals: globals.browser }},
+  pluginJs.configs.recommended,
+  ...tseslint.configs.recommended,
+  pluginReact.configs.flat.recommended,
+];
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index 81f5976d6..c4d69bbcf 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -249,7 +249,7 @@
                 "xregexp": "^5.1.1"
             },
             "devDependencies": {
-                "@eslint/js": "^9.1.1",
+                "@eslint/js": "^9.9.1",
                 "@types/adm-zip": "^0.5.5",
                 "@types/animejs": "^3.1.12",
                 "@types/archiver": "^6.0.2",
@@ -298,9 +298,9 @@
                 "@types/youtube": "^0.1.0",
                 "chai": "^5.0.0",
                 "cross-env": "^7.0.3",
-                "eslint": "^9.9.0",
-                "eslint-plugin-react": "^7.34.1",
-                "globals": "^15.1.0",
+                "eslint": "^9.9.1",
+                "eslint-plugin-react": "^7.35.0",
+                "globals": "^15.9.0",
                 "jsdom": "^25.0.0",
                 "mocha": "^10.2.0",
                 "prettier": "^3.1.0",
@@ -309,7 +309,7 @@
                 "ts-loader": "^9.5.1",
                 "ts-node": "^10.9.1",
                 "ts-node-dev": "^2.0.0",
-                "typescript-eslint": "^8.2.0",
+                "typescript-eslint": "^8.3.0",
                 "webpack-dev-server": "^5.0.4"
             },
             "engines": {
@@ -2681,6 +2681,7 @@
             "version": "9.9.1",
             "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.9.1.tgz",
             "integrity": "sha512-xIDQRsfg5hNBqHz04H1R3scSVwmI+KUbqjsQKHKQ1DAUSaUjYPReZZmS/5PNiKu1fUvzDd6H7DEDKACSEhu+TQ==",
+            "license": "MIT",
             "engines": {
                 "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
             }
@@ -17478,6 +17479,7 @@
             "version": "9.9.1",
             "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.9.1.tgz",
             "integrity": "sha512-dHvhrbfr4xFQ9/dq+jcVneZMyRYLjggWjk6RVsIiHsP8Rz6yZ8LvZ//iU4TrZF+SXWG+JkNF2OyiZRvzgRDqMg==",
+            "license": "MIT",
             "dependencies": {
                 "@eslint-community/eslint-utils": "^4.2.0",
                 "@eslint-community/regexpp": "^4.11.0",
@@ -17537,6 +17539,7 @@
             "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.35.0.tgz",
             "integrity": "sha512-v501SSMOWv8gerHkk+IIQBkcGRGrO2nfybfj5pLxuJNFTPxxA3PSryhXTK+9pNbtkggheDdsC0E9Q8CuPk6JKA==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
                 "array-includes": "^3.1.8",
                 "array.prototype.findlast": "^1.2.5",
@@ -19332,6 +19335,7 @@
             "resolved": "https://registry.npmjs.org/globals/-/globals-15.9.0.tgz",
             "integrity": "sha512-SmSKyLLKFbSr6rptvP8izbyxJL4ILwqO9Jg23UA0sDlGlu58V59D1//I3vlc0KJphVdUR7vMjHIplYnzBxorQA==",
             "dev": true,
+            "license": "MIT",
             "engines": {
                 "node": ">=18"
             },
@@ -32652,6 +32656,7 @@
             "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.3.0.tgz",
             "integrity": "sha512-EvWjwWLwwKDIJuBjk2I6UkV8KEQcwZ0VM10nR1rIunRDIP67QJTZAHBXTX0HW/oI1H10YESF8yWie8fRQxjvFA==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
                 "@typescript-eslint/eslint-plugin": "8.3.0",
                 "@typescript-eslint/parser": "8.3.0",
diff --git a/package.json b/package.json
index 0b17d9b60..51e7cf8a9 100644
--- a/package.json
+++ b/package.json
@@ -23,7 +23,7 @@
         "tsc": "tsc -t es5"
     },
     "devDependencies": {
-        "@eslint/js": "^9.1.1",
+        "@eslint/js": "^9.9.1",
         "@types/adm-zip": "^0.5.5",
         "@types/animejs": "^3.1.12",
         "@types/archiver": "^6.0.2",
@@ -72,9 +72,9 @@
         "@types/youtube": "^0.1.0",
         "chai": "^5.0.0",
         "cross-env": "^7.0.3",
-        "eslint": "^9.9.0",
-        "eslint-plugin-react": "^7.34.1",
-        "globals": "^15.1.0",
+        "eslint": "^9.9.1",
+        "eslint-plugin-react": "^7.35.0",
+        "globals": "^15.9.0",
         "jsdom": "^25.0.0",
         "mocha": "^10.2.0",
         "prettier": "^3.1.0",
@@ -83,7 +83,7 @@
         "ts-loader": "^9.5.1",
         "ts-node": "^10.9.1",
         "ts-node-dev": "^2.0.0",
-        "typescript-eslint": "^8.2.0",
+        "typescript-eslint": "^8.3.0",
         "webpack-dev-server": "^5.0.4"
     },
     "dependencies": {
diff --git a/src/client/util/Scripting.ts b/src/client/util/Scripting.ts
index c63d3d7cb..cb314e3f1 100644
--- a/src/client/util/Scripting.ts
+++ b/src/client/util/Scripting.ts
@@ -1,7 +1,7 @@
 // export const ts = (window as any).ts;
 // import * as typescriptlib from '!!raw-loader!../../../node_modules/typescript/lib/lib.d.ts'
 // import * as typescriptes5 from '!!raw-loader!../../../node_modules/typescript/lib/lib.es5.d.ts'
-import typescriptlib from 'type_decls.d';
+// import typescriptlib from 'type_decls.d';
 import * as ts from 'typescript';
 import { Doc, FieldType } from '../../fields/Doc';
 import { RefField } from '../../fields/RefField';
@@ -248,7 +248,7 @@ export function CompileScript(script: string, options: ScriptOptions = {}): Comp
     const funcScript = `(function(${paramString})${reqTypes} { ${body} })`;
     host.writeFile('file.ts', funcScript);
 
-    if (typecheck) host.writeFile('node_modules/typescript/lib/lib.d.ts', typescriptlib);
+    // if (typecheck) host.writeFile('node_modules/typescript/lib/lib.d.ts', typescriptlib);
     const program = ts.createProgram(['file.ts'], {}, host);
     const testResult = program.emit();
     const outputText = host.readFile('file.js');
diff --git a/src/client/views/nodes/PDFBox.scss b/src/client/views/nodes/PDFBox.scss
index 6e24b2931..7bca1230f 100644
--- a/src/client/views/nodes/PDFBox.scss
+++ b/src/client/views/nodes/PDFBox.scss
@@ -20,27 +20,15 @@
         top: 0;
         left: 0;
 
-        .pdfBox-sidebarBtn-container {
-            display: flex;
-            flex-direction: row;
-            position: absolute;
-            width: 53px;
-            height: 33px;
-            right: 5px;
-            align-items: center;
-            justify-content: space-between;
-            z-index: 1;
-        }
-
         // glr: This should really be the same component as text and PDFs
         .pdfBox-sidebarBtn {
             background: $black;
             height: 25px;
             width: 25px;
-            // right: 5px;
+            right: 5px;
             color: $white;
             display: flex;
-            // position: absolute;
+            position: absolute;
             align-items: center;
             justify-content: center;
             border-radius: 3px;
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index 08f14193a..b17275a1e 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -1,6 +1,4 @@
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { IconButton } from 'browndash-components';
-import { black } from 'colors';
 import { action, computed, IReactionDisposer, makeObservable, observable, reaction, runInAction } from 'mobx';
 import { observer } from 'mobx-react';
 import * as Pdfjs from 'pdfjs-dist';
@@ -505,30 +503,17 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
     }
     @computed get sidebarHandle() {
         return (
-            <div className="pdfBox-sidebarBtn-container">
-                <div
-                    className="pdfBox-sidebarBtn"
-                    key="sidebar"
-                    title="Toggle Sidebar"
-                    style={{
-                        display: !this._props.isContentActive() ? 'none' : undefined,
-                        top: StrCast(this.layoutDoc._layout_showTitle) === 'title' ? 20 : 5,
-                        backgroundColor: this.SidebarShown ? Colors.MEDIUM_BLUE : Colors.BLACK,
-                    }}>
-                    {/* // onPointerDown={e => this.sidebarBtnDown(e, true)} */}
-                    <IconButton tooltip="Toggle Annotation Palette" icon={<FontAwesomeIcon style={{ color: Colors.WHITE }} icon="palette" />} onPointerDown={e => this.sidebarBtnDown(e, true)} />
-                </div>
-                <div
-                    className="pdfBox-sidebarBtn"
-                    key="sidebar"
-                    title="Toggle Sidebar"
-                    style={{
-                        display: !this._props.isContentActive() ? 'none' : undefined,
-                        top: StrCast(this.layoutDoc._layout_showTitle) === 'title' ? 20 : 5,
-                        backgroundColor: this.SidebarShown ? Colors.MEDIUM_BLUE : Colors.BLACK,
-                    }}>
-                    <IconButton tooltip="Toggle Sidebar" icon={<FontAwesomeIcon style={{ color: Colors.WHITE }} icon="comment-alt" size="sm" />} onPointerDown={e => this.sidebarBtnDown(e, true)} />
-                </div>
+            <div
+                className="pdfBox-sidebarBtn"
+                key="sidebar"
+                title="Toggle Sidebar"
+                style={{
+                    display: !this._props.isContentActive() ? 'none' : undefined,
+                    top: StrCast(this.layoutDoc._layout_showTitle) === 'title' ? 20 : 5,
+                    backgroundColor: this.SidebarShown ? Colors.MEDIUM_BLUE : Colors.BLACK,
+                }}
+                onPointerDown={e => this.sidebarBtnDown(e, true)}>
+                <FontAwesomeIcon style={{ color: Colors.WHITE }} icon="comment-alt" size="sm" />
             </div>
         );
     }
diff --git a/src/client/views/smartdraw/AnnotationPalette.tsx b/src/client/views/smartdraw/AnnotationPalette.tsx
index b57907152..c296138a8 100644
--- a/src/client/views/smartdraw/AnnotationPalette.tsx
+++ b/src/client/views/smartdraw/AnnotationPalette.tsx
@@ -1,4 +1,3 @@
-import { faLaptopHouse } from '@fortawesome/free-solid-svg-icons';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { Slider, Switch } from '@mui/material';
 import { Button } from 'browndash-components';
@@ -16,9 +15,8 @@ import { Docs } from '../../documents/Documents';
 import { makeUserTemplateImage } from '../../util/DropConverter';
 import { SettingsManager } from '../../util/SettingsManager';
 import { Transform } from '../../util/Transform';
-import { undoable, undoBatch } from '../../util/UndoManager';
-import { CollectionFreeFormView, MarqueeOptionsMenu, MarqueeView } from '../collections/collectionFreeForm';
-import { ActiveArrowEnd, ActiveArrowStart, ActiveDash, ActiveFillColor, ActiveInkBezierApprox, ActiveInkColor, ActiveIsInkMask, DocumentView, DocumentViewInternal } from '../nodes/DocumentView';
+import { undoBatch } from '../../util/UndoManager';
+import { DocumentView, DocumentViewInternal } from '../nodes/DocumentView';
 import { FieldView } from '../nodes/FieldView';
 import { ObservableReactComponent } from '../ObservableReactComponent';
 import { DefaultStyleProvider } from '../StyleProvider';
@@ -26,7 +24,6 @@ import './AnnotationPalette.scss';
 import { DrawingOptions, SmartDrawHandler } from './SmartDrawHandler';
 import { DocumentType } from '../../documents/DocumentTypes';
 import { ImageField } from '../../../fields/URLField';
-import { CollectionCarousel3DView } from '../collections/CollectionCarousel3DView';
 import { Copy } from '../../../fields/FieldSymbols';
 
 interface AnnotationPaletteProps {
@@ -45,7 +42,7 @@ export class AnnotationPalette extends ObservableReactComponent<AnnotationPalett
     @observable private _opts: DrawingOptions = { text: '', complexity: 5, size: 200, autoColor: true, x: 0, y: 0 };
     private _gptRes: string[] = [];
 
-    constructor(props: any) {
+    constructor(props: AnnotationPaletteProps) {
         super(props);
         makeObservable(this);
     }
@@ -140,7 +137,7 @@ export class AnnotationPalette extends ObservableReactComponent<AnnotationPalett
     generateDrawings = action(async () => {
         this._isLoading = true;
         this._props.Document[DocData].data = undefined;
-        for (var i = 0; i < 3; i++) {
+        for (let i = 0; i < 3; i++) {
             try {
                 SmartDrawHandler.Instance.AddDrawing = this.addDrawing;
                 this._canInteract = false;
@@ -150,9 +147,10 @@ export class AnnotationPalette extends ObservableReactComponent<AnnotationPalett
                     await SmartDrawHandler.Instance.drawWithGPT({ X: 0, Y: 0 }, this._userInput, this._opts.complexity, this._opts.size, this._opts.autoColor);
                 }
             } catch (e) {
-                console.log('Error generating drawing');
+                console.log('Error generating drawing', e);
             }
         }
+        // eslint-disable-next-line @typescript-eslint/no-unused-expressions
         this._opts.text !== '' ? (this._opts.text = `${this._opts.text} ~~~ ${this._userInput}`) : (this._opts.text = this._userInput);
         this._userInput = '';
         this._isLoading = false;
diff --git a/src/client/views/smartdraw/SmartDrawHandler.tsx b/src/client/views/smartdraw/SmartDrawHandler.tsx
index 4ec787e07..368970f75 100644
--- a/src/client/views/smartdraw/SmartDrawHandler.tsx
+++ b/src/client/views/smartdraw/SmartDrawHandler.tsx
@@ -10,7 +10,7 @@ import { AiOutlineSend } from 'react-icons/ai';
 import { gptAPICall, GPTCallType, gptDrawingColor } from '../../apis/gpt/GPT';
 import { InkData, InkField, InkTool } from '../../../fields/InkField';
 import { SVGToBezier } from '../../util/bezierFit';
-const { parse } = require('svgson');
+import { INode, parse } from 'svgson';
 import { Slider, Switch } from '@mui/material';
 import { Doc, DocListCast } from '../../../fields/Doc';
 import { DocData } from '../../../fields/DocSymbols';
@@ -35,6 +35,7 @@ export interface DrawingOptions {
 }
 
 @observer
+// eslint-disable-next-line @typescript-eslint/no-empty-object-type
 export class SmartDrawHandler extends ObservableReactComponent<{}> {
     static Instance: SmartDrawHandler;
 
@@ -59,7 +60,7 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> {
     private _errorOccurredOnce = false;
 
     public RemoveDrawing: (doc?: Doc) => void = unimplementedFunction;
-    public CreateDrawingDoc: (strokeList: [InkData, string, string][], opts: DrawingOptions, gptRes: string, containerDoc?: Doc) => Doc | undefined = (strokeList: [InkData, string, string][], opts: DrawingOptions, gptRes: string) => {
+    public CreateDrawingDoc: (strokeList: [InkData, string, string][], opts: DrawingOptions, gptRes: string, containerDoc?: Doc) => Doc | undefined = (strokeList: [InkData, string, string][], opts: DrawingOptions) => {
         const drawing: Doc[] = [];
         strokeList.forEach((stroke: [InkData, string, string]) => {
             const bounds = InkField.getBounds(stroke[0]);
@@ -89,6 +90,7 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> {
     };
     public AddDrawing: (doc: Doc, opts: DrawingOptions, gptRes: string) => void = unimplementedFunction;
 
+    // eslint-disable-next-line @typescript-eslint/no-explicit-any
     constructor(props: any) {
         super(props);
         makeObservable(this);
@@ -223,6 +225,7 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> {
         console.log(res);
         const strokeData = await this.parseSvg(res, startPt, false, autoColor);
         const drawingDoc = strokeData && this.CreateDrawingDoc(strokeData?.data, strokeData?.lastInput, strokeData?.lastRes);
+        // eslint-disable-next-line @typescript-eslint/no-unused-expressions
         drawingDoc && this.AddDrawing(drawingDoc, this._lastInput, res);
 
         this._errorOccurredOnce = false;
@@ -253,8 +256,10 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> {
             }
             console.log(res);
             const strokeData = await this.parseSvg(res, { X: this._lastInput.x, Y: this._lastInput.y }, true, lastInput?.autoColor || this._autoColor);
+            // eslint-disable-next-line @typescript-eslint/no-unused-expressions
             this.RemoveDrawing !== unimplementedFunction && this.RemoveDrawing(this._selectedDoc);
             const drawingDoc = strokeData && this.CreateDrawingDoc(strokeData?.data, strokeData?.lastInput, strokeData?.lastRes);
+            // eslint-disable-next-line @typescript-eslint/no-unused-expressions
             drawingDoc && this.AddDrawing(drawingDoc, this._lastInput, res);
             return strokeData;
         } catch (err) {
@@ -271,8 +276,9 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> {
         if (svg) {
             this._lastResponse = svg[0];
             const svgObject = await parse(svg[0]);
-            const svgStrokes: any = svgObject.children;
+            const svgStrokes: INode[] = svgObject.children;
             const strokeData: [InkData, string, string][] = [];
+            // eslint-disable-next-line @typescript-eslint/no-explicit-any
             svgStrokes.forEach((child: any) => {
                 const convertedBezier: InkData = SVGToBezier(child.name, child.attributes);
                 strokeData.push([
@@ -318,7 +324,7 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> {
             console.log(colorResponse);
             this.colorStrokes(colorResponse, drawing);
         } catch (error) {
-            console.log('GPT call failed');
+            console.log('GPT call failed', error);
         }
     };
 
@@ -335,6 +341,7 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> {
                 strokes[index][DocData].color = strokeAndFill[0];
                 const inkStroke = DocumentView.getDocumentView(strokes[index])?.ComponentView as InkingStroke;
                 const { inkData } = inkStroke.inkScaledData();
+                // eslint-disable-next-line @typescript-eslint/no-unused-expressions
                 InkingStroke.IsClosed(inkData) ? (strokes[index][DocData].fillColor = strokeAndFill[1]) : (strokes[index][DocData].fillColor = undefined);
             }
         });
-- 
cgit v1.2.3-70-g09d2


From b453414dc2bb11d56c5dcb2a73d389eefabff7d5 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Mon, 2 Sep 2024 12:16:43 -0400
Subject: cleaned up updateIcon to use promises to avoid a bunch of setTimeouts

---
 src/client/util/DropConverter.ts                   |  3 +-
 src/client/views/InkTranscription.tsx              | 14 ++------
 src/client/views/ViewBoxInterface.ts               |  2 +-
 .../collectionFreeForm/CollectionFreeFormView.tsx  |  2 +-
 src/client/views/nodes/DocumentView.tsx            | 13 ++++++-
 src/client/views/nodes/PDFBox.tsx                  | 42 +++++++++++-----------
 src/client/views/nodes/VideoBox.tsx                | 15 ++++----
 src/client/views/nodes/WebBox.tsx                  | 29 ++++++---------
 src/client/views/smartdraw/AnnotationPalette.tsx   | 40 +++++++--------------
 src/client/views/smartdraw/SmartDrawHandler.tsx    | 14 +-------
 10 files changed, 71 insertions(+), 103 deletions(-)

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

diff --git a/src/client/util/DropConverter.ts b/src/client/util/DropConverter.ts
index 57c79cff3..0ede44298 100644
--- a/src/client/util/DropConverter.ts
+++ b/src/client/util/DropConverter.ts
@@ -92,7 +92,8 @@ export function makeUserTemplateButton(doc: Doc) {
  * Similar to makeUserTemplateButton, but rather than creating a draggable button for the template, it takes in
  * an ImageField that will display.
  */
-export function makeUserTemplateImage(doc: Doc, image: ImageField) {
+export function makeUserTemplateImage(doc: Doc, imageHref: string | undefined) {
+    const image = imageHref ?? 'http://www.cs.brown.edu/~bcz/noImage.png';
     const layoutDoc = doc; // doc.layout instanceof Doc && doc.layout.isTemplateForField ? doc.layout : doc;
     if (layoutDoc.type !== DocumentType.FONTICON) {
         !layoutDoc.isTemplateDoc && makeTemplate(layoutDoc);
diff --git a/src/client/views/InkTranscription.tsx b/src/client/views/InkTranscription.tsx
index 485a0e7c4..26e0aa372 100644
--- a/src/client/views/InkTranscription.tsx
+++ b/src/client/views/InkTranscription.tsx
@@ -3,7 +3,7 @@ import { action, observable } from 'mobx';
 import * as React from 'react';
 import { Doc, DocListCast } from '../../fields/Doc';
 import { InkData, InkField, InkTool } from '../../fields/InkField';
-import { Cast, DateCast, ImageCast, NumCast, StrCast } from '../../fields/Types';
+import { Cast, DateCast, DocCast, ImageCast, NumCast, StrCast } from '../../fields/Types';
 import { aggregateBounds } from '../../Utils';
 import { DocumentType } from '../documents/DocumentTypes';
 import { CollectionFreeFormView, MarqueeView } from './collections/collectionFreeForm';
@@ -273,7 +273,7 @@ export class InkTranscription extends React.Component {
                     DocumentView.getDocumentView(this.currGroup)?.ComponentView?.updateIcon?.();
                     this.currGroup.transcription = text;
                     this.currGroup.title = text;
-                    let image = await this.getIcon();
+                    let image = await DocumentView.GetDocImage(this.currGroup);
                     const pathname = image?.url.href as string;
                     console.log(image?.url);
                     console.log(image);
@@ -300,16 +300,6 @@ export class InkTranscription extends React.Component {
             }
         }
     };
-    async getIcon() {
-        const docView = DocumentView.getDocumentView(this.currGroup);
-        console.log(this.currGroup);
-        if (docView) {
-            console.log(docView);
-            docView.ComponentView?.updateIcon?.();
-            return new Promise<ImageField | undefined>(res => setTimeout(() => res(ImageCast(docView.Document.icon)), 1000));
-        }
-        return undefined;
-    }
     imageUrlToBase64 = async (imageUrl: string): Promise<string> => {
         try {
             const response = await fetch(imageUrl);
diff --git a/src/client/views/ViewBoxInterface.ts b/src/client/views/ViewBoxInterface.ts
index 111771ba0..f66f6062e 100644
--- a/src/client/views/ViewBoxInterface.ts
+++ b/src/client/views/ViewBoxInterface.ts
@@ -22,7 +22,7 @@ export abstract class ViewBoxInterface<P> extends ObservableReactComponent<React
         return ''; //
     }
     promoteCollection?: () => void; // moves contents of collection to parent
-    updateIcon?: (usePanelDimensions?: boolean) => void; // updates the icon representation of the document
+    updateIcon?: (usePanelDimensions?: boolean) => Promise<void>; // updates the icon representation of the document
     getAnchor?: (addAsAnnotation: boolean, pinData?: PinProps) => Doc; // returns an Anchor Doc that represents the current state of the doc's componentview (e.g., the current playhead location of a an audio/video box)
     restoreView?: (viewSpec: Doc) => boolean;
     scrollPreview?: (docView: DocumentView, doc: Doc, focusSpeed: number, options: FocusViewOptions) => Opt<number>; // returns the duration of the focus
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 880d1cd74..4b4a07757 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1878,7 +1878,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
 
     updateIcon = (usePanelDimensions?: boolean) =>
         UpdateIcon(
-            this.layoutDoc[Id] + '-icon' + new Date().getTime(),
+            this.layoutDoc[Id] + '_icon_' + new Date().getTime(),
             this.DocumentView?.().ContentDiv!,
             usePanelDimensions ? this._props.PanelWidth() : NumCast(this.layoutDoc._width),
             usePanelDimensions ? this._props.PanelHeight() : NumCast(this.layoutDoc._height),
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 4cc7eb0ff..c279badf4 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -16,7 +16,7 @@ import { List } from '../../../fields/List';
 import { PrefetchProxy } from '../../../fields/Proxy';
 import { listSpec } from '../../../fields/Schema';
 import { ScriptField } from '../../../fields/ScriptField';
-import { BoolCast, Cast, DocCast, NumCast, RTFCast, ScriptCast, StrCast } from '../../../fields/Types';
+import { BoolCast, Cast, DocCast, ImageCast, NumCast, RTFCast, ScriptCast, StrCast } from '../../../fields/Types';
 import { AudioField } from '../../../fields/URLField';
 import { GetEffectiveAcl, TraceMobx } from '../../../fields/util';
 import { AudioAnnoState } from '../../../server/SharedMediaTypes';
@@ -1087,6 +1087,17 @@ export class DocumentView extends DocComponent<DocumentViewProps>() {
      * Pins a Doc to the current presentation trail. (see TabDocView for implementation)
      */
     public static PinDoc: (docIn: Doc | Doc[], pinProps: PinProps) => void;
+
+    /**
+     * Renders an image of a Doc into the Doc's icon field, then returns a promise for the image value
+     * @param doc Doc to snapshot
+     * @returns promise of icon ImageField
+     */
+    public static GetDocImage(doc: Doc) {
+        return DocumentView.getDocumentView(doc)
+            ?.ComponentView?.updateIcon?.()
+            .then(() => ImageCast(DocCast(doc).icon));
+    }
     /**
      * The DocumentView below the cursor at the start of a gesture (that receives the pointerDown event).  Used by GestureOverlay to determine the doc a gesture should apply to.
      */
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index b17275a1e..209c5abbc 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -179,28 +179,26 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
     updateIcon = () => {
         // currently we render pdf icons as text labels
         const docViewContent = this.DocumentView?.().ContentDiv;
-        const filename = this.layoutDoc[Id] + '-icon' + new Date().getTime();
-        this._pdfViewer?._mainCont.current &&
-            docViewContent &&
-            UpdateIcon(
-                filename,
-                docViewContent,
-                NumCast(this.layoutDoc._width),
-                NumCast(this.layoutDoc._height),
-                this._props.PanelWidth(),
-                this._props.PanelHeight(),
-                NumCast(this.layoutDoc._layout_scrollTop),
-                NumCast(this.dataDoc[this.fieldKey + '_nativeHeight'], 1),
-                true,
-                this.layoutDoc[Id] + '-icon',
-                (iconFile: string, nativeWidth: number, nativeHeight: number) => {
-                    setTimeout(() => {
-                        this.dataDoc.icon = new ImageField(iconFile);
-                        this.dataDoc.icon_nativeWidth = nativeWidth;
-                        this.dataDoc.icon_nativeHeight = nativeHeight;
-                    }, 500);
-                }
-            );
+        const filename = this.layoutDoc[Id] + '_icon_' + new Date().getTime();
+        return !(this._pdfViewer?._mainCont.current && docViewContent)
+            ? new Promise<void>(res => res())
+            : UpdateIcon(
+                  filename,
+                  docViewContent,
+                  NumCast(this.layoutDoc._width),
+                  NumCast(this.layoutDoc._height),
+                  this._props.PanelWidth(),
+                  this._props.PanelHeight(),
+                  NumCast(this.layoutDoc._layout_scrollTop),
+                  NumCast(this.dataDoc[this.fieldKey + '_nativeHeight'], 1),
+                  true,
+                  this.layoutDoc[Id] + '_icon_' + new Date().getTime(),
+                  (iconFile: string, nativeWidth: number, nativeHeight: number) => {
+                      this.dataDoc.icon = new ImageField(iconFile);
+                      this.dataDoc.icon_nativeWidth = nativeWidth;
+                      this.dataDoc.icon_nativeHeight = nativeHeight;
+                  }
+              );
     };
 
     componentWillUnmount() {
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index 4933869a7..d653b27d7 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -298,18 +298,19 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
             const retitled = StrCast(this.Document.title).replace(/[ -.:]/g, '');
             const encodedFilename = encodeURIComponent(('snapshot' + retitled + '_' + (this.layoutDoc._layout_currentTimecode || 0).toString()).replace(/[./?=]/g, '_'));
             const filename = basename(encodedFilename);
-            ClientUtils.convertDataUri(dataUrl, filename).then((returnedFilename: string) => returnedFilename && (cb ?? this.createSnapshotLink)(returnedFilename, downX, downY));
+            return ClientUtils.convertDataUri(dataUrl, filename).then((returnedFilename: string) => {
+                if (returnedFilename) (cb ?? this.createSnapshotLink)(returnedFilename, downX, downY);
+            });
         }
+        return new Promise<void>(res => res());
     };
 
-    updateIcon = () => {
-        const makeIcon = (returnedfilename: string) => {
+    updateIcon = () =>
+        this.Snapshot(undefined, undefined, (returnedfilename: string) => {
             this.dataDoc.icon = new ImageField(returnedfilename);
             this.dataDoc.icon_nativeWidth = NumCast(this.layoutDoc._width);
             this.dataDoc.icon_nativeHeight = NumCast(this.layoutDoc._height);
-        };
-        this.Snapshot(undefined, undefined, makeIcon);
-    };
+        });
 
     // creates link for snapshot
     createSnapshotLink = (imagePath: string, downX?: number, downY?: number) => {
@@ -459,7 +460,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
             const url = field.url.href;
             const subitems: ContextMenuProps[] = [];
             subitems.push({ description: 'Full Screen', event: this.FullScreen, icon: 'expand' });
-            subitems.push({ description: 'Take Snapshot', event: this.Snapshot, icon: 'expand-arrows-alt' });
+            subitems.push({ description: 'Take Snapshot', event: () => this.Snapshot(), icon: 'expand-arrows-alt' });
             this.Document.type === DocumentType.SCREENSHOT &&
                 subitems.push({
                     description: 'Screen Capture',
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx
index 8088bddd4..a5788d02a 100644
--- a/src/client/views/nodes/WebBox.tsx
+++ b/src/client/views/nodes/WebBox.tsx
@@ -144,38 +144,31 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
     };
 
     updateIcon = async () => {
-        if (!this._iframe) return;
+        if (!this._iframe) return new Promise<void>(res => res());
         const scrollTop = NumCast(this.layoutDoc._layout_scrollTop);
         const nativeWidth = NumCast(this.layoutDoc.nativeWidth);
         const nativeHeight = (nativeWidth * this._props.PanelHeight()) / this._props.PanelWidth();
         let htmlString = this._iframe.contentDocument && new XMLSerializer().serializeToString(this._iframe.contentDocument);
         if (!htmlString) {
-            htmlString = await (await fetch(ClientUtils.CorsProxy(this.webField!.href))).text();
+            htmlString = await fetch(ClientUtils.CorsProxy(this.webField!.href)).then(response => response.text());
         }
         this.layoutDoc.thumb = undefined;
         this.Document.thumbLockout = true; // lock to prevent multiple thumb updates.
-        CreateImage(this._webUrl.endsWith('/') ? this._webUrl.substring(0, this._webUrl.length - 1) : this._webUrl, this._iframe.contentDocument?.styleSheets ?? [], htmlString, nativeWidth, nativeHeight, scrollTop)
+        return (CreateImage(this._webUrl.endsWith('/') ? this._webUrl.substring(0, this._webUrl.length - 1) : this._webUrl, this._iframe.contentDocument?.styleSheets ?? [], htmlString, nativeWidth, nativeHeight, scrollTop) as Promise<string>)
             .then((dataUrl: string) => {
                 if (dataUrl.includes('<!DOCTYPE')) {
                     console.log('BAD DATA IN THUMB CREATION');
                     return;
                 }
-                ClientUtils.convertDataUri(dataUrl, this.layoutDoc[Id] + '-icon' + new Date().getTime(), true, this.layoutDoc[Id] + '-icon').then(returnedfilename =>
-                    setTimeout(
-                        action(() => {
-                            this.Document.thumbLockout = false;
-                            this.layoutDoc.thumb = new ImageField(returnedfilename);
-                            this.layoutDoc.thumbScrollTop = scrollTop;
-                            this.layoutDoc.thumbNativeWidth = nativeWidth;
-                            this.layoutDoc.thumbNativeHeight = nativeHeight;
-                        }),
-                        500
-                    )
-                );
+                return ClientUtils.convertDataUri(dataUrl, this.layoutDoc[Id] + '_icon_' + new Date().getTime(), true, this.layoutDoc[Id] + '_icon_').then(returnedfilename => {
+                    this.Document.thumbLockout = false;
+                    this.layoutDoc.thumb = new ImageField(returnedfilename);
+                    this.layoutDoc.thumbScrollTop = scrollTop;
+                    this.layoutDoc.thumbNativeWidth = nativeWidth;
+                    this.layoutDoc.thumbNativeHeight = nativeHeight;
+                });
             })
-            .catch((error: object) => {
-                console.error('oops, something went wrong!', error);
-            });
+            .catch((error: object) => console.error('oops, something went wrong!', error));
     };
 
     componentDidMount() {
diff --git a/src/client/views/smartdraw/AnnotationPalette.tsx b/src/client/views/smartdraw/AnnotationPalette.tsx
index 72364be09..2ebe5bca5 100644
--- a/src/client/views/smartdraw/AnnotationPalette.tsx
+++ b/src/client/views/smartdraw/AnnotationPalette.tsx
@@ -6,7 +6,7 @@ import { observer } from 'mobx-react';
 import * as React from 'react';
 import { AiOutlineSend } from 'react-icons/ai';
 import ReactLoading from 'react-loading';
-import { returnEmptyFilter, returnFalse, returnTrue } from '../../../ClientUtils';
+import { ClientUtils, returnEmptyFilter, returnFalse, returnTrue } from '../../../ClientUtils';
 import { emptyFunction } from '../../../Utils';
 import { Doc, DocListCast, returnEmptyDoclist } from '../../../fields/Doc';
 import { DocData } from '../../../fields/DocSymbols';
@@ -25,6 +25,7 @@ import { DocumentView, DocumentViewInternal } from '../nodes/DocumentView';
 import { FieldView } from '../nodes/FieldView';
 import './AnnotationPalette.scss';
 import { DrawingOptions, SmartDrawHandler } from './SmartDrawHandler';
+import { setTime } from 'react-datepicker/dist/date_utils';
 
 interface AnnotationPaletteProps {
     Document: Doc;
@@ -109,26 +110,20 @@ export class AnnotationPalette extends ObservableReactComponent<AnnotationPalett
      */
     public static addToPalette = async (doc: Doc) => {
         if (!doc.savedAsAnno) {
-            const clone = await Doc.MakeClone(doc);
-            clone.clone.title = doc.title;
-            const image = ((await AnnotationPalette.getIcon(doc)) ?? ImageCast(doc[Doc.LayoutFieldKey(doc)]))?.[Copy]();
-            if (image) {
-                const imageTemplate = makeUserTemplateImage(clone.clone, image);
-                Doc.AddDocToList(Doc.MyAnnos, 'data', imageTemplate);
-                doc.savedAsAnno = true;
-            }
+            Doc.MakeClone(doc).then(cloneMap =>
+                DocumentView.getDocumentView(doc)
+                    ?.ComponentView?.updateIcon?.(true)
+                    .then(() => {
+                        const { clone } = cloneMap;
+                        clone.title = doc.title;
+                        const image = ImageCast(doc.icon, ImageCast(clone[Doc.LayoutFieldKey(clone)]))?.url?.href;
+                        Doc.AddDocToList(Doc.MyAnnos, 'data', makeUserTemplateImage(clone, image));
+                        doc.savedAsAnno = true;
+                    })
+            );
         }
     };
 
-    public static getIcon(group: Doc) {
-        const docView = DocumentView.getDocumentView(group);
-        if (docView) {
-            docView.ComponentView?.updateIcon?.(true);
-            return new Promise<ImageField | undefined>(res => setTimeout(() => res(ImageCast(docView.Document.icon)), 1000));
-        }
-        return undefined;
-    }
-
     /**
      * Calls the draw with GPT functions in SmartDrawHandler to allow users to generate drawings straight from
      * the annotation palette.
@@ -184,15 +179,6 @@ export class AnnotationPalette extends ObservableReactComponent<AnnotationPalett
         this.resetPalette(true);
     };
 
-    async getIcon(group: Doc) {
-        const docView = DocumentView.getDocumentView(group);
-        if (docView) {
-            docView.ComponentView?.updateIcon?.(true);
-            return new Promise<ImageField | undefined>(res => setTimeout(() => res(ImageCast(docView.Document.icon)), 1000));
-        }
-        return undefined;
-    }
-
     render() {
         return (
             <div className="annotation-palette" style={{ zIndex: 1000 }} onClick={e => e.stopPropagation()}>
diff --git a/src/client/views/smartdraw/SmartDrawHandler.tsx b/src/client/views/smartdraw/SmartDrawHandler.tsx
index 879358742..8271c0959 100644
--- a/src/client/views/smartdraw/SmartDrawHandler.tsx
+++ b/src/client/views/smartdraw/SmartDrawHandler.tsx
@@ -249,7 +249,7 @@ export class SmartDrawHandler extends ObservableReactComponent<object> {
      * Sends request to GPT API to recolor a selected ink document or group of ink documents.
      */
     colorWithGPT = async (drawing: Doc) => {
-        const img = await this.getIcon(drawing);
+        const img = await DocumentView.GetDocImage(drawing);
         const { href } = ImageCast(img).url;
         const hrefParts = href.split('.');
         const hrefComplete = `${hrefParts[0]}_o.${hrefParts[1]}`;
@@ -286,18 +286,6 @@ export class SmartDrawHandler extends ObservableReactComponent<object> {
         });
     }, 'color strokes');
 
-    /**
-     * Gets an image snapshot of a doc. In this class, it's used to snapshot a selected ink stroke/group to use for GPT color.
-     */
-    async getIcon(doc: Doc) {
-        const docView = DocumentView.getDocumentView(doc);
-        if (docView) {
-            docView.ComponentView?.updateIcon?.();
-            return new Promise<ImageField | undefined>(res => setTimeout(() => res(ImageCast(docView.Document.icon)), 1000));
-        }
-        return undefined;
-    }
-
     renderDisplay() {
         return (
             <div
-- 
cgit v1.2.3-70-g09d2


From 8d7bf0588ca63c2d505a494865dcf9921eb1383d Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Tue, 1 Oct 2024 15:57:57 -0400
Subject: more lint fixes

---
 src/client/util/CurrentUserUtils.ts                   |  2 +-
 src/client/util/DropConverter.ts                      |  2 +-
 src/client/util/Scripting.ts                          |  5 -----
 src/client/views/DocumentDecorations.tsx              |  2 +-
 src/client/views/InkTranscription.tsx                 |  1 +
 src/client/views/InkingStroke.tsx                     |  4 +---
 src/client/views/LightboxView.tsx                     |  2 --
 src/client/views/Main.tsx                             |  1 -
 src/client/views/MainView.tsx                         | 19 +++++++------------
 .../views/collections/CollectionCarousel3DView.tsx    |  2 +-
 .../views/collections/CollectionCarouselView.tsx      |  4 ++--
 .../collectionFreeForm/CollectionFreeFormView.tsx     | 11 ++++++-----
 .../collections/collectionFreeForm/MarqueeView.tsx    |  3 +--
 src/client/views/nodes/FontIconBox/FontIconBox.tsx    |  1 -
 src/client/views/nodes/ImageBox.tsx                   |  1 -
 src/client/views/nodes/PDFBox.tsx                     |  5 +----
 .../views/nodes/formattedText/FormattedTextBox.tsx    |  8 --------
 src/client/views/nodes/formattedText/RichTextMenu.tsx |  1 -
 src/client/views/pdf/PDFViewer.tsx                    |  2 --
 src/client/views/smartdraw/AnnotationPalette.tsx      |  4 +---
 src/client/views/smartdraw/SmartDrawHandler.tsx       |  3 ++-
 src/fields/SchemaHeaderField.ts                       |  1 -
 22 files changed, 26 insertions(+), 58 deletions(-)

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

diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 59760ba32..96d69e7a1 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -2,7 +2,7 @@
 import { reaction, runInAction } from "mobx";
 import * as rp from 'request-promise';
 import { ClientUtils, OmitKeys } from "../../ClientUtils";
-import { Doc, DocListCast, DocListCastAsync, FieldType, Opt, StrListCast } from "../../fields/Doc";
+import { Doc, DocListCast, DocListCastAsync, FieldType, Opt } from "../../fields/Doc";
 import { DocData } from "../../fields/DocSymbols";
 import { InkTool } from "../../fields/InkField";
 import { List } from "../../fields/List";
diff --git a/src/client/util/DropConverter.ts b/src/client/util/DropConverter.ts
index 71cdaa58b..b5d29be4c 100644
--- a/src/client/util/DropConverter.ts
+++ b/src/client/util/DropConverter.ts
@@ -67,7 +67,7 @@ export function MakeTemplate(doc: Doc) {
 /**
  * Makes a draggable button or image that will create a template doc Instance
  */
-export function makeUserTemplateButtonOrImage(doc: Doc, image: string | undefined) {
+export function makeUserTemplateButtonOrImage(doc: Doc, image?: string) {
     const layoutDoc = doc; // doc.layout instanceof Doc && doc.layout.isTemplateForField ? doc.layout : doc;
     if (layoutDoc.type !== DocumentType.FONTICON) {
         !layoutDoc.isTemplateDoc && makeTemplate(layoutDoc);
diff --git a/src/client/util/Scripting.ts b/src/client/util/Scripting.ts
index c63d3d7cb..c7b86815a 100644
--- a/src/client/util/Scripting.ts
+++ b/src/client/util/Scripting.ts
@@ -60,7 +60,6 @@ function Run(script: string | undefined, customParams: string[], diagnostics: ts
     // let params: any[] = [Docs, ...fieldTypes];
     const compiledFunction = (() => {
         try {
-            // eslint-disable-next-line no-new-func
             return new Function(...paramNames, `return ${script}`);
         } catch (e) {
             console.log(e);
@@ -69,10 +68,8 @@ function Run(script: string | undefined, customParams: string[], diagnostics: ts
     })();
     if (!compiledFunction) return { compiled: false, errors };
     const { capturedVariables = {} } = options;
-    // eslint-disable-next-line default-param-last
     const run = (args: { [name: string]: unknown } = {}, onError?: (e: string) => void, errorVal?: ts.Diagnostic): ScriptResult => {
         const argsArray: unknown[] = [];
-        // eslint-disable-next-line no-restricted-syntax
         for (const name of customParams) {
             if (name !== 'this') {
                 argsArray.push(name in args ? args[name] : capturedVariables[name]);
@@ -224,7 +221,6 @@ export function CompileScript(script: string, options: ScriptOptions = {}): Comp
     if ('this' in params || 'this' in capturedVariables) {
         paramNames.push('this');
     }
-    // eslint-disable-next-line no-restricted-syntax
     for (const key in params) {
         if (key !== 'this') {
             paramNames.push(key);
@@ -234,7 +230,6 @@ export function CompileScript(script: string, options: ScriptOptions = {}): Comp
         const val = params[key];
         return `${key}: ${val}`;
     });
-    // eslint-disable-next-line no-restricted-syntax
     for (const key in capturedVariables) {
         if (key !== 'this') {
             const val = capturedVariables[key];
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index e569c7dc8..1c0d51e17 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -2,7 +2,7 @@ import { IconProp } from '@fortawesome/fontawesome-svg-core';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { Tooltip } from '@mui/material';
 import { IconButton } from 'browndash-components';
-import { action, computed, makeObservable, observable, runInAction, trace } from 'mobx';
+import { action, computed, makeObservable, observable, runInAction } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
 import { FaUndo } from 'react-icons/fa';
diff --git a/src/client/views/InkTranscription.tsx b/src/client/views/InkTranscription.tsx
index b4f4ebf63..24d53a8c8 100644
--- a/src/client/views/InkTranscription.tsx
+++ b/src/client/views/InkTranscription.tsx
@@ -18,6 +18,7 @@ import { URLField } from '../../fields/URLField';
  * Class component that handles inking in writing mode
  */
 export class InkTranscription extends React.Component {
+    // eslint-disable-next-line no-use-before-define
     static Instance: InkTranscription;
 
     // eslint-disable-next-line @typescript-eslint/no-explicit-any
diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx
index f44c1720d..270266a94 100644
--- a/src/client/views/InkingStroke.tsx
+++ b/src/client/views/InkingStroke.tsx
@@ -51,7 +51,7 @@ import { InkTranscription } from './InkTranscription';
 import { CollectionFreeFormView } from './collections/collectionFreeForm';
 import { DocumentView } from './nodes/DocumentView';
 
-// eslint-disable-next-line @typescript-eslint/no-var-requires, @typescript-eslint/no-require-imports
+// eslint-disable-next-line @typescript-eslint/no-require-imports
 const { INK_MASK_SIZE } = require('./global/globalCssVariables.module.scss'); // prettier-ignore
 
 @observer
@@ -473,7 +473,6 @@ export class InkingStroke extends ViewBoxAnnotatableComponent<FieldViewProps>()
                         // mixBlendMode: this.layoutDoc.tool === InkTool.Highlighter ? 'multiply' : 'unset',
                         cursor: this._props.isSelected() ? 'default' : undefined,
                     }}
-                    // eslint-disable-next-line react/jsx-props-no-spreading
                     {...interactions}>
                     {clickableLine(this.onPointerDown, isInkMask)}
                     {isInkMask ? null : inkLine}
@@ -490,7 +489,6 @@ export class InkingStroke extends ViewBoxAnnotatableComponent<FieldViewProps>()
                             // top: (this._props.PanelHeight() - (lineHeightGuess * fsize + 20) * (this._props.NativeDimScaling?.() || 1)) / 2,
                         }}>
                         <FormattedTextBox
-                            // eslint-disable-next-line react/jsx-props-no-spreading
                             {...this._props}
                             setHeight={undefined}
                             setContentViewBox={this.setSubContentView} // this makes the inkingStroke the "dominant" component - ie, it will show the inking UI when selected (not text)
diff --git a/src/client/views/LightboxView.tsx b/src/client/views/LightboxView.tsx
index 331b3db64..a543b4875 100644
--- a/src/client/views/LightboxView.tsx
+++ b/src/client/views/LightboxView.tsx
@@ -46,7 +46,6 @@ export class LightboxView extends ObservableReactComponent<LightboxViewProps> {
         ); 
     } // prettier-ignore
     public static LightboxDoc = () => LightboxView.Instance?._doc;
-    // eslint-disable-next-line no-use-before-define
     static Instance: LightboxView;
     private _path: {
         doc: Opt<Doc>; //
@@ -341,7 +340,6 @@ export class LightboxView extends ObservableReactComponent<LightboxViewProps> {
 }
 interface LightboxTourBtnProps {
     navBtn: (left: Opt<string | number>, bottom: Opt<number>, top: number, icon: IconProp, display: boolean, click: () => void, color?: string) => JSX.Element;
-    // eslint-disable-next-line react/no-unused-prop-types
     future: () => Opt<Doc[]>;
     stepInto: () => void;
     lightboxDoc: () => Opt<Doc>;
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index 94294e97a..73d2872d1 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -1,4 +1,3 @@
-/* eslint-disable no-new */
 // if ((module as any).hot) {
 //     (module as any).hot.accept();
 // }
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 8e921ca5e..fa2e94d12 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -3,7 +3,7 @@ import { faBuffer, faHireAHelper } from '@fortawesome/free-brands-svg-icons';
 import * as far from '@fortawesome/free-regular-svg-icons';
 import * as fa from '@fortawesome/free-solid-svg-icons';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { action, computed, configure, makeObservable, observable, reaction, runInAction, trace } from 'mobx';
+import { action, computed, configure, makeObservable, observable, reaction, runInAction } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
 import ResizeObserver from 'resize-observer-polyfill';
@@ -77,7 +77,7 @@ import { TopBar } from './topbar/TopBar';
 import { SmartDrawHandler } from './smartdraw/SmartDrawHandler';
 import { InkTranscription } from './InkTranscription';
 
-// eslint-disable-next-line @typescript-eslint/no-var-requires, @typescript-eslint/no-require-imports
+// eslint-disable-next-line @typescript-eslint/no-require-imports
 const { LEFT_MENU_WIDTH, TOPBAR_HEIGHT } = require('./global/globalCssVariables.module.scss'); // prettier-ignore
 
 @observer
@@ -977,13 +977,11 @@ export class MainView extends ObservableReactComponent<object> {
             <div className="mainView-snapLines">
                 <svg style={{ width: '100%', height: '100%' }}>
                     {[
-                        ...SnappingManager.HorizSnapLines.map((l, i) => (
-                            // eslint-disable-next-line react/no-array-index-key
-                            <line key={'horiz' + i} x1="0" y1={l} x2="2000" y2={l} stroke={lightOrDark(StrCast(dragPar.layoutDoc.backgroundColor, 'gray'))} opacity={0.3} strokeWidth={1} strokeDasharray="2 2" />
+                        ...SnappingManager.HorizSnapLines.map(l => (
+                            <line key={'horiz' + l} x1="0" y1={l} x2="2000" y2={l} stroke={lightOrDark(StrCast(dragPar.layoutDoc.backgroundColor, 'gray'))} opacity={0.3} strokeWidth={1} strokeDasharray="2 2" />
                         )),
-                        ...SnappingManager.VertSnapLines.map((l, i) => (
-                            // eslint-disable-next-line react/no-array-index-key
-                            <line key={'vert' + i} y1={this.topOfMainDocContent.toString()} x1={l} y2="2000" x2={l} stroke={lightOrDark(StrCast(dragPar.layoutDoc.backgroundColor, 'gray'))} opacity={0.3} strokeWidth={1} strokeDasharray="2 2" />
+                        ...SnappingManager.VertSnapLines.map(l => (
+                            <line key={'vert' + l} y1={this.topOfMainDocContent.toString()} x1={l} y2="2000" x2={l} stroke={lightOrDark(StrCast(dragPar.layoutDoc.backgroundColor, 'gray'))} opacity={0.3} strokeWidth={1} strokeDasharray="2 2" />
                         )),
                     ]}
                 </svg>
@@ -1071,10 +1069,7 @@ export class MainView extends ObservableReactComponent<object> {
                         docView={DocButtonState.Instance.LinkEditorDocView}
                     />
                 ) : null}
-                {LinkInfo.Instance?.LinkInfo ? (
-                    // eslint-disable-next-line react/jsx-props-no-spreading
-                    <LinkDocPreview {...LinkInfo.Instance.LinkInfo} />
-                ) : null}
+                {LinkInfo.Instance?.LinkInfo ? <LinkDocPreview {...LinkInfo.Instance.LinkInfo} /> : null}
                 {((page: string) => {
                     // prettier-ignore
                     switch (page) {
diff --git a/src/client/views/collections/CollectionCarousel3DView.tsx b/src/client/views/collections/CollectionCarousel3DView.tsx
index cf86a0a4e..c5da8e037 100644
--- a/src/client/views/collections/CollectionCarousel3DView.tsx
+++ b/src/client/views/collections/CollectionCarousel3DView.tsx
@@ -16,6 +16,7 @@ import './CollectionCarousel3DView.scss';
 import { CollectionSubView, SubCollectionViewProps } from './CollectionSubView';
 import { Transform } from '../../util/Transform';
 
+// eslint-disable-next-line @typescript-eslint/no-require-imports
 const { CAROUSEL3D_CENTER_SCALE, CAROUSEL3D_SIDE_SCALE, CAROUSEL3D_TOP } = require('../global/globalCssVariables.module.scss');
 
 @observer
@@ -88,7 +89,6 @@ export class CollectionCarousel3DView extends CollectionSubView() {
         const currentIndex = NumCast(this.layoutDoc._carousel_index);
         const displayDoc = (childPair: { layout: Doc; data: Doc }, dxf: () => Transform) => (
             <DocumentView
-                // eslint-disable-next-line react/jsx-props-no-spreading
                 {...this._props}
                 Document={childPair.layout}
                 TemplateDataDocument={childPair.data}
diff --git a/src/client/views/collections/CollectionCarouselView.tsx b/src/client/views/collections/CollectionCarouselView.tsx
index db75c9e8b..74cf580c9 100644
--- a/src/client/views/collections/CollectionCarouselView.tsx
+++ b/src/client/views/collections/CollectionCarouselView.tsx
@@ -3,8 +3,8 @@ import { IReactionDisposer, action, computed, makeObservable, observable, reacti
 import { observer } from 'mobx-react';
 import * as React from 'react';
 import { StopEvent, returnOne, returnZero } from '../../../ClientUtils';
-import { Doc, DocListCast, Opt } from '../../../fields/Doc';
-import { BoolCast, Cast, DocCast, NumCast, ScriptCast, StrCast } from '../../../fields/Types';
+import { Doc, Opt } from '../../../fields/Doc';
+import { BoolCast, DocCast, NumCast, ScriptCast, StrCast } from '../../../fields/Types';
 import { DocumentType } from '../../documents/DocumentTypes';
 import { DragManager } from '../../util/DragManager';
 import { ContextMenu } from '../ContextMenu';
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index cdcc2328f..0cc63d632 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -510,12 +510,13 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
                         e.stopPropagation();
                         break;
                     case InkTool.SmartDraw:
-                        setupMoveUpEvents(this, e, this.onPointerMove, emptyFunction, e => this.showSmartDraw(e.pageX, e.pageY), hit !== -1);
+                        setupMoveUpEvents(this, e, this.onPointerMove, emptyFunction, () => this.showSmartDraw(e.pageX, e.pageY), hit !== -1);
                         e.stopPropagation();
+                        break;
                     case InkTool.None:
                         if (!(this._props.layoutEngine?.() || StrCast(this.layoutDoc._layoutEngine))) {
-                            const hit = this._clusters.handlePointerDown(this.screenToFreeformContentsXf.transformPoint(e.clientX, e.clientY));
-                            setupMoveUpEvents(this, e, this.onPointerMove, emptyFunction, emptyFunction, hit !== -1, false);
+                            const ahit = this._clusters.handlePointerDown(this.screenToFreeformContentsXf.transformPoint(e.clientX, e.clientY));
+                            setupMoveUpEvents(this, e, this.onPointerMove, emptyFunction, emptyFunction, ahit !== -1, false);
                         }
                         break;
                     default:
@@ -655,13 +656,13 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
     };
 
     @action
-    onEraserClick = (e: PointerEvent, doubleTap?: boolean) => {
+    onEraserClick = (e: PointerEvent) => {
         e.preventDefault();
         e.stopImmediatePropagation();
         this.erase(e, [0, 0]);
     };
 
-    forceStrokeGesture = (e: PointerEvent, gesture: Gestures, points: InkData, text?: any) => {
+    forceStrokeGesture = (e: PointerEvent, gesture: Gestures, points: InkData, text?: string) => {
         this.onGesture(e, new GestureUtils.GestureEvent(gesture, points, InkField.getBounds(points), text));
     };
 
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index 7614b5337..b1f6815b3 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -57,6 +57,7 @@ export class MarqueeView extends ObservableReactComponent<SubCollectionViewProps
         return { left: NumCast(pinDoc._freeform_panX) - panelWidth / 2 / ps, top: NumCast(pinDoc._freeform_panY) - panelHeight / 2 / ps, width: panelWidth / ps, height: panelHeight / ps };
     }
 
+    // eslint-disable-next-line no-use-before-define
     static Instance: MarqueeView;
 
     constructor(props: SubCollectionViewProps & MarqueeViewProps) {
@@ -548,7 +549,6 @@ export class MarqueeView extends ObservableReactComponent<SubCollectionViewProps
     };
 
     touchesLine(r1: { left: number; top: number; width: number; height: number }) {
-        // eslint-disable-next-line no-restricted-syntax
         for (const lassoPt of this._lassoPts) {
             const topLeft = this.Transform.transformPoint(lassoPt[0], lassoPt[1]);
             if (r1.left < topLeft[0] && topLeft[0] < r1.left + r1.width && r1.top < topLeft[1] && topLeft[1] < r1.top + r1.height) {
@@ -569,7 +569,6 @@ export class MarqueeView extends ObservableReactComponent<SubCollectionViewProps
             let hasLeft = false;
             let hasBottom = false;
             let hasRight = false;
-            // eslint-disable-next-line no-restricted-syntax
             for (const lassoPt of this._lassoPts) {
                 const truePoint = this.Transform.transformPoint(lassoPt[0], lassoPt[1]);
                 hasLeft = hasLeft || (truePoint[0] > tl[0] && truePoint[0] < r1.left && truePoint[1] > r1.top && truePoint[1] < r1.top + r1.height);
diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
index b7e1350ca..feaf84b7b 100644
--- a/src/client/views/nodes/FontIconBox/FontIconBox.tsx
+++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
@@ -1,4 +1,3 @@
-/* eslint-disable react/jsx-props-no-spreading */
 import { IconProp } from '@fortawesome/fontawesome-svg-core';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { Button, ColorPicker, Dropdown, DropdownType, IconButton, IListItemProps, MultiToggle, NumberDropdown, NumberDropdownType, Popup, Size, Toggle, ToggleType, Type } from 'browndash-components';
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index aa4376bb2..ec5e062c8 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -493,7 +493,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 42ac51107..7ef431885 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';
@@ -538,7 +538,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}
@@ -554,7 +553,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}
@@ -608,7 +606,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 d1b0dc7bf..d3bc08bd3 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -655,7 +655,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);
@@ -714,7 +713,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)
     };
 
@@ -1131,7 +1129,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);
@@ -1285,7 +1282,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) {
@@ -1711,7 +1707,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));
         }
@@ -1793,7 +1788,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 => {
@@ -1880,7 +1874,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}
@@ -1900,7 +1893,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/nodes/formattedText/RichTextMenu.tsx b/src/client/views/nodes/formattedText/RichTextMenu.tsx
index 1560d51a1..88e2e4248 100644
--- a/src/client/views/nodes/formattedText/RichTextMenu.tsx
+++ b/src/client/views/nodes/formattedText/RichTextMenu.tsx
@@ -697,7 +697,6 @@ interface RichTextMenuPluginProps {
     editorProps: FormattedTextBoxProps;
 }
 export class RichTextMenuPlugin extends React.Component<RichTextMenuPluginProps> {
-    // eslint-disable-next-line react/no-unused-class-component-methods
     update(view: EditorView & { TextView?: FormattedTextBox }, lastState: EditorState | undefined) {
         RichTextMenu.Instance?.updateMenu(view, lastState, this.props.editorProps, view.TextView?.layoutDoc);
     }
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index 01242ba48..7a86ee802 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -504,7 +504,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>
@@ -537,7 +536,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/client/views/smartdraw/AnnotationPalette.tsx b/src/client/views/smartdraw/AnnotationPalette.tsx
index 1c17469c3..f1e2e4f41 100644
--- a/src/client/views/smartdraw/AnnotationPalette.tsx
+++ b/src/client/views/smartdraw/AnnotationPalette.tsx
@@ -11,6 +11,7 @@ import { emptyFunction } from '../../../Utils';
 import { Doc, DocListCast, returnEmptyDoclist } from '../../../fields/Doc';
 import { DocData } from '../../../fields/DocSymbols';
 import { ImageCast, NumCast } from '../../../fields/Types';
+import { ImageField } from '../../../fields/URLField';
 import { DocumentType } from '../../documents/DocumentTypes';
 import { Docs } from '../../documents/Documents';
 import { makeUserTemplateButtonOrImage } from '../../util/DropConverter';
@@ -23,8 +24,6 @@ import { DocumentView, DocumentViewInternal } from '../nodes/DocumentView';
 import { FieldView } from '../nodes/FieldView';
 import './AnnotationPalette.scss';
 import { DrawingOptions, SmartDrawHandler } from './SmartDrawHandler';
-import { ImageField } from '../../../fields/URLField';
-import { Copy } from '../../../fields/FieldSymbols';
 
 interface AnnotationPaletteProps {
     Document: Doc;
@@ -158,7 +157,6 @@ export class AnnotationPalette extends ObservableReactComponent<AnnotationPalett
                 console.log('Error generating drawing', e);
             }
         }
-        // eslint-disable-next-line @typescript-eslint/no-unused-expressions
         this._opts.text !== '' ? (this._opts.text = `${this._opts.text} ~~~ ${this._userInput}`) : (this._opts.text = this._userInput);
         this._userInput = '';
         this._isLoading = false;
diff --git a/src/client/views/smartdraw/SmartDrawHandler.tsx b/src/client/views/smartdraw/SmartDrawHandler.tsx
index 76bfe2a19..75ef55060 100644
--- a/src/client/views/smartdraw/SmartDrawHandler.tsx
+++ b/src/client/views/smartdraw/SmartDrawHandler.tsx
@@ -50,6 +50,7 @@ export interface DrawingOptions {
 
 @observer
 export class SmartDrawHandler extends ObservableReactComponent<object> {
+    // eslint-disable-next-line no-use-before-define
     static Instance: SmartDrawHandler;
 
     private _lastInput: DrawingOptions = { text: '', complexity: 5, size: 350, autoColor: true, x: 0, y: 0 };
@@ -395,7 +396,7 @@ export class SmartDrawHandler extends ObservableReactComponent<object> {
                                 defaultChecked={true}
                                 value={this._autoColor}
                                 size="small"
-                                onChange={action(e => this._canInteract && (this._autoColor = !this._autoColor))}
+                                onChange={action(() => this._canInteract && (this._autoColor = !this._autoColor))}
                             />
                         </div>
                         <div className="complexity">
diff --git a/src/fields/SchemaHeaderField.ts b/src/fields/SchemaHeaderField.ts
index 0a8dd1d9e..5f4d59cf9 100644
--- a/src/fields/SchemaHeaderField.ts
+++ b/src/fields/SchemaHeaderField.ts
@@ -79,7 +79,6 @@ export class SchemaHeaderField extends ObjectField {
     @serializable(primitive())
     desc: boolean | undefined; // boolean determines sort order, undefined when no sort
 
-    // eslint-disable-next-line default-param-last
     constructor(heading: string = '', color: string = RandomPastel(), type?: ColumnType, width?: number, desc?: boolean, collapsed?: boolean) {
         super();
 
-- 
cgit v1.2.3-70-g09d2

