From 35f0c9940d0ea7c0cb37c711557454b77ac038ad Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Tue, 1 Mar 2022 19:59:47 -0500
Subject: updated to webpack 5

---
 src/client/util/Import & Export/DirectoryImportBox.tsx | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'src/client/util/Import & Export/DirectoryImportBox.tsx')

diff --git a/src/client/util/Import & Export/DirectoryImportBox.tsx b/src/client/util/Import & Export/DirectoryImportBox.tsx
index 925b74efa..cf72cd0df 100644
--- a/src/client/util/Import & Export/DirectoryImportBox.tsx	
+++ b/src/client/util/Import & Export/DirectoryImportBox.tsx	
@@ -86,7 +86,7 @@ export class DirectoryImportBox extends React.Component<FieldViewProps> {
         for (let i = 0; i < files.length; i++) {
             const file = files.item(i);
             if (file && !unsupported.includes(file.type)) {
-                const ext = path.extname(file.name).toLowerCase();
+                const ext = file.name.replace(/.*\./, "").toLowerCase(); // path.extname(file.name).toLowerCase();
                 if (AcceptableMedia.imageFormats.includes(ext)) {
                     validated.push(file);
                 }
@@ -120,7 +120,7 @@ export class DirectoryImportBox extends React.Component<FieldViewProps> {
             }
             const { accessPaths, exifData } = result;
             const path = Utils.prepend(accessPaths.agnostic.client);
-            const document = await DocUtils.DocumentFromType(type, path, { _width: 300, title: name });
+            const document = type && await DocUtils.DocumentFromType(type, path, { _width: 300, title: name });
             const { data, error } = exifData;
             if (document) {
                 Doc.GetProto(document).exif = error || Doc.Get.FromJson({ data });
-- 
cgit v1.2.3-70-g09d2


From 398a50bc1d7e77691620a4a6752fd38d4bb391b0 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Wed, 2 Mar 2022 14:43:48 -0500
Subject: upgraded to typescript 4.6.2

---
 .vscode/launch.json                                |   2 +-
 package-lock.json                                  | 371 +++++++++++++--------
 package.json                                       |  17 +-
 src/client/documents/Documents.ts                  |   5 +-
 src/client/util/CurrentUserUtils.ts                |   6 +-
 src/client/util/DictationManager.ts                |   7 +-
 src/client/util/DocumentManager.ts                 |   4 +-
 src/client/util/DragManager.ts                     |   2 +-
 .../util/Import & Export/DirectoryImportBox.tsx    |   4 +-
 src/client/util/LinkManager.ts                     |   2 +-
 .../collectionSchema/CollectionSchemaCells.tsx     |   7 +-
 .../collectionSchema/CollectionSchemaView.tsx      |  25 +-
 .../collections/collectionSchema/SchemaTable.tsx   |   1 -
 src/client/views/nodes/AudioBox.tsx                | 130 ++++----
 src/client/views/nodes/DocumentView.tsx            |   9 +-
 src/client/views/nodes/ImageBox.tsx                |   2 +-
 .../views/nodes/formattedText/FormattedTextBox.tsx |   3 +-
 .../formattedText/ProsemirrorExampleTransfer.ts    |  24 +-
 .../views/nodes/formattedText/RichTextRules.ts     |  26 +-
 src/fields/CursorField.ts                          |   2 +-
 src/fields/Doc.ts                                  |   2 +-
 src/fields/ObjectField.ts                          |   2 +-
 src/fields/SchemaHeaderField.ts                    |  12 +-
 src/fields/Types.ts                                |   3 +-
 src/scraping/buxton/final/BuxtonImporter.ts        |   2 +-
 src/server/ActionUtilities.ts                      |   2 +-
 src/server/ApiManagers/UploadManager.ts            |  12 +-
 src/server/ApiManagers/UserManager.ts              |   2 +-
 src/server/DashSession/DashSessionAgent.ts         |   2 +-
 src/server/DashSession/Session/agents/monitor.ts   |   2 +-
 .../Session/agents/promisified_ipc_manager.ts      |   2 +-
 .../DashSession/Session/agents/server_worker.ts    |   2 +-
 src/server/DashUploadUtils.ts                      |   4 +-
 src/server/Search.ts                               |   2 +-
 src/server/apis/google/GoogleApiServerUtils.ts     |   4 +-
 src/server/remapUrl.ts                             |   2 +-
 src/server/server_Initialization.ts                |  12 +-
 webpack.config.js                                  |   4 +-
 38 files changed, 409 insertions(+), 313 deletions(-)

(limited to 'src/client/util/Import & Export/DirectoryImportBox.tsx')

diff --git a/.vscode/launch.json b/.vscode/launch.json
index 26c45a9d3..a7c30ca1e 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -33,7 +33,7 @@
             "type": "firefox",
             "request": "launch",
             "name": "Launch Firefox against localhost",
-            "sourceMaps": "client",
+            //"sourceMaps": "client",
             "reAttach": true,
             "url": "http://localhost:1050/login",
             "webRoot": "${workspaceFolder}",
diff --git a/package-lock.json b/package-lock.json
index 4184dd705..95cc7dec2 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1404,6 +1404,11 @@
             "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-2.1.1.tgz",
             "integrity": "sha512-9MVYlmIgmRR31C5b4FVSWtuMmBHh2mOWQYfl7XAYOa8dsnb7iEmUmRSWSFgXFtkjxO65d7hTUHQC+RhR/9IWFg=="
         },
+        "@types/dom-speech-recognition": {
+            "version": "0.0.1",
+            "resolved": "https://registry.npmjs.org/@types/dom-speech-recognition/-/dom-speech-recognition-0.0.1.tgz",
+            "integrity": "sha512-udCxb8DvjcDKfk1WTBzDsxFbLgYxmQGKrE/ricoMqHRNjSlSUCcamVTA5lIQqzY10mY5qCY0QDwBfFEwhfoDPw=="
+        },
         "@types/dotenv": {
             "version": "6.1.1",
             "resolved": "https://registry.npmjs.org/@types/dotenv/-/dotenv-6.1.1.tgz",
@@ -1448,6 +1453,11 @@
             "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==",
             "dev": true
         },
+        "@types/events": {
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz",
+            "integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g=="
+        },
         "@types/exif": {
             "version": "0.6.3",
             "resolved": "https://registry.npmjs.org/@types/exif/-/exif-0.6.3.tgz",
@@ -1515,14 +1525,19 @@
             "dev": true
         },
         "@types/formidable": {
-            "version": "1.2.5",
-            "resolved": "https://registry.npmjs.org/@types/formidable/-/formidable-1.2.5.tgz",
-            "integrity": "sha512-zu3mQJa4hDNubEMViSj937602XdDGzK7Q5pJ5QmLUbNxclbo9tZGt5jtwM352ssZ+pqo5V4H14TBvT/ALqQQcA==",
-            "dev": true,
+            "version": "1.0.31",
+            "resolved": "https://registry.npmjs.org/@types/formidable/-/formidable-1.0.31.tgz",
+            "integrity": "sha512-dIhM5t8lRP0oWe2HF8MuPvdd1TpPTjhDMAqemcq6oIZQCBQTovhBAdTQ5L5veJB4pdQChadmHuxtB0YzqvfU3Q==",
             "requires": {
+                "@types/events": "*",
                 "@types/node": "*"
             }
         },
+        "@types/geojson": {
+            "version": "7946.0.8",
+            "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.8.tgz",
+            "integrity": "sha512-1rkryxURpr6aWP7R786/UQOkJ3PcpQiWkAXBmdWc7ryFWqN6a4xfK7BtjXvFBKO9LjQ+MWQSWxYeZX1OApnArA=="
+        },
         "@types/glob": {
             "version": "7.2.0",
             "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz",
@@ -1596,8 +1611,7 @@
         "@types/json-schema": {
             "version": "7.0.9",
             "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz",
-            "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==",
-            "dev": true
+            "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ=="
         },
         "@types/keygrip": {
             "version": "1.0.2",
@@ -1628,15 +1642,6 @@
             "integrity": "sha512-uwc1x90yCKqGcIOAT6DwOSuxnrAbpkdPsUOZtwrXb4D/6wZs+6qG7QnIawDuZWg0sWpxl+ltIKCaLoMlna678w==",
             "dev": true
         },
-        "@types/memory-fs": {
-            "version": "0.3.3",
-            "resolved": "https://registry.npmjs.org/@types/memory-fs/-/memory-fs-0.3.3.tgz",
-            "integrity": "sha512-rLEYzl1xODshz+Lm+YX8NYws8Xw7/qcYbQInMkotl96VpLZmUvoCfYYGxfajMSiugANV02QO5Fc+R98KKeE4gQ==",
-            "dev": true,
-            "requires": {
-                "@types/node": "*"
-            }
-        },
         "@types/mime": {
             "version": "1.3.2",
             "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz",
@@ -2039,6 +2044,7 @@
             "version": "6.8.9",
             "resolved": "https://registry.npmjs.org/@types/react-table/-/react-table-6.8.9.tgz",
             "integrity": "sha512-fVQXjy/EYDbgraScgjDONA291McKqGrw0R0NeK639fx2bS4T19TnXMjg3FjOPlkI3qYTQtFTPADlRYysaQIMpA==",
+            "dev": true,
             "requires": {
                 "@types/react": "*"
             }
@@ -2189,6 +2195,14 @@
             "integrity": "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==",
             "dev": true
         },
+        "@types/supercluster": {
+            "version": "7.1.0",
+            "resolved": "https://registry.npmjs.org/@types/supercluster/-/supercluster-7.1.0.tgz",
+            "integrity": "sha512-6JapQ2GmEkH66r23BK49I+u6zczVDGTtiJEVvKDYZVSm/vepWaJuTq6BXzJ6I4agG5s8vA1KM7m/gXWDg03O4Q==",
+            "requires": {
+                "@types/geojson": "*"
+            }
+        },
         "@types/tapable": {
             "version": "1.0.8",
             "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.8.tgz",
@@ -2243,6 +2257,11 @@
             "integrity": "sha512-+33x29mg+ecU88ODdWpqaie2upIuRkhujVLA7TuJjM823cNMbeggfI6NhxewaRaRF8dy+g33e4uIg/m5Mb3xDQ==",
             "dev": true
         },
+        "@types/web": {
+            "version": "0.0.53",
+            "resolved": "https://registry.npmjs.org/@types/web/-/web-0.0.53.tgz",
+            "integrity": "sha512-ULJJgHevSiiD/QaSWcpAfWHXHEaeXUXGGJ82XVderV4TAWdI22NFyjWcRfzJwjEIdUi0gvfVRlTFDeLTZpvF4Q=="
+        },
         "@types/webpack": {
             "version": "4.41.32",
             "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.32.tgz",
@@ -2275,18 +2294,6 @@
                 }
             }
         },
-        "@types/webpack-dev-middleware": {
-            "version": "2.0.7",
-            "resolved": "https://registry.npmjs.org/@types/webpack-dev-middleware/-/webpack-dev-middleware-2.0.7.tgz",
-            "integrity": "sha512-pArv7YnqpbSCOBWiRlR1KgqVorlzkIiwto66hI8Gdgp5ATQAC+Ug4QVz69ZI1dP+D5Rs8QWnbT81tE4tcMuTag==",
-            "dev": true,
-            "requires": {
-                "@types/connect": "*",
-                "@types/memory-fs": "*",
-                "@types/webpack": "^4",
-                "loglevel": "^1.6.2"
-            }
-        },
         "@types/webpack-hot-middleware": {
             "version": "2.25.6",
             "resolved": "https://registry.npmjs.org/@types/webpack-hot-middleware/-/webpack-hot-middleware-2.25.6.tgz",
@@ -2554,6 +2561,11 @@
             "resolved": "https://registry.npmjs.org/Base64/-/Base64-0.2.1.tgz",
             "integrity": "sha1-ujpCMHCOGGcFBl5mur3Uw1z2ACg="
         },
+        "D": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/D/-/D-1.0.0.tgz",
+            "integrity": "sha512-nQvrCBu7K2pSSEtIM0EEF03FVjcczCXInMt3moLNFbjlWx6bZrX72uT6/1uAXDbnzGUAx9gTyDiQ+vrFi663oA=="
+        },
         "abab": {
             "version": "2.0.3",
             "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.3.tgz",
@@ -2678,6 +2690,32 @@
             "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz",
             "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ=="
         },
+        "ajv-formats": {
+            "version": "2.1.1",
+            "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz",
+            "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==",
+            "requires": {
+                "ajv": "^8.0.0"
+            },
+            "dependencies": {
+                "ajv": {
+                    "version": "8.10.0",
+                    "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.10.0.tgz",
+                    "integrity": "sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==",
+                    "requires": {
+                        "fast-deep-equal": "^3.1.1",
+                        "json-schema-traverse": "^1.0.0",
+                        "require-from-string": "^2.0.2",
+                        "uri-js": "^4.2.2"
+                    }
+                },
+                "json-schema-traverse": {
+                    "version": "1.0.0",
+                    "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
+                    "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="
+                }
+            }
+        },
         "ajv-keywords": {
             "version": "3.4.1",
             "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz",
@@ -3621,9 +3659,12 @@
             }
         },
         "bson": {
-            "version": "1.0.9",
-            "resolved": "https://registry.npmjs.org/bson/-/bson-1.0.9.tgz",
-            "integrity": "sha512-IQX9/h7WdMBIW/q/++tGd+emQr0XMdeZ6icnT/74Xk9fnabWn+gZgpE+9V+gujL3hhJOoNrnDVY7tWdzc7NUTg=="
+            "version": "4.6.1",
+            "resolved": "https://registry.npmjs.org/bson/-/bson-4.6.1.tgz",
+            "integrity": "sha512-I1LQ7Hz5zgwR4QquilLNZwbhPw0Apx7i7X9kGMBTsqPdml/03Q9NBtD9nt/19ahjlphktQImrnderxqpzeVDjw==",
+            "requires": {
+                "buffer": "^5.6.0"
+            }
         },
         "buffer": {
             "version": "5.6.0",
@@ -6106,15 +6147,6 @@
             "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==",
             "dev": true
         },
-        "dezalgo": {
-            "version": "1.0.3",
-            "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.3.tgz",
-            "integrity": "sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY=",
-            "requires": {
-                "asap": "^2.0.0",
-                "wrappy": "1"
-            }
-        },
         "diff": {
             "version": "3.5.0",
             "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz",
@@ -7415,22 +7447,9 @@
             "integrity": "sha512-EFRDrsMm/kyqbTQocNvRXMLjc7Es2Vk+IQFx/YW7hkUH1eBl4J1fqiP34l74Yt0pFLCNpc06fkbVk00008mzjg=="
         },
         "formidable": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/formidable/-/formidable-2.0.1.tgz",
-            "integrity": "sha512-rjTMNbp2BpfQShhFbR3Ruk3qk2y9jKpvMW78nJgx8QKtxjDVrwbZG+wvDOmVbifHyOUOQJXxqEy6r0faRrPzTQ==",
-            "requires": {
-                "dezalgo": "1.0.3",
-                "hexoid": "1.0.0",
-                "once": "1.4.0",
-                "qs": "6.9.3"
-            },
-            "dependencies": {
-                "qs": {
-                    "version": "6.9.3",
-                    "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.3.tgz",
-                    "integrity": "sha512-EbZYNarm6138UKKq46tdx08Yo/q9ZhFoAXAI1meAFd2GtbRDhbZY2WQSICskT0c5q99aFzLG1D4nvTk9tqfXIw=="
-                }
-            }
+            "version": "1.2.1",
+            "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.1.tgz",
+            "integrity": "sha512-Fs9VRguL0gqGHkXS5GQiMCr1VhZBxz0JnJs4JmMp/2jL18Fmbzvv7vOFRU+U8TBkHEE/CX1qDXzJplVULgsLeg=="
         },
         "forwarded": {
             "version": "0.2.0",
@@ -7482,28 +7501,6 @@
             "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
             "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="
         },
-        "fs-extra": {
-            "version": "0.26.7",
-            "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.26.7.tgz",
-            "integrity": "sha1-muH92UiXeY7at20JGM9C0MMYT6k=",
-            "requires": {
-                "graceful-fs": "^4.1.2",
-                "jsonfile": "^2.1.0",
-                "klaw": "^1.0.0",
-                "path-is-absolute": "^1.0.0",
-                "rimraf": "^2.2.8"
-            },
-            "dependencies": {
-                "rimraf": {
-                    "version": "2.7.1",
-                    "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
-                    "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
-                    "requires": {
-                        "glob": "^7.1.3"
-                    }
-                }
-            }
-        },
         "fs-minipass": {
             "version": "1.2.7",
             "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz",
@@ -7512,6 +7509,11 @@
                 "minipass": "^2.6.0"
             }
         },
+        "fs-monkey": {
+            "version": "1.0.3",
+            "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.3.tgz",
+            "integrity": "sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q=="
+        },
         "fs-write-stream-atomic": {
             "version": "1.0.10",
             "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz",
@@ -8134,11 +8136,6 @@
             "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
             "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw=="
         },
-        "hexoid": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz",
-            "integrity": "sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g=="
-        },
         "hoist-non-react-statics": {
             "version": "3.3.2",
             "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
@@ -8482,6 +8479,36 @@
                 "magicli": "0.0.8",
                 "mime-types": "^2.1.18",
                 "request": "^2.88.0"
+            },
+            "dependencies": {
+                "fs-extra": {
+                    "version": "0.26.7",
+                    "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.26.7.tgz",
+                    "integrity": "sha1-muH92UiXeY7at20JGM9C0MMYT6k=",
+                    "requires": {
+                        "graceful-fs": "^4.1.2",
+                        "jsonfile": "^2.1.0",
+                        "klaw": "^1.0.0",
+                        "path-is-absolute": "^1.0.0",
+                        "rimraf": "^2.2.8"
+                    }
+                },
+                "jsonfile": {
+                    "version": "2.4.0",
+                    "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz",
+                    "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=",
+                    "requires": {
+                        "graceful-fs": "^4.1.6"
+                    }
+                },
+                "rimraf": {
+                    "version": "2.7.1",
+                    "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
+                    "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
+                    "requires": {
+                        "glob": "^7.1.3"
+                    }
+                }
             }
         },
         "image-size": {
@@ -9539,14 +9566,6 @@
                 "diff-match-patch": "^1.0.0"
             }
         },
-        "jsonfile": {
-            "version": "2.4.0",
-            "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz",
-            "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=",
-            "requires": {
-                "graceful-fs": "^4.1.6"
-            }
-        },
         "jsonschema": {
             "version": "1.4.0",
             "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.4.0.tgz",
@@ -10254,6 +10273,14 @@
             "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
             "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
         },
+        "memfs": {
+            "version": "3.4.1",
+            "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.1.tgz",
+            "integrity": "sha512-1c9VPVvW5P7I85c35zAdEr1TD5+F11IToIHIlrVIcflfnzPkJa0ZoYEoEdYDP8KgPFoSZ/opDrUsAoZWym3mtw==",
+            "requires": {
+                "fs-monkey": "1.0.3"
+            }
+        },
         "memoize-one": {
             "version": "5.1.1",
             "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.1.1.tgz",
@@ -10652,6 +10679,13 @@
             "requires": {
                 "bson": "~1.0.4",
                 "require_optional": "~1.0.0"
+            },
+            "dependencies": {
+                "bson": {
+                    "version": "1.0.9",
+                    "resolved": "https://registry.npmjs.org/bson/-/bson-1.0.9.tgz",
+                    "integrity": "sha512-IQX9/h7WdMBIW/q/++tGd+emQr0XMdeZ6icnT/74Xk9fnabWn+gZgpE+9V+gujL3hhJOoNrnDVY7tWdzc7NUTg=="
+                }
             }
         },
         "mongoose": {
@@ -16108,14 +16142,9 @@
             }
         },
         "react-table": {
-            "version": "6.11.5",
-            "resolved": "https://registry.npmjs.org/react-table/-/react-table-6.11.5.tgz",
-            "integrity": "sha512-LM+AS9v//7Y7lAlgTWW/cW6Sn5VOb3EsSkKQfQTzOW8FngB1FUskLLNEVkAYsTX9LjOWR3QlGjykJqCE6eXT/g==",
-            "requires": {
-                "@types/react-table": "^6.8.5",
-                "classnames": "^2.2.5",
-                "react-is": "^16.8.1"
-            }
+            "version": "7.7.0",
+            "resolved": "https://registry.npmjs.org/react-table/-/react-table-7.7.0.tgz",
+            "integrity": "sha512-jBlj70iBwOTvvImsU9t01LjFjy4sXEtclBovl3mTiqjz23Reu0DKnRza4zlLtOPACx6j2/7MrQIthIK1Wi+LIA=="
         },
         "react-themeable": {
             "version": "1.1.0",
@@ -16577,6 +16606,11 @@
             "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
             "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I="
         },
+        "require-from-string": {
+            "version": "2.0.2",
+            "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
+            "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw=="
+        },
         "require-main-filename": {
             "version": "2.0.0",
             "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
@@ -18785,9 +18819,9 @@
             "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c="
         },
         "typescript": {
-            "version": "3.9.10",
-            "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.10.tgz",
-            "integrity": "sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==",
+            "version": "4.6.2",
+            "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.2.tgz",
+            "integrity": "sha512-HM/hFigTBHZhLXshn9sN37H085+hQGeJHJ/X7LpBWLID/fbc2acUMfU+lGD98X81sKP+pFa9f0DZmCwB9GnbAg==",
             "dev": true
         },
         "typescript-collections": {
@@ -19688,57 +19722,70 @@
             }
         },
         "webpack-dev-middleware": {
-            "version": "3.7.3",
-            "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.7.3.tgz",
-            "integrity": "sha512-djelc/zGiz9nZj/U7PTBi2ViorGJXEWo/3ltkPbDyxCXhhEXkW0ce99falaok4TPj+AsxLiXJR0EBOb0zh9fKQ==",
-            "dev": true,
+            "version": "5.3.1",
+            "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.1.tgz",
+            "integrity": "sha512-81EujCKkyles2wphtdrnPg/QqegC/AtqNH//mQkBYSMqwFVCQrxM6ktB2O/SPlZy7LqeEfTbV3cZARGQz6umhg==",
             "requires": {
-                "memory-fs": "^0.4.1",
-                "mime": "^2.4.4",
-                "mkdirp": "^0.5.1",
+                "colorette": "^2.0.10",
+                "memfs": "^3.4.1",
+                "mime-types": "^2.1.31",
                 "range-parser": "^1.2.1",
-                "webpack-log": "^2.0.0"
+                "schema-utils": "^4.0.0"
             },
             "dependencies": {
-                "memory-fs": {
-                    "version": "0.4.1",
-                    "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz",
-                    "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=",
-                    "dev": true,
+                "ajv": {
+                    "version": "8.10.0",
+                    "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.10.0.tgz",
+                    "integrity": "sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==",
                     "requires": {
-                        "errno": "^0.1.3",
-                        "readable-stream": "^2.0.1"
+                        "fast-deep-equal": "^3.1.1",
+                        "json-schema-traverse": "^1.0.0",
+                        "require-from-string": "^2.0.2",
+                        "uri-js": "^4.2.2"
                     }
                 },
-                "mime": {
-                    "version": "2.5.2",
-                    "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz",
-                    "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==",
-                    "dev": true
+                "ajv-keywords": {
+                    "version": "5.1.0",
+                    "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz",
+                    "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==",
+                    "requires": {
+                        "fast-deep-equal": "^3.1.3"
+                    },
+                    "dependencies": {
+                        "fast-deep-equal": {
+                            "version": "3.1.3",
+                            "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+                            "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
+                        }
+                    }
                 },
-                "readable-stream": {
-                    "version": "2.3.7",
-                    "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
-                    "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
-                    "dev": true,
+                "json-schema-traverse": {
+                    "version": "1.0.0",
+                    "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
+                    "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="
+                },
+                "mime-db": {
+                    "version": "1.51.0",
+                    "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz",
+                    "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g=="
+                },
+                "mime-types": {
+                    "version": "2.1.34",
+                    "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz",
+                    "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==",
                     "requires": {
-                        "core-util-is": "~1.0.0",
-                        "inherits": "~2.0.3",
-                        "isarray": "~1.0.0",
-                        "process-nextick-args": "~2.0.0",
-                        "safe-buffer": "~5.1.1",
-                        "string_decoder": "~1.1.1",
-                        "util-deprecate": "~1.0.1"
+                        "mime-db": "1.51.0"
                     }
                 },
-                "webpack-log": {
-                    "version": "2.0.0",
-                    "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz",
-                    "integrity": "sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==",
-                    "dev": true,
+                "schema-utils": {
+                    "version": "4.0.0",
+                    "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz",
+                    "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==",
                     "requires": {
-                        "ansi-colors": "^3.0.0",
-                        "uuid": "^3.3.2"
+                        "@types/json-schema": "^7.0.9",
+                        "ajv": "^8.8.0",
+                        "ajv-formats": "^2.1.1",
+                        "ajv-keywords": "^5.0.0"
                     }
                 }
             }
@@ -19799,12 +19846,43 @@
                         "ms": "2.1.2"
                     }
                 },
+                "memory-fs": {
+                    "version": "0.4.1",
+                    "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz",
+                    "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=",
+                    "dev": true,
+                    "requires": {
+                        "errno": "^0.1.3",
+                        "readable-stream": "^2.0.1"
+                    }
+                },
+                "mime": {
+                    "version": "2.6.0",
+                    "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz",
+                    "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==",
+                    "dev": true
+                },
                 "ms": {
                     "version": "2.1.2",
                     "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
                     "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
                     "dev": true
                 },
+                "readable-stream": {
+                    "version": "2.3.7",
+                    "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
+                    "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
+                    "dev": true,
+                    "requires": {
+                        "core-util-is": "~1.0.0",
+                        "inherits": "~2.0.3",
+                        "isarray": "~1.0.0",
+                        "process-nextick-args": "~2.0.0",
+                        "safe-buffer": "~5.1.1",
+                        "string_decoder": "~1.1.1",
+                        "util-deprecate": "~1.0.1"
+                    }
+                },
                 "semver": {
                     "version": "6.3.0",
                     "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
@@ -19829,6 +19907,19 @@
                         "has-flag": "^3.0.0"
                     }
                 },
+                "webpack-dev-middleware": {
+                    "version": "3.7.3",
+                    "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.7.3.tgz",
+                    "integrity": "sha512-djelc/zGiz9nZj/U7PTBi2ViorGJXEWo/3ltkPbDyxCXhhEXkW0ce99falaok4TPj+AsxLiXJR0EBOb0zh9fKQ==",
+                    "dev": true,
+                    "requires": {
+                        "memory-fs": "^0.4.1",
+                        "mime": "^2.4.4",
+                        "mkdirp": "^0.5.1",
+                        "range-parser": "^1.2.1",
+                        "webpack-log": "^2.0.0"
+                    }
+                },
                 "webpack-log": {
                     "version": "2.0.0",
                     "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz",
diff --git a/package.json b/package.json
index 5bbb5dfdb..898256c99 100644
--- a/package.json
+++ b/package.json
@@ -39,7 +39,6 @@
         "@types/express-session": "^1.17.4",
         "@types/express-validator": "^3.0.0",
         "@types/file-saver": "^2.0.5",
-        "@types/formidable": "^1.2.5",
         "@types/google-maps-react": "^2.0.5",
         "@types/jquery": "^3.5.14",
         "@types/libxmljs": "^0.18.7",
@@ -86,7 +85,6 @@
         "@types/uuid": "^3.4.10",
         "@types/valid-url": "^1.0.3",
         "@types/webpack": "^4.41.32",
-        "@types/webpack-dev-middleware": "^2.0.7",
         "@types/webpack-hot-middleware": "^2.25.6",
         "@types/xregexp": "^4.4.0",
         "@types/youtube": "0.0.39",
@@ -108,9 +106,8 @@
         "ts-node-dev": "^1.1.8",
         "tslint": "^5.20.1",
         "tslint-loader": "^3.6.0",
-        "typescript": "^3.9.10",
+        "typescript": "^4.6.2",
         "webpack": "^5.69.1",
-        "webpack-dev-middleware": "^3.7.3",
         "webpack-dev-server": "^3.11.3",
         "webpack-hot-middleware": "^2.25.1"
     },
@@ -132,12 +129,17 @@
         "@types/d3-color": "^2.0.3",
         "@types/d3-scale": "^3.3.2",
         "@types/d3-selection": "^2.0.1",
+        "@types/dom-speech-recognition": "0.0.1",
+        "@types/formidable": "1.0.31",
         "@types/google-maps": "^3.2.3",
         "@types/react-reconciler": "^0.26.4",
         "@types/reveal": "^3.3.33",
+        "@types/supercluster": "^7.1.0",
         "@types/three": "^0.126.2",
+        "@types/web": "0.0.53",
         "@types/webscopeio__react-textarea-autocomplete": "^4.7.2",
         "@webscopeio/react-textarea-autocomplete": "^4.9.1",
+        "D": "^1.0.0",
         "adm-zip": "^0.4.16",
         "archiver": "^3.1.1",
         "array-batcher": "^1.2.3",
@@ -151,6 +153,7 @@
         "body-parser": "^1.19.2",
         "bootstrap": "^4.6.1",
         "browser-assert": "^1.2.1",
+        "bson": "^4.6.1",
         "canvas": "^2.9.0",
         "child_process": "^1.0.2",
         "chrome": "^0.1.0",
@@ -177,7 +180,7 @@
         "flexlayout-react": "^0.3.11",
         "fluent-ffmpeg": "^2.1.2",
         "forever-agent": "^0.6.1",
-        "formidable": "^2.0.1",
+        "formidable": "1.2.1",
         "function-plot": "^1.22.8",
         "golden-layout": "^1.5.9",
         "google-auth-library": "^4.2.4",
@@ -258,7 +261,7 @@
         "react-resizable-rotatable-draggable": "^0.2.0",
         "react-reveal": "^1.2.2",
         "react-select": "^3.2.0",
-        "react-table": "^6.11.5",
+        "react-table": "^7.7.0",
         "readline": "^1.3.0",
         "request": "^2.88.2",
         "request-promise": "^4.2.6",
@@ -273,6 +276,7 @@
         "standard-http-error": "^2.0.1",
         "stream-browserify": "^3.0.0",
         "styled-components": "^4.4.1",
+        "supercluster": "^7.1.4",
         "textarea-caret": "^3.1.0",
         "three": "^0.127.0",
         "tough-cookie": "^4.0.0",
@@ -285,6 +289,7 @@
         "valid-url": "^1.0.9",
         "web-request": "^1.0.7",
         "webpack-cli": "^4.9.2",
+        "webpack-dev-middleware": "^5.3.1",
         "webrtc-adapter": "^7.7.1",
         "wikijs": "^6.3.3",
         "words-to-numbers": "^1.5.1",
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 279916bac..df4aa3acf 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -1450,7 +1450,7 @@ export namespace DocUtils {
         if (doc) {
             const proto = Doc.GetProto(doc);
             proto.text = result.rawText;
-            proto.fileUpload = basename(pathname).replace("upload_", "").replace(/\.[a-z0-9]*$/, "");
+            proto.fileUpload = pathname.replace(/.*\//, "").replace("upload_", "").replace(/\.[a-z0-9]*$/, "");
             if (Upload.isImageInformation(result)) {
                 const maxNativeDim = Math.min(Math.max(result.nativeHeight, result.nativeWidth), defaultNativeImageDim);
                 proto["data-nativeOrientation"] = result.exifData?.data?.image?.Orientation;
@@ -1485,7 +1485,8 @@ export namespace DocUtils {
     }
     export async function uploadFilesToDocs(files: File[], options: DocumentOptions) {
         const generatedDocuments: Doc[] = [];
-        for (const { source: { name, type }, result } of await Networking.UploadFilesToServer(files)) {
+        const upfiles = await Networking.UploadFilesToServer(files);
+        for (const { source: { name, type }, result } of upfiles) {
             name && type && processFileupload(generatedDocuments, name, type, result, options);
         }
         return generatedDocuments;
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 6e2a72f3a..600c143a7 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -535,11 +535,11 @@ export class CurrentUserUtils {
     // setup the "creator" buttons for the sidebar-- eg. the default set of draggable document creation tools
     static async setupCreatorButtons(doc: Doc) {
         let alreadyCreatedButtons: string[] = [];
-        const dragCreatorSet = await Cast(doc.myItemCreators, Doc, null);
+        const dragCreatorSet = Cast(doc.myItemCreators, Doc, null);
         if (dragCreatorSet) {
-            const dragCreators = await Cast(dragCreatorSet.data, listSpec(Doc));
+            const dragCreators = Cast(dragCreatorSet.data, listSpec(Doc));
             if (dragCreators) {
-                const dragDocs = await Promise.all(dragCreators);
+                const dragDocs = await Promise.all(Array.from(dragCreators));
                 alreadyCreatedButtons = dragDocs.map(d => StrCast(d.title));
             }
         }
diff --git a/src/client/util/DictationManager.ts b/src/client/util/DictationManager.ts
index a93b2f573..a086ac45e 100644
--- a/src/client/util/DictationManager.ts
+++ b/src/client/util/DictationManager.ts
@@ -1,4 +1,6 @@
 import * as interpreter from "words-to-numbers";
+// @ts-ignore  bcz: how are you supposed to include these definitions since dom-speech-recognition isn't a module?
+import type { } from "@types/dom-speech-recognition";
 import { Doc, Opt } from "../../fields/Doc";
 import { List } from "../../fields/List";
 import { RichTextField } from "../../fields/RichTextField";
@@ -13,6 +15,7 @@ import { DocumentView } from "../views/nodes/DocumentView";
 import { SelectionManager } from "./SelectionManager";
 import { UndoManager } from "./UndoManager";
 
+
 /**
  * This namespace provides a singleton instance of a manager that
  * handles the listening and text-conversion of user speech.
@@ -112,7 +115,7 @@ export namespace DictationManager {
                     }
                     options?.tryExecute && await DictationManager.Commands.execute(results);
                 }
-            } catch (e) {
+            } catch (e: any) {
                 console.log(e);
                 if (overlay) {
                     DictationOverlay.Instance.isListening = false;
@@ -188,7 +191,7 @@ export namespace DictationManager {
                         current && sessionResults.push(current);
                         sessionResults.length && resolve(sessionResults.join(inter || interSession));
                     } else {
-                        resolve(current);
+                        resolve(current || "");
                     }
                     current = undefined;
                     sessionResults = [];
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index 66b6a1e44..e1dc96155 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -198,7 +198,7 @@ export class DocumentManager {
                 originalTarget, willZoom, scale: presZoom, afterFocus: (didFocus: boolean) =>
                     new Promise<ViewAdjustment>(res => {
                         focusAndFinish(didFocus);
-                        res();
+                        res(ViewAdjustment.doNothing);
                     })
             });
         } else {
@@ -227,7 +227,7 @@ export class DocumentManager {
                                     willZoom, afterFocus: (didFocus: boolean) =>
                                         new Promise<ViewAdjustment>(res => {
                                             !noSelect && focusAndFinish(didFocus);
-                                            res();
+                                            res(ViewAdjustment.doNothing);
                                         })
                                 }); // focus on the target in the context
                             } else if (delay > 1500) {
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index ae3fa3170..c9c499fff 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -499,7 +499,7 @@ export namespace DragManager {
                                 screenX: e.screenX,
                                 screenY: e.screenY,
                                 detail: e.detail,
-                                view: e.view ? e.view : new Window,
+                                view: e.view ? e.view : new Window as any,
                                 nativeEvent: new DragEvent("dashDragAutoScroll"),
                                 currentTarget: target,
                                 target: target,
diff --git a/src/client/util/Import & Export/DirectoryImportBox.tsx b/src/client/util/Import & Export/DirectoryImportBox.tsx
index cf72cd0df..9eee75253 100644
--- a/src/client/util/Import & Export/DirectoryImportBox.tsx	
+++ b/src/client/util/Import & Export/DirectoryImportBox.tsx	
@@ -1,9 +1,7 @@
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { BatchedArray } from "array-batcher";
-import "fs";
 import { action, computed, IReactionDisposer, observable, reaction, runInAction } from "mobx";
 import { observer } from "mobx-react";
-import * as path from 'path';
 import Measure, { ContentRect } from "react-measure";
 import { Doc, DocListCast, DocListCastAsync, Opt } from "../../../fields/Doc";
 import { Id } from "../../../fields/FieldSymbols";
@@ -120,7 +118,7 @@ export class DirectoryImportBox extends React.Component<FieldViewProps> {
             }
             const { accessPaths, exifData } = result;
             const path = Utils.prepend(accessPaths.agnostic.client);
-            const document = type && await DocUtils.DocumentFromType(type, path, { _width: 300, title: name });
+            const document = type && await DocUtils.DocumentFromType(type, path, { _width: 300 });
             const { data, error } = exifData;
             if (document) {
                 Doc.GetProto(document).exif = error || Doc.Get.FromJson({ data });
diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts
index 62b13e2c6..df2c02a8d 100644
--- a/src/client/util/LinkManager.ts
+++ b/src/client/util/LinkManager.ts
@@ -194,7 +194,7 @@ export class LinkManager {
                             afterFocus: (didFocus: boolean) => {
                                 finished?.();
                                 res(ViewAdjustment.resetView);
-                                return new Promise<ViewAdjustment>(res2 => res2());
+                                return new Promise<ViewAdjustment>(res2 => res2(ViewAdjustment.doNothing));
                             }
                         });
                     } else {
diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaCells.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaCells.tsx
index a439a7998..6a9b27d02 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaCells.tsx
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaCells.tsx
@@ -3,9 +3,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
 import { action, computed, observable } from "mobx";
 import { observer } from "mobx-react";
 import DatePicker from "react-datepicker";
-import "react-datepicker/dist/react-datepicker.css";
 import { CellInfo } from "react-table";
-import "react-table/react-table.css";
 import { DateField } from "../../../../fields/DateField";
 import { Doc, DocListCast, Field, Opt } from "../../../../fields/Doc";
 import { Id } from "../../../../fields/FieldSymbols";
@@ -31,7 +29,6 @@ import { DocumentIconContainer } from "../../nodes/DocumentIcon";
 import { OverlayView } from "../../OverlayView";
 import "./CollectionSchemaView.scss";
 import { CollectionView } from "../CollectionView";
-const path = require('path');
 
 // intialize cell properties
 export interface CellProps {
@@ -495,8 +492,8 @@ export class CollectionSchemaImageCell extends CollectionSchemaCell {
         if (url.href.indexOf(window.location.origin) === -1) return Utils.CorsProxy(url.href); // otherwise, put it through the cors proxy erver
         if (!/\.(png|jpg|jpeg|gif|webp)$/.test(url.href.toLowerCase())) return url.href;//Why is this here — good question
 
-        const ext = path.extname(url.href); // the extension of the file
-        return url.href.replace(ext, "_o" + path.extname(url.href));
+        const ext = "." + url.href.replace(/.*\./, "");//  path.extname(url.href); // the extension of the file
+        return url.href.replace(ext, "_o" + ext);
     }
 
     render() {
diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
index b89246489..83d339f0a 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
@@ -4,7 +4,6 @@ import { action, computed, observable, untracked, trace } from "mobx";
 import { observer } from "mobx-react";
 import Measure from "react-measure";
 import { Resize } from "react-table";
-import "react-table/react-table.css";
 import { Doc, Opt } from "../../../../fields/Doc";
 import { List } from "../../../../fields/List";
 import { listSpec } from "../../../../fields/Schema";
@@ -147,43 +146,43 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
 
         const anyType = <div className={"columnMenu-option" + (type === ColumnType.Any ? " active" : "")} onClick={() => this.setColumnType(col, ColumnType.Any)}>
             <FontAwesomeIcon icon={"align-justify"} size="sm" />
-                Any
-            </div>;
+            Any
+        </div>;
 
         const numType = <div className={"columnMenu-option" + (type === ColumnType.Number ? " active" : "")} onClick={() => this.setColumnType(col, ColumnType.Number)}>
             <FontAwesomeIcon icon={"hashtag"} size="sm" />
-                Number
-            </div>;
+            Number
+        </div>;
 
         const textType = <div className={"columnMenu-option" + (type === ColumnType.String ? " active" : "")} onClick={() => this.setColumnType(col, ColumnType.String)}>
             <FontAwesomeIcon icon={"font"} size="sm" />
             Text
-            </div>;
+        </div>;
 
         const boolType = <div className={"columnMenu-option" + (type === ColumnType.Boolean ? " active" : "")} onClick={() => this.setColumnType(col, ColumnType.Boolean)}>
             <FontAwesomeIcon icon={"check-square"} size="sm" />
             Checkbox
-            </div>;
+        </div>;
 
         const listType = <div className={"columnMenu-option" + (type === ColumnType.List ? " active" : "")} onClick={() => this.setColumnType(col, ColumnType.List)}>
             <FontAwesomeIcon icon={"list-ul"} size="sm" />
             List
-            </div>;
+        </div>;
 
         const docType = <div className={"columnMenu-option" + (type === ColumnType.Doc ? " active" : "")} onClick={() => this.setColumnType(col, ColumnType.Doc)}>
             <FontAwesomeIcon icon={"file"} size="sm" />
             Document
-            </div>;
+        </div>;
 
         const imageType = <div className={"columnMenu-option" + (type === ColumnType.Image ? " active" : "")} onClick={() => this.setColumnType(col, ColumnType.Image)}>
             <FontAwesomeIcon icon={"image"} size="sm" />
             Image
-            </div>;
+        </div>;
 
         const dateType = <div className={"columnMenu-option" + (type === ColumnType.Date ? " active" : "")} onClick={() => this.setColumnType(col, ColumnType.Date)}>
             <FontAwesomeIcon icon={"calendar"} size="sm" />
-                Date
-                </div>;
+            Date
+        </div>;
 
 
         const allColumnTypes = <div className="columnMenu-types">
@@ -557,7 +556,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
             style={{
                 overflow: this.props.scrollOverflow === true ? "scroll" : undefined, backgroundColor: "white",
                 pointerEvents: this.props.Document._searchDoc !== undefined && !this.props.isContentActive() && !SnappingManager.GetIsDragging() ? "none" : undefined,
-                width: name === "collectionSchemaView-searchContainer" ? "auto" : this.props.PanelWidth() || "100%", height: this.props.PanelHeight() || "100%", position: "relative",
+                width: this.props.PanelWidth() || "100%", height: this.props.PanelHeight() || "100%", position: "relative",
             }}  >
             <div className="collectionSchemaView-tableContainer"
                 style={{ width: `calc(100% - ${this.previewWidth()}px)` }}
diff --git a/src/client/views/collections/collectionSchema/SchemaTable.tsx b/src/client/views/collections/collectionSchema/SchemaTable.tsx
index 2219345f6..605481ddf 100644
--- a/src/client/views/collections/collectionSchema/SchemaTable.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaTable.tsx
@@ -4,7 +4,6 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { action, computed, observable, trace } from "mobx";
 import { observer } from "mobx-react";
 import ReactTable, { CellInfo, Column, ComponentPropsGetterR, Resize, SortingRule } from "react-table";
-import "react-table/react-table.css";
 import { DateField } from "../../../../fields/DateField";
 import { AclPrivate, AclReadonly, DataSym, Doc, DocListCast, Field, Opt } from "../../../../fields/Doc";
 import { Id } from "../../../../fields/FieldSymbols";
diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx
index c79828470..02451bdac 100644
--- a/src/client/views/nodes/AudioBox.tsx
+++ b/src/client/views/nodes/AudioBox.tsx
@@ -310,7 +310,9 @@ export class AudioBox extends ViewBoxAnnotatableComponent<
         );
         DocUtils.ActiveRecordings.push(this);
         this._recorder.ondataavailable = async (e: any) => {
+            console.log("Data available", e);
             const [{ result }] = await Networking.UploadFilesToServer(e.data);
+            console.log("Data result", result);
             if (!(result instanceof Error)) {
                 this.props.Document[this.props.fieldKey] = new AudioField(result.accessPaths.agnostic.client);
             }
@@ -336,8 +338,8 @@ export class AudioBox extends ViewBoxAnnotatableComponent<
                 (this.layoutDoc.dontAutoPlayFollowedLinks ? "" : "Don't") +
                 " play when link is selected",
             event: () =>
-                (this.layoutDoc.dontAutoPlayFollowedLinks =
-                    !this.layoutDoc.dontAutoPlayFollowedLinks),
+            (this.layoutDoc.dontAutoPlayFollowedLinks =
+                !this.layoutDoc.dontAutoPlayFollowedLinks),
             icon: "expand-arrows-alt",
         });
         funcs.push({
@@ -637,77 +639,77 @@ export class AudioBox extends ViewBoxAnnotatableComponent<
                                 </div>
                             </div>
                         ) : (
-                                <div
-                                    className={`audiobox-record${interactive}`}
-                                    style={{ backgroundColor: Colors.DARK_GRAY }}
-                                >
-                                    <FontAwesomeIcon icon="microphone" />
+                            <div
+                                className={`audiobox-record${interactive}`}
+                                style={{ backgroundColor: Colors.DARK_GRAY }}
+                            >
+                                <FontAwesomeIcon icon="microphone" />
                                 RECORD
-                                </div>
-                            )}
+                            </div>
+                        )}
                     </div>
                 ) : (
+                    <div
+                        className="audiobox-controls"
+                        style={{
+                            pointerEvents:
+                                this._isAnyChildContentActive || this.props.isContentActive()
+                                    ? "all"
+                                    : "none",
+                        }}
+                    >
+                        <div className="audiobox-dictation" />
                         <div
-                            className="audiobox-controls"
-                            style={{
-                                pointerEvents:
-                                    this._isAnyChildContentActive || this.props.isContentActive()
-                                        ? "all"
-                                        : "none",
-                            }}
+                            className="audiobox-player"
+                            style={{ height: `${AudioBox.heightPercent}%` }}
                         >
-                            <div className="audiobox-dictation" />
                             <div
-                                className="audiobox-player"
-                                style={{ height: `${AudioBox.heightPercent}%` }}
+                                className="audiobox-buttons"
+                                title={this.mediaState === "paused" ? "play" : "pause"}
+                                onClick={this.mediaState === "paused" ? this.Play : this.Pause}
                             >
-                                <div
-                                    className="audiobox-buttons"
-                                    title={this.mediaState === "paused" ? "play" : "pause"}
-                                    onClick={this.mediaState === "paused" ? this.Play : this.Pause}
-                                >
-                                    {" "}
-                                    <FontAwesomeIcon
-                                        icon={this.mediaState === "paused" ? "play" : "pause"}
-                                        size={"1x"}
-                                    />
-                                </div>
-                                <div
-                                    className="audiobox-buttons"
-                                    title={this._trimming ? "finish" : "trim"}
-                                    onClick={this._trimming ? this.finishTrim : this.startTrim}
-                                >
-                                    <FontAwesomeIcon
-                                        icon={this._trimming ? "check" : "cut"}
-                                        size={"1x"}
-                                    />
-                                </div>
-                                <div
-                                    className="audiobox-timeline"
-                                    style={{
-                                        top: 0,
-                                        height: `100%`,
-                                        left: AudioBox.playheadWidth,
-                                        width: `calc(100% - ${AudioBox.playheadWidth}px)`,
-                                        background: "white",
-                                    }}
-                                >
-                                    {this.renderTimeline}
-                                </div>
-                                {this.audio}
-                                <div className="audioBox-current-time">
-                                    {this._trimming ?
-                                        formatTime(Math.round(NumCast(this.layoutDoc._currentTimecode)))
-                                        : formatTime(Math.round(NumCast(this.layoutDoc._currentTimecode) - NumCast(this._trimStart)))}
-                                </div>
-                                <div className="audioBox-total-time">
-                                    {this._trimming || !this._trimEnd ?
-                                        formatTime(Math.round(NumCast(this.duration)))
-                                        : formatTime(Math.round(NumCast(this.trimDuration)))}
-                                </div>
+                                {" "}
+                                <FontAwesomeIcon
+                                    icon={this.mediaState === "paused" ? "play" : "pause"}
+                                    size={"1x"}
+                                />
+                            </div>
+                            <div
+                                className="audiobox-buttons"
+                                title={this._trimming ? "finish" : "trim"}
+                                onClick={this._trimming ? this.finishTrim : this.startTrim}
+                            >
+                                <FontAwesomeIcon
+                                    icon={this._trimming ? "check" : "cut"}
+                                    size={"1x"}
+                                />
+                            </div>
+                            <div
+                                className="audiobox-timeline"
+                                style={{
+                                    top: 0,
+                                    height: `100%`,
+                                    left: AudioBox.playheadWidth,
+                                    width: `calc(100% - ${AudioBox.playheadWidth}px)`,
+                                    background: "white",
+                                }}
+                            >
+                                {this.renderTimeline}
+                            </div>
+                            {this.audio}
+                            <div className="audioBox-current-time">
+                                {this._trimming ?
+                                    formatTime(Math.round(NumCast(this.layoutDoc._currentTimecode)))
+                                    : formatTime(Math.round(NumCast(this.layoutDoc._currentTimecode) - NumCast(this._trimStart)))}
+                            </div>
+                            <div className="audioBox-total-time">
+                                {this._trimming || !this._trimEnd ?
+                                    formatTime(Math.round(NumCast(this.duration)))
+                                    : formatTime(Math.round(NumCast(this.trimDuration)))}
                             </div>
                         </div>
-                    )}
+                    </div>
+                )}
             </div>
         );
     }
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 67486dcf4..e2380bfba 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -1025,19 +1025,18 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
                     display={"block"}
                     fontSize={10}
                     GetValue={() => showTitle.split(";").length === 1 ? showTitle + "=" + Field.toString(targetDoc[showTitle.split(";")[0]] as any as Field) : "#" + showTitle}
-                    SetValue={undoBatch(input => {
+                    SetValue={undoBatch((input: string) => {
                         if (input?.startsWith("#")) {
                             if (this.props.showTitle) {
                                 this.rootDoc._showTitle = input?.substring(1) ? input.substring(1) : undefined;
                             } else {
                                 Doc.UserDoc().showTitle = input?.substring(1) ? input.substring(1) : "creationDate";
                             }
-                            return true;
                         } else {
-                            var value = input.replace(new RegExp(showTitle + "="), "");
+                            var value = input.replace(new RegExp(showTitle + "="), "") as string | number;
                             if (showTitle !== "title" && Number(value).toString() === value) value = Number(value);
                             if (showTitle.includes("Date") || showTitle === "author") return true;
-                            return Doc.SetInPlace(targetDoc, showTitle, value, true) ? true : true;
+                            Doc.SetInPlace(targetDoc, showTitle, value, true);
                         }
                         return true;
                     })}
@@ -1148,7 +1147,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
     get LayoutFieldKey() { return this.docView?.LayoutFieldKey || "layout"; }
     get fitWidth() { return this.props.fitWidth?.(this.rootDoc) || this.layoutDoc.fitWidth; }
 
-    @computed get docViewPath() { return this.props.docViewPath ? [...this.props.docViewPath(), this] : [this]; }
+    @computed get docViewPath(): DocumentView[] { return this.props.docViewPath ? [...this.props.docViewPath(), this] : [this]; }
     @computed get layoutDoc() { return Doc.Layout(this.Document, this.props.LayoutTemplate?.()); }
     @computed get nativeWidth() {
         return this.docView?._componentView?.reverseNativeScaling?.() ? 0 :
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index 5d122ed54..112325cc3 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -188,7 +188,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
         if (url.href.indexOf(window.location.origin) === -1) return Utils.CorsProxy(url.href);
         if (!/\.(png|jpg|jpeg|gif|webp)$/.test(lower)) return url.href;  //Why is this here
 
-        const ext = url.href.replace(/.*\./, "");//path.extname(url.href);
+        const ext = "." + url.href.replace(/.*\./, "");//path.extname(url.href);
         return url.href.replace(ext, this._curSuffix + ext);
     }
 
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index d4ff40e8f..c2f4ea8da 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -65,6 +65,7 @@ import React = require("react");
 import { SidebarAnnos } from '../../SidebarAnnos';
 import { Colors } from '../../global/globalEnums';
 import { IconProp } from '@fortawesome/fontawesome-svg-core';
+import { UnknownErrorException } from 'pdfjs-dist/types/src/shared/util';
 const translateGoogleApi = require("translate-google-api");
 
 export interface FormattedTextBoxProps {
@@ -1423,7 +1424,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
                         this.dataDoc[this.fieldKey + "-translation"] = result1 + "\r\n\r\n" + result[0];
                     }), 1000);
                 });
-            } catch (e) { console.log(e.message); }
+            } catch (e: any) { console.log(e.message); }
             this._lastText = curText;
         }
     }
diff --git a/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts b/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts
index 76a5675de..c76eda859 100644
--- a/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts
+++ b/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts
@@ -106,7 +106,7 @@ export function buildKeymap<S extends Schema<any>>(schema: S, props: any, mapKey
     bind("Mod-U", toggleEditableMark(schema.marks.underline));
 
     //Commands for lists
-    bind("Ctrl-i", (state: EditorState<S>, dispatch: (tx: Transaction<S>) => void) => canEdit(state) && wrapInList(schema.nodes.ordered_list)(state, dispatch as any));
+    bind("Ctrl-i", (state: EditorState<S>, dispatch: (tx: Transaction<S>) => void) => canEdit(state) && wrapInList(schema.nodes.ordered_list)(state as any, dispatch as any));
 
     bind("Tab", (state: EditorState<S>, dispatch: (tx: Transaction<S>) => void) => {
         /// bcz; Argh!!  replace layotuTEmpalteString with a onTab prop conditionally handles Tab);
@@ -125,7 +125,7 @@ export function buildKeymap<S extends Schema<any>>(schema: S, props: any, mapKey
             dispatch(tx3);
         })) { // couldn't sink into an existing list, so wrap in a new one
             const newstate = state.applyTransaction(state.tr.setSelection(TextSelection.create(state.doc, range!.start, range!.end)));
-            if (!wrapInList(schema.nodes.ordered_list)(newstate.state, (tx2: Transaction) => {
+            if (!wrapInList(schema.nodes.ordered_list)(newstate.state as any, (tx2: Transaction) => {
                 const tx3 = updateBullets(tx2, schema);
                 // when promoting to a list, assume list will format things so don't copy the stored marks.
                 marks && tx3.ensureMarks([...marks]);
@@ -160,14 +160,14 @@ export function buildKeymap<S extends Schema<any>>(schema: S, props: any, mapKey
     });
 
     //Commands to modify BlockType
-    bind("Ctrl->", (state: EditorState<S>, dispatch: (tx: Transaction<S>) => void) => canEdit((state) && wrapIn(schema.nodes.blockquote)(state, dispatch as any)));
-    bind("Alt-\\", (state: EditorState<S>, dispatch: (tx: Transaction<S>) => void) => canEdit(state) && setBlockType(schema.nodes.paragraph)(state, dispatch as any));
-    bind("Shift-Ctrl-\\", (state: EditorState<S>, dispatch: (tx: Transaction<S>) => void) => canEdit(state) && setBlockType(schema.nodes.code_block)(state, dispatch as any));
+    bind("Ctrl->", (state: EditorState<S>, dispatch: (tx: Transaction<S>) => void) => canEdit((state) && wrapIn(schema.nodes.blockquote)(state as any, dispatch as any)));
+    bind("Alt-\\", (state: EditorState<S>, dispatch: (tx: Transaction<S>) => void) => canEdit(state) && setBlockType(schema.nodes.paragraph)(state as any, dispatch as any));
+    bind("Shift-Ctrl-\\", (state: EditorState<S>, dispatch: (tx: Transaction<S>) => void) => canEdit(state) && setBlockType(schema.nodes.code_block)(state as any, dispatch as any));
 
     bind("Ctrl-m", (state: EditorState<S>, dispatch: (tx: Transaction<S>) => void) => canEdit(state) && dispatch(state.tr.replaceSelectionWith(schema.nodes.equation.create({ fieldKey: "math" + Utils.GenerateGuid() }))));
 
     for (let i = 1; i <= 6; i++) {
-        bind("Shift-Ctrl-" + i, (state: EditorState<S>, dispatch: (tx: Transaction<S>) => void) => canEdit(state) && setBlockType(schema.nodes.heading, { level: i })(state, dispatch as any));
+        bind("Shift-Ctrl-" + i, (state: EditorState<S>, dispatch: (tx: Transaction<S>) => void) => canEdit(state) && setBlockType(schema.nodes.heading, { level: i })(state as any, dispatch as any));
     }
 
     //Command to create a horizontal break line
@@ -197,13 +197,13 @@ export function buildKeymap<S extends Schema<any>>(schema: S, props: any, mapKey
     bind("Backspace", (state: EditorState<S>, dispatch: (tx: Transaction<Schema<any, any>>) => void) => {
         if (!canEdit(state)) return true;
 
-        if (!deleteSelection(state, (tx: Transaction<Schema<any, any>>) => {
+        if (!deleteSelection(state, (tx: Transaction<S>) => {
             dispatch(updateBullets(tx, schema));
         })) {
-            if (!joinBackward(state, (tx: Transaction<Schema<any, any>>) => {
+            if (!joinBackward(state, (tx: Transaction<S>) => {
                 dispatch(updateBullets(tx, schema));
             })) {
-                if (!selectNodeBackward(state, (tx: Transaction<Schema<any, any>>) => {
+                if (!selectNodeBackward(state, (tx: Transaction<S>) => {
                     dispatch(updateBullets(tx, schema));
                 })) {
                     return false;
@@ -225,14 +225,14 @@ export function buildKeymap<S extends Schema<any>>(schema: S, props: any, mapKey
         const depth = trange ? liftTarget(trange) : undefined;
         const split = path.length > 5 && !path[path.length - 3].textContent && path[path.length - 6].type !== schema.nodes.list_item;
         if (split && trange && depth !== undefined && depth !== null) {
-            dispatch(state.tr.lift(trange, depth));
+            dispatch(state.tr.lift(trange, depth) as any);
             return true;
         }
 
         const marks = state.storedMarks || (state.selection.$to.parentOffset && state.selection.$from.marks());
         const cr = state.selection.$from.node().textContent.endsWith("\n");
-        if (cr || !newlineInCode(state, dispatch)) {
-            if (!splitListItem(schema.nodes.list_item)(state, (tx2: Transaction) => {
+        if (cr || !newlineInCode(state, dispatch as any)) {
+            if (!splitListItem(schema.nodes.list_item)(state as any, (tx2: Transaction) => {
                 const tx3 = updateBullets(tx2, schema);
                 marks && tx3.ensureMarks([...marks]);
                 marks && tx3.setStoredMarks([...marks]);
diff --git a/src/client/views/nodes/formattedText/RichTextRules.ts b/src/client/views/nodes/formattedText/RichTextRules.ts
index 711136469..bafae84dc 100644
--- a/src/client/views/nodes/formattedText/RichTextRules.ts
+++ b/src/client/views/nodes/formattedText/RichTextRules.ts
@@ -34,13 +34,9 @@ export class RichTextRules {
             wrappingInputRule(
                 /^1\.\s$/,
                 schema.nodes.ordered_list,
-                () => {
-                    return ({ mapStyle: "decimal", bulletStyle: 1 });
-                },
-                (match: any, node: any) => {
-                    return node.childCount + node.attrs.order === +match[1];
-                },
-                (type: any) => ({ type: type, attrs: { mapStyle: "decimal", bulletStyle: 1 } })
+                () => ({ mapStyle: "decimal", bulletStyle: 1 }),
+                (match: any, node: any) => node.childCount + node.attrs.order === +match[1],
+                ((type: any) => ({ type: type, attrs: { mapStyle: "decimal", bulletStyle: 1 } })) as any
             ),
 
             // A. create alphabetical ordered list
@@ -55,20 +51,16 @@ export class RichTextRules {
                 (match: any, node: any) => {
                     return node.childCount + node.attrs.order === +match[1];
                 },
-                (type: any) => ({ type: type, attrs: { mapStyle: "multi", bulletStyle: 1 } })
+                ((type: any) => ({ type: type, attrs: { mapStyle: "multi", bulletStyle: 1 } })) as any
             ),
 
             // * + - create bullet list
             wrappingInputRule(/^\s*([-+*])\s$/, schema.nodes.ordered_list,
                 // match => {
-                () => {
-                    return ({ mapStyle: "bullet" });
-                    // return ({ order: +match[1] })
-                },
-                (match: any, node: any) => {
-                    return node.childCount + node.attrs.order === +match[1];
-                },
-                (type: any) => ({ type: type, attrs: { mapStyle: "bullet" } })),
+                () => ({ mapStyle: "bullet" }),  //  ({ order: +match[1] })
+                (match: any, node: any) => node.childCount + node.attrs.order === +match[1],
+                ((type: any) => ({ type: type, attrs: { mapStyle: "bullet" } })) as any
+            ),
 
             // ``` create code block
             textblockTypeInputRule(/^```$/, schema.nodes.code_block),
@@ -221,7 +213,7 @@ export class RichTextRules {
                     tr.deleteRange(start, end).replaceSelectionWith(newNode); // replace insertion with a footnote.
                     return tr.setSelection(new NodeSelection( // select the footnote node to open its display
                         tr.doc.resolve(  // get the location of the footnote node by subtracting the nodesize of the footnote from the current insertion point anchor (which will be immediately after the footnote node)
-                            tr.selection.anchor - tr.selection.$anchor.nodeBefore!.nodeSize)));
+                            tr.selection.anchor - (tr.selection.$anchor.nodeBefore?.nodeSize || 0))));
                 }),
 
             // activate a style by name using prefix '%<color name>'
diff --git a/src/fields/CursorField.ts b/src/fields/CursorField.ts
index 28467377b..a8a2859d2 100644
--- a/src/fields/CursorField.ts
+++ b/src/fields/CursorField.ts
@@ -50,7 +50,7 @@ export default class CursorField extends ObjectField {
     setPosition(position: CursorPosition) {
         this.data.position = position;
         this.data.metadata.timestamp = Date.now();
-        this[OnUpdate]();
+        this[OnUpdate]?.();
     }
 
     [Copy]() {
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts
index 0b9a8b3fe..63c67aeb0 100644
--- a/src/fields/Doc.ts
+++ b/src/fields/Doc.ts
@@ -216,7 +216,7 @@ export class Doc extends RefField {
         return self.resolvedDataDoc && !self.isTemplateForField ? self :
             Doc.GetProto(Cast(Doc.Layout(self).resolvedDataDoc, Doc, null) || self);
     }
-    @computed get __LAYOUT__() {
+    @computed get __LAYOUT__(): Doc | undefined {
         const templateLayoutDoc = Cast(Doc.LayoutField(this[SelfProxy]), Doc, null);
         if (templateLayoutDoc) {
             let renderFieldKey: any;
diff --git a/src/fields/ObjectField.ts b/src/fields/ObjectField.ts
index 92b2cfa60..9211afe86 100644
--- a/src/fields/ObjectField.ts
+++ b/src/fields/ObjectField.ts
@@ -3,7 +3,7 @@ import { OnUpdate, Parent, Copy, ToScriptString, ToString } from "./FieldSymbols
 import { Scripting } from "../client/util/Scripting";
 
 export abstract class ObjectField {
-    public [OnUpdate](diff?: any) { }
+    public [OnUpdate]?: (diff?: any) => void;
     public [Parent]?: RefField | ObjectField;
     abstract [Copy](): ObjectField;
 
diff --git a/src/fields/SchemaHeaderField.ts b/src/fields/SchemaHeaderField.ts
index a53fa542e..3dc70ac19 100644
--- a/src/fields/SchemaHeaderField.ts
+++ b/src/fields/SchemaHeaderField.ts
@@ -82,32 +82,32 @@ export class SchemaHeaderField extends ObjectField {
 
     setHeading(heading: string) {
         this.heading = heading;
-        this[OnUpdate]();
+        this[OnUpdate]?.();
     }
 
     setColor(color: string) {
         this.color = color;
-        this[OnUpdate]();
+        this[OnUpdate]?.();
     }
 
     setType(type: ColumnType) {
         this.type = type;
-        this[OnUpdate]();
+        this[OnUpdate]?.();
     }
 
     setWidth(width: number) {
         this.width = width;
-        this[OnUpdate]();
+        this[OnUpdate]?.();
     }
 
     setDesc(desc: boolean | undefined) {
         this.desc = desc;
-        this[OnUpdate]();
+        this[OnUpdate]?.();
     }
 
     setCollapsed(collapsed: boolean | undefined) {
         this.collapsed = collapsed;
-        this[OnUpdate]();
+        this[OnUpdate]?.();
     }
 
     [Copy]() {
diff --git a/src/fields/Types.ts b/src/fields/Types.ts
index 220a30fe4..c90f3b6b3 100644
--- a/src/fields/Types.ts
+++ b/src/fields/Types.ts
@@ -111,5 +111,6 @@ export interface PromiseLike<T> {
     then(callback: (field: Opt<T>) => void): void;
 }
 export function PromiseValue<T extends Field>(field: FieldResult<T>): PromiseLike<Opt<T>> {
-    return field instanceof Promise ? field : { then(cb: ((field: Opt<T>) => void)) { return cb(field); } };
+    if (field instanceof Promise) return field as Promise<Opt<T>>;
+    return { then(cb: ((field: Opt<T>) => void)) { return cb(field); } };
 }
\ No newline at end of file
diff --git a/src/scraping/buxton/final/BuxtonImporter.ts b/src/scraping/buxton/final/BuxtonImporter.ts
index 684c00c0d..ee8dd5b5b 100644
--- a/src/scraping/buxton/final/BuxtonImporter.ts
+++ b/src/scraping/buxton/final/BuxtonImporter.ts
@@ -282,7 +282,7 @@ export default async function executeImport(emitter: ResultCallback, terminator:
         });
         await transferAssets();
         return parseFiles(wordDocuments, emitter, terminator);
-    } catch (e) {
+    } catch (e: any) {
         const message = [
             "Unable to find a source directory.",
             "Please ensure that the following directory exists:",
diff --git a/src/server/ActionUtilities.ts b/src/server/ActionUtilities.ts
index d237869ed..bc8fd6f87 100644
--- a/src/server/ActionUtilities.ts
+++ b/src/server/ActionUtilities.ts
@@ -62,7 +62,7 @@ export async function log_execution<T>({ startMessage, endMessage, action, color
     log_helper(`${startMessage}...`, resolvedColor);
     try {
         result = await action();
-    } catch (e) {
+    } catch (e: any) {
         error = e;
     } finally {
         log_helper(typeof endMessage === "string" ? endMessage : endMessage({ result, error }), resolvedColor);
diff --git a/src/server/ApiManagers/UploadManager.ts b/src/server/ApiManagers/UploadManager.ts
index 8da08fe33..bfa07d47a 100644
--- a/src/server/ApiManagers/UploadManager.ts
+++ b/src/server/ApiManagers/UploadManager.ts
@@ -48,10 +48,9 @@ export default class UploadManager extends ApiManager {
             method: Method.POST,
             subscription: "/uploadFormData",
             secureHandler: async ({ req, res }) => {
-                const form = new formidable.IncomingForm({
-                    keepExtensions: true,
-                    uploadDir: pathToDirectory(Directory.parsed_files)
-                });
+                const form = new formidable.IncomingForm();
+                form.keepExtensions = true;
+                form.uploadDir = pathToDirectory(Directory.parsed_files);
                 return new Promise<void>(resolve => {
                     form.parse(req, async (_err, _fields, files) => {
                         const results: Upload.FileResponse[] = [];
@@ -144,7 +143,8 @@ export default class UploadManager extends ApiManager {
             subscription: "/uploadDoc",
             secureHandler: ({ req, res }) => {
 
-                const form = new formidable.IncomingForm({ keepExtensions: true });
+                const form = new formidable.IncomingForm();
+                form.keepExtensions = true;
                 // let path = req.body.path;
                 const ids: { [id: string]: string } = {};
                 let remap = true;
@@ -222,7 +222,7 @@ export default class UploadManager extends ApiManager {
                                     id = getId(data.id);
                                     const docs = Object.keys(datadocs).map(key => datadocs[key]);
                                     docs.forEach(mapFn);
-                                    await Promise.all(docs.map((doc: any) => new Promise(res => {
+                                    await Promise.all(docs.map((doc: any) => new Promise<void>(res => {
                                         Database.Instance.replace(doc.id, doc, (err, r) => {
                                             err && console.log(err);
                                             res();
diff --git a/src/server/ApiManagers/UserManager.ts b/src/server/ApiManagers/UserManager.ts
index fe80c6a7c..7be8a1e9f 100644
--- a/src/server/ApiManagers/UserManager.ts
+++ b/src/server/ApiManagers/UserManager.ts
@@ -22,7 +22,7 @@ export default class UserManager extends ApiManager {
             secureHandler: async ({ res }) => {
                 const cursor = await Database.Instance.query({}, { email: 1, linkDatabaseId: 1, sharingDocumentId: 1 }, "users");
                 const results = await cursor.toArray();
-                res.send(results.map(user => ({ email: user.email, linkDatabaseId: user.linkDatabaseId, sharingDocumentId: user.sharingDocumentId })));
+                res.send(results.map((user: any) => ({ email: user.email, linkDatabaseId: user.linkDatabaseId, sharingDocumentId: user.sharingDocumentId })));
             }
         });
 
diff --git a/src/server/DashSession/DashSessionAgent.ts b/src/server/DashSession/DashSessionAgent.ts
index 03ba33fee..1a5934d8f 100644
--- a/src/server/DashSession/DashSessionAgent.ts
+++ b/src/server/DashSession/DashSessionAgent.ts
@@ -214,7 +214,7 @@ export class DashSessionAgent extends AppliedSessionAgent {
             // indicate success or failure
             mainLog(`${error === null ? green("successfully dispatched") : red("failed to dispatch")} ${zipName} to ${cyan(to)}`);
             error && mainLog(red(error.message));
-        } catch (error) {
+        } catch (error: any) {
             mainLog(red("unable to dispatch zipped backup..."));
             mainLog(red(error.message));
         }
diff --git a/src/server/DashSession/Session/agents/monitor.ts b/src/server/DashSession/Session/agents/monitor.ts
index 0fdaf07ff..9cb5ab576 100644
--- a/src/server/DashSession/Session/agents/monitor.ts
+++ b/src/server/DashSession/Session/agents/monitor.ts
@@ -178,7 +178,7 @@ export class Monitor extends IPCMessageReceiver {
             // ensure all necessary and no excess information is specified by the configuration file
             validate(config, configurationSchema, options);
             config = Utilities.preciseAssign({}, defaultConfig, config);
-        } catch (error) {
+        } catch (error: any) {
             if (error instanceof ValidationError) {
                 console.log(red("\nSession configuration failed."));
                 console.log("The given session.config.json configuration file is invalid.");
diff --git a/src/server/DashSession/Session/agents/promisified_ipc_manager.ts b/src/server/DashSession/Session/agents/promisified_ipc_manager.ts
index 95aa686e6..f6c8de521 100644
--- a/src/server/DashSession/Session/agents/promisified_ipc_manager.ts
+++ b/src/server/DashSession/Session/agents/promisified_ipc_manager.ts
@@ -157,7 +157,7 @@ export class PromisifiedIPCManager {
                 if (registered) {
                     results = await Promise.all(registered.map(handler => handler(args)));
                 }
-            } catch (e) {
+            } catch (e: any) {
                 error = e;
             }
             if (!this.isDestroyed && this.target.send) {
diff --git a/src/server/DashSession/Session/agents/server_worker.ts b/src/server/DashSession/Session/agents/server_worker.ts
index 84d35b40e..634b0113d 100644
--- a/src/server/DashSession/Session/agents/server_worker.ts
+++ b/src/server/DashSession/Session/agents/server_worker.ts
@@ -138,7 +138,7 @@ export class ServerWorker extends IPCMessageReceiver {
                         this.isInitialized = true;
                     }
                     this.shouldServerBeResponsive = true;
-                } catch (error) {
+                } catch (error: any) {
                     // if we expect the server to be unavailable, i.e. during compilation,
                     // the listening variable is false, activeExit will return early and the child
                     // process will continue
diff --git a/src/server/DashUploadUtils.ts b/src/server/DashUploadUtils.ts
index 7073ee90b..552ab57a5 100644
--- a/src/server/DashUploadUtils.ts
+++ b/src/server/DashUploadUtils.ts
@@ -244,7 +244,7 @@ export namespace DashUploadUtils {
         // Use the request library to parse out file level image information in the headers
         const { headers } = (await new Promise<any>((resolve, reject) => {
             request.head(resolvedUrl, (error, res) => error ? reject(error) : resolve(res));
-        }).catch(error => console.error(error)));
+        }).catch(console.error));
         try {
             // Compute the native width and height ofthe image with an npm module
             const { width: nativeWidth, height: nativeHeight } = await requestImageSize(resolvedUrl);
@@ -258,7 +258,7 @@ export namespace DashUploadUtils {
                 filename,
                 ...results
             };
-        } catch (e) {
+        } catch (e: any) {
             console.log(e);
             return e;
         }
diff --git a/src/server/Search.ts b/src/server/Search.ts
index 68f61deb2..25bd8badf 100644
--- a/src/server/Search.ts
+++ b/src/server/Search.ts
@@ -49,7 +49,7 @@ export namespace Search {
                 },
                 json: true
             });
-        } catch (e) {
+        } catch (e: any) {
             console.log(red("Unable to clear search..."));
             console.log(red(e.message));
         }
diff --git a/src/server/apis/google/GoogleApiServerUtils.ts b/src/server/apis/google/GoogleApiServerUtils.ts
index 64bafe7fb..4453b83bf 100644
--- a/src/server/apis/google/GoogleApiServerUtils.ts
+++ b/src/server/apis/google/GoogleApiServerUtils.ts
@@ -128,7 +128,7 @@ export namespace GoogleApiServerUtils {
      * @param userId the id of the Dash user making the request to the API
      * @returns the relevant 'googleapis' wrapper, if any
      */
-    export async function GetEndpoint(sector: string, userId: string): Promise<Opt<Endpoint>> {
+    export async function GetEndpoint(sector: string, userId: string): Promise<Endpoint | void> {
         return new Promise(async resolve => {
             const auth = await retrieveOAuthClient(userId);
             if (!auth) {
@@ -157,7 +157,7 @@ export namespace GoogleApiServerUtils {
      * npm-installed API wrappers that use authenticated client instances rather than access codes for
      * security.
      */
-    export async function retrieveOAuthClient(userId: string): Promise<OAuth2Client> {
+    export async function retrieveOAuthClient(userId: string): Promise<OAuth2Client | void> {
         return new Promise(async resolve => {
             const { credentials, refreshed } = await retrieveCredentials(userId);
             if (!credentials) {
diff --git a/src/server/remapUrl.ts b/src/server/remapUrl.ts
index e9f9da25a..b8e17ec66 100644
--- a/src/server/remapUrl.ts
+++ b/src/server/remapUrl.ts
@@ -47,7 +47,7 @@ async function update() {
     await cursor.forEach(updateDoc);
     await Promise.all(updates.map(doc => {
         console.log(doc[0], doc[1]);
-        return new Promise(res => Database.Instance.update(doc[0], doc[1], () => {
+        return new Promise<void>(res => Database.Instance.update(doc[0], doc[1], () => {
             console.log("wrote " + JSON.stringify(doc[1]));
             res();
         }, false));
diff --git a/src/server/server_Initialization.ts b/src/server/server_Initialization.ts
index 06c701468..a10cd4983 100644
--- a/src/server/server_Initialization.ts
+++ b/src/server/server_Initialization.ts
@@ -31,7 +31,7 @@ const compiler = webpack(config);
 /* RouteSetter is a wrapper around the server that prevents the server
    from being exposed. */
 export type RouteSetter = (server: RouteManager) => void;
-export let disconnect: Function;
+//export let disconnect: Function;
 
 export let resolvedPorts: { server: number, socket: number } = { server: 1050, socket: 4321 };
 export let resolvedServerUrl: string;
@@ -40,6 +40,14 @@ export default async function InitializeServer(routeSetter: RouteSetter) {
     const isRelease = determineEnvironment();
     const app = buildWithMiddleware(express());
 
+    const compiler = webpack(config);
+
+    app.use(require("webpack-dev-middleware")(compiler, {
+        publicPath: config.output.publicPath
+    }));
+
+    app.use(require("webpack-hot-middleware")(compiler));
+
     // route table managed by express.  routes are tested sequentially against each of these map rules.  when a match is found, the handler is called to process the request
     app.get(new RegExp(/^\/+$/), (req, res) => res.redirect(req.user ? "/home" : "/login")); // target urls that consist of one or more '/'s with nothing in between
     app.use(express.static(publicDirectory, { setHeaders: res => res.setHeader("Access-Control-Allow-Origin", "*") }));  //all urls that start with dash's public directory: /files/  (e.g., /files/images, /files/audio, etc)
@@ -66,7 +74,7 @@ export default async function InitializeServer(routeSetter: RouteSetter) {
     // a field on one client, that change must be broadcast to all other clients)
     await WebSocket.initialize(isRelease, app);
 
-    disconnect = async () => new Promise<Error>(resolve => server.close(resolve));
+    //disconnect = async () => new Promise<Error>(resolve => server.close(resolve));
     return isRelease;
 }
 
diff --git a/webpack.config.js b/webpack.config.js
index 32f19d388..05bf4ed76 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -65,12 +65,12 @@ module.exports = {
             net: false,
             path: false,
             zlib: false,
-            http: require.resolve("http-browserify"),
-            https: require.resolve("https-browserify"),
             dns: false,
             crypto: false,
             assert: false,
             os: false,
+            http: require.resolve("http-browserify"),
+            https: require.resolve("https-browserify"),
             stream: require.resolve("stream-browserify"),
             buffer: require.resolve("buffer")
         }
-- 
cgit v1.2.3-70-g09d2


From ff2602bb598b6e82330a9a0b2453e44d70c94c39 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Fri, 4 Mar 2022 15:19:09 -0500
Subject: removed pseudo Doc type system. playing with hot reloading.

---
 deploy/index.html                                  |  12 +-
 package-lock.json                                  | 146 ++++++++-
 package.json                                       |   3 +
 src/Utils.ts                                       |   2 +-
 src/client/documents/Documents.ts                  |   2 +-
 src/client/util/DictationManager.ts                | 346 ++++++++++-----------
 .../util/Import & Export/DirectoryImportBox.tsx    |   3 +-
 src/client/util/Scripting.ts                       |  15 +-
 src/client/util/SerializationHelper.ts             |   2 +-
 src/client/views/DocComponent.tsx                  |  12 +-
 src/client/views/InkingStroke.tsx                  |   7 +-
 src/client/views/Main.tsx                          |  16 +-
 src/client/views/MainView.tsx                      |   1 -
 src/client/views/StyleProvider.tsx                 |   2 +-
 src/client/views/TemplateMenu.tsx                  |   2 +-
 src/client/views/animationtimeline/Keyframe.tsx    |  21 +-
 .../views/collections/CollectionCarousel3DView.tsx |  10 +-
 .../views/collections/CollectionCarouselView.tsx   |   9 +-
 .../views/collections/CollectionDockingView.tsx    |  12 +-
 .../views/collections/CollectionPileView.tsx       |   2 +-
 .../collections/CollectionStackedTimeline.tsx      |  54 ++--
 .../views/collections/CollectionStackingView.tsx   |  17 +-
 .../views/collections/CollectionStaffView.tsx      |   2 +-
 src/client/views/collections/CollectionSubView.tsx |   4 +-
 .../views/collections/CollectionTimeView.tsx       |  11 +-
 .../views/collections/CollectionTreeView.tsx       |   6 +-
 src/client/views/collections/CollectionView.tsx    |  15 +-
 .../collectionFreeForm/CollectionFreeFormView.tsx  |  42 ++-
 .../collectionGrid/CollectionGridView.tsx          |   7 +-
 .../collectionLinear/CollectionLinearView.tsx      |   7 +-
 .../CollectionMulticolumnView.tsx                  |   8 +-
 .../CollectionMultirowView.tsx                     |   9 +-
 .../collectionSchema/CollectionSchemaCells.tsx     |   9 +-
 .../collectionSchema/CollectionSchemaView.tsx      |   2 +-
 src/client/views/nodes/AudioBox.tsx                |  20 +-
 .../views/nodes/CollectionFreeFormDocumentView.tsx |  12 +-
 src/client/views/nodes/ColorBox.tsx                |   7 +-
 src/client/views/nodes/ComparisonBox.tsx           |   9 +-
 src/client/views/nodes/DocumentView.tsx            |  11 +-
 src/client/views/nodes/EquationBox.tsx             |  11 +-
 src/client/views/nodes/FilterBox.tsx               |  11 +-
 src/client/views/nodes/FunctionPlotBox.tsx         |   2 +-
 src/client/views/nodes/ImageBox.tsx                |  13 +-
 src/client/views/nodes/LabelBox.tsx                |   9 +-
 src/client/views/nodes/LinkAnchorBox.tsx           |   6 +-
 src/client/views/nodes/LinkBox.tsx                 |   7 +-
 src/client/views/nodes/MapBox/MapBox.tsx           |   7 +-
 src/client/views/nodes/PDFBox.tsx                  |  20 +-
 src/client/views/nodes/ScreenshotBox.tsx           |  14 +-
 src/client/views/nodes/ScriptingBox.tsx            |  15 +-
 src/client/views/nodes/SliderBox.tsx               |  15 +-
 src/client/views/nodes/VideoBox.tsx                |  49 ++-
 src/client/views/nodes/WebBox.tsx                  |  14 +-
 src/client/views/nodes/button/FontIconBox.tsx      |  22 +-
 .../views/nodes/formattedText/FormattedTextBox.tsx |   8 +-
 src/client/views/nodes/trails/PresBox.tsx          |   8 +-
 src/client/views/nodes/trails/PresElementBox.tsx   |  29 +-
 src/client/views/search/SearchBox.tsx              |  18 +-
 src/fields/Doc.ts                                  |   3 +
 src/fields/InkField.ts                             |   5 +-
 src/fields/ObjectField.ts                          |   5 +-
 src/fields/RichTextField.ts                        |   6 +-
 src/fields/ScriptField.ts                          |  18 +-
 webpack.config.js                                  |   3 +
 64 files changed, 571 insertions(+), 624 deletions(-)

(limited to 'src/client/util/Import & Export/DirectoryImportBox.tsx')

diff --git a/deploy/index.html b/deploy/index.html
index a236de872..f8003f126 100644
--- a/deploy/index.html
+++ b/deploy/index.html
@@ -34,7 +34,7 @@
             align-content: center;
             justify-content: center;
             background-color: #BDDDF5;
-            transition: 3s;
+            transition: .3s;
             z-index: 10;
             z-index: 10;
             width: 100%;
@@ -139,11 +139,11 @@
                         if (document.getElementById("dash-progress")) document.getElementById("dash-progress").style.width = width
                         if (document.getElementById("dash-progress")) document.getElementById("dash-loader-text").innerHTML = msg
                     }
-                    setTimeout(() => dashmesg("10%", "Loading Dash..."), load / 10);
-                    setTimeout(() => dashmesg("33%", "Preparing dashboards..."), load / 3);
-                    setTimeout(() => dashmesg("50%", "Initializing scripts..."), load / 2);
-                    setTimeout(() => dashmesg("75%", "Fetching documents..."), load / 4 * 3);
-                    setTimeout(() => dashmesg("100%", "Finalising setup..."), load);
+                    // setTimeout(() => dashmesg("10%", "Loading Dash..."), load / 10);
+                    // setTimeout(() => dashmesg("33%", "Preparing dashboards..."), load / 3);
+                    // setTimeout(() => dashmesg("50%", "Initializing scripts..."), load / 2);
+                    // setTimeout(() => dashmesg("75%", "Fetching documents..."), load / 4 * 3);
+                    // setTimeout(() => dashmesg("100%", "Finalising setup..."), load);
                 </script>
             </div>
             <div id="dash-loader-text" class="dash-loader-text">
diff --git a/package-lock.json b/package-lock.json
index 420f226e8..eff8ed627 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1063,6 +1063,108 @@
                 "react-is": "^16.8.0 || ^17.0.0"
             }
         },
+        "@pmmmwh/react-refresh-webpack-plugin": {
+            "version": "0.5.4",
+            "resolved": "https://registry.npmjs.org/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.4.tgz",
+            "integrity": "sha512-zZbZeHQDnoTlt2AF+diQT0wsSXpvWiaIOZwBRdltNFhG1+I3ozyaw7U/nBiUwyJ0D+zwdXp0E3bWOl38Ag2BMw==",
+            "requires": {
+                "ansi-html-community": "^0.0.8",
+                "common-path-prefix": "^3.0.0",
+                "core-js-pure": "^3.8.1",
+                "error-stack-parser": "^2.0.6",
+                "find-up": "^5.0.0",
+                "html-entities": "^2.1.0",
+                "loader-utils": "^2.0.0",
+                "schema-utils": "^3.0.0",
+                "source-map": "^0.7.3"
+            },
+            "dependencies": {
+                "ajv": {
+                    "version": "6.12.6",
+                    "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+                    "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+                    "requires": {
+                        "fast-deep-equal": "^3.1.1",
+                        "fast-json-stable-stringify": "^2.0.0",
+                        "json-schema-traverse": "^0.4.1",
+                        "uri-js": "^4.2.2"
+                    }
+                },
+                "ajv-keywords": {
+                    "version": "3.5.2",
+                    "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
+                    "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ=="
+                },
+                "find-up": {
+                    "version": "5.0.0",
+                    "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+                    "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+                    "requires": {
+                        "locate-path": "^6.0.0",
+                        "path-exists": "^4.0.0"
+                    }
+                },
+                "html-entities": {
+                    "version": "2.3.2",
+                    "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.2.tgz",
+                    "integrity": "sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ=="
+                },
+                "loader-utils": {
+                    "version": "2.0.2",
+                    "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz",
+                    "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==",
+                    "requires": {
+                        "big.js": "^5.2.2",
+                        "emojis-list": "^3.0.0",
+                        "json5": "^2.1.2"
+                    }
+                },
+                "locate-path": {
+                    "version": "6.0.0",
+                    "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+                    "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+                    "requires": {
+                        "p-locate": "^5.0.0"
+                    }
+                },
+                "p-limit": {
+                    "version": "3.1.0",
+                    "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+                    "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+                    "requires": {
+                        "yocto-queue": "^0.1.0"
+                    }
+                },
+                "p-locate": {
+                    "version": "5.0.0",
+                    "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+                    "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+                    "requires": {
+                        "p-limit": "^3.0.2"
+                    }
+                },
+                "path-exists": {
+                    "version": "4.0.0",
+                    "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+                    "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="
+                },
+                "schema-utils": {
+                    "version": "3.1.1",
+                    "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz",
+                    "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==",
+                    "requires": {
+                        "@types/json-schema": "^7.0.8",
+                        "ajv": "^6.12.5",
+                        "ajv-keywords": "^3.5.2"
+                    }
+                },
+                "source-map": {
+                    "version": "0.7.3",
+                    "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
+                    "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ=="
+                }
+            }
+        },
         "@react-google-maps/api": {
             "version": "2.7.0",
             "resolved": "https://registry.npmjs.org/@react-google-maps/api/-/api-2.7.0.tgz",
@@ -2782,8 +2884,7 @@
         "ansi-html-community": {
             "version": "0.0.8",
             "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz",
-            "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==",
-            "dev": true
+            "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw=="
         },
         "ansi-regex": {
             "version": "3.0.0",
@@ -4774,6 +4875,11 @@
             "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
             "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
         },
+        "common-path-prefix": {
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-3.0.0.tgz",
+            "integrity": "sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w=="
+        },
         "commondir": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
@@ -6550,6 +6656,14 @@
                 "is-arrayish": "^0.2.1"
             }
         },
+        "error-stack-parser": {
+            "version": "2.0.7",
+            "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.0.7.tgz",
+            "integrity": "sha512-chLOW0ZGRf4s8raLrDxa5sdkvPec5YdvwbFnqJme4rk0rFajP8mPtrDL1+I+CwrQDCjswDA5sREX7jYQDQs9vA==",
+            "requires": {
+                "stackframe": "^1.1.1"
+            }
+        },
         "es-abstract": {
             "version": "1.17.5",
             "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz",
@@ -9557,6 +9671,14 @@
             "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
             "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
         },
+        "json5": {
+            "version": "2.2.0",
+            "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz",
+            "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==",
+            "requires": {
+                "minimist": "^1.2.5"
+            }
+        },
         "jsondiffpatch": {
             "version": "0.4.1",
             "resolved": "https://registry.npmjs.org/jsondiffpatch/-/jsondiffpatch-0.4.1.tgz",
@@ -16072,6 +16194,16 @@
                 }
             }
         },
+        "react-refresh": {
+            "version": "0.11.0",
+            "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz",
+            "integrity": "sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A=="
+        },
+        "react-refresh-typescript": {
+            "version": "2.0.3",
+            "resolved": "https://registry.npmjs.org/react-refresh-typescript/-/react-refresh-typescript-2.0.3.tgz",
+            "integrity": "sha512-CnR+UkpCFUIxW3u+KPxc6UhSO3M3aQxd9XCvgdry4a22LFwwITnjbANFUKtPGxA/Skw3PbZJrLiZ08UQnpXprQ=="
+        },
         "react-resizable": {
             "version": "1.11.1",
             "resolved": "https://registry.npmjs.org/react-resizable/-/react-resizable-1.11.1.tgz",
@@ -17766,6 +17898,11 @@
                 "safe-buffer": "^5.1.1"
             }
         },
+        "stackframe": {
+            "version": "1.2.1",
+            "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.2.1.tgz",
+            "integrity": "sha512-h88QkzREN/hy8eRdyNhhsO7RSJ5oyTqxxmmn0dzBIMUclZsjpfmrsg81vp8mjjAs2vAZ72nyWxRUwSwmh0e4xg=="
+        },
         "standard-error": {
             "version": "1.1.0",
             "resolved": "https://registry.npmjs.org/standard-error/-/standard-error-1.1.0.tgz",
@@ -20486,6 +20623,11 @@
             "integrity": "sha1-5a2ryKz0CPY4X8dklWhMiOavaJo=",
             "dev": true
         },
+        "yocto-queue": {
+            "version": "0.1.0",
+            "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+            "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="
+        },
         "zip-stream": {
             "version": "2.1.3",
             "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-2.1.3.tgz",
diff --git a/package.json b/package.json
index 5aa2cf32d..5cf892b1e 100644
--- a/package.json
+++ b/package.json
@@ -121,6 +121,7 @@
         "@hig/theme-context": "^2.1.3",
         "@hig/theme-data": "^2.23.1",
         "@material-ui/core": "^4.12.3",
+        "@pmmmwh/react-refresh-webpack-plugin": "^0.5.4",
         "@react-google-maps/api": "^2.7.0",
         "@react-three/fiber": "^6.2.3",
         "@types/bezier-js": "^4.1.0",
@@ -258,6 +259,8 @@
         "react-jsx-parser": "^1.29.0",
         "react-loading": "^2.0.3",
         "react-measure": "^2.5.2",
+        "react-refresh": "^0.11.0",
+        "react-refresh-typescript": "^2.0.3",
         "react-resizable": "^1.11.1",
         "react-resizable-rotatable-draggable": "^0.2.0",
         "react-reveal": "^1.2.2",
diff --git a/src/Utils.ts b/src/Utils.ts
index f2d9e7766..d0d891f77 100644
--- a/src/Utils.ts
+++ b/src/Utils.ts
@@ -2,8 +2,8 @@ import v4 = require('uuid/v4');
 import v5 = require("uuid/v5");
 import { ColorState } from 'react-color';
 import { Socket } from 'socket.io';
-import { Message } from './server/Message';
 import { Colors } from './client/views/global/globalEnums';
+import { Message } from './server/Message';
 import Color = require('color');
 
 export namespace Utils {
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 3de59ecc3..b81037085 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -662,7 +662,7 @@ export namespace Docs {
 
         export function ImageDocument(url: string, options: DocumentOptions = {}) {
             const imgField = new ImageField(url);
-            return InstanceFromProto(Prototypes.get(DocumentType.IMG), imgField, { title: url.replace(/.*\//, "") /* path.basename(url)*/, ...options });
+            return InstanceFromProto(Prototypes.get(DocumentType.IMG), imgField, { title: basename(url), ...options });
         }
 
         export function PresDocument(initial: List<Doc> = new List(), options: DocumentOptions = {}) {
diff --git a/src/client/util/DictationManager.ts b/src/client/util/DictationManager.ts
index a086ac45e..a6dcda4bc 100644
--- a/src/client/util/DictationManager.ts
+++ b/src/client/util/DictationManager.ts
@@ -105,16 +105,16 @@ export namespace DictationManager {
             try {
                 results = await (pendingListen = listenImpl(options));
                 pendingListen = undefined;
-                if (results) {
-                    Utils.CopyText(results);
-                    if (overlay) {
-                        DictationOverlay.Instance.isListening = false;
-                        const execute = options?.tryExecute;
-                        DictationOverlay.Instance.dictatedPhrase = execute ? results.toLowerCase() : results;
-                        DictationOverlay.Instance.dictationSuccess = execute ? await DictationManager.Commands.execute(results) : true;
-                    }
-                    options?.tryExecute && await DictationManager.Commands.execute(results);
-                }
+                // if (results) {
+                //     Utils.CopyText(results);
+                //     if (overlay) {
+                //         DictationOverlay.Instance.isListening = false;
+                //         const execute = options?.tryExecute;
+                //         DictationOverlay.Instance.dictatedPhrase = execute ? results.toLowerCase() : results;
+                //         DictationOverlay.Instance.dictationSuccess = execute ? await DictationManager.Commands.execute(results) : true;
+                //     }
+                //     options?.tryExecute && await DictationManager.Commands.execute(results);
+                // }
             } catch (e: any) {
                 console.log(e);
                 if (overlay) {
@@ -225,168 +225,168 @@ export namespace DictationManager {
 
     }
 
-    export namespace Commands {
-
-        export const dictationFadeDuration = 2000;
-
-        export type IndependentAction = (target: DocumentView) => any | Promise<any>;
-        export type IndependentEntry = { action: IndependentAction, restrictTo?: DocumentType[] };
-
-        export type DependentAction = (target: DocumentView, matches: RegExpExecArray) => any | Promise<any>;
-        export type DependentEntry = { expression: RegExp, action: DependentAction, restrictTo?: DocumentType[] };
-
-        export const RegisterIndependent = (key: string, value: IndependentEntry) => Independent.set(key, value);
-        export const RegisterDependent = (entry: DependentEntry) => Dependent.push(entry);
-
-        export const execute = async (phrase: string) => {
-            return UndoManager.RunInBatch(async () => {
-                const targets = SelectionManager.Views();
-                if (!targets || !targets.length) {
-                    return;
-                }
-
-                phrase = phrase.toLowerCase();
-                const entry = Independent.get(phrase);
-
-                if (entry) {
-                    let success = false;
-                    const restrictTo = entry.restrictTo;
-                    for (const target of targets) {
-                        if (!restrictTo || validate(target, restrictTo)) {
-                            await entry.action(target);
-                            success = true;
-                        }
-                    }
-                    return success;
-                }
-
-                for (const entry of Dependent) {
-                    const regex = entry.expression;
-                    const matches = regex.exec(phrase);
-                    regex.lastIndex = 0;
-                    if (matches !== null) {
-                        let success = false;
-                        const restrictTo = entry.restrictTo;
-                        for (const target of targets) {
-                            if (!restrictTo || validate(target, restrictTo)) {
-                                await entry.action(target, matches);
-                                success = true;
-                            }
-                        }
-                        return success;
-                    }
-                }
-
-                return false;
-            }, "Execute Command");
-        };
-
-        const ConstructorMap = new Map<DocumentType, CastCtor>([
-            [DocumentType.COL, listSpec(Doc)],
-            [DocumentType.AUDIO, AudioField],
-            [DocumentType.IMG, ImageField],
-            [DocumentType.IMPORT, listSpec(Doc)],
-            [DocumentType.RTF, "string"]
-        ]);
-
-        const tryCast = (view: DocumentView, type: DocumentType) => {
-            const ctor = ConstructorMap.get(type);
-            if (!ctor) {
-                return false;
-            }
-            return Cast(Doc.GetProto(view.props.Document).data, ctor) !== undefined;
-        };
-
-        const validate = (target: DocumentView, types: DocumentType[]) => {
-            for (const type of types) {
-                if (tryCast(target, type)) {
-                    return true;
-                }
-            }
-            return false;
-        };
-
-        const interpretNumber = (number: string) => {
-            const initial = parseInt(number);
-            if (!isNaN(initial)) {
-                return initial;
-            }
-            const converted = interpreter.wordsToNumbers(number, { fuzzy: true });
-            if (converted === null) {
-                return NaN;
-            }
-            return typeof converted === "string" ? parseInt(converted) : converted;
-        };
-
-        const Independent = new Map<string, IndependentEntry>([
-
-            ["clear", {
-                action: (target: DocumentView) => Doc.GetProto(target.props.Document).data = new List(),
-                restrictTo: [DocumentType.COL]
-            }],
-
-            ["open fields", {
-                action: (target: DocumentView) => {
-                    const kvp = Docs.Create.KVPDocument(target.props.Document, { _width: 300, _height: 300 });
-                    target.props.addDocTab(kvp, "add:right");
-                }
-            }],
-
-            ["new outline", {
-                action: (target: DocumentView) => {
-                    const newBox = Docs.Create.TextDocument("", { _width: 400, _height: 200, title: "My Outline", _autoHeight: true });
-                    const proto = newBox.proto!;
-                    const prompt = "Press alt + r to start dictating here...";
-                    const head = 3;
-                    const anchor = head + prompt.length;
-                    const proseMirrorState = `{"doc":{"type":"doc","content":[{"type":"ordered_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"type":"text","text":"${prompt}"}]}]}]}]},"selection":{"type":"text","anchor":${anchor},"head":${head}}}`;
-                    proto.data = new RichTextField(proseMirrorState);
-                    proto.backgroundColor = "#eeffff";
-                    target.props.addDocTab(newBox, "add:right");
-                }
-            }]
-
-        ]);
-
-        const Dependent = new Array<DependentEntry>(
-
-            {
-                expression: /create (\w+) documents of type (image|nested collection)/g,
-                action: (target: DocumentView, matches: RegExpExecArray) => {
-                    const count = interpretNumber(matches[1]);
-                    const what = matches[2];
-                    const dataDoc = Doc.GetProto(target.props.Document);
-                    const fieldKey = "data";
-                    if (isNaN(count)) {
-                        return;
-                    }
-                    for (let i = 0; i < count; i++) {
-                        let created: Doc | undefined;
-                        switch (what) {
-                            case "image":
-                                created = Docs.Create.ImageDocument("https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg");
-                                break;
-                            case "nested collection":
-                                created = Docs.Create.FreeformDocument([], {});
-                                break;
-                        }
-                        created && Doc.AddDocToList(dataDoc, fieldKey, created);
-                    }
-                },
-                restrictTo: [DocumentType.COL]
-            },
-
-            {
-                expression: /view as (freeform|stacking|masonry|schema|tree)/g,
-                action: (target: DocumentView, matches: RegExpExecArray) => {
-                    const mode = matches[1];
-                    mode && (target.props.Document._viewType = mode);
-                },
-                restrictTo: [DocumentType.COL]
-            }
-
-        );
-
-    }
+    // export namespace Commands {
+
+    //     export const dictationFadeDuration = 2000;
+
+    //     export type IndependentAction = (target: DocumentView) => any | Promise<any>;
+    //     export type IndependentEntry = { action: IndependentAction, restrictTo?: DocumentType[] };
+
+    //     export type DependentAction = (target: DocumentView, matches: RegExpExecArray) => any | Promise<any>;
+    //     export type DependentEntry = { expression: RegExp, action: DependentAction, restrictTo?: DocumentType[] };
+
+    //     export const RegisterIndependent = (key: string, value: IndependentEntry) => Independent.set(key, value);
+    //     export const RegisterDependent = (entry: DependentEntry) => Dependent.push(entry);
+
+    //     export const execute = async (phrase: string) => {
+    //         return UndoManager.RunInBatch(async () => {
+    //             const targets = SelectionManager.Views();
+    //             if (!targets || !targets.length) {
+    //                 return;
+    //             }
+
+    //             phrase = phrase.toLowerCase();
+    //             const entry = Independent.get(phrase);
+
+    //             if (entry) {
+    //                 let success = false;
+    //                 const restrictTo = entry.restrictTo;
+    //                 for (const target of targets) {
+    //                     if (!restrictTo || validate(target, restrictTo)) {
+    //                         await entry.action(target);
+    //                         success = true;
+    //                     }
+    //                 }
+    //                 return success;
+    //             }
+
+    //             for (const entry of Dependent) {
+    //                 const regex = entry.expression;
+    //                 const matches = regex.exec(phrase);
+    //                 regex.lastIndex = 0;
+    //                 if (matches !== null) {
+    //                     let success = false;
+    //                     const restrictTo = entry.restrictTo;
+    //                     for (const target of targets) {
+    //                         if (!restrictTo || validate(target, restrictTo)) {
+    //                             await entry.action(target, matches);
+    //                             success = true;
+    //                         }
+    //                     }
+    //                     return success;
+    //                 }
+    //             }
+
+    //             return false;
+    //         }, "Execute Command");
+    //     };
+
+    //     const ConstructorMap = new Map<DocumentType, CastCtor>([
+    //         [DocumentType.COL, listSpec(Doc)],
+    //         [DocumentType.AUDIO, AudioField],
+    //         [DocumentType.IMG, ImageField],
+    //         [DocumentType.IMPORT, listSpec(Doc)],
+    //         [DocumentType.RTF, "string"]
+    //     ]);
+
+    //     const tryCast = (view: DocumentView, type: DocumentType) => {
+    //         const ctor = ConstructorMap.get(type);
+    //         if (!ctor) {
+    //             return false;
+    //         }
+    //         return Cast(Doc.GetProto(view.props.Document).data, ctor) !== undefined;
+    //     };
+
+    //     const validate = (target: DocumentView, types: DocumentType[]) => {
+    //         for (const type of types) {
+    //             if (tryCast(target, type)) {
+    //                 return true;
+    //             }
+    //         }
+    //         return false;
+    //     };
+
+    //     const interpretNumber = (number: string) => {
+    //         const initial = parseInt(number);
+    //         if (!isNaN(initial)) {
+    //             return initial;
+    //         }
+    //         const converted = interpreter.wordsToNumbers(number, { fuzzy: true });
+    //         if (converted === null) {
+    //             return NaN;
+    //         }
+    //         return typeof converted === "string" ? parseInt(converted) : converted;
+    //     };
+
+    //     const Independent = new Map<string, IndependentEntry>([
+
+    //         ["clear", {
+    //             action: (target: DocumentView) => Doc.GetProto(target.props.Document).data = new List(),
+    //             restrictTo: [DocumentType.COL]
+    //         }],
+
+    //         ["open fields", {
+    //             action: (target: DocumentView) => {
+    //                 const kvp = Docs.Create.KVPDocument(target.props.Document, { _width: 300, _height: 300 });
+    //                 target.props.addDocTab(kvp, "add:right");
+    //             }
+    //         }],
+
+    //         ["new outline", {
+    //             action: (target: DocumentView) => {
+    //                 const newBox = Docs.Create.TextDocument("", { _width: 400, _height: 200, title: "My Outline", _autoHeight: true });
+    //                 const proto = newBox.proto!;
+    //                 const prompt = "Press alt + r to start dictating here...";
+    //                 const head = 3;
+    //                 const anchor = head + prompt.length;
+    //                 const proseMirrorState = `{"doc":{"type":"doc","content":[{"type":"ordered_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"type":"text","text":"${prompt}"}]}]}]}]},"selection":{"type":"text","anchor":${anchor},"head":${head}}}`;
+    //                 proto.data = new RichTextField(proseMirrorState);
+    //                 proto.backgroundColor = "#eeffff";
+    //                 target.props.addDocTab(newBox, "add:right");
+    //             }
+    //         }]
+
+    //     ]);
+
+    //     const Dependent = new Array<DependentEntry>(
+
+    //         {
+    //             expression: /create (\w+) documents of type (image|nested collection)/g,
+    //             action: (target: DocumentView, matches: RegExpExecArray) => {
+    //                 const count = interpretNumber(matches[1]);
+    //                 const what = matches[2];
+    //                 const dataDoc = Doc.GetProto(target.props.Document);
+    //                 const fieldKey = "data";
+    //                 if (isNaN(count)) {
+    //                     return;
+    //                 }
+    //                 for (let i = 0; i < count; i++) {
+    //                     let created: Doc | undefined;
+    //                     switch (what) {
+    //                         case "image":
+    //                             created = Docs.Create.ImageDocument("https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg");
+    //                             break;
+    //                         case "nested collection":
+    //                             created = Docs.Create.FreeformDocument([], {});
+    //                             break;
+    //                     }
+    //                     created && Doc.AddDocToList(dataDoc, fieldKey, created);
+    //                 }
+    //             },
+    //             restrictTo: [DocumentType.COL]
+    //         },
+
+    //         {
+    //             expression: /view as (freeform|stacking|masonry|schema|tree)/g,
+    //             action: (target: DocumentView, matches: RegExpExecArray) => {
+    //                 const mode = matches[1];
+    //                 mode && (target.props.Document._viewType = mode);
+    //             },
+    //             restrictTo: [DocumentType.COL]
+    //         }
+
+    //     );
+
+    // }
 
 }
\ No newline at end of file
diff --git a/src/client/util/Import & Export/DirectoryImportBox.tsx b/src/client/util/Import & Export/DirectoryImportBox.tsx
index 9eee75253..39e9251a5 100644
--- a/src/client/util/Import & Export/DirectoryImportBox.tsx	
+++ b/src/client/util/Import & Export/DirectoryImportBox.tsx	
@@ -2,6 +2,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { BatchedArray } from "array-batcher";
 import { action, computed, IReactionDisposer, observable, reaction, runInAction } from "mobx";
 import { observer } from "mobx-react";
+import { extname } from "path";
 import Measure, { ContentRect } from "react-measure";
 import { Doc, DocListCast, DocListCastAsync, Opt } from "../../../fields/Doc";
 import { Id } from "../../../fields/FieldSymbols";
@@ -84,7 +85,7 @@ export class DirectoryImportBox extends React.Component<FieldViewProps> {
         for (let i = 0; i < files.length; i++) {
             const file = files.item(i);
             if (file && !unsupported.includes(file.type)) {
-                const ext = file.name.replace(/.*\./, "").toLowerCase(); // path.extname(file.name).toLowerCase();
+                const ext = extname(file.name).toLowerCase();
                 if (AcceptableMedia.imageFormats.includes(ext)) {
                     validated.push(file);
                 }
diff --git a/src/client/util/Scripting.ts b/src/client/util/Scripting.ts
index 40b94024e..ffe60c72e 100644
--- a/src/client/util/Scripting.ts
+++ b/src/client/util/Scripting.ts
@@ -10,7 +10,6 @@ export { ts };
 
 // @ts-ignore
 import * as typescriptlib from '!!raw-loader!./type_decls.d';
-import { Doc, Field } from '../../fields/Doc';
 
 export interface ScriptSuccess {
     success: true;
@@ -169,19 +168,19 @@ function Run(script: string | undefined, customParams: string[], diagnostics: an
         let batch: { end(): void } | undefined = undefined;
         try {
             if (!options.editable) {
-                batch = Doc.MakeReadOnly();
+                // batch = Doc.MakeReadOnly();
             }
 
             const result = compiledFunction.apply(thisParam, params).apply(thisParam, argsArray);
             if (batch) {
-                batch.end();
+                //batch.end();
             }
 
             return { success: true, result };
         } catch (error) {
 
             if (batch) {
-                batch.end();
+                //batch.end();
             }
             onError?.(script + " " + error);
             return { success: false, error, result: errorVal };
@@ -247,13 +246,13 @@ export type Traverser = (node: ts.Node, indentation: string) => boolean | void;
 export type TraverserParam = Traverser | { onEnter: Traverser, onLeave: Traverser };
 export type Transformer = {
     transformer: ts.TransformerFactory<ts.SourceFile>,
-    getVars?: () => { capturedVariables: { [name: string]: Field } }
+    getVars?: () => { capturedVariables: { [name: string]: any /* Field*/ } }
 };
 export interface ScriptOptions {
     requiredType?: string; // does function required a typed return value
     addReturn?: boolean;   // does the compiler automatically add a return statement
     params?: { [name: string]: string }; // list of function parameters and their types
-    capturedVariables?: { [name: string]: Field }; // list of captured variables
+    capturedVariables?: { [name: string]: any /* Field */ }; // list of captured variables
     typecheck?: boolean; // should the compiler perform typechecking
     editable?: boolean; // can the script edit Docs
     traverser?: TraverserParam;
@@ -270,8 +269,8 @@ function forEachNode(node: ts.Node, onEnter: Traverser, onExit?: Traverser, inde
 
 export function CompileScript(script: string, options: ScriptOptions = {}): CompileResult {
     const { requiredType = "", addReturn = false, params = {}, capturedVariables = {}, typecheck = true } = options;
-    if (options.params && !options.params.this) options.params.this = Doc.name;
-    if (options.params && !options.params.self) options.params.self = Doc.name;
+    if (options.params && !options.params.this) options.params.this = "Doc";//Doc.name;
+    if (options.params && !options.params.self) options.params.self = "Doc";//Doc.name;
     if (options.globals) {
         Scripting.setScriptingGlobals(options.globals);
     }
diff --git a/src/client/util/SerializationHelper.ts b/src/client/util/SerializationHelper.ts
index 2d598c1ac..fd8e38361 100644
--- a/src/client/util/SerializationHelper.ts
+++ b/src/client/util/SerializationHelper.ts
@@ -86,7 +86,7 @@ export function Deserializable(constructor: { new(...args: any[]): any } | strin
             serializationTypes[name] = { ctor, afterDeserialize };
             reverseMap[ctor.name] = name;
         } else {
-            throw new Error(`Name ${name} has already been registered as deserializable`);
+            ;//throw new Error(`Name ${name} has already been registered as deserializable`);
         }
     }
     if (typeof constructor === "string") {
diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx
index b9772fd57..2e6ea1faa 100644
--- a/src/client/views/DocComponent.tsx
+++ b/src/client/views/DocComponent.tsx
@@ -20,10 +20,10 @@ export interface DocComponentProps {
     LayoutTemplate?: () => Opt<Doc>;
     LayoutTemplateString?: string;
 }
-export function DocComponent<P extends DocComponentProps, T>(schemaCtor: (doc: Doc) => T) {
+export function DocComponent<P extends DocComponentProps>() {
     class Component extends Touchable<P> {
         //TODO This might be pretty inefficient if doc isn't observed, because computed doesn't cache then
-        @computed get Document(): T { return schemaCtor(this.props.Document); }
+        @computed get Document() { return this.props.Document; }
         // This is the "The Document" -- it encapsulates, data, layout, and any templates
         @computed get rootDoc() { return Cast(this.props.Document.rootDocument, Doc, null) || this.props.Document; }
         // This is the rendering data of a document -- it may be "The Document", or it may be some template document that holds the rendering info
@@ -48,7 +48,7 @@ interface ViewBoxBaseProps {
     renderDepth: number;
     rootSelected: (outsideReaction?: boolean) => boolean;
 }
-export function ViewBoxBaseComponent<P extends ViewBoxBaseProps, T>(schemaCtor: (doc: Doc) => T) {
+export function ViewBoxBaseComponent<P extends ViewBoxBaseProps>() {
     class Component extends Touchable<P> {
         //TODO This might be pretty inefficient if doc isn't observed, because computed doesn't cache then
         //@computed get Document(): T { return schemaCtor(this.props.Document); }
@@ -92,17 +92,17 @@ export interface ViewBoxAnnotatableProps {
     renderDepth: number;
     isAnnotationOverlay?: boolean;
 }
-export function ViewBoxAnnotatableComponent<P extends ViewBoxAnnotatableProps, T>(schemaCtor: (doc: Doc) => T) {
+export function ViewBoxAnnotatableComponent<P extends ViewBoxAnnotatableProps>() {
     class Component extends Touchable<P> {
         @observable _annotationKeySuffix = () => "annotations";
 
         @observable _isAnyChildContentActive = false;
         //TODO This might be pretty inefficient if doc isn't observed, because computed doesn't cache then
-        @computed get Document(): T { return schemaCtor(this.props.Document); }
+        @computed get Document() { return this.props.Document; }
         // This is the "The Document" -- it encapsulates, data, layout, and any templates
         @computed get rootDoc() { return Cast(this.props.Document.rootDocument, Doc, null) || this.props.Document; }
         // This is the rendering data of a document -- it may be "The Document", or it may be some template document that holds the rendering info
-        @computed get layoutDoc() { return schemaCtor(Doc.Layout(this.props.Document)); }
+        @computed get layoutDoc() { return Doc.Layout(this.props.Document); }
         // This is the data part of a document -- ie, the data that is constant across all views of the document
         @computed get dataDoc() { return this.props.DataDoc && (this.props.Document.isTemplateForField || this.props.Document.isTemplateDoc) ? this.props.DataDoc : this.props.Document[DataSym]; }
 
diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx
index 9dbd97c16..40fe6aa68 100644
--- a/src/client/views/InkingStroke.tsx
+++ b/src/client/views/InkingStroke.tsx
@@ -24,9 +24,7 @@ import React = require("react");
 import { action, IReactionDisposer, observable, reaction } from "mobx";
 import { observer } from "mobx-react";
 import { Doc, WidthSym } from "../../fields/Doc";
-import { documentSchema } from "../../fields/documentSchemas";
 import { InkData, InkField, InkTool } from "../../fields/InkField";
-import { makeInterface } from "../../fields/Schema";
 import { BoolCast, Cast, NumCast, StrCast } from "../../fields/Types";
 import { TraceMobx } from "../../fields/util";
 import { OmitKeys, returnFalse, setupMoveUpEvents } from "../../Utils";
@@ -46,11 +44,8 @@ import { FieldView, FieldViewProps } from "./nodes/FieldView";
 import { FormattedTextBox } from "./nodes/formattedText/FormattedTextBox";
 import Color = require("color");
 
-type InkDocument = makeInterface<[typeof documentSchema]>;
-const InkDocument = makeInterface(documentSchema);
-
 @observer
-export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps, InkDocument>(InkDocument) {
+export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps>() {
     static readonly MaskDim = 50000; // choose a really big number to make sure mask fits over container (which in theory can be arbitrarily big)
     public static LayoutString(fieldStr: string) { return FieldView.LayoutString(InkingStroke, fieldStr); }
     public static IsClosed(inkData: InkData) {
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index 7553c8118..8560ccb29 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -1,13 +1,15 @@
-import { MainView } from "./MainView";
-import { Docs } from "../documents/Documents";
-import { CurrentUserUtils } from "../util/CurrentUserUtils";
-import * as ReactDOM from 'react-dom';
+// if ((module as any).hot) {
+//     (module as any).hot.accept();
+// }
+
 import * as React from 'react';
-import { DocServer } from "../DocServer";
+import * as ReactDOM from 'react-dom';
 import { AssignAllExtensions } from "../../extensions/General/Extensions";
-import { Networking } from "../Network";
-import { CollectionView } from "./collections/CollectionView";
+import { Docs } from "../documents/Documents";
+import { CurrentUserUtils } from "../util/CurrentUserUtils";
 import { LinkManager } from "../util/LinkManager";
+import { CollectionView } from "./collections/CollectionView";
+import { MainView } from "./MainView";
 
 AssignAllExtensions();
 
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 7f1dd0c7d..85f75637e 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -44,7 +44,6 @@ import { GestureOverlay } from './GestureOverlay';
 import { DASHBOARD_SELECTOR_HEIGHT, LEFT_MENU_WIDTH } from './global/globalCssVariables.scss';
 import { Colors } from './global/globalEnums';
 import { KeyManager } from './GlobalKeyHandler';
-import { InkStrokeProperties } from './InkStrokeProperties';
 import { LightboxView } from './LightboxView';
 import { LinkMenu } from './linking/LinkMenu';
 import "./MainView.scss";
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index 8ee673115..a2f23ee09 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -7,7 +7,7 @@ import { Doc, Opt, StrListCast } from "../../fields/Doc";
 import { List } from '../../fields/List';
 import { listSpec } from '../../fields/Schema';
 import { BoolCast, Cast, NumCast, StrCast } from "../../fields/Types";
-import { lightOrDark, DashColor } from '../../Utils';
+import { DashColor, lightOrDark } from '../../Utils';
 import { DocumentType } from '../documents/DocumentTypes';
 import { CurrentUserUtils } from '../util/CurrentUserUtils';
 import { ColorScheme } from '../util/SettingsManager';
diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx
index ff3f92364..4425ccac2 100644
--- a/src/client/views/TemplateMenu.tsx
+++ b/src/client/views/TemplateMenu.tsx
@@ -5,7 +5,7 @@ import { List } from "../../fields/List";
 import { ScriptField } from "../../fields/ScriptField";
 import { Cast, StrCast } from "../../fields/Types";
 import { TraceMobx } from "../../fields/util";
-import { emptyFunction, emptyPath, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue } from "../../Utils";
+import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue } from "../../Utils";
 import { Docs, DocUtils } from "../documents/Documents";
 import { Scripting } from "../util/Scripting";
 import { Transform } from "../util/Transform";
diff --git a/src/client/views/animationtimeline/Keyframe.tsx b/src/client/views/animationtimeline/Keyframe.tsx
index 82b0218bf..92d3e2bed 100644
--- a/src/client/views/animationtimeline/Keyframe.tsx
+++ b/src/client/views/animationtimeline/Keyframe.tsx
@@ -1,18 +1,17 @@
-import * as React from "react";
-import "./Keyframe.scss";
-import "./Timeline.scss";
-import "../global/globalCssVariables.scss";
+import { action, computed, observable, runInAction } from "mobx";
 import { observer } from "mobx-react";
-import { observable, reaction, action, IReactionDisposer, observe, computed, runInAction, trace } from "mobx";
-import { Doc, DocListCast, DocListCastAsync, Opt } from "../../../fields/Doc";
-import { Cast, NumCast } from "../../../fields/Types";
+import * as React from "react";
+import { Doc, DocListCast, Opt } from "../../../fields/Doc";
 import { List } from "../../../fields/List";
-import { createSchema, defaultSpec, makeInterface, listSpec } from "../../../fields/Schema";
-import { Transform } from "../../util/Transform";
-import { TimelineMenu } from "./TimelineMenu";
+import { createSchema, defaultSpec, listSpec, makeInterface } from "../../../fields/Schema";
+import { Cast, NumCast } from "../../../fields/Types";
 import { Docs } from "../../documents/Documents";
+import { Transform } from "../../util/Transform";
 import { CollectionDockingView } from "../collections/CollectionDockingView";
-import { emptyPath } from "../../../Utils";
+import "../global/globalCssVariables.scss";
+import "./Keyframe.scss";
+import "./Timeline.scss";
+import { TimelineMenu } from "./TimelineMenu";
 
 
 /**
diff --git a/src/client/views/collections/CollectionCarousel3DView.tsx b/src/client/views/collections/CollectionCarousel3DView.tsx
index 3bdc427d6..01f41869e 100644
--- a/src/client/views/collections/CollectionCarousel3DView.tsx
+++ b/src/client/views/collections/CollectionCarousel3DView.tsx
@@ -3,23 +3,17 @@ import { computed } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
 import { Doc } from '../../../fields/Doc';
-import { collectionSchema, documentSchema } from '../../../fields/documentSchemas';
 import { Id } from '../../../fields/FieldSymbols';
-import { makeInterface } from '../../../fields/Schema';
-import { ScriptField } from '../../../fields/ScriptField';
 import { NumCast, ScriptCast, StrCast } from '../../../fields/Types';
 import { OmitKeys, returnFalse, Utils } from '../../../Utils';
 import { DragManager } from '../../util/DragManager';
 import { DocumentView } from '../nodes/DocumentView';
+import { StyleProp } from '../StyleProvider';
 import "./CollectionCarousel3DView.scss";
 import { CollectionSubView } from './CollectionSubView';
-import { StyleProp } from '../StyleProvider';
-
-type Carousel3DDocument = makeInterface<[typeof documentSchema, typeof collectionSchema]>;
-const Carousel3DDocument = makeInterface(documentSchema, collectionSchema);
 
 @observer
-export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocument) {
+export class CollectionCarousel3DView extends CollectionSubView() {
     @computed get scrollSpeed() {
         return this.layoutDoc._autoScrollSpeed ? NumCast(this.layoutDoc._autoScrollSpeed) : 1000; //default scroll speed
     }
diff --git a/src/client/views/collections/CollectionCarouselView.tsx b/src/client/views/collections/CollectionCarouselView.tsx
index 733c07031..467c2893f 100644
--- a/src/client/views/collections/CollectionCarouselView.tsx
+++ b/src/client/views/collections/CollectionCarouselView.tsx
@@ -3,8 +3,6 @@ import { computed } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
 import { Doc, Opt } from '../../../fields/Doc';
-import { collectionSchema, documentSchema } from '../../../fields/documentSchemas';
-import { makeInterface } from '../../../fields/Schema';
 import { NumCast, ScriptCast, StrCast } from '../../../fields/Types';
 import { OmitKeys, returnFalse } from '../../../Utils';
 import { DragManager } from '../../util/DragManager';
@@ -12,13 +10,10 @@ import { DocumentView, DocumentViewProps } from '../nodes/DocumentView';
 import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox';
 import { StyleProp } from '../StyleProvider';
 import "./CollectionCarouselView.scss";
-import { CollectionSubView, SubCollectionViewProps } from './CollectionSubView';
-
-type CarouselDocument = makeInterface<[typeof documentSchema, typeof collectionSchema]>;
-const CarouselDocument = makeInterface(documentSchema, collectionSchema);
+import { CollectionSubView } from './CollectionSubView';
 
 @observer
-export class CollectionCarouselView extends CollectionSubView(CarouselDocument) {
+export class CollectionCarouselView extends CollectionSubView() {
     private _dropDisposer?: DragManager.DragDropDisposer;
 
     componentWillUnmount() { this._dropDisposer?.(); }
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index f543d924d..f6740ac33 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -4,31 +4,31 @@ import { action, IReactionDisposer, observable, reaction, runInAction } from "mo
 import { observer } from "mobx-react";
 import * as ReactDOM from 'react-dom';
 import * as GoldenLayout from "../../../client/goldenLayout";
-import { Doc, DocListCast, Opt, DocListCastAsync, DataSym } from "../../../fields/Doc";
+import { DataSym, Doc, DocListCast, DocListCastAsync, Opt } from "../../../fields/Doc";
 import { Id } from '../../../fields/FieldSymbols';
 import { InkTool } from '../../../fields/InkField';
 import { List } from '../../../fields/List';
+import { listSpec } from '../../../fields/Schema';
 import { Cast, NumCast, StrCast } from "../../../fields/Types";
+import { inheritParentAcls } from '../../../fields/util';
 import { DocServer } from "../../DocServer";
 import { Docs } from '../../documents/Documents';
+import { DocumentType } from '../../documents/DocumentTypes';
 import { CurrentUserUtils } from '../../util/CurrentUserUtils';
 import { DragManager } from "../../util/DragManager";
 import { InteractionUtils } from '../../util/InteractionUtils';
 import { Scripting } from '../../util/Scripting';
 import { undoBatch, UndoManager } from "../../util/UndoManager";
+import { LightboxView } from '../LightboxView';
 import "./CollectionDockingView.scss";
 import { CollectionSubView, SubCollectionViewProps } from "./CollectionSubView";
 import { CollectionViewType } from './CollectionView';
 import { TabDocView } from './TabDocView';
 import React = require("react");
-import { DocumentType } from '../../documents/DocumentTypes';
-import { listSpec } from '../../../fields/Schema';
-import { LightboxView } from '../LightboxView';
-import { inheritParentAcls } from '../../../fields/util';
 const _global = (window /* browser */ || global /* node */) as any;
 
 @observer
-export class CollectionDockingView extends CollectionSubView(doc => doc) {
+export class CollectionDockingView extends CollectionSubView() {
     @observable public static Instance: CollectionDockingView;
     public static makeDocumentConfig(document: Doc, panelName?: string, width?: number) {
         return {
diff --git a/src/client/views/collections/CollectionPileView.tsx b/src/client/views/collections/CollectionPileView.tsx
index bc1407c53..0a336c544 100644
--- a/src/client/views/collections/CollectionPileView.tsx
+++ b/src/client/views/collections/CollectionPileView.tsx
@@ -13,7 +13,7 @@ import { CollectionSubView } from "./CollectionSubView";
 import React = require("react");
 
 @observer
-export class CollectionPileView extends CollectionSubView(doc => doc) {
+export class CollectionPileView extends CollectionSubView() {
     _originalChrome: any = "";
     _disposers: { [name: string]: IReactionDisposer } = {};
 
diff --git a/src/client/views/collections/CollectionStackedTimeline.tsx b/src/client/views/collections/CollectionStackedTimeline.tsx
index 89da6692a..a72042df9 100644
--- a/src/client/views/collections/CollectionStackedTimeline.tsx
+++ b/src/client/views/collections/CollectionStackedTimeline.tsx
@@ -5,14 +5,14 @@ import {
     IReactionDisposer,
     observable,
     reaction,
-    runInAction,
+    runInAction
 } from "mobx";
 import { observer } from "mobx-react";
 import { computedFn } from "mobx-utils";
 import { Doc, DocListCast } from "../../../fields/Doc";
 import { Id } from "../../../fields/FieldSymbols";
 import { List } from "../../../fields/List";
-import { listSpec, makeInterface } from "../../../fields/Schema";
+import { listSpec } from "../../../fields/Schema";
 import { ComputedField, ScriptField } from "../../../fields/ScriptField";
 import { Cast, NumCast } from "../../../fields/Types";
 import {
@@ -22,33 +22,30 @@ import {
     returnFalse,
     returnOne,
     setupMoveUpEvents,
-    StopEvent,
-    returnTrue,
+    StopEvent
 } from "../../../Utils";
 import { Docs } from "../../documents/Documents";
+import { DocumentManager } from "../../util/DocumentManager";
+import { DragManager } from "../../util/DragManager";
 import { LinkManager } from "../../util/LinkManager";
 import { Scripting } from "../../util/Scripting";
 import { SelectionManager } from "../../util/SelectionManager";
+import { SnappingManager } from "../../util/SnappingManager";
 import { Transform } from "../../util/Transform";
 import { undoBatch } from "../../util/UndoManager";
 import { AudioWaveform } from "../AudioWaveform";
 import { CollectionSubView } from "../collections/CollectionSubView";
+import { Colors } from "../global/globalEnums";
 import { LightboxView } from "../LightboxView";
 import {
     DocAfterFocusFunc,
     DocFocusFunc,
     DocumentView,
-    DocumentViewProps,
+    DocumentViewProps
 } from "../nodes/DocumentView";
 import { LabelBox } from "../nodes/LabelBox";
 import "./CollectionStackedTimeline.scss";
-import { Colors } from "../global/globalEnums";
-import { DocumentManager } from "../../util/DocumentManager";
-import { SnappingManager } from "../../util/SnappingManager";
-import { DragManager } from "../../util/DragManager";
 
-type PanZoomDocument = makeInterface<[]>;
-const PanZoomDocument = makeInterface();
 export type CollectionStackedTimelineProps = {
     duration: number;
     Play: () => void;
@@ -70,10 +67,7 @@ export type CollectionStackedTimelineProps = {
 };
 
 @observer
-export class CollectionStackedTimeline extends CollectionSubView<
-    PanZoomDocument,
-    CollectionStackedTimelineProps
->(PanZoomDocument) {
+export class CollectionStackedTimeline extends CollectionSubView<CollectionStackedTimelineProps>() {
     @observable static SelectingRegion: CollectionStackedTimeline | undefined =
         undefined;
     static RangeScript: ScriptField;
@@ -851,21 +845,21 @@ class StackedTimelineAnchor extends React.Component<StackedTimelineAnchorProps>
                 {inner.view}
                 {!inner.anchor.view ||
                     !SelectionManager.IsSelected(inner.anchor.view) ? null : (
-                        <>
-                            <div
-                                key="left"
-                                className="collectionStackedTimeline-left-resizer"
-                                onPointerDown={(e) => this.onAnchorDown(e, this.props.mark, true)}
-                            />
-                            <div
-                                key="right"
-                                className="collectionStackedTimeline-resizer"
-                                onPointerDown={(e) =>
-                                    this.onAnchorDown(e, this.props.mark, false)
-                                }
-                            />
-                        </>
-                    )}
+                    <>
+                        <div
+                            key="left"
+                            className="collectionStackedTimeline-left-resizer"
+                            onPointerDown={(e) => this.onAnchorDown(e, this.props.mark, true)}
+                        />
+                        <div
+                            key="right"
+                            className="collectionStackedTimeline-resizer"
+                            onPointerDown={(e) =>
+                                this.onAnchorDown(e, this.props.mark, false)
+                            }
+                        />
+                    </>
+                )}
             </>
         );
     }
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index cdc680a08..8634ea139 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -3,16 +3,15 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
 import { CursorProperty } from "csstype";
 import { action, computed, IReactionDisposer, observable, reaction, runInAction } from "mobx";
 import { observer } from "mobx-react";
-import { DataSym, Doc, HeightSym, Opt, WidthSym, DocListCast } from "../../../fields/Doc";
-import { collectionSchema, documentSchema } from "../../../fields/documentSchemas";
+import { DataSym, Doc, HeightSym, Opt, WidthSym } from "../../../fields/Doc";
 import { Id } from "../../../fields/FieldSymbols";
 import { List } from "../../../fields/List";
-import { listSpec, makeInterface } from "../../../fields/Schema";
+import { listSpec } from "../../../fields/Schema";
 import { SchemaHeaderField } from "../../../fields/SchemaHeaderField";
 import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from "../../../fields/Types";
 import { TraceMobx } from "../../../fields/util";
-import { emptyFunction, returnFalse, returnZero, setupMoveUpEvents, smoothScroll, Utils, returnTrue, returnEmptyDoclist, returnEmptyFilter } from "../../../Utils";
-import { DocUtils, Docs } from "../../documents/Documents";
+import { emptyFunction, returnEmptyDoclist, returnFalse, returnTrue, returnZero, setupMoveUpEvents, smoothScroll, Utils } from "../../../Utils";
+import { Docs, DocUtils } from "../../documents/Documents";
 import { DragManager, dropActionType } from "../../util/DragManager";
 import { SnappingManager } from "../../util/SnappingManager";
 import { Transform } from "../../util/Transform";
@@ -23,18 +22,14 @@ import { EditableView } from "../EditableView";
 import { LightboxView } from "../LightboxView";
 import { CollectionFreeFormDocumentView } from "../nodes/CollectionFreeFormDocumentView";
 import { DocFocusOptions, DocumentView, DocumentViewProps, ViewAdjustment } from "../nodes/DocumentView";
-import { StyleProp, DefaultStyleProvider } from "../StyleProvider";
+import { StyleProp } from "../StyleProvider";
 import { CollectionMasonryViewFieldRow } from "./CollectionMasonryViewFieldRow";
 import "./CollectionStackingView.scss";
 import { CollectionStackingViewFieldColumn } from "./CollectionStackingViewFieldColumn";
 import { CollectionSubView } from "./CollectionSubView";
 import { CollectionViewType } from "./CollectionView";
-import { FontIconBox } from "../nodes/button/FontIconBox";
-import { CurrentUserUtils } from "../../util/CurrentUserUtils";
 const _global = (window /* browser */ || global /* node */) as any;
 
-type StackingDocument = makeInterface<[typeof collectionSchema, typeof documentSchema]>;
-const StackingDocument = makeInterface(collectionSchema, documentSchema);
 
 export type collectionStackingViewProps = {
     chromeHidden?: boolean;
@@ -44,7 +39,7 @@ export type collectionStackingViewProps = {
 };
 
 @observer
-export class CollectionStackingView extends CollectionSubView<StackingDocument, Partial<collectionStackingViewProps>>(StackingDocument) {
+export class CollectionStackingView extends CollectionSubView<Partial<collectionStackingViewProps>>() {
     _masonryGridRef: HTMLDivElement | null = null;
     _draggerRef = React.createRef<HTMLDivElement>();
     _pivotFieldDisposer?: IReactionDisposer;
diff --git a/src/client/views/collections/CollectionStaffView.tsx b/src/client/views/collections/CollectionStaffView.tsx
index c5c3f96e8..c025e94a8 100644
--- a/src/client/views/collections/CollectionStaffView.tsx
+++ b/src/client/views/collections/CollectionStaffView.tsx
@@ -6,7 +6,7 @@ import "./CollectionStaffView.scss";
 import { observer } from "mobx-react";
 
 @observer
-export class CollectionStaffView extends CollectionSubView(doc => doc) {
+export class CollectionStaffView extends CollectionSubView() {
     private _reactionDisposer: IReactionDisposer | undefined;
     @observable private _staves = NumCast(this.props.Document.staves);
 
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index b7e0fecee..42e157396 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -25,8 +25,8 @@ export interface SubCollectionViewProps extends CollectionViewProps {
     isAnyChildContentActive: () => boolean;
 }
 
-export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?: X) {
-    class CollectionSubView extends DocComponent<X & SubCollectionViewProps, T>(schemaCtor) {
+export function CollectionSubView<X>(moreProps?: X) {
+    class CollectionSubView extends DocComponent<X & SubCollectionViewProps>() {
         private dropDisposer?: DragManager.DragDropDisposer;
         private gestureDisposer?: GestureUtils.GestureEventDisposer;
         protected _multiTouchDisposer?: InteractionUtils.MultiTouchEventDisposer;
diff --git a/src/client/views/collections/CollectionTimeView.tsx b/src/client/views/collections/CollectionTimeView.tsx
index 292dfd77c..be48eac23 100644
--- a/src/client/views/collections/CollectionTimeView.tsx
+++ b/src/client/views/collections/CollectionTimeView.tsx
@@ -1,15 +1,15 @@
 import { toUpper } from "lodash";
 import { action, computed, observable, runInAction } from "mobx";
 import { observer } from "mobx-react";
-import { Doc, DocCastAsync, Opt, StrListCast } from "../../../fields/Doc";
+import { Doc, Opt, StrListCast } from "../../../fields/Doc";
 import { List } from "../../../fields/List";
 import { ObjectField } from "../../../fields/ObjectField";
 import { RichTextField } from "../../../fields/RichTextField";
 import { listSpec } from "../../../fields/Schema";
 import { ComputedField, ScriptField } from "../../../fields/ScriptField";
 import { Cast, NumCast, StrCast } from "../../../fields/Types";
-import { emptyFunction, returnFalse, returnTrue, setupMoveUpEvents, returnEmptyString } from "../../../Utils";
-import { Docs, DocUtils } from "../../documents/Documents";
+import { emptyFunction, returnEmptyString, returnFalse, returnTrue, setupMoveUpEvents } from "../../../Utils";
+import { Docs } from "../../documents/Documents";
 import { DocumentManager } from "../../util/DocumentManager";
 import { Scripting } from "../../util/Scripting";
 import { ContextMenu } from "../ContextMenu";
@@ -20,13 +20,10 @@ import { ViewDefBounds } from "./collectionFreeForm/CollectionFreeFormLayoutEngi
 import { CollectionFreeFormView } from "./collectionFreeForm/CollectionFreeFormView";
 import { CollectionSubView } from "./CollectionSubView";
 import "./CollectionTimeView.scss";
-const higflyout = require("@hig/flyout");
-export const { anchorPoints } = higflyout;
-export const Flyout = higflyout.default;
 import React = require("react");
 
 @observer
-export class CollectionTimeView extends CollectionSubView(doc => doc) {
+export class CollectionTimeView extends CollectionSubView() {
     _changing = false;
     @observable _layoutEngine = "pivot";
     @observable _collapsed: boolean = false;
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index ea077ea40..e84517f40 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -3,11 +3,11 @@ import { observer } from "mobx-react";
 import { DataSym, Doc, DocListCast, HeightSym, Opt, StrListCast, WidthSym } from '../../../fields/Doc';
 import { Id } from '../../../fields/FieldSymbols';
 import { InkTool } from '../../../fields/InkField';
-import { Document, listSpec } from '../../../fields/Schema';
+import { listSpec } from '../../../fields/Schema';
 import { ScriptField } from '../../../fields/ScriptField';
 import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../fields/Types';
 import { TraceMobx } from '../../../fields/util';
-import { emptyFunction, OmitKeys, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, returnOne } from '../../../Utils';
+import { emptyFunction, OmitKeys, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnOne, returnTrue } from '../../../Utils';
 import { DocUtils } from '../../documents/Documents';
 import { CurrentUserUtils } from '../../util/CurrentUserUtils';
 import { DocumentManager } from '../../util/DocumentManager';
@@ -40,7 +40,7 @@ export type collectionTreeViewProps = {
 };
 
 @observer
-export class CollectionTreeView extends CollectionSubView<Document, Partial<collectionTreeViewProps>>(Document) {
+export class CollectionTreeView extends CollectionSubView<Partial<collectionTreeViewProps>>() {
     private _treedropDisposer?: DragManager.DragDropDisposer;
     private _mainEle?: HTMLDivElement;
     private _titleRef?: HTMLDivElement | HTMLInputElement | null;
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 681a15e3d..ee2c28b5f 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -1,15 +1,14 @@
-import { computed, observable, runInAction, action } from 'mobx';
+import { computed, observable, runInAction } from 'mobx';
 import { observer } from "mobx-react";
 import * as React from 'react';
 import 'react-image-lightbox-with-rotate/style.css'; // This only needs to be imported once in your app
-import { Doc, DocListCast, StrListCast } from '../../../fields/Doc';
-import { documentSchema } from '../../../fields/documentSchemas';
+import { Doc, DocListCast } from '../../../fields/Doc';
 import { Id } from '../../../fields/FieldSymbols';
 import { ObjectField } from '../../../fields/ObjectField';
-import { makeInterface } from '../../../fields/Schema';
 import { ScriptField } from '../../../fields/ScriptField';
 import { Cast, ScriptCast, StrCast } from '../../../fields/Types';
 import { TraceMobx } from '../../../fields/util';
+import { returnEmptyString } from '../../../Utils';
 import { DocUtils } from '../../documents/Documents';
 import { BranchCreate, BranchTask } from '../../documents/Gitlike';
 import { CurrentUserUtils } from '../../util/CurrentUserUtils';
@@ -33,10 +32,7 @@ import { CollectionStackingView } from './CollectionStackingView';
 import { SubCollectionViewProps } from './CollectionSubView';
 import { CollectionTimeView } from './CollectionTimeView';
 import { CollectionTreeView } from "./CollectionTreeView";
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import './CollectionView.scss';
-import { returnEmptyString } from '../../../Utils';
-import { InkTool } from '../../../fields/InkField';
 export const COLLECTION_BORDER_WIDTH = 2;
 const path = require('path');
 
@@ -84,11 +80,8 @@ export interface CollectionViewProps extends FieldViewProps {
     childClickScript?: ScriptField;
     childDoubleClickScript?: ScriptField;
 }
-
-type CollectionDocument = makeInterface<[typeof documentSchema]>;
-const CollectionDocument = makeInterface(documentSchema);
 @observer
-export class CollectionView extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps & CollectionViewProps, CollectionDocument>(CollectionDocument) {
+export class CollectionView extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps & CollectionViewProps>() {
     public static LayoutString(fieldStr: string) { return FieldView.LayoutString(CollectionView, fieldStr); }
 
     @observable private static _safeMode = false;
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 3d664e146..e2ea81392 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1,16 +1,15 @@
 import { Bezier } from "bezier-js";
-import { action, computed, IReactionDisposer, observable, reaction, runInAction, trace } from "mobx";
+import { action, computed, IReactionDisposer, observable, reaction, runInAction } from "mobx";
 import { observer } from "mobx-react";
 import { computedFn } from "mobx-utils";
 import { DateField } from "../../../../fields/DateField";
 import { Doc, HeightSym, Opt, StrListCast, WidthSym } from "../../../../fields/Doc";
-import { collectionSchema, documentSchema } from "../../../../fields/documentSchemas";
 import { Id } from "../../../../fields/FieldSymbols";
 import { InkData, InkField, InkTool, PointData, Segment } from "../../../../fields/InkField";
 import { List } from "../../../../fields/List";
 import { ObjectField } from "../../../../fields/ObjectField";
 import { RichTextField } from "../../../../fields/RichTextField";
-import { createSchema, listSpec, makeInterface } from "../../../../fields/Schema";
+import { createSchema, listSpec } from "../../../../fields/Schema";
 import { ScriptField } from "../../../../fields/ScriptField";
 import { BoolCast, Cast, FieldValue, NumCast, ScriptCast, StrCast } from "../../../../fields/Types";
 import { TraceMobx } from "../../../../fields/util";
@@ -41,7 +40,6 @@ import { LightboxView } from "../../LightboxView";
 import { CollectionFreeFormDocumentView } from "../../nodes/CollectionFreeFormDocumentView";
 import { DocFocusOptions, DocumentView, DocumentViewProps, ViewAdjustment, ViewSpecPrefix } from "../../nodes/DocumentView";
 import { FormattedTextBox } from "../../nodes/formattedText/FormattedTextBox";
-import { pageSchema } from "../../nodes/ImageBox";
 import { PresBox } from "../../nodes/trails/PresBox";
 import { StyleLayers, StyleProp } from "../../StyleProvider";
 import { CollectionDockingView } from "../CollectionDockingView";
@@ -67,8 +65,6 @@ export const panZoomSchema = createSchema({
     scrollHeight: "number"    // this will be set when the collection is an annotation overlay for a PDF/Webpage
 });
 
-type PanZoomDocument = makeInterface<[typeof panZoomSchema, typeof collectionSchema, typeof documentSchema, typeof pageSchema]>;
-const PanZoomDocument = makeInterface(panZoomSchema, collectionSchema, documentSchema, pageSchema);
 export type collectionFreeformViewProps = {
     annotationLayerHostsContent?: boolean; // whether to force scaling of content (needed by ImageBox)
     viewDefDivClick?: ScriptField;
@@ -81,7 +77,7 @@ export type collectionFreeformViewProps = {
 };
 
 @observer
-export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, Partial<collectionFreeformViewProps>>(PanZoomDocument) {
+export class CollectionFreeFormView extends CollectionSubView<Partial<collectionFreeformViewProps>>() {
     public get displayName() { return "CollectionFreeFormView(" + this.props.Document.title?.toString() + ")"; } // this makes mobx trace() statements more descriptive
 
     private _lastNudge: any;
@@ -207,7 +203,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
                 }
             }
             if (this.Document._currentFrame !== undefined && !this.props.isAnnotationOverlay) {
-                CollectionFreeFormDocumentView.setupKeyframes(newBoxes, this.Document._currentFrame, true);
+                CollectionFreeFormDocumentView.setupKeyframes(newBoxes, NumCast(this.Document._currentFrame), true);
             }
         }
         return retVal;
@@ -237,12 +233,12 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
             const d = docDragData.droppedDocuments[i];
             const layoutDoc = Doc.Layout(d);
             if (this.Document._currentFrame !== undefined) {
-                CollectionFreeFormDocumentView.setupKeyframes([d], this.Document._currentFrame, false);
+                CollectionFreeFormDocumentView.setupKeyframes([d], NumCast(this.Document._currentFrame), false);
                 const vals = CollectionFreeFormDocumentView.getValues(d, NumCast(d.activeFrame, 1000));
                 vals.x = x + (vals.x || 0) - dropPos[0];
                 vals.y = y + (vals.y || 0) - dropPos[1];
                 vals._scrollTop = this.Document.editScrollProgressivize ? vals._scrollTop : undefined;
-                CollectionFreeFormDocumentView.setValues(this.Document._currentFrame, d, vals);
+                CollectionFreeFormDocumentView.setValues(NumCast(this.Document._currentFrame), d, vals);
             } else {
                 d.x = x + NumCast(d.x) - dropPos[0];
                 d.y = y + NumCast(d.y) - dropPos[1];
@@ -637,7 +633,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
     @action
     pan = (e: PointerEvent | React.Touch | { clientX: number, clientY: number }): void => {
         const [dx, dy] = this.getTransform().transformDirection(e.clientX - this._lastX, e.clientY - this._lastY);
-        this.setPan((this.Document._panX || 0) - dx, (this.Document._panY || 0) - dy, 0, true);
+        this.setPan(NumCast(this.Document._panX) - dx, NumCast(this.Document._panY) - dy, 0, true);
         this._lastX = e.clientX;
         this._lastY = e.clientY;
     }
@@ -969,10 +965,10 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
                 .filter(({ pos, size }) => pos && size).map(({ pos, size }) => ({ pos: pos!, size: size! }));
             if (measuredDocs.length) {
                 const ranges = measuredDocs.reduce(({ xrange, yrange }, { pos, size }) =>  // computes range of content
-                    ({
-                        xrange: { min: Math.min(xrange.min, pos.x), max: Math.max(xrange.max, pos.x + (size.width || 0)) },
-                        yrange: { min: Math.min(yrange.min, pos.y), max: Math.max(yrange.max, pos.y + (size.height || 0)) }
-                    })
+                ({
+                    xrange: { min: Math.min(xrange.min, pos.x), max: Math.max(xrange.max, pos.x + (size.width || 0)) },
+                    yrange: { min: Math.min(yrange.min, pos.y), max: Math.max(yrange.max, pos.y + (size.height || 0)) }
+                })
                     , {
                         xrange: { min: Number.MAX_VALUE, max: -Number.MAX_VALUE },
                         yrange: { min: Number.MAX_VALUE, max: -Number.MAX_VALUE }
@@ -1047,11 +1043,11 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
         if (state.type === "doc" && this.Document._panX !== undefined && this.Document._panY !== undefined) {
             const init = state.initializers![this.Document[Id]];
             if (!init) {
-                state.initializers![this.Document[Id]] = { panX: this.Document._panX, panY: this.Document._panY };
+                state.initializers![this.Document[Id]] = { panX: NumCast(this.Document._panX), panY: NumCast(this.Document._panY) };
                 HistoryUtil.pushState(state);
             } else if (init.panX !== this.Document._panX || init.panY !== this.Document._panY) {
-                init.panX = this.Document._panX;
-                init.panY = this.Document._panY;
+                init.panX = NumCast(this.Document._panX);
+                init.panY = NumCast(this.Document._panY);
                 HistoryUtil.pushState(state);
             }
         }
@@ -1217,7 +1213,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
         const { z, color, zIndex } = params.pair.layout;
         const { x, y, opacity } = this.Document._currentFrame === undefined ?
             { x: params.pair.layout.x, y: params.pair.layout.y, opacity: this.props.styleProvider?.(params.pair.layout, this.props, StyleProp.Opacity) } :
-            CollectionFreeFormDocumentView.getValues(params.pair.layout, this.Document._currentFrame);
+            CollectionFreeFormDocumentView.getValues(params.pair.layout, NumCast(this.Document._currentFrame));
         return {
             x: NumCast(x), y: NumCast(y), z: Cast(z, "number"), color: StrCast(color), zIndex: Cast(zIndex, "number"),
             transition: StrCast(layoutDoc.dataTransition), opacity: this._keyframeEditing ? 1 : Cast(opacity, "number", null),
@@ -1463,8 +1459,8 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
         const height = Math.max(...docs.map(doc => NumCast(doc._height))) + 20;
         const dim = Math.ceil(Math.sqrt(docs.length));
         docs.forEach((doc, i) => {
-            doc.x = (this.Document._panX || 0) + (i % dim) * width - width * dim / 2;
-            doc.y = (this.Document._panY || 0) + Math.floor(i / dim) * height - height * dim / 2;
+            doc.x = NumCast(this.Document._panX) + (i % dim) * width - width * dim / 2;
+            doc.y = NumCast(this.Document._panY) + Math.floor(i / dim) * height - height * dim / 2;
         });
     }
 
@@ -1593,7 +1589,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
     }
 
     @computed get placeholder() {
-        return <div className="collectionfreeformview-placeholder" style={{ background: this.Document.backgroundColor }}>
+        return <div className="collectionfreeformview-placeholder" style={{ background: StrCast(this.Document.backgroundColor) }}>
             <span className="collectionfreeformview-placeholderSpan">{this.props.Document.title?.toString()}</span>
         </div>;
     }
@@ -1677,7 +1673,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
                     this.backgroundEvents ? "all" : this.props.pointerEvents as any,
                 transform: `scale(${this.contentScaling || 1})`,
                 width: `${100 / (this.contentScaling || 1)}%`,
-                height: this.isAnnotationOverlay && this.Document.scrollHeight ? this.Document.scrollHeight : `${100 / (this.contentScaling || 1)}%`// : this.isAnnotationOverlay ? (this.Document.scrollHeight ? this.Document.scrollHeight : "100%") : this.props.PanelHeight()
+                height: this.isAnnotationOverlay && this.Document.scrollHeight ? NumCast(this.Document.scrollHeight) : `${100 / (this.contentScaling || 1)}%`// : this.isAnnotationOverlay ? (this.Document.scrollHeight ? this.Document.scrollHeight : "100%") : this.props.PanelHeight()
             }}>
             {this._firstRender || (this.Document._freeformLOD && !this.props.isContentActive() && !this.props.isAnnotationOverlay && this.props.renderDepth > 0) ?
                 this.placeholder : this.marqueeView}
diff --git a/src/client/views/collections/collectionGrid/CollectionGridView.tsx b/src/client/views/collections/collectionGrid/CollectionGridView.tsx
index b0030471d..58ea7410d 100644
--- a/src/client/views/collections/collectionGrid/CollectionGridView.tsx
+++ b/src/client/views/collections/collectionGrid/CollectionGridView.tsx
@@ -2,9 +2,7 @@ import { action, computed, Lambda, observable, reaction } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from "react";
 import { Doc, Opt } from '../../../../fields/Doc';
-import { documentSchema } from '../../../../fields/documentSchemas';
 import { Id } from '../../../../fields/FieldSymbols';
-import { makeInterface } from '../../../../fields/Schema';
 import { BoolCast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types';
 import { emptyFunction, OmitKeys, returnFalse, setupMoveUpEvents } from '../../../../Utils';
 import { Docs } from '../../../documents/Documents';
@@ -20,11 +18,8 @@ import { CollectionSubView } from '../CollectionSubView';
 import "./CollectionGridView.scss";
 import Grid, { Layout } from "./Grid";
 
-type GridSchema = makeInterface<[typeof documentSchema]>;
-const GridSchema = makeInterface(documentSchema);
-
 @observer
-export class CollectionGridView extends CollectionSubView(GridSchema) {
+export class CollectionGridView extends CollectionSubView() {
     private _containerRef: React.RefObject<HTMLDivElement> = React.createRef();
     private _changeListenerDisposer: Opt<Lambda>; // listens for changes in this.childLayoutPairs
     private _resetListenerDisposer: Opt<Lambda>; // listens for when the reset button is clicked
diff --git a/src/client/views/collections/collectionLinear/CollectionLinearView.tsx b/src/client/views/collections/collectionLinear/CollectionLinearView.tsx
index 9466d8753..44762dbe3 100644
--- a/src/client/views/collections/collectionLinear/CollectionLinearView.tsx
+++ b/src/client/views/collections/collectionLinear/CollectionLinearView.tsx
@@ -4,9 +4,7 @@ import { action, IReactionDisposer, observable, reaction, runInAction } from 'mo
 import { observer } from 'mobx-react';
 import * as React from 'react';
 import { Doc, HeightSym, Opt, WidthSym } from '../../../../fields/Doc';
-import { documentSchema } from '../../../../fields/documentSchemas';
 import { Id } from '../../../../fields/FieldSymbols';
-import { makeInterface } from '../../../../fields/Schema';
 import { BoolCast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types';
 import { emptyFunction, returnEmptyDoclist, returnTrue, Utils } from '../../../../Utils';
 import { DragManager } from '../../../util/DragManager';
@@ -21,9 +19,6 @@ import { CollectionViewType } from '../CollectionView';
 import "./CollectionLinearView.scss";
 
 
-type LinearDocument = makeInterface<[typeof documentSchema,]>;
-const LinearDocument = makeInterface(documentSchema);
-
 /**
  * CollectionLinearView is the class for rendering the horizontal collection 
  * of documents, it useful for horizontal menus. It can either be expandable
@@ -33,7 +28,7 @@ const LinearDocument = makeInterface(documentSchema);
  * - It is used for the context sensitive toolbar at the top (see contMenuButtons() in CollectionMenu.tsx)
  */
 @observer
-export class CollectionLinearView extends CollectionSubView(LinearDocument) {
+export class CollectionLinearView extends CollectionSubView() {
     @observable public addMenuToggle = React.createRef<HTMLInputElement>();
     @observable private _selectedIndex = -1;
     private _dropDisposer?: DragManager.DragDropDisposer;
diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
index b89e28c4f..2bdf92417 100644
--- a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
+++ b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
@@ -2,11 +2,9 @@ import { action, computed } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from "react";
 import { Doc } from '../../../../fields/Doc';
-import { documentSchema } from '../../../../fields/documentSchemas';
 import { List } from '../../../../fields/List';
-import { makeInterface } from '../../../../fields/Schema';
 import { BoolCast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types';
-import { returnFalse, emptyPath, returnEmptyDoclist, emptyFunction } from '../../../../Utils';
+import { emptyFunction, returnFalse } from '../../../../Utils';
 import { DragManager, dropActionType } from '../../../util/DragManager';
 import { Transform } from '../../../util/Transform';
 import { undoBatch } from '../../../util/UndoManager';
@@ -16,8 +14,6 @@ import "./CollectionMulticolumnView.scss";
 import ResizeBar from './MulticolumnResizer';
 import WidthLabel from './MulticolumnWidthLabel';
 
-type MulticolumnDocument = makeInterface<[typeof documentSchema]>;
-const MulticolumnDocument = makeInterface(documentSchema);
 
 interface WidthSpecifier {
     magnitude: number;
@@ -38,7 +34,7 @@ const resolvedUnits = Object.values(DimUnit);
 const resizerWidth = 8;
 
 @observer
-export class CollectionMulticolumnView extends CollectionSubView(MulticolumnDocument) {
+export class CollectionMulticolumnView extends CollectionSubView() {
 
     /**
      * @returns the list of layout documents whose width unit is
diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
index 759ddeeac..7e2b83230 100644
--- a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
+++ b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
@@ -2,11 +2,9 @@ import { action, computed } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from "react";
 import { Doc } from '../../../../fields/Doc';
-import { documentSchema } from '../../../../fields/documentSchemas';
 import { List } from '../../../../fields/List';
-import { makeInterface } from '../../../../fields/Schema';
 import { BoolCast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types';
-import { returnFalse, emptyPath, returnEmptyDoclist, emptyFunction } from '../../../../Utils';
+import { emptyFunction, returnFalse } from '../../../../Utils';
 import { DragManager, dropActionType } from '../../../util/DragManager';
 import { Transform } from '../../../util/Transform';
 import { undoBatch } from '../../../util/UndoManager';
@@ -16,9 +14,6 @@ import "./CollectionMultirowView.scss";
 import HeightLabel from './MultirowHeightLabel';
 import ResizeBar from './MultirowResizer';
 
-type MultirowDocument = makeInterface<[typeof documentSchema]>;
-const MultirowDocument = makeInterface(documentSchema);
-
 interface HeightSpecifier {
     magnitude: number;
     unit: string;
@@ -38,7 +33,7 @@ const resolvedUnits = Object.values(DimUnit);
 const resizerHeight = 8;
 
 @observer
-export class CollectionMultirowView extends CollectionSubView(MultirowDocument) {
+export class CollectionMultirowView extends CollectionSubView() {
 
     /**
      * @returns the list of layout documents whose width unit is
diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaCells.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaCells.tsx
index 6a9b27d02..c2bb3b3ac 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaCells.tsx
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaCells.tsx
@@ -2,6 +2,7 @@ import React = require("react");
 import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
 import { action, computed, observable } from "mobx";
 import { observer } from "mobx-react";
+import { extname } from "path";
 import DatePicker from "react-datepicker";
 import { CellInfo } from "react-table";
 import { DateField } from "../../../../fields/DateField";
@@ -10,9 +11,9 @@ import { Id } from "../../../../fields/FieldSymbols";
 import { List } from "../../../../fields/List";
 import { SchemaHeaderField } from "../../../../fields/SchemaHeaderField";
 import { ComputedField } from "../../../../fields/ScriptField";
-import { BoolCast, Cast, DateCast, FieldValue, NumCast, StrCast } from "../../../../fields/Types";
+import { BoolCast, Cast, DateCast, FieldValue, StrCast } from "../../../../fields/Types";
 import { ImageField } from "../../../../fields/URLField";
-import { Utils, emptyFunction } from "../../../../Utils";
+import { emptyFunction, Utils } from "../../../../Utils";
 import { Docs } from "../../../documents/Documents";
 import { DocumentType } from "../../../documents/DocumentTypes";
 import { DocumentManager } from "../../../util/DocumentManager";
@@ -27,8 +28,8 @@ import { EditableView } from "../../EditableView";
 import { MAX_ROW_HEIGHT } from '../../global/globalCssVariables.scss';
 import { DocumentIconContainer } from "../../nodes/DocumentIcon";
 import { OverlayView } from "../../OverlayView";
-import "./CollectionSchemaView.scss";
 import { CollectionView } from "../CollectionView";
+import "./CollectionSchemaView.scss";
 
 // intialize cell properties
 export interface CellProps {
@@ -492,7 +493,7 @@ export class CollectionSchemaImageCell extends CollectionSchemaCell {
         if (url.href.indexOf(window.location.origin) === -1) return Utils.CorsProxy(url.href); // otherwise, put it through the cors proxy erver
         if (!/\.(png|jpg|jpeg|gif|webp)$/.test(url.href.toLowerCase())) return url.href;//Why is this here — good question
 
-        const ext = "." + url.href.replace(/.*\./, "");//  path.extname(url.href); // the extension of the file
+        const ext = extname(url.href);
         return url.href.replace(ext, "_o" + ext);
     }
 
diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
index 83d339f0a..8b73351d5 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
@@ -46,7 +46,7 @@ const columnTypes: Map<string, ColumnType> = new Map([
 ]);
 
 @observer
-export class CollectionSchemaView extends CollectionSubView(doc => doc) {
+export class CollectionSchemaView extends CollectionSubView() {
     private _previewCont?: HTMLDivElement;
 
     @observable _previewDoc: Doc | undefined = undefined;
diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx
index 02451bdac..93377f1dc 100644
--- a/src/client/views/nodes/AudioBox.tsx
+++ b/src/client/views/nodes/AudioBox.tsx
@@ -6,13 +6,11 @@ import {
     IReactionDisposer,
     observable,
     reaction,
-    runInAction,
+    runInAction
 } from "mobx";
 import { observer } from "mobx-react";
 import { DateField } from "../../../fields/DateField";
 import { Doc, DocListCast, Opt } from "../../../fields/Doc";
-import { documentSchema } from "../../../fields/documentSchemas";
-import { makeInterface } from "../../../fields/Schema";
 import { ComputedField } from "../../../fields/ScriptField";
 import { Cast, NumCast } from "../../../fields/Types";
 import { AudioField, nullAudio } from "../../../fields/URLField";
@@ -26,26 +24,18 @@ import { ContextMenu } from "../ContextMenu";
 import { ContextMenuProps } from "../ContextMenuItem";
 import {
     ViewBoxAnnotatableComponent,
-    ViewBoxAnnotatableProps,
+    ViewBoxAnnotatableProps
 } from "../DocComponent";
+import { Colors } from "../global/globalEnums";
 import "./AudioBox.scss";
 import { FieldView, FieldViewProps } from "./FieldView";
 import { LinkDocPreview } from "./LinkDocPreview";
-import { faLessThan } from "@fortawesome/free-solid-svg-icons";
-import { Colors } from "../global/globalEnums";
 
 declare class MediaRecorder {
     constructor(e: any); // whatever MediaRecorder has
 }
-
-type AudioDocument = makeInterface<[typeof documentSchema]>;
-const AudioDocument = makeInterface(documentSchema);
-
 @observer
-export class AudioBox extends ViewBoxAnnotatableComponent<
-    ViewBoxAnnotatableProps & FieldViewProps,
-    AudioDocument
->(AudioDocument) {
+export class AudioBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps & FieldViewProps>() {
     public static LayoutString(fieldKey: string) {
         return FieldView.LayoutString(AudioBox, fieldKey);
     }
@@ -70,7 +60,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<
     @observable static _scrubTime = 0;
     @observable _markerEnd: number = 0;
     @observable _position: number = 0;
-    @observable _waveHeight: Opt<number> = this.layoutDoc._height;
+    @observable _waveHeight: Opt<number> = NumCast(this.layoutDoc._height);
     @observable _paused: boolean = false;
     @observable _trimming: boolean = false;
     @observable _trimStart: number = NumCast(this.layoutDoc.clipStart) ? NumCast(this.layoutDoc.clipStart) : 0;
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index 235c8accb..c2a526804 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -1,7 +1,6 @@
-import { action, computed, observable, trace } from "mobx";
+import { action, computed, observable } from "mobx";
 import { observer } from "mobx-react";
 import { Doc, Opt } from "../../../fields/Doc";
-import { Document } from "../../../fields/documentSchemas";
 import { List } from "../../../fields/List";
 import { listSpec } from "../../../fields/Schema";
 import { ComputedField } from "../../../fields/ScriptField";
@@ -18,7 +17,6 @@ import { StyleProp } from "../StyleProvider";
 import "./CollectionFreeFormDocumentView.scss";
 import { DocumentView, DocumentViewProps } from "./DocumentView";
 import React = require("react");
-import { Id } from "../../../fields/FieldSymbols";
 
 export interface CollectionFreeFormDocumentViewProps extends DocumentViewProps {
     dataProvider?: (doc: Doc, replica: string) => { x: number, y: number, zIndex?: number, opacity?: number, highlight?: boolean, z: number, transition?: string } | undefined;
@@ -35,16 +33,16 @@ export interface CollectionFreeFormDocumentViewProps extends DocumentViewProps {
 }
 
 @observer
-export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeFormDocumentViewProps, Document>(Document) {
+export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeFormDocumentViewProps>() {
     public static animFields = ["_height", "_width", "x", "y", "_scrollTop", "opacity"];  // fields that are configured to be animatable using animation frames
     @observable _animPos: number[] | undefined = undefined;
     @observable _contentView: DocumentView | undefined | null;
     get displayName() { return "CollectionFreeFormDocumentView(" + this.rootDoc.title + ")"; } // this makes mobx trace() statements more descriptive
     get maskCentering() { return this.props.Document.isInkMask ? InkingStroke.MaskDim / 2 : 0; }
     get transform() { return `translate(${this.X - this.maskCentering}px, ${this.Y - this.maskCentering}px) rotate(${this.props.jitterRotation}deg)`; }
-    get X() { return this.dataProvider ? this.dataProvider.x : (this.Document.x || 0); }
-    get Y() { return this.dataProvider ? this.dataProvider.y : (this.Document.y || 0); }
-    get ZInd() { return this.dataProvider ? this.dataProvider.zIndex : (this.Document.zIndex || 0); }
+    get X() { return this.dataProvider ? this.dataProvider.x : NumCast(this.Document.x); }
+    get Y() { return this.dataProvider ? this.dataProvider.y : NumCast(this.Document.y); }
+    get ZInd() { return this.dataProvider ? this.dataProvider.zIndex : NumCast(this.Document.zIndex); }
     get Opacity() { return this.dataProvider ? this.dataProvider.opacity : undefined; }
     get Highlight() { return this.dataProvider?.highlight; }
     @computed get dataProvider() { return this.props.dataProvider?.(this.props.Document, this.props.replica); }
diff --git a/src/client/views/nodes/ColorBox.tsx b/src/client/views/nodes/ColorBox.tsx
index 8da5cd1b1..d975baf9b 100644
--- a/src/client/views/nodes/ColorBox.tsx
+++ b/src/client/views/nodes/ColorBox.tsx
@@ -3,9 +3,7 @@ import { action } from "mobx";
 import { observer } from "mobx-react";
 import { ColorState, SketchPicker } from 'react-color';
 import { Doc, HeightSym, WidthSym } from '../../../fields/Doc';
-import { documentSchema } from "../../../fields/documentSchemas";
 import { InkTool } from "../../../fields/InkField";
-import { makeInterface } from "../../../fields/Schema";
 import { StrCast } from "../../../fields/Types";
 import { DocumentType } from "../../documents/DocumentTypes";
 import { CurrentUserUtils } from "../../util/CurrentUserUtils";
@@ -17,11 +15,8 @@ import "./ColorBox.scss";
 import { FieldView, FieldViewProps } from './FieldView';
 import { RichTextMenu } from "./formattedText/RichTextMenu";
 
-type ColorDocument = makeInterface<[typeof documentSchema]>;
-const ColorDocument = makeInterface(documentSchema);
-
 @observer
-export class ColorBox extends ViewBoxBaseComponent<FieldViewProps, ColorDocument>(ColorDocument) {
+export class ColorBox extends ViewBoxBaseComponent<FieldViewProps>() {
     public static LayoutString(fieldKey: string) { return FieldView.LayoutString(ColorBox, fieldKey); }
 
     @undoBatch
diff --git a/src/client/views/nodes/ComparisonBox.tsx b/src/client/views/nodes/ComparisonBox.tsx
index 750213e67..5919cd8f2 100644
--- a/src/client/views/nodes/ComparisonBox.tsx
+++ b/src/client/views/nodes/ComparisonBox.tsx
@@ -2,8 +2,6 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { action, observable } from 'mobx';
 import { observer } from "mobx-react";
 import { Doc, Opt } from '../../../fields/Doc';
-import { documentSchema } from '../../../fields/documentSchemas';
-import { createSchema, makeInterface } from '../../../fields/Schema';
 import { Cast, NumCast, StrCast } from '../../../fields/Types';
 import { emptyFunction, OmitKeys, returnFalse, setupMoveUpEvents } from '../../../Utils';
 import { DragManager } from '../../util/DragManager';
@@ -15,15 +13,10 @@ import "./ComparisonBox.scss";
 import { DocumentView, DocumentViewProps } from './DocumentView';
 import { FieldView, FieldViewProps } from './FieldView';
 import React = require("react");
-import { DocumentType } from '../../documents/DocumentTypes';
 
-export const comparisonSchema = createSchema({});
-
-type ComparisonDocument = makeInterface<[typeof comparisonSchema, typeof documentSchema]>;
-const ComparisonDocument = makeInterface(comparisonSchema, documentSchema);
 
 @observer
-export class ComparisonBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps & FieldViewProps, ComparisonDocument>(ComparisonDocument) {
+export class ComparisonBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps & FieldViewProps>() {
     public static LayoutString(fieldKey: string) { return FieldView.LayoutString(ComparisonBox, fieldKey); }
     protected _multiTouchDisposer?: import("../../util/InteractionUtils").InteractionUtils.MultiTouchEventDisposer | undefined;
     private _disposers: (DragManager.DragDropDisposer | undefined)[] = [undefined, undefined];
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index bde11dc68..b8c16790e 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -1,5 +1,6 @@
+import { IconProp } from "@fortawesome/fontawesome-svg-core";
 import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-import { action, computed, IReactionDisposer, observable, reaction, runInAction, trace } from "mobx";
+import { action, computed, IReactionDisposer, observable, reaction, runInAction } from "mobx";
 import { observer } from "mobx-react";
 import { AclAdmin, AclEdit, AclPrivate, DataSym, Doc, DocListCast, Field, Opt, StrListCast } from "../../../fields/Doc";
 import { Document } from '../../../fields/documentSchemas';
@@ -9,11 +10,11 @@ import { List } from "../../../fields/List";
 import { ObjectField } from "../../../fields/ObjectField";
 import { listSpec } from "../../../fields/Schema";
 import { ScriptField } from '../../../fields/ScriptField';
-import { BoolCast, Cast, NumCast, ScriptCast, StrCast, ImageCast } from "../../../fields/Types";
+import { BoolCast, Cast, ImageCast, NumCast, ScriptCast, StrCast } from "../../../fields/Types";
 import { AudioField } from "../../../fields/URLField";
 import { GetEffectiveAcl, SharingPermissions, TraceMobx } from '../../../fields/util';
 import { MobileInterface } from '../../../mobile/MobileInterface';
-import { emptyFunction, hasDescendantTarget, OmitKeys, returnTrue, returnVal, Utils, lightOrDark, simulateMouseClick, returnEmptyString } from "../../../Utils";
+import { emptyFunction, hasDescendantTarget, lightOrDark, OmitKeys, returnEmptyString, returnTrue, returnVal, simulateMouseClick, Utils } from "../../../Utils";
 import { GooglePhotos } from '../../apis/google_docs/GooglePhotosClientUtils';
 import { Docs, DocUtils } from "../../documents/Documents";
 import { DocumentType } from '../../documents/DocumentTypes';
@@ -48,8 +49,6 @@ import { RadialMenu } from './RadialMenu';
 import { ScriptingBox } from "./ScriptingBox";
 import { PresBox } from './trails/PresBox';
 import React = require("react");
-import { IconProp } from "@fortawesome/fontawesome-svg-core";
-import { ColorScheme } from "../../util/SettingsManager";
 const { Howl } = require('howler');
 
 interface Window {
@@ -179,7 +178,7 @@ export interface DocumentViewInternalProps extends DocumentViewProps {
 }
 
 @observer
-export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps, Document>(Document) {
+export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps>() {
     public static SelectAfterContextMenu = true; //  whether a document should be selected after it's contextmenu is triggered.
     @observable _animateScalingTo = 0;
     @observable _mediaState = 0;
diff --git a/src/client/views/nodes/EquationBox.tsx b/src/client/views/nodes/EquationBox.tsx
index f1f802c13..c170f9867 100644
--- a/src/client/views/nodes/EquationBox.tsx
+++ b/src/client/views/nodes/EquationBox.tsx
@@ -3,25 +3,18 @@ import { action, reaction } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
 import { WidthSym } from '../../../fields/Doc';
-import { documentSchema } from '../../../fields/documentSchemas';
 import { Id } from '../../../fields/FieldSymbols';
-import { createSchema, makeInterface } from '../../../fields/Schema';
 import { NumCast, StrCast } from '../../../fields/Types';
 import { TraceMobx } from '../../../fields/util';
 import { Docs } from '../../documents/Documents';
 import { ViewBoxBaseComponent } from '../DocComponent';
 import { LightboxView } from '../LightboxView';
-import { FieldView, FieldViewProps } from './FieldView';
 import './EquationBox.scss';
+import { FieldView, FieldViewProps } from './FieldView';
 
 
-const EquationSchema = createSchema({});
-
-type EquationDocument = makeInterface<[typeof EquationSchema, typeof documentSchema]>;
-const EquationDocument = makeInterface(EquationSchema, documentSchema);
-
 @observer
-export class EquationBox extends ViewBoxBaseComponent<FieldViewProps, EquationDocument>(EquationDocument) {
+export class EquationBox extends ViewBoxBaseComponent<FieldViewProps>() {
     public static LayoutString(fieldKey: string) { return FieldView.LayoutString(EquationBox, fieldKey); }
     public static SelectOnLoad: string = "";
     _ref: React.RefObject<EquationEditor> = React.createRef();
diff --git a/src/client/views/nodes/FilterBox.tsx b/src/client/views/nodes/FilterBox.tsx
index fb8e89da9..6e25443ce 100644
--- a/src/client/views/nodes/FilterBox.tsx
+++ b/src/client/views/nodes/FilterBox.tsx
@@ -4,12 +4,11 @@ import { action, computed, observable, reaction, runInAction } from "mobx";
 import { observer } from "mobx-react";
 import Select from "react-select";
 import { Doc, DocListCast, DocListCastAsync, Field, HeightSym, Opt } from "../../../fields/Doc";
-import { documentSchema } from "../../../fields/documentSchemas";
 import { List } from "../../../fields/List";
 import { RichTextField } from "../../../fields/RichTextField";
-import { listSpec, makeInterface } from "../../../fields/Schema";
+import { listSpec } from "../../../fields/Schema";
 import { ComputedField, ScriptField } from "../../../fields/ScriptField";
-import { Cast, StrCast, NumCast } from "../../../fields/Types";
+import { Cast, NumCast, StrCast } from "../../../fields/Types";
 import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue } from "../../../Utils";
 import { Docs } from "../../documents/Documents";
 import { DocumentType } from "../../documents/DocumentTypes";
@@ -30,11 +29,8 @@ const higflyout = require("@hig/flyout");
 export const { anchorPoints } = higflyout;
 export const Flyout = higflyout.default;
 
-type FilterBoxDocument = makeInterface<[typeof documentSchema]>;
-const FilterBoxDocument = makeInterface(documentSchema);
-
 @observer
-export class FilterBox extends ViewBoxBaseComponent<FieldViewProps, FilterBoxDocument>(FilterBoxDocument) {
+export class FilterBox extends ViewBoxBaseComponent<FieldViewProps>() {
 
     constructor(props: Readonly<FieldViewProps>) {
         super(props);
@@ -425,7 +421,6 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps, FilterBoxDoc
                     treeViewHideTitle={true}
                     focus={returnFalse}
                     treeViewHideHeaderFields={false}
-                    onCheckedClick={this.scriptField}
                     dontRegisterView={true}
                     styleProvider={this.FilterStyleProvider}
                     layerProvider={this.props.layerProvider}
diff --git a/src/client/views/nodes/FunctionPlotBox.tsx b/src/client/views/nodes/FunctionPlotBox.tsx
index 5050fc2d2..3ab0a3ff2 100644
--- a/src/client/views/nodes/FunctionPlotBox.tsx
+++ b/src/client/views/nodes/FunctionPlotBox.tsx
@@ -19,7 +19,7 @@ type EquationDocument = makeInterface<[typeof EquationSchema, typeof documentSch
 const EquationDocument = makeInterface(EquationSchema, documentSchema);
 
 @observer
-export class FunctionPlotBox extends ViewBoxBaseComponent<FieldViewProps, EquationDocument>(EquationDocument) {
+export class FunctionPlotBox extends ViewBoxBaseComponent<FieldViewProps>() {
     public static LayoutString(fieldKey: string) { return FieldView.LayoutString(FunctionPlotBox, fieldKey); }
     public static GraphCount = 0;
     _plot: any;
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index 112325cc3..0a4168698 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -1,12 +1,12 @@
-import { action, computed, IReactionDisposer, observable, ObservableMap, reaction, runInAction, trace } from 'mobx';
+import { action, computed, IReactionDisposer, observable, ObservableMap, reaction, runInAction } from 'mobx';
 import { observer } from "mobx-react";
+import { extname } from 'path';
 import { DataSym, Doc, DocListCast, WidthSym } from '../../../fields/Doc';
-import { documentSchema } from '../../../fields/documentSchemas';
 import { Id } from '../../../fields/FieldSymbols';
 import { InkTool } from '../../../fields/InkField';
 import { List } from '../../../fields/List';
 import { ObjectField } from '../../../fields/ObjectField';
-import { createSchema, makeInterface } from '../../../fields/Schema';
+import { createSchema } from '../../../fields/Schema';
 import { ComputedField } from '../../../fields/ScriptField';
 import { Cast, NumCast } from '../../../fields/Types';
 import { ImageField } from '../../../fields/URLField';
@@ -34,9 +34,6 @@ export const pageSchema = createSchema({
     googlePhotosUrl: "string",
     googlePhotosTags: "string"
 });
-type ImageDocument = makeInterface<[typeof pageSchema, typeof documentSchema]>;
-const ImageDocument = makeInterface(pageSchema, documentSchema);
-
 const uploadIcons = {
     idle: "downarrow.png",
     loading: "loading.gif",
@@ -45,7 +42,7 @@ const uploadIcons = {
 };
 
 @observer
-export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps & FieldViewProps, ImageDocument>(ImageDocument) {
+export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps & FieldViewProps>() {
     protected _multiTouchDisposer?: import("../../util/InteractionUtils").InteractionUtils.MultiTouchEventDisposer | undefined;
     public static LayoutString(fieldKey: string) { return FieldView.LayoutString(ImageBox, fieldKey); }
     private _imgRef: React.RefObject<HTMLImageElement> = React.createRef();
@@ -188,7 +185,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
         if (url.href.indexOf(window.location.origin) === -1) return Utils.CorsProxy(url.href);
         if (!/\.(png|jpg|jpeg|gif|webp)$/.test(lower)) return url.href;  //Why is this here
 
-        const ext = "." + url.href.replace(/.*\./, "");//path.extname(url.href);
+        const ext = extname(url.href);
         return url.href.replace(ext, this._curSuffix + ext);
     }
 
diff --git a/src/client/views/nodes/LabelBox.tsx b/src/client/views/nodes/LabelBox.tsx
index 90b9ce55d..4e0461650 100644
--- a/src/client/views/nodes/LabelBox.tsx
+++ b/src/client/views/nodes/LabelBox.tsx
@@ -2,9 +2,8 @@ import { action, computed, observable } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
 import { Doc, DocListCast } from '../../../fields/Doc';
-import { documentSchema } from '../../../fields/documentSchemas';
 import { List } from '../../../fields/List';
-import { createSchema, listSpec, makeInterface } from '../../../fields/Schema';
+import { listSpec } from '../../../fields/Schema';
 import { Cast, StrCast } from '../../../fields/Types';
 import { DragManager } from '../../util/DragManager';
 import { undoBatch } from '../../util/UndoManager';
@@ -16,17 +15,13 @@ import { FieldView, FieldViewProps } from './FieldView';
 import BigText from './LabelBigText';
 import './LabelBox.scss';
 
-const LabelSchema = createSchema({});
-
-type LabelDocument = makeInterface<[typeof LabelSchema, typeof documentSchema]>;
-const LabelDocument = makeInterface(LabelSchema, documentSchema);
 
 export interface LabelBoxProps {
     label?: string;
 }
 
 @observer
-export class LabelBox extends ViewBoxBaseComponent<(FieldViewProps & LabelBoxProps), LabelDocument>(LabelDocument) {
+export class LabelBox extends ViewBoxBaseComponent<(FieldViewProps & LabelBoxProps)>() {
     public static LayoutString(fieldKey: string) { return FieldView.LayoutString(LabelBox, fieldKey); }
     public static LayoutStringWithTitle(fieldType: { name: string }, fieldStr: string, label: string) {
         return `<${fieldType.name} fieldKey={'${fieldStr}'} label={'${label}'} {...props} />`;  //e.g., "<ImageBox {...props} fieldKey={"data} />"
diff --git a/src/client/views/nodes/LinkAnchorBox.tsx b/src/client/views/nodes/LinkAnchorBox.tsx
index a7bfb93eb..437d29f39 100644
--- a/src/client/views/nodes/LinkAnchorBox.tsx
+++ b/src/client/views/nodes/LinkAnchorBox.tsx
@@ -2,8 +2,6 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
 import { action, observable } from "mobx";
 import { observer } from "mobx-react";
 import { Doc } from "../../../fields/Doc";
-import { documentSchema } from "../../../fields/documentSchemas";
-import { makeInterface } from "../../../fields/Schema";
 import { Cast, NumCast, StrCast } from "../../../fields/Types";
 import { TraceMobx } from "../../../fields/util";
 import { emptyFunction, setupMoveUpEvents, Utils } from '../../../Utils';
@@ -23,11 +21,9 @@ const higflyout = require("@hig/flyout");
 export const { anchorPoints } = higflyout;
 export const Flyout = higflyout.default;
 
-type LinkAnchorSchema = makeInterface<[typeof documentSchema]>;
-const LinkAnchorDocument = makeInterface(documentSchema);
 
 @observer
-export class LinkAnchorBox extends ViewBoxBaseComponent<FieldViewProps, LinkAnchorSchema>(LinkAnchorDocument) {
+export class LinkAnchorBox extends ViewBoxBaseComponent<FieldViewProps>() {
     public static LayoutString(fieldKey: string) { return FieldView.LayoutString(LinkAnchorBox, fieldKey); }
     _doubleTap = false;
     _lastTap: number = 0;
diff --git a/src/client/views/nodes/LinkBox.tsx b/src/client/views/nodes/LinkBox.tsx
index 879a63248..43f4b43fb 100644
--- a/src/client/views/nodes/LinkBox.tsx
+++ b/src/client/views/nodes/LinkBox.tsx
@@ -1,7 +1,5 @@
 import React = require("react");
 import { observer } from "mobx-react";
-import { documentSchema } from "../../../fields/documentSchemas";
-import { makeInterface } from "../../../fields/Schema";
 import { emptyFunction, returnFalse } from "../../../Utils";
 import { ViewBoxBaseComponent } from "../DocComponent";
 import { StyleProp } from "../StyleProvider";
@@ -9,11 +7,8 @@ import { ComparisonBox } from "./ComparisonBox";
 import { FieldView, FieldViewProps } from './FieldView';
 import "./LinkBox.scss";
 
-type LinkDocument = makeInterface<[typeof documentSchema]>;
-const LinkDocument = makeInterface(documentSchema);
-
 @observer
-export class LinkBox extends ViewBoxBaseComponent<FieldViewProps, LinkDocument>(LinkDocument) {
+export class LinkBox extends ViewBoxBaseComponent<FieldViewProps>() {
     public static LayoutString(fieldKey: string) { return FieldView.LayoutString(LinkBox, fieldKey); }
     isContentActiveFunc = () => this.isContentActive();
     render() {
diff --git a/src/client/views/nodes/MapBox/MapBox.tsx b/src/client/views/nodes/MapBox/MapBox.tsx
index 2c09a7b90..aa2130af5 100644
--- a/src/client/views/nodes/MapBox/MapBox.tsx
+++ b/src/client/views/nodes/MapBox/MapBox.tsx
@@ -4,10 +4,8 @@ import { action, computed, IReactionDisposer, observable, ObservableMap } from '
 import { observer } from "mobx-react";
 import * as React from "react";
 import { Doc, DocListCast, Opt, WidthSym } from '../../../../fields/Doc';
-import { documentSchema } from '../../../../fields/documentSchemas';
 import { Id } from '../../../../fields/FieldSymbols';
 import { InkTool } from '../../../../fields/InkField';
-import { makeInterface } from '../../../../fields/Schema';
 import { NumCast, StrCast } from '../../../../fields/Types';
 import { TraceMobx } from '../../../../fields/util';
 import { emptyFunction, OmitKeys, returnFalse, returnOne, setupMoveUpEvents, Utils } from '../../../../Utils';
@@ -42,9 +40,6 @@ import { MapBoxInfoWindow } from './MapBoxInfoWindow';
 
 // const _global = (window /* browser */ || global /* node */) as any;
 
-type MapDocument = makeInterface<[typeof documentSchema]>;
-const MapDocument = makeInterface(documentSchema);
-
 const mapContainerStyle = {
     height: '100%',
 };
@@ -91,7 +86,7 @@ const options = {
 } as google.maps.places.AutocompleteOptions;
 
 @observer
-export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps & FieldViewProps & Partial<GoogleMapProps>, MapDocument>(MapDocument) {
+export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps & FieldViewProps & Partial<GoogleMapProps>>() {
 
     private _dropDisposer?: DragManager.DragDropDisposer;
     private _disposers: { [name: string]: IReactionDisposer } = {};
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index 91f0805bf..5b98103da 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -3,9 +3,7 @@ import { action, computed, IReactionDisposer, observable, reaction, runInAction
 import { observer } from "mobx-react";
 import * as Pdfjs from "pdfjs-dist";
 import "pdfjs-dist/web/pdf_viewer.css";
-import { Doc, DocListCast, Opt, WidthSym, StrListCast } from "../../../fields/Doc";
-import { documentSchema } from '../../../fields/documentSchemas';
-import { makeInterface, listSpec } from "../../../fields/Schema";
+import { Doc, DocListCast, Opt, WidthSym } from "../../../fields/Doc";
 import { Cast, NumCast, StrCast } from '../../../fields/Types';
 import { PdfField } from "../../../fields/URLField";
 import { TraceMobx } from '../../../fields/util';
@@ -13,7 +11,6 @@ import { emptyFunction, returnOne, setupMoveUpEvents, Utils } from '../../../Uti
 import { Docs } from '../../documents/Documents';
 import { KeyCodes } from '../../util/KeyCodes';
 import { undoBatch } from '../../util/UndoManager';
-import { panZoomSchema } from '../collections/collectionFreeForm/CollectionFreeFormView';
 import { ContextMenu } from '../ContextMenu';
 import { ContextMenuProps } from '../ContextMenuItem';
 import { ViewBoxAnnotatableComponent, ViewBoxAnnotatableProps } from "../DocComponent";
@@ -22,16 +19,11 @@ import { AnchorMenu } from '../pdf/AnchorMenu';
 import { PDFViewer } from "../pdf/PDFViewer";
 import { SidebarAnnos } from '../SidebarAnnos';
 import { FieldView, FieldViewProps } from './FieldView';
-import { pageSchema } from "./ImageBox";
 import "./PDFBox.scss";
 import React = require("react");
-import { CurrentUserUtils } from '../../util/CurrentUserUtils';
-
-type PdfDocument = makeInterface<[typeof documentSchema, typeof panZoomSchema, typeof pageSchema]>;
-const PdfDocument = makeInterface(documentSchema, panZoomSchema, pageSchema);
 
 @observer
-export class PDFBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps & FieldViewProps, PdfDocument>(PdfDocument) {
+export class PDFBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps & FieldViewProps>() {
     public static LayoutString(fieldKey: string) { return FieldView.LayoutString(PDFBox, fieldKey); }
     public static openSidebarWidth = 250;
     private _searchString: string = "";
@@ -80,7 +72,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
         const anchor =
             AnchorMenu.Instance?.GetAnchor() ??
             Docs.Create.TextanchorDocument({
-                title: StrCast(this.rootDoc.title + "@" + this.layoutDoc._scrollTop?.toFixed(0)),
+                title: StrCast(this.rootDoc.title + "@" + NumCast(this.layoutDoc._scrollTop)?.toFixed(0)),
                 y: NumCast(this.layoutDoc._scrollTop),
                 unrendered: true
             });
@@ -110,8 +102,8 @@ export class PDFBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
     });
     public prevAnnotation = () => this._pdfViewer?.prevAnnotation();
     public nextAnnotation = () => this._pdfViewer?.nextAnnotation();
-    public backPage = () => { this.Document._curPage = (this.Document._curPage || 1) - 1; return true; };
-    public forwardPage = () => { this.Document._curPage = (this.Document._curPage || 1) + 1; return true; };
+    public backPage = () => { this.Document._curPage = (NumCast(this.Document._curPage) || 1) - 1; return true; };
+    public forwardPage = () => { this.Document._curPage = (NumCast(this.Document._curPage) || 1) + 1; return true; };
     public gotoPage = (p: number) => this.Document._curPage = p;
 
     @undoBatch
@@ -185,7 +177,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
             </button>
         </>;
         const searchTitle = `${!this._searching ? "Open" : "Close"} Search Bar`;
-        const curPage = this.Document._curPage || 1;
+        const curPage = NumCast(this.Document._curPage) || 1;
         return !this.props.isContentActive() ? (null) :
             <div className="pdfBox-ui" onKeyDown={e => [KeyCodes.BACKSPACE, KeyCodes.DELETE].includes(e.keyCode) ? e.stopPropagation() : true}
                 onPointerDown={e => e.stopPropagation()} style={{ display: this.props.isContentActive() ? "flex" : "none" }}>
diff --git a/src/client/views/nodes/ScreenshotBox.tsx b/src/client/views/nodes/ScreenshotBox.tsx
index 0c631e5f9..dbb567d3a 100644
--- a/src/client/views/nodes/ScreenshotBox.tsx
+++ b/src/client/views/nodes/ScreenshotBox.tsx
@@ -1,20 +1,17 @@
 import React = require("react");
 import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
 // import { Canvas } from '@react-three/fiber';
-import { action, computed, observable, reaction, trace, runInAction } from "mobx";
+import { computed, observable, runInAction } from "mobx";
 import { observer } from "mobx-react";
 // import { BufferAttribute, Camera, Vector2, Vector3 } from 'three';
 import { DateField } from "../../../fields/DateField";
-import { Doc, WidthSym, HeightSym } from "../../../fields/Doc";
-import { documentSchema } from "../../../fields/documentSchemas";
+import { Doc, HeightSym, WidthSym } from "../../../fields/Doc";
 import { Id } from "../../../fields/FieldSymbols";
-import { InkTool } from "../../../fields/InkField";
-import { makeInterface } from "../../../fields/Schema";
 import { ComputedField } from "../../../fields/ScriptField";
 import { Cast, NumCast } from "../../../fields/Types";
 import { AudioField, VideoField } from "../../../fields/URLField";
 import { TraceMobx } from "../../../fields/util";
-import { emptyFunction, numberRange, OmitKeys, returnFalse, returnOne, Utils } from "../../../Utils";
+import { emptyFunction, OmitKeys, returnFalse, returnOne } from "../../../Utils";
 import { DocUtils } from "../../documents/Documents";
 import { DocumentType } from "../../documents/DocumentTypes";
 import { Networking } from "../../Network";
@@ -32,9 +29,6 @@ declare class MediaRecorder {
     constructor(e: any, options?: any);  // whatever MediaRecorder has
 }
 
-type ScreenshotDocument = makeInterface<[typeof documentSchema]>;
-const ScreenshotDocument = makeInterface(documentSchema);
-
 // interface VideoTileProps {
 //     raised: { coord: Vector2, off: Vector3 }[];
 //     setRaised: (r: { coord: Vector2, off: Vector3 }[]) => void;
@@ -112,7 +106,7 @@ const ScreenshotDocument = makeInterface(documentSchema);
 // }
 
 @observer
-export class ScreenshotBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps & FieldViewProps, ScreenshotDocument>(ScreenshotDocument) {
+export class ScreenshotBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps & FieldViewProps>() {
     public static LayoutString(fieldKey: string) { return FieldView.LayoutString(ScreenshotBox, fieldKey); }
     private _audioRec: any;
     private _videoRec: any;
diff --git a/src/client/views/nodes/ScriptingBox.tsx b/src/client/views/nodes/ScriptingBox.tsx
index e0cd6bae1..c39501df9 100644
--- a/src/client/views/nodes/ScriptingBox.tsx
+++ b/src/client/views/nodes/ScriptingBox.tsx
@@ -1,14 +1,14 @@
 import ReactTextareaAutocomplete from "@webscopeio/react-textarea-autocomplete";
 import "@webscopeio/react-textarea-autocomplete/style.css";
-import { action, computed, observable, runInAction, trace } from "mobx";
+import { action, computed, observable } from "mobx";
 import { observer } from "mobx-react";
 import * as React from "react";
 import { Doc } from "../../../fields/Doc";
-import { documentSchema } from "../../../fields/documentSchemas";
 import { List } from "../../../fields/List";
-import { createSchema, listSpec, makeInterface } from "../../../fields/Schema";
+import { listSpec } from "../../../fields/Schema";
 import { ScriptField } from "../../../fields/ScriptField";
-import { Cast, NumCast, ScriptCast, StrCast, BoolCast } from "../../../fields/Types";
+import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from "../../../fields/Types";
+import { TraceMobx } from "../../../fields/util";
 import { returnEmptyString } from "../../../Utils";
 import { DragManager } from "../../util/DragManager";
 import { InteractionUtils } from "../../util/InteractionUtils";
@@ -21,15 +21,10 @@ import { FieldView, FieldViewProps } from "../nodes/FieldView";
 import { OverlayView } from "../OverlayView";
 import { DocumentIconContainer } from "./DocumentIcon";
 import "./ScriptingBox.scss";
-import { TraceMobx } from "../../../fields/util";
 const _global = (window /* browser */ || global /* node */) as any;
 
-const ScriptingSchema = createSchema({});
-type ScriptingDocument = makeInterface<[typeof ScriptingSchema, typeof documentSchema]>;
-const ScriptingDocument = makeInterface(ScriptingSchema, documentSchema);
-
 @observer
-export class ScriptingBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps & FieldViewProps, ScriptingDocument>(ScriptingDocument) {
+export class ScriptingBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps & FieldViewProps>() {
 
     private dropDisposer?: DragManager.DragDropDisposer;
     protected _multiTouchDisposer?: InteractionUtils.MultiTouchEventDisposer | undefined;
diff --git a/src/client/views/nodes/SliderBox.tsx b/src/client/views/nodes/SliderBox.tsx
index 92d1f7446..b96977f32 100644
--- a/src/client/views/nodes/SliderBox.tsx
+++ b/src/client/views/nodes/SliderBox.tsx
@@ -2,30 +2,19 @@ import { runInAction } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
 import { Handles, Rail, Slider, Ticks, Tracks } from 'react-compound-slider';
-import { documentSchema } from '../../../fields/documentSchemas';
-import { createSchema, makeInterface } from '../../../fields/Schema';
 import { NumCast, ScriptCast, StrCast } from '../../../fields/Types';
 import { ContextMenu } from '../ContextMenu';
 import { ContextMenuProps } from '../ContextMenuItem';
 import { ViewBoxBaseComponent } from '../DocComponent';
 import { ScriptBox } from '../ScriptBox';
+import { StyleProp } from '../StyleProvider';
 import { FieldView, FieldViewProps } from './FieldView';
 import { Handle, Tick, TooltipRail, Track } from './SliderBox-components';
 import './SliderBox.scss';
-import { StyleProp } from '../StyleProvider';
-
-const SliderSchema = createSchema({
-    _sliderMin: "number",
-    _sliderMax: "number",
-    _sliderMinThumb: "number",
-    _sliderMaxThumb: "number",
-});
 
-type SliderDocument = makeInterface<[typeof SliderSchema, typeof documentSchema]>;
-const SliderDocument = makeInterface(SliderSchema, documentSchema);
 
 @observer
-export class SliderBox extends ViewBoxBaseComponent<FieldViewProps, SliderDocument>(SliderDocument) {
+export class SliderBox extends ViewBoxBaseComponent<FieldViewProps>() {
     public static LayoutString(fieldKey: string) { return FieldView.LayoutString(SliderBox, fieldKey); }
 
     get minThumbKey() { return this.fieldKey + "-minThumb"; }
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index 956fcfbb9..036b3ba14 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -1,18 +1,20 @@
 import React = require("react");
 import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { Tooltip } from "@material-ui/core";
 import { action, computed, IReactionDisposer, observable, ObservableMap, reaction, runInAction, untracked } from "mobx";
 import { observer } from "mobx-react";
+import { basename } from "path";
 import * as rp from 'request-promise';
 import { Doc, DocListCast } from "../../../fields/Doc";
-import { documentSchema } from "../../../fields/documentSchemas";
 import { InkTool } from "../../../fields/InkField";
-import { makeInterface } from "../../../fields/Schema";
 import { Cast, NumCast, StrCast } from "../../../fields/Types";
-import { AudioField, nullAudio, VideoField } from "../../../fields/URLField";
-import { emptyFunction, formatTime, OmitKeys, returnOne, setupMoveUpEvents, Utils, returnFalse } from "../../../Utils";
+import { AudioField, VideoField } from "../../../fields/URLField";
+import { emptyFunction, formatTime, OmitKeys, returnFalse, returnOne, setupMoveUpEvents, Utils } from "../../../Utils";
 import { Docs, DocUtils } from "../../documents/Documents";
+import { DocumentType } from "../../documents/DocumentTypes";
 import { Networking } from "../../Network";
 import { CurrentUserUtils } from "../../util/CurrentUserUtils";
+import { DocumentManager } from "../../util/DocumentManager";
 import { SelectionManager } from "../../util/SelectionManager";
 import { SnappingManager } from "../../util/SnappingManager";
 import { CollectionFreeFormView } from "../collections/collectionFreeForm/CollectionFreeFormView";
@@ -22,21 +24,14 @@ import { ContextMenuProps } from "../ContextMenuItem";
 import { ViewBoxAnnotatableComponent, ViewBoxAnnotatableProps } from "../DocComponent";
 import { DocumentDecorations } from "../DocumentDecorations";
 import { MarqueeAnnotator } from "../MarqueeAnnotator";
+import { AnchorMenu } from "../pdf/AnchorMenu";
 import { StyleProp } from "../StyleProvider";
 import { FieldView, FieldViewProps } from './FieldView';
 import { LinkDocPreview } from "./LinkDocPreview";
 import "./VideoBox.scss";
-import { DragManager } from "../../util/DragManager";
-import { DocumentManager } from "../../util/DocumentManager";
-import { DocumentType } from "../../documents/DocumentTypes";
-import { Tooltip } from "@material-ui/core";
-import { AnchorMenu } from "../pdf/AnchorMenu";
-
-type VideoDocument = makeInterface<[typeof documentSchema]>;
-const VideoDocument = makeInterface(documentSchema);
 
 @observer
-export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps & FieldViewProps, VideoDocument>(VideoDocument) {
+export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps & FieldViewProps>() {
     public static LayoutString(fieldKey: string) { return FieldView.LayoutString(VideoBox, fieldKey); }
     static _youtubeIframeCounter: number = 0;
     static Instance: VideoBox;
@@ -82,7 +77,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
         const aspect = this.player!.videoWidth / this.player!.videoHeight;
         Doc.SetNativeWidth(this.dataDoc, this.player!.videoWidth);
         Doc.SetNativeHeight(this.dataDoc, this.player!.videoHeight);
-        this.layoutDoc._height = (this.layoutDoc._width || 0) / aspect;
+        this.layoutDoc._height = NumCast(this.layoutDoc._width) / aspect;
         if (Number.isFinite(this.player!.duration)) {
             this.dataDoc[this.fieldKey + "-duration"] = this.player!.duration;
         }
@@ -139,7 +134,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
     }
 
     @action public Snapshot(downX?: number, downY?: number) {
-        const width = (this.layoutDoc._width || 0);
+        const width = NumCast(this.layoutDoc._width);
         const canvas = document.createElement('canvas');
         canvas.width = 640;
         canvas.height = 640 * Doc.NativeHeight(this.layoutDoc) / (Doc.NativeWidth(this.layoutDoc) || 1);
@@ -153,7 +148,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
 
         if (!this._videoRef) {
             const b = Docs.Create.LabelDocument({
-                x: (this.layoutDoc.x || 0) + width, y: (this.layoutDoc.y || 1),
+                x: NumCast(this.layoutDoc.x) + width, y: NumCast(this.layoutDoc.y, 1),
                 _width: 150, _height: 50, title: (this.layoutDoc._currentTimecode || 0).toString(),
                 _isLinkButton: true
             });
@@ -175,7 +170,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
             // if you want to preview the captured image,
             const retitled = StrCast(this.rootDoc.title).replace(/[ -\.]/g, "");
             const encodedFilename = encodeURIComponent("snapshot" + retitled + "_" + (this.layoutDoc._currentTimecode || 0).toString().replace(/\./, "_"));
-            const filename = encodedFilename.replace(/.*\//, ""); // path.basename();
+            const filename = basename(encodedFilename);
             VideoBox.convertDataUri(dataUrl, filename).then((returnedFilename: string) =>
                 returnedFilename && this.createRealSummaryLink(returnedFilename, downX, downY));
         }
@@ -183,12 +178,12 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
 
     private createRealSummaryLink = (imagePath: string, downX?: number, downY?: number) => {
         const url = !imagePath.startsWith("/") ? Utils.CorsProxy(imagePath) : imagePath;
-        const width = this.layoutDoc._width || 1;
-        const height = this.layoutDoc._height || 0;
+        const width = NumCast(this.layoutDoc._width) || 1;
+        const height = NumCast(this.layoutDoc._height);
         const imageSummary = Docs.Create.ImageDocument(url, {
             _nativeWidth: Doc.NativeWidth(this.layoutDoc), _nativeHeight: Doc.NativeHeight(this.layoutDoc),
-            x: (this.layoutDoc.x || 0) + width, y: (this.layoutDoc.y || 0), _isLinkButton: true,
-            _width: 150, _height: height / width * 150, title: "--snapshot" + (this.layoutDoc._currentTimecode || 0) + " image-"
+            x: NumCast(this.layoutDoc.x) + width, y: NumCast(this.layoutDoc.y), _isLinkButton: true,
+            _width: 150, _height: height / width * 150, title: "--snapshot" + NumCast(this.layoutDoc._currentTimecode) + " image-"
         });
         Doc.SetNativeWidth(Doc.GetProto(imageSummary), Doc.NativeWidth(this.layoutDoc));
         Doc.SetNativeHeight(Doc.GetProto(imageSummary), Doc.NativeHeight(this.layoutDoc));
@@ -234,7 +229,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
             if (!nativeWidth || !nativeHeight) {
                 if (!nativeWidth) Doc.SetNativeWidth(this.dataDoc, 600);
                 Doc.SetNativeHeight(this.dataDoc, (nativeWidth || 600) / youtubeaspect);
-                this.layoutDoc._height = (this.layoutDoc._width || 0) / youtubeaspect;
+                this.layoutDoc._height = NumCast(this.layoutDoc._width) / youtubeaspect;
             }
         }
     }
@@ -252,7 +247,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
             // @ts-ignore
             vref.onfullscreenchange = action((e) => this._fullScreen = vref.webkitDisplayingFullscreen);
             this._disposers.reactionDisposer?.();
-            this._disposers.reactionDisposer = reaction(() => (this.layoutDoc._currentTimecode || 0),
+            this._disposers.reactionDisposer = reaction(() => NumCast(this.layoutDoc._currentTimecode),
                 time => !this._playing && (vref.currentTime = time), { fireImmediately: true });
         }
     }
@@ -360,7 +355,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
         const onYoutubePlayerReady = (event: any) => {
             this._disposers.reactionDisposer?.();
             this._disposers.youtubeReactionDisposer?.();
-            this._disposers.reactionDisposer = reaction(() => this.layoutDoc._currentTimecode, () => !this._playing && this.Seek((this.layoutDoc._currentTimecode || 0)));
+            this._disposers.reactionDisposer = reaction(() => this.layoutDoc._currentTimecode, () => !this._playing && this.Seek(NumCast(this.layoutDoc._currentTimecode)));
             this._disposers.youtubeReactionDisposer = reaction(
                 () => CurrentUserUtils.SelectedTool === InkTool.None && this.props.isSelected(true) && !SnappingManager.GetIsDragging() && !DocumentDecorations.Instance.Interacting,
                 (interactive) => iframe.style.pointerEvents = interactive ? "all" : "none", { fireImmediately: true });
@@ -378,7 +373,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
         }
     }
     private get uIButtons() {
-        const curTime = (this.layoutDoc._currentTimecode || 0);
+        const curTime = NumCast(this.layoutDoc._currentTimecode);
         const nonNativeControls = [
             <Tooltip title={<div className="dash-tooltip">{"playback"}</div>} key="play" placement="bottom">
                 <div className="videoBox-play" onPointerDown={this.onPlayDown} >
@@ -446,7 +441,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
     onResetDown = (e: React.PointerEvent) => {
         setupMoveUpEvents(this, e,
             (e: PointerEvent) => {
-                this.Seek(Math.max(0, (this.layoutDoc._currentTimecode || 0) + Math.sign(e.movementX) * 0.0333));
+                this.Seek(Math.max(0, NumCast(this.layoutDoc._currentTimecode) + Math.sign(e.movementX) * 0.0333));
                 e.stopImmediatePropagation();
                 return false;
             },
@@ -458,7 +453,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
         this._youtubeIframeId = VideoBox._youtubeIframeCounter++;
         this._youtubeContentCreated = this._forceCreateYouTubeIFrame ? true : true;
         const classname = "videoBox-content-YouTube" + (this._fullScreen ? "-fullScreen" : "");
-        const start = untracked(() => Math.round((this.layoutDoc._currentTimecode || 0)));
+        const start = untracked(() => Math.round(NumCast(this.layoutDoc._currentTimecode)));
         return <iframe key={this._youtubeIframeId} id={`${this.youtubeVideoId + this._youtubeIframeId}-player`}
             onPointerLeave={this.updateTimecode}
             onLoad={this.youtubeIframeLoaded} className={classname} width={Doc.NativeWidth(this.layoutDoc) || 640} height={Doc.NativeHeight(this.layoutDoc) || 390}
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx
index 6c22df4d8..bace469f7 100644
--- a/src/client/views/nodes/WebBox.tsx
+++ b/src/client/views/nodes/WebBox.tsx
@@ -3,15 +3,14 @@ import { action, computed, IReactionDisposer, observable, ObservableMap, reactio
 import { observer } from "mobx-react";
 import * as WebRequest from 'web-request';
 import { Doc, DocListCast, HeightSym, Opt, WidthSym } from "../../../fields/Doc";
-import { documentSchema } from "../../../fields/documentSchemas";
 import { Id } from "../../../fields/FieldSymbols";
 import { HtmlField } from "../../../fields/HtmlField";
 import { InkTool } from "../../../fields/InkField";
 import { List } from "../../../fields/List";
-import { listSpec, makeInterface } from "../../../fields/Schema";
+import { listSpec } from "../../../fields/Schema";
 import { ComputedField } from "../../../fields/ScriptField";
-import { Cast, NumCast, StrCast, WebCast, ImageCast, BoolCast } from "../../../fields/Types";
-import { WebField, ImageField } from "../../../fields/URLField";
+import { Cast, ImageCast, NumCast, StrCast } from "../../../fields/Types";
+import { ImageField, WebField } from "../../../fields/URLField";
 import { TraceMobx } from "../../../fields/util";
 import { emptyFunction, getWordAtPoint, OmitKeys, returnFalse, returnOne, setupMoveUpEvents, smoothScroll, Utils } from "../../../Utils";
 import { Docs } from "../../documents/Documents";
@@ -36,18 +35,15 @@ import { StyleProp } from "../StyleProvider";
 import { DocumentViewProps } from "./DocumentView";
 import { FieldView, FieldViewProps } from './FieldView';
 import { LinkDocPreview } from "./LinkDocPreview";
+import { VideoBox } from "./VideoBox";
 import "./WebBox.scss";
 import React = require("react");
-import { RequestOptions } from "https";
-import { VideoBox } from "./VideoBox";
 const { CreateImage } = require("./WebBoxRenderer");
 const _global = (window /* browser */ || global /* node */) as any;
 const htmlToText = require("html-to-text");
-type WebDocument = makeInterface<[typeof documentSchema]>;
-const WebDocument = makeInterface(documentSchema);
 
 @observer
-export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps & FieldViewProps, WebDocument>(WebDocument) {
+export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps & FieldViewProps>() {
     public static LayoutString(fieldKey: string) { return FieldView.LayoutString(WebBox, fieldKey); }
     public static openSidebarWidth = 250;
     private _setPreviewCursor: undefined | ((x: number, y: number, drag: boolean, hide: boolean) => void);
diff --git a/src/client/views/nodes/button/FontIconBox.tsx b/src/client/views/nodes/button/FontIconBox.tsx
index 91365121f..6a9d9e59f 100644
--- a/src/client/views/nodes/button/FontIconBox.tsx
+++ b/src/client/views/nodes/button/FontIconBox.tsx
@@ -1,35 +1,34 @@
 import { IconProp } from '@fortawesome/fontawesome-svg-core';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { Tooltip } from '@material-ui/core';
-import { action, computed, observable, trace } from 'mobx';
+import { action, computed, observable } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
 import { ColorState, SketchPicker } from 'react-color';
-import { Doc, StrListCast, WidthSym, HeightSym } from '../../../../fields/Doc';
+import { Doc, StrListCast } from '../../../../fields/Doc';
 import { InkTool } from '../../../../fields/InkField';
-import { createSchema, makeInterface } from '../../../../fields/Schema';
+import { createSchema } from '../../../../fields/Schema';
 import { ScriptField } from '../../../../fields/ScriptField';
-import { BoolCast, Cast, NumCast, StrCast, ScriptCast } from '../../../../fields/Types';
+import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types';
 import { WebField } from '../../../../fields/URLField';
+import { Utils } from '../../../../Utils';
 import { DocumentType } from '../../../documents/DocumentTypes';
 import { Scripting } from "../../../util/Scripting";
 import { SelectionManager } from '../../../util/SelectionManager';
-import { UndoManager, undoBatch } from '../../../util/UndoManager';
+import { undoBatch, UndoManager } from '../../../util/UndoManager';
 import { CollectionViewType } from '../../collections/CollectionView';
 import { ContextMenu } from '../../ContextMenu';
 import { DocComponent } from '../../DocComponent';
 import { EditableView } from '../../EditableView';
 import { GestureOverlay } from '../../GestureOverlay';
 import { Colors } from '../../global/globalEnums';
-import { SetActiveInkColor, ActiveFillColor, SetActiveFillColor, ActiveInkWidth, ActiveInkColor, SetActiveInkWidth } from '../../InkingStroke';
+import { ActiveFillColor, ActiveInkColor, ActiveInkWidth, SetActiveFillColor, SetActiveInkColor, SetActiveInkWidth } from '../../InkingStroke';
 import { StyleProp } from '../../StyleProvider';
 import { FieldView, FieldViewProps } from '.././FieldView';
 import { RichTextMenu } from '../formattedText/RichTextMenu';
-import { Utils } from '../../../../Utils';
-import { IButtonProps } from './ButtonInterface';
+import { WebBox } from '../WebBox';
 import { FontIconBadge } from './FontIconBadge';
 import './FontIconBox.scss';
-import { WebBox } from '../WebBox';
 const FontIconSchema = createSchema({
     icon: "string",
 });
@@ -57,11 +56,8 @@ export enum NumButtonType {
 export interface ButtonProps extends FieldViewProps {
     type?: ButtonType;
 }
-
-type FontIconDocument = makeInterface<[typeof FontIconSchema]>;
-const FontIconDocument = makeInterface(FontIconSchema);
 @observer
-export class FontIconBox extends DocComponent<ButtonProps, FontIconDocument>(FontIconDocument) {
+export class FontIconBox extends DocComponent<ButtonProps>() {
     public static LayoutString(fieldKey: string) { return FieldView.LayoutString(FontIconBox, fieldKey); }
     showTemplate = (): void => {
         const dragFactory = Cast(this.layoutDoc.dragFactory, Doc, null);
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index c2f4ea8da..4a819ce86 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -12,13 +12,11 @@ import { EditorState, NodeSelection, Plugin, TextSelection, Transaction } from "
 import { EditorView } from "prosemirror-view";
 import { DateField } from '../../../../fields/DateField';
 import { AclAdmin, AclEdit, AclSelfEdit, DataSym, Doc, DocListCast, DocListCastAsync, Field, ForceServerWrite, HeightSym, Opt, UpdatingFromServer, WidthSym, AclAugment } from "../../../../fields/Doc";
-import { documentSchema } from '../../../../fields/documentSchemas';
 import { Id } from '../../../../fields/FieldSymbols';
 import { InkTool } from '../../../../fields/InkField';
 import { PrefetchProxy } from '../../../../fields/Proxy';
 import { RichTextField } from "../../../../fields/RichTextField";
 import { RichTextUtils } from '../../../../fields/RichTextUtils';
-import { makeInterface } from "../../../../fields/Schema";
 import { Cast, DateCast, NumCast, ScriptCast, StrCast } from "../../../../fields/Types";
 import { GetEffectiveAcl, TraceMobx } from '../../../../fields/util';
 import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, emptyFunction, numberRange, OmitKeys, returnZero, setupMoveUpEvents, smoothScroll, Utils } from '../../../../Utils';
@@ -65,7 +63,6 @@ import React = require("react");
 import { SidebarAnnos } from '../../SidebarAnnos';
 import { Colors } from '../../global/globalEnums';
 import { IconProp } from '@fortawesome/fontawesome-svg-core';
-import { UnknownErrorException } from 'pdfjs-dist/types/src/shared/util';
 const translateGoogleApi = require("translate-google-api");
 
 export interface FormattedTextBoxProps {
@@ -78,13 +75,10 @@ export interface FormattedTextBoxProps {
 }
 export const GoogleRef = "googleDocId";
 
-type RichTextDocument = makeInterface<[typeof documentSchema]>;
-const RichTextDocument = makeInterface(documentSchema);
-
 type PullHandler = (exportState: Opt<GoogleApiClientUtils.Docs.ImportResult>, dataDoc: Doc) => void;
 
 @observer
-export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProps & FormattedTextBoxProps), RichTextDocument>(RichTextDocument) {
+export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProps & FormattedTextBoxProps)>() {
     public static LayoutString(fieldStr: string) { return FieldView.LayoutString(FormattedTextBox, fieldStr); }
     public static blankState = () => EditorState.create(FormattedTextBox.Instance.config);
     public static Instance: FormattedTextBox;
diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx
index 14d6e8be6..b8b926b57 100644
--- a/src/client/views/nodes/trails/PresBox.tsx
+++ b/src/client/views/nodes/trails/PresBox.tsx
@@ -6,11 +6,10 @@ import { observer } from "mobx-react";
 import { ColorState, SketchPicker } from "react-color";
 import { Bounce, Fade, Flip, LightSpeed, Roll, Rotate, Zoom } from 'react-reveal';
 import { Doc, DocListCast, DocListCastAsync, FieldResult } from "../../../../fields/Doc";
-import { documentSchema } from "../../../../fields/documentSchemas";
 import { InkTool } from "../../../../fields/InkField";
 import { List } from "../../../../fields/List";
 import { PrefetchProxy } from "../../../../fields/Proxy";
-import { listSpec, makeInterface } from "../../../../fields/Schema";
+import { listSpec } from "../../../../fields/Schema";
 import { ScriptField } from "../../../../fields/ScriptField";
 import { BoolCast, Cast, NumCast, StrCast } from "../../../../fields/Types";
 import { emptyFunction, returnFalse, returnOne, returnTrue } from '../../../../Utils';
@@ -39,11 +38,8 @@ export class PinProps {
     hidePresBox?: boolean;
 }
 
-type PresBoxSchema = makeInterface<[typeof documentSchema]>;
-const PresBoxDocument = makeInterface(documentSchema);
-
 @observer
-export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>(PresBoxDocument) {
+export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
     public static LayoutString(fieldKey: string) { return FieldView.LayoutString(PresBox, fieldKey); }
 
     /**
diff --git a/src/client/views/nodes/trails/PresElementBox.tsx b/src/client/views/nodes/trails/PresElementBox.tsx
index 238d025dc..a4ec559f5 100644
--- a/src/client/views/nodes/trails/PresElementBox.tsx
+++ b/src/client/views/nodes/trails/PresElementBox.tsx
@@ -3,11 +3,10 @@ import { Tooltip } from "@material-ui/core";
 import { action, computed, IReactionDisposer, observable, reaction } from "mobx";
 import { observer } from "mobx-react";
 import { DataSym, Doc, Opt } from "../../../../fields/Doc";
-import { documentSchema } from '../../../../fields/documentSchemas';
 import { Id } from "../../../../fields/FieldSymbols";
-import { createSchema, makeInterface } from '../../../../fields/Schema';
 import { Cast, NumCast, StrCast } from "../../../../fields/Types";
-import { emptyFunction, returnFalse, returnTrue, setupMoveUpEvents, emptyPath, returnEmptyDoclist } from "../../../../Utils";
+import { emptyFunction, returnEmptyDoclist, returnFalse, returnTrue, setupMoveUpEvents } from "../../../../Utils";
+import { DocUtils } from "../../../documents/Documents";
 import { DocumentType } from "../../../documents/DocumentTypes";
 import { CurrentUserUtils } from "../../../util/CurrentUserUtils";
 import { DocumentManager } from "../../../util/DocumentManager";
@@ -16,36 +15,20 @@ import { Transform } from "../../../util/Transform";
 import { undoBatch } from "../../../util/UndoManager";
 import { ViewBoxBaseComponent } from '../../DocComponent';
 import { EditableView } from "../../EditableView";
+import { Colors } from "../../global/globalEnums";
 import { DocumentView, DocumentViewProps } from "../../nodes/DocumentView";
 import { FieldView, FieldViewProps } from '../../nodes/FieldView';
-import { PresBox } from "./PresBox";
-import { Colors } from "../../global/globalEnums";
 import { StyleProp } from "../../StyleProvider";
+import { PresBox } from "./PresBox";
 import "./PresElementBox.scss";
-import React = require("react");
-import { DocUtils } from "../../../documents/Documents";
 import { PresMovement } from "./PresEnums";
-
-export const presSchema = createSchema({
-    presentationTargetDoc: Doc,
-    presBox: Doc,
-    presZoomButton: "boolean",
-    presNavButton: "boolean",
-    presHideTillShownButton: "boolean",
-    presFadeButton: "boolean",
-    presHideAfterButton: "boolean",
-    presGroupButton: "boolean",
-    presExpandInlineButton: "boolean"
-});
-
-type PresDocument = makeInterface<[typeof presSchema, typeof documentSchema]>;
-const PresDocument = makeInterface(presSchema, documentSchema);
+import React = require("react");
 /**
  * This class models the view a document added to presentation will have in the presentation.
  * It involves some functionality for its buttons and options.
  */
 @observer
-export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDocument>(PresDocument) {
+export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() {
     public static LayoutString(fieldKey: string) { return FieldView.LayoutString(PresElementBox, fieldKey); }
     _heightDisposer: IReactionDisposer | undefined;
 
diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx
index 09cfb2077..5fe2a5ab1 100644
--- a/src/client/views/search/SearchBox.tsx
+++ b/src/client/views/search/SearchBox.tsx
@@ -1,28 +1,18 @@
+import { Tooltip } from "@material-ui/core";
 import { action, computed, observable } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
 import { DirectLinksSym, Doc, DocListCast, DocListCastAsync, Field } from '../../../fields/Doc';
-import { documentSchema } from "../../../fields/documentSchemas";
 import { Id } from '../../../fields/FieldSymbols';
-import { createSchema, makeInterface } from '../../../fields/Schema';
 import { StrCast } from '../../../fields/Types';
+import { DocUtils } from '../../documents/Documents';
 import { DocumentType } from "../../documents/DocumentTypes";
+import { DocumentManager } from '../../util/DocumentManager';
 import { CollectionDockingView } from "../collections/CollectionDockingView";
 import { ViewBoxBaseComponent } from "../DocComponent";
 import { FieldView, FieldViewProps } from '../nodes/FieldView';
 import "./SearchBox.scss";
-import { DocumentManager } from '../../util/DocumentManager';
-import { DocUtils } from '../../documents/Documents';
-import { Tooltip } from "@material-ui/core";
-import { DictationOverlay } from '../DictationOverlay';
-import { CollectionSchemaBooleanCell } from '../collections/collectionSchema/CollectionSchemaCells';
-
-export const searchSchema = createSchema({
-    Document: Doc
-});
 
-type SearchBoxDocument = makeInterface<[typeof documentSchema, typeof searchSchema]>;
-const SearchBoxDocument = makeInterface(documentSchema, searchSchema);
 
 const DAMPENING_FACTOR = 0.9;
 const MAX_ITERATIONS = 25;
@@ -38,7 +28,7 @@ export interface SearchBoxProps extends FieldViewProps {
  * the search panel on the left side of the screen.
  */
 @observer
-export class SearchBox extends ViewBoxBaseComponent<SearchBoxProps, SearchBoxDocument>(SearchBoxDocument) {
+export class SearchBox extends ViewBoxBaseComponent<SearchBoxProps>() {
     public static LayoutString(fieldKey: string) { return FieldView.LayoutString(SearchBox, fieldKey); }
     public static Instance: SearchBox;
 
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts
index 63c67aeb0..9efa092a0 100644
--- a/src/fields/Doc.ts
+++ b/src/fields/Doc.ts
@@ -25,6 +25,7 @@ import { Cast, FieldValue, NumCast, StrCast, ToConstructor } from "./Types";
 import { AudioField, ImageField, MapField, PdfField, VideoField, WebField } from "./URLField";
 import { deleteProperty, GetEffectiveAcl, getField, getter, inheritParentAcls, makeEditable, makeReadOnly, normalizeEmail, setter, SharingPermissions, updateFunction } from "./util";
 import JSZip = require("jszip");
+import { InkField } from "./InkField";
 
 export namespace Field {
     export function toKeyValueString(doc: Doc, key: string): string {
@@ -1391,6 +1392,8 @@ export namespace Doc {
 
 }
 
+Scripting.addGlobal(ObjectField);
+Scripting.addGlobal("InkField", InkField);
 Scripting.addGlobal(function idToDoc(id: string): any { return DocServer.GetCachedRefField(id); });
 Scripting.addGlobal(function renameAlias(doc: any) { return StrCast(Doc.GetProto(doc).title).replace(/\([0-9]*\)/, "") + `(${doc.aliasNumber})`; });
 Scripting.addGlobal(function getProto(doc: any) { return Doc.GetProto(doc); });
diff --git a/src/fields/InkField.ts b/src/fields/InkField.ts
index 560cf3d63..473536176 100644
--- a/src/fields/InkField.ts
+++ b/src/fields/InkField.ts
@@ -1,9 +1,8 @@
+import { Bezier } from "bezier-js";
 import { createSimpleSchema, list, object, serializable } from "serializr";
-import { Scripting } from "../client/util/Scripting";
 import { Deserializable } from "../client/util/SerializationHelper";
 import { Copy, ToScriptString, ToString } from "./FieldSymbols";
 import { ObjectField } from "./ObjectField";
-import { Bezier } from "bezier-js";
 
 // Helps keep track of the current ink tool in use.
 export enum InkTool {
@@ -89,5 +88,3 @@ export class InkField extends ObjectField {
         return "InkField";
     }
 }
-
-Scripting.addGlobal("InkField", InkField);
\ No newline at end of file
diff --git a/src/fields/ObjectField.ts b/src/fields/ObjectField.ts
index 9211afe86..461e247db 100644
--- a/src/fields/ObjectField.ts
+++ b/src/fields/ObjectField.ts
@@ -1,6 +1,5 @@
+import { Copy, OnUpdate, Parent, ToScriptString, ToString } from "./FieldSymbols";
 import { RefField } from "./RefField";
-import { OnUpdate, Parent, Copy, ToScriptString, ToString } from "./FieldSymbols";
-import { Scripting } from "../client/util/Scripting";
 
 export abstract class ObjectField {
     public [OnUpdate]?: (diff?: any) => void;
@@ -16,5 +15,3 @@ export namespace ObjectField {
         return field?.[Copy]();
     }
 }
-
-Scripting.addGlobal(ObjectField);
\ No newline at end of file
diff --git a/src/fields/RichTextField.ts b/src/fields/RichTextField.ts
index ae5f301d0..64a01a478 100644
--- a/src/fields/RichTextField.ts
+++ b/src/fields/RichTextField.ts
@@ -1,8 +1,8 @@
-import { ObjectField } from "./ObjectField";
 import { serializable } from "serializr";
-import { Deserializable } from "../client/util/SerializationHelper";
-import { Copy, ToScriptString, ToPlainText, ToString } from "./FieldSymbols";
 import { scriptingGlobal } from "../client/util/Scripting";
+import { Deserializable } from "../client/util/SerializationHelper";
+import { Copy, ToScriptString, ToString } from "./FieldSymbols";
+import { ObjectField } from "./ObjectField";
 
 @scriptingGlobal
 @Deserializable("RichTextField")
diff --git a/src/fields/ScriptField.ts b/src/fields/ScriptField.ts
index 85cd73dfe..258348950 100644
--- a/src/fields/ScriptField.ts
+++ b/src/fields/ScriptField.ts
@@ -1,15 +1,15 @@
-import { ObjectField } from "./ObjectField";
-import { CompiledScript, CompileScript, scriptingGlobal, ScriptOptions, CompileError, CompileResult, Scripting } from "../client/util/Scripting";
-import { Copy, ToScriptString, ToString, Parent, SelfProxy } from "./FieldSymbols";
-import { serializable, createSimpleSchema, map, primitive, object, deserialize, PropSchema, custom, SKIP } from "serializr";
-import { Deserializable, autoObject } from "../client/util/SerializationHelper";
-import { Doc, Field, Opt } from "./Doc";
-import { Plugins, setter } from "./util";
 import { computedFn } from "mobx-utils";
+import { createSimpleSchema, custom, map, object, primitive, PropSchema, serializable, SKIP } from "serializr";
+import { CompiledScript, CompileScript, Scripting, scriptingGlobal } from "../client/util/Scripting";
+import { autoObject, Deserializable } from "../client/util/SerializationHelper";
+import { numberRange } from "../Utils";
+import { Doc, Field, Opt } from "./Doc";
+import { Copy, ToScriptString, ToString } from "./FieldSymbols";
+import { List } from "./List";
+import { ObjectField } from "./ObjectField";
 import { ProxyField } from "./Proxy";
 import { Cast, NumCast } from "./Types";
-import { List } from "./List";
-import { numberRange } from "../Utils";
+import { Plugins } from "./util";
 
 function optional(propSchema: PropSchema) {
     return custom(value => {
diff --git a/webpack.config.js b/webpack.config.js
index 3fd00bcf3..02d91c575 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -3,6 +3,8 @@ var webpack = require('webpack');
 const CopyWebpackPlugin = require("copy-webpack-plugin");
 const HtmlWebpackPlugin = require('html-webpack-plugin');
 const ForkTsCheckerWebpackPlugin = require("fork-ts-checker-webpack-plugin");
+const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');
+
 
 const plugins = [
     new CopyWebpackPlugin([{
@@ -20,6 +22,7 @@ const plugins = [
     new webpack.ProvidePlugin({ Buffer: ['buffer', 'Buffer'], }),
     new webpack.ProvidePlugin({ process: 'process/browser', }),
     new webpack.HotModuleReplacementPlugin(),
+    //new ReactRefreshWebpackPlugin(),
 ];
 
 function transferEnvironmentVariables() {
-- 
cgit v1.2.3-70-g09d2

