From c6de68c4c4bda3edcf6cf012bd98adea3baf866b Mon Sep 17 00:00:00 2001
From: ManeraKai <manerakai@protonmail.com>
Date: Thu, 25 Jul 2024 15:17:57 +0300
Subject: Migrating popup to svelte

---
 src/pages/components/Button.svelte | 29 +++++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)
 create mode 100644 src/pages/components/Button.svelte

(limited to 'src/pages/components/Button.svelte')

diff --git a/src/pages/components/Button.svelte b/src/pages/components/Button.svelte
new file mode 100644
index 00000000..3405c2ea
--- /dev/null
+++ b/src/pages/components/Button.svelte
@@ -0,0 +1,29 @@
+<button on:click {...$$props}>
+  <slot></slot>
+</button>
+
+<style>
+  button {
+    color: var(--text);
+    border: none;
+    text-decoration: none;
+    cursor: pointer;
+    font-size: 16px;
+    font-weight: bold;
+    transition-duration: 0.1s;
+    display: inline-flex;
+    align-items: center;
+    margin: 7.5px 0;
+    background-color: var(--bg-secondary);
+    border-radius: 5px;
+    padding: 10px;
+  }
+
+  button:hover {
+    color: var(--active);
+  }
+
+  button:active {
+    transform: translateY(1px);
+  }
+</style>
-- 
cgit 1.4.1


From ed0c90ec3de1fa5fa8f7ebc138d62174eb07b363 Mon Sep 17 00:00:00 2001
From: ManeraKai <manerakai@protonmail.com>
Date: Sat, 27 Jul 2024 12:11:54 +0300
Subject: Cleaned code

---
 src/pages/components/Button.svelte                 |  2 +-
 src/pages/components/Input.svelte                  |  2 +-
 src/pages/components/Row.svelte                    |  2 +-
 src/pages/options_src/General/General.svelte       |  6 ++--
 .../options_src/General/SettingsButtons.svelte     | 34 +++++++---------------
 src/pages/options_src/Sidebar.svelte               |  6 ++--
 6 files changed, 18 insertions(+), 34 deletions(-)

(limited to 'src/pages/components/Button.svelte')

diff --git a/src/pages/components/Button.svelte b/src/pages/components/Button.svelte
index 3405c2ea..8836b47e 100644
--- a/src/pages/components/Button.svelte
+++ b/src/pages/components/Button.svelte
@@ -1,4 +1,4 @@
-<button on:click {...$$props}>
+<button {...$$restProps} on:click {...$$props}>
   <slot></slot>
 </button>
 
diff --git a/src/pages/components/Input.svelte b/src/pages/components/Input.svelte
index 97a47e6d..59e584db 100644
--- a/src/pages/components/Input.svelte
+++ b/src/pages/components/Input.svelte
@@ -3,7 +3,7 @@
 </script>
 
 <input
-  {...$$props}
+  {...$$restProps}
   bind:value
   on:blur
   on:change
diff --git a/src/pages/components/Row.svelte b/src/pages/components/Row.svelte
index 68b528e3..09246d98 100644
--- a/src/pages/components/Row.svelte
+++ b/src/pages/components/Row.svelte
@@ -1,4 +1,4 @@
-<div {...$$props} on:click>
+<div {...$$restProps} on:click>
   <slot></slot>
 </div>
 
diff --git a/src/pages/options_src/General/General.svelte b/src/pages/options_src/General/General.svelte
index 732ad83b..37c38a0a 100644
--- a/src/pages/options_src/General/General.svelte
+++ b/src/pages/options_src/General/General.svelte
@@ -38,7 +38,6 @@
         _options.theme = e.target.options[e.target.options.selectedIndex].value
         options.set(_options)
       }}
-      ariaLabel="select theme"
     />
   </Row>
 
@@ -55,7 +54,6 @@
         _options.fetchInstances = e.target.options[e.target.options.selectedIndex].value
         options.set(_options)
       }}
-      ariaLabel={"Select fetch public instances"}
     />
   </Row>
 
@@ -75,7 +73,7 @@
     <Checkbox bind:checked={bookmarksPermission} />
   </Row>
 
-  <Exceptions opts={_options} />
+  <Exceptions />
 
-  <SettingsButtons opts={_options} />
+  <SettingsButtons />
 </div>
diff --git a/src/pages/options_src/General/SettingsButtons.svelte b/src/pages/options_src/General/SettingsButtons.svelte
index 3ea46a2d..2f574199 100644
--- a/src/pages/options_src/General/SettingsButtons.svelte
+++ b/src/pages/options_src/General/SettingsButtons.svelte
@@ -14,24 +14,18 @@
   const unsubscribe = options.subscribe(val => (_options = val))
   onDestroy(unsubscribe)
 
-  let disableButtons = false
-
   let importSettingsInput
   let importSettingsFiles
   $: if (importSettingsFiles) {
-    disableButtons = true
     const reader = new FileReader()
     reader.readAsText(importSettingsFiles[0])
     reader.onload = async () => {
       const data = JSON.parse(reader.result)
       if ("theme" in data && data.version == browser.runtime.getManifest().version) {
         browser.storage.local.clear(async () => {
-          console.log("clearing")
           options.set(data)
-          disableButtons = false
         })
       } else {
-        console.log("incompatible settings")
         alert("Incompatible settings")
       }
     }
@@ -42,26 +36,21 @@
   }
 
   async function exportSettings() {
-    disableButtons = true
     _options.version = browser.runtime.getManifest().version
     const resultString = JSON.stringify(_options, null, "  ")
     const anchor = document.createElement("a")
     anchor.href = "data:application/json;base64," + btoa(resultString)
     anchor.download = `libredirect-settings-v${_options.version}.json`
     anchor.click()
-    disableButtons = false
   }
 
   async function exportSettingsSync() {
-    disableButtons = true
     _options.version = browser.runtime.getManifest().version
     await servicesHelper.initDefaults()
     browser.storage.sync.set({ options: _options })
-    disableButtons = false
   }
 
   async function importSettingsSync() {
-    disableButtons = true
     browser.storage.sync.get({ options }, r => {
       const optionsSync = r.options
       if (optionsSync.version == browser.runtime.getManifest().version) {
@@ -69,24 +58,21 @@
       } else {
         alert("Error")
       }
-      disableButtons = false
     })
   }
 
   async function resetSettings() {
-    disableButtons = true
     browser.storage.local.clear(async () => {
       await servicesHelper.initDefaults()
       options.set(await utils.getOptions())
-      disableButtons = false
     })
   }
 </script>
 
 <div class="buttons">
-  <Button on:click={() => importSettingsInput.click()} disabled={disableButtons}>
+  <Button on:click={() => importSettingsInput.click()}>
     <ImportIcon class="margin margin_{document.body.dir}" />
-    <x data-localise="__MSG_importSettings__">{browser.i18n.getMessage("importSettings") || "Import Settings"}</x>
+    {browser.i18n.getMessage("importSettings") || "Import Settings"}
   </Button>
   <input
     type="file"
@@ -96,24 +82,24 @@
     bind:files={importSettingsFiles}
   />
 
-  <Button on:click={exportSettings} disabled={disableButtons}>
+  <Button on:click={exportSettings}>
     <ExportIcon class="margin margin_{document.body.dir}" />
-    <x data-localise="__MSG_exportSettings__">{browser.i18n.getMessage("exportSettings") || "Export Settings"}</x>
+    {browser.i18n.getMessage("exportSettings") || "Export Settings"}
   </Button>
 
-  <Button on:click={exportSettingsSync} disabled={disableButtons}>
+  <Button on:click={exportSettingsSync}>
     <ExportIcon class="margin margin_{document.body.dir}" />
-    <x>Export Settings to Sync</x>
+    {browser.i18n.getMessage("exportSettingsToSync") || "Export Settings to Sync"}
   </Button>
 
-  <Button on:click={importSettingsSync} disabled={disableButtons}>
+  <Button on:click={importSettingsSync}>
     <ImportIcon class="margin margin_{document.body.dir}" />
-    <x>{browser.i18n.getMessage("importSettingsFromSync") || "Import Settings from Sync"}</x>
+    {browser.i18n.getMessage("importSettingsFromSync") || "Import Settings from Sync"}
   </Button>
 
-  <Button on:click={resetSettings} disabled={disableButtons}>
+  <Button on:click={resetSettings}>
     <ResetIcon class="margin margin_{document.body.dir}" />
-    <x>{browser.i18n.getMessage("resetSettings") || "Reset Settings"}</x>
+    {browser.i18n.getMessage("resetSettings") || "Reset Settings"}
   </Button>
 </div>
 
diff --git a/src/pages/options_src/Sidebar.svelte b/src/pages/options_src/Sidebar.svelte
index fb515f53..97780b15 100644
--- a/src/pages/options_src/Sidebar.svelte
+++ b/src/pages/options_src/Sidebar.svelte
@@ -10,15 +10,15 @@
 <div>
   <a href="#general" on:click={() => page.set("general")} style={$page == "general" && "color: var(--active);"}>
     <GeneralIcon class="margin margin_{document.body.dir}" />
-    <span data-localise="__MSG_general__">{browser.i18n.getMessage("general") || "General"}</span>
+    {browser.i18n.getMessage("general") || "General"}
   </a>
   <a href="#services" on:click={() => page.set("services")} style={$page == "services" && "color: var(--active);"}>
     <ServicesIcon class="margin margin_{document.body.dir}" />
-    <span data-localise="__MSG_services__">{browser.i18n.getMessage("general") || "Services"}</span>
+    {browser.i18n.getMessage("general") || "Services"}
   </a>
   <a href="https://libredirect.github.io" target="_blank" rel="noopener noreferrer">
     <AboutIcon class="margin margin_{document.body.dir}" />
-    <span data-localise="__MSG_about__">{browser.i18n.getMessage("about") || "About"}</span>
+    {browser.i18n.getMessage("about") || "About"}
   </a>
 </div>
 
-- 
cgit 1.4.1


From 97d390737e7e953fe1e6559e41963c547b31afa0 Mon Sep 17 00:00:00 2001
From: ManeraKai <manerakai@protonmail.com>
Date: Thu, 29 Aug 2024 13:36:21 +0300
Subject: Improving popup messages

---
 .gitignore                                      |   3 +-
 package.json                                    |   2 +-
 rollup.config.js                                |   4 +
 src/assets/javascripts/services.js              |  27 +++--
 src/assets/javascripts/utils.js                 |  53 +++++++++-
 src/config.json                                 |   2 +-
 src/pages/background/background.js              |  21 +++-
 src/pages/components/Button.svelte              |  10 +-
 src/pages/messages/index.html                   |  14 +++
 src/pages/messages/no_instance.html             |  24 -----
 src/pages/messages_src/App.svelte               | 132 ++++++++++++++++++++++++
 src/pages/messages_src/main.js                  |   7 ++
 src/pages/messages_src/stores.js                |   5 +
 src/pages/options_src/App.svelte                |  44 +-------
 src/pages/options_src/Services/Instances.svelte |  13 +--
 src/pages/popup_src/App.svelte                  |  42 +-------
 16 files changed, 266 insertions(+), 137 deletions(-)
 create mode 100644 src/pages/messages/index.html
 delete mode 100644 src/pages/messages/no_instance.html
 create mode 100644 src/pages/messages_src/App.svelte
 create mode 100644 src/pages/messages_src/main.js
 create mode 100644 src/pages/messages_src/stores.js

(limited to 'src/pages/components/Button.svelte')

diff --git a/.gitignore b/.gitignore
index f9768f05..c10438e0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,4 +6,5 @@ package-lock.json
 .vscode
 pnpm-lock.yaml
 src/pages/options/build
-src/pages/popup/build
\ No newline at end of file
+src/pages/popup/build
+src/pages/messages/build
\ No newline at end of file
diff --git a/package.json b/package.json
index 7b9fbd11..83705623 100644
--- a/package.json
+++ b/package.json
@@ -14,7 +14,7 @@
     "build": "web-ext build -i pages/options_src -i pages/popup_src pages/icons -i pages/popup_src -i pages/components",
     "build_chromium": "brave-browser --pack-extension=src/ --pack-extension-key=src.pem",
     "test": "web-ext lint",
-    "html": "rollup -c --config-popup && rollup -c --config-options"
+    "html": "rollup -c --config-popup && rollup -c --config-options && rollup -c --config-messages"
   },
   "repository": {
     "type": "git",
diff --git a/rollup.config.js b/rollup.config.js
index 5a2ce362..0bad0c97 100644
--- a/rollup.config.js
+++ b/rollup.config.js
@@ -14,6 +14,10 @@ if (process.argv.includes("--config-options")) {
   input = "src/pages/popup_src/main.js"
   output = "src/pages/popup/build/bundle.js"
 }
+else if (process.argv.includes("--config-messages")) {
+  input = "src/pages/messages_src/main.js"
+  output = "src/pages/messages/build/bundle.js"
+}
 
 export default {
   input,
diff --git a/src/assets/javascripts/services.js b/src/assets/javascripts/services.js
index ee48a1b9..d1c12375 100644
--- a/src/assets/javascripts/services.js
+++ b/src/assets/javascripts/services.js
@@ -610,18 +610,20 @@ function redirect(url, type, originUrl, documentUrl, incognito, forceRedirection
     }
 
     let instanceList = options[frontend]
-    if (instanceList === undefined) break
-    if (instanceList.length === 0) return "https://libredirect.invalid"
+    if (instanceList === undefined) break // should not happen if settings are correct
+
+    if (config.services[service].frontends[frontend].localhost && options[service].instance == "localhost") {
+      randomInstance = `http://${frontend}.localhost:8080`
+    } else if (instanceList.length === 0) {
+      return `https://no-instance.libredirect.invalid?frontend=${encodeURIComponent(frontend)}&url=${encodeURIComponent(url.href)}`
+    } else {
+      randomInstance = utils.getRandomInstance(instanceList)
+    }
 
     if (originUrl && instanceList.includes(originUrl.origin)) {
       if (type == "main_frame") return "BYPASSTAB"
       else return null
     }
-
-    randomInstance = utils.getRandomInstance(instanceList)
-    if (config.services[service].frontends[frontend].localhost && options[service].instance == "localhost") {
-      randomInstance = `http://${frontend}.localhost:8080`
-    }
     break
   }
   if (!frontend) return
@@ -636,7 +638,7 @@ function redirect(url, type, originUrl, documentUrl, incognito, forceRedirection
  * @param {URL} documentUrl
  * @param {boolean} incognito
  * @param {boolean} forceRedirection
- * @returns {string | undefined}
+ * @returns {Promise<string | undefined>}
  */
 async function redirectAsync(url, type, originUrl, documentUrl, incognito, forceRedirection) {
   await init()
@@ -645,9 +647,8 @@ async function redirectAsync(url, type, originUrl, documentUrl, incognito, force
 
 /**
  * @param {URL} url
- * @param {*} returnFrontend
  */
-function computeService(url, returnFrontend) {
+function computeService(url) {
   return new Promise(async resolve => {
     const config = await utils.getConfig()
     const options = await utils.getOptions()
@@ -658,9 +659,7 @@ function computeService(url, returnFrontend) {
       } else {
         for (const frontend in config.services[service].frontends) {
           if (all(service, frontend, options, config).includes(utils.protocolHost(url))) {
-            if (returnFrontend) resolve([service, frontend, utils.protocolHost(url)])
-            else resolve(service)
-            return
+            return resolve(service)
           }
         }
       }
@@ -768,7 +767,7 @@ async function reverse(url) {
 }
 
 const defaultInstances = {
-  invidious: ["https://inv.vern.cc"],
+  // invidious: ["https://inv.vern.cc"],
   materialious: ["https://app.materialio.us"],
   viewtube: ["https://viewtube.io"],
   piped: ["https://pipedapi-libre.kavin.rocks"],
diff --git a/src/assets/javascripts/utils.js b/src/assets/javascripts/utils.js
index 36271a8a..e5b8ba46 100644
--- a/src/assets/javascripts/utils.js
+++ b/src/assets/javascripts/utils.js
@@ -24,7 +24,7 @@ function getNextInstance(currentInstanceUrl, instances) {
  * @param {URL} url
  */
 function protocolHost(url) {
-  url.pathname = url.pathname.replace(/\/$/, '');
+  url.pathname = url.pathname.replace(/\/$/, "")
   if (url.username && url.password) return `${url.protocol}//${url.username}:${url.password}@${url.host}${url.pathname}`
 
   // workaround
@@ -211,6 +211,55 @@ function convertMapCentre(url) {
   return { zoom, lon, lat }
 }
 
+export function randomInstances(clearnet, n) {
+  let instances = []
+  if (n > clearnet.length) n = clearnet.length
+  for (let i = 0; i < n; i++) {
+    const randomNumber = Math.floor(Math.random() * clearnet.length)
+    const randomInstance = clearnet[randomNumber]
+    instances.push(randomInstance)
+  }
+  return instances
+}
+export function style(options, window) {
+  const vars = cssVariables(options, window)
+  return `--text: ${vars.text};
+  --bg-main: ${vars.bgMain};
+  --bg-secondary: ${vars.bgSecondary};
+  --active: ${vars.active};
+  --danger: ${vars.danger};
+  --light-grey: ${vars.lightGrey};`
+}
+
+function cssVariables(options, window) {
+  const dark = {
+    text: "#fff",
+    bgMain: "#121212",
+    bgSecondary: "#202020",
+    active: "#fbc117",
+    danger: "#f04141",
+    lightGrey: "#c3c3c3",
+  }
+
+  const light = {
+    text: "black",
+    bgMain: "white",
+    bgSecondary: "#e4e4e4",
+    active: "#fb9817",
+    danger: "#f04141",
+    lightGrey: "#c3c3c3",
+  }
+  if (options.theme == "dark") {
+    return dark
+  } else if (options.theme == "light") {
+    return light
+  } else if (window.matchMedia("(prefers-color-scheme: dark)").matches) {
+    return dark
+  } else {
+    return light
+  }
+}
+
 export default {
   getRandomInstance,
   getNextInstance,
@@ -225,4 +274,6 @@ export default {
   getQuery,
   prefsEncoded,
   convertMapCentre,
+  randomInstances,
+  style,
 }
diff --git a/src/config.json b/src/config.json
index 6ef3dbe6..045d7f20 100644
--- a/src/config.json
+++ b/src/config.json
@@ -143,7 +143,7 @@
       ],
       "name": "YouTube",
       "options": {
-        "enabled": false,
+        "enabled": true,
         "redirectType": "main_frame",
         "frontend": "invidious",
         "embedFrontend": "invidious",
diff --git a/src/pages/background/background.js b/src/pages/background/background.js
index f41cb55e..db7ad087 100644
--- a/src/pages/background/background.js
+++ b/src/pages/background/background.js
@@ -67,10 +67,25 @@ browser.webRequest.onBeforeRequest.addListener(
       tabIdRedirects[details.tabId]
     )
 
+    if (newUrl && newUrl.startsWith("https://no-instance.libredirect.invalid")) {
+      const url = new URL(newUrl)
+      const frontend = url.searchParams.get("frontend")
+      const oldUrl = new URL(url.searchParams.get("url"))
+
+      browser.tabs.update({
+        url: browser.runtime.getURL(
+          `/pages/messages/index.html?message=no_instance&url=${encodeURIComponent(oldUrl)}&frontend=${encodeURIComponent(frontend)}`
+        ),
+      })
+    }
+
     if (!newUrl) {
-      const match = url.href.match(/^https?:\/{2}(.*\.)?libredirect\.invalid.*/)
-      if (match) {
-        browser.tabs.update({ url: browser.runtime.getURL(`/pages/messages/no_instance.html`) })
+      if (url.href.match(/^https?:\/{2}(.*\.)?libredirect\.invalid.*/)) {
+        browser.tabs.update({
+          url: browser.runtime.getURL(
+            `/pages/messages/index.html?message=disabled&url=${encodeURIComponent(url.href)}`
+          ),
+        })
       }
     }
 
diff --git a/src/pages/components/Button.svelte b/src/pages/components/Button.svelte
index 8836b47e..6ae2ba61 100644
--- a/src/pages/components/Button.svelte
+++ b/src/pages/components/Button.svelte
@@ -19,11 +19,17 @@
     padding: 10px;
   }
 
-  button:hover {
+  button:hover:enabled {
     color: var(--active);
   }
 
-  button:active {
+  button:active:enabled {
     transform: translateY(1px);
   }
+
+  button:disabled {
+    cursor: not-allowed;
+    opacity: 0.5;
+  }
+  
 </style>
diff --git a/src/pages/messages/index.html b/src/pages/messages/index.html
new file mode 100644
index 00000000..8701c152
--- /dev/null
+++ b/src/pages/messages/index.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<html lang="en">
+  <head>
+    <meta charset="utf-8" />
+    <meta name="viewport" content="width=device-width,initial-scale=1" />
+    <link rel="icon" type="image/x-icon" href="../../../assets/images/libredirect.svg" />
+    <title>Settings</title>
+    <link rel="stylesheet" href="build/bundle.css" />
+    <link rel="stylesheet" href="../fonts/styles.css" />
+    <script defer src="build/bundle.js"></script>
+  </head>
+
+  <body></body>
+</html>
diff --git a/src/pages/messages/no_instance.html b/src/pages/messages/no_instance.html
deleted file mode 100644
index 55e5fac7..00000000
--- a/src/pages/messages/no_instance.html
+++ /dev/null
@@ -1,24 +0,0 @@
-<!doctype html>
-<html lang="en">
-  <head>
-    <meta charset="UTF-8" />
-    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
-    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
-    <link href="../stylesheets/styles.css" rel="stylesheet" />
-    <title>No instances found</title>
-    <style>
-      #body {
-        display: flex;
-        justify-content: center;
-        align-items: center;
-        height: 100vh;
-      }
-    </style>
-  </head>
-
-  <body>
-    <div id="body">
-      <h1>LibRedirect: You have no instance selected for this frontend</h1>
-    </div>
-  </body>
-</html>
diff --git a/src/pages/messages_src/App.svelte b/src/pages/messages_src/App.svelte
new file mode 100644
index 00000000..b08a143b
--- /dev/null
+++ b/src/pages/messages_src/App.svelte
@@ -0,0 +1,132 @@
+<script>
+  const browser = window.browser || window.chrome
+
+  import utils from "../../assets/javascripts/utils.js"
+  import { onDestroy } from "svelte"
+  import servicesHelper from "../../assets/javascripts/services.js"
+  import { onMount } from "svelte"
+
+  import { options, config, page } from "./stores"
+  import Button from "../components/Button.svelte"
+  import AutoPickIcon from "../icons/AutoPickIcon.svelte"
+
+  let _options
+  const unsubscribeOptions = options.subscribe(val => {
+    if (val) {
+      _options = val
+      browser.storage.local.set({ options: val })
+    }
+  })
+
+  let _config
+  const unsubscribeConfig = config.subscribe(val => (_config = val))
+
+  onDestroy(() => {
+    unsubscribeOptions()
+    unsubscribeConfig()
+  })
+
+  onMount(async () => {
+    let opts = await utils.getOptions()
+    if (!opts) {
+      await servicesHelper.initDefaults()
+      opts = await utils.getOptions()
+    }
+    redirects = await utils.getList(opts)
+    options.set(opts)
+    config.set(await utils.getConfig())
+  })
+
+  let _page
+  page.subscribe(val => (_page = val))
+
+  let style
+  $: if (_options) style = utils.style(_options, window)
+
+  let autoPicking = false
+  let redirects
+
+  const params = new URLSearchParams(window.location.search)
+  const oldUrl = new URL(params.get("url"))
+
+  async function autoPickInstance() {
+    const frontend = params.get("frontend")
+    autoPicking = true
+    const instances = utils.randomInstances(redirects[frontend]["clearnet"], 5)
+    const pings = await Promise.all([...instances.map(async instance => [instance, await utils.ping(instance)])])
+    pings.sort((a, b) => a[1] - b[1])
+    console.log(pings)
+    _options[frontend].push(pings[0][0])
+    options.set(_options)
+    autoPicking = false
+    await redirectUrl()
+  }
+
+  async function enableService() {
+    const service = await servicesHelper.computeService(oldUrl)
+    _options[service].enabled = true
+    options.set(_options)
+    await redirectUrl()
+  }
+
+  async function redirectUrl() {
+    const newUrl = await servicesHelper.redirectAsync(oldUrl, "main_frame", null, null, false, true)
+    browser.tabs.update({ url: newUrl })
+  }
+</script>
+
+{#if _options && _config}
+  <div class="main" dir="auto" {style}>
+    {#if window.location.search.includes("message=disabled")}
+      <div>
+        <h1>You disabled redirections for this service</h1>
+        <Button on:click={enableService}>
+          {browser.i18n.getMessage("enable") || "Enable"}
+        </Button>
+      </div>
+    {:else if window.location.search.includes("message=no_instance")}
+      <div>
+        <h1>You have no instance selected for this frontend</h1>
+        <Button on:click={autoPickInstance} disabled={autoPicking}>
+          <AutoPickIcon class="margin margin_{document.body.dir}" />
+          {browser.i18n.getMessage("autoPickInstance") || "Auto Pick Instance"}
+        </Button>
+      </div>
+    {/if}
+  </div>
+{:else}
+  <p>Loading...</p>
+{/if}
+
+<style>
+  :global(body) {
+    width: 100vw;
+    height: 100vh;
+    margin: 0;
+    padding: 0;
+  }
+
+  div.main {
+    height: 100%;
+    display: grid;
+    grid-template-columns: 800px;
+    margin: 0;
+    padding-top: 50px;
+    justify-content: center;
+    font-family: "Inter", sans-serif;
+    box-sizing: border-box;
+    font-size: 16px;
+    background-color: var(--bg-main);
+    color: var(--text);
+    overflow: scroll;
+  }
+
+  :global(.margin) {
+    margin-right: 10px;
+    margin-left: 0;
+  }
+  :global(.margin_rtl) {
+    margin-right: 0;
+    margin-left: 10px;
+  }
+</style>
diff --git a/src/pages/messages_src/main.js b/src/pages/messages_src/main.js
new file mode 100644
index 00000000..c4012f4a
--- /dev/null
+++ b/src/pages/messages_src/main.js
@@ -0,0 +1,7 @@
+import App from "./App.svelte"
+
+const app = new App({
+  target: document.body,
+})
+
+export default app
diff --git a/src/pages/messages_src/stores.js b/src/pages/messages_src/stores.js
new file mode 100644
index 00000000..782f6064
--- /dev/null
+++ b/src/pages/messages_src/stores.js
@@ -0,0 +1,5 @@
+import { writable } from "svelte/store"
+
+export const options = writable(null)
+export const config = writable(null)
+export const page = writable("general")
diff --git a/src/pages/options_src/App.svelte b/src/pages/options_src/App.svelte
index 565aacef..1c4830bf 100644
--- a/src/pages/options_src/App.svelte
+++ b/src/pages/options_src/App.svelte
@@ -2,7 +2,7 @@
   const browser = window.browser || window.chrome
 
   import General from "./General/General.svelte"
-  import url from './url'
+  import url from "./url"
   import utils from "../../assets/javascripts/utils.js"
   import { onDestroy } from "svelte"
   import servicesHelper from "../../assets/javascripts/services.js"
@@ -37,51 +37,15 @@
     config.set(await utils.getConfig())
   })
 
-  const dark = {
-    text: "#fff",
-    bgMain: "#121212",
-    bgSecondary: "#202020",
-    active: "#fbc117",
-    danger: "#f04141",
-    lightGrey: "#c3c3c3",
-  }
-  const light = {
-    text: "black",
-    bgMain: "white",
-    bgSecondary: "#e4e4e4",
-    active: "#fb9817",
-    danger: "#f04141",
-    lightGrey: "#c3c3c3",
-  }
-  let cssVariables
-  $: if (_options) {
-    if (_options.theme == "dark") {
-      cssVariables = dark
-    } else if (_options.theme == "light") {
-      cssVariables = light
-    } else if (window.matchMedia("(prefers-color-scheme: dark)").matches) {
-      cssVariables = dark
-    } else {
-      cssVariables = light
-    }
-  }
+  let style
+  $: if (_options) style = utils.style(_options, window)
 
   const dir = ["ar", "iw", "ku", "fa", "ur"].includes(browser.i18n.getUILanguage()) ? "rtl" : "ltr"
   document.body.dir = dir
 </script>
 
 {#if _options && _config}
-  <div
-    class={dir}
-    {dir}
-    style="
-    --text: {cssVariables.text};
-    --bg-main: {cssVariables.bgMain};
-    --bg-secondary: {cssVariables.bgSecondary};
-    --active: {cssVariables.active};
-    --danger: {cssVariables.danger};
-    --light-grey: {cssVariables.lightGrey};"
-  >
+  <div class={dir} {dir} {style}>
     <Sidebar />
     {#if !$url.hash || $url.hash == "#general"}
       <General />
diff --git a/src/pages/options_src/Services/Instances.svelte b/src/pages/options_src/Services/Instances.svelte
index 32425b80..4e5d1e7d 100644
--- a/src/pages/options_src/Services/Instances.svelte
+++ b/src/pages/options_src/Services/Instances.svelte
@@ -64,16 +64,9 @@
       pingCache[instance] = colorTime(time)
     }
   }
-  function randomInstances(n) {
-    let instances = []
-    for (let i = 0; i < n; i++) {
-      instances.push(redirects[selectedFrontend]["clearnet"][Math.floor(Math.random() * allInstances.length)])
-    }
-    return instances
-  }
 
   async function autoPickInstance() {
-    const instances = randomInstances(5)
+    const instances = utils.randomInstances(redirects[selectedFrontend]["clearnet"], 5)
     const myInstancesCache = []
     for (const instance of instances) {
       pingCache[instance] = { color: "lightblue", value: "pinging..." }
@@ -81,9 +74,7 @@
       pingCache[instance] = colorTime(time)
       myInstancesCache.push([instance, time])
     }
-    myInstancesCache.sort(function (a, b) {
-      return a[1] - b[1]
-    })
+    myInstancesCache.sort((a, b) => a[1] - b[1])
 
     _options[selectedFrontend].push(myInstancesCache[0][0])
     options.set(_options)
diff --git a/src/pages/popup_src/App.svelte b/src/pages/popup_src/App.svelte
index 8f958a3e..f6699312 100644
--- a/src/pages/popup_src/App.svelte
+++ b/src/pages/popup_src/App.svelte
@@ -38,48 +38,12 @@
   let _page
   page.subscribe(val => (_page = val))
 
-  const dark = {
-    text: "#fff",
-    bgMain: "#121212",
-    bgSecondary: "#202020",
-    active: "#fbc117",
-    danger: "#f04141",
-    lightGrey: "#c3c3c3",
-  }
-  const light = {
-    text: "black",
-    bgMain: "white",
-    bgSecondary: "#e4e4e4",
-    active: "#fb9817",
-    danger: "#f04141",
-    lightGrey: "#c3c3c3",
-  }
-  let cssVariables
-  $: if (_options) {
-    if (_options.theme == "dark") {
-      cssVariables = dark
-    } else if (_options.theme == "light") {
-      cssVariables = light
-    } else if (window.matchMedia("(prefers-color-scheme: dark)").matches) {
-      cssVariables = dark
-    } else {
-      cssVariables = light
-    }
-  }
+  let style
+  $: if (_options) style = utils.style(_options, window)
 </script>
 
 {#if _options && _config}
-  <div
-    class="main"
-    dir="auto"
-    style="
-    --text: {cssVariables.text};
-    --bg-main: {cssVariables.bgMain};
-    --bg-secondary: {cssVariables.bgSecondary};
-    --active: {cssVariables.active};
-    --danger: {cssVariables.danger};
-    --light-grey: {cssVariables.lightGrey};"
-  >
+  <div class="main" dir="auto" {style}>
     <Buttons />
   </div>
 {:else}
-- 
cgit 1.4.1

