From 80d4bf70cb8e29f15d8e51b1e0bd378a26d68fcf Mon Sep 17 00:00:00 2001
From: vellichora <fangrui_tong@brown.edu>
Date: Tue, 7 Jan 2020 03:07:18 -0500
Subject: converted tool tip text menu to react component with basic marks and
 dropdown

---
 src/client/views/DocumentDecorations.tsx | 6 ++++++
 1 file changed, 6 insertions(+)

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

diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 4bc24fa93..76b6a8834 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -26,6 +26,8 @@ import { IconBox } from "./nodes/IconBox";
 import React = require("react");
 import { DocumentType } from '../documents/DocumentTypes';
 import { ScriptField } from '../../new_fields/ScriptField';
+import { render } from 'react-dom';
+import RichTextMenu from '../util/RichTextMenu';
 const higflyout = require("@hig/flyout");
 export const { anchorPoints } = higflyout;
 export const Flyout = higflyout.default;
@@ -572,6 +574,8 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
         if (bounds.y > bounds.b) {
             bounds.y = bounds.b - (this._resizeBorderWidth + this._linkBoxHeight + this._titleHeight);
         }
+        // RichTextMenu.Instance.jumpTo(this._lastX, this._lastY - 50);
+        RichTextMenu.Instance.jumpTo(500, 300);
         return (<div className="documentDecorations">
             <div className="documentDecorations-background" style={{
                 width: (bounds.r - bounds.x + this._resizeBorderWidth) + "px",
@@ -591,6 +595,8 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
             }}>
                 {minimizeIcon}
 
+                {/* <RichTextMenu /> */}
+
                 {this._edtingTitle ?
                     <input ref={this._keyinput} className="title" type="text" name="dynbox" value={this._accumulatedTitle} onBlur={e => this.titleBlur(true)} onChange={this.titleChanged} onKeyPress={this.titleEntered} /> :
                     <div className="title" onPointerDown={this.onTitleDown} ><span>{`${this.selectionTitle}`}</span></div>}
-- 
cgit v1.2.3-70-g09d2


From 80c417f24bcc1109e12645cfc522a820cf22e099 Mon Sep 17 00:00:00 2001
From: vellichora <fangrui_tong@brown.edu>
Date: Tue, 7 Jan 2020 10:51:40 -0500
Subject: pull from master

---
 package-lock.json                        | 77 ++++++++++++++++----------------
 src/client/util/RichTextMenu.tsx         | 20 +--------
 src/client/util/SelectionManager.ts      |  1 +
 src/client/views/DocumentDecorations.tsx | 10 ++++-
 4 files changed, 50 insertions(+), 58 deletions(-)

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

diff --git a/package-lock.json b/package-lock.json
index 0fbc4dcf5..2c70ba94d 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -2423,7 +2423,7 @@
             "resolved": "https://registry.npmjs.org/boolify-string/-/boolify-string-2.0.2.tgz",
             "integrity": "sha1-n4m9l9YKFEijlAF8SjuaPSQNRY4=",
             "requires": {
-                "type-detect": "1.0.0"
+                "type-detect": "^1.0.0"
             },
             "dependencies": {
                 "type-detect": {
@@ -2561,7 +2561,7 @@
         },
         "browserify-aes": {
             "version": "1.2.0",
-            "resolved": "http://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz",
+            "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz",
             "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==",
             "requires": {
                 "buffer-xor": "^1.0.3",
@@ -2595,7 +2595,7 @@
         },
         "browserify-rsa": {
             "version": "4.0.1",
-            "resolved": "http://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz",
+            "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz",
             "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=",
             "requires": {
                 "bn.js": "^4.1.0",
@@ -2632,7 +2632,7 @@
         },
         "buffer": {
             "version": "4.9.1",
-            "resolved": "http://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz",
+            "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz",
             "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=",
             "dev": true,
             "requires": {
@@ -2779,7 +2779,7 @@
         },
         "camelcase-keys": {
             "version": "2.1.0",
-            "resolved": "http://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz",
+            "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz",
             "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=",
             "requires": {
                 "camelcase": "^2.0.0",
@@ -3482,8 +3482,8 @@
             "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
             "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
             "requires": {
-                "object-assign": "4.1.1",
-                "vary": "1.1.2"
+                "object-assign": "^4",
+                "vary": "^1"
             }
         },
         "cosmiconfig": {
@@ -3563,7 +3563,7 @@
         },
         "create-hash": {
             "version": "1.2.0",
-            "resolved": "http://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz",
+            "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz",
             "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==",
             "requires": {
                 "cipher-base": "^1.0.1",
@@ -3575,7 +3575,7 @@
         },
         "create-hmac": {
             "version": "1.1.7",
-            "resolved": "http://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz",
+            "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz",
             "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==",
             "requires": {
                 "cipher-base": "^1.0.3",
@@ -4118,7 +4118,7 @@
         },
         "diffie-hellman": {
             "version": "5.0.3",
-            "resolved": "http://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz",
+            "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz",
             "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==",
             "requires": {
                 "bn.js": "^4.1.0",
@@ -4318,9 +4318,10 @@
         },
         "emit-logger": {
             "version": "github:chocolateboy/emit-logger#b9d25a2d939e42f29c940861e9648bd0fb810070",
+            "from": "github:chocolateboy/emit-logger#better-emitter-name",
             "requires": {
-                "chalk": "1.1.3",
-                "moment": "2.24.0"
+                "chalk": "^1.1.1",
+                "moment": "^2.10.6"
             }
         },
         "emoji-regex": {
@@ -7069,18 +7070,18 @@
             "resolved": "https://registry.npmjs.org/ipc-event-emitter/-/ipc-event-emitter-2.0.2.tgz",
             "integrity": "sha512-hJsN8zCg8MZwl5nbTutqINDO4pJPbKwmCfrTJaRLNE+5H15mJx7Mxo3pXIAi8zlh+N5xpf+PdMOQ0pbtZQvRKA==",
             "requires": {
-                "babel-runtime": "6.26.0",
-                "bluebird": "3.5.5",
-                "boolify-string": "2.0.2",
-                "emit-logger": "github:chocolateboy/emit-logger#b9d25a2d939e42f29c940861e9648bd0fb810070",
-                "lodash": "4.17.15",
-                "semver": "5.7.0",
-                "source-map-support": "0.5.12"
+                "babel-runtime": "^6.22.0",
+                "bluebird": "^3.4.7",
+                "boolify-string": "^2.0.2",
+                "emit-logger": "github:chocolateboy/emit-logger#better-emitter-name",
+                "lodash": "^4.17.4",
+                "semver": "^5.0.3",
+                "source-map-support": "^0.5.9"
             }
         },
         "is-accessor-descriptor": {
             "version": "0.1.6",
-            "resolved": "http://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
+            "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
             "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
             "requires": {
                 "kind-of": "^3.0.2"
@@ -7129,7 +7130,7 @@
         },
         "is-data-descriptor": {
             "version": "0.1.4",
-            "resolved": "http://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
+            "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
             "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
             "requires": {
                 "kind-of": "^3.0.2"
@@ -7914,7 +7915,7 @@
         },
         "load-json-file": {
             "version": "1.1.0",
-            "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
+            "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
             "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
             "requires": {
                 "graceful-fs": "^4.1.2",
@@ -8228,7 +8229,7 @@
         },
         "media-typer": {
             "version": "0.3.0",
-            "resolved": "http://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
+            "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
             "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
         },
         "mem": {
@@ -8260,7 +8261,7 @@
         },
         "meow": {
             "version": "3.7.0",
-            "resolved": "http://registry.npmjs.org/meow/-/meow-3.7.0.tgz",
+            "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz",
             "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=",
             "requires": {
                 "camelcase-keys": "^2.0.0",
@@ -8453,7 +8454,7 @@
         },
         "mkdirp": {
             "version": "0.5.1",
-            "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
+            "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
             "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
             "requires": {
                 "minimist": "0.0.8"
@@ -8799,7 +8800,7 @@
         },
         "next-tick": {
             "version": "1.0.0",
-            "resolved": "http://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz",
+            "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz",
             "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw="
         },
         "nice-try": {
@@ -8963,7 +8964,7 @@
                 },
                 "semver": {
                     "version": "5.3.0",
-                    "resolved": "http://registry.npmjs.org/semver/-/semver-5.3.0.tgz",
+                    "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz",
                     "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8="
                 },
                 "tar": {
@@ -12572,7 +12573,7 @@
         },
         "os-homedir": {
             "version": "1.0.2",
-            "resolved": "http://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
+            "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
             "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M="
         },
         "os-locale": {
@@ -12585,7 +12586,7 @@
         },
         "os-tmpdir": {
             "version": "1.0.2",
-            "resolved": "http://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
+            "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
             "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ="
         },
         "osenv": {
@@ -12825,7 +12826,7 @@
         },
         "path-is-absolute": {
             "version": "1.0.1",
-            "resolved": "http://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+            "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
             "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
         },
         "path-is-inside": {
@@ -14145,7 +14146,7 @@
         },
         "readable-stream": {
             "version": "2.3.6",
-            "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
+            "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
             "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
             "requires": {
                 "core-util-is": "~1.0.0",
@@ -14490,7 +14491,7 @@
         },
         "safe-regex": {
             "version": "1.1.0",
-            "resolved": "http://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
+            "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
             "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=",
             "requires": {
                 "ret": "~0.1.10"
@@ -14755,7 +14756,7 @@
         },
         "sha.js": {
             "version": "2.4.11",
-            "resolved": "http://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz",
+            "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz",
             "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==",
             "requires": {
                 "inherits": "^2.0.1",
@@ -15498,7 +15499,7 @@
         },
         "string_decoder": {
             "version": "1.1.1",
-            "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+            "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
             "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
             "requires": {
                 "safe-buffer": "~5.1.0"
@@ -15528,7 +15529,7 @@
         },
         "strip-ansi": {
             "version": "3.0.1",
-            "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+            "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
             "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
             "requires": {
                 "ansi-regex": "^2.0.0"
@@ -15544,7 +15545,7 @@
         },
         "strip-eof": {
             "version": "1.0.0",
-            "resolved": "http://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
+            "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
             "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8="
         },
         "strip-indent": {
@@ -16297,7 +16298,7 @@
         },
         "tty-browserify": {
             "version": "0.0.0",
-            "resolved": "http://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz",
+            "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz",
             "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=",
             "dev": true
         },
@@ -17739,7 +17740,7 @@
         },
         "wrap-ansi": {
             "version": "2.1.0",
-            "resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
+            "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
             "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
             "requires": {
                 "string-width": "^1.0.1",
diff --git a/src/client/util/RichTextMenu.tsx b/src/client/util/RichTextMenu.tsx
index 371ba97a9..111822307 100644
--- a/src/client/util/RichTextMenu.tsx
+++ b/src/client/util/RichTextMenu.tsx
@@ -53,6 +53,7 @@ export default class RichTextMenu extends AntimodeMenu {
     constructor(props: Readonly<{}>) {
         super(props);
         RichTextMenu.Instance = this;
+        this.Pinned = true;
     }
 
     @action
@@ -79,16 +80,6 @@ export default class RichTextMenu extends AntimodeMenu {
 
         // this.reset_mark_doms();
 
-        // // update link dropdown
-        // const linkDropdown = await this.createLinkDropdown();
-        // const newLinkDropdowndom = linkDropdown.render(this.view).dom;
-        // this._linkDropdownDom && this.tooltip.replaceChild(newLinkDropdowndom, this._linkDropdownDom);
-        // this._linkDropdownDom = newLinkDropdowndom;
-
-        // const targetTitle = await this.getTextLinkTargetTitle();
-        // // console.log(targetTitle);
-        // this.setCurrentLink(targetTitle);
-
         // update active font family and size
         const active = this.getActiveFontStylesOnSelection();
         const activeFamilies = active && active.get("families");
@@ -97,6 +88,7 @@ export default class RichTextMenu extends AntimodeMenu {
         this.activeFontFamily = !activeFamilies || activeFamilies.length === 0 ? "default" : activeFamilies.length === 1 ? String(activeFamilies[0]) : "various";
         this.activeFontSize = !activeSizes || activeSizes.length === 0 ? "default" : activeSizes.length === 1 ? String(activeSizes[0]) + "pt" : "various";
 
+        // update link in current selection
         const targetTitle = await this.getTextLinkTargetTitle();
         this.setCurrentLink(targetTitle);
 
@@ -574,29 +566,21 @@ export default class RichTextMenu extends AntimodeMenu {
         const node = this.view.state.selection.$from.nodeAfter;
         const link = node && node.marks.find(m => m.type === this.view!.state.schema.marks.link);
         const href = link!.attrs.href;
-        console.log("delete link", node, link, href);
         if (href) {
-            console.log("has href");
             if (href.indexOf(Utils.prepend("/doc/")) === 0) {
                 const linkclicked = href.replace(Utils.prepend("/doc/"), "").split("?")[0];
                 if (linkclicked) {
-                    console.log("linkclicked");
                     DocServer.GetRefField(linkclicked).then(async linkDoc => {
                         if (linkDoc instanceof Doc) {
-                            console.log("is doc");
                             LinkManager.Instance.deleteLink(linkDoc);
-                            console.log("remove the link! ", this.view!.state.selection.from, this.view!.state.selection.to, this.view!.state.schema.marks.link);
                             this.view!.dispatch(this.view!.state.tr.removeMark(this.view!.state.selection.from, this.view!.state.selection.to, this.view!.state.schema.marks.link));
                         }
                     });
                 }
             } else {
-                console.log("remove the link! ", this.view!.state.selection.from, this.view!.state.selection.to, this.view!.state.schema.marks.link);
                 if (node) {
                     let extension = this.linkExtend(this.view!.state.selection.$anchor, href);
-                    console.log("remove the link", extension.from, extension.to);
                     this.view!.dispatch(this.view!.state.tr.removeMark(extension.from, extension.to, this.view!.state.schema.marks.link));
-
                 }
             }
         }
diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts
index 4612f10f4..0c733ac47 100644
--- a/src/client/util/SelectionManager.ts
+++ b/src/client/util/SelectionManager.ts
@@ -14,6 +14,7 @@ export namespace SelectionManager {
 
         @action
         SelectDoc(docView: DocumentView, ctrlPressed: boolean): void {
+            console.log("select doc!!!");
             // if doc is not in SelectedDocuments, add it
             if (!manager.SelectedDocuments.get(docView)) {
                 if (!ctrlPressed) {
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 76b6a8834..093761f1f 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -77,6 +77,11 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
         DocumentDecorations.Instance = this;
         this._keyinput = React.createRef();
         reaction(() => SelectionManager.SelectedDocuments().slice(), docs => this.titleBlur(false));
+        console.log("constructing document decorations!!!");
+    }
+
+    componentDidMount() {
+        console.log("mounting deocument deoctirioeon!!!!");
     }
 
     @action titleChanged = (event: any) => this._accumulatedTitle = event.target.value;
@@ -574,8 +579,9 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
         if (bounds.y > bounds.b) {
             bounds.y = bounds.b - (this._resizeBorderWidth + this._linkBoxHeight + this._titleHeight);
         }
-        // RichTextMenu.Instance.jumpTo(this._lastX, this._lastY - 50);
-        RichTextMenu.Instance.jumpTo(500, 300);
+        // // RichTextMenu.Instance.jumpTo(this._lastX, this._lastY - 50);
+        // console.log("jump to ");
+        // RichTextMenu.Instance.jumpTo(500, 300);
         return (<div className="documentDecorations">
             <div className="documentDecorations-background" style={{
                 width: (bounds.r - bounds.x + this._resizeBorderWidth) + "px",
-- 
cgit v1.2.3-70-g09d2


From ced3532239c582938271635802e0d2d62703e148 Mon Sep 17 00:00:00 2001
From: vellichora <fangrui_tong@brown.edu>
Date: Tue, 7 Jan 2020 14:20:36 -0500
Subject: richtextmenu appears whenever formattedtextbox is focused

---
 src/client/util/RichTextMenu.scss           | 64 +++++++++++++++++++++++++++++
 src/client/util/RichTextMenu.tsx            | 58 +++++++++++++++++---------
 src/client/util/SelectionManager.ts         |  3 +-
 src/client/util/TooltipTextMenu.tsx         |  2 +
 src/client/views/DocumentDecorations.tsx    |  8 ----
 src/client/views/nodes/FormattedTextBox.tsx |  7 ++++
 6 files changed, 113 insertions(+), 29 deletions(-)

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

diff --git a/src/client/util/RichTextMenu.scss b/src/client/util/RichTextMenu.scss
index f7414cc7f..85d2765e3 100644
--- a/src/client/util/RichTextMenu.scss
+++ b/src/client/util/RichTextMenu.scss
@@ -20,9 +20,73 @@
         box-shadow: 3px 3px 3px rgba(0, 0, 0, 0.25);
         min-width: 150px;
         padding: 5px;
+
+        button {
+            background-color: #323232;
+            border: 1px solid black;
+            border-radius: 1px;
+            padding: 6px;
+            margin: 5px 0;
+
+            &:hover {
+                background-color: black;
+            }
+        }
     }
 
     input {
         color: black;
     }
+}
+
+.link-menu {
+    .divider {
+        background-color: white;
+        height: 1px;
+        width: 100%;
+    }
+}
+
+.color-preview-button {
+    .color-preview {
+        width: 100%;
+        height: 3px;
+        margin-top: 3px;
+    }
+}
+
+.color-wrapper {
+    display: flex;
+    flex-wrap: wrap;
+    justify-content: space-between;
+
+    button.color-button {
+        width: 20px;
+        height: 20px;
+        border-radius: 15px !important;
+        margin: 3px;
+        border: 2px solid transparent !important;
+        padding: 3px;
+
+        &.active {
+            border: 2px solid white !important;
+        }
+    }
+}
+
+select {
+    background-color: #323232;
+    color: white;
+    border: 1px solid black;
+    border-top: none;
+    border-bottom: none;
+
+    &:focus,
+    &:hover {
+        background-color: black;
+    }
+
+    &::-ms-expand {
+        color: white;
+    }
 }
\ No newline at end of file
diff --git a/src/client/util/RichTextMenu.tsx b/src/client/util/RichTextMenu.tsx
index 111822307..8c373b818 100644
--- a/src/client/util/RichTextMenu.tsx
+++ b/src/client/util/RichTextMenu.tsx
@@ -29,6 +29,7 @@ library.add(faBold, faItalic, faUnderline, faStrikethrough, faSuperscript, faSub
 @observer
 export default class RichTextMenu extends AntimodeMenu {
     static Instance: RichTextMenu;
+    @observable private isVisible: boolean = false;
 
     private view?: EditorView;
     private editorProps: FieldViewProps & FormattedTextBoxProps | undefined;
@@ -53,7 +54,6 @@ export default class RichTextMenu extends AntimodeMenu {
     constructor(props: Readonly<{}>) {
         super(props);
         RichTextMenu.Instance = this;
-        this.Pinned = true;
     }
 
     @action
@@ -73,6 +73,7 @@ export default class RichTextMenu extends AntimodeMenu {
         }
         this.view = view;
         const state = view.state;
+        this.isVisible = true;
         // DocumentDecorations.Instance.showTextBar();
         props && (this.editorProps = props);
         // Don't do anything if the document/selection didn't change
@@ -146,7 +147,6 @@ export default class RichTextMenu extends AntimodeMenu {
     }
 
     destroy() {
-        console.log("destroy");
     }
 
     createButton(faIcon: string, title: string, command?: any, onclick?: any) {
@@ -213,7 +213,6 @@ export default class RichTextMenu extends AntimodeMenu {
     }
 
     changeFontSize = (mark: Mark, view: EditorView) => {
-        console.log("change font size!!");
         const size = mark.attrs.fontSize;
         if (this.editorProps) {
             const ruleProvider = this.editorProps.ruleProvider;
@@ -241,9 +240,7 @@ export default class RichTextMenu extends AntimodeMenu {
     // TODO: remove doesn't work
     //remove all node type and apply the passed-in one to the selected text
     changeListType = (nodeType: NodeType | undefined) => {
-        console.log("change the list type ");
         if (!this.view) return;
-        console.log("change the list type has view");
 
         if (nodeType === schema.nodes.bullet_list) {
             wrapInList(nodeType)(this.view.state, this.view.dispatch);
@@ -354,7 +351,6 @@ export default class RichTextMenu extends AntimodeMenu {
                 this.brushIsEmpty = !this.brushIsEmpty;
             }
         }
-        console.log("brush marks are ", this.brushMarks);
     }
 
     @action toggleColorDropdown() { this.showColorDropdown = !this.showColorDropdown; }
@@ -397,13 +393,23 @@ export default class RichTextMenu extends AntimodeMenu {
 
         return (
             <div className="button-dropdown-wrapper">
-                <button className="antimodeMenu-button" title="" onPointerDown={onColorClick}><FontAwesomeIcon icon="palette" size="lg" /></button>
+                <button className="antimodeMenu-button color-preview-button" title="" onPointerDown={onColorClick}>
+                    <FontAwesomeIcon icon="palette" size="lg" />
+                    <div className="color-preview" style={{ backgroundColor: this.activeFontColor }}></div>
+                </button>
                 <button className="dropdown-button antimodeMenu-button" onPointerDown={onDropdownClick}><FontAwesomeIcon icon="caret-down" size="sm" /></button>
                 {this.showColorDropdown ?
                     (<div className="dropdown">
-                        {colors.map(color => {
-                            if (color) return <button style={{ backgroundColor: color }} onPointerDown={e => changeColor(e, color)}></button>;
-                        })}
+                        <p>Change font color:</p>
+                        <div className="color-wrapper">
+                            {colors.map(color => {
+                                if (color) {
+                                    return this.activeFontColor === color ?
+                                        <button className="color-button active" style={{ backgroundColor: color }} onPointerDown={e => changeColor(e, color)}></button> :
+                                        <button className="color-button" style={{ backgroundColor: color }} onPointerDown={e => changeColor(e, color)}></button>;
+                                }
+                            })}
+                        </div>
                     </div>)
                     : <></>}
             </div>
@@ -459,13 +465,23 @@ export default class RichTextMenu extends AntimodeMenu {
 
         return (
             <div className="button-dropdown-wrapper">
-                <button className="antimodeMenu-button" title="" onPointerDown={onHighlightClick}><FontAwesomeIcon icon="highlighter" size="lg" /></button>
+                <button className="antimodeMenu-button color-preview-button" title="" onPointerDown={onHighlightClick}>
+                    <FontAwesomeIcon icon="highlighter" size="lg" />
+                    <div className="color-preview" style={{ backgroundColor: this.activeHighlightColor }}></div>
+                </button>
                 <button className="dropdown-button antimodeMenu-button" onPointerDown={onDropdownClick}><FontAwesomeIcon icon="caret-down" size="sm" /></button>
                 {this.showHighlightDropdown ?
                     (<div className="dropdown">
-                        {colors.map(color => {
-                            if (color) return <button style={{ backgroundColor: color }} onPointerDown={e => changeHighlight(e, color)}></button>;
-                        })}
+                        <p>Change highlight color:</p>
+                        <div className="color-wrapper">
+                            {colors.map(color => {
+                                if (color) {
+                                    return this.activeHighlightColor === color ?
+                                        <button className="color-button active" style={{ backgroundColor: color }} onPointerDown={e => changeHighlight(e, color)}>{color === "transparent" ? "X" : ""}</button> :
+                                        <button className="color-button" style={{ backgroundColor: color }} onPointerDown={e => changeHighlight(e, color)}>{color === "transparent" ? "X" : ""}</button>;
+                                }
+                            })}
+                        </div>
                     </div>)
                     : <></>}
             </div>
@@ -492,9 +508,6 @@ export default class RichTextMenu extends AntimodeMenu {
             self.setCurrentLink(e.target.value);
         }
 
-        // const targetTitle = this.getTextLinkTargetTitle();
-        console.log("link curr is ", this.currentLink);
-        // // this.setCurrentLink(targetTitle);
         const link = this.currentLink ? this.currentLink : "";
 
         return (
@@ -502,11 +515,12 @@ export default class RichTextMenu extends AntimodeMenu {
                 <button className="antimodeMenu-button" title="" onPointerDown={onDropdownClick}><FontAwesomeIcon icon="link" size="lg" /></button>
                 <button className="dropdown-button antimodeMenu-button" onPointerDown={onDropdownClick}><FontAwesomeIcon icon="caret-down" size="sm" /></button>
                 {this.showLinkDropdown ?
-                    (<div className="dropdown">
+                    (<div className="dropdown link-menu">
                         <p>Linked to:</p>
                         <input value={link} placeholder="Enter URL" onChange={onLinkChange} />
-                        <button onPointerDown={e => this.makeLinkToURL(link, "onRight")}>Apply hyperlink</button>
-                        <button onPointerDown={e => this.deleteLink()}>Remove link</button>
+                        <button className="make-button" onPointerDown={e => this.makeLinkToURL(link, "onRight")}>Apply hyperlink</button>
+                        <div className="divider"></div>
+                        <button className="remove-button" onPointerDown={e => this.deleteLink()}>Remove link</button>
                     </div>)
                     : <></>}
             </div>
@@ -634,6 +648,10 @@ export default class RichTextMenu extends AntimodeMenu {
     }
 
     render() {
+        // if (!this.isVisible) return <></>;
+        SelectionManager.SelectedDocuments()
+        // if (this.Pinned || )
+
         const fontSizeOptions = [
             { mark: schema.marks.pFontSize.create({ fontSize: 7 }), title: "Set font size", label: "7pt", command: this.changeFontSize },
             { mark: schema.marks.pFontSize.create({ fontSize: 8 }), title: "Set font size", label: "8pt", command: this.changeFontSize },
diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts
index 0c733ac47..86a7a620e 100644
--- a/src/client/util/SelectionManager.ts
+++ b/src/client/util/SelectionManager.ts
@@ -3,6 +3,8 @@ import { Doc } from "../../new_fields/Doc";
 import { DocumentView } from "../views/nodes/DocumentView";
 import { computedFn } from "mobx-utils";
 import { List } from "../../new_fields/List";
+import { DocumentDecorations } from "../views/DocumentDecorations";
+import RichTextMenu from "./RichTextMenu";
 
 export namespace SelectionManager {
 
@@ -14,7 +16,6 @@ export namespace SelectionManager {
 
         @action
         SelectDoc(docView: DocumentView, ctrlPressed: boolean): void {
-            console.log("select doc!!!");
             // if doc is not in SelectedDocuments, add it
             if (!manager.SelectedDocuments.get(docView)) {
                 if (!ctrlPressed) {
diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx
index 33257b658..2c4d08b82 100644
--- a/src/client/util/TooltipTextMenu.tsx
+++ b/src/client/util/TooltipTextMenu.tsx
@@ -20,6 +20,8 @@ import { PastelSchemaPalette, DarkPastelSchemaPalette } from '../../new_fields/S
 const { toggleMark, setBlockType } = require("prosemirror-commands");
 const { openPrompt, TextField } = require("./ProsemirrorCopy/prompt.js");
 
+// deprecated in favor of richtextmenu
+
 //appears above a selection of text in a RichTextBox to give user options such as Bold, Italics, etc.
 export class TooltipTextMenu {
     public static Toolbar: HTMLDivElement | undefined;
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 093761f1f..799b3695c 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -77,11 +77,6 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
         DocumentDecorations.Instance = this;
         this._keyinput = React.createRef();
         reaction(() => SelectionManager.SelectedDocuments().slice(), docs => this.titleBlur(false));
-        console.log("constructing document decorations!!!");
-    }
-
-    componentDidMount() {
-        console.log("mounting deocument deoctirioeon!!!!");
     }
 
     @action titleChanged = (event: any) => this._accumulatedTitle = event.target.value;
@@ -579,9 +574,6 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
         if (bounds.y > bounds.b) {
             bounds.y = bounds.b - (this._resizeBorderWidth + this._linkBoxHeight + this._titleHeight);
         }
-        // // RichTextMenu.Instance.jumpTo(this._lastX, this._lastY - 50);
-        // console.log("jump to ");
-        // RichTextMenu.Instance.jumpTo(500, 300);
         return (<div className="documentDecorations">
             <div className="documentDecorations-background" style={{
                 width: (bounds.r - bounds.x + this._resizeBorderWidth) + "px",
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index f00a24d41..7d48a0859 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -48,6 +48,7 @@ import { CollectionFreeFormView } from '../collections/collectionFreeForm/Collec
 import { InkTool } from '../../../new_fields/InkField';
 import { TraceMobx } from '../../../new_fields/util';
 import RichTextMenu from '../../util/RichTextMenu';
+import { DocumentDecorations } from '../DocumentDecorations';
 
 library.add(faEdit);
 library.add(faSmile, faTextHeight, faUpload);
@@ -910,6 +911,9 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps &
         prosediv && (prosediv.keeplocation = undefined);
         const pos = this._editorView?.state.selection.$from.pos || 1;
         keeplocation && setTimeout(() => this._editorView?.dispatch(this._editorView?.state.tr.setSelection(TextSelection.create(this._editorView.state.doc, pos))));
+
+        // jump rich text menu to this textbox
+        this._ref.current && RichTextMenu.Instance.jumpTo(this._ref.current.getBoundingClientRect().x, this._ref.current?.getBoundingClientRect().y - 70);
     }
     onPointerWheel = (e: React.WheelEvent): void => {
         // if a text note is not selected and scrollable, this prevents us from being able to scroll and zoom out at the same time
@@ -1055,6 +1059,9 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps &
             this._undoTyping = undefined;
         }
         this.doLinkOnDeselect();
+
+        // move the richtextmenu offscreen
+        if (!RichTextMenu.Instance.Pinned) RichTextMenu.Instance.jumpTo(-300, -300);
     }
 
     _lastTimedMark: Mark | undefined = undefined;
-- 
cgit v1.2.3-70-g09d2

