From 0a6a540a41243ab9bc9149736fd948b4275bcb85 Mon Sep 17 00:00:00 2001
From: dragonwocky <thedragonring.bod@gmail.com>
Date: Tue, 4 Aug 2020 23:02:20 +1000
Subject: [PATCH] menu options: input + files

---
 repo/bracketed-links/mod.js         |   2 +-
 repo/bracketed-links/styles.css     |   4 +-
 repo/core/create.js                 |   8 +-
 repo/core/css/menu.css              |  71 ++++++++++++++---
 repo/core/icons/alwaysontop_off.svg |   2 +-
 repo/core/icons/alwaysontop_on.svg  |   2 +-
 repo/core/icons/file.svg            |   1 +
 repo/core/icons/maximize_off.svg    |   2 +-
 repo/core/icons/maximize_on.svg     |   2 +-
 repo/core/icons/minimize.svg        |   2 +-
 repo/core/menu.js                   | 116 +++++++++++++++++++++-------
 repo/core/mod.js                    |  13 ++--
 repo/core/tray.js                   |  16 ++++
 repo/custom-inserts/mod.js          |  30 +++++++
 14 files changed, 215 insertions(+), 56 deletions(-)
 create mode 100644 repo/core/icons/file.svg
 create mode 100644 repo/custom-inserts/mod.js

diff --git a/repo/bracketed-links/mod.js b/repo/bracketed-links/mod.js
index c2ad673..981df61 100644
--- a/repo/bracketed-links/mod.js
+++ b/repo/bracketed-links/mod.js
@@ -10,7 +10,7 @@ module.exports = {
   id: '60e14feb-a81d-4ffb-9b12-7585d346bad8',
   tags: ['extension'],
   name: 'bracketed links',
-  desc: 'render links surrounded with [brackets] instead of __underlined__.',
+  desc: 'render links surrounded with [[brackets]] instead of __underlined__.',
   version: '0.0.1',
   author: 'arecsu',
 };
diff --git a/repo/bracketed-links/styles.css b/repo/bracketed-links/styles.css
index 3087e62..8bc3f9d 100644
--- a/repo/bracketed-links/styles.css
+++ b/repo/bracketed-links/styles.css
@@ -9,12 +9,12 @@
   border-bottom: none !important;
 }
 .notion-link-token:before {
-  content: '[';
+  content: '[[';
   opacity: 0.7;
   transition: opacity 100ms ease-in;
 }
 .notion-link-token:after {
-  content: ']';
+  content: ']]';
   opacity: 0.7;
   transition: opacity 100ms ease-in;
 }
diff --git a/repo/core/create.js b/repo/core/create.js
index 1343670..9cee6e8 100644
--- a/repo/core/create.js
+++ b/repo/core/create.js
@@ -18,7 +18,7 @@ module.exports = (store, __exports) => {
     helpers = require('../../pkg/helpers.js'),
     __notion = helpers.getNotion();
 
-  __exports.createWindow = function (relativeUrl) {
+  __exports.createWindow = function (relativeUrl, focused_window) {
     if (!relativeUrl) relativeUrl = '';
     const window_state = require(`${__notion.replace(
         /\\/g,
@@ -32,8 +32,9 @@ module.exports = (store, __exports) => {
         y: window_state.y,
         width: window_state.width,
         height: window_state.height,
-      },
-      focused_window = electron.BrowserWindow.getFocusedWindow();
+      };
+    focused_window =
+      focused_window || electron.BrowserWindow.getFocusedWindow();
     if (focused_window && !focused_window.isMaximized()) {
       rect.x = focused_window.getPosition()[0] + 20;
       rect.y = focused_window.getPosition()[1] + 20;
@@ -81,4 +82,5 @@ module.exports = (store, __exports) => {
     window.loadURL(__exports.getIndexUrl(relativeUrl));
     return window;
   };
+  return __exports.createWindow;
 };
diff --git a/repo/core/css/menu.css b/repo/core/css/menu.css
index 58ee971..a7f8e86 100644
--- a/repo/core/css/menu.css
+++ b/repo/core/css/menu.css
@@ -205,6 +205,7 @@ s {
   font-size: 0.9em;
 }
 #modules section .desc p {
+  font-size: inherit;
   margin: 0;
 }
 #modules section .desc blockquote {
@@ -265,7 +266,16 @@ s {
   margin-bottom: 0.5em;
 }
 
-select {
+.toggle *,
+.input *,
+.select *,
+.file * {
+  cursor: pointer;
+}
+.select select,
+.input input[type='text'],
+.input input[type='number'],
+.file input[type='file'] + label .choose {
   width: 100%;
   margin: 0.25em 0;
   font-size: 0.9rem;
@@ -274,20 +284,59 @@ select {
   color: var(--theme_local--text);
   background: var(--theme_local--main);
 }
-
-.toggle * {
-  cursor: pointer;
+.select select:focus,
+.input input[type='text']:focus,
+.input input[type='number']:focus,
+.file input[type='file']:focus + label .choose,
+.file input[type='file'] + label .choose:hover {
+  outline: var(--theme_local--table-border) solid 2px;
 }
-.toggle input {
+.file input[type='file'],
+.toggle input[type='checkbox'] {
   display: none;
 }
-.toggle input + label {
+
+.input input[type='text'],
+.input input[type='number'] {
+  padding: 0.4rem;
+  cursor: text;
+}
+
+.file input[type='file'] + label .label {
+  position: relative;
   display: flex;
 }
-.toggle input + label .name {
+.file input[type='file'] + label .label .name {
+  flex-basis: calc(100% - 1.5rem);
+}
+.file input[type='file'] + label .label .clear {
+  font-size: 1rem;
+  position: absolute;
+  top: 0.4em;
+  right: 0;
+  width: 1em;
+  height: 0.1em;
+  border: 0.35em solid var(--theme_local--card);
+  background: currentColor;
+}
+.file input[type='file'] + label .choose {
+  display: block;
+  white-space: nowrap;
+  overflow: hidden;
+}
+.file input[type='file'] + label .choose svg {
+  padding-top: 0.5em;
+  height: 1.25em;
+  width: 1.25em;
+}
+
+.toggle input[type='checkbox'] + label {
+  display: flex;
+}
+.toggle input[type='checkbox'] + label .name {
   flex-basis: calc(100% - 2.25em);
 }
-.toggle input + label .switch {
+.toggle input[type='checkbox'] + label .switch {
   position: relative;
   margin-top: 0.5em;
   float: right;
@@ -296,7 +345,7 @@ select {
   background: var(--theme_local--main);
   border-radius: 5px;
 }
-.toggle input + label .switch:before {
+.toggle input[type='checkbox'] + label .switch::before {
   content: '';
   position: absolute;
   left: 0;
@@ -312,7 +361,7 @@ select {
   opacity: var(--menu--toggle_opacity, 0);
   transition: opacity 300ms;
 }
-.toggle input + label .switch .dot {
+.toggle input[type='checkbox'] + label .switch .dot {
   position: absolute;
   width: 1em;
   height: 1em;
@@ -323,7 +372,7 @@ select {
   background: var(--theme_local--todo_ticked-fill);
   box-shadow: 2px 1px 4px var(--theme_local--table-border);
 }
-.toggle input:checked + label {
+.toggle input[type='checkbox']:checked + label {
   --menu--toggle_offset: 1em;
   --menu--toggle_opacity: 1;
 }
diff --git a/repo/core/icons/alwaysontop_off.svg b/repo/core/icons/alwaysontop_off.svg
index 648339d..e8711d6 100644
--- a/repo/core/icons/alwaysontop_off.svg
+++ b/repo/core/icons/alwaysontop_off.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="250" height="250" fill="none" viewBox="0 0 250 250"><path fill="#000" d="M124.859 234.52L67.5474 135.736H102.683V12.184H147.323V135.736H182.459L124.859 234.52Z"></path></svg>
\ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" width="250" height="250" file="currentColor" viewBox="0 0 250 250"><path file="currentColor" d="M124.859 234.52L67.5474 135.736H102.683V12.184H147.323V135.736H182.459L124.859 234.52Z"></path></svg>
\ No newline at end of file
diff --git a/repo/core/icons/alwaysontop_on.svg b/repo/core/icons/alwaysontop_on.svg
index 0c2abaf..4b700e3 100644
--- a/repo/core/icons/alwaysontop_on.svg
+++ b/repo/core/icons/alwaysontop_on.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="250" height="250" fill="none" viewBox="0 0 250 250"><path fill="#000" d="M102.683 234.52V110.968H67.5474L124.859 12.184L182.459 110.968H147.323V234.52H102.683Z"></path></svg>
\ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" width="250" height="250" file="currentColor" viewBox="0 0 250 250"><path file="currentColor" d="M102.683 234.52V110.968H67.5474L124.859 12.184L182.459 110.968H147.323V234.52H102.683Z"></path></svg>
\ No newline at end of file
diff --git a/repo/core/icons/file.svg b/repo/core/icons/file.svg
new file mode 100644
index 0000000..159a961
--- /dev/null
+++ b/repo/core/icons/file.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><path fill="currentColor" d="M224 136V0H24C10.7 0 0 10.7 0 24v464c0 13.3 10.7 24 24 24h336c13.3 0 24-10.7 24-24V160H248c-13.2 0-24-10.8-24-24zm160-14.1v6.1H256V0h6.1c6.4 0 12.5 2.5 17 7l97.9 98c4.5 4.5 7 10.6 7 16.9z" class=""></path></svg>
\ No newline at end of file
diff --git a/repo/core/icons/maximize_off.svg b/repo/core/icons/maximize_off.svg
index ebd1c92..378e3d2 100644
--- a/repo/core/icons/maximize_off.svg
+++ b/repo/core/icons/maximize_off.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="250" height="250" fill="none" viewBox="0 0 250 250"><path fill="#000" d="M14.7346 227.26V7.03998H235.215V227.26H14.7346ZM46.4546 195.8H203.495V70.48H46.4546V195.8Z"></path></svg>
\ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" width="250" height="250" file="currentColor" viewBox="0 0 250 250"><path file="currentColor" d="M14.7346 227.26V7.03998H235.215V227.26H14.7346ZM46.4546 195.8H203.495V70.48H46.4546V195.8Z"></path></svg>
\ No newline at end of file
diff --git a/repo/core/icons/maximize_on.svg b/repo/core/icons/maximize_on.svg
index c7fdcbd..6f19bf5 100644
--- a/repo/core/icons/maximize_on.svg
+++ b/repo/core/icons/maximize_on.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="250" height="250" fill="none" viewBox="0 0 250 250"><path fill="#000" d="M16.1311 225.96V76.72H84.5111V8.07999H233.751V157.32H165.371V225.96H16.1311ZM110.771 53.58V76.72H165.371V131.32H207.491V53.58H110.771ZM42.3911 199.96H139.111V122.22H42.3911V199.96Z"></path></svg>
\ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" width="250" height="250" file="currentColor" viewBox="0 0 250 250"><path file="currentColor" d="M16.1311 225.96V76.72H84.5111V8.07999H233.751V157.32H165.371V225.96H16.1311ZM110.771 53.58V76.72H165.371V131.32H207.491V53.58H110.771ZM42.3911 199.96H139.111V122.22H42.3911V199.96Z"></path></svg>
\ No newline at end of file
diff --git a/repo/core/icons/minimize.svg b/repo/core/icons/minimize.svg
index ec85d9d..3ea3cc9 100644
--- a/repo/core/icons/minimize.svg
+++ b/repo/core/icons/minimize.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="250" height="250" fill="none" viewBox="0 0 250 250"><path fill="#000" d="M17.8021 138.04V106.072H232.074V138.04H17.8021Z"></path></svg>
\ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" width="250" height="250" file="currentColor" viewBox="0 0 250 250"><path file="currentColor" d="M17.8021 138.04V106.072H232.074V138.04H17.8021Z"></path></svg>
\ No newline at end of file
diff --git a/repo/core/menu.js b/repo/core/menu.js
index f5cea1f..013cf9a 100644
--- a/repo/core/menu.js
+++ b/repo/core/menu.js
@@ -8,6 +8,8 @@
 
 const store = require('../../pkg/store.js'),
   helpers = require('../../pkg/helpers.js'),
+  fs = require('fs-extra'),
+  path = require('path'),
   electron = require('electron'),
   browser = electron.remote.getCurrentWindow();
 
@@ -17,7 +19,7 @@ window['__start'] = async () => {
 
   document.defaultView.addEventListener('keyup', (event) => {
     if (event.code === 'F5') window.reload();
-    if (event.key === 'e' && (event.ctrlKey || event.metaKey)) browser.close();
+    if ((event.ctrlKey || event.metaKey) && event.key === 'e') browser.close();
   });
 
   electron.ipcRenderer.on('enhancer:set-theme', (event, theme) => {
@@ -68,11 +70,11 @@ window['__start'] = async () => {
       if (version.local == version.repo) return;
       // compare func from https://github.com/substack/semver-compare
       version.sorted = [version.local, version.repo].sort((a, b) => {
-        var pa = a.split('.');
-        var pb = b.split('.');
-        for (var i = 0; i < 3; i++) {
-          var na = Number(pa[i]);
-          var nb = Number(pb[i]);
+        const pa = a.split('.'),
+          pb = b.split('.');
+        for (let i = 0; i < 3; i++) {
+          let na = Number(pa[i]),
+            nb = Number(pb[i]);
           if (na > nb) return 1;
           if (nb > na) return -1;
           if (!isNaN(na) && isNaN(nb)) return 1;
@@ -133,7 +135,7 @@ window['__start'] = async () => {
           // ![image_title](source)
           .replace(
             /([^\\])?\!\[([^\]]*[^\\\]]?)\]\(([^)]*[^\\)])\)/g,
-            '$1<img alt="" src="$3">$2</img>'
+            '$1<img alt="$2" src="$3">'
           )
           // [link](destination)
           .replace(
@@ -153,7 +155,7 @@ window['__start'] = async () => {
     if (modified_notice) return;
     modified_notice = createAlert(
       'info',
-      `changes may not apply until app restart.`
+      `changes may not fully apply until app restart.`
     );
     modified_notice.append();
   }
@@ -193,7 +195,7 @@ window['__start'] = async () => {
           <div class="desc">${markdown(mod.desc)}</div>
           <p>
             <a href="https://github.com/${mod.author}" class="author">
-              <img src="https://github.com/${mod.author}.png" />
+              <img src="https://github.com/${mod.author}.png">
               ${mod.author}
             </a>
             <span class="version">v${mod.version}</span>
@@ -210,7 +212,9 @@ window['__start'] = async () => {
         menuStore[mod.id].enabled = $enable.checked;
         mod.elem.className = menuStore[mod.id].enabled ? 'enabled' : 'disabled';
       });
+
     const $options = mod.elem.querySelector('.options');
+    let file_icon;
     if ($options)
       for (const opt of mod.options) {
         let $opt;
@@ -219,21 +223,17 @@ window['__start'] = async () => {
             $opt = createElement(`
               <p class="toggle">
                 <input type="checkbox" id="toggle_${mod.id}--${opt.key}"
-                ${store(mod.id)[opt.key] ? 'checked' : ''} />
+                ${
+                  store(mod.id, { [opt.key]: opt.value })[opt.key]
+                    ? 'checked'
+                    : ''
+                } />
                 <label for="toggle_${mod.id}--${opt.key}">
                   <span class="name">${opt.label}</span>
                   <span class="switch"><span class="dot"></span></span>
                 </label>
               </p>
             `);
-            const $opt_checkbox = $opt.querySelector(
-              `#toggle_${mod.id}--${opt.key}`
-            );
-            $opt_checkbox.addEventListener('change', (event) => {
-              store(mod.id)[opt.key] = $opt_checkbox.checked;
-              modified();
-            });
-            $options.appendChild($opt);
             break;
           case 'select':
             $opt = createElement(`
@@ -246,21 +246,83 @@ window['__start'] = async () => {
                 </select>
               </p>
             `);
-            const $opt_select = $opt.querySelector(
-              `#select_${mod.id}--${opt.key}`
-            );
-            $opt_select.value = store(mod.id)[opt.key];
-            $opt_select.addEventListener('change', (event) => {
-              store(mod.id)[opt.key] = $opt_select.value;
-              modified();
-            });
-            $options.appendChild($opt);
             break;
           case 'input':
+            $opt = createElement(`
+              <p class="input">
+                <label for="input_${mod.id}--${opt.key}">${opt.label}</label>
+                <input type="${
+                  typeof opt.value === 'number' ? 'number' : 'text'
+                }" id="input_${mod.id}--${opt.key}">
+              </p>
+            `);
             break;
           case 'file':
+            if (!file_icon)
+              file_icon = await fs.readFile(
+                path.resolve(`${__dirname}/icons/file.svg`)
+              );
+            $opt = createElement(`
+              <p class="file">
+              <input type="file" id="file_${mod.id}--${opt.key}"
+              ${
+                opt.extensions
+                  ? ` accept="${opt.extensions
+                      .map((ext) => (ext.startsWith('.') ? ext : `.${ext}`))
+                      .join(',')}"`
+                  : ''
+              }>
+                <label for="file_${mod.id}--${opt.key}">
+                  <span class="label">
+                    <span class="name">${opt.label}</span>
+                    <button class="clear"></button>
+                  </span>
+                  <span class="choose">
+                    ${file_icon}
+                    <span class="path">${
+                      store(mod.id)[opt.key]
+                        ? store(mod.id)[opt.key].split(path.sep).reverse()[0]
+                        : 'choose a file...'
+                    }</span>
+                  </span>
+                </label>
+              </p>
+            `);
+            $opt.querySelector('.clear').addEventListener('click', (event) => {
+              store(mod.id)[opt.key] = '';
+              $opt.querySelector('.path').innerText = store(mod.id)[opt.key]
+                ? store(mod.id)[opt.key].split(path.sep).reverse()[0]
+                : 'choose a file...';
+            });
             break;
         }
+
+        if (opt.type !== 'file') {
+          $opt.querySelector(
+            `#${opt.type}_${mod.id}--${opt.key}`
+          ).value = store(mod.id, {
+            [opt.key]: opt.type === 'select' ? opt.value[0] : opt.value,
+          })[opt.key];
+        }
+        $opt
+          .querySelector(`#${opt.type}_${mod.id}--${opt.key}`)
+          .addEventListener('change', (event) => {
+            if (opt.type === 'toggle') {
+              store(mod.id)[opt.key] = event.target.checked;
+            } else if (opt.type === 'file') {
+              if (event.target.files.length)
+                store(mod.id)[opt.key] = event.target.files[0].path;
+              $opt.querySelector('.path').innerText = store(mod.id)[opt.key]
+                ? store(mod.id)[opt.key].split(path.sep).reverse()[0]
+                : 'choose a file...';
+            } else
+              store(mod.id)[opt.key] =
+                typeof opt.value === 'number'
+                  ? Number(event.target.value)
+                  : event.target.value;
+            modified();
+          });
+        $options.appendChild($opt);
       }
     $modules.append(mod.elem);
   }
diff --git a/repo/core/mod.js b/repo/core/mod.js
index 6d02054..feca362 100644
--- a/repo/core/mod.js
+++ b/repo/core/mod.js
@@ -10,8 +10,7 @@ module.exports = {
   id: '0f0bf8b6-eae6-4273-b307-8fc43f2ee082',
   tags: ['core', 'extension'],
   name: 'notion-enhancer core',
-  desc: `> the **modloader** itself, _including_: the [CLI](https://github.com), the \`menu\`, and ~~enabling/disabling/insertion/updating of~~ mods.
-    ![](https://preview.redd.it/vtiw9ulqlt951.png?width=1368&format=png&auto=webp&s=733d8b27ec62151c7858b4eca463f809ead6395a)`,
+  desc: 'what makes this whole thing possible: cli, modloader, menu, & tray.',
   version: require('../../package.json').version,
   author: 'dragonwocky',
   options: [
@@ -35,27 +34,27 @@ module.exports = {
     },
     {
       key: 'frameless',
-      label: 'integrate titlebar into notion',
+      label: 'integrated titlebar',
       type: 'toggle',
       value: true,
     },
     {
       key: 'dragarea_height',
-      label: 'height of frameless dragarea',
+      label: 'height of frameless dragarea:',
       type: 'input',
       value: 15,
     },
     {
       key: 'smooth_scrollbars',
-      label: 'integrate scrollbars into notion',
+      label: 'integrated scrollbars',
       type: 'toggle',
       value: true,
     },
     {
       key: 'hotkey',
-      label: 'window display hotkey',
+      label: 'window display hotkey:',
       type: 'input',
-      value: 'CmdOrCtrl+Shift+A',
+      value: 'CommandOrControl+Shift+A',
     },
   ],
   hacks: {
diff --git a/repo/core/tray.js b/repo/core/tray.js
index cc7ddcf..4e98c60 100644
--- a/repo/core/tray.js
+++ b/repo/core/tray.js
@@ -143,6 +143,22 @@ module.exports = (store, __exports) => {
         accelerator: 'CommandOrControl+E',
         click: openExtensionMenu,
       },
+      {
+        type: 'normal',
+        label: 'New Window',
+        click: () => {
+          require('./create.js')(
+            store,
+            require(path.resolve(`${__notion}/app/main/createWindow.js`))
+          )(
+            '',
+            electron.BrowserWindow.getAllWindows().find(
+              (win) => win !== enhancer_menu
+            )
+          );
+        },
+        accelerator: 'CommandOrControl+Shift+N',
+      },
       {
         type: 'separator',
       },
diff --git a/repo/custom-inserts/mod.js b/repo/custom-inserts/mod.js
new file mode 100644
index 0000000..54ca1ff
--- /dev/null
+++ b/repo/custom-inserts/mod.js
@@ -0,0 +1,30 @@
+/*
+ * notion-enhancer
+ * (c) 2020 dragonwocky <thedragonring.bod@gmail.com>
+ * (https://dragonwocky.me/) under the MIT license
+ */
+
+'use strict';
+
+module.exports = {
+  id: 'b4b0aced-2059-43bf-8d1d-ccd757ee5ebb',
+  tags: ['extension'],
+  name: 'custom inserts',
+  desc: 'directly link files for small client-side tweaks.',
+  version: '0.0.2',
+  author: 'dragonwocky',
+  options: [
+    {
+      key: 'css',
+      label: 'css insert',
+      type: 'file',
+      extensions: ['css'],
+    },
+    {
+      key: 'js',
+      label: 'client-side js insert',
+      type: 'file',
+      extensions: ['js'],
+    },
+  ],
+};