From 944f2e6ef09a1534bac061acca2e3b3a4c13b13a Mon Sep 17 00:00:00 2001 From: SimonBrazell Date: Sun, 10 Jan 2021 22:04:03 +1100 Subject: Restructure code with helper modules, add search engine settings, & advanced settings collapsibles. --- README.md | 20 +- _locales/en/messages.json | 16 + _locales/ru/messages.json | 2 +- assets/images/Screen Shot Chrome 1.png | Bin 331026 -> 0 bytes assets/images/Screen Shot Chrome 2.png | Bin 704517 -> 0 bytes assets/images/Screen Shot Chrome 3.png | Bin 180386 -> 0 bytes assets/images/Screen Shot Chrome 4.png | Bin 1038484 -> 0 bytes assets/images/Screen Shot Chrome 5.png | Bin 191954 -> 0 bytes assets/images/Screen Shot FF 1.png | Bin 335716 -> 0 bytes assets/images/Screen Shot FF 2.png | Bin 2093693 -> 0 bytes assets/images/Screen Shot FF 3.png | Bin 228957 -> 0 bytes assets/images/Screen Shot FF 4.png | Bin 2866335 -> 0 bytes assets/images/Screen Shot FF 5.png | Bin 256223 -> 0 bytes assets/images/badge-amo.png | Bin 2750 -> 0 bytes assets/images/badge-chrome.png | Bin 2391 -> 0 bytes assets/images/badge-ms.png | Bin 9320 -> 0 bytes assets/images/buy-me-a-coffee.png | Bin 3926 -> 0 bytes assets/images/chevron-down.svg | 3 - assets/images/icon128.png | Bin 1773 -> 0 bytes assets/images/icon16.png | Bin 709 -> 0 bytes assets/images/icon32.png | Bin 1162 -> 0 bytes assets/images/icon48.png | Bin 690 -> 0 bytes assets/images/logo-small.png | Bin 14128 -> 0 bytes assets/images/logo-store.png | Bin 89803 -> 0 bytes assets/images/logo-tile.png | Bin 14751 -> 0 bytes assets/images/logo.png | Bin 16364 -> 0 bytes assets/javascript/localise.js | 19 - assets/javascript/persist-invidious-prefs.js | 30 - assets/javascript/remove-twitter-sw.js | 92 --- background.js | 692 ---------------------- manifest.json | 49 +- pages/options/options.html | 569 ------------------ pages/options/options.js | 526 ---------------- pages/popup/popup.html | 214 ------- pages/popup/popup.js | 62 -- pages/styles.css | 481 --------------- src/assets/images/Screen Shot Chrome 1.png | Bin 0 -> 331026 bytes src/assets/images/Screen Shot Chrome 2.png | Bin 0 -> 704517 bytes src/assets/images/Screen Shot Chrome 3.png | Bin 0 -> 180386 bytes src/assets/images/Screen Shot Chrome 4.png | Bin 0 -> 1038484 bytes src/assets/images/Screen Shot Chrome 5.png | Bin 0 -> 191954 bytes src/assets/images/Screen Shot FF 1.png | Bin 0 -> 335716 bytes src/assets/images/Screen Shot FF 2.png | Bin 0 -> 2093693 bytes src/assets/images/Screen Shot FF 3.png | Bin 0 -> 228957 bytes src/assets/images/Screen Shot FF 4.png | Bin 0 -> 2866335 bytes src/assets/images/Screen Shot FF 5.png | Bin 0 -> 256223 bytes src/assets/images/badge-amo.png | Bin 0 -> 2750 bytes src/assets/images/badge-chrome.png | Bin 0 -> 2391 bytes src/assets/images/badge-ms.png | Bin 0 -> 9320 bytes src/assets/images/buy-me-a-coffee.png | Bin 0 -> 3926 bytes src/assets/images/chevron-down.svg | 3 + src/assets/images/icon128.png | Bin 0 -> 1773 bytes src/assets/images/icon16.png | Bin 0 -> 709 bytes src/assets/images/icon32.png | Bin 0 -> 1162 bytes src/assets/images/icon48.png | Bin 0 -> 690 bytes src/assets/images/logo-small.png | Bin 0 -> 14128 bytes src/assets/images/logo-store.png | Bin 0 -> 89803 bytes src/assets/images/logo-tile.png | Bin 0 -> 14751 bytes src/assets/images/logo.png | Bin 0 -> 16364 bytes src/assets/javascripts/helpers/common.js | 9 + src/assets/javascripts/helpers/google-maps.js | 43 ++ src/assets/javascripts/helpers/google-search.js | 9 + src/assets/javascripts/helpers/instagram.js | 47 ++ src/assets/javascripts/helpers/reddit.js | 24 + src/assets/javascripts/helpers/twitter.js | 38 ++ src/assets/javascripts/helpers/youtube.js | 33 ++ src/assets/javascripts/localise.js | 19 + src/assets/javascripts/persist-invidious-prefs.js | 30 + src/assets/javascripts/remove-twitter-sw.js | 89 +++ src/assets/stylesheets/styles.css | 516 ++++++++++++++++ src/pages/background/background.html | 1 + src/pages/background/background.js | 549 +++++++++++++++++ src/pages/options/options.html | 585 ++++++++++++++++++ src/pages/options/options.js | 522 ++++++++++++++++ src/pages/popup/popup.html | 214 +++++++ src/pages/popup/popup.js | 62 ++ 76 files changed, 2844 insertions(+), 2724 deletions(-) delete mode 100644 assets/images/Screen Shot Chrome 1.png delete mode 100644 assets/images/Screen Shot Chrome 2.png delete mode 100644 assets/images/Screen Shot Chrome 3.png delete mode 100644 assets/images/Screen Shot Chrome 4.png delete mode 100644 assets/images/Screen Shot Chrome 5.png delete mode 100644 assets/images/Screen Shot FF 1.png delete mode 100644 assets/images/Screen Shot FF 2.png delete mode 100644 assets/images/Screen Shot FF 3.png delete mode 100644 assets/images/Screen Shot FF 4.png delete mode 100644 assets/images/Screen Shot FF 5.png delete mode 100644 assets/images/badge-amo.png delete mode 100644 assets/images/badge-chrome.png delete mode 100644 assets/images/badge-ms.png delete mode 100644 assets/images/buy-me-a-coffee.png delete mode 100644 assets/images/chevron-down.svg delete mode 100644 assets/images/icon128.png delete mode 100644 assets/images/icon16.png delete mode 100644 assets/images/icon32.png delete mode 100644 assets/images/icon48.png delete mode 100644 assets/images/logo-small.png delete mode 100644 assets/images/logo-store.png delete mode 100644 assets/images/logo-tile.png delete mode 100644 assets/images/logo.png delete mode 100644 assets/javascript/localise.js delete mode 100644 assets/javascript/persist-invidious-prefs.js delete mode 100644 assets/javascript/remove-twitter-sw.js delete mode 100644 background.js delete mode 100644 pages/options/options.html delete mode 100644 pages/options/options.js delete mode 100644 pages/popup/popup.html delete mode 100644 pages/popup/popup.js delete mode 100644 pages/styles.css create mode 100644 src/assets/images/Screen Shot Chrome 1.png create mode 100644 src/assets/images/Screen Shot Chrome 2.png create mode 100644 src/assets/images/Screen Shot Chrome 3.png create mode 100644 src/assets/images/Screen Shot Chrome 4.png create mode 100644 src/assets/images/Screen Shot Chrome 5.png create mode 100644 src/assets/images/Screen Shot FF 1.png create mode 100644 src/assets/images/Screen Shot FF 2.png create mode 100644 src/assets/images/Screen Shot FF 3.png create mode 100644 src/assets/images/Screen Shot FF 4.png create mode 100644 src/assets/images/Screen Shot FF 5.png create mode 100644 src/assets/images/badge-amo.png create mode 100644 src/assets/images/badge-chrome.png create mode 100644 src/assets/images/badge-ms.png create mode 100644 src/assets/images/buy-me-a-coffee.png create mode 100644 src/assets/images/chevron-down.svg create mode 100644 src/assets/images/icon128.png create mode 100644 src/assets/images/icon16.png create mode 100644 src/assets/images/icon32.png create mode 100644 src/assets/images/icon48.png create mode 100644 src/assets/images/logo-small.png create mode 100644 src/assets/images/logo-store.png create mode 100644 src/assets/images/logo-tile.png create mode 100644 src/assets/images/logo.png create mode 100644 src/assets/javascripts/helpers/common.js create mode 100644 src/assets/javascripts/helpers/google-maps.js create mode 100644 src/assets/javascripts/helpers/google-search.js create mode 100644 src/assets/javascripts/helpers/instagram.js create mode 100644 src/assets/javascripts/helpers/reddit.js create mode 100644 src/assets/javascripts/helpers/twitter.js create mode 100644 src/assets/javascripts/helpers/youtube.js create mode 100644 src/assets/javascripts/localise.js create mode 100644 src/assets/javascripts/persist-invidious-prefs.js create mode 100644 src/assets/javascripts/remove-twitter-sw.js create mode 100644 src/assets/stylesheets/styles.css create mode 100644 src/pages/background/background.html create mode 100644 src/pages/background/background.js create mode 100644 src/pages/options/options.html create mode 100644 src/pages/options/options.js create mode 100644 src/pages/popup/popup.html create mode 100644 src/pages/popup/popup.js diff --git a/README.md b/README.md index 820daebb..ce9ee7de 100644 --- a/README.md +++ b/README.md @@ -5,32 +5,36 @@ [![Donate](https://liberapay.com/assets/widgets/donate.svg)](https://liberapay.com/SimonBrazell/donate) [![Buy me a coffee](assets/images/buy-me-a-coffee.png)](https://www.buymeacoffee.com/SimonBrazell) ## Get -[![Firefox Add-on](assets/images/badge-amo.png)](https://addons.mozilla.org/en-US/firefox/addon/privacy-redirect/) -[![Chrome Extension](assets/images/badge-chrome.png)](https://chrome.google.com/webstore/detail/privacy-redirect/pmcmeagblkinmogikoikkdjiligflglb) + +[![Firefox Add-on](assets/images/badge-amo.png)](https://addons.mozilla.org/en-US/firefox/addon/privacy-redirect/) +[![Chrome Extension](assets/images/badge-chrome.png)](https://chrome.google.com/webstore/detail/privacy-redirect/pmcmeagblkinmogikoikkdjiligflglb) [![Edge Extension](assets/images/badge-ms.png)](https://microsoftedge.microsoft.com/addons/detail/privacy-redirect/elnabkhcgpajchapppkhiaifkgikgihj) ## About -A web extension that redirects *Twitter, YouTube, Instagram, Google Maps & Non-Private Searches* requests to privacy friendly alternatives - [Nitter](https://github.com/zedeus/nitter), [Invidious](https://github.com/iv-org/invidious), [FreeTube](https://github.com/FreeTubeApp/FreeTube), [Bibliogram](https://sr.ht/~cadence/bibliogram/), [OpenStreetMap](https://www.openstreetmap.org/) & Private Search Engines like [DuckDuckGo](https://duckduckgo.com) and [Startpage](https://startpage.com). + +A web extension that redirects _Twitter, YouTube, Instagram, Google Maps & Non-Private Searches_ requests to privacy friendly alternatives - [Nitter](https://github.com/zedeus/nitter), [Invidious](https://github.com/iv-org/invidious), [FreeTube](https://github.com/FreeTubeApp/FreeTube), [Bibliogram](https://sr.ht/~cadence/bibliogram/), [OpenStreetMap](https://www.openstreetmap.org/) & Private Search Engines like [DuckDuckGo](https://duckduckgo.com) and [Startpage](https://startpage.com). It's possible to toggle all redirects on and off. The extension will default to using random instances if none are selected. If these instances are not working, you can try and set a custom instance from the list below. \*Instance for Search Engine redirect cannot be chosen at the moment. ### Custom instances + Privacy Redirect allows setting custom instances, instances can be found here: + - [Nitter instances](https://github.com/zedeus/nitter/wiki/Instances) - [Invidious instances](https://github.com/iv-org/invidious/wiki/Invidious-Instances) - [Bibliogram instances](https://git.sr.ht/~cadence/bibliogram-docs/tree/master/docs/Instances.md) - [OpenStreetMap tile servers](https://wiki.openstreetmap.org/wiki/Tile_servers) - Private Search Engine list - - [DuckDuckGo](https://duckduckgo.com) - - [Startpage](https://startpage.com) - - [Qwant](https://www.qwant.com) - - [Mojeek](https://www.mojeek.com) + - [DuckDuckGo](https://duckduckgo.com) + - [Startpage](https://startpage.com) + - [Qwant](https://www.qwant.com) + - [Mojeek](https://www.mojeek.com) ## Build 1. `npm install --global web-ext` 2. `web-ext build --overwrite-dest` -3. See `web-ext-artifacts/` for outputs. +3. `open web-ext-artifacts/` for outputs. ## License diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 3748db3b..8f698af8 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -23,6 +23,14 @@ "message": "OpenStreetMap Instance", "description": "Label for OSM instance field option (options)." }, + "redditInstance": { + "message": "Reddit Instance", + "description": "Label for Reddit instance field option (options)." + }, + "searchEngineInstance": { + "message": "Search Engine Instance", + "description": "Label for Search Engine instance field option (options)." + }, "disableNitter": { "message": "Nitter Redirects", "description": "Label for enable/disable Nitter redirects option (options & pop-up)." @@ -39,6 +47,14 @@ "message": "OpenStreetMap Redirects", "description": "Label for enable/disable OSM redirects option (options & pop-up)." }, + "disableReddit": { + "message": "Reddit Redirects", + "description": "Label for enable/disable Reddit redirects option (options & pop-up)." + }, + "disableSearchEngine": { + "message": "Search Engine Redirects", + "description": "Label for enable/disable Search Engine redirects option (options & pop-up)." + }, "alwaysProxy": { "message": "Always proxy videos through Invidious", "description": "Label for 'Always proxy videos through Invidious' option (options)." diff --git a/_locales/ru/messages.json b/_locales/ru/messages.json index 30cee49f..a993f042 100644 --- a/_locales/ru/messages.json +++ b/_locales/ru/messages.json @@ -39,7 +39,7 @@ "message": "Перенаправление на OpenStreetMap", "description": "Название настройки для включения/выключения перенаправления на OSM (в настройках и всплывающем окне)." }, - "disableOldReddit": { + "disableReddit": { "message": "Перенаправление на старый Reddit", "description": "Название настройки для включения/выключения перенаправления на старый Reddit (в настройках и всплывающем окне)." }, diff --git a/assets/images/Screen Shot Chrome 1.png b/assets/images/Screen Shot Chrome 1.png deleted file mode 100644 index 1628b509..00000000 Binary files a/assets/images/Screen Shot Chrome 1.png and /dev/null differ diff --git a/assets/images/Screen Shot Chrome 2.png b/assets/images/Screen Shot Chrome 2.png deleted file mode 100644 index 61eed643..00000000 Binary files a/assets/images/Screen Shot Chrome 2.png and /dev/null differ diff --git a/assets/images/Screen Shot Chrome 3.png b/assets/images/Screen Shot Chrome 3.png deleted file mode 100644 index 42c92014..00000000 Binary files a/assets/images/Screen Shot Chrome 3.png and /dev/null differ diff --git a/assets/images/Screen Shot Chrome 4.png b/assets/images/Screen Shot Chrome 4.png deleted file mode 100644 index 8bae0410..00000000 Binary files a/assets/images/Screen Shot Chrome 4.png and /dev/null differ diff --git a/assets/images/Screen Shot Chrome 5.png b/assets/images/Screen Shot Chrome 5.png deleted file mode 100644 index d3f54841..00000000 Binary files a/assets/images/Screen Shot Chrome 5.png and /dev/null differ diff --git a/assets/images/Screen Shot FF 1.png b/assets/images/Screen Shot FF 1.png deleted file mode 100644 index 7ae2e614..00000000 Binary files a/assets/images/Screen Shot FF 1.png and /dev/null differ diff --git a/assets/images/Screen Shot FF 2.png b/assets/images/Screen Shot FF 2.png deleted file mode 100644 index a995478a..00000000 Binary files a/assets/images/Screen Shot FF 2.png and /dev/null differ diff --git a/assets/images/Screen Shot FF 3.png b/assets/images/Screen Shot FF 3.png deleted file mode 100644 index fc3232b6..00000000 Binary files a/assets/images/Screen Shot FF 3.png and /dev/null differ diff --git a/assets/images/Screen Shot FF 4.png b/assets/images/Screen Shot FF 4.png deleted file mode 100644 index f230fed2..00000000 Binary files a/assets/images/Screen Shot FF 4.png and /dev/null differ diff --git a/assets/images/Screen Shot FF 5.png b/assets/images/Screen Shot FF 5.png deleted file mode 100644 index 420838d9..00000000 Binary files a/assets/images/Screen Shot FF 5.png and /dev/null differ diff --git a/assets/images/badge-amo.png b/assets/images/badge-amo.png deleted file mode 100644 index 9dbb7e46..00000000 Binary files a/assets/images/badge-amo.png and /dev/null differ diff --git a/assets/images/badge-chrome.png b/assets/images/badge-chrome.png deleted file mode 100644 index afd2c6b2..00000000 Binary files a/assets/images/badge-chrome.png and /dev/null differ diff --git a/assets/images/badge-ms.png b/assets/images/badge-ms.png deleted file mode 100644 index 1b1dcbc9..00000000 Binary files a/assets/images/badge-ms.png and /dev/null differ diff --git a/assets/images/buy-me-a-coffee.png b/assets/images/buy-me-a-coffee.png deleted file mode 100644 index 8d9ea893..00000000 Binary files a/assets/images/buy-me-a-coffee.png and /dev/null differ diff --git a/assets/images/chevron-down.svg b/assets/images/chevron-down.svg deleted file mode 100644 index 7679f267..00000000 --- a/assets/images/chevron-down.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/assets/images/icon128.png b/assets/images/icon128.png deleted file mode 100644 index cd16befd..00000000 Binary files a/assets/images/icon128.png and /dev/null differ diff --git a/assets/images/icon16.png b/assets/images/icon16.png deleted file mode 100644 index f896608b..00000000 Binary files a/assets/images/icon16.png and /dev/null differ diff --git a/assets/images/icon32.png b/assets/images/icon32.png deleted file mode 100644 index c5b417cf..00000000 Binary files a/assets/images/icon32.png and /dev/null differ diff --git a/assets/images/icon48.png b/assets/images/icon48.png deleted file mode 100644 index 24dd5af7..00000000 Binary files a/assets/images/icon48.png and /dev/null differ diff --git a/assets/images/logo-small.png b/assets/images/logo-small.png deleted file mode 100644 index 27ca660a..00000000 Binary files a/assets/images/logo-small.png and /dev/null differ diff --git a/assets/images/logo-store.png b/assets/images/logo-store.png deleted file mode 100644 index f321de43..00000000 Binary files a/assets/images/logo-store.png and /dev/null differ diff --git a/assets/images/logo-tile.png b/assets/images/logo-tile.png deleted file mode 100644 index 101c6b3a..00000000 Binary files a/assets/images/logo-tile.png and /dev/null differ diff --git a/assets/images/logo.png b/assets/images/logo.png deleted file mode 100644 index ad854aaa..00000000 Binary files a/assets/images/logo.png and /dev/null differ diff --git a/assets/javascript/localise.js b/assets/javascript/localise.js deleted file mode 100644 index cbe5c191..00000000 --- a/assets/javascript/localise.js +++ /dev/null @@ -1,19 +0,0 @@ -window.browser = window.browser || window.chrome; - -function localisePage() { - var data = document.querySelectorAll("[data-localise]"); - - for (var i in data) - if (data.hasOwnProperty(i)) { - var obj = data[i]; - var tag = obj.getAttribute("data-localise").toString(); - - var msg = tag.replace(/__MSG_(\w+)__/g, function (_match, v1) { - return v1 ? browser.i18n.getMessage(v1) : null; - }); - - if (msg && msg !== tag) obj.textContent = msg; - } -} - -localisePage(); diff --git a/assets/javascript/persist-invidious-prefs.js b/assets/javascript/persist-invidious-prefs.js deleted file mode 100644 index 4c13a310..00000000 --- a/assets/javascript/persist-invidious-prefs.js +++ /dev/null @@ -1,30 +0,0 @@ -'use strict'; - -window.browser = window.browser || window.chrome; - -function getCookie() { - let ca = document.cookie.split(';'); - for (let i = 0; i < ca.length; i++) { - let c = ca[i]; - while (c.charAt(0) == ' ') c = c.substring(1, c.length); - if (c.indexOf('PREFS=') == 0) { - return JSON.parse( - decodeURIComponent(c.substring('PREFS='.length, c.length)) - ) - }; - } - return {}; -} - -browser.storage.sync.get( - ['alwaysProxy', 'videoQuality', 'invidiousDarkMode', 'persistInvidiousPrefs'], - (result) => { - if (result.persistInvidiousPrefs) { - const prefs = getCookie(); - prefs.local = result.alwaysProxy; - prefs.quality = result.videoQuality; - prefs.dark_mode = result.invidiousDarkMode; - document.cookie = `PREFS=${encodeURIComponent(JSON.stringify(prefs))}`; - } - } -); \ No newline at end of file diff --git a/assets/javascript/remove-twitter-sw.js b/assets/javascript/remove-twitter-sw.js deleted file mode 100644 index f74ff89f..00000000 --- a/assets/javascript/remove-twitter-sw.js +++ /dev/null @@ -1,92 +0,0 @@ -"use strict"; - -const nitterInstances = [ - "https://nitter.net", - "https://nitter.snopyta.org", - "https://nitter.42l.fr", - "https://nitter.nixnet.services", - "https://nitter.13ad.de", - "https://nitter.pussthecat.org", - "https://nitter.mastodont.cat", - "https://nitter", - "https://nitter.tedomum.net", - "https://nitter.cattube.org", - "https://nitter.fdn.fr", - "https://nitter.1d4.us", - "https://nitter.kavin.rocks", - "https://nitter.unixfox.eu", -]; - -let disableNitter; -let nitterInstance; -let redirectBypassFlag; -let exceptions; - -window.browser = window.browser || window.chrome; - -function getRandomInstance() { - return nitterInstances[~~(nitterInstances.length * Math.random())]; -} - -function isNotException(url) { - return !exceptions.some((regex) => regex.test(url.href)); -} - -function shouldRedirect(url) { - return ( - !redirectBypassFlag && - isNotException(url) && - !disableNitter && - url.host !== nitterInstance && - !url.pathname.includes("/home") - ); -} - -function redirectTwitter(url) { - if (url.host.split(".")[0] === "pbs") { - return `${nitterInstance}/pic/${encodeURIComponent(url.href)}`; - } else if (url.host.split(".")[0] === "video") { - return `${nitterInstance}/gif/${encodeURIComponent(url.href)}`; - } else { - return `${nitterInstance}${url.pathname}${url.search}`; - } -} - -browser.storage.sync.get( - [ - "nitterInstance", - "disableNitter", - "removeTwitterSW", - "redirectBypassFlag", - "exceptions", - ], - (result) => { - redirectBypassFlag = result.redirectBypassFlag; - browser.storage.sync.set({ - redirectBypassFlag: false, - }); - if (!result.removeTwitterSW) { - disableNitter = result.disableNitter; - nitterInstance = result.nitterInstance || getRandomInstance(); - exceptions = result.exceptions - ? result.exceptions.map((e) => { - return new RegExp(e); - }) - : []; - navigator.serviceWorker.getRegistrations().then((registrations) => { - for (let registration of registrations) { - if (registration.scope === "https://twitter.com/") { - registration.unregister(); - console.log("Unregistered Twitter SW", registration); - } - } - }); - const url = new URL(window.location); - if (shouldRedirect(url)) { - const redirect = redirectTwitter(url); - console.info("Redirecting", `"${url.href}"`, "=>", `"${redirect}"`); - window.location = redirect; - } - } - } -); diff --git a/background.js b/background.js deleted file mode 100644 index 6fdce2d7..00000000 --- a/background.js +++ /dev/null @@ -1,692 +0,0 @@ -"use strict"; - -const youtubeDomains = [ - "m.youtube.com", - "youtube.com", - "img.youtube.com", - "www.youtube.com", - "youtube-nocookie.com", - "www.youtube-nocookie.com", - "youtu.be", - "s.ytimg.com", - "music.youtube.com", -]; -const nitterInstances = [ - "https://nitter.net", - "https://nitter.snopyta.org", - "https://nitter.42l.fr", - "https://nitter.nixnet.services", - "https://nitter.13ad.de", - "https://nitter.pussthecat.org", - "https://nitter.mastodont.cat", - "https://nitter.dark.fail", - "https://nitter.tedomum.net", - "https://nitter.cattube.org", - "https://nitter.fdn.fr", - "https://nitter.1d4.us", - "https://nitter.kavin.rocks", - "https://tweet.lambda.dance", - "https://nitter.cc", - "https://nitter.weaponizedhumiliation.com", - "https://nitter.vxempire.xyz", - "https://nitter.unixfox.eu", - "http://3nzoldnxplag42gqjs23xvghtzf6t6yzssrtytnntc6ppc7xxuoneoad.onion", - "http://nitter.l4qlywnpwqsluw65ts7md3khrivpirse744un3x7mlskqauz5pyuzgqd.onion", - "http://nitterlgj3n5fgwesu3vxc5h67ruku33nqaoeoocae2mvlzhsu6k7fqd.onion", - "http://npf37k3mtzwxreiw52ccs5ay4e6qt2fkcs2ndieurdyn2cuzzsfyfvid.onion", -]; -const twitterDomains = [ - "twitter.com", - "www.twitter.com", - "mobile.twitter.com", - "pbs.twimg.com", - "video.twimg.com", -]; -const invidiousInstances = [ - "https://invidious.snopyta.org", - "https://invidious.xyz", - "https://invidious.kavin.rocks", - "https://tube.connect.cafe", - "https://invidious.zapashcanon.fr", - "https://invidiou.site", - "https://vid.mint.lgbt", - "https://invidious.site", - "https://yewtu.be", - "http://fz253lmuao3strwbfbmx46yu7acac2jz27iwtorgmbqlkurlclmancad.onion", - "http://qklhadlycap4cnod.onion", - "http://c7hqkpkpemu6e7emz5b4vyz7idjgdvgaaa3dyimmeojqbgpea3xqjoid.onion", - "http://w6ijuptxiku4xpnnaetxvnkc5vqcdu7mgns2u77qefoixi63vbvnpnqd.onion", -]; -const instagramDomains = [ - "instagram.com", - "www.instagram.com", - "help.instagram.com", - "about.instagram.com", -]; -const instagramReservedPaths = [ - "about", - "explore", - "support", - "press", - "api", - "privacy", - "safety", - "admin", - "graphql", - "accounts", - "help", - "terms", - "contact", - "blog", - "igtv", - "u", - "p", - "fragment", - "imageproxy", - "videoproxy", - ".well-known", - "tv", - "reel", -]; -const bibliogramBypassPaths = /\/(accounts\/|embeds?.js)/; -const bibliogramInstances = [ - "https://bibliogram.art", - "https://bibliogram.snopyta.org", - "https://bibliogram.pussthecat.org", - "https://bibliogram.nixnet.services", - "https://bg.endl.site", - "https://bibliogram.13ad.de", - "https://bibliogram.pixelfed.uno", - "https://bibliogram.ethibox.fr", - "https://bibliogram.hamster.dance", - "https://bibliogram.kavin.rocks", - "https://bibliogram.ggc-project.de", -]; -const osmDefault = "https://openstreetmap.org"; -const redditDomains = [ - "www.reddit.com", - "np.reddit.com", - "new.reddit.com", - "amp.reddit.com", -]; -const redditBypassPaths = /\/(gallery\/poll\/rpan\/settings\/topics)/; -const oldRedditViews = [ - // teddit: privacy w/ old UI - "https://teddit.net", - "https://teddit.ggc-project.de", - "https://teddit.kavin.rocks", - "https://snew.notabug.io", // anti-censorship - // libreddit: privacy w/ modern UI - "https://libredd.it", - "https://libreddit.spike.codes", - "https://libreddit.kavin.rocks", - "https://libreddit.insanity.wtf", - "https://libreddit.dothq.co", - "https://old.reddit.com", // desktop - "https://i.reddit.com" // mobile -]; -const oldRedditDefaultView = oldRedditViews[0]; -const googleMapsRegex = /https?:\/\/(((www|maps)\.)?(google\.).*(\/maps)|maps\.(google\.).*)/; -const mapCentreRegex = /@(-?\d[0-9.]*),(-?\d[0-9.]*),(\d{1,2})[.z]/; -const dataLatLngRegex = /(!3d|!4d)(-?[0-9]{1,10}.[0-9]{1,10})/g; -const placeRegex = /\/place\/(.*)\//; -const travelModes = { - driving: "fossgis_osrm_car", - walking: "fossgis_osrm_foot", - bicycling: "fossgis_osrm_bike", - transit: "fossgis_osrm_car", // not implemented on OSM, default to car. -}; -const layers = { - none: "S", - transit: "T", - traffic: "S", // not implemented on OSM, default to standard. - bicycling: "C", -}; -const googleSearchRegex = /https?:\/\/(((www|maps)\.)?(google\.).*(\/search)|search\.(google\.).*)/; -const privateSearchEngine = [ - { link: "https://duckduckgo.com", q: "/" }, - { link: "https://startpage.com", q: "/search/" }, - { link: "https://www.qwant.com", q: "/" }, - { link: "https://www.mojeek.com", q: "/search" }, -]; - -let disableNitter; -let disableInvidious; -let disableBibliogram; -let disableOsm; -let disableOldReddit; -let disableSearchEngine; -let nitterInstance; -let invidiousInstance; -let bibliogramInstance; -let osmInstance; -let oldRedditView; -let alwaysProxy; -let onlyEmbeddedVideo; -let videoQuality; -let invidiousDarkMode; -let invidiousVolume; -let invidiousPlayerStyle; -let invidiousSubtitles; -let invidiousAutoplay; -let useFreeTube; -let nitterRandomPool; -let invidiousRandomPool; -let bibliogramRandomPool; -let exceptions; - -window.browser = window.browser || window.chrome; - -function filterInstances(instances) { - return instances.filter((instance) => !instance.includes(".onion")); -} - -browser.storage.sync.get( - [ - "nitterInstance", - "invidiousInstance", - "bibliogramInstance", - "osmInstance", - "oldRedditView", - "disableNitter", - "disableInvidious", - "disableBibliogram", - "disableOsm", - "disableOldReddit", - "disableSearchEngine", - "alwaysProxy", - "onlyEmbeddedVideo", - "videoQuality", - "invidiousDarkMode", - "invidiousVolume", - "invidiousPlayerStyle", - "invidiousSubtitles", - "invidiousAutoplay", - "useFreeTube", - "nitterRandomPool", - "invidiousRandomPool", - "bibliogramRandomPool", - "exceptions", - ], - (result) => { - disableNitter = result.disableNitter; - disableInvidious = result.disableInvidious; - disableBibliogram = result.disableBibliogram; - disableOsm = result.disableOsm; - disableOldReddit = result.disableOldReddit; - disableSearchEngine = result.disableSearchEngine; - nitterInstance = result.nitterInstance; - invidiousInstance = result.invidiousInstance; - bibliogramInstance = result.bibliogramInstance; - osmInstance = result.osmInstance || osmDefault; - oldRedditView = result.oldRedditView || oldRedditDefaultView; - alwaysProxy = result.alwaysProxy; - onlyEmbeddedVideo = result.onlyEmbeddedVideo; - videoQuality = result.videoQuality; - invidiousDarkMode = result.invidiousDarkMode; - exceptions = result.exceptions - ? result.exceptions.map((e) => { - return new RegExp(e); - }) - : []; - invidiousVolume = result.invidiousVolume; - invidiousPlayerStyle = result.invidiousPlayerStyle; - invidiousSubtitles = result.invidiousSubtitles || ""; - invidiousAutoplay = result.invidiousAutoplay; - useFreeTube = result.useFreeTube; - nitterRandomPool = result.nitterRandomPool - ? result.nitterRandomPool.split(",") - : filterInstances(nitterInstances); - invidiousRandomPool = result.invidiousRandomPool - ? result.invidiousRandomPool.split(",") - : filterInstances(invidiousInstances); - bibliogramRandomPool = result.bibliogramRandomPool - ? result.bibliogramRandomPool.split(",") - : filterInstances(bibliogramInstances); - } -); - -browser.storage.onChanged.addListener((changes) => { - if ("nitterInstance" in changes) { - nitterInstance = changes.nitterInstance.newValue; - } - if ("invidiousInstance" in changes) { - invidiousInstance = changes.invidiousInstance.newValue; - } - if ("bibliogramInstance" in changes) { - bibliogramInstance = changes.bibliogramInstance.newValue; - } - if ("osmInstance" in changes) { - osmInstance = changes.osmInstance.newValue || osmDefault; - } - if ("oldRedditView" in changes) { - oldRedditView = changes.oldRedditView.newValue || oldRedditDefaultView; - } - if ("disableNitter" in changes) { - disableNitter = changes.disableNitter.newValue; - } - if ("disableInvidious" in changes) { - disableInvidious = changes.disableInvidious.newValue; - } - if ("disableBibliogram" in changes) { - disableBibliogram = changes.disableBibliogram.newValue; - } - if ("disableOsm" in changes) { - disableOsm = changes.disableOsm.newValue; - } - if ("disableOldReddit" in changes) { - disableOldReddit = changes.disableOldReddit.newValue; - } - if ("disableSearchEngine" in changes) { - disableSearchEngine = changes.disableSearchEngine.newValue; - } - if ("alwaysProxy" in changes) { - alwaysProxy = changes.alwaysProxy.newValue; - } - if ("onlyEmbeddedVideo" in changes) { - onlyEmbeddedVideo = changes.onlyEmbeddedVideo.newValue; - } - if ("videoQuality" in changes) { - videoQuality = changes.videoQuality.newValue; - } - if ("invidiousDarkMode" in changes) { - invidiousDarkMode = changes.invidiousDarkMode.newValue; - } - if ("invidiousVolume" in changes) { - invidiousVolume = changes.invidiousVolume.newValue; - } - if ("invidiousPlayerStyle" in changes) { - invidiousPlayerStyle = changes.invidiousPlayerStyle.newValue; - } - if ("invidiousSubtitles" in changes) { - invidiousSubtitles = changes.invidiousSubtitles.newValue; - } - if ("invidiousAutoplay" in changes) { - invidiousAutoplay = changes.invidiousAutoplay.newValue; - } - if ("useFreeTube" in changes) { - useFreeTube = changes.useFreeTube.newValue; - } - if ("nitterRandomPool" in changes) { - nitterRandomPool = changes.nitterRandomPool.newValue.split(","); - } - if ("invidiousRandomPool" in changes) { - invidiousRandomPool = changes.invidiousRandomPool.newValue.split(","); - } - if ("bibliogramRandomPool" in changes) { - bibliogramRandomPool = changes.bibliogramRandomPool.newValue.split(","); - } - if ("exceptions" in changes) { - exceptions = changes.exceptions.newValue.map((e) => { - return new RegExp(e); - }); - } -}); - -function getRandomInstance(instanceList) { - return instanceList[~~(instanceList.length * Math.random())]; -} - -function addressToLatLng(address, callback) { - const xmlhttp = new XMLHttpRequest(); - xmlhttp.onreadystatechange = () => { - if (xmlhttp.readyState === XMLHttpRequest.DONE) { - if (xmlhttp.status === 200) { - const json = JSON.parse(xmlhttp.responseText)[0]; - if (json) { - callback( - `${json.lat}%2C${json.lon}`, - `${json.boundingbox[2]},${json.boundingbox[1]},${json.boundingbox[3]},${json.boundingbox[0]}` - ); - } - } else { - console.info("Error: Status is " + xmlhttp.status); - } - } - }; - xmlhttp.open( - "GET", - `https://nominatim.openstreetmap.org/search/${address}?format=json&limit=1`, - false - ); - xmlhttp.send(); -} - -function isException(url, initiator) { - return ( - exceptions.some((regex) => regex.test(url.href)) || - (initiator && exceptions.some((regex) => regex.test(initiator.href))) - ); -} - -function isFirefox() { - return typeof InstallTrigger !== "undefined"; -} - -function redirectYouTube(url, initiator, type) { - if (disableInvidious || isException(url, initiator)) { - return null; - } - if ( - initiator && - (initiator.origin === invidiousInstance || - invidiousInstances.includes(initiator.origin) || - youtubeDomains.includes(initiator.host)) - ) { - return null; - } - if (url.pathname.match(/iframe_api/) || url.pathname.match(/www-widgetapi/)) { - // Don't redirect YouTube Player API. - return null; - } - if (url.host.split(".")[0] === "studio") { - // Avoid redirecting `studio.youtube.com` - return null; - } - if (onlyEmbeddedVideo && type !== "sub_frame") { - return null; - } - if (useFreeTube && type === "main_frame") { - return `freetube://${url}`; - } - // Apply settings - if (alwaysProxy) { - url.searchParams.append("local", true); - } - if (videoQuality) { - url.searchParams.append("quality", videoQuality); - } - if (invidiousDarkMode) { - url.searchParams.append("dark_mode", invidiousDarkMode); - } - if (invidiousVolume) { - url.searchParams.append("volume", invidiousVolume); - } - if (invidiousPlayerStyle) { - url.searchParams.append("player_style", invidiousPlayerStyle); - } - if (invidiousSubtitles) { - url.searchParams.append("subtitles", invidiousSubtitles); - } - url.searchParams.append("autoplay", invidiousAutoplay ? 1 : 0); - - return `${ - invidiousInstance || getRandomInstance(invidiousRandomPool) - }${url.pathname.replace("/shorts", "")}${url.search}`; -} - -function redirectTwitter(url, initiator) { - if (disableNitter || isException(url, initiator)) { - return null; - } - if (url.pathname.includes("/home")) { - return null; - } - if ( - isFirefox() && - initiator && - (initiator.origin === nitterInstance || - nitterInstances.includes(initiator.origin) || - twitterDomains.includes(initiator.host)) - ) { - browser.storage.sync.set({ - redirectBypassFlag: true, - }); - return null; - } - if (url.host.split(".")[0] === "pbs") { - return `${ - nitterInstance || getRandomInstance(nitterRandomPool) - }/pic/${encodeURIComponent(url.href)}`; - } else if (url.host.split(".")[0] === "video") { - return `${ - nitterInstance || getRandomInstance(nitterRandomPool) - }/gif/${encodeURIComponent(url.href)}`; - } else if (url.pathname.includes("tweets")) { - return `${ - nitterInstance || getRandomInstance(nitterRandomPool) - }${url.pathname.replace("/tweets", "")}${url.search}`; - } else { - return `${nitterInstance || getRandomInstance(nitterRandomPool)}${ - url.pathname - }${url.search}`; - } -} - -function redirectInstagram(url, initiator, type) { - if (disableBibliogram || isException(url, initiator)) { - return null; - } - // Do not redirect Bibliogram view on Instagram links - if ( - initiator && - (initiator.origin === bibliogramInstance || - bibliogramInstances.includes(initiator.origin) || - instagramDomains.includes(initiator.host)) - ) { - return null; - } - // Do not redirect /accounts, /embeds.js, or anything other than main_frame - if (type !== "main_frame" || url.pathname.match(bibliogramBypassPaths)) { - return null; - } - if ( - url.pathname === "/" || - instagramReservedPaths.includes(url.pathname.split("/")[1]) - ) { - return `${bibliogramInstance || getRandomInstance(bibliogramRandomPool)}${ - url.pathname - }${url.search}`; - } else { - // Likely a user profile, redirect to '/u/...' - return `${bibliogramInstance || getRandomInstance(bibliogramRandomPool)}/u${ - url.pathname - }${url.search}`; - } -} - -function redirectGoogleMaps(url, initiator) { - if (disableOsm || isException(url, initiator)) { - return null; - } - let redirect; - let mapCentre = ""; - let params = ""; - // Set map centre if present - if (url.pathname.match(mapCentreRegex)) { - const [, lat, lon, zoom] = url.pathname.match(mapCentreRegex); - mapCentre = `#map=${zoom}/${lat}/${lon}`; - } else if (url.search.includes("center=")) { - const [lat, lon] = url.searchParams.get("center").split(","); - mapCentre = `#map=${url.searchParams.get("zoom") || "17"}/${lat}/${lon}`; - // Set default zoom if mapCentre not present - } else { - params = "&zoom=17"; - } - // Set map layer - params = `${params}&layers=${ - layers[url.searchParams.get("layer")] || layers["none"] - }`; - // Handle Google Maps Embed API - if (url.pathname.includes("/embed")) { - let query = ""; - if (url.searchParams.has("q")) { - query = url.searchParams.get("q"); - } else if (url.searchParams.has("query")) { - query = url.searchParams.has("query"); - } else if (url.searchParams.has("pb")) { - try { - query = url.searchParams.get("pb").split(/!2s(.*?)!/)[1]; - } catch (error) { - console.error(error); - // Unable to find map marker in URL. - } - } - let marker, bbox; - addressToLatLng(query, (coords, boundingbox) => { - marker = coords; - bbox = boundingbox; - }); - redirect = `${osmInstance}/export/embed.html?bbox=${bbox}&layer=mapnik&marker=${marker}`; - // Handle Google Maps Directions - } else if (url.pathname.includes("/dir")) { - const travelMode = - travelModes[url.searchParams.get("travelmode")] || travelModes["driving"]; - let origin; - addressToLatLng(url.searchParams.get("origin"), (coords) => { - origin = coords; - }); - let destination; - addressToLatLng(url.searchParams.get("destination"), (coords) => { - destination = coords; - }); - redirect = `${osmInstance}/directions?engine=${travelMode}&route=${origin}%3B${destination}${mapCentre}${params}`; - // Get marker from data attribute - } else if ( - url.pathname.includes("data=") && - url.pathname.match(dataLatLngRegex) - ) { - const [mlat, mlon] = url.pathname.match(dataLatLngRegex); - redirect = `${osmInstance}/?mlat=${mlat.replace( - "!3d", - "" - )}&mlon=${mlon.replace("!4d", "")}${mapCentre}${params}`; - // Get marker from ll param - } else if (url.searchParams.has("ll")) { - const [mlat, mlon] = url.searchParams.get("ll").split(","); - redirect = `${osmInstance}/?mlat=${mlat}&mlon=${mlon}${mapCentre}${params}`; - // Get marker from viewpoint param. - } else if (url.searchParams.has("viewpoint")) { - const [mlat, mlon] = url.searchParams.get("viewpoint").split(","); - redirect = `${osmInstance}/?mlat=${mlat}&mlon=${mlon}${mapCentre}${params}`; - // Use query as search if present. - } else { - let query; - if (url.searchParams.has("q")) { - query = url.searchParams.get("q"); - } else if (url.searchParams.has("query")) { - query = url.searchParams.get("query"); - } else if (url.pathname.match(placeRegex)) { - query = url.pathname.match(placeRegex)[1]; - } - redirect = `${osmInstance}/${query ? "search?query=" + query : ""}${ - mapCentre || "#" - }${params}`; - } - - return redirect; -} - -function redirectReddit(url, initiator, type) { - if (disableOldReddit || isException(url, initiator)) { - return null; - } - // Do not redirect when already on the selected view - if ( - (initiator && initiator.origin === oldRedditView) || - url.origin === oldRedditView - ) { - return null; - } - // Do not redirect exclusions nor anything other than main_frame - if (type !== "main_frame" || url.pathname.match(redditBypassPaths)) { - return null; - } - return `${oldRedditView}${url.pathname}${url.search}`; -} - -function redirectSearchEngine(url, initiator) { - if (disableSearchEngine || isException(url, initiator)) { - return null; - } - - let searchEngine = getRandomInstance(privateSearchEngine); - let search = ""; - url.search - .slice(1) - .split("&") - .forEach(function (input) { - if (input.startsWith("q=")) search = input; - }); - console.log("search: ", search); - return `${searchEngine.link}${searchEngine.q}?${search}`; -} - -browser.webRequest.onBeforeRequest.addListener( - (details) => { - const url = new URL(details.url); - let initiator; - if (details.originUrl) { - initiator = new URL(details.originUrl); - } else if (details.initiator) { - initiator = new URL(details.initiator); - } - let redirect; - if (youtubeDomains.includes(url.host)) { - redirect = { - redirectUrl: redirectYouTube(url, initiator, details.type), - }; - } else if (twitterDomains.includes(url.host)) { - redirect = { - redirectUrl: redirectTwitter(url, initiator), - }; - } else if (instagramDomains.includes(url.host)) { - redirect = { - redirectUrl: redirectInstagram(url, initiator, details.type), - }; - } else if (url.href.match(googleMapsRegex)) { - redirect = { - redirectUrl: redirectGoogleMaps(url, initiator), - }; - } else if ( - redditDomains.includes(url.host) || - oldRedditViews.includes(url.origin) - ) { - redirect = { - redirectUrl: redirectReddit(url, initiator, details.type), - }; - } else if (url.href.match(googleSearchRegex)) { - redirect = { - redirectUrl: redirectSearchEngine(url, initiator), - }; - } - if (redirect && redirect.redirectUrl) { - console.info( - "Redirecting", - `"${url.href}"`, - "=>", - `"${redirect.redirectUrl}"` - ); - console.info("Details", details); - } - return redirect; - }, - { - urls: [""], - }, - ["blocking"] -); - -browser.runtime.onInstalled.addListener((details) => { - if (details.reason === "update") { - browser.storage.sync.get( - ["whitelist", "exceptions", "invidiousInstance"], - (result) => { - if (result.whitelist) { - let whitelist = result.whitelist.map((e) => - e.replace(/[-\/\\^$*+?.()|[\]{}]/g, "\\$&") - ); - browser.storage.sync.set({ - exceptions: result.exceptions.concat(whitelist), - whitelist: null, - }); - } - if (result.invidiousInstance === "https://invidio.us") { - browser.storage.sync.set({ - invidiousInstance: null, - }); - } - } - ); - } -}); diff --git a/manifest.json b/manifest.json index 0fc6f104..04ea6c16 100644 --- a/manifest.json +++ b/manifest.json @@ -1,28 +1,28 @@ { "name": "__MSG_extensionName__", "description": "__MSG_extensionDescription__", - "version": "1.1.43", + "version": "1.1.44", "manifest_version": 2, "background": { - "scripts": ["background.js"], + "page": "src/pages/background/background.html", "persistent": true }, "default_locale": "en", "icons": { - "16": "assets/images/icon16.png", - "32": "assets/images/icon32.png", - "48": "assets/images/icon48.png", - "128": "assets/images/icon128.png" + "16": "src/assets/images/icon16.png", + "32": "src/assets/images/icon32.png", + "48": "src/assets/images/icon48.png", + "128": "src/assets/images/icon128.png" }, "permissions": ["storage", "webRequest", "webRequestBlocking", ""], "browser_action": { "default_title": "Privacy Redirect", - "default_popup": "pages/popup/popup.html", + "default_popup": "src/pages/popup/popup.html", "default_icon": { - "16": "assets/images/icon16.png", - "32": "assets/images/icon32.png", - "48": "assets/images/icon48.png", - "128": "assets/images/icon128.png" + "16": "src/assets/images/icon16.png", + "32": "src/assets/images/icon32.png", + "48": "src/assets/images/icon48.png", + "128": "src/assets/images/icon128.png" } }, "content_scripts": [ @@ -34,39 +34,34 @@ "*://pbs.twimg.com/*", "*://video.twimg.com/*" ], - "js": ["assets/javascript/remove-twitter-sw.js"], + "js": ["src/assets/javascripts/remove-twitter-sw.js"], "run_at": "document_start" }, { "matches": [ "*://invidious.snopyta.org/*", - "*://yewtu.be/*", "*://invidious.xyz/*", - "*://invidious.site/*", + "*://invidious.kavin.rocks/*", + "*://tube.connect.cafe/*", + "*://invidious.zapashcanon.fr/*", "*://invidiou.site/*", - "*://invidious.ggc-project.de/*", - "*://invidious.13ad.de/*", - "*://invidious.toot.koeln/*", - "*://invidious.fdn.fr/*", - "*://watch.nettohikari.com/*", - "*://yt.iswleuven.be/*", - "*://yt.maisputain.ovh/*", - "*://kgg2m7yk5aybusll.onion/*", - "*://axqzx4s6s54s32yentfqojs3x5i7faxza6xo3ehd4bzzsg2ii4fv2iid.onion/*", + "*://vid.mint.lgbt/*", + "*://invidious.site/*", + "*://yewtu.be/*", "*://fz253lmuao3strwbfbmx46yu7acac2jz27iwtorgmbqlkurlclmancad.onion/*", "*://qklhadlycap4cnod.onion/*", "*://c7hqkpkpemu6e7emz5b4vyz7idjgdvgaaa3dyimmeojqbgpea3xqjoid.onion/*", - "*://mfqczy4mysscub2s.onion/*", - "*://4l2dgddgsrkf2ous66i6seeyi6etzfgrue332grh2n7madpwopotugyd.onion/*" + "*://w6ijuptxiku4xpnnaetxvnkc5vqcdu7mgns2u77qefoixi63vbvnpnqd.onion/*" ], - "js": ["assets/javascript/persist-invidious-prefs.js"], + "js": ["src/assets/javascripts/persist-invidious-prefs.js"], "run_at": "document_start" } ], "options_ui": { - "page": "pages/options/options.html", + "page": "src/pages/options/options.html", "open_in_tab": false }, + "web_accessible_resources": ["src/assets/javascripts/helpers/*"], "browser_specific_settings": { "gecko": { "id": "{b7f9d2cd-d772-4302-8c3f-eb941af36f76}" diff --git a/pages/options/options.html b/pages/options/options.html deleted file mode 100644 index bd7cee7e..00000000 --- a/pages/options/options.html +++ /dev/null @@ -1,569 +0,0 @@ - - - - - - - - Privacy Redirect Options - - - -
- - - -
- -
-
- - - - - - - -
-

Nitter Redirects

-
-   - -
-
-
- - - - - - - -
-

- Invidious Redirects -

-
-   - -
-
-
- - - - - - - -
-

- Bibliogram Redirects -

-
-   - -
-
-
- - - - - - - -
-

- OpenStreetMap Redirects -

-
-   - -
-
-
- - - - - - - -
-

- Old Reddit Redirects -

-
-   - -
-
-
- - - - - - - -
-

- Search Engine Redirects -

-
-   - -
-
-
-

Nitter Instance

-
- -
-
-
-

Invidious Instance

-
- -
-
-
-

Bibliogram Instance

-
- -
-
-
-

OpenStreetMap Instance

-
- -
-
-
-

Old Reddit View (Desktop or Mobile)

-
- -
-
-
-

Theme

- -
-
- -
-
-

Invidious

-
-
-
-

- Invidious random instance pool (comma-separated) -

- -
-
- - - - - - - -
-

- Use FreeTube over Invidious when possible -

-
-   - -
-
-
- - - - - - - -
-

- Always proxy videos through Invidious -

-
-   - -
-
-
- - - - - - - -
-

- Only redirect embedded video to Invidious -

-
-   - -
-
-
-

Invidious Video Quality

- -
-
- - - - - - - -
-

- Invidious dark mode always on -

-
-   - -
-
-
-

- Invidious Volume -

- -
-
-

- Invidious Player Style -

- -
-
-

- Invidious Subtitles - language codes (comma-separated) -

- -
-
- - - - - - - -
-

- Invidious automatically play video on load -

-
-   - -
-
-
- - - - - - - -
-

- Persist Invidious preferences (as cookie) -

-
-   - -
-
-
-

Nitter

-
-
-
-

- Nitter random instance pool (comma-separated) -

- -
-
- - - - - - - -
-

- Proactively remove Twitter service worker -

-
-   - -
-
-
-

Bibliogram

-
-
-
-

- Bibliogram random instance pool (comma-separated) -

- -
-
- -
-
-

- Enter a URL or Regular Expression to be excluded from redirects. -

-

- All requests for or initiating from a URL that matches your exception - will be excluded from redirects. -

-

- Note - Supports JavaScript regular expressions, excluding the - enclosing forward slashes. -

-
-
- - - - - - - - - - - -
-

Add Exception

-
- - - - - - - - -
-
-
    -
    - - - - - diff --git a/pages/options/options.js b/pages/options/options.js deleted file mode 100644 index 2530a328..00000000 --- a/pages/options/options.js +++ /dev/null @@ -1,526 +0,0 @@ -"use strict"; - -const nitterInstances = [ - "https://nitter.net", - "https://nitter.snopyta.org", - "https://nitter.42l.fr", - "https://nitter.nixnet.services", - "https://nitter.13ad.de", - "https://nitter.pussthecat.org", - "https://nitter.mastodont.cat", - "https://nitter.dark.fail", - "https://nitter.tedomum.net", - "https://nitter.cattube.org", - "https://nitter.fdn.fr", - "https://nitter.1d4.us", - "https://nitter.kavin.rocks", - "https://tweet.lambda.dance", - "https://nitter.cc", - "https://nitter.weaponizedhumiliation.com", - "https://nitter.vxempire.xyz", - "https://nitter.unixfox.eu", - "http://3nzoldnxplag42gqjs23xvghtzf6t6yzssrtytnntc6ppc7xxuoneoad.onion", - "http://nitter.l4qlywnpwqsluw65ts7md3khrivpirse744un3x7mlskqauz5pyuzgqd.onion", - "http://nitterlgj3n5fgwesu3vxc5h67ruku33nqaoeoocae2mvlzhsu6k7fqd.onion", - "http://npf37k3mtzwxreiw52ccs5ay4e6qt2fkcs2ndieurdyn2cuzzsfyfvid.onion", -]; -const invidiousInstances = [ - "https://invidious.snopyta.org", - "https://invidious.xyz", - "https://invidious.kavin.rocks", - "https://tube.connect.cafe", - "https://invidious.zapashcanon.fr", - "https://invidiou.site", - "https://vid.mint.lgbt", - "https://invidious.site", - "http://fz253lmuao3strwbfbmx46yu7acac2jz27iwtorgmbqlkurlclmancad.onion", - "http://qklhadlycap4cnod.onion", - "http://c7hqkpkpemu6e7emz5b4vyz7idjgdvgaaa3dyimmeojqbgpea3xqjoid.onion", - "http://w6ijuptxiku4xpnnaetxvnkc5vqcdu7mgns2u77qefoixi63vbvnpnqd.onion", -]; -const bibliogramInstances = [ - "https://bibliogram.art", - "https://bibliogram.snopyta.org", - "https://bibliogram.pussthecat.org", - "https://bibliogram.nixnet.services", - "https://bg.endl.site", - "https://bibliogram.13ad.de", - "https://bibliogram.pixelfed.uno", - "https://bibliogram.ethibox.fr", - "https://bibliogram.hamster.dance", - "https://bibliogram.kavin.rocks", - "https://bibliogram.ggc-project.de", -]; -const osmInstances = ["https://openstreetmap.org"]; -const oldRedditViews = ["https://old.reddit.com", "https://i.reddit.com"]; -const autocompletes = [ - { id: "nitter-instance", instances: nitterInstances }, - { id: "invidious-instance", instances: invidiousInstances }, - { id: "bibliogram-instance", instances: bibliogramInstances }, - { id: "osm-instance", instances: osmInstances }, - { id: "old-reddit-view", instances: oldRedditViews }, -]; - -let nitterInstance = document.getElementById("nitter-instance"); -let invidiousInstance = document.getElementById("invidious-instance"); -let bibliogramInstance = document.getElementById("bibliogram-instance"); -let osmInstance = document.getElementById("osm-instance"); -let oldRedditView = document.getElementById("old-reddit-view"); -let disableNitter = document.getElementById("disable-nitter"); -let disableInvidious = document.getElementById("disable-invidious"); -let disableBibliogram = document.getElementById("disable-bibliogram"); -let disableOsm = document.getElementById("disable-osm"); -let disableOldReddit = document.getElementById("disable-old-reddit"); -let disableSearchEngine = document.getElementById("disable-searchEngine"); -let alwaysProxy = document.getElementById("always-proxy"); -let onlyEmbeddedVideo = document.getElementById("only-embed"); -let videoQuality = document.getElementById("video-quality"); -let removeTwitterSW = document.getElementById("remove-twitter-sw"); -let invidiousDarkMode = document.getElementById("invidious-dark-mode"); -let persistInvidiousPrefs = document.getElementById("persist-invidious-prefs"); -let invidiousVolume = document.getElementById("invidious-volume"); -let invidiousPlayerStyle = document.getElementById("invidious-player-style"); -let invidiousSubtitles = document.getElementById("invidious-subtitles"); -let invidiousAutoplay = document.getElementById("invidious-autoplay"); -let theme = document.getElementById("theme"); -let useFreeTube = document.getElementById("use-freetube"); -let nitterRandomPool = document.getElementById("nitter-random-pool"); -let invidiousRandomPool = document.getElementById("invidious-random-pool"); -let bibliogramRandomPool = document.getElementById("bibliogram-random-pool"); -let exceptions; - -window.browser = window.browser || window.chrome; - -function prependExceptionsItem(item, index) { - const li = document.createElement("li"); - li.appendChild(document.createTextNode(item.toString())); - const button = document.createElement("button"); - li.appendChild(button); - document.getElementById("exceptions-items").prepend(li); - const svg = ` - - - `; - button.innerHTML = svg; - button.addEventListener("click", () => { - exceptions.splice(index, 1); - browser.storage.sync.set({ - exceptions: exceptions, - }); - li.remove(); - }); -} - -function filterInstances(instances) { - return instances.filter((instance) => !instance.includes(".onion")).join(); -} - -browser.storage.sync.get( - [ - "nitterInstance", - "invidiousInstance", - "bibliogramInstance", - "osmInstance", - "oldRedditView", - "disableNitter", - "disableInvidious", - "disableBibliogram", - "disableOsm", - "disableOldReddit", - "disableSearchEngine", - "alwaysProxy", - "onlyEmbeddedVideo", - "videoQuality", - "removeTwitterSW", - "invidiousDarkMode", - "persistInvidiousPrefs", - "invidiousVolume", - "invidiousPlayerStyle", - "invidiousSubtitles", - "invidiousAutoplay", - "exceptions", - "theme", - "useFreeTube", - "nitterRandomPool", - "invidiousRandomPool", - "bibliogramRandomPool", - ], - (result) => { - theme.value = result.theme || ""; - if (result.theme) document.body.classList.add(result.theme); - nitterInstance.value = result.nitterInstance || ""; - invidiousInstance.value = result.invidiousInstance || ""; - bibliogramInstance.value = result.bibliogramInstance || ""; - osmInstance.value = result.osmInstance || ""; - oldRedditView.value = result.oldRedditView || ""; - disableNitter.checked = !result.disableNitter; - disableInvidious.checked = !result.disableInvidious; - disableBibliogram.checked = !result.disableBibliogram; - disableOsm.checked = !result.disableOsm; - disableOldReddit.checked = !result.disableOldReddit; - disableSearchEngine.checked = !result.disableSearchEngine; - alwaysProxy.checked = result.alwaysProxy; - onlyEmbeddedVideo.checked = result.onlyEmbeddedVideo; - videoQuality.value = result.videoQuality || ""; - removeTwitterSW.checked = !result.removeTwitterSW; - invidiousDarkMode.checked = result.invidiousDarkMode; - persistInvidiousPrefs.checked = result.persistInvidiousPrefs; - exceptions = result.exceptions || []; - exceptions.forEach(prependExceptionsItem); - invidiousVolume.value = result.invidiousVolume; - document.querySelector("#volume-value").textContent = result.invidiousVolume - ? `${result.invidiousVolume}%` - : " - "; - invidiousPlayerStyle.value = result.invidiousPlayerStyle || ""; - invidiousSubtitles.value = result.invidiousSubtitles || ""; - invidiousAutoplay.checked = result.invidiousAutoplay; - useFreeTube.checked = result.useFreeTube; - nitterRandomPool.value = - result.nitterRandomPool || filterInstances(nitterInstances); - invidiousRandomPool.value = - result.invidiousRandomPool || filterInstances(invidiousInstances); - bibliogramRandomPool.value = - result.bibliogramRandomPool || filterInstances(bibliogramInstances); - } -); - -function openTab(tab, event) { - let i, tabcontent, tablinks; - tabcontent = document.getElementsByClassName("tabcontent"); - for (i = 0; i < tabcontent.length; i++) { - tabcontent[i].style.display = "none"; - } - tablinks = document.getElementsByClassName("tablinks"); - for (i = 0; i < tablinks.length; i++) { - tablinks[i].className = tablinks[i].className.replace(" active", ""); - } - document.getElementById(tab).style.display = "block"; - event.currentTarget.className += " active"; -} - -document - .getElementById("general-tab") - .addEventListener("click", openTab.bind(null, "general")); -document - .getElementById("advanced-tab") - .addEventListener("click", openTab.bind(null, "advanced")); -document - .getElementById("exceptions-tab") - .addEventListener("click", openTab.bind(null, "exceptions")); - -document.getElementById("general-tab").click(); - -function addToExceptions() { - const input = document.getElementById("new-exceptions-item"); - const type = document.querySelector('input[name="type"]:checked').value; - if (input.value) { - try { - let value = input.value; - new RegExp(input.value); - if (type === "URL") { - value = value.replace(/[-\/\\^$*+?.()|[\]{}]/g, "\\$&"); - } - exceptions.push(value); - browser.storage.sync.set({ - exceptions: exceptions, - }); - prependExceptionsItem(value, exceptions.indexOf(value)); - input.value = ""; - } catch (error) { - input.setCustomValidity("Invalid RegExp"); - } - } else { - input.setCustomValidity("Invalid RegExp"); - } -} - -document - .getElementById("add-to-exceptions") - .addEventListener("click", addToExceptions); - -function debounce(func, wait, immediate) { - let timeout; - return () => { - let context = this, - args = arguments; - let later = () => { - timeout = null; - if (!immediate) func.apply(context, args); - }; - let callNow = immediate && !timeout; - clearTimeout(timeout); - timeout = setTimeout(later, wait); - if (callNow) func.apply(context, args); - }; -} - -function parseURL(urlString) { - if (urlString) { - try { - const url = new URL(urlString); - if (url.username && url.password) { - return `${url.protocol}//${url.username}:${url.password}@${url.host}`; - } else { - return url.origin; - } - } catch (error) { - console.log(error); - return ""; - } - } else { - return ""; - } -} - -let nitterInstanceChange = debounce(() => { - if (nitterInstance.checkValidity()) { - browser.storage.sync.set({ - nitterInstance: parseURL(nitterInstance.value), - }); - } -}, 500); -nitterInstance.addEventListener("input", nitterInstanceChange); - -let invidiousInstanceChange = debounce(() => { - if (invidiousInstance.checkValidity()) { - browser.storage.sync.set({ - invidiousInstance: parseURL(invidiousInstance.value), - }); - } -}, 500); -invidiousInstance.addEventListener("input", invidiousInstanceChange); - -let bibliogramInstanceChange = debounce(() => { - if (bibliogramInstance.checkValidity()) { - browser.storage.sync.set({ - bibliogramInstance: parseURL(bibliogramInstance.value), - }); - } -}, 500); -bibliogramInstance.addEventListener("input", bibliogramInstanceChange); - -let osmInstanceChange = debounce(() => { - if (osmInstance.checkValidity()) { - browser.storage.sync.set({ - osmInstance: parseURL(osmInstance.value), - }); - } -}, 500); -osmInstance.addEventListener("input", osmInstanceChange); - -let oldRedditViewChange = debounce(() => { - if (oldRedditView.checkValidity()) { - browser.storage.sync.set({ - oldRedditView: parseURL(oldRedditView.value), - }); - } -}, 500); -oldRedditView.addEventListener("input", oldRedditViewChange); - -disableNitter.addEventListener("change", (event) => { - browser.storage.sync.set({ disableNitter: !event.target.checked }); -}); - -disableInvidious.addEventListener("change", (event) => { - browser.storage.sync.set({ disableInvidious: !event.target.checked }); -}); - -disableBibliogram.addEventListener("change", (event) => { - browser.storage.sync.set({ disableBibliogram: !event.target.checked }); -}); - -disableOsm.addEventListener("change", (event) => { - browser.storage.sync.set({ disableOsm: !event.target.checked }); -}); - -disableOldReddit.addEventListener("change", (event) => { - browser.storage.sync.set({ disableOldReddit: !event.target.checked }); -}); - -disableSearchEngine.addEventListener("change", (event) => { - browser.storage.sync.set({ disableSearchEngine: !event.target.checked }); -}); - -alwaysProxy.addEventListener("change", (event) => { - browser.storage.sync.set({ alwaysProxy: event.target.checked }); -}); - -onlyEmbeddedVideo.addEventListener("change", (event) => { - browser.storage.sync.set({ onlyEmbeddedVideo: event.target.checked }); -}); - -videoQuality.addEventListener("change", (event) => { - browser.storage.sync.set({ - videoQuality: event.target.options[videoQuality.selectedIndex].value, - }); -}); - -removeTwitterSW.addEventListener("change", (event) => { - browser.storage.sync.set({ removeTwitterSW: !event.target.checked }); -}); - -invidiousDarkMode.addEventListener("change", (event) => { - browser.storage.sync.set({ invidiousDarkMode: event.target.checked }); -}); - -persistInvidiousPrefs.addEventListener("change", (event) => { - browser.storage.sync.set({ persistInvidiousPrefs: event.target.checked }); -}); - -useFreeTube.addEventListener("change", (event) => { - browser.storage.sync.set({ useFreeTube: event.target.checked }); -}); - -let invidiousVolumeChange = debounce(() => { - document.querySelector( - "#volume-value" - ).textContent = `${invidiousVolume.value}%`; - browser.storage.sync.set({ - invidiousVolume: invidiousVolume.value, - }); -}, 500); -invidiousVolume.addEventListener("input", invidiousVolumeChange); - -invidiousPlayerStyle.addEventListener("change", (event) => { - browser.storage.sync.set({ - invidiousPlayerStyle: - event.target.options[invidiousPlayerStyle.selectedIndex].value, - }); -}); - -let invidiousSubtitlesChange = debounce(() => { - browser.storage.sync.set({ invidiousSubtitles: invidiousSubtitles.value }); -}, 500); -invidiousSubtitles.addEventListener("input", invidiousSubtitlesChange); - -invidiousAutoplay.addEventListener("change", (event) => { - browser.storage.sync.set({ invidiousAutoplay: event.target.checked }); -}); - -let nitterRandomPoolChange = debounce(() => { - browser.storage.sync.set({ nitterRandomPool: nitterRandomPool.value }); -}, 500); -nitterRandomPool.addEventListener("input", nitterRandomPoolChange); - -let invidiousRandomPoolChange = debounce(() => { - browser.storage.sync.set({ invidiousRandomPool: invidiousRandomPool.value }); -}, 500); -invidiousRandomPool.addEventListener("input", invidiousRandomPoolChange); - -let bibliogramRandomPoolChange = debounce(() => { - browser.storage.sync.set({ - bibliogramRandomPool: bibliogramRandomPool.value, - }); -}, 500); -bibliogramRandomPool.addEventListener("input", bibliogramRandomPoolChange); - -theme.addEventListener("change", (event) => { - const value = event.target.options[theme.selectedIndex].value; - switch (value) { - case "dark-theme": - document.body.classList.add("dark-theme"); - document.body.classList.remove("light-theme"); - break; - case "light-theme": - document.body.classList.add("light-theme"); - document.body.classList.remove("dark-theme"); - break; - default: - document.body.classList.remove("light-theme"); - document.body.classList.remove("dark-theme"); - } - browser.storage.sync.set({ - theme: value, - }); -}); - -function autocomplete(input, list) { - let currentFocus; - input.addEventListener("focus", (e) => { - showOptions(e, true); - }); - input.addEventListener("input", (e) => { - const val = e.target.value; - if (!val) { - return false; - } - currentFocus = -1; - showOptions(e); - }); - input.addEventListener("keydown", function (e) { - let x = document.getElementById(this.id + "autocomplete-list"); - if (x) x = x.getElementsByTagName("div"); - if (e.keyCode == 40) { - currentFocus++; - addActive(x); - } else if (e.keyCode == 38) { - currentFocus--; - addActive(x); - } else if (e.keyCode == 13) { - e.preventDefault(); - if (currentFocus > -1) { - if (x) x[currentFocus].click(); - } - } - }); - function showOptions(event, showAll = false) { - let div, - i, - val = event.target.value; - closeAllLists(); - div = document.createElement("div"); - div.setAttribute("id", event.target.id + "autocomplete-list"); - div.setAttribute("class", "autocomplete-items"); - event.target.parentNode.appendChild(div); - for (i = 0; i < list.length; i++) { - if (list[i].toLowerCase().indexOf(val.toLowerCase()) > -1) { - div.appendChild(getItem(list[i], val)); - } else if (showAll) { - div.appendChild(getItem(list[i], val)); - } - } - } - function getItem(item, val) { - let div = document.createElement("div"); - div.innerHTML = "" + item.substr(0, val.length) + ""; - div.innerHTML += item.substr(val.length); - div.innerHTML += ""; - div.addEventListener("click", function (e) { - input.value = e.target.getElementsByTagName("input")[0].value; - input.dispatchEvent(new Event("input")); - closeAllLists(); - }); - return div; - } - function addActive(x) { - if (!x) return false; - removeActive(x); - if (currentFocus >= x.length) currentFocus = 0; - if (currentFocus < 0) currentFocus = x.length - 1; - x[currentFocus].classList.add("autocomplete-active"); - } - function removeActive(x) { - for (let i = 0; i < x.length; i++) { - x[i].classList.remove("autocomplete-active"); - } - } - function closeAllLists(elmnt) { - let x = document.getElementsByClassName("autocomplete-items"); - for (let i = 0; i < x.length; i++) { - if (elmnt != x[i] && elmnt != input) { - x[i].parentNode.removeChild(x[i]); - } - } - } - document.addEventListener("click", (e) => { - if (!autocompletes.find((element) => element.id === e.target.id)) { - closeAllLists(e.target); - } - }); -} - -autocompletes.forEach((value) => { - autocomplete(document.getElementById(value.id), value.instances); -}); diff --git a/pages/popup/popup.html b/pages/popup/popup.html deleted file mode 100644 index af44b23e..00000000 --- a/pages/popup/popup.html +++ /dev/null @@ -1,214 +0,0 @@ - - - - - - - - - - - - -
    - - - - - - - -
    -

    Nitter Redirects

    -
    -   - -
    -
    - -
    - - - - - - - -
    -

    - Invidious Redirects -

    -
    -   - -
    -
    - -
    - - - - - - - -
    -

    - Bibliogram Redirects -

    -
    -   - -
    -
    - -
    - - - - - - - -
    -

    - OpenStreetMap Redirects -

    -
    -   - -
    -
    - -
    - - - - - - - -
    -

    - Old Reddit Redirects -

    -
    -   - -
    -
    - -
    - - - - - - - -
    -

    Search Engine Redirects

    -
    -   - -
    -
    - -
    - - - - - - - diff --git a/pages/popup/popup.js b/pages/popup/popup.js deleted file mode 100644 index 6d4c3ff7..00000000 --- a/pages/popup/popup.js +++ /dev/null @@ -1,62 +0,0 @@ -"use strict"; - -let disableNitter = document.querySelector("#disable-nitter"); -let disableInvidious = document.querySelector("#disable-invidious"); -let disableBibliogram = document.querySelector("#disable-bibliogram"); -let disableOsm = document.querySelector("#disable-osm"); -let disableOldReddit = document.querySelector("#disable-old-reddit"); -let disableSearchEngine = document.querySelector("#disable-searchEngine"); -let version = document.querySelector("#version"); - -window.browser = window.browser || window.chrome; - -browser.storage.sync.get( - [ - "disableNitter", - "disableInvidious", - "disableBibliogram", - "disableOsm", - "disableOldReddit", - "disableSearchEngine", - "theme", - ], - (result) => { - if (result.theme) document.body.classList.add(result.theme); - disableNitter.checked = !result.disableNitter; - disableInvidious.checked = !result.disableInvidious; - disableBibliogram.checked = !result.disableBibliogram; - disableOsm.checked = !result.disableOsm; - disableOldReddit.checked = !result.disableOldReddit; - disableSearchEngine.checked = !result.disableSearchEngine; - } -); - -version.textContent = browser.runtime.getManifest().version; - -disableNitter.addEventListener("change", (event) => { - browser.storage.sync.set({ disableNitter: !event.target.checked }); -}); - -disableInvidious.addEventListener("change", (event) => { - browser.storage.sync.set({ disableInvidious: !event.target.checked }); -}); - -disableBibliogram.addEventListener("change", (event) => { - browser.storage.sync.set({ disableBibliogram: !event.target.checked }); -}); - -disableOsm.addEventListener("change", (event) => { - browser.storage.sync.set({ disableOsm: !event.target.checked }); -}); - -disableOldReddit.addEventListener("change", (event) => { - browser.storage.sync.set({ disableOldReddit: !event.target.checked }); -}); - -disableSearchEngine.addEventListener("change", (event) => { - browser.storage.sync.set({ disableSearchEngine: !event.target.checked }); -}); - -document.querySelector("#more-options").addEventListener("click", () => { - browser.runtime.openOptionsPage(); -}); diff --git a/pages/styles.css b/pages/styles.css deleted file mode 100644 index 022b96bd..00000000 --- a/pages/styles.css +++ /dev/null @@ -1,481 +0,0 @@ -body { - --text: #fff; - --bg-main: #3c4043; - --bg-secondary: #292a2d; - --active: #ff5b56; - --space: 5px; - --danger: #f04141; - --danger-light: #f9d0d5; - --dark-grey: #767676; - --light-grey: #c3c3c3; -} - -body.light-theme { - --text: #000; - --bg-main: #e3e7ea; - --bg-secondary: #fff; -} - -.light-theme.popup, -.light-theme .popup { - background-color: var(--bg-secondary); -} - -body { - margin: 0; - max-width: 400px; - margin: auto; - min-height: 572px; - font-family: Sans-Serif; - background-color: var(--bg-secondary); - color: var(--text); -} - -.popup { - width: 300px; - min-height: auto; - overflow: hidden; - background-color: var(--bg-main); -} - -input { - appearance: none; - -moz-appearance: none; - -webkit-appearance: none; -} - -header { - background-color: var(--bg-main); - color: var(--text); - display: flex; - padding: var(--space); -} - -header .logo-container { - width: 100%; - margin: var(--space) 0 var(--space) 0; - display: flex; - align-items: center; -} - -header .logo-container img { - height: 85px; - float: left; -} - -header .logo-container h1 { - font-size: 25px; - float: left; - margin-left: 15px; - text-transform: uppercase; - font-weight: normal; -} - -header .privacy { - letter-spacing: 0.13em; -} - -header .version { - font-size: 8.5px; - font-weight: bold; - position: absolute; - top: var(--space); - right: var(--space); -} - -h1 { - font-size: 14px; - margin: 7px auto; -} - -i { - font-size: 12px; -} - -h2 { - clear: both; - font-size: 12px; - font-weight: normal; - margin: 0; -} - -h3 { - font-size: 16px; -} - -h1, -h2 { - color: var(--text); -} - -footer { - width: 100%; -} - -footer a.button { - margin: var(--space); -} - -input[type="url"], -input[type="text"], -select { - width: 100%; - box-sizing: border-box; - margin-bottom: var(--space); - background-color: var(--bg-main); - border-style: inset; - color: var(--text); -} - -input[type="url"] { - padding: 1px 2px; -} - -input[type="checkbox"] { - opacity: 0; -} - -input[type="radio"] { - appearance: radio; - -moz-appearance: radio; - -webkit-appearance: radio; -} - -input[type="radio"]:checked + label { - background: transparent; -} - -.checkbox-label { - margin-left: 5px; - background: grey; - border-radius: 25px; - color: var(--text); - cursor: pointer; - display: block; - float: right; - font-weight: bold; - height: 30px; - position: relative; - text-indent: -400px; - width: 50px; -} - -.checkbox-label:after { - background: white; - border-radius: 90px; - content: ""; - height: 20px; - left: var(--space); - position: absolute; - top: var(--space); - transition: 0.3s; - width: 20px; -} - -input:checked + label { - background: var(--active); -} - -input:checked + label:after { - left: calc(100% - var(--space)); - transform: translateX(-100%); -} - -.settings-block { - display: block; - padding: 5px 10px 5px 10px; -} - -.settings-block h1 { - float: left; -} - -.button { - border: var(--active) solid 1px; - color: var(--text); - stroke: var(--text); - display: block; - font-size: 12px; - font-weight: bold; - margin: var(--space) auto; - padding: 10px; - text-align: center; - text-decoration: none; - cursor: pointer; - -webkit-transition-duration: 0.4s; - transition-duration: 0.4s; -} - -.button * { - vertical-align: middle; -} - -.button:hover { - background-color: var(--active); - color: var(--text); - stroke: var(--text); -} - -.button:active { - background-color: var(--active); - box-shadow: 0 var(--space) var(--bg-main); - transform: translateY(4px); -} - -input:invalid { - color: var(--danger); - border-color: var(--danger); - background-color: var(--danger-light); -} - -.margin-bottom { - margin-bottom: 20px; -} - -.tab { - overflow: hidden; - background-color: var(--bg-secondary); - position: fixed; - top: 0; - width: 400px; - z-index: 2; -} - -.tab button { - border-top-left-radius: 10px; - border-top-right-radius: 10px; - color: var(--text); - background-color: inherit; - float: left; - border: none; - outline: none; - cursor: pointer; - padding: 14px 16px; - transition: 0.3s; - border: solid 1px var(--bg-main); - width: 33.333%; - font-size: 14px; -} - -.tab button:hover { - background-color: var(--active); -} - -.tab button.active { - background-color: var(--bg-main); -} - -.tabcontent { - padding-top: 50px; - display: none; - background-color: var(--bg-main); - min-height: 510px; -} - -div.exceptions { - clear: left; -} - -div.exceptions > input { - width: 240px; - float: left; -} - -#add-to-exceptions { - float: right; - border: var(--active) solid 1px; - background-color: var(--active); - color: var(--text); - font-weight: bold; - cursor: pointer; - border-radius: 50%; - padding: 1px 1px 0px 1px; - margin-right: 5px; -} - -#add-to-exceptions svg { - height: 20px; - width: 20px; -} - -ul { - padding: 0; - list-style-type: none; - color: var(--text); - margin: 20px 20px 0 20px; -} - -li { - border-bottom: solid 0.5px var(--bg-secondary); - padding: 20px 0px 20px 20px; -} - -#exceptions-items button { - float: right; - margin-right: -5px; - border: var(--active) solid 1px; - background-color: var(--active); - color: var(--text); - font-weight: bold; - cursor: pointer; - border-radius: 50%; - padding: 2px 2px 0px 2px; -} - -.button svg { - height: 18px; - width: 18px; -} - -.autocomplete { - position: relative; - display: inline-block; - width: 100%; -} - -.autocomplete input { - background: url(../assets/images/chevron-down.svg) right no-repeat; -} - -.autocomplete-items { - position: absolute; - border: 1px solid var(--bg-main); - border-bottom: none; - border-top: none; - z-index: 99; - top: 85%; - left: 0; - right: 0; - overflow-y: auto; - max-height: 175px; - color: var(--text); - overflow-x: hidden; - max-width: 380px; -} - -.autocomplete-items div { - padding: 10px; - cursor: pointer; - background-color: var(--bg-secondary); - border-bottom: 1px solid var(--bg-main); -} - -.autocomplete-items div:hover { - background-color: var(--active); -} - -.autocomplete-active { - background-color: var(--active); - color: var(--text); -} - -.option { - width: 100%; -} - -.option td { - vertical-align: middle; -} - -input[type="range"] { - -webkit-appearance: none; - margin: 18px 0; - width: 100%; -} - -input[type="range"]:focus { - outline: none; -} - -input[type="range"]::-webkit-slider-runnable-track { - width: 100%; - height: 8.4px; - cursor: pointer; - border-color: var(--dark-grey), var(--light-grey); - background: var(--bg-main); - border-radius: 1.3px; - border: 0.2px inset var(--dark-grey); -} - -input[type="range"]::-webkit-slider-thumb { - border-color: var(--active); - border: 1px solid var(--dark-grey); - height: 36px; - width: 16px; - border-radius: 3px; - background: var(--active); - cursor: pointer; - -webkit-appearance: none; - margin-top: -14px; -} - -input[type="range"]:focus::-webkit-slider-runnable-track { - background: var(--bg-main); -} - -input[type="range"]::-moz-range-track { - width: 100%; - height: 8.4px; - cursor: pointer; - border-color: var(--dark-grey), var(--light-grey); - background: var(--bg-main); - border-radius: 1.3px; - border: 0.2px inset var(--dark-grey); -} - -input[type="range"]::-moz-range-thumb { - border-color: var(--active); - border: 1px solid var(--dark-grey); - height: 36px; - width: 16px; - border-radius: 3px; - background: var(--active); - cursor: pointer; -} - -::placeholder { - color: var(--text); - opacity: 0.7; -} - -*:focus { - outline: var(--active) solid 2px; -} - -@media (prefers-color-scheme: light) { - body { - --text: #000; - --text-secondary: #fff; - --bg-main: #e3e7ea; - --bg-secondary: #fff; - } - - body.dark-theme { - --text: #fff; - --text-secondary: #000; - --bg-main: #3c4043; - --bg-secondary: #292a2d; - } - - .popup { - background-color: var(--bg-secondary); - } -} - -#volume-value { - float: right; -} - -.subheading { - padding: 0 10px; -} - -.subheading h1 { - color: var(--active); -} - -.subheading hr { - height: 1px; - background-color: var(--active); - border: none; -} diff --git a/src/assets/images/Screen Shot Chrome 1.png b/src/assets/images/Screen Shot Chrome 1.png new file mode 100644 index 00000000..1628b509 Binary files /dev/null and b/src/assets/images/Screen Shot Chrome 1.png differ diff --git a/src/assets/images/Screen Shot Chrome 2.png b/src/assets/images/Screen Shot Chrome 2.png new file mode 100644 index 00000000..61eed643 Binary files /dev/null and b/src/assets/images/Screen Shot Chrome 2.png differ diff --git a/src/assets/images/Screen Shot Chrome 3.png b/src/assets/images/Screen Shot Chrome 3.png new file mode 100644 index 00000000..42c92014 Binary files /dev/null and b/src/assets/images/Screen Shot Chrome 3.png differ diff --git a/src/assets/images/Screen Shot Chrome 4.png b/src/assets/images/Screen Shot Chrome 4.png new file mode 100644 index 00000000..8bae0410 Binary files /dev/null and b/src/assets/images/Screen Shot Chrome 4.png differ diff --git a/src/assets/images/Screen Shot Chrome 5.png b/src/assets/images/Screen Shot Chrome 5.png new file mode 100644 index 00000000..d3f54841 Binary files /dev/null and b/src/assets/images/Screen Shot Chrome 5.png differ diff --git a/src/assets/images/Screen Shot FF 1.png b/src/assets/images/Screen Shot FF 1.png new file mode 100644 index 00000000..7ae2e614 Binary files /dev/null and b/src/assets/images/Screen Shot FF 1.png differ diff --git a/src/assets/images/Screen Shot FF 2.png b/src/assets/images/Screen Shot FF 2.png new file mode 100644 index 00000000..a995478a Binary files /dev/null and b/src/assets/images/Screen Shot FF 2.png differ diff --git a/src/assets/images/Screen Shot FF 3.png b/src/assets/images/Screen Shot FF 3.png new file mode 100644 index 00000000..fc3232b6 Binary files /dev/null and b/src/assets/images/Screen Shot FF 3.png differ diff --git a/src/assets/images/Screen Shot FF 4.png b/src/assets/images/Screen Shot FF 4.png new file mode 100644 index 00000000..f230fed2 Binary files /dev/null and b/src/assets/images/Screen Shot FF 4.png differ diff --git a/src/assets/images/Screen Shot FF 5.png b/src/assets/images/Screen Shot FF 5.png new file mode 100644 index 00000000..420838d9 Binary files /dev/null and b/src/assets/images/Screen Shot FF 5.png differ diff --git a/src/assets/images/badge-amo.png b/src/assets/images/badge-amo.png new file mode 100644 index 00000000..9dbb7e46 Binary files /dev/null and b/src/assets/images/badge-amo.png differ diff --git a/src/assets/images/badge-chrome.png b/src/assets/images/badge-chrome.png new file mode 100644 index 00000000..afd2c6b2 Binary files /dev/null and b/src/assets/images/badge-chrome.png differ diff --git a/src/assets/images/badge-ms.png b/src/assets/images/badge-ms.png new file mode 100644 index 00000000..1b1dcbc9 Binary files /dev/null and b/src/assets/images/badge-ms.png differ diff --git a/src/assets/images/buy-me-a-coffee.png b/src/assets/images/buy-me-a-coffee.png new file mode 100644 index 00000000..8d9ea893 Binary files /dev/null and b/src/assets/images/buy-me-a-coffee.png differ diff --git a/src/assets/images/chevron-down.svg b/src/assets/images/chevron-down.svg new file mode 100644 index 00000000..7679f267 --- /dev/null +++ b/src/assets/images/chevron-down.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/src/assets/images/icon128.png b/src/assets/images/icon128.png new file mode 100644 index 00000000..cd16befd Binary files /dev/null and b/src/assets/images/icon128.png differ diff --git a/src/assets/images/icon16.png b/src/assets/images/icon16.png new file mode 100644 index 00000000..f896608b Binary files /dev/null and b/src/assets/images/icon16.png differ diff --git a/src/assets/images/icon32.png b/src/assets/images/icon32.png new file mode 100644 index 00000000..c5b417cf Binary files /dev/null and b/src/assets/images/icon32.png differ diff --git a/src/assets/images/icon48.png b/src/assets/images/icon48.png new file mode 100644 index 00000000..24dd5af7 Binary files /dev/null and b/src/assets/images/icon48.png differ diff --git a/src/assets/images/logo-small.png b/src/assets/images/logo-small.png new file mode 100644 index 00000000..27ca660a Binary files /dev/null and b/src/assets/images/logo-small.png differ diff --git a/src/assets/images/logo-store.png b/src/assets/images/logo-store.png new file mode 100644 index 00000000..f321de43 Binary files /dev/null and b/src/assets/images/logo-store.png differ diff --git a/src/assets/images/logo-tile.png b/src/assets/images/logo-tile.png new file mode 100644 index 00000000..101c6b3a Binary files /dev/null and b/src/assets/images/logo-tile.png differ diff --git a/src/assets/images/logo.png b/src/assets/images/logo.png new file mode 100644 index 00000000..ad854aaa Binary files /dev/null and b/src/assets/images/logo.png differ diff --git a/src/assets/javascripts/helpers/common.js b/src/assets/javascripts/helpers/common.js new file mode 100644 index 00000000..6edd3d3c --- /dev/null +++ b/src/assets/javascripts/helpers/common.js @@ -0,0 +1,9 @@ +export default class { + static filterInstances(instances) { + return instances.filter((instance) => !instance.includes(".onion")); + } + + static getRandomInstance(instances) { + return instances[~~(instances.length * Math.random())]; + } +} diff --git a/src/assets/javascripts/helpers/google-maps.js b/src/assets/javascripts/helpers/google-maps.js new file mode 100644 index 00000000..3a041c67 --- /dev/null +++ b/src/assets/javascripts/helpers/google-maps.js @@ -0,0 +1,43 @@ +export default class { + static targets = /https?:\/\/(((www|maps)\.)?(google\.).*(\/maps)|maps\.(google\.).*)/; + static redirects = ["https://openstreetmap.org"]; + static mapCentreRegex = /@(-?\d[0-9.]*),(-?\d[0-9.]*),(\d{1,2})[.z]/; + static dataLatLngRegex = /(!3d|!4d)(-?[0-9]{1,10}.[0-9]{1,10})/g; + static placeRegex = /\/place\/(.*)\//; + static travelModes = { + driving: "fossgis_osrm_car", + walking: "fossgis_osrm_foot", + bicycling: "fossgis_osrm_bike", + transit: "fossgis_osrm_car", // not implemented on OSM, default to car. + }; + static layers = { + none: "S", + transit: "T", + traffic: "S", // not implemented on OSM, default to standard. + bicycling: "C", + }; + static addressToLatLng(address, callback) { + const xmlhttp = new XMLHttpRequest(); + xmlhttp.onreadystatechange = () => { + if (xmlhttp.readyState === XMLHttpRequest.DONE) { + if (xmlhttp.status === 200) { + const json = JSON.parse(xmlhttp.responseText)[0]; + if (json) { + callback( + `${json.lat}%2C${json.lon}`, + `${json.boundingbox[2]},${json.boundingbox[1]},${json.boundingbox[3]},${json.boundingbox[0]}` + ); + } + } else { + console.info("Error: Status is " + xmlhttp.status); + } + } + }; + xmlhttp.open( + "GET", + `https://nominatim.openstreetmap.org/search/${address}?format=json&limit=1`, + false + ); + xmlhttp.send(); + } +} diff --git a/src/assets/javascripts/helpers/google-search.js b/src/assets/javascripts/helpers/google-search.js new file mode 100644 index 00000000..dc12042f --- /dev/null +++ b/src/assets/javascripts/helpers/google-search.js @@ -0,0 +1,9 @@ +export default class { + static targets = /https?:\/\/(((www|maps)\.)?(google\.).*(\/search)|search\.(google\.).*)/; + static redirects = [ + { link: "https://duckduckgo.com", q: "/" }, + { link: "https://startpage.com", q: "/search/" }, + { link: "https://www.qwant.com", q: "/" }, + { link: "https://www.mojeek.com", q: "/search" }, + ]; +} diff --git a/src/assets/javascripts/helpers/instagram.js b/src/assets/javascripts/helpers/instagram.js new file mode 100644 index 00000000..bd0ad9f5 --- /dev/null +++ b/src/assets/javascripts/helpers/instagram.js @@ -0,0 +1,47 @@ +export default class { + static targets = [ + "instagram.com", + "www.instagram.com", + "help.instagram.com", + "about.instagram.com", + ]; + static redirects = [ + "https://bibliogram.art", + "https://bibliogram.snopyta.org", + "https://bibliogram.pussthecat.org", + "https://bibliogram.nixnet.services", + "https://bg.endl.site", + "https://bibliogram.13ad.de", + "https://bibliogram.pixelfed.uno", + "https://bibliogram.ethibox.fr", + "https://bibliogram.hamster.dance", + "https://bibliogram.kavin.rocks", + "https://bibliogram.ggc-project.de", + ]; + static reservedPaths = [ + "about", + "explore", + "support", + "press", + "api", + "privacy", + "safety", + "admin", + "graphql", + "accounts", + "help", + "terms", + "contact", + "blog", + "igtv", + "u", + "p", + "fragment", + "imageproxy", + "videoproxy", + ".well-known", + "tv", + "reel", + ]; + static bypassPaths = /\/(accounts\/|embeds?.js)/; +} diff --git a/src/assets/javascripts/helpers/reddit.js b/src/assets/javascripts/helpers/reddit.js new file mode 100644 index 00000000..46fff4cf --- /dev/null +++ b/src/assets/javascripts/helpers/reddit.js @@ -0,0 +1,24 @@ +export default class { + static targets = [ + "www.reddit.com", + "np.reddit.com", + "new.reddit.com", + "amp.reddit.com", + ]; + static redirects = [ + "https://old.reddit.com", // desktop + "https://i.reddit.com", // mobile + // teddit: privacy w/ old UI + "https://teddit.net", + "https://teddit.ggc-project.de", + "https://teddit.kavin.rocks", + "https://snew.notabug.io", // anti-censorship + // libreddit: privacy w/ modern UI + "https://libredd.it", + "https://libreddit.spike.codes", + "https://libreddit.kavin.rocks", + "https://libreddit.insanity.wtf", + "https://libreddit.dothq.co", + ]; + static bypassPaths = /\/(gallery\/poll\/rpan\/settings\/topics)/; +} diff --git a/src/assets/javascripts/helpers/twitter.js b/src/assets/javascripts/helpers/twitter.js new file mode 100644 index 00000000..1ebc025b --- /dev/null +++ b/src/assets/javascripts/helpers/twitter.js @@ -0,0 +1,38 @@ +export default class { + /* + Please remember to also update the manifest.json file + (content_scripts > matches, 'remove-twitter-sw.js') + when updating this list: + */ + static targets = [ + "twitter.com", + "www.twitter.com", + "mobile.twitter.com", + "pbs.twimg.com", + "video.twimg.com", + ]; + static redirects = [ + "https://nitter.net", + "https://nitter.snopyta.org", + "https://nitter.42l.fr", + "https://nitter.nixnet.services", + "https://nitter.13ad.de", + "https://nitter.pussthecat.org", + "https://nitter.mastodont.cat", + "https://nitter.dark.fail", + "https://nitter.tedomum.net", + "https://nitter.cattube.org", + "https://nitter.fdn.fr", + "https://nitter.1d4.us", + "https://nitter.kavin.rocks", + "https://tweet.lambda.dance", + "https://nitter.cc", + "https://nitter.weaponizedhumiliation.com", + "https://nitter.vxempire.xyz", + "https://nitter.unixfox.eu", + "http://3nzoldnxplag42gqjs23xvghtzf6t6yzssrtytnntc6ppc7xxuoneoad.onion", + "http://nitter.l4qlywnpwqsluw65ts7md3khrivpirse744un3x7mlskqauz5pyuzgqd.onion", + "http://nitterlgj3n5fgwesu3vxc5h67ruku33nqaoeoocae2mvlzhsu6k7fqd.onion", + "http://npf37k3mtzwxreiw52ccs5ay4e6qt2fkcs2ndieurdyn2cuzzsfyfvid.onion", + ]; +} diff --git a/src/assets/javascripts/helpers/youtube.js b/src/assets/javascripts/helpers/youtube.js new file mode 100644 index 00000000..3d1fcd27 --- /dev/null +++ b/src/assets/javascripts/helpers/youtube.js @@ -0,0 +1,33 @@ +export default class { + static targets = [ + "m.youtube.com", + "youtube.com", + "img.youtube.com", + "www.youtube.com", + "youtube-nocookie.com", + "www.youtube-nocookie.com", + "youtu.be", + "s.ytimg.com", + "music.youtube.com", + ]; + /* + Please remember to also update the manifest.json file + (content_scripts > matches, 'persist-invidious-prefs.js') + when updating this list: + */ + static redirects = [ + "https://invidious.snopyta.org", + "https://invidious.xyz", + "https://invidious.kavin.rocks", + "https://tube.connect.cafe", + "https://invidious.zapashcanon.fr", + "https://invidiou.site", + "https://vid.mint.lgbt", + "https://invidious.site", + "https://yewtu.be", + "http://fz253lmuao3strwbfbmx46yu7acac2jz27iwtorgmbqlkurlclmancad.onion", + "http://qklhadlycap4cnod.onion", + "http://c7hqkpkpemu6e7emz5b4vyz7idjgdvgaaa3dyimmeojqbgpea3xqjoid.onion", + "http://w6ijuptxiku4xpnnaetxvnkc5vqcdu7mgns2u77qefoixi63vbvnpnqd.onion", + ]; +} diff --git a/src/assets/javascripts/localise.js b/src/assets/javascripts/localise.js new file mode 100644 index 00000000..cbe5c191 --- /dev/null +++ b/src/assets/javascripts/localise.js @@ -0,0 +1,19 @@ +window.browser = window.browser || window.chrome; + +function localisePage() { + var data = document.querySelectorAll("[data-localise]"); + + for (var i in data) + if (data.hasOwnProperty(i)) { + var obj = data[i]; + var tag = obj.getAttribute("data-localise").toString(); + + var msg = tag.replace(/__MSG_(\w+)__/g, function (_match, v1) { + return v1 ? browser.i18n.getMessage(v1) : null; + }); + + if (msg && msg !== tag) obj.textContent = msg; + } +} + +localisePage(); diff --git a/src/assets/javascripts/persist-invidious-prefs.js b/src/assets/javascripts/persist-invidious-prefs.js new file mode 100644 index 00000000..4c13a310 --- /dev/null +++ b/src/assets/javascripts/persist-invidious-prefs.js @@ -0,0 +1,30 @@ +'use strict'; + +window.browser = window.browser || window.chrome; + +function getCookie() { + let ca = document.cookie.split(';'); + for (let i = 0; i < ca.length; i++) { + let c = ca[i]; + while (c.charAt(0) == ' ') c = c.substring(1, c.length); + if (c.indexOf('PREFS=') == 0) { + return JSON.parse( + decodeURIComponent(c.substring('PREFS='.length, c.length)) + ) + }; + } + return {}; +} + +browser.storage.sync.get( + ['alwaysProxy', 'videoQuality', 'invidiousDarkMode', 'persistInvidiousPrefs'], + (result) => { + if (result.persistInvidiousPrefs) { + const prefs = getCookie(); + prefs.local = result.alwaysProxy; + prefs.quality = result.videoQuality; + prefs.dark_mode = result.invidiousDarkMode; + document.cookie = `PREFS=${encodeURIComponent(JSON.stringify(prefs))}`; + } + } +); \ No newline at end of file diff --git a/src/assets/javascripts/remove-twitter-sw.js b/src/assets/javascripts/remove-twitter-sw.js new file mode 100644 index 00000000..c39b4c9e --- /dev/null +++ b/src/assets/javascripts/remove-twitter-sw.js @@ -0,0 +1,89 @@ +"use strict"; + +let disableNitter; +let nitterInstance; +let redirectBypassFlag; +let exceptions; + +window.browser = window.browser || window.chrome; + +Promise.all([ + import(browser.extension.getURL("src/assets/javascripts/helpers/common.js")), + import(browser.extension.getURL("src/assets/javascripts/helpers/twitter.js")), +]).then( + (helpers) => { + let commonHelper; + let twitterHelper; + [commonHelper, twitterHelper] = helpers; + + function isNotException(url) { + return !exceptions.some((regex) => regex.test(url.href)); + } + + function shouldRedirect(url) { + return ( + !redirectBypassFlag && + isNotException(url) && + !disableNitter && + url.host !== nitterInstance && + !url.pathname.includes("/home") + ); + } + + function redirectTwitter(url) { + if (url.host.split(".")[0] === "pbs") { + return `${nitterInstance}/pic/${encodeURIComponent(url.href)}`; + } else if (url.host.split(".")[0] === "video") { + return `${nitterInstance}/gif/${encodeURIComponent(url.href)}`; + } else { + return `${nitterInstance}${url.pathname}${url.search}`; + } + } + + browser.storage.sync.get( + [ + "nitterInstance", + "disableNitter", + "removeTwitterSW", + "redirectBypassFlag", + "exceptions", + ], + (result) => { + redirectBypassFlag = result.redirectBypassFlag; + browser.storage.sync.set({ + redirectBypassFlag: false, + }); + if (!result.removeTwitterSW) { + disableNitter = result.disableNitter; + nitterInstance = + result.nitterInstance || + commonHelper.default.getRandomInstance( + twitterHelper.default.redirects + ); + exceptions = result.exceptions + ? result.exceptions.map((e) => { + return new RegExp(e); + }) + : []; + navigator.serviceWorker.getRegistrations().then((registrations) => { + for (let registration of registrations) { + if (registration.scope === "https://twitter.com/") { + registration.unregister(); + console.log("Unregistered Twitter SW", registration); + } + } + }); + const url = new URL(window.location); + if (shouldRedirect(url)) { + const redirect = redirectTwitter(url); + console.info("Redirecting", `"${url.href}"`, "=>", `"${redirect}"`); + window.location = redirect; + } + } + } + ); + }, + (error) => { + console.error(error); + } +); diff --git a/src/assets/stylesheets/styles.css b/src/assets/stylesheets/styles.css new file mode 100644 index 00000000..e11f313b --- /dev/null +++ b/src/assets/stylesheets/styles.css @@ -0,0 +1,516 @@ +body { + --text: #fff; + --bg-main: #3c4043; + --bg-secondary: #292a2d; + --active: #ff5b56; + --space: 5px; + --danger: #f04141; + --danger-light: #f9d0d5; + --dark-grey: #767676; + --light-grey: #c3c3c3; +} + +body.light-theme { + --text: #000; + --bg-main: #e3e7ea; + --bg-secondary: #fff; +} + +.light-theme.popup, +.light-theme .popup { + background-color: var(--bg-secondary); +} + +body { + margin: 0; + width: 400px; + margin: auto; + min-height: 572px; + font-family: Sans-Serif; + background-color: var(--bg-secondary); + color: var(--text); +} + +.popup { + width: 300px; + min-height: auto; + overflow: hidden; + background-color: var(--bg-main); +} + +input { + appearance: none; + -moz-appearance: none; + -webkit-appearance: none; +} + +header { + background-color: var(--bg-main); + color: var(--text); + display: flex; + padding: var(--space); +} + +header .logo-container { + width: 100%; + margin: var(--space) 0 var(--space) 0; + display: flex; + align-items: center; +} + +header .logo-container img { + height: 85px; + float: left; +} + +header .logo-container h1 { + font-size: 25px; + float: left; + margin-left: 15px; + text-transform: uppercase; + font-weight: normal; +} + +header .privacy { + letter-spacing: 0.13em; +} + +header .version { + font-size: 8.5px; + font-weight: bold; + position: absolute; + top: var(--space); + right: var(--space); +} + +h1 { + font-size: 14px; + margin: 7px auto; +} + +i { + font-size: 12px; +} + +h2 { + clear: both; + font-size: 12px; + font-weight: normal; + margin: 0; +} + +h3 { + font-size: 16px; +} + +h1, +h2 { + color: var(--text); +} + +footer { + width: 100%; +} + +footer a.button { + margin: var(--space); +} + +input[type="url"], +input[type="text"], +select { + width: 100%; + box-sizing: border-box; + margin-bottom: var(--space); + background-color: var(--bg-main); + border-style: inset; + color: var(--text); +} + +input[type="url"] { + padding: 1px 2px; +} + +input[type="checkbox"] { + opacity: 0; +} + +input[type="radio"] { + appearance: radio; + -moz-appearance: radio; + -webkit-appearance: radio; +} + +input[type="radio"]:checked + label { + background: transparent; +} + +.checkbox-label { + margin-left: 5px; + background: grey; + border-radius: 25px; + color: var(--text); + cursor: pointer; + display: block; + float: right; + font-weight: bold; + height: 30px; + position: relative; + text-indent: -400px; + width: 50px; +} + +.checkbox-label:after { + background: white; + border-radius: 90px; + content: ""; + height: 20px; + left: var(--space); + position: absolute; + top: var(--space); + transition: 0.3s; + width: 20px; +} + +input:checked + label { + background: var(--active); +} + +input:checked + label:after { + left: calc(100% - var(--space)); + transform: translateX(-100%); +} + +.settings-block { + display: block; + padding: 5px 10px 5px 10px; +} + +.settings-block h1 { + float: left; +} + +.button { + border: var(--active) solid 1px; + color: var(--text); + stroke: var(--text); + display: block; + font-size: 12px; + font-weight: bold; + margin: var(--space) auto; + padding: 10px; + text-align: center; + text-decoration: none; + cursor: pointer; + -webkit-transition-duration: 0.4s; + transition-duration: 0.4s; +} + +.button * { + vertical-align: middle; +} + +.button:hover { + background-color: var(--active); + color: var(--text); + stroke: var(--text); +} + +.button:active { + background-color: var(--active); + box-shadow: 0 var(--space) var(--bg-main); + transform: translateY(4px); +} + +input:invalid { + color: var(--danger); + border-color: var(--danger); + background-color: var(--danger-light); +} + +.margin-bottom { + margin-bottom: 20px; +} + +.tab { + overflow: hidden; + background-color: var(--bg-secondary); + position: fixed; + top: 0; + width: 400px; + z-index: 2; +} + +.tab button { + border-top-left-radius: 10px; + border-top-right-radius: 10px; + color: var(--text); + background-color: inherit; + float: left; + border: none; + outline: none; + cursor: pointer; + padding: 14px 16px; + transition: 0.3s; + border: solid 1px var(--bg-main); + width: 33.333%; + font-size: 14px; +} + +.tab button:hover { + background-color: var(--active); +} + +.tab button.active { + background-color: var(--bg-main); +} + +.tabcontent { + padding-top: 50px; + display: none; + background-color: var(--bg-main); + min-height: 510px; +} + +div.exceptions { + clear: left; +} + +div.exceptions > input { + width: 240px; + float: left; +} + +#add-to-exceptions { + float: right; + border: var(--active) solid 1px; + background-color: var(--active); + color: var(--text); + font-weight: bold; + cursor: pointer; + border-radius: 50%; + padding: 1px 1px 0px 1px; + margin-right: 5px; +} + +#add-to-exceptions svg { + height: 20px; + width: 20px; +} + +ul { + padding: 0; + list-style-type: none; + color: var(--text); + margin: 20px 20px 0 20px; +} + +li { + border-bottom: solid 0.5px var(--bg-secondary); + padding: 20px 0px 20px 20px; +} + +#exceptions-items button { + float: right; + margin-right: -5px; + border: var(--active) solid 1px; + background-color: var(--active); + color: var(--text); + font-weight: bold; + cursor: pointer; + border-radius: 50%; + padding: 2px 2px 0px 2px; +} + +.button svg { + height: 18px; + width: 18px; +} + +.autocomplete { + position: relative; + display: inline-block; + width: 100%; +} + +.autocomplete input { + background: url(../images/chevron-down.svg) right no-repeat; +} + +.autocomplete-items { + position: absolute; + border: 1px solid var(--bg-main); + border-bottom: none; + border-top: none; + z-index: 99; + top: 85%; + left: 0; + right: 0; + overflow-y: auto; + max-height: 175px; + color: var(--text); + overflow-x: hidden; + max-width: 380px; +} + +.autocomplete-items div { + padding: 10px; + cursor: pointer; + background-color: var(--bg-secondary); + border-bottom: 1px solid var(--bg-main); +} + +.autocomplete-items div:hover { + background-color: var(--active); +} + +.autocomplete-active { + background-color: var(--active); + color: var(--text); +} + +.option { + width: 100%; +} + +.option td { + vertical-align: middle; +} + +input[type="range"] { + -webkit-appearance: none; + margin: 18px 0; + width: 100%; +} + +input[type="range"]:focus { + outline: none; +} + +input[type="range"]::-webkit-slider-runnable-track { + width: 100%; + height: 8.4px; + cursor: pointer; + border-color: var(--dark-grey), var(--light-grey); + background: var(--bg-main); + border-radius: 1.3px; + border: 0.2px inset var(--dark-grey); +} + +input[type="range"]::-webkit-slider-thumb { + border-color: var(--active); + border: 1px solid var(--dark-grey); + height: 36px; + width: 16px; + border-radius: 3px; + background: var(--active); + cursor: pointer; + -webkit-appearance: none; + margin-top: -14px; +} + +input[type="range"]:focus::-webkit-slider-runnable-track { + background: var(--bg-main); +} + +input[type="range"]::-moz-range-track { + width: 100%; + height: 8.4px; + cursor: pointer; + border-color: var(--dark-grey), var(--light-grey); + background: var(--bg-main); + border-radius: 1.3px; + border: 0.2px inset var(--dark-grey); +} + +input[type="range"]::-moz-range-thumb { + border-color: var(--active); + border: 1px solid var(--dark-grey); + height: 36px; + width: 16px; + border-radius: 3px; + background: var(--active); + cursor: pointer; +} + +::placeholder { + color: var(--text); + opacity: 0.7; +} + +*:focus { + outline: var(--active) solid 2px; +} + +@media (prefers-color-scheme: light) { + body { + --text: #000; + --text-secondary: #fff; + --bg-main: #e3e7ea; + --bg-secondary: #fff; + } + + body.dark-theme { + --text: #fff; + --text-secondary: #000; + --bg-main: #3c4043; + --bg-secondary: #292a2d; + } + + .popup { + background-color: var(--bg-secondary); + } +} + +#volume-value { + float: right; +} + +.collapsible { + background-color: var(--bg-main); + cursor: pointer; + color: var(--active); + padding: 18px; + width: 100%; + border: none; + text-align: left; + outline: none; + font-size: 15px; + border-bottom: solid var(--active); + font-weight: bold; +} + +.collapsible:after { + content: "\002B"; + color: var(--active); + font-weight: bold; + float: right; + margin-left: 5px; +} + +.collapsible-active, +.collapsible:hover, +.collapsible:hover::after { + background-color: var(--active); + color: var(--text-secondary); +} + +.collapsible-active:after { + content: "\002D"; + color: var(--text-secondary); + font-weight: bold; + float: right; + margin-left: 5px; +} + +.collapsible-content { + padding: 0 18px; + display: none; + overflow: hidden; +} + +hr { + height: 2px; + background-color: var(--active); + border: none; +} diff --git a/src/pages/background/background.html b/src/pages/background/background.html new file mode 100644 index 00000000..2d0fb686 --- /dev/null +++ b/src/pages/background/background.html @@ -0,0 +1 @@ + diff --git a/src/pages/background/background.js b/src/pages/background/background.js new file mode 100644 index 00000000..d5a19662 --- /dev/null +++ b/src/pages/background/background.js @@ -0,0 +1,549 @@ +"use strict"; + +import commonHelper from "../../assets/javascripts/helpers/common.js"; +import twitterHelper from "../../assets/javascripts/helpers/twitter.js"; +import youtubeHelper from "../../assets/javascripts/helpers/youtube.js"; +import instagramHelper from "../../assets/javascripts/helpers/instagram.js"; +import mapsHelper from "../../assets/javascripts/helpers/google-maps.js"; +import redditHelper from "../../assets/javascripts/helpers/reddit.js"; +import searchHelper from "../../assets/javascripts/helpers/google-search.js"; + +const nitterInstances = twitterHelper.redirects; +const twitterDomains = twitterHelper.targets; +const youtubeDomains = youtubeHelper.targets; +const invidiousInstances = youtubeHelper.redirects; +const instagramDomains = instagramHelper.targets; +const bibliogramInstances = instagramHelper.redirects; +const instagramReservedPaths = instagramHelper.reservedPaths; +const bibliogramBypassPaths = instagramHelper.bypassPaths; +const osmDefault = mapsHelper.redirects[0]; +const googleMapsRegex = mapsHelper.targets; +const mapCentreRegex = mapsHelper.mapCentreRegex; +const dataLatLngRegex = mapsHelper.dataLatLngRegex; +const placeRegex = mapsHelper.placeRegex; +const travelModes = mapsHelper.travelModes; +const layers = mapsHelper.layers; +const redditInstances = redditHelper.redirects; +const redditDomains = redditHelper.targets; +const redditBypassPaths = redditHelper.bypassPaths; +const redditDefault = redditHelper.redirects[0]; +const googleSearchRegex = searchHelper.targets; +const searchEngineInstances = searchHelper.redirects; + +let disableNitter; +let disableInvidious; +let disableBibliogram; +let disableOsm; +let disableReddit; +let disableSearchEngine; +let nitterInstance; +let invidiousInstance; +let bibliogramInstance; +let osmInstance; +let redditInstance; +let searchEngineInstance; +let alwaysProxy; +let onlyEmbeddedVideo; +let videoQuality; +let invidiousDarkMode; +let invidiousVolume; +let invidiousPlayerStyle; +let invidiousSubtitles; +let invidiousAutoplay; +let useFreeTube; +let nitterRandomPool; +let invidiousRandomPool; +let bibliogramRandomPool; +let exceptions; + +window.browser = window.browser || window.chrome; + +browser.storage.sync.get( + [ + "nitterInstance", + "invidiousInstance", + "bibliogramInstance", + "osmInstance", + "redditInstance", + "searchEngineInstance", + "disableNitter", + "disableInvidious", + "disableBibliogram", + "disableOsm", + "disableReddit", + "disableSearchEngine", + "alwaysProxy", + "onlyEmbeddedVideo", + "videoQuality", + "invidiousDarkMode", + "invidiousVolume", + "invidiousPlayerStyle", + "invidiousSubtitles", + "invidiousAutoplay", + "useFreeTube", + "nitterRandomPool", + "invidiousRandomPool", + "bibliogramRandomPool", + "exceptions", + ], + (result) => { + nitterInstance = result.nitterInstance; + invidiousInstance = result.invidiousInstance; + bibliogramInstance = result.bibliogramInstance; + osmInstance = result.osmInstance || osmDefault; + redditInstance = result.redditInstance || redditDefault; + searchEngineInstance = result.searchEngineInstance; + disableNitter = result.disableNitter; + disableInvidious = result.disableInvidious; + disableBibliogram = result.disableBibliogram; + disableOsm = result.disableOsm; + disableReddit = result.disableReddit; + disableSearchEngine = result.disableSearchEngine; + alwaysProxy = result.alwaysProxy; + onlyEmbeddedVideo = result.onlyEmbeddedVideo; + videoQuality = result.videoQuality; + invidiousDarkMode = result.invidiousDarkMode; + exceptions = result.exceptions + ? result.exceptions.map((e) => { + return new RegExp(e); + }) + : []; + invidiousVolume = result.invidiousVolume; + invidiousPlayerStyle = result.invidiousPlayerStyle; + invidiousSubtitles = result.invidiousSubtitles || ""; + invidiousAutoplay = result.invidiousAutoplay; + useFreeTube = result.useFreeTube; + nitterRandomPool = result.nitterRandomPool + ? result.nitterRandomPool.split(",") + : commonHelper.filterInstances(nitterInstances); + invidiousRandomPool = result.invidiousRandomPool + ? result.invidiousRandomPool.split(",") + : commonHelper.filterInstances(invidiousInstances); + bibliogramRandomPool = result.bibliogramRandomPool + ? result.bibliogramRandomPool.split(",") + : commonHelper.filterInstances(bibliogramInstances); + } +); + +browser.storage.onChanged.addListener((changes) => { + if ("nitterInstance" in changes) { + nitterInstance = changes.nitterInstance.newValue; + } + if ("invidiousInstance" in changes) { + invidiousInstance = changes.invidiousInstance.newValue; + } + if ("bibliogramInstance" in changes) { + bibliogramInstance = changes.bibliogramInstance.newValue; + } + if ("osmInstance" in changes) { + osmInstance = changes.osmInstance.newValue || osmDefault; + } + if ("redditInstance" in changes) { + redditInstance = changes.redditInstance.newValue || redditDefault; + } + if ("searchEngineInstance" in changes) { + searchEngineInstance = changes.searchEngineInstance.newValue; + } + if ("disableNitter" in changes) { + disableNitter = changes.disableNitter.newValue; + } + if ("disableInvidious" in changes) { + disableInvidious = changes.disableInvidious.newValue; + } + if ("disableBibliogram" in changes) { + disableBibliogram = changes.disableBibliogram.newValue; + } + if ("disableOsm" in changes) { + disableOsm = changes.disableOsm.newValue; + } + if ("disableReddit" in changes) { + disableReddit = changes.disableReddit.newValue; + } + if ("disableSearchEngine" in changes) { + disableSearchEngine = changes.disableSearchEngine.newValue; + } + if ("alwaysProxy" in changes) { + alwaysProxy = changes.alwaysProxy.newValue; + } + if ("onlyEmbeddedVideo" in changes) { + onlyEmbeddedVideo = changes.onlyEmbeddedVideo.newValue; + } + if ("videoQuality" in changes) { + videoQuality = changes.videoQuality.newValue; + } + if ("invidiousDarkMode" in changes) { + invidiousDarkMode = changes.invidiousDarkMode.newValue; + } + if ("invidiousVolume" in changes) { + invidiousVolume = changes.invidiousVolume.newValue; + } + if ("invidiousPlayerStyle" in changes) { + invidiousPlayerStyle = changes.invidiousPlayerStyle.newValue; + } + if ("invidiousSubtitles" in changes) { + invidiousSubtitles = changes.invidiousSubtitles.newValue; + } + if ("invidiousAutoplay" in changes) { + invidiousAutoplay = changes.invidiousAutoplay.newValue; + } + if ("useFreeTube" in changes) { + useFreeTube = changes.useFreeTube.newValue; + } + if ("nitterRandomPool" in changes) { + nitterRandomPool = changes.nitterRandomPool.newValue.split(","); + } + if ("invidiousRandomPool" in changes) { + invidiousRandomPool = changes.invidiousRandomPool.newValue.split(","); + } + if ("bibliogramRandomPool" in changes) { + bibliogramRandomPool = changes.bibliogramRandomPool.newValue.split(","); + } + if ("exceptions" in changes) { + exceptions = changes.exceptions.newValue.map((e) => { + return new RegExp(e); + }); + } +}); + +function isException(url, initiator) { + return ( + exceptions.some((regex) => regex.test(url.href)) || + (initiator && exceptions.some((regex) => regex.test(initiator.href))) + ); +} + +function isFirefox() { + return typeof InstallTrigger !== "undefined"; +} + +function redirectYouTube(url, initiator, type) { + if (disableInvidious || isException(url, initiator)) { + return null; + } + if ( + initiator && + (initiator.origin === invidiousInstance || + invidiousInstances.includes(initiator.origin) || + youtubeDomains.includes(initiator.host)) + ) { + return null; + } + if (url.pathname.match(/iframe_api/) || url.pathname.match(/www-widgetapi/)) { + // Don't redirect YouTube Player API. + return null; + } + if (url.host.split(".")[0] === "studio") { + // Avoid redirecting `studio.youtube.com` + return null; + } + if (onlyEmbeddedVideo && type !== "sub_frame") { + return null; + } + if (useFreeTube && type === "main_frame") { + return `freetube://${url}`; + } + // Apply settings + if (alwaysProxy) { + url.searchParams.append("local", true); + } + if (videoQuality) { + url.searchParams.append("quality", videoQuality); + } + if (invidiousDarkMode) { + url.searchParams.append("dark_mode", invidiousDarkMode); + } + if (invidiousVolume) { + url.searchParams.append("volume", invidiousVolume); + } + if (invidiousPlayerStyle) { + url.searchParams.append("player_style", invidiousPlayerStyle); + } + if (invidiousSubtitles) { + url.searchParams.append("subtitles", invidiousSubtitles); + } + url.searchParams.append("autoplay", invidiousAutoplay ? 1 : 0); + + return `${ + invidiousInstance || commonHelper.getRandomInstance(invidiousRandomPool) + }${url.pathname.replace("/shorts", "")}${url.search}`; +} + +function redirectTwitter(url, initiator) { + if (disableNitter || isException(url, initiator)) { + return null; + } + if (url.pathname.includes("/home")) { + return null; + } + if ( + isFirefox() && + initiator && + (initiator.origin === nitterInstance || + nitterInstances.includes(initiator.origin) || + twitterDomains.includes(initiator.host)) + ) { + browser.storage.sync.set({ + redirectBypassFlag: true, + }); + return null; + } + if (url.host.split(".")[0] === "pbs") { + return `${ + nitterInstance || commonHelper.getRandomInstance(nitterRandomPool) + }/pic/${encodeURIComponent(url.href)}`; + } else if (url.host.split(".")[0] === "video") { + return `${ + nitterInstance || commonHelper.getRandomInstance(nitterRandomPool) + }/gif/${encodeURIComponent(url.href)}`; + } else if (url.pathname.includes("tweets")) { + return `${ + nitterInstance || commonHelper.getRandomInstance(nitterRandomPool) + }${url.pathname.replace("/tweets", "")}${url.search}`; + } else { + return `${ + nitterInstance || commonHelper.getRandomInstance(nitterRandomPool) + }${url.pathname}${url.search}`; + } +} + +function redirectInstagram(url, initiator, type) { + if (disableBibliogram || isException(url, initiator)) { + return null; + } + // Do not redirect Bibliogram view on Instagram links + if ( + initiator && + (initiator.origin === bibliogramInstance || + bibliogramInstances.includes(initiator.origin) || + instagramDomains.includes(initiator.host)) + ) { + return null; + } + // Do not redirect /accounts, /embeds.js, or anything other than main_frame + if (type !== "main_frame" || url.pathname.match(bibliogramBypassPaths)) { + return null; + } + if ( + url.pathname === "/" || + instagramReservedPaths.includes(url.pathname.split("/")[1]) + ) { + return `${ + bibliogramInstance || commonHelper.getRandomInstance(bibliogramRandomPool) + }${url.pathname}${url.search}`; + } else { + // Likely a user profile, redirect to '/u/...' + return `${ + bibliogramInstance || commonHelper.getRandomInstance(bibliogramRandomPool) + }/u${url.pathname}${url.search}`; + } +} + +function redirectGoogleMaps(url, initiator) { + if (disableOsm || isException(url, initiator)) { + return null; + } + let redirect; + let mapCentre = ""; + let params = ""; + // Set map centre if present + if (url.pathname.match(mapCentreRegex)) { + const [, lat, lon, zoom] = url.pathname.match(mapCentreRegex); + mapCentre = `#map=${zoom}/${lat}/${lon}`; + } else if (url.search.includes("center=")) { + const [lat, lon] = url.searchParams.get("center").split(","); + mapCentre = `#map=${url.searchParams.get("zoom") || "17"}/${lat}/${lon}`; + // Set default zoom if mapCentre not present + } else { + params = "&zoom=17"; + } + // Set map layer + params = `${params}&layers=${ + layers[url.searchParams.get("layer")] || layers["none"] + }`; + // Handle Google Maps Embed API + if (url.pathname.includes("/embed")) { + let query = ""; + if (url.searchParams.has("q")) { + query = url.searchParams.get("q"); + } else if (url.searchParams.has("query")) { + query = url.searchParams.has("query"); + } else if (url.searchParams.has("pb")) { + try { + query = url.searchParams.get("pb").split(/!2s(.*?)!/)[1]; + } catch (error) { + console.error(error); + // Unable to find map marker in URL. + } + } + let marker, bbox; + mapsHelper.addressToLatLng(query, (coords, boundingbox) => { + marker = coords; + bbox = boundingbox; + }); + redirect = `${osmInstance}/export/embed.html?bbox=${bbox}&layer=mapnik&marker=${marker}`; + // Handle Google Maps Directions + } else if (url.pathname.includes("/dir")) { + const travelMode = + travelModes[url.searchParams.get("travelmode")] || travelModes["driving"]; + let origin; + mapsHelper.addressToLatLng(url.searchParams.get("origin"), (coords) => { + origin = coords; + }); + let destination; + mapsHelper.addressToLatLng( + url.searchParams.get("destination"), + (coords) => { + destination = coords; + } + ); + redirect = `${osmInstance}/directions?engine=${travelMode}&route=${origin}%3B${destination}${mapCentre}${params}`; + // Get marker from data attribute + } else if ( + url.pathname.includes("data=") && + url.pathname.match(dataLatLngRegex) + ) { + const [mlat, mlon] = url.pathname.match(dataLatLngRegex); + redirect = `${osmInstance}/?mlat=${mlat.replace( + "!3d", + "" + )}&mlon=${mlon.replace("!4d", "")}${mapCentre}${params}`; + // Get marker from ll param + } else if (url.searchParams.has("ll")) { + const [mlat, mlon] = url.searchParams.get("ll").split(","); + redirect = `${osmInstance}/?mlat=${mlat}&mlon=${mlon}${mapCentre}${params}`; + // Get marker from viewpoint param. + } else if (url.searchParams.has("viewpoint")) { + const [mlat, mlon] = url.searchParams.get("viewpoint").split(","); + redirect = `${osmInstance}/?mlat=${mlat}&mlon=${mlon}${mapCentre}${params}`; + // Use query as search if present. + } else { + let query; + if (url.searchParams.has("q")) { + query = url.searchParams.get("q"); + } else if (url.searchParams.has("query")) { + query = url.searchParams.get("query"); + } else if (url.pathname.match(placeRegex)) { + query = url.pathname.match(placeRegex)[1]; + } + redirect = `${osmInstance}/${query ? "search?query=" + query : ""}${ + mapCentre || "#" + }${params}`; + } + + return redirect; +} + +function redirectReddit(url, initiator, type) { + if (disableReddit || isException(url, initiator)) { + return null; + } + // Do not redirect when already on the selected view + if ( + (initiator && initiator.origin === redditInstance) || + url.origin === redditInstance + ) { + return null; + } + // Do not redirect exclusions nor anything other than main_frame + if (type !== "main_frame" || url.pathname.match(redditBypassPaths)) { + return null; + } + return `${redditInstance}${url.pathname}${url.search}`; +} + +function redirectSearchEngine(url, initiator) { + if (disableSearchEngine || isException(url, initiator)) { + return null; + } + + const searchEngine = + searchEngineInstance || + commonHelper.getRandomInstance(searchEngineInstances); + let search = ""; + url.search + .slice(1) + .split("&") + .forEach(function (input) { + if (input.startsWith("q=")) search = input; + }); + return `${searchEngine.link}${searchEngine.q}?${search}`; +} + +browser.webRequest.onBeforeRequest.addListener( + (details) => { + const url = new URL(details.url); + let initiator; + if (details.originUrl) { + initiator = new URL(details.originUrl); + } else if (details.initiator) { + initiator = new URL(details.initiator); + } + let redirect; + if (youtubeDomains.includes(url.host)) { + redirect = { + redirectUrl: redirectYouTube(url, initiator, details.type), + }; + } else if (twitterDomains.includes(url.host)) { + redirect = { + redirectUrl: redirectTwitter(url, initiator), + }; + } else if (instagramDomains.includes(url.host)) { + redirect = { + redirectUrl: redirectInstagram(url, initiator, details.type), + }; + } else if (url.href.match(googleMapsRegex)) { + redirect = { + redirectUrl: redirectGoogleMaps(url, initiator), + }; + } else if ( + redditDomains.includes(url.host) || + redditInstances.includes(url.origin) + ) { + redirect = { + redirectUrl: redirectReddit(url, initiator, details.type), + }; + } else if (url.href.match(googleSearchRegex)) { + redirect = { + redirectUrl: redirectSearchEngine(url, initiator), + }; + } + if (redirect && redirect.redirectUrl) { + console.info( + "Redirecting", + `"${url.href}"`, + "=>", + `"${redirect.redirectUrl}"` + ); + console.info("Details", details); + } + return redirect; + }, + { + urls: [""], + }, + ["blocking"] +); + +browser.runtime.onInstalled.addListener((details) => { + if (details.reason === "update") { + browser.storage.sync.get( + ["whitelist", "exceptions", "invidiousInstance"], + (result) => { + if (result.whitelist) { + let whitelist = result.whitelist.map((e) => + e.replace(/[-\/\\^$*+?.()|[\]{}]/g, "\\$&") + ); + browser.storage.sync.set({ + exceptions: result.exceptions.concat(whitelist), + whitelist: null, + }); + } + if (result.invidiousInstance === "https://invidio.us") { + browser.storage.sync.set({ + invidiousInstance: null, + }); + } + } + ); + } +}); diff --git a/src/pages/options/options.html b/src/pages/options/options.html new file mode 100644 index 00000000..af7bd41a --- /dev/null +++ b/src/pages/options/options.html @@ -0,0 +1,585 @@ + + + + + + + + Privacy Redirect Options + + + +
    + + + +
    + +
    +
    + + + + + + + +
    +

    Nitter Redirects

    +
    +   + +
    +
    +
    + + + + + + + +
    +

    + Invidious Redirects +

    +
    +   + +
    +
    +
    + + + + + + + +
    +

    + Bibliogram Redirects +

    +
    +   + +
    +
    +
    + + + + + + + +
    +

    + OpenStreetMap Redirects +

    +
    +   + +
    +
    +
    + + + + + + + +
    +

    + Reddit Redirects +

    +
    +   + +
    +
    +
    + + + + + + + +
    +

    + Search Engine Redirects +

    +
    +   + +
    +
    +
    +

    Nitter Instance

    +
    + +
    +
    +
    +

    Invidious Instance

    +
    + +
    +
    +
    +

    Bibliogram Instance

    +
    + +
    +
    +
    +

    OpenStreetMap Instance

    +
    + +
    +
    +
    +

    Reddit Instance

    +
    + +
    +
    +
    +

    Search Engine Instance

    +
    + +
    +
    +
    +

    Theme

    + +
    +
    + +
    + +
    +
    +

    + Invidious random instance pool (comma-separated) +

    + +
    +
    + + + + + + + +
    +

    + Use FreeTube over Invidious when possible +

    +
    +   + +
    +
    +
    + + + + + + + +
    +

    + Always proxy videos through Invidious +

    +
    +   + +
    +
    +
    + + + + + + + +
    +

    + Only redirect embedded video to Invidious +

    +
    +   + +
    +
    +
    +

    Invidious Video Quality

    + +
    +
    + + + + + + + +
    +

    + Invidious dark mode always on +

    +
    +   + +
    +
    +
    +

    + Invidious Volume +

    + +
    +
    +

    + Invidious Player Style +

    + +
    +
    +

    + Invidious Subtitles - language codes (comma-separated) +

    + +
    +
    + + + + + + + +
    +

    + Invidious automatically play video on load +

    +
    +   + +
    +
    +
    + + + + + + + +
    +

    + Persist Invidious preferences (as cookie) +

    +
    +   + +
    +
    +
    +
    + +
    +
    +

    + Nitter random instance pool (comma-separated) +

    + +
    +
    + + + + + + + +
    +

    + Proactively remove Twitter service worker +

    +
    +   + +
    +
    +
    +
    + +
    +
    +

    + Bibliogram random instance pool (comma-separated) +

    + +
    +
    +
    +
    + +
    +
    +

    + Enter a URL or Regular Expression to be excluded from redirects. +

    +

    + All requests for or initiating from a URL that matches your exception + will be excluded from redirects. +

    +

    + Note - Supports JavaScript regular expressions, excluding the + enclosing forward slashes. +

    +
    +
    + + + + + + + + + + + +
    +

    Add Exception

    +
    + + + + + + + + +
    +
    +
      +
      + + + + + diff --git a/src/pages/options/options.js b/src/pages/options/options.js new file mode 100644 index 00000000..e6bd224a --- /dev/null +++ b/src/pages/options/options.js @@ -0,0 +1,522 @@ +"use strict"; + +import commonHelper from "../../assets/javascripts/helpers/common.js"; +import twitterHelper from "../../assets/javascripts/helpers/twitter.js"; +import youtubeHelper from "../../assets/javascripts/helpers/youtube.js"; +import instagramHelper from "../../assets/javascripts/helpers/instagram.js"; +import mapsHelper from "../../assets/javascripts/helpers/google-maps.js"; +import redditHelper from "../../assets/javascripts/helpers/reddit.js"; +import searchHelper from "../../assets/javascripts/helpers/google-search.js"; + +const nitterInstances = twitterHelper.redirects; +const invidiousInstances = youtubeHelper.redirects; +const bibliogramInstances = instagramHelper.redirects; +const osmInstances = mapsHelper.redirects; +const redditInstances = redditHelper.redirects; +const searchEngineInstances = searchHelper.redirects; +const autocompletes = [ + { id: "nitter-instance", instances: nitterInstances }, + { id: "invidious-instance", instances: invidiousInstances }, + { id: "bibliogram-instance", instances: bibliogramInstances }, + { id: "osm-instance", instances: osmInstances }, + { id: "reddit-instance", instances: redditInstances }, + { + id: "search-engine-instance", + instances: searchEngineInstances.map((instance) => instance.link), + }, +]; + +let nitterInstance = document.getElementById("nitter-instance"); +let invidiousInstance = document.getElementById("invidious-instance"); +let bibliogramInstance = document.getElementById("bibliogram-instance"); +let osmInstance = document.getElementById("osm-instance"); +let redditInstance = document.getElementById("reddit-instance"); +let searchEngineInstance = document.getElementById("search-engine-instance"); +let disableNitter = document.getElementById("disable-nitter"); +let disableInvidious = document.getElementById("disable-invidious"); +let disableBibliogram = document.getElementById("disable-bibliogram"); +let disableOsm = document.getElementById("disable-osm"); +let disableReddit = document.getElementById("disable-reddit"); +let disableSearchEngine = document.getElementById("disable-search-engine"); +let alwaysProxy = document.getElementById("always-proxy"); +let onlyEmbeddedVideo = document.getElementById("only-embed"); +let videoQuality = document.getElementById("video-quality"); +let removeTwitterSW = document.getElementById("remove-twitter-sw"); +let invidiousDarkMode = document.getElementById("invidious-dark-mode"); +let persistInvidiousPrefs = document.getElementById("persist-invidious-prefs"); +let invidiousVolume = document.getElementById("invidious-volume"); +let invidiousPlayerStyle = document.getElementById("invidious-player-style"); +let invidiousSubtitles = document.getElementById("invidious-subtitles"); +let invidiousAutoplay = document.getElementById("invidious-autoplay"); +let theme = document.getElementById("theme"); +let useFreeTube = document.getElementById("use-freetube"); +let nitterRandomPool = document.getElementById("nitter-random-pool"); +let invidiousRandomPool = document.getElementById("invidious-random-pool"); +let bibliogramRandomPool = document.getElementById("bibliogram-random-pool"); +let exceptions; + +window.browser = window.browser || window.chrome; + +function prependExceptionsItem(item, index) { + const li = document.createElement("li"); + li.appendChild(document.createTextNode(item.toString())); + const button = document.createElement("button"); + li.appendChild(button); + document.getElementById("exceptions-items").prepend(li); + const svg = ` + + + `; + button.innerHTML = svg; + button.addEventListener("click", () => { + exceptions.splice(index, 1); + browser.storage.sync.set({ + exceptions: exceptions, + }); + li.remove(); + }); +} + +browser.storage.sync.get( + [ + "nitterInstance", + "invidiousInstance", + "bibliogramInstance", + "osmInstance", + "redditInstance", + "searchEngineInstance", + "disableNitter", + "disableInvidious", + "disableBibliogram", + "disableOsm", + "disableReddit", + "disableSearchEngine", + "alwaysProxy", + "onlyEmbeddedVideo", + "videoQuality", + "removeTwitterSW", + "invidiousDarkMode", + "persistInvidiousPrefs", + "invidiousVolume", + "invidiousPlayerStyle", + "invidiousSubtitles", + "invidiousAutoplay", + "exceptions", + "theme", + "useFreeTube", + "nitterRandomPool", + "invidiousRandomPool", + "bibliogramRandomPool", + ], + (result) => { + theme.value = result.theme || ""; + if (result.theme) document.body.classList.add(result.theme); + nitterInstance.value = result.nitterInstance || ""; + invidiousInstance.value = result.invidiousInstance || ""; + bibliogramInstance.value = result.bibliogramInstance || ""; + osmInstance.value = result.osmInstance || ""; + redditInstance.value = result.redditInstance || ""; + searchEngineInstance.value = + (result.searchEngineInstance && result.searchEngineInstance.link) || ""; + disableNitter.checked = !result.disableNitter; + disableInvidious.checked = !result.disableInvidious; + disableBibliogram.checked = !result.disableBibliogram; + disableOsm.checked = !result.disableOsm; + disableReddit.checked = !result.disableReddit; + disableSearchEngine.checked = !result.disableSearchEngine; + alwaysProxy.checked = result.alwaysProxy; + onlyEmbeddedVideo.checked = result.onlyEmbeddedVideo; + videoQuality.value = result.videoQuality || ""; + removeTwitterSW.checked = !result.removeTwitterSW; + invidiousDarkMode.checked = result.invidiousDarkMode; + persistInvidiousPrefs.checked = result.persistInvidiousPrefs; + exceptions = result.exceptions || []; + exceptions.forEach(prependExceptionsItem); + invidiousVolume.value = result.invidiousVolume; + document.querySelector("#volume-value").textContent = result.invidiousVolume + ? `${result.invidiousVolume}%` + : " - "; + invidiousPlayerStyle.value = result.invidiousPlayerStyle || ""; + invidiousSubtitles.value = result.invidiousSubtitles || ""; + invidiousAutoplay.checked = result.invidiousAutoplay; + useFreeTube.checked = result.useFreeTube; + nitterRandomPool.value = + result.nitterRandomPool || commonHelper.filterInstances(nitterInstances); + invidiousRandomPool.value = + result.invidiousRandomPool || + commonHelper.filterInstances(invidiousInstances); + bibliogramRandomPool.value = + result.bibliogramRandomPool || + commonHelper.filterInstances(bibliogramInstances); + } +); + +function openTab(tab, event) { + let i, tabcontent, tablinks; + tabcontent = document.getElementsByClassName("tabcontent"); + for (i = 0; i < tabcontent.length; i++) { + tabcontent[i].style.display = "none"; + } + tablinks = document.getElementsByClassName("tablinks"); + for (i = 0; i < tablinks.length; i++) { + tablinks[i].className = tablinks[i].className.replace(" active", ""); + } + document.getElementById(tab).style.display = "block"; + event.currentTarget.className += " active"; +} + +document + .getElementById("general-tab") + .addEventListener("click", openTab.bind(null, "general")); +document + .getElementById("advanced-tab") + .addEventListener("click", openTab.bind(null, "advanced")); +document + .getElementById("exceptions-tab") + .addEventListener("click", openTab.bind(null, "exceptions")); + +document.getElementById("general-tab").click(); + +function addToExceptions() { + const input = document.getElementById("new-exceptions-item"); + const type = document.querySelector('input[name="type"]:checked').value; + if (input.value) { + try { + let value = input.value; + new RegExp(input.value); + if (type === "URL") { + value = value.replace(/[-\/\\^$*+?.()|[\]{}]/g, "\\$&"); + } + exceptions.push(value); + browser.storage.sync.set({ + exceptions: exceptions, + }); + prependExceptionsItem(value, exceptions.indexOf(value)); + input.value = ""; + } catch (error) { + input.setCustomValidity("Invalid RegExp"); + } + } else { + input.setCustomValidity("Invalid RegExp"); + } +} + +document + .getElementById("add-to-exceptions") + .addEventListener("click", addToExceptions); + +function debounce(func, wait, immediate) { + let timeout; + return () => { + let context = this, + args = arguments; + let later = () => { + timeout = null; + if (!immediate) func.apply(context, args); + }; + let callNow = immediate && !timeout; + clearTimeout(timeout); + timeout = setTimeout(later, wait); + if (callNow) func.apply(context, args); + }; +} + +function parseURL(urlString) { + if (urlString) { + try { + const url = new URL(urlString); + if (url.username && url.password) { + return `${url.protocol}//${url.username}:${url.password}@${url.host}`; + } else { + return url.origin; + } + } catch (error) { + console.log(error); + return ""; + } + } else { + return ""; + } +} + +const nitterInstanceChange = debounce(() => { + if (nitterInstance.checkValidity()) { + browser.storage.sync.set({ + nitterInstance: parseURL(nitterInstance.value), + }); + } +}, 500); +nitterInstance.addEventListener("input", nitterInstanceChange); + +const invidiousInstanceChange = debounce(() => { + if (invidiousInstance.checkValidity()) { + browser.storage.sync.set({ + invidiousInstance: parseURL(invidiousInstance.value), + }); + } +}, 500); +invidiousInstance.addEventListener("input", invidiousInstanceChange); + +const bibliogramInstanceChange = debounce(() => { + if (bibliogramInstance.checkValidity()) { + browser.storage.sync.set({ + bibliogramInstance: parseURL(bibliogramInstance.value), + }); + } +}, 500); +bibliogramInstance.addEventListener("input", bibliogramInstanceChange); + +const osmInstanceChange = debounce(() => { + if (osmInstance.checkValidity()) { + browser.storage.sync.set({ + osmInstance: parseURL(osmInstance.value), + }); + } +}, 500); +osmInstance.addEventListener("input", osmInstanceChange); + +const redditInstanceChange = debounce(() => { + if (redditInstance.checkValidity()) { + browser.storage.sync.set({ + redditInstance: parseURL(redditInstance.value), + }); + } +}, 500); +redditInstance.addEventListener("input", redditInstanceChange); + +const searchEngineInstanceChange = debounce(() => { + const instance = searchEngineInstances.find( + (instance) => instance.link === searchEngineInstance.value + ); + if (instance || !searchEngineInstance.value) { + browser.storage.sync.set({ + searchEngineInstance: instance || searchEngineInstance.value, + }); + } else { + searchEngineInstance.setCustomValidity("Must be an instance from the list"); + } +}, 500); +searchEngineInstance.addEventListener("input", searchEngineInstanceChange); + +disableNitter.addEventListener("change", (event) => { + browser.storage.sync.set({ disableNitter: !event.target.checked }); +}); + +disableInvidious.addEventListener("change", (event) => { + browser.storage.sync.set({ disableInvidious: !event.target.checked }); +}); + +disableBibliogram.addEventListener("change", (event) => { + browser.storage.sync.set({ disableBibliogram: !event.target.checked }); +}); + +disableOsm.addEventListener("change", (event) => { + browser.storage.sync.set({ disableOsm: !event.target.checked }); +}); + +disableReddit.addEventListener("change", (event) => { + browser.storage.sync.set({ disableReddit: !event.target.checked }); +}); + +disableSearchEngine.addEventListener("change", (event) => { + browser.storage.sync.set({ disableSearchEngine: !event.target.checked }); +}); + +alwaysProxy.addEventListener("change", (event) => { + browser.storage.sync.set({ alwaysProxy: event.target.checked }); +}); + +onlyEmbeddedVideo.addEventListener("change", (event) => { + browser.storage.sync.set({ onlyEmbeddedVideo: event.target.checked }); +}); + +videoQuality.addEventListener("change", (event) => { + browser.storage.sync.set({ + videoQuality: event.target.options[videoQuality.selectedIndex].value, + }); +}); + +removeTwitterSW.addEventListener("change", (event) => { + browser.storage.sync.set({ removeTwitterSW: !event.target.checked }); +}); + +invidiousDarkMode.addEventListener("change", (event) => { + browser.storage.sync.set({ invidiousDarkMode: event.target.checked }); +}); + +persistInvidiousPrefs.addEventListener("change", (event) => { + browser.storage.sync.set({ persistInvidiousPrefs: event.target.checked }); +}); + +useFreeTube.addEventListener("change", (event) => { + browser.storage.sync.set({ useFreeTube: event.target.checked }); +}); + +const invidiousVolumeChange = debounce(() => { + document.querySelector( + "#volume-value" + ).textContent = `${invidiousVolume.value}%`; + browser.storage.sync.set({ + invidiousVolume: invidiousVolume.value, + }); +}, 500); +invidiousVolume.addEventListener("input", invidiousVolumeChange); + +invidiousPlayerStyle.addEventListener("change", (event) => { + browser.storage.sync.set({ + invidiousPlayerStyle: + event.target.options[invidiousPlayerStyle.selectedIndex].value, + }); +}); + +const invidiousSubtitlesChange = debounce(() => { + browser.storage.sync.set({ invidiousSubtitles: invidiousSubtitles.value }); +}, 500); +invidiousSubtitles.addEventListener("input", invidiousSubtitlesChange); + +invidiousAutoplay.addEventListener("change", (event) => { + browser.storage.sync.set({ invidiousAutoplay: event.target.checked }); +}); + +const nitterRandomPoolChange = debounce(() => { + browser.storage.sync.set({ nitterRandomPool: nitterRandomPool.value }); +}, 500); +nitterRandomPool.addEventListener("input", nitterRandomPoolChange); + +const invidiousRandomPoolChange = debounce(() => { + browser.storage.sync.set({ invidiousRandomPool: invidiousRandomPool.value }); +}, 500); +invidiousRandomPool.addEventListener("input", invidiousRandomPoolChange); + +const bibliogramRandomPoolChange = debounce(() => { + browser.storage.sync.set({ + bibliogramRandomPool: bibliogramRandomPool.value, + }); +}, 500); +bibliogramRandomPool.addEventListener("input", bibliogramRandomPoolChange); + +theme.addEventListener("change", (event) => { + const value = event.target.options[theme.selectedIndex].value; + switch (value) { + case "dark-theme": + document.body.classList.add("dark-theme"); + document.body.classList.remove("light-theme"); + break; + case "light-theme": + document.body.classList.add("light-theme"); + document.body.classList.remove("dark-theme"); + break; + default: + document.body.classList.remove("light-theme"); + document.body.classList.remove("dark-theme"); + } + browser.storage.sync.set({ + theme: value, + }); +}); + +function autocomplete(input, list) { + let currentFocus; + input.addEventListener("focus", (e) => { + showOptions(e, true); + }); + input.addEventListener("input", (e) => { + const val = e.target.value; + if (!val) { + return false; + } + currentFocus = -1; + showOptions(e); + }); + input.addEventListener("keydown", function (e) { + let x = document.getElementById(this.id + "autocomplete-list"); + if (x) x = x.getElementsByTagName("div"); + if (e.keyCode == 40) { + currentFocus++; + addActive(x); + } else if (e.keyCode == 38) { + currentFocus--; + addActive(x); + } else if (e.keyCode == 13) { + e.preventDefault(); + if (currentFocus > -1) { + if (x) x[currentFocus].click(); + } + } + }); + function showOptions(event, showAll = false) { + let div, + i, + val = event.target.value; + closeAllLists(); + div = document.createElement("div"); + div.setAttribute("id", event.target.id + "autocomplete-list"); + div.setAttribute("class", "autocomplete-items"); + event.target.parentNode.appendChild(div); + for (i = 0; i < list.length; i++) { + if (list[i].toLowerCase().indexOf(val.toLowerCase()) > -1) { + div.appendChild(getItem(list[i], val)); + } else if (showAll) { + div.appendChild(getItem(list[i], val)); + } + } + } + function getItem(item, val) { + let div = document.createElement("div"); + div.innerHTML = "" + item.substr(0, val.length) + ""; + div.innerHTML += item.substr(val.length); + div.innerHTML += ""; + div.addEventListener("click", function (e) { + input.value = e.target.getElementsByTagName("input")[0].value; + input.dispatchEvent(new Event("input")); + closeAllLists(); + }); + return div; + } + function addActive(x) { + if (!x) return false; + removeActive(x); + if (currentFocus >= x.length) currentFocus = 0; + if (currentFocus < 0) currentFocus = x.length - 1; + x[currentFocus].classList.add("autocomplete-active"); + } + function removeActive(x) { + for (let i = 0; i < x.length; i++) { + x[i].classList.remove("autocomplete-active"); + } + } + function closeAllLists(elmnt) { + let x = document.getElementsByClassName("autocomplete-items"); + for (let i = 0; i < x.length; i++) { + if (elmnt != x[i] && elmnt != input) { + x[i].parentNode.removeChild(x[i]); + } + } + } + document.addEventListener("click", (e) => { + if (!autocompletes.find((element) => element.id === e.target.id)) { + closeAllLists(e.target); + } + }); +} + +autocompletes.forEach((value) => { + autocomplete(document.getElementById(value.id), value.instances); +}); + +var coll = document.getElementsByClassName("collapsible"); +var i; + +for (i = 0; i < coll.length; i++) { + coll[i].addEventListener("click", function () { + this.classList.toggle("collapsible-active"); + var content = this.nextElementSibling; + if (content.style.display === "block") { + content.style.display = "none"; + } else { + content.style.display = "block"; + } + }); +} diff --git a/src/pages/popup/popup.html b/src/pages/popup/popup.html new file mode 100644 index 00000000..43a4a1a8 --- /dev/null +++ b/src/pages/popup/popup.html @@ -0,0 +1,214 @@ + + + + + + + + + + + + +
      + + + + + + + +
      +

      Nitter Redirects

      +
      +   + +
      +
      + +
      + + + + + + + +
      +

      + Invidious Redirects +

      +
      +   + +
      +
      + +
      + + + + + + + +
      +

      + Bibliogram Redirects +

      +
      +   + +
      +
      + +
      + + + + + + + +
      +

      + OpenStreetMap Redirects +

      +
      +   + +
      +
      + +
      + + + + + + + +
      +

      Reddit Redirects

      +
      +   + +
      +
      + +
      + + + + + + + +
      +

      + Search Engine Redirects +

      +
      +   + +
      +
      + +
      + + + + + + + diff --git a/src/pages/popup/popup.js b/src/pages/popup/popup.js new file mode 100644 index 00000000..0afb2f97 --- /dev/null +++ b/src/pages/popup/popup.js @@ -0,0 +1,62 @@ +"use strict"; + +let disableNitter = document.querySelector("#disable-nitter"); +let disableInvidious = document.querySelector("#disable-invidious"); +let disableBibliogram = document.querySelector("#disable-bibliogram"); +let disableOsm = document.querySelector("#disable-osm"); +let disableReddit = document.querySelector("#disable-reddit"); +let disableSearchEngine = document.querySelector("#disable-searchEngine"); +let version = document.querySelector("#version"); + +window.browser = window.browser || window.chrome; + +browser.storage.sync.get( + [ + "disableNitter", + "disableInvidious", + "disableBibliogram", + "disableOsm", + "disableReddit", + "disableSearchEngine", + "theme", + ], + (result) => { + if (result.theme) document.body.classList.add(result.theme); + disableNitter.checked = !result.disableNitter; + disableInvidious.checked = !result.disableInvidious; + disableBibliogram.checked = !result.disableBibliogram; + disableOsm.checked = !result.disableOsm; + disableReddit.checked = !result.disableReddit; + disableSearchEngine.checked = !result.disableSearchEngine; + } +); + +version.textContent = browser.runtime.getManifest().version; + +disableNitter.addEventListener("change", (event) => { + browser.storage.sync.set({ disableNitter: !event.target.checked }); +}); + +disableInvidious.addEventListener("change", (event) => { + browser.storage.sync.set({ disableInvidious: !event.target.checked }); +}); + +disableBibliogram.addEventListener("change", (event) => { + browser.storage.sync.set({ disableBibliogram: !event.target.checked }); +}); + +disableOsm.addEventListener("change", (event) => { + browser.storage.sync.set({ disableOsm: !event.target.checked }); +}); + +disableReddit.addEventListener("change", (event) => { + browser.storage.sync.set({ disableReddit: !event.target.checked }); +}); + +disableSearchEngine.addEventListener("change", (event) => { + browser.storage.sync.set({ disableSearchEngine: !event.target.checked }); +}); + +document.querySelector("#more-options").addEventListener("click", () => { + browser.runtime.openOptionsPage(); +}); -- cgit 1.4.1