From 62ba1277934fcd4bc94fd8b0b20ccb6ee1de12ec Mon Sep 17 00:00:00 2001
From: dragonwocky <thedragonring.bod@gmail.com>
Date: Tue, 27 Apr 2021 22:06:45 +1000
Subject: [PATCH] add mod enabling/disabling

---
 extension/helpers.js                          | 53 ++++++++++++-------
 extension/launcher.js                         |  1 +
 .../menu.css                                  |  5 +-
 .../menu.js                                   | 28 +++++++---
 4 files changed, 57 insertions(+), 30 deletions(-)

diff --git a/extension/helpers.js b/extension/helpers.js
index b332a0c..5449002 100644
--- a/extension/helpers.js
+++ b/extension/helpers.js
@@ -196,45 +196,50 @@ fmt.slugger = (heading, slugs = new Set()) => {
   return slug;
 };
 
-regexers.uuid = (str) => {
+regexers.uuid = (str, err = () => {}) => {
   const match = str.match(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i);
   if (match && match.length) return true;
-  error(`invalid uuid ${str}`);
-  return false;
+  err(`invalid uuid ${str}`);
+  return ERROR;
 };
-regexers.semver = (str) => {
+regexers.semver = (str, err = () => {}) => {
   const match = str.match(
     /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/i
   );
   if (match && match.length) return true;
-  error(`invalid semver ${str}`);
-  return false;
+  err(`invalid semver ${str}`);
+  return ERROR;
 };
-regexers.email = (str) => {
+regexers.email = (str, err = () => {}) => {
   const match = str.match(
     /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/i
   );
   if (match && match.length) return true;
-  error(`invalid email ${str}`);
-  return false;
+  err(`invalid email ${str}`);
+  return ERROR;
 };
-regexers.url = (str) => {
+regexers.url = (str, err = () => {}) => {
   const match = str.match(
     /^[(http(s)?):\/\/(www\.)?a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)$/i
   );
   if (match && match.length) return true;
-  error(`invalid url ${str}`);
-  return false;
+  err(`invalid url ${str}`);
+  return ERROR;
 };
 
+registry.CORE = [
+  'a6621988-551d-495a-97d8-3c568bca2e9e',
+  '0f0bf8b6-eae6-4273-b307-8fc43f2ee082',
+];
+
 registry.validate = async (mod, err, check) => {
   let conditions = [
     check('name', mod.name, typeof mod.name === 'string'),
     check('id', mod.id, typeof mod.id === 'string').then((id) =>
-      id === ERROR ? ERROR : regexers.uuid(id)
+      id === ERROR ? ERROR : regexers.uuid(id, err)
     ),
     check('version', mod.version, typeof mod.version === 'string').then((version) =>
-      version === ERROR ? ERROR : regexers.semver(version)
+      version === ERROR ? ERROR : regexers.semver(version, err)
     ),
     check('description', mod.description, typeof mod.description === 'string'),
     check(
@@ -242,7 +247,7 @@ registry.validate = async (mod, err, check) => {
       mod.preview,
       mod.preview === undefined || typeof mod.preview === 'string'
     ).then((preview) =>
-      preview ? (preview === ERROR ? ERROR : regexers.url(preview)) : undefined
+      preview ? (preview === ERROR ? ERROR : regexers.url(preview, err)) : undefined
     ),
     check('tags', mod.tags, Array.isArray(mod.tags)).then((tags) =>
       tags === ERROR ? ERROR : tags.map((tag) => check('tag', tag, typeof tag === 'string'))
@@ -256,12 +261,12 @@ registry.validate = async (mod, err, check) => {
               'author.email',
               author.email,
               typeof author.email === 'string'
-            ).then((email) => (email === ERROR ? ERROR : regexers.email(email))),
+            ).then((email) => (email === ERROR ? ERROR : regexers.email(email, err))),
             check('author.url', author.url, typeof author.url === 'string').then((url) =>
-              url === ERROR ? ERROR : regexers.url(url)
+              url === ERROR ? ERROR : regexers.url(url, err)
             ),
             check('author.icon', author.icon, typeof author.icon === 'string').then((icon) =>
-              icon === ERROR ? ERROR : regexers.url(icon)
+              icon === ERROR ? ERROR : regexers.url(icon, err)
             ),
           ])
     ),
@@ -420,7 +425,10 @@ registry.validate = async (mod, err, check) => {
   return conditions;
 };
 registry.defaults = async (id) => {
-  const mod = (await registry.get()).find((mod) => mod.id === id);
+  const mod =
+    regexers.uuid(id) !== ERROR
+      ? (await registry.get()).find((mod) => mod.id === id)
+      : undefined;
   if (!mod || !mod.options) return {};
   const defaults = {};
   for (const opt of mod.options) {
@@ -445,7 +453,8 @@ registry.defaults = async (id) => {
   return defaults;
 };
 
-registry.get = async () => {
+registry.get = async (enabled) => {
+  if (registry._list && registry._list.length) return registry._list;
   registry._list = [];
   if (!registry._errors) registry._errors = [];
   for (const dir of await fs.getJSON('repo/registry.json')) {
@@ -472,3 +481,7 @@ registry.errors = async () => {
   if (!registry._errors) await registry.get();
   return registry._errors;
 };
+registry.enabled = async (id) => {
+  if (registry.CORE.includes(id)) return true;
+  return await storage.get('_enabled', id, false);
+};
diff --git a/extension/launcher.js b/extension/launcher.js
index 2cb71e9..702decf 100644
--- a/extension/launcher.js
+++ b/extension/launcher.js
@@ -9,6 +9,7 @@
 import(chrome.runtime.getURL('helpers.js')).then(({ web, registry }) => {
   web.whenReady().then(async () => {
     for (let mod of await registry.get()) {
+      if (!(await registry.enabled(mod.id))) continue;
       for (let sheet of mod.css?.client || []) {
         web.loadStyleset(`repo/${mod._dir}/${sheet}`);
       }
diff --git a/extension/repo/menu@a6621988-551d-495a-97d8-3c568bca2e9e/menu.css b/extension/repo/menu@a6621988-551d-495a-97d8-3c568bca2e9e/menu.css
index 2674e5d..317c9f2 100644
--- a/extension/repo/menu@a6621988-551d-495a-97d8-3c568bca2e9e/menu.css
+++ b/extension/repo/menu@a6621988-551d-495a-97d8-3c568bca2e9e/menu.css
@@ -361,11 +361,10 @@ label [data-icon='fa/question-circle'] {
   border: none;
   background: none;
 }
-.library--title {
-  margin: 0;
-}
+.library--title,
 .library--title h2 {
   margin: 0;
+  font-size: var(--theme--font_ui-size);
 }
 .library--title h2 > span {
   font-size: var(--theme--font_heading2-size);
diff --git a/extension/repo/menu@a6621988-551d-495a-97d8-3c568bca2e9e/menu.js b/extension/repo/menu@a6621988-551d-495a-97d8-3c568bca2e9e/menu.js
index 5860ad7..7176aad 100644
--- a/extension/repo/menu@a6621988-551d-495a-97d8-3c568bca2e9e/menu.js
+++ b/extension/repo/menu@a6621988-551d-495a-97d8-3c568bca2e9e/menu.js
@@ -10,6 +10,7 @@ const _id = 'a6621988-551d-495a-97d8-3c568bca2e9e';
 import { env, storage, web, fmt, fs, registry } from '../../helpers.js';
 
 for (let mod of await registry.get()) {
+  if (!(await registry.enabled(mod.id))) continue;
   for (let sheet of mod.css?.menu || []) {
     web.loadStyleset(`repo/${mod._dir}/${sheet}`);
   }
@@ -50,13 +51,21 @@ components.card = {
       alt=""
       class="library--preview"
       src="${web.escapeHtml(preview)}"
-    />`),
-  name: ({ name, id, version }) =>
-    web.createElement(web.html`<label
+      />`),
+  async name({ name, id, version }) {
+    if (registry.CORE.includes(id))
+      return web.createElement(web.html`<div class="library--title"><h2>
+      <span>
+        ${web.escapeHtml(name)}
+        <span class="library--version">v${web.escapeHtml(version)}</span>
+      </span>
+    </h2></div>`);
+    const $name = web.createElement(web.html`<label
       for="enable--${web.escapeHtml(id)}"
       class="library--title library--toggle_label"
-    >
-      <input type="checkbox" id="enable--${web.escapeHtml(id)}" />
+      >
+      <input type="checkbox" id="enable--${web.escapeHtml(id)}"
+      ${(await storage.get('_enabled', id, false)) ? 'checked' : ''}/>
       <h2>
         <span>
           ${web.escapeHtml(name)}
@@ -64,7 +73,12 @@ components.card = {
         </span>
         <span class="library--toggle"></span>
       </h2>
-    </label>`),
+    </label>`);
+    $name.addEventListener('change', async (event) =>
+      storage.set('_enabled', id, !(await storage.get('_enabled', id, false)))
+    );
+    return $name;
+  },
   tags: ({ tags = [] }) =>
     web.createElement(web.html`<ul class="library--tags">
       ${tags.map((tag) => web.html`<li>#${web.escapeHtml(tag)}</li>`).join('')}
@@ -102,7 +116,7 @@ components.card = {
     const card = web.createElement(web.html`<article class="library--card"></article>`),
       body = web.createElement(web.html`<div></div>`);
     card.append(this.preview(mod));
-    body.append(this.name(mod));
+    body.append(await this.name(mod));
     body.append(this.tags(mod));
     body.append(this.description(mod));
     body.append(this.authors(mod));