commit
631453600b
@ -1,5 +1,9 @@
|
|||||||
# Cookie Monster Dialog Browser Extension
|
# Cookie Monster Dialog Browser Extension
|
||||||
|
|
||||||
|
This browser extension was designed to remove cookie consent dialogs that appear on websites without setting your preferences. Only in a few cases, it operates based on predefined rules specified in the file `data/fixes.txt` from where the extension will automatically decline or accept the cookie consent dialogs.
|
||||||
|
|
||||||
|
Please note that the `data/fixes.txt` file should be regularly updated to reflect changes in websites' cookie consent practices and to ensure accurate handling of the dialogs by the extension.
|
||||||
|
|
||||||
## Downloads
|
## Downloads
|
||||||
|
|
||||||
- [Chrome Web Store](https://chrome.google.com/webstore/detail/djcbfpkdhdkaflcigibkbpboflaplabg)
|
- [Chrome Web Store](https://chrome.google.com/webstore/detail/djcbfpkdhdkaflcigibkbpboflaplabg)
|
||||||
@ -11,9 +15,9 @@
|
|||||||
- All browsers based on Chromium 88+ (Blisk, Brave, Colibri, Epic Browser, Iron Browser, Vivaldi and many more)
|
- All browsers based on Chromium 88+ (Blisk, Brave, Colibri, Epic Browser, Iron Browser, Vivaldi and many more)
|
||||||
- Google Chrome 88+
|
- Google Chrome 88+
|
||||||
- Microsoft Edge 88+
|
- Microsoft Edge 88+
|
||||||
- ~~Mozilla Firefox 54+~~ (development stalled until further notice, you can still download and use this extension in its **5.5.5** version)
|
- ~~Mozilla Firefox~~ (development stalled until further notice)
|
||||||
|
|
||||||
## Installation (only for developers)
|
## Installation (only for developers or Mozilla Firefox users)
|
||||||
|
|
||||||
1. Clone this repository and then run `yarn install`
|
1. Clone this repository and then run `yarn install`
|
||||||
2. Build this repository running the command `yarn workspace browser-extension run build`
|
2. Build this repository running the command `yarn workspace browser-extension run build`
|
||||||
|
@ -5,6 +5,21 @@
|
|||||||
"contextMenu_reportOption": {
|
"contextMenu_reportOption": {
|
||||||
"message": "Webseite melden..."
|
"message": "Webseite melden..."
|
||||||
},
|
},
|
||||||
|
"options_clearButton": {
|
||||||
|
"message": "Liste leeren"
|
||||||
|
},
|
||||||
|
"options_exclusionListTitle": {
|
||||||
|
"message": "Ausschlussliste"
|
||||||
|
},
|
||||||
|
"options_exportButton": {
|
||||||
|
"message": "Liste exportieren"
|
||||||
|
},
|
||||||
|
"options_filterPlaceholder": {
|
||||||
|
"message": "Nach dem Eintippen ENTER drücken, um zu filtern"
|
||||||
|
},
|
||||||
|
"options_importButton": {
|
||||||
|
"message": "Liste importieren"
|
||||||
|
},
|
||||||
"popup_contributeOption": {
|
"popup_contributeOption": {
|
||||||
"message": "Tragen Sie zu diesem Projekt bei"
|
"message": "Tragen Sie zu diesem Projekt bei"
|
||||||
},
|
},
|
||||||
|
@ -5,6 +5,21 @@
|
|||||||
"contextMenu_reportOption": {
|
"contextMenu_reportOption": {
|
||||||
"message": "Report site..."
|
"message": "Report site..."
|
||||||
},
|
},
|
||||||
|
"options_clearButton": {
|
||||||
|
"message": "Clear list"
|
||||||
|
},
|
||||||
|
"options_exclusionListTitle": {
|
||||||
|
"message": "Exclusion list"
|
||||||
|
},
|
||||||
|
"options_exportButton": {
|
||||||
|
"message": "Export list"
|
||||||
|
},
|
||||||
|
"options_filterPlaceholder": {
|
||||||
|
"message": "Press ENTER to filter after typing"
|
||||||
|
},
|
||||||
|
"options_importButton": {
|
||||||
|
"message": "Import list"
|
||||||
|
},
|
||||||
"popup_contributeOption": {
|
"popup_contributeOption": {
|
||||||
"message": "Contribute to this project"
|
"message": "Contribute to this project"
|
||||||
},
|
},
|
||||||
|
@ -5,6 +5,21 @@
|
|||||||
"contextMenu_reportOption": {
|
"contextMenu_reportOption": {
|
||||||
"message": "Reportar sitio..."
|
"message": "Reportar sitio..."
|
||||||
},
|
},
|
||||||
|
"options_clearButton": {
|
||||||
|
"message": "Borrar lista"
|
||||||
|
},
|
||||||
|
"options_exclusionListTitle": {
|
||||||
|
"message": "Lista de exclusión"
|
||||||
|
},
|
||||||
|
"options_exportButton": {
|
||||||
|
"message": "Exportar lista"
|
||||||
|
},
|
||||||
|
"options_filterPlaceholder": {
|
||||||
|
"message": "Presiona ENTER para filtrar después de escribir"
|
||||||
|
},
|
||||||
|
"options_importButton": {
|
||||||
|
"message": "Importar lista"
|
||||||
|
},
|
||||||
"popup_contributeOption": {
|
"popup_contributeOption": {
|
||||||
"message": "Contribuye a este proyecto"
|
"message": "Contribuye a este proyecto"
|
||||||
},
|
},
|
||||||
|
@ -5,6 +5,21 @@
|
|||||||
"contextMenu_reportOption": {
|
"contextMenu_reportOption": {
|
||||||
"message": "Signaler le site..."
|
"message": "Signaler le site..."
|
||||||
},
|
},
|
||||||
|
"options_clearButton": {
|
||||||
|
"message": "Effacer la liste"
|
||||||
|
},
|
||||||
|
"options_exclusionListTitle": {
|
||||||
|
"message": "Liste d'exclusion"
|
||||||
|
},
|
||||||
|
"options_exportButton": {
|
||||||
|
"message": "Exporter la liste"
|
||||||
|
},
|
||||||
|
"options_filterPlaceholder": {
|
||||||
|
"message": "Appuyez sur ENTRÉE pour filtrer après avoir tapé"
|
||||||
|
},
|
||||||
|
"options_importButton": {
|
||||||
|
"message": "Importer la liste"
|
||||||
|
},
|
||||||
"popup_contributeOption": {
|
"popup_contributeOption": {
|
||||||
"message": "Contribuez à ce projet"
|
"message": "Contribuez à ce projet"
|
||||||
},
|
},
|
||||||
|
@ -5,6 +5,21 @@
|
|||||||
"contextMenu_reportOption": {
|
"contextMenu_reportOption": {
|
||||||
"message": "Segnala sito..."
|
"message": "Segnala sito..."
|
||||||
},
|
},
|
||||||
|
"options_clearButton": {
|
||||||
|
"message": "Cancella elenco"
|
||||||
|
},
|
||||||
|
"options_exclusionListTitle": {
|
||||||
|
"message": "Elenco di esclusione"
|
||||||
|
},
|
||||||
|
"options_exportButton": {
|
||||||
|
"message": "Esporta elenco"
|
||||||
|
},
|
||||||
|
"options_filterPlaceholder": {
|
||||||
|
"message": "Premi INVIO per filtrare dopo aver digitato"
|
||||||
|
},
|
||||||
|
"options_importButton": {
|
||||||
|
"message": "Importa elenco"
|
||||||
|
},
|
||||||
"popup_contributeOption": {
|
"popup_contributeOption": {
|
||||||
"message": "Contribuisci a questo progetto"
|
"message": "Contribuisci a questo progetto"
|
||||||
},
|
},
|
||||||
|
@ -5,6 +5,21 @@
|
|||||||
"contextMenu_reportOption": {
|
"contextMenu_reportOption": {
|
||||||
"message": "Reportar site..."
|
"message": "Reportar site..."
|
||||||
},
|
},
|
||||||
|
"options_clearButton": {
|
||||||
|
"message": "Limpar lista"
|
||||||
|
},
|
||||||
|
"options_exclusionListTitle": {
|
||||||
|
"message": "Lista de exclusão"
|
||||||
|
},
|
||||||
|
"options_exportButton": {
|
||||||
|
"message": "Exportar lista"
|
||||||
|
},
|
||||||
|
"options_filterPlaceholder": {
|
||||||
|
"message": "Pressione ENTER para filtrar após digitar"
|
||||||
|
},
|
||||||
|
"options_importButton": {
|
||||||
|
"message": "Importar lista"
|
||||||
|
},
|
||||||
"popup_contributeOption": {
|
"popup_contributeOption": {
|
||||||
"message": "Contribua para este projeto"
|
"message": "Contribua para este projeto"
|
||||||
},
|
},
|
||||||
|
@ -5,6 +5,21 @@
|
|||||||
"contextMenu_reportOption": {
|
"contextMenu_reportOption": {
|
||||||
"message": "Reportar site..."
|
"message": "Reportar site..."
|
||||||
},
|
},
|
||||||
|
"options_clearButton": {
|
||||||
|
"message": "Limpar lista"
|
||||||
|
},
|
||||||
|
"options_exclusionListTitle": {
|
||||||
|
"message": "Lista de exclusão"
|
||||||
|
},
|
||||||
|
"options_exportButton": {
|
||||||
|
"message": "Exportar lista"
|
||||||
|
},
|
||||||
|
"options_filterPlaceholder": {
|
||||||
|
"message": "Pressione ENTER para filtrar após digitar"
|
||||||
|
},
|
||||||
|
"options_importButton": {
|
||||||
|
"message": "Importar lista"
|
||||||
|
},
|
||||||
"popup_contributeOption": {
|
"popup_contributeOption": {
|
||||||
"message": "Contribua para este projeto"
|
"message": "Contribua para este projeto"
|
||||||
},
|
},
|
||||||
|
@ -5,6 +5,21 @@
|
|||||||
"contextMenu_reportOption": {
|
"contextMenu_reportOption": {
|
||||||
"message": "Raportați site-ul..."
|
"message": "Raportați site-ul..."
|
||||||
},
|
},
|
||||||
|
"options_clearButton": {
|
||||||
|
"message": "Ștergeți lista"
|
||||||
|
},
|
||||||
|
"options_exclusionListTitle": {
|
||||||
|
"message": "Listă de excludere"
|
||||||
|
},
|
||||||
|
"options_exportButton": {
|
||||||
|
"message": "Exportați lista"
|
||||||
|
},
|
||||||
|
"options_filterPlaceholder": {
|
||||||
|
"message": "Apăsați ENTER pentru a filtra după ce ați tastat"
|
||||||
|
},
|
||||||
|
"options_importButton": {
|
||||||
|
"message": "Importați lista"
|
||||||
|
},
|
||||||
"popup_contributeOption": {
|
"popup_contributeOption": {
|
||||||
"message": "Contribuie la acest proiect"
|
"message": "Contribuie la acest proiect"
|
||||||
},
|
},
|
||||||
|
@ -5,6 +5,21 @@
|
|||||||
"contextMenu_reportOption": {
|
"contextMenu_reportOption": {
|
||||||
"message": "Сообщить о сайте..."
|
"message": "Сообщить о сайте..."
|
||||||
},
|
},
|
||||||
|
"options_clearButton": {
|
||||||
|
"message": "Очистить список"
|
||||||
|
},
|
||||||
|
"options_exclusionListTitle": {
|
||||||
|
"message": "Список исключений"
|
||||||
|
},
|
||||||
|
"options_exportButton": {
|
||||||
|
"message": "Экспорт списка"
|
||||||
|
},
|
||||||
|
"options_filterPlaceholder": {
|
||||||
|
"message": "Нажмите ENTER для фильтрации после ввода"
|
||||||
|
},
|
||||||
|
"options_importButton": {
|
||||||
|
"message": "Импорт списка"
|
||||||
|
},
|
||||||
"popup_contributeOption": {
|
"popup_contributeOption": {
|
||||||
"message": "Внести свой вклад в этот проект"
|
"message": "Внести свой вклад в этот проект"
|
||||||
},
|
},
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"manifest_version": 3,
|
"manifest_version": 3,
|
||||||
"name": "Cookie Dialog Monster",
|
"name": "Cookie Dialog Monster",
|
||||||
"version": "6.3.4",
|
"version": "6.4.0",
|
||||||
"default_locale": "en",
|
"default_locale": "en",
|
||||||
"description": "__MSG_appDesc__",
|
"description": "__MSG_appDesc__",
|
||||||
"icons": {
|
"icons": {
|
||||||
@ -13,6 +13,7 @@
|
|||||||
"default_icon": "assets/icons/disabled.png",
|
"default_icon": "assets/icons/disabled.png",
|
||||||
"default_title": "Cookie Dialog Monster"
|
"default_title": "Cookie Dialog Monster"
|
||||||
},
|
},
|
||||||
|
"options_page": "options.html",
|
||||||
"author": "wanhose",
|
"author": "wanhose",
|
||||||
"background": {
|
"background": {
|
||||||
"service_worker": "scripts/background.js"
|
"service_worker": "scripts/background.js"
|
||||||
@ -25,6 +26,7 @@
|
|||||||
"*://*.sharepoint.com/*",
|
"*://*.sharepoint.com/*",
|
||||||
"*://*.youtube.com/embed/*",
|
"*://*.youtube.com/embed/*",
|
||||||
"*://*.youtube-nocookie.com/embed/*",
|
"*://*.youtube-nocookie.com/embed/*",
|
||||||
|
"https://translate.google.com/*",
|
||||||
"https://www.cookie-dialog-monster.com/*"
|
"https://www.cookie-dialog-monster.com/*"
|
||||||
],
|
],
|
||||||
"js": ["scripts/content.js", "scripts/dialog.js"],
|
"js": ["scripts/content.js", "scripts/dialog.js"],
|
||||||
|
110
packages/browser-extension/src/options.html
Normal file
110
packages/browser-extension/src/options.html
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<title>Cookie Dialog Monster > Exclusion List</title>
|
||||||
|
<link rel="stylesheet" href="/styles/reset.css" />
|
||||||
|
<link rel="stylesheet" href="/styles/options.css" />
|
||||||
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Inter" />
|
||||||
|
<script src="/scripts/options.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<header>
|
||||||
|
<div>
|
||||||
|
<h1 class="header-title">
|
||||||
|
Cookie Dialog Monster > <span data-i18n="options_exclusionListTitle"></span>
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
<main>
|
||||||
|
<div class="button-group">
|
||||||
|
<button data-variant="large" id="clear-button">
|
||||||
|
<span data-i18n="options_clearButton"></span>
|
||||||
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
|
fill="none"
|
||||||
|
height="14"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke="currentColor"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
width="14"
|
||||||
|
>
|
||||||
|
<polyline points="3 6 5 6 21 6"></polyline>
|
||||||
|
<path
|
||||||
|
d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"
|
||||||
|
/>
|
||||||
|
<line x1="10" y1="11" x2="10" y2="17"></line>
|
||||||
|
<line x1="14" y1="11" x2="14" y2="17"></line>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<button data-variant="large" id="import-button">
|
||||||
|
<span data-i18n="options_importButton"></span>
|
||||||
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
|
fill="none"
|
||||||
|
height="14"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke="currentColor"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
width="14"
|
||||||
|
>
|
||||||
|
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
|
||||||
|
<polyline points="17 8 12 3 7 8"></polyline>
|
||||||
|
<line x1="12" y1="3" x2="12" y2="15"></line>
|
||||||
|
</svg>
|
||||||
|
<input accept=".cdm" id="file-input" style="display: none" type="file" />
|
||||||
|
</button>
|
||||||
|
<button data-variant="large" id="export-button">
|
||||||
|
<span data-i18n="options_exportButton"></span>
|
||||||
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
|
fill="none"
|
||||||
|
height="14"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke="currentColor"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
width="14"
|
||||||
|
>
|
||||||
|
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
|
||||||
|
<polyline points="7 10 12 15 17 10"></polyline>
|
||||||
|
<line x1="12" y1="15" x2="12" y2="3"></line>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<input id="filter-input" data-i18n-placeholder="options_filterPlaceholder" />
|
||||||
|
<ul id="exclusion-list">
|
||||||
|
<li id="exclusion-list-item-template" style="display: none">
|
||||||
|
<span></span>
|
||||||
|
<button>
|
||||||
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
|
fill="none"
|
||||||
|
height="14"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke="currentColor"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
width="14"
|
||||||
|
>
|
||||||
|
<polyline points="3 6 5 6 21 6"></polyline>
|
||||||
|
<path
|
||||||
|
d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"
|
||||||
|
/>
|
||||||
|
<line x1="10" y1="11" x2="10" y2="17"></line>
|
||||||
|
<line x1="14" y1="11" x2="14" y2="17"></line>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
<li id="exclusion-list-item-empty" style="display: none"></li>
|
||||||
|
</ul>
|
||||||
|
</main>
|
||||||
|
<footer></footer>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -1,7 +1,6 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="author" content="wanhose" />
|
|
||||||
<link rel="stylesheet" href="/styles/reset.css" />
|
<link rel="stylesheet" href="/styles/reset.css" />
|
||||||
<link rel="stylesheet" href="/styles/popup.css" />
|
<link rel="stylesheet" href="/styles/popup.css" />
|
||||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Inter" />
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Inter" />
|
||||||
@ -10,6 +9,24 @@
|
|||||||
<body>
|
<body>
|
||||||
<header>
|
<header>
|
||||||
<h1 class="header-title">Cookie Dialog Monster</h1>
|
<h1 class="header-title">Cookie Dialog Monster</h1>
|
||||||
|
<button id="settings-button">
|
||||||
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
|
fill="none"
|
||||||
|
height="18"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke="currentColor"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
width="18"
|
||||||
|
>
|
||||||
|
<circle cx="12" cy="12" r="3"></circle>
|
||||||
|
<path
|
||||||
|
d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
</header>
|
</header>
|
||||||
<main>
|
<main>
|
||||||
<popup-button id="power-option" role="button" tabindex="0">
|
<popup-button id="power-option" role="button" tabindex="0">
|
||||||
@ -17,10 +34,10 @@
|
|||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
fill="none"
|
fill="none"
|
||||||
height="32"
|
height="32"
|
||||||
stroke="currentColor"
|
|
||||||
stroke-linecap="round"
|
stroke-linecap="round"
|
||||||
stroke-linejoin="round"
|
stroke-linejoin="round"
|
||||||
stroke-width="2"
|
stroke-width="2"
|
||||||
|
stroke="currentColor"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
width="32"
|
width="32"
|
||||||
>
|
>
|
||||||
@ -34,10 +51,10 @@
|
|||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
fill="none"
|
fill="none"
|
||||||
height="32"
|
height="32"
|
||||||
stroke="currentColor"
|
|
||||||
stroke-linecap="round"
|
stroke-linecap="round"
|
||||||
stroke-linejoin="round"
|
stroke-linejoin="round"
|
||||||
stroke-width="2"
|
stroke-width="2"
|
||||||
|
stroke="currentColor"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
width="32"
|
width="32"
|
||||||
>
|
>
|
||||||
@ -57,10 +74,10 @@
|
|||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
fill="none"
|
fill="none"
|
||||||
height="32"
|
height="32"
|
||||||
stroke="currentColor"
|
|
||||||
stroke-linecap="round"
|
stroke-linecap="round"
|
||||||
stroke-linejoin="round"
|
stroke-linejoin="round"
|
||||||
stroke-width="2"
|
stroke-width="2"
|
||||||
|
stroke="currentColor"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
width="32"
|
width="32"
|
||||||
>
|
>
|
||||||
@ -75,10 +92,10 @@
|
|||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
fill="none"
|
fill="none"
|
||||||
height="32"
|
height="32"
|
||||||
stroke="currentColor"
|
|
||||||
stroke-linecap="round"
|
stroke-linecap="round"
|
||||||
stroke-linejoin="round"
|
stroke-linejoin="round"
|
||||||
stroke-width="2"
|
stroke-width="2"
|
||||||
|
stroke="currentColor"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
width="32"
|
width="32"
|
||||||
>
|
>
|
||||||
|
@ -5,13 +5,6 @@
|
|||||||
|
|
||||||
const apiUrl = 'https://api.cookie-dialog-monster.com/rest/v2';
|
const apiUrl = 'https://api.cookie-dialog-monster.com/rest/v2';
|
||||||
|
|
||||||
/**
|
|
||||||
* @description Initial state
|
|
||||||
* @type {{ enabled: boolean }}
|
|
||||||
*/
|
|
||||||
|
|
||||||
const initial = { enabled: true };
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description Context menu identifier
|
* @description Context menu identifier
|
||||||
* @type {string}
|
* @type {string}
|
||||||
@ -90,31 +83,65 @@ chrome.runtime.onMessage.addListener((message, sender, callback) => {
|
|||||||
|
|
||||||
switch (message.type) {
|
switch (message.type) {
|
||||||
case 'DISABLE_ICON':
|
case 'DISABLE_ICON':
|
||||||
if (isPage && tabId) chrome.action.setIcon({ path: '/assets/icons/disabled.png', tabId });
|
if (isPage && tabId) {
|
||||||
|
chrome.action.setIcon({ path: '/assets/icons/disabled.png', tabId });
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 'ENABLE_ICON':
|
case 'ENABLE_ICON':
|
||||||
if (isPage && tabId) chrome.action.setIcon({ path: '/assets/icons/enabled.png', tabId });
|
if (isPage && tabId) {
|
||||||
|
chrome.action.setIcon({ path: '/assets/icons/enabled.png', tabId });
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 'ENABLE_POPUP':
|
case 'ENABLE_POPUP':
|
||||||
if (isPage && tabId) chrome.action.setPopup({ popup: '/popup.html', tabId });
|
if (isPage && tabId) {
|
||||||
|
chrome.action.setPopup({ popup: '/popup.html', tabId });
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 'GET_DATA':
|
case 'GET_DATA':
|
||||||
storage.get('data', ({ data }) => (data ? callback(data) : refreshData(callback)));
|
storage.get('data', ({ data }) => {
|
||||||
|
if (data) {
|
||||||
|
callback(data);
|
||||||
|
} else {
|
||||||
|
refreshData(callback);
|
||||||
|
}
|
||||||
|
});
|
||||||
return true;
|
return true;
|
||||||
case 'GET_STATE':
|
case 'GET_EXCLUSION_LIST':
|
||||||
if (hostname) storage.get(hostname, (state) => callback(state[hostname] ?? initial));
|
storage.get(null, (exclusions) => {
|
||||||
|
const exclusionList = Object.entries(exclusions || {}).flatMap((x) =>
|
||||||
|
x[0] !== 'data' && !x[1]?.enabled ? [x[0]] : []
|
||||||
|
);
|
||||||
|
callback(exclusionList);
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
case 'GET_HOSTNAME_STATE':
|
||||||
|
if (hostname) {
|
||||||
|
storage.get(hostname, (state) => {
|
||||||
|
callback(state[hostname] ?? { enabled: true });
|
||||||
|
});
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
case 'GET_TAB':
|
case 'GET_TAB':
|
||||||
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => callback(tabs[0]));
|
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
|
||||||
|
callback(tabs[0]);
|
||||||
|
});
|
||||||
return true;
|
return true;
|
||||||
case 'INSERT_DIALOG_CSS':
|
case 'INSERT_DIALOG_CSS':
|
||||||
if (isPage && tabId) script.insertCSS({ files: ['styles/dialog.css'], target: { tabId } });
|
if (isPage && tabId) {
|
||||||
|
script.insertCSS({ files: ['styles/dialog.css'], target: { tabId } });
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 'REPORT':
|
case 'REPORT':
|
||||||
if (tabId) report(message, sender.tab);
|
if (tabId) {
|
||||||
|
report(message, sender.tab);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 'UPDATE_STATE':
|
case 'SET_HOSTNAME_STATE':
|
||||||
if (hostname) storage.set({ [hostname]: message.state });
|
if (hostname && message.state.enabled === false) {
|
||||||
|
storage.set({ [hostname]: message.state });
|
||||||
|
} else if (hostname) {
|
||||||
|
storage.remove(hostname);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -42,6 +42,7 @@ let state = { enabled: true };
|
|||||||
* @description Cleans DOM
|
* @description Cleans DOM
|
||||||
* @param {Element[]} elements
|
* @param {Element[]} elements
|
||||||
* @param {boolean?} skipMatch
|
* @param {boolean?} skipMatch
|
||||||
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function clean(elements, skipMatch) {
|
function clean(elements, skipMatch) {
|
||||||
@ -59,6 +60,7 @@ function clean(elements, skipMatch) {
|
|||||||
/**
|
/**
|
||||||
* @description Forces a DOM clean in the specific element
|
* @description Forces a DOM clean in the specific element
|
||||||
* @param {HTMLElement} element
|
* @param {HTMLElement} element
|
||||||
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function forceClean(element) {
|
function forceClean(element) {
|
||||||
@ -73,6 +75,7 @@ function forceClean(element) {
|
|||||||
/**
|
/**
|
||||||
* @description Forces element to have these styles
|
* @description Forces element to have these styles
|
||||||
* @param {HTMLElement} element
|
* @param {HTMLElement} element
|
||||||
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function forceElementStyles(element) {
|
function forceElementStyles(element) {
|
||||||
@ -112,7 +115,7 @@ function match(element, skipMatch) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data?.tags.includes(element.tagName?.toUpperCase?.())) {
|
if (!data?.tags?.length || data.tags.includes(element.tagName?.toUpperCase?.())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,6 +139,7 @@ function match(element, skipMatch) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @description Fixes scroll issues
|
* @description Fixes scroll issues
|
||||||
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function fix() {
|
function fix() {
|
||||||
@ -198,6 +202,29 @@ function readingTime() {
|
|||||||
return time;
|
return time;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @async
|
||||||
|
* @description Sets up everything
|
||||||
|
* @param {boolean} skipReadyStateHack
|
||||||
|
*/
|
||||||
|
|
||||||
|
async function runSetup(skipReadyStateHack) {
|
||||||
|
state = (await dispatch({ hostname, type: 'GET_HOSTNAME_STATE' })) ?? state;
|
||||||
|
dispatch({ type: 'ENABLE_POPUP' });
|
||||||
|
|
||||||
|
if (state.enabled) {
|
||||||
|
data = await dispatch({ hostname, type: 'GET_DATA' });
|
||||||
|
|
||||||
|
// 2023-06-13: hack to force clean when data request takes too long and there are no changes later
|
||||||
|
if (document.readyState === 'complete' && !skipReadyStateHack) {
|
||||||
|
window.dispatchEvent(new Event('run'));
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatch({ type: 'ENABLE_ICON' });
|
||||||
|
observer.observe(document.body ?? document.documentElement, options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description Mutation Observer instance
|
* @description Mutation Observer instance
|
||||||
* @type {MutationObserver}
|
* @type {MutationObserver}
|
||||||
@ -212,22 +239,40 @@ const observer = new MutationObserver((mutations) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @async
|
||||||
|
* @description Runs setup if the page wasn't focused yet
|
||||||
|
* @listens window#focus
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
|
||||||
|
window.addEventListener('focus', async () => {
|
||||||
|
if (!data) {
|
||||||
|
await runSetup(true);
|
||||||
|
forceClean(document.body);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description Fixes still existing elements when page fully load
|
* @description Fixes still existing elements when page fully load
|
||||||
* @listens window#load
|
* @listens window#load
|
||||||
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
window.addEventListener('load', () => {
|
window.addEventListener('load', () => {
|
||||||
window.dispatchEvent(new Event('run'));
|
if (document.hasFocus()) {
|
||||||
|
window.dispatchEvent(new Event('run'));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description Fixes bfcache issues
|
* @description Fixes bfcache issues
|
||||||
* @listens window#pageshow
|
* @listens window#pageshow
|
||||||
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
window.addEventListener('pageshow', (event) => {
|
window.addEventListener('pageshow', (event) => {
|
||||||
if (event.persisted) {
|
if (document.hasFocus() && event.persisted) {
|
||||||
window.dispatchEvent(new Event('run'));
|
window.dispatchEvent(new Event('run'));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -235,6 +280,7 @@ window.addEventListener('pageshow', (event) => {
|
|||||||
/**
|
/**
|
||||||
* @description Forces a clean when this event is fired
|
* @description Forces a clean when this event is fired
|
||||||
* @listens window#run
|
* @listens window#run
|
||||||
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
window.addEventListener('run', () => {
|
window.addEventListener('run', () => {
|
||||||
@ -249,23 +295,9 @@ window.addEventListener('run', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @async
|
* @description As this extension do really expensive work, it only runs if the user is on the page
|
||||||
* @description Sets up everything
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
(async () => {
|
if (document.hasFocus()) {
|
||||||
state = (await dispatch({ hostname, type: 'GET_STATE' })) ?? state;
|
runSetup();
|
||||||
dispatch({ type: 'ENABLE_POPUP' });
|
}
|
||||||
|
|
||||||
if (state.enabled) {
|
|
||||||
data = await dispatch({ hostname, type: 'GET_DATA' });
|
|
||||||
|
|
||||||
// 2023-06-13: hack to force clean when data request takes too long and there are no changes later
|
|
||||||
if (document.readyState === 'complete') {
|
|
||||||
window.dispatchEvent(new Event('run'));
|
|
||||||
}
|
|
||||||
|
|
||||||
dispatch({ type: 'ENABLE_ICON' });
|
|
||||||
observer.observe(document.body ?? document.documentElement, options);
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
|
244
packages/browser-extension/src/scripts/options.js
Normal file
244
packages/browser-extension/src/scripts/options.js
Normal file
@ -0,0 +1,244 @@
|
|||||||
|
/**
|
||||||
|
* @description Shortcut to send messages to background script
|
||||||
|
*/
|
||||||
|
|
||||||
|
const dispatch = chrome.runtime.sendMessage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description Exclusion list, URLs where the user prefers to disable the extension
|
||||||
|
* @type {string[]}
|
||||||
|
*/
|
||||||
|
|
||||||
|
let exclusionList = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description Renders exclusion items into exclusion list
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
|
||||||
|
function createList() {
|
||||||
|
const emptyItemElement = document.getElementById('exclusion-list-item-empty');
|
||||||
|
const exclusionListElement = document.getElementById('exclusion-list');
|
||||||
|
const exclusionListItemTemplateElement = document.getElementById('exclusion-list-item-template');
|
||||||
|
|
||||||
|
Array.from(exclusionListElement.querySelectorAll('[data-value]')).forEach((exclusionItem) => {
|
||||||
|
exclusionItem.remove();
|
||||||
|
});
|
||||||
|
|
||||||
|
if (exclusionList.length) {
|
||||||
|
for (const exclusionValue of exclusionList) {
|
||||||
|
const ariaLabelOrTitle = `Delete ${exclusionValue}`;
|
||||||
|
const itemElement = exclusionListItemTemplateElement.cloneNode(true);
|
||||||
|
const deleteButtonElement = itemElement.getElementsByTagName('button')[0];
|
||||||
|
|
||||||
|
deleteButtonElement.addEventListener('click', handleDeleteClick);
|
||||||
|
deleteButtonElement.setAttribute('aria-label', ariaLabelOrTitle);
|
||||||
|
deleteButtonElement.setAttribute('title', ariaLabelOrTitle);
|
||||||
|
itemElement.removeAttribute('id');
|
||||||
|
itemElement.getElementsByTagName('span')[0].innerText = exclusionValue;
|
||||||
|
itemElement.setAttribute('data-value', exclusionValue);
|
||||||
|
itemElement.style.removeProperty('display');
|
||||||
|
exclusionListElement.appendChild(itemElement);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
emptyItemElement.innerText = "You don't have any exclusions yet";
|
||||||
|
emptyItemElement.style.removeProperty('display');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @async
|
||||||
|
* @description Clear all items from the exclusion list
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
|
||||||
|
async function handleClearClick() {
|
||||||
|
const filterInputElement = document.getElementById('filter-input');
|
||||||
|
|
||||||
|
for (const exclusionValue of exclusionList) {
|
||||||
|
const state = { enabled: true };
|
||||||
|
await dispatch({ hostname: exclusionValue, state, type: 'SET_HOSTNAME_STATE' });
|
||||||
|
}
|
||||||
|
|
||||||
|
exclusionList = [];
|
||||||
|
createList();
|
||||||
|
updateList(filterInputElement.value.trim());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @async
|
||||||
|
* @description Setup handlers and items
|
||||||
|
*/
|
||||||
|
|
||||||
|
async function handleContentLoaded() {
|
||||||
|
exclusionList = await dispatch({ type: 'GET_EXCLUSION_LIST' });
|
||||||
|
createList();
|
||||||
|
|
||||||
|
const clearButtonElement = document.getElementById('clear-button');
|
||||||
|
clearButtonElement.addEventListener('click', handleClearClick);
|
||||||
|
|
||||||
|
const exportButtonElement = document.getElementById('export-button');
|
||||||
|
exportButtonElement.addEventListener('click', handleExportClick);
|
||||||
|
|
||||||
|
const fileInputElement = document.getElementById('file-input');
|
||||||
|
fileInputElement.addEventListener('change', handleFileChange);
|
||||||
|
|
||||||
|
const filterInputElement = document.getElementById('filter-input');
|
||||||
|
filterInputElement.addEventListener('keydown', handleFilterKeyDown);
|
||||||
|
|
||||||
|
const importButtonElement = document.getElementById('import-button');
|
||||||
|
importButtonElement.addEventListener('click', handleImportClick);
|
||||||
|
|
||||||
|
translate();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @async
|
||||||
|
* @description Deletes the clicked element from the exclusion list
|
||||||
|
* @param {MouseEvent} event
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
|
||||||
|
async function handleDeleteClick(event) {
|
||||||
|
const filterInputElement = document.getElementById('filter-input');
|
||||||
|
const { value } = event.currentTarget.parentElement.dataset;
|
||||||
|
const state = { enabled: true };
|
||||||
|
|
||||||
|
await dispatch({ hostname: value, state, type: 'SET_HOSTNAME_STATE' });
|
||||||
|
exclusionList = exclusionList.filter((exclusionValue) => exclusionValue !== value);
|
||||||
|
itemElement.remove();
|
||||||
|
updateList(filterInputElement.value.trim());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description Exports a file with the current exclusion list
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
|
||||||
|
function handleExportClick() {
|
||||||
|
const anchor = document.createElement('a');
|
||||||
|
const text = exclusionList.join('\n');
|
||||||
|
const blob = new Blob([text], { type: 'octet/stream' });
|
||||||
|
const url = window.URL.createObjectURL(blob);
|
||||||
|
|
||||||
|
anchor.href = url;
|
||||||
|
anchor.download = `${new Date().valueOf()}.cdm`;
|
||||||
|
anchor.click();
|
||||||
|
window.URL.revokeObjectURL(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description Processes a file and sends the updates
|
||||||
|
* @param {InputEvent} event
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
|
||||||
|
function handleFileChange(event) {
|
||||||
|
const file = event.currentTarget.files[0];
|
||||||
|
const filterInputElement = document.getElementById('filter-input');
|
||||||
|
const reader = new FileReader();
|
||||||
|
|
||||||
|
reader.addEventListener('load', async (event) => {
|
||||||
|
const newExclusionList = event.currentTarget.result.split('\n').filter((x) => x.trim());
|
||||||
|
|
||||||
|
for (const exclusionValue of newExclusionList) {
|
||||||
|
const state = { enabled: false };
|
||||||
|
await dispatch({ hostname: exclusionValue, state, type: 'SET_HOSTNAME_STATE' });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newExclusionList.length) {
|
||||||
|
exclusionList = [...new Set([...exclusionList, ...newExclusionList])].sort();
|
||||||
|
createList();
|
||||||
|
updateList(filterInputElement.value.trim());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
event.currentTarget.value = '';
|
||||||
|
reader.readAsText(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description Applies filter to the exclusion list when the user presses ENTER key
|
||||||
|
* @param {KeyboardEvent} event
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
|
||||||
|
function handleFilterKeyDown(event) {
|
||||||
|
if (event.key === 'Enter') {
|
||||||
|
const filterValue = event.currentTarget.value.trim();
|
||||||
|
updateList(filterValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description Shallow clicks an hidden input to open the file explorer
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
|
||||||
|
function handleImportClick() {
|
||||||
|
const fileInputElement = document.getElementById('file-input');
|
||||||
|
fileInputElement.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description Applies translations to tags with i18n data attribute
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
|
||||||
|
function translate() {
|
||||||
|
const nodes = document.querySelectorAll('[data-i18n], [data-i18n-placeholder]');
|
||||||
|
|
||||||
|
for (let i = nodes.length; i--; ) {
|
||||||
|
const node = nodes[i];
|
||||||
|
const { i18n, i18nPlaceholder } = node.dataset;
|
||||||
|
|
||||||
|
if (i18n) {
|
||||||
|
node.innerHTML = chrome.i18n.getMessage(i18n);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i18nPlaceholder) {
|
||||||
|
node.setAttribute('placeholder', chrome.i18n.getMessage(i18nPlaceholder));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description Updates exclusion items in DOM
|
||||||
|
* @param {string | undefined} filterValue
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
|
||||||
|
function updateList(filterValue) {
|
||||||
|
const emptyItemElement = document.getElementById('exclusion-list-item-empty');
|
||||||
|
const exclusionListElement = document.getElementById('exclusion-list');
|
||||||
|
const exclusionListElements = exclusionListElement.querySelectorAll(`[data-value]`);
|
||||||
|
|
||||||
|
if (exclusionListElements.length) {
|
||||||
|
let isEmpty = true;
|
||||||
|
emptyItemElement.style.setProperty('display', 'none');
|
||||||
|
|
||||||
|
for (const exclusionItemElement of Array.from(exclusionListElements)) {
|
||||||
|
if (exclusionItemElement.matches(`[data-value*="${filterValue}"]`) || !filterValue) {
|
||||||
|
exclusionItemElement.style.removeProperty('display');
|
||||||
|
isEmpty = false;
|
||||||
|
} else {
|
||||||
|
exclusionItemElement.style.setProperty('display', 'none');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isEmpty) {
|
||||||
|
emptyItemElement.innerText = 'No exclusions found';
|
||||||
|
emptyItemElement.style.removeProperty('display');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
emptyItemElement.innerText = "You don't have any exclusions yet";
|
||||||
|
emptyItemElement.style.removeProperty('display');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description Listen to document ready
|
||||||
|
* @listens document#DOMContentLoaded
|
||||||
|
*/
|
||||||
|
|
||||||
|
document.addEventListener('DOMContentLoaded', handleContentLoaded);
|
@ -64,80 +64,104 @@ let state = { enabled: true };
|
|||||||
/**
|
/**
|
||||||
* @async
|
* @async
|
||||||
* @description Setup stars handlers and result message links
|
* @description Setup stars handlers and result message links
|
||||||
|
* @returns {Promise<void>}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const handleContentLoaded = async () => {
|
async function handleContentLoaded() {
|
||||||
const tab = await dispatch({ type: 'GET_TAB' });
|
const tab = await dispatch({ type: 'GET_TAB' });
|
||||||
|
|
||||||
hostname = tab?.url
|
hostname = tab?.url
|
||||||
? new URL(tab.url).hostname.split('.').slice(-3).join('.').replace('www.', '')
|
? new URL(tab.url).hostname.split('.').slice(-3).join('.').replace('www.', '')
|
||||||
: undefined;
|
: undefined;
|
||||||
state = (await dispatch({ hostname, type: 'GET_STATE' })) ?? state;
|
state = (await dispatch({ hostname, type: 'GET_HOSTNAME_STATE' })) ?? state;
|
||||||
|
|
||||||
const host = document.getElementById('host');
|
const hostTextElement = document.getElementById('host');
|
||||||
host.innerText = hostname ?? 'unknown';
|
hostTextElement.innerText = hostname ?? 'unknown';
|
||||||
|
|
||||||
const contribute = document.getElementById('contribute-option');
|
const contributeButtonElement = document.getElementById('contribute-option');
|
||||||
contribute?.addEventListener('click', handleLinkRedirect);
|
contributeButtonElement?.addEventListener('click', handleLinkRedirect);
|
||||||
|
|
||||||
const help = document.getElementById('help-option');
|
const helpButtonElement = document.getElementById('help-option');
|
||||||
help?.addEventListener('click', handleLinkRedirect);
|
helpButtonElement?.addEventListener('click', handleLinkRedirect);
|
||||||
|
|
||||||
const power = document.getElementById('power-option');
|
const powerButtonElement = document.getElementById('power-option');
|
||||||
power?.addEventListener('click', handlePowerToggle);
|
powerButtonElement?.addEventListener('click', handlePowerToggle);
|
||||||
if (state.enabled) power?.setAttribute('data-value', 'on');
|
if (state.enabled) powerButtonElement?.setAttribute('data-value', 'on');
|
||||||
else power?.setAttribute('data-value', 'off');
|
else powerButtonElement?.setAttribute('data-value', 'off');
|
||||||
|
|
||||||
const rate = document.getElementById('rate-option');
|
const rateButtonElement = document.getElementById('rate-option');
|
||||||
rate?.addEventListener('click', handleLinkRedirect);
|
rateButtonElement?.addEventListener('click', handleLinkRedirect);
|
||||||
if (isEdge) rate?.setAttribute('data-href', edgeUrl);
|
if (isEdge) rateButtonElement?.setAttribute('data-href', edgeUrl);
|
||||||
else if (isChromium) rate?.setAttribute('data-href', chromeUrl);
|
else if (isChromium) rateButtonElement?.setAttribute('data-href', chromeUrl);
|
||||||
else if (isFirefox) rate?.setAttribute('data-href', firefoxUrl);
|
else if (isFirefox) rateButtonElement?.setAttribute('data-href', firefoxUrl);
|
||||||
|
|
||||||
|
const settingsButtonElement = document.getElementById('settings-button');
|
||||||
|
settingsButtonElement.addEventListener('click', handleSettingsClick);
|
||||||
|
|
||||||
translate();
|
translate();
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @async
|
* @async
|
||||||
* @description Opens a new tab
|
* @description Opens a new tab
|
||||||
* @param {MouseEvent} event
|
* @param {MouseEvent} event
|
||||||
|
* @returns {Promise<void>}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const handleLinkRedirect = async (event) => {
|
async function handleLinkRedirect(event) {
|
||||||
const { href } = event.currentTarget.dataset;
|
const { href } = event.currentTarget.dataset;
|
||||||
|
|
||||||
if (href) {
|
if (href) {
|
||||||
await chrome.tabs.create({ url: href });
|
await chrome.tabs.create({ url: href });
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @async
|
||||||
* @description Disables or enables extension on current page
|
* @description Disables or enables extension on current page
|
||||||
* @param {MouseEvent} event
|
* @param {MouseEvent} event
|
||||||
|
* @returns {Promise<void>}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const handlePowerToggle = async (event) => {
|
async function handlePowerToggle(event) {
|
||||||
state = { enabled: !state.enabled };
|
state = { enabled: !state.enabled };
|
||||||
dispatch({ hostname, state, type: 'UPDATE_STATE' });
|
dispatch({ hostname, state, type: 'SET_HOSTNAME_STATE' });
|
||||||
if (state.enabled) event.currentTarget.setAttribute('data-value', 'on');
|
if (state.enabled) event.currentTarget.setAttribute('data-value', 'on');
|
||||||
else event.currentTarget.setAttribute('data-value', 'off');
|
else event.currentTarget.setAttribute('data-value', 'off');
|
||||||
await chrome.tabs.reload({ bypassCache: true });
|
await chrome.tabs.reload({ bypassCache: true });
|
||||||
};
|
window.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description Opens options page
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
|
||||||
|
function handleSettingsClick() {
|
||||||
|
chrome.runtime.openOptionsPage();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description Applies translations to tags with i18n data attribute
|
* @description Applies translations to tags with i18n data attribute
|
||||||
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const translate = () => {
|
function translate() {
|
||||||
const nodes = document.querySelectorAll('[data-i18n]');
|
const nodes = document.querySelectorAll('[data-i18n], [data-i18n-placeholder]');
|
||||||
|
|
||||||
for (let i = nodes.length; i--; ) {
|
for (let i = nodes.length; i--; ) {
|
||||||
const node = nodes[i];
|
const node = nodes[i];
|
||||||
const { i18n } = node.dataset;
|
const { i18n, i18nPlaceholder } = node.dataset;
|
||||||
|
|
||||||
node.innerHTML = chrome.i18n.getMessage(i18n);
|
if (i18n) {
|
||||||
|
node.innerHTML = chrome.i18n.getMessage(i18n);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i18nPlaceholder) {
|
||||||
|
node.setAttribute('placeholder', chrome.i18n.getMessage(i18nPlaceholder));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description Listen to document ready
|
* @description Listen to document ready
|
||||||
|
137
packages/browser-extension/src/styles/options.css
Normal file
137
packages/browser-extension/src/styles/options.css
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
:root {
|
||||||
|
--color-error: #cc0000;
|
||||||
|
--color-primary: #3dd9eb;
|
||||||
|
--color-secondary: #34495e;
|
||||||
|
--color-success: #5cb85c;
|
||||||
|
--color-tertiary: #6b7280;
|
||||||
|
--color-transparent: transparent;
|
||||||
|
--color-warning: #ffdf00;
|
||||||
|
--color-white: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
box-sizing: border-box;
|
||||||
|
color: var(--color-tertiary);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
font-family: Inter, Arial, Helvetica, sans-serif;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
body * {
|
||||||
|
box-sizing: border-box;
|
||||||
|
font-family: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
align-items: center;
|
||||||
|
background-color: var(--color-white);
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
color: var(--color-secondary);
|
||||||
|
display: inline-flex;
|
||||||
|
gap: 4px;
|
||||||
|
outline: none;
|
||||||
|
transition: 0.4s;
|
||||||
|
}
|
||||||
|
|
||||||
|
button[data-variant='large'] {
|
||||||
|
direction: rtl;
|
||||||
|
padding: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:focus,
|
||||||
|
button:hover {
|
||||||
|
background-color: var(--color-secondary);
|
||||||
|
color: var(--color-white);
|
||||||
|
}
|
||||||
|
|
||||||
|
footer {
|
||||||
|
background-color: var(--color-secondary);
|
||||||
|
font-size: 12px;
|
||||||
|
height: 4px;
|
||||||
|
margin-top: auto;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
header {
|
||||||
|
background-color: var(--color-secondary);
|
||||||
|
color: var(--color-white);
|
||||||
|
font-size: 16px !important;
|
||||||
|
height: 48px;
|
||||||
|
}
|
||||||
|
|
||||||
|
header > div {
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
height: 100%;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin: auto 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
main input {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
background-color: var(--color-white);
|
||||||
|
border: none;
|
||||||
|
border-bottom: 1px solid var(--color-tertiary);
|
||||||
|
border-radius: 0px;
|
||||||
|
color: var(--color-secondary);
|
||||||
|
font-size: 16px;
|
||||||
|
height: 42px;
|
||||||
|
outline: none;
|
||||||
|
padding: 0px 8px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
main input::placeholder {
|
||||||
|
color: var(--color-tertiary);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
main input:focus,
|
||||||
|
main input:hover {
|
||||||
|
border-bottom: 1px solid var(--color-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
header > div,
|
||||||
|
main {
|
||||||
|
margin: 0px auto;
|
||||||
|
max-width: 768px;
|
||||||
|
padding: 16px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-group {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
gap: 4px;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#exclusion-list {
|
||||||
|
font-size: 14px;
|
||||||
|
list-style: none;
|
||||||
|
padding: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#exclusion-list > li {
|
||||||
|
align-items: center;
|
||||||
|
border-radius: 4px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 8px;
|
||||||
|
transition: 0.4s;
|
||||||
|
}
|
||||||
|
|
||||||
|
#exclusion-list > li:focus-within,
|
||||||
|
#exclusion-list > li:hover {
|
||||||
|
background-color: var(--color-secondary);
|
||||||
|
color: var(--color-white);
|
||||||
|
}
|
||||||
|
|
||||||
|
#exclusion-list > li > button {
|
||||||
|
background-color: var(--color-white);
|
||||||
|
color: var(--color-error);
|
||||||
|
padding: 4px;
|
||||||
|
}
|
@ -21,6 +21,25 @@ body * {
|
|||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
align-items: center;
|
||||||
|
background-color: var(--color-secondary);
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
color: var(--color-white);
|
||||||
|
display: inline-flex;
|
||||||
|
gap: 4px;
|
||||||
|
outline: none;
|
||||||
|
padding: 2px;
|
||||||
|
transition: 0.4s;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:focus,
|
||||||
|
button:hover {
|
||||||
|
background-color: var(--color-white);
|
||||||
|
color: var(--color-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
footer {
|
footer {
|
||||||
background-color: var(--color-secondary);
|
background-color: var(--color-secondary);
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
|
Loading…
Reference in New Issue
Block a user