Compare commits

...

26 Commits

Author SHA1 Message Date
e7afb73c48 fix(browser-extension): possible undefined 2024-10-15 11:52:09 +02:00
1352d28f83 fix(browser-extension): report cancel button clickable area 2024-10-15 11:52:09 +02:00
bd047e560b feat(web): add new issue tracking section 2024-10-15 11:52:09 +02:00
7624ec9fcf fix(browser-extension): media queries for mobile version 2024-10-15 11:52:09 +02:00
c3e7acf4f9 feat(web): update options and popup images 2024-10-15 11:52:09 +02:00
41c23ead28 fix(browser-extension): how options and popup look on mobile 2024-10-15 11:52:09 +02:00
35fec2f0fd chore(browser-extension): bump extension version 2024-10-15 11:52:09 +02:00
11d85e8d3f feat(browser-extension): minor improvement to new error extra text english translation 2024-10-15 11:52:09 +02:00
fa60a0be99 feat(browser-extension): enable report only on supported pages 2024-10-15 11:52:09 +02:00
60933d024d feat(browser-extension): handle new error cases when reporting 2024-10-15 11:52:09 +02:00
a25b060bcf feat(browser-extension): bump api version to use 2024-10-15 11:52:09 +02:00
c16edf1ee5 refactor(browser-extension): move report dialog to popup 2024-10-15 11:52:09 +02:00
fdb84959a7 fix(browser-extension): popup auto height issue 2024-10-15 11:52:09 +02:00
9d498421b5 refactor: drop old dialog stuff 2024-10-15 11:52:09 +02:00
0763d8df8a feat(api): add issues and version endpoints 2024-10-15 11:52:09 +02:00
029fa138cf feat(browser-extension): switch to warn mode after reporting an issue 2024-10-15 11:52:09 +02:00
9036060df4 fix(browser-extension): off/on performance 2024-10-15 11:52:09 +02:00
e34b2e6270 feat(browser-extension): add issue banner translations 2024-10-15 11:52:09 +02:00
8efee3509a feat(browser-extension): add request batching, issue details fetching and minor refactors to scripts 2024-10-15 11:52:09 +02:00
8afc3a99c6 feat(browser-extension): add issue banner to popup giving user some information about what's wrong and where to find the issue easily 2024-10-15 11:52:09 +02:00
fe619378dc refactor(browser-extension): assets naming 2024-10-15 11:52:09 +02:00
838266bfc7 chore(browser-extension): upgrade manifest version 2024-10-15 11:52:09 +02:00
fd1c57996b refactor: move licenses up 2024-10-15 11:51:07 +02:00
0a9e0fa3a9 docs: add resources to main readme 2024-10-15 11:46:14 +02:00
a66c4bedc7 feat(web): update links to wiki 2024-10-14 15:35:33 +02:00
d3e7c061f0 docs(browser-extension): move installation guides to wiki 2024-10-14 15:33:37 +02:00
38 changed files with 1313 additions and 1001 deletions

View File

@ -12,8 +12,25 @@
Cookie Dialog Monster is a browser extension that hides cookie consent dialogs without changing user preferences. By default, we do NOT accept cookies (except in [a few cases](https://git.wanhose.dev/wanhose/cookie-dialog-monster/src/branch/main/database.json#L248) where the pages do not function without accepting them). You can report broken sites with a single click, which will create an issue in this repository to be fixed promptly.
## Contributing
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
## License
[MIT](https://choosealicense.com/licenses/mit/)
## Repositories
- [API](/wanhose/cookie-dialog-monster/src/branch/main/packages/api)
- [Browser extension](/wanhose/cookie-dialog-monster/src/branch/main/packages/browser-extension)
- [Web](/wanhose/cookie-dialog-monster/src/branch/main/packages/web)
## Resources
- [FAQs](https://git.wanhose.dev/wanhose/cookie-dialog-monster/wiki/Welcome#faqs)
- [Guides](https://git.wanhose.dev/wanhose/cookie-dialog-monster/wiki/Welcome#guides)
- [Issues](https://git.wanhose.dev/wanhose/cookie-dialog-monster/issues)
- [Pull requests](https://git.wanhose.dev/wanhose/cookie-dialog-monster/pulls)
- [Releases](https://git.wanhose.dev/wanhose/cookie-dialog-monster/releases)
- [Wiki](https://git.wanhose.dev/wanhose/cookie-dialog-monster/wiki/Welcome)

View File

@ -20,5 +20,6 @@
"engines": {
"node": "20.x"
},
"packageManager": "yarn@4.2.1"
"packageManager": "yarn@4.2.1",
"license": "MIT"
}

View File

@ -25,11 +25,3 @@ Lints the codebase using ESLint.
### `yarn start`
Starts the API server instance in production mode.
## Contributing
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
## License
[MIT](https://choosealicense.com/licenses/mit/)

View File

@ -34,6 +34,5 @@
"engines": {
"node": "20.x"
},
"packageManager": "yarn@4.1.0",
"license": "MIT"
"packageManager": "yarn@4.2.1"
}

View File

@ -1,21 +0,0 @@
MIT License Copyright (c) 2022 wanhose
Permission is hereby
granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to the
following conditions:
The above copyright notice and this permission notice
(including the next paragraph) shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@ -1,14 +1,5 @@
# Cookie Dialog Monster Browser Extension
## Downloads
- [Chrome Web Store](https://chrome.google.com/webstore/detail/djcbfpkdhdkaflcigibkbpboflaplabg)
- [Edge Add-ons](https://microsoftedge.microsoft.com/addons/detail/hbogodfciblakeneadpcolhmfckmjcii)
- [Mozilla Firefox (.xpi)](https://www.cookie-dialog-monster.com/releases/latest.xpi)
- Advanced users or non-listed browsers ¹
¹ Scroll down to [this section](#installation-for-advanced-users-and-non-listed-browser-users) and follow the instructions to install the latest version of this extension in your browser.
## Compatibility
- All browsers based on Chromium 127+ (Blisk, Brave, Colibri, Epic Browser, Iron Browser, Vivaldi and many more)
@ -17,67 +8,12 @@
- Mozilla Firefox 126+
- Mozilla Firefox Mobile 126+
## Installation (for Mozilla Firefox users)
## Downloads
1. Start by downloading the latest `.xpi` file [from here](https://www.cookie-dialog-monster.com/releases/latest.xpi).
2. Open your Firefox browser. Depending on your browser settings, Firefox may prompt you to install the add-on automatically upon download completion. If the installation prompt appears, you can proceed with the installation directly from the prompt by clicking **Add** and skip to step 8.
3. If the automatic prompt does not appear, navigate to [about:addons](about:addons) to open the Add-ons Manager.
4. Click on the gear icon (⚙️) to open the menu.
5. Select **Install Add-on From File...** from the menu.
6. A file dialog will open. Navigate to and select the downloaded `.xpi` file.
7. A confirmation dialog will appear asking if you wish to install the add-on. Click **Add** to proceed.
8. Congratulations! You've successfully installed the latest build of this extension in Firefox.
- [Chrome Web Store](https://chrome.google.com/webstore/detail/djcbfpkdhdkaflcigibkbpboflaplabg)
- [Edge Add-ons](https://microsoftedge.microsoft.com/addons/detail/hbogodfciblakeneadpcolhmfckmjcii)
- [Mozilla Firefox (.xpi)](https://www.cookie-dialog-monster.com/releases/latest.xpi)
Optionally, if you wish to allow the extension to run in private browsing mode, find the extension in the list, click on the **Details** button, and then enable the **Allow in Private Browsing** checkbox.
## Installation
## Installation (for Mozilla Firefox Mobile users)
1. Start by downloading the latest `.xpi` file [from here](https://www.cookie-dialog-monster.com/releases/latest-mozilla-mobile.xpi).
2. Open your Firefox browser, then tap the three-dot menu icon in the bottom-right corner of the browser and click on the **Settings** option.
3. If you haven't already enabled debug mode, go to the About Firefox option and tap the Firefox logo 5 times. If you have already enabled it, skip to step 4.
4. Go back and you will see a new option **Install extension from file**, click on it.
5. A file dialog will open. Navigate to and select the downloaded `.xpi` file.
6. A confirmation dialog will appear asking if you wish to install the add-on. Click **Add** to proceed.
7. Congratulations! You've successfully installed the latest build of this extension in Firefox.
Optionally, if you wish to allow the extension to run in private browsing mode, find the extension in the list, click on the **Details** button, and then enable the **Allow in Private Browsing** checkbox.
## Installation (for advanced and non-listed browser users)
1. Start by downloading the latest zip file [from here](https://www.cookie-dialog-monster.com/releases/latest.zip).
2. Extract the downloaded zip file to a location on your local machine.
3. Open your browser's extensions page:
- For Chrome, navigate to [chrome://extensions](chrome://extensions)
- For Firefox, navigate to [about:addons](about:addons)
- For Edge, navigate to [edge://extensions](edge://extensions)
(Replace with the correct URL based on your browser)
4. Enable **Developer mode** (usually a toggle switch in the top right corner of the extensions page).
5. Click on the **Load Temporary Add-on…** button in Firefox or **Load unpacked** in other browsers.
6. A file dialog will open. Navigate to and select the extracted folder (or `manifest.json` file inside this folder if needed).
7. Congratulations! You've successfully loaded the latest build of this extension.
## Installation (only for developers)
1. Start by cloning the repository to your local machine using the command `git clone <repository-url>` or downloading it from the assets section of a release.
2. Navigate to the cloned repository's directory with `cd <repository-name>`.
3. Open your browser's extensions page:
- For Chrome, navigate to [chrome://extensions](chrome://extensions)
- For Firefox, navigate to [about:addons](about:addons)
- For Edge, navigate to [edge://extensions](edge://extensions)
(Replace with the correct URL based on your browser)
4. Enable **Developer mode** (usually a toggle switch in the top right corner of the extensions page).
5. Click on the **Load unpacked** button.
6. A file dialog will open. Navigate to and select the `packages/browser-extension/src` folder from the cloned repository.
7. Congratulations! You've successfully loaded the development build of this extension.
To ensure you're using the latest version of the extension, it's important to regularly pull the latest changes from the repository. You can do this by navigating to the repository's directory in your terminal and running the command `git pull`. This will fetch and download the latest changes from the remote repository and merge them into your local repository.
In some cases, after pulling the latest changes and rebuilding the extension, your browser may not immediately reflect the updates. This is because browsers typically cache extensions for performance reasons. To manually update the extension, navigate to your browser's extensions page. Look for a button or option to "Update" or "Reload" the extension. This forces the browser to reload the extension, ensuring it's running the latest version. Remember, this process may vary slightly depending on the browser you're using. Always refer to your browser's specific instructions for managing extensions.
## Contributing
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
## License
[MIT](https://choosealicense.com/licenses/mit/)
Follow one of [these guides](https://git.wanhose.dev/wanhose/cookie-dialog-monster/wiki/Welcome#guides).

View File

@ -16,6 +16,5 @@
"engines": {
"node": "20.x"
},
"packageManager": "yarn@4.1.0",
"license": "MIT"
"packageManager": "yarn@4.2.1"
}

View File

@ -32,6 +32,12 @@
"options_importButton": {
"message": "Liste importieren"
},
"popup_bannerIssueOpen": {
"message": "Ein Problem wurde für diese Seite gemeldet. Die Erweiterung funktioniert möglicherweise vorübergehend nicht wie erwartet. Verfolgen Sie das Problem oder fügen Sie weitere Informationen hinzu."
},
"popup_bannerIssueWontFix": {
"message": "Ein Problem wurde für diese Seite gemeldet, wird jedoch nicht behoben. Bitte beachten Sie, dass die Erweiterung auf dieser Seite möglicherweise nicht wie erwartet funktioniert. Wir empfehlen dringend, die Erweiterung über die Schaltfläche unten zu deaktivieren."
},
"popup_contributeOption": {
"message": "Zu diesem Projekt beitragen"
},
@ -47,28 +53,37 @@
"popup_rateOption": {
"message": "Bewerten Sie diese Erweiterung"
},
"reportDialog_bodyText": {
"report_bodyText": {
"message": "Bitte geben Sie in diesem Bericht keine persönlichen Informationen weiter. Wenn Sie weitere Details hinzufügen möchten, öffnen Sie das GitHub-Problem im nächsten Schritt und fügen Sie einen Kommentar hinzu."
},
"reportDialog_reasonInputError": {
"report_cancelButtonText": {
"message": "Abbrechen"
},
"report_reasonInputError": {
"message": "Bitte geben Sie einen Grund mit mindestens 10 und höchstens 1000 Zeichen ein"
},
"reportDialog_reasonInputLabel": {
"report_reasonInputLabel": {
"message": "Grund"
},
"reportDialog_reasonInputPlaceholder": {
"report_reasonInputPlaceholder": {
"message": "Popup ist erschienen"
},
"reportDialog_submitExtraText": {
"report_submitErrorExtraText": {
"message": "Es scheint, dass bereits ein Problem geöffnet ist oder als 'wontfix' markiert wurde. Bitte öffnen Sie das Problem und fügen Sie gegebenenfalls weitere Informationen hinzu, indem Sie den folgenden Button verwenden."
},
"report_submitErrorText": {
"message": "Bericht nicht gesendet?"
},
"report_submitSuccessExtraText": {
"message": "Während wir daran arbeiten, können Sie diese Website zur Ausschlussliste in den Erweiterungseinstellungen hinzufügen oder einfach die Erweiterung für diese Website deaktivieren, indem Sie auf das Erweiterungssymbol in Ihrer Browser-Symbolleiste klicken."
},
"reportDialog_submitText": {
"report_submitSuccessText": {
"message": "Bericht gesendet!"
},
"reportDialog_urlInputError": {
"report_urlInputError": {
"message": "Bitte geben Sie eine gültige URL mit höchstens 1000 Zeichen ein"
},
"reportDialog_urlInputLabel": {
"report_urlInputLabel": {
"message": "URL"
}
}

View File

@ -32,6 +32,12 @@
"options_importButton": {
"message": "Import list"
},
"popup_bannerIssueOpen": {
"message": "An issue has been reported for this page. The extension may not work as expected temporarily. Follow the issue, or add more information"
},
"popup_bannerIssueWontFix": {
"message": "An issue has been reported for this page, but it won't be fixed. Please be aware that the extension may not function as expected on this page. We highly recommend turning off the extension using the button below"
},
"popup_contributeOption": {
"message": "Contribute to this project"
},
@ -47,28 +53,37 @@
"popup_rateOption": {
"message": "Rate this extension"
},
"reportDialog_bodyText": {
"report_bodyText": {
"message": "Please, do not share any personal information in this report. If you want to add more details, open the GitHub issue in the next step and add a comment."
},
"reportDialog_reasonInputError": {
"report_cancelButtonText": {
"message": "Cancel"
},
"report_reasonInputError": {
"message": "Please enter a reason with at least 10 characters and no more than 1000 characters"
},
"reportDialog_reasonInputLabel": {
"report_reasonInputLabel": {
"message": "Reason"
},
"reportDialog_reasonInputPlaceholder": {
"report_reasonInputPlaceholder": {
"message": "Popup showed up"
},
"reportDialog_submitExtraText": {
"report_submitErrorExtraText": {
"message": "It seems that there's an issue open already, or it is marked as 'wontfix'. Please enter the issue if you want to add more information using the following button."
},
"report_submitErrorText": {
"message": "Report not sent?"
},
"report_submitSuccessExtraText": {
"message": "While we are working on this, you can add this website to the exclusion list in the extension settings or just disable the extension for this website clicking on the extension icon in your browser toolbar"
},
"reportDialog_submitText": {
"report_submitSuccessText": {
"message": "Report sent!"
},
"reportDialog_urlInputError": {
"report_urlInputError": {
"message": "Please enter a valid URL with no more than 1000 characters"
},
"reportDialog_urlInputLabel": {
"report_urlInputLabel": {
"message": "URL"
}
}

View File

@ -32,6 +32,12 @@
"options_importButton": {
"message": "Importar lista"
},
"popup_bannerIssueOpen": {
"message": "Se ha informado de un problema en esta página. La extensión puede no funcionar como se espera temporalmente. Siga el problema o agregue más información."
},
"popup_bannerIssueWontFix": {
"message": "Se ha informado de un problema en esta página, pero no se solucionará. Tenga en cuenta que la extensión puede no funcionar como se espera en esta página. Recomendamos encarecidamente desactivar la extensión utilizando el botón a continuación."
},
"popup_contributeOption": {
"message": "Contribuir a este proyecto"
},
@ -47,28 +53,37 @@
"popup_rateOption": {
"message": "Califica esta extensión"
},
"reportDialog_bodyText": {
"report_bodyText": {
"message": "Por favor, no compartas ninguna información personal en este informe. Si deseas agregar más detalles, abre el problema de GitHub en el siguiente paso y agrega un comentario."
},
"reportDialog_reasonInputError": {
"report_cancelButtonText": {
"message": "Cancelar"
},
"report_reasonInputError": {
"message": "Por favor, ingrese una razón con al menos 10 caracteres y no más de 1000 caracteres"
},
"reportDialog_reasonInputLabel": {
"report_reasonInputLabel": {
"message": "Razón"
},
"reportDialog_reasonInputPlaceholder": {
"report_reasonInputPlaceholder": {
"message": "Apareció un popup"
},
"reportDialog_submitExtraText": {
"message": "Mientras trabajamos en esto, puedes agregar este sitio web a la lista de exclusión en la configuración de la extensión o simplemente deshabilitar la extensión para este sitio web haciendo clic en el ícono de la extensión en la barra de herramientas de tu navegador."
"report_submitErrorExtraText": {
"message": "Reporte no enviado?"
},
"reportDialog_submitText": {
"message": "¡Informe enviado!"
"report_submitErrorText": {
"message": "Parece que ya hay un problema abierto o está marcado como 'no se solucionará'. Por favor, ingrese al problema para agregar más información usando el siguiente botón."
},
"reportDialog_urlInputError": {
"report_submitSuccessExtraText": {
"message": "Mientras trabajamos en esto, puedes agregar este sitio web a la lista de exclusiones en la configuración de la extensión o simplemente deshabilitar la extensión para este sitio web haciendo clic en el icono de la extensión en la barra de herramientas de tu navegador."
},
"report_submitSuccessText": {
"message": "Reporte enviado!"
},
"report_urlInputError": {
"message": "Por favor, ingrese una URL válida con no más de 1000 caracteres"
},
"reportDialog_urlInputLabel": {
"report_urlInputLabel": {
"message": "URL"
}
}

View File

@ -32,6 +32,12 @@
"options_importButton": {
"message": "Importer la liste"
},
"popup_bannerIssueOpen": {
"message": "Un problème a été signalé pour cette page. L'extension peut ne pas fonctionner comme prévu temporairement. Suivez le problème ou ajoutez plus d'informations."
},
"popup_bannerIssueWontFix": {
"message": "Un problème a été signalé pour cette page, mais il ne sera pas résolu. Veuillez noter que l'extension pourrait ne pas fonctionner comme prévu sur cette page. Nous vous recommandons vivement de désactiver l'extension en utilisant le bouton ci-dessous."
},
"popup_contributeOption": {
"message": "Contribuer à ce projet"
},
@ -47,28 +53,37 @@
"popup_rateOption": {
"message": "Évaluer cette extension"
},
"reportDialog_bodyText": {
"report_bodyText": {
"message": "Veuillez ne pas partager d'informations personnelles dans ce rapport. Si vous souhaitez ajouter plus de détails, ouvrez le problème GitHub à l'étape suivante et ajoutez un commentaire."
},
"reportDialog_reasonInputError": {
"report_cancelButtonText": {
"message": "Annuler"
},
"report_reasonInputError": {
"message": "Veuillez entrer une raison d'au moins 10 caractères et de pas plus de 1000 caractères"
},
"reportDialog_reasonInputLabel": {
"report_reasonInputLabel": {
"message": "Raison"
},
"reportDialog_reasonInputPlaceholder": {
"report_reasonInputPlaceholder": {
"message": "Le popup est apparu"
},
"reportDialog_submitExtraText": {
"report_submitErrorExtraText": {
"message": "Il semble qu'un problème soit déjà ouvert ou marqué comme 'ne sera pas corrigé'. Veuillez entrer dans le problème pour ajouter plus d'informations en utilisant le bouton suivant."
},
"report_submitErrorText": {
"message": "Rapport non envoyé?"
},
"report_submitSuccessExtraText": {
"message": "Pendant que nous travaillons sur ce point, vous pouvez ajouter ce site web à la liste d'exclusion dans les paramètres de l'extension ou simplement désactiver l'extension pour ce site web en cliquant sur l'icône de l'extension dans la barre d'outils de votre navigateur."
},
"reportDialog_submitText": {
"report_submitSuccessText": {
"message": "Rapport envoyé!"
},
"reportDialog_urlInputError": {
"report_urlInputError": {
"message": "Veuillez entrer une URL valide de pas plus de 1000 caractères"
},
"reportDialog_urlInputLabel": {
"report_urlInputLabel": {
"message": "URL"
}
}

View File

@ -32,6 +32,12 @@
"options_importButton": {
"message": "Importa lista"
},
"popup_bannerIssueOpen": {
"message": "È stato segnalato un problema per questa pagina. L'estensione potrebbe non funzionare temporaneamente come previsto. Segui il problema o aggiungi ulteriori informazioni."
},
"popup_bannerIssueWontFix": {
"message": "È stato segnalato un problema per questa pagina, ma non verrà risolto. Si prega di notare che l'estensione potrebbe non funzionare come previsto su questa pagina. Si consiglia vivamente di disattivare l'estensione utilizzando il pulsante qui sotto."
},
"popup_contributeOption": {
"message": "Contribuisci a questo progetto"
},
@ -47,28 +53,37 @@
"popup_rateOption": {
"message": "Valuta questa estensione"
},
"reportDialog_bodyText": {
"report_bodyText": {
"message": "Per favore, non condividere informazioni personali in questo rapporto. Se vuoi aggiungere più dettagli, apri il problema su GitHub nel passaggio successivo e aggiungi un commento."
},
"reportDialog_reasonInputError": {
"report_cancelButtonText": {
"message": "Annulla"
},
"report_reasonInputError": {
"message": "Inserisci una motivazione con almeno 10 caratteri e non più di 1000 caratteri"
},
"reportDialog_reasonInputLabel": {
"report_reasonInputLabel": {
"message": "Motivo"
},
"reportDialog_reasonInputPlaceholder": {
"report_reasonInputPlaceholder": {
"message": "Popup apparso"
},
"reportDialog_submitExtraText": {
"report_submitErrorExtraText": {
"message": "Sembra che ci sia già un problema aperto o contrassegnato come 'non risolvibile'. Per favore, entra nel problema per aggiungere ulteriori informazioni usando il pulsante seguente."
},
"report_submitErrorText": {
"message": "Segnalazione non inviata?"
},
"report_submitSuccessExtraText": {
"message": "Mentre lavoriamo su questo, puoi aggiungere questo sito web alla lista di esclusione nelle impostazioni dell'estensione o semplicemente disattivare l'estensione per questo sito web cliccando sull'icona dell'estensione nella barra degli strumenti del browser."
},
"reportDialog_submitText": {
"report_submitSuccessText": {
"message": "Rapporto inviato!"
},
"reportDialog_urlInputError": {
"report_urlInputError": {
"message": "Inserisci un URL valido con non più di 1000 caratteri"
},
"reportDialog_urlInputLabel": {
"report_urlInputLabel": {
"message": "URL"
}
}

View File

@ -32,6 +32,12 @@
"options_importButton": {
"message": "Importuj listę"
},
"popup_bannerIssueOpen": {
"message": "Zgłoszono problem z tą stroną. Rozszerzenie może tymczasowo nie działać zgodnie z oczekiwaniami. Śledź problem lub dodaj więcej informacji."
},
"popup_bannerIssueWontFix": {
"message": "Zgłoszono problem z tą stroną, ale nie zostanie on naprawiony. Należy pamiętać, że rozszerzenie może nie działać zgodnie z oczekiwaniami na tej stronie. Zdecydowanie zalecamy wyłączenie rozszerzenia za pomocą poniższego przycisku."
},
"popup_contributeOption": {
"message": "Wesprzyj ten projekt"
},
@ -47,28 +53,37 @@
"popup_rateOption": {
"message": "Oceń to rozszerzenie"
},
"reportDialog_bodyText": {
"report_bodyText": {
"message": "Prosimy, nie udostępniaj żadnych danych osobowych w tym raporcie. Jeśli chcesz dodać więcej szczegółów, otwórz zgłoszenie na GitHub w następnym kroku i dodaj komentarz."
},
"reportDialog_reasonInputError": {
"report_cancelButtonText": {
"message": "Anuluj"
},
"report_reasonInputError": {
"message": "Proszę podać powód zawierający co najmniej 10 znaków i nie więcej niż 1000 znaków"
},
"reportDialog_reasonInputLabel": {
"report_reasonInputLabel": {
"message": "Powód"
},
"reportDialog_reasonInputPlaceholder": {
"report_reasonInputPlaceholder": {
"message": "Pojawił się popup"
},
"reportDialog_submitExtraText": {
"report_submitErrorExtraText": {
"message": "Wygląda na to, że istnieje już otwarte zgłoszenie lub zostało oznaczone jako 'nie do rozwiązania'. Wprowadź zgłoszenie, aby dodać więcej informacji, używając poniższego przycisku."
},
"report_submitErrorText": {
"message": "Raport nie został wysłany?"
},
"report_submitSuccessExtraText": {
"message": "Podczas gdy nad tym pracujemy, możesz dodać tę stronę do listy wykluczeń w ustawieniach rozszerzenia lub po prostu wyłączyć rozszerzenie dla tej strony, klikając ikonę rozszerzenia na pasku narzędzi przeglądarki."
},
"reportDialog_submitText": {
"report_submitSuccessText": {
"message": "Zgłoszenie wysłane!"
},
"reportDialog_urlInputError": {
"report_urlInputError": {
"message": "Proszę wprowadzić prawidłowy URL zawierający nie więcej niż 1000 znaków"
},
"reportDialog_urlInputLabel": {
"report_urlInputLabel": {
"message": "URL"
}
}

View File

@ -32,6 +32,12 @@
"options_importButton": {
"message": "Importar lista"
},
"popup_bannerIssueOpen": {
"message": "Um problema foi relatado para esta página. A extensão pode não funcionar conforme o esperado temporariamente. Acompanhe o problema ou adicione mais informações."
},
"popup_bannerIssueWontFix": {
"message": "Um problema foi relatado para esta página, mas não será corrigido. Esteja ciente de que a extensão pode não funcionar conforme o esperado nesta página. Recomendamos desativar a extensão usando o botão abaixo."
},
"popup_contributeOption": {
"message": "Contribuir para este projeto"
},
@ -47,28 +53,37 @@
"popup_rateOption": {
"message": "Avalie esta extensão"
},
"reportDialog_bodyText": {
"report_bodyText": {
"message": "Por favor, não compartilhe nenhuma informação pessoal neste relatório. Se você quiser adicionar mais detalhes, abra o problema no GitHub na próxima etapa e adicione um comentário."
},
"reportDialog_reasonInputError": {
"report_cancelButtonText": {
"message": "Cancelar"
},
"report_reasonInputError": {
"message": "Por favor, insira um motivo com pelo menos 10 caracteres e no máximo 1000 caracteres"
},
"reportDialog_reasonInputLabel": {
"report_reasonInputLabel": {
"message": "Motivo"
},
"reportDialog_reasonInputPlaceholder": {
"report_reasonInputPlaceholder": {
"message": "Popup apareceu"
},
"reportDialog_submitExtraText": {
"report_submitErrorExtraText": {
"message": "Parece que já existe um problema aberto ou marcado como 'não corrigido'. Por favor, acesse o problema para adicionar mais informações usando o botão a seguir."
},
"report_submitErrorText": {
"message": "Relatório não enviado?"
},
"report_submitSuccessExtraText": {
"message": "Enquanto estamos trabalhando nisso, você pode adicionar este site à lista de exclusão nas configurações da extensão ou simplesmente desativar a extensão para este site clicando no ícone da extensão na barra de ferramentas do navegador."
},
"reportDialog_submitText": {
"report_submitSuccessText": {
"message": "Relatório enviado!"
},
"reportDialog_urlInputError": {
"report_urlInputError": {
"message": "Por favor, insira uma URL válida com no máximo 1000 caracteres"
},
"reportDialog_urlInputLabel": {
"report_urlInputLabel": {
"message": "URL"
}
}

View File

@ -32,6 +32,12 @@
"options_importButton": {
"message": "Importar lista"
},
"popup_bannerIssueOpen": {
"message": "Foi relatado um problema para esta página. A extensão pode não funcionar conforme o esperado temporariamente. Siga o problema ou adicione mais informações."
},
"popup_bannerIssueWontFix": {
"message": "Foi relatado um problema para esta página, mas não será resolvido. Esteja ciente de que a extensão pode não funcionar conforme o esperado nesta página. Recomendamos desativar a extensão usando o botão abaixo."
},
"popup_contributeOption": {
"message": "Contribuir para este projeto"
},
@ -47,28 +53,37 @@
"popup_rateOption": {
"message": "Avalie esta extensão"
},
"reportDialog_bodyText": {
"report_bodyText": {
"message": "Por favor, não partilhe nenhuma informação pessoal neste relatório. Se quiser adicionar mais detalhes, abra o problema no GitHub na próxima etapa e adicione um comentário."
},
"reportDialog_reasonInputError": {
"report_cancelButtonText": {
"message": "Cancelar"
},
"report_reasonInputError": {
"message": "Por favor, insira um motivo com pelo menos 10 caracteres e no máximo 1000 caracteres"
},
"reportDialog_reasonInputLabel": {
"report_reasonInputLabel": {
"message": "Motivo"
},
"reportDialog_reasonInputPlaceholder": {
"report_reasonInputPlaceholder": {
"message": "Popup apareceu"
},
"reportDialog_submitExtraText": {
"report_submitErrorExtraText": {
"message": "Parece que já existe um problema aberto ou marcado como 'não corrigido'. Por favor, aceda ao problema para adicionar mais informações usando o botão seguinte."
},
"report_submitErrorText": {
"message": "Relatório não enviado?"
},
"report_submitSuccessExtraText": {
"message": "Enquanto trabalhamos nisso, pode adicionar este site à lista de exclusão nas definições da extensão ou simplesmente desativar a extensão para este site clicando no ícone da extensão na barra de ferramentas do navegador."
},
"reportDialog_submitText": {
"report_submitSuccessText": {
"message": "Relatório enviado!"
},
"reportDialog_urlInputError": {
"report_urlInputError": {
"message": "Por favor, insira uma URL válida com no máximo 1000 caracteres"
},
"reportDialog_urlInputLabel": {
"report_urlInputLabel": {
"message": "URL"
}
}

View File

@ -32,6 +32,12 @@
"options_importButton": {
"message": "Importă lista"
},
"popup_bannerIssueOpen": {
"message": "A fost raportată o problemă pentru această pagină. Extensia poate să nu funcționeze temporar conform așteptărilor. Urmăriți problema sau adăugați mai multe informații."
},
"popup_bannerIssueWontFix": {
"message": "A fost raportată o problemă pentru această pagină, dar nu va fi rezolvată. Rețineți că extensia poate să nu funcționeze conform așteptărilor pe această pagină. Vă recomandăm cu insistență să dezactivați extensia folosind butonul de mai jos."
},
"popup_contributeOption": {
"message": "Contribuie la acest proiect"
},
@ -47,28 +53,37 @@
"popup_rateOption": {
"message": "Evaluează această extensie"
},
"reportDialog_bodyText": {
"report_bodyText": {
"message": "Te rugăm să nu împărtășești informații personale în acest raport. Dacă dorești să adaugi mai multe detalii, deschide problema GitHub în pasul următor și adaugă un comentariu."
},
"reportDialog_reasonInputError": {
"report_cancelButtonText": {
"message": "Anulează"
},
"report_reasonInputError": {
"message": "Vă rugăm să introduceți un motiv cu cel puțin 10 caractere și maximum 1000 de caractere"
},
"reportDialog_reasonInputLabel": {
"report_reasonInputLabel": {
"message": "Motiv"
},
"reportDialog_reasonInputPlaceholder": {
"report_reasonInputPlaceholder": {
"message": "A apărut un popup"
},
"reportDialog_submitExtraText": {
"report_submitErrorExtraText": {
"message": "Se pare că există deja o problemă deschisă sau marcată ca 'nu va fi rezolvată'. Vă rugăm să intrați în problemă pentru a adăuga mai multe informații folosind butonul de mai jos."
},
"report_submitErrorText": {
"message": "Raportul nu a fost trimis?"
},
"report_submitSuccessExtraText": {
"message": "În timp ce lucrăm la acest aspect, poți adăuga acest site web la lista de excludere din setările extensiei sau poți dezactiva extensia pentru acest site web făcând clic pe pictograma extensiei din bara de instrumente a browserului."
},
"reportDialog_submitText": {
"report_submitSuccessText": {
"message": "Raport trimis!"
},
"reportDialog_urlInputError": {
"report_urlInputError": {
"message": "Vă rugăm să introduceți o adresă URL validă cu maximum 1000 de caractere"
},
"reportDialog_urlInputLabel": {
"report_urlInputLabel": {
"message": "URL"
}
}

View File

@ -32,6 +32,12 @@
"options_importButton": {
"message": "Импорт списка"
},
"popup_bannerIssueOpen": {
"message": "Для этой страницы было сообщено о проблеме. Расширение может временно не работать должным образом. Следите за проблемой или добавьте дополнительную информацию."
},
"popup_bannerIssueWontFix": {
"message": "Для этой страницы было сообщено о проблеме, но она не будет исправлена. Обратите внимание, что расширение может работать некорректно на этой странице. Мы настоятельно рекомендуем отключить расширение, используя кнопку ниже."
},
"popup_contributeOption": {
"message": "Содействовать этому проекту"
},
@ -47,28 +53,37 @@
"popup_rateOption": {
"message": "Оцените это расширение"
},
"reportDialog_bodyText": {
"report_bodyText": {
"message": "Пожалуйста, не делитесь личной информацией в этом отчете. Если вы хотите добавить больше деталей, откройте вопрос на GitHub на следующем шаге и добавьте комментарий."
},
"reportDialog_reasonInputError": {
"report_cancelButtonText": {
"message": "Отмена"
},
"report_reasonInputError": {
"message": "Пожалуйста, введите причину длиной не менее 10 и не более 1000 символов"
},
"reportDialog_reasonInputLabel": {
"report_reasonInputLabel": {
"message": "Причина"
},
"reportDialog_reasonInputPlaceholder": {
"report_reasonInputPlaceholder": {
"message": "Появилось всплывающее окно"
},
"reportDialog_submitExtraText": {
"report_submitErrorExtraText": {
"message": "Похоже, что уже существует открытая проблема или она помечена как 'не будет исправлено'. Пожалуйста, войдите в проблему, чтобы добавить больше информации, используя следующую кнопку."
},
"report_submitErrorText": {
"message": "Отчет не отправлен?"
},
"report_submitSuccessExtraText": {
"message": "Пока мы работаем над этим, вы можете добавить этот сайт в список исключений в настройках расширения или просто отключить расширение для этого сайта, нажав на значок расширения на панели инструментов вашего браузера."
},
"reportDialog_submitText": {
"report_submitSuccessText": {
"message": "Отчет отправлен!"
},
"reportDialog_urlInputError": {
"report_urlInputError": {
"message": "Пожалуйста, введите корректный URL длиной не более 1000 символов"
},
"reportDialog_urlInputLabel": {
"report_urlInputLabel": {
"message": "URL"
}
}

View File

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -1,7 +1,7 @@
{
"manifest_version": 3,
"name": "Cookie Dialog Monster",
"version": "7.3.2",
"version": "8.0.0",
"default_locale": "en",
"description": "__MSG_appDesc__",
"icons": {
@ -10,7 +10,7 @@
"128": "assets/icons/128.png"
},
"action": {
"default_icon": "assets/icons/disabled.png",
"default_icon": "assets/icons/off.png",
"default_title": "Cookie Dialog Monster"
},
"options_page": "options.html",
@ -51,7 +51,7 @@
"*://translate.google.it/*",
"*://www.cookie-dialog-monster.com/*"
],
"js": ["scripts/content.js", "scripts/dialog.js"],
"js": ["scripts/content.js"],
"matches": ["http://*/*", "https://*/*"],
"run_at": "document_start"
}

View File

@ -1,6 +1,8 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Cookie Dialog Monster > Exclusion List</title>
<link rel="stylesheet" href="/styles/reset.css" />
<link rel="stylesheet" href="/styles/options.css" />

View File

@ -1,6 +1,8 @@
<!doctype html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="/styles/reset.css" />
<link rel="stylesheet" href="/styles/popup.css" />
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Inter" />
@ -9,6 +11,22 @@
<body>
<header>
<h1 class="header-title">Cookie Dialog Monster</h1>
<div class="header-actions">
<button disabled id="report-button">
<svg
fill="none"
height="18"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
stroke="currentColor"
viewBox="0 0 24 24"
width="18"
>
<path d="M4 15s1-1 4-1 5 2 8 2 4-1 4-1V3s-1 1-4 1-5-2-8-2-4 1-4 1z"></path>
<line x1="4" y1="22" x2="4" y2="15"></line>
</svg>
</button>
<button id="settings-button">
<svg
aria-hidden="true"
@ -27,8 +45,29 @@
/>
</svg>
</button>
</div>
</header>
<main>
<p aria-hidden="true" class="banner" id="issue-banner" role="alert">
<span id="issue-banner-text"></span>
<a aria-label="GitHub" id="issue-banner-url" target="_blank">
<svg
fill="none"
height="12"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
stroke="currentColor"
viewBox="0 0 24 24"
width="12"
>
<path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path>
<polyline points="15 3 21 3 21 9"></polyline>
<line x1="10" y1="14" x2="21" y2="3"></line>
</svg>
</a>
</p>
<div class="content">
<popup-button id="power-option" role="button" tabindex="0">
<svg
aria-hidden="true"
@ -46,7 +85,12 @@
</svg>
<span id="host"></span>
</popup-button>
<popup-button data-href="mailto:hello@wanhose.dev" id="help-option" role="link" tabindex="0">
<popup-button
data-href="mailto:hello@wanhose.dev"
id="help-option"
role="link"
tabindex="0"
>
<svg
aria-hidden="true"
fill="none"
@ -129,7 +173,9 @@
>
<polyline points="1 4 1 10 7 10"></polyline>
<polyline points="23 20 23 14 17 14"></polyline>
<path d="M20.49 9A9 9 0 0 0 5.64 5.64L1 10m22 4l-4.64 4.36A9 9 0 0 1 3.51 15"></path>
<path
d="M20.49 9A9 9 0 0 0 5.64 5.64L1 10m22 4l-4.64 4.36A9 9 0 0 1 3.51 15"
></path>
</svg>
<svg
aria-hidden="true"
@ -152,6 +198,101 @@
<span id="extension-version"></span>
</popup-data>
</popup-data-container>
</div>
<div class="report" style="display: none">
<div class="report-form-view">
<div class="report-body-text" data-i18n="report_bodyText"></div>
<div class="report-form">
<div class="report-input-group">
<div class="report-input-label" id="report-label-url">
<span data-i18n="report_urlInputLabel"></span>
<span class="report-input-label-required">*</span>
</div>
<input
aria-labelledby="report-label-url"
aria-required="true"
class="report-input"
id="report-input-url"
/>
<div
class="report-input-error"
data-i18n="report_urlInputError"
id="report-input-url-error"
></div>
</div>
<div class="report-input-group">
<div class="report-input-label" id="report-label-reason">
<span data-i18n="report_reasonInputLabel"></span>
<span class="report-input-label-required">*</span>
</div>
<textarea
aria-labelledby="report-label-reason"
aria-required="true"
class="report-input"
data-i18n="report_reasonInputPlaceholder"
id="report-input-reason"
rows="4"
></textarea>
<div
class="report-input-error"
data-i18n="report_reasonInputError"
id="report-input-reason-error"
></div>
</div>
<div class="report-buttons">
<button class="report-submit-button" data-i18n="contextMenu_reportOption"></button>
<button class="report-cancel-button" data-i18n="report_cancelButtonText"></button>
</div>
</div>
</div>
<div class="report-submit-error-view" hidden>
<svg
fill="none"
height="48"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
stroke="var(--color-error)"
viewBox="0 0 24 24"
width="48"
>
<circle cx="12" cy="12" r="10"></circle>
<line x1="12" y1="8" x2="12" y2="12"></line>
<line x1="12" y1="16" x2="12.01" y2="16"></line>
</svg>
<div class="report-submit-text" data-i18n="report_submitErrorText"></div>
<div class="report-submit-extra-text" data-i18n="report_submitErrorExtraText"></div>
<div
class="report-issue-button"
data-i18n="contextMenu_issueOption"
role="button"
tabindex="0"
></div>
</div>
<div class="report-submit-success-view" hidden>
<svg
fill="none"
height="48"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
stroke="var(--color-success)"
viewBox="0 0 24 24"
width="48"
>
<path d="M22 11.08V12a10 10 0 1 1-5.93-9.14" />
<polyline points="22 4 12 14.01 9 11.01" />
</svg>
<div class="report-submit-text" data-i18n="report_submitSuccessText"></div>
<div class="report-submit-extra-text" data-i18n="report_submitSuccessExtraText"></div>
<div
class="report-issue-button"
data-i18n="contextMenu_issueOption"
role="button"
tabindex="0"
></div>
</div>
</div>
</main>
<footer></footer>
</body>

View File

@ -1,12 +1,54 @@
/**
* @typedef {Object} ExtensionIssue
* @property {number} [expiresIn]
* @property {string[]} [flags]
* @property {string} [url]
*/
/**
* @typedef {Object} ExtensionState
* @property {ExtensionIssue} [issue]
* @property {boolean} on
*/
if (typeof browser === 'undefined') {
browser = chrome;
}
/**
* @description Class for request batching
*/
class RequestManager {
constructor() {
this.requests = new Map(); // Store ongoing requests
}
/**
* @description Fetch wrapper to play with the request map
* @param {string} input
* @param {RequestInit} [init]
* @returns {Promise<any>}
*/
fetchData(input, init) {
if (this.requests.has(input)) {
return this.requests.get(input);
}
const promise = fetch(input, init)
.then((response) => response.json())
.finally(() => this.requests.delete(input));
this.requests.set(input, promise);
return promise;
}
}
/**
* @description API URL
* @type {string}
*/
const apiUrl = 'https://api.cookie-dialog-monster.com/rest/v4';
const apiUrl = 'https://api.cookie-dialog-monster.com/rest/v5';
/**
* @description Context menu identifier
@ -20,6 +62,11 @@ const extensionMenuItemId = 'CDM-MENU';
*/
const reportMenuItemId = 'CDM-REPORT';
/**
* @description Request manager instance
*/
const requestManager = new RequestManager();
/**
* @description Context menu identifier
* @type {string}
@ -32,9 +79,15 @@ const settingsMenuItemId = 'CDM-SETTINGS';
*/
const script = browser.scripting;
/**
* @description Default value for extension state
* @type {ExtensionState}
*/
const stateByDefault = { issue: { expiresIn: 0 }, on: true };
/**
* @description The storage to use
* @type {browser.storage.LocalStorageArea}
* @type {browser.storage.StorageArea}
*/
const storage = browser.storage.local;
@ -44,7 +97,44 @@ const storage = browser.storage.local;
const suppressLastError = () => void browser.runtime.lastError;
/**
* @description Calculate current hostname
* @async
* @description Enable extension icon
* @param {number} tabId
* @returns {Promise<void>}
*/
async function enableIcon(hostname, tabId) {
const state = await getState(hostname);
const path = state.issue?.url ? '/assets/icons/warn.png' : '/assets/icons/on.png';
await browser.action.setIcon({ path, tabId }, suppressLastError);
}
/**
* @async
* @description Get database
* @returns {Promise<Object>}
*/
async function getData() {
const { data } = await storage.get('data');
if (!data) {
return await refreshData();
}
return data;
}
/**
* @async
* @description Disable report context menu option
* @returns {Promise<void>}
*/
async function disableReport() {
return browser.contextMenus.update(reportMenuItemId, { enabled: false });
}
/**
* @description Get current hostname
* @param {string} url
* @returns {string}
*/
@ -52,6 +142,33 @@ function getHostname(url) {
return new URL(url).hostname.split('.').slice(-3).join('.').replace('www.', '');
}
/**
* @async
* @description Get current active tab
* @returns {Promise<browser.tabs.Tab>}
*/
async function getTab() {
const tabs = await browser.tabs.query({ active: true, currentWindow: true });
return tabs[0];
}
/**
* @async
* @description Get state for the given hostname
* @param {string} hostname
* @returns {Promise<ExtensionState>}
*/
async function getState(hostname) {
const { [hostname]: state = stateByDefault } = await storage.get(hostname);
if ((state.issue && Date.now() > state.issue.expiresIn) || !state.issue?.expiresIn) {
state.issue = await refreshIssue(hostname);
}
return { ...stateByDefault, ...state };
}
/**
* @description Format number to avoid errors
* @param {number} [value]
@ -81,32 +198,57 @@ function matchToPattern(match) {
}
/**
* @async
* @description Refresh data
* @param {void?} callback
* @returns {void}
* @returns {Promise<void>}
*/
function refreshData(callback) {
async function refreshData() {
try {
fetch(`${apiUrl}/data/`).then((result) => {
result.json().then(({ data }) => {
storage.set({ data }, suppressLastError);
callback?.(data);
});
});
const { data } = await requestManager.fetchData(`${apiUrl}/data/`);
await updateStore('data', data);
return data;
} catch {
refreshData(callback);
return await refreshData();
}
}
/**
* @async
* @description Report active tab URL
* @description Refresh issues for the given hostname
* @param {string} hostname
* @returns {Promise<ExtensionIssue | undefined>}
*/
async function refreshIssue(hostname) {
try {
const { data } = await requestManager.fetchData(`${apiUrl}/issues/${hostname}`);
if (Object.keys(data).length === 0) {
await updateStore(hostname, { issue: { expiresIn: Date.now() + 8 * 60 * 60 * 1000 } });
return undefined;
}
const issue = { expiresIn: Date.now() + 4 * 60 * 60 * 1000, flags: data.flags, url: data.url };
await updateStore(hostname, { issue });
return data;
} catch {
return await refreshData();
}
}
/**
* @async
* @description Report given page
* @param {any} message
* @param {browser.tabs.Tab} tab
* @param {void?} callback
* @returns {void}
* @returns {Promise<void>}
*/
async function report(message, tab, callback) {
async function report(message) {
try {
const reason = message.reason;
const url = message.url;
@ -114,25 +256,36 @@ async function report(message, tab, callback) {
const version = browser.runtime.getManifest().version;
const body = JSON.stringify({ reason, url, userAgent, version });
const headers = { 'Cache-Control': 'no-cache', 'Content-type': 'application/json' };
const requestInit = { body, headers, method: 'POST' };
const response = await fetch(`${apiUrl}/report/`, { body, headers, method: 'POST' });
callback?.((await response.json()).data);
return await requestManager.fetchData(`${apiUrl}/report/`, requestInit);
} catch {
console.error("Can't send report");
}
}
/**
* @async
* @description Update extension store for a given key
* @param {string} [key]
* @param {Object} value
* @returns {Promise<void>}
*/
async function updateStore(key, value) {
if (key) {
const { [key]: prev } = await storage.get(key);
await storage.set({ [key]: { ...prev, ...value } }, suppressLastError);
}
}
/**
* @description Listen to context menus clicked
*/
browser.contextMenus.onClicked.addListener((info, tab) => {
const tabId = tab?.id;
browser.contextMenus.onClicked.addListener((info) => {
switch (info.menuItemId) {
case reportMenuItemId:
if (tabId !== undefined) {
browser.tabs.sendMessage(tabId, { type: 'SHOW_REPORT_DIALOG' }, suppressLastError);
}
browser.action.openPopup();
break;
case settingsMenuItemId:
browser.runtime.openOptionsPage();
@ -151,14 +304,18 @@ browser.runtime.onMessage.addListener((message, sender, callback) => {
const tabId = sender.tab?.id;
switch (message.type) {
case 'DISABLE_REPORT':
if (isPage && tabId !== undefined) disableReport();
break;
case 'DISABLE_ICON':
if (isPage && tabId !== undefined) {
browser.action.setIcon({ path: '/assets/icons/disabled.png', tabId }, suppressLastError);
browser.action.setIcon({ path: '/assets/icons/off.png', tabId }, suppressLastError);
}
break;
case 'ENABLE_ICON':
if (isPage && tabId !== undefined) {
browser.action.setIcon({ path: '/assets/icons/enabled.png', tabId }, suppressLastError);
enableIcon(hostname, tabId).then(callback);
return true;
}
break;
case 'ENABLE_POPUP':
@ -166,59 +323,47 @@ browser.runtime.onMessage.addListener((message, sender, callback) => {
browser.action.setPopup({ popup: '/popup.html', tabId }, suppressLastError);
}
break;
case 'ENABLE_REPORT':
if (isPage && tabId !== undefined) {
browser.contextMenus.update(reportMenuItemId, { enabled: true });
}
break;
case 'GET_DATA':
storage.get('data', ({ data }) => {
if (data) callback(data);
else refreshData(callback);
});
getData().then(callback);
return true;
case 'GET_EXCLUSION_LIST':
storage.get(null, (exclusions) => {
const exclusionList = Object.entries(exclusions || {}).flatMap((exclusion) =>
exclusion[0] !== 'data' && !exclusion[1]?.enabled ? [exclusion[0]] : []
);
const exclusionList = Object.entries(exclusions || {}).flatMap((exclusion) => {
return exclusion[0] !== 'data' && exclusion[1].on === false ? [exclusion[0]] : [];
});
callback(exclusionList);
});
return true;
case 'GET_HOSTNAME_STATE':
case 'GET_STATE':
if (hostname) {
storage.get(hostname, (state) => {
callback(state[hostname] ?? { enabled: true });
});
getState(hostname).then(callback);
return true;
}
break;
case 'GET_TAB':
browser.tabs.query({ active: true, currentWindow: true }, (tabs) => {
callback(tabs[0]);
});
getTab().then(callback);
return true;
case 'INSERT_DIALOG_CSS':
if (isPage && tabId !== undefined) {
script.insertCSS({ files: ['styles/dialog.css'], target: { tabId } });
}
break;
case 'REFRESH_DATA':
refreshData(callback);
refreshData().then(callback);
return true;
case 'REPORT':
if (tabId !== undefined) {
report(message, sender.tab, callback);
report(message).then(callback);
return true;
}
break;
case 'SET_BADGE':
case 'UPDATE_BADGE':
if (isPage && tabId !== undefined) {
browser.action.setBadgeBackgroundColor({ color: '#6b7280' });
browser.action.setBadgeText({ tabId, text: formatNumber(message.value) });
}
break;
case 'SET_HOSTNAME_STATE':
if (hostname) {
if (message.state.enabled === false) storage.set({ [hostname]: message.state });
else storage.remove(hostname);
}
break;
case 'UPDATE_STORE':
updateStore(hostname, message.state).then(callback);
return true;
default:
break;
}
@ -227,7 +372,7 @@ browser.runtime.onMessage.addListener((message, sender, callback) => {
/**
* @description Listens to extension installed
*/
browser.runtime.onInstalled.addListener(() => {
browser.runtime.onInstalled.addListener((details) => {
const documentUrlPatterns = browser.runtime.getManifest().content_scripts[0].matches;
browser.contextMenus.create(
@ -253,12 +398,24 @@ browser.runtime.onInstalled.addListener(() => {
{
contexts: ['all'],
documentUrlPatterns,
enabled: false,
id: reportMenuItemId,
parentId: extensionMenuItemId,
title: browser.i18n.getMessage('contextMenu_reportOption'),
},
suppressLastError
);
if (details.reason === 'update') {
storage.remove('updateAvailable');
}
});
/**
* @description Listen to available updates
*/
browser.runtime.onUpdateAvailable.addListener((details) => {
storage.set({ updateAvailable: details.version }, suppressLastError);
});
/**
@ -268,6 +425,13 @@ browser.runtime.onStartup.addListener(() => {
refreshData();
});
/**
* @description Listen to tab changes
*/
browser.tabs.onActivated.addListener(() => {
disableReport();
});
/**
* @description Listen to the moment before a request is made to apply the rules
* @returns {Promise<void>}
@ -285,8 +449,9 @@ browser.webRequest.onBeforeRequest.addListener(
return;
}
const data = await getData();
const hostname = getHostname(url);
const { data, [hostname]: state = { enabled: true } } = await storage.get(['data', hostname]);
const state = await getState(hostname);
if (data?.rules?.length) {
const rules = data.rules.map((rule) => ({
@ -295,7 +460,7 @@ browser.webRequest.onBeforeRequest.addListener(
}));
await browser.declarativeNetRequest.updateSessionRules({
addRules: state.enabled ? rules : undefined,
addRules: state.on ? rules : undefined,
removeRuleIds: data.rules.map((rule) => rule.id),
});
}
@ -313,9 +478,9 @@ browser.webRequest.onErrorOccurred.addListener(
if (error === 'net::ERR_BLOCKED_BY_CLIENT' && tabId > -1) {
const hostname = getHostname(url);
const { [hostname]: state = { enabled: true } } = await storage.get(hostname);
const state = await getState(hostname);
if (state.enabled) {
if (state.on) {
await browser.tabs.sendMessage(tabId, { type: 'INCREASE_ACTIONS_COUNT' });
}
}

View File

@ -6,6 +6,11 @@
* @property {{ backdrops: string[], classes: string[], containers: string[], selectors: string[] }} tokens
*/
/**
* @typedef {Object} ContentState
* @property {boolean} on
*/
/**
* @typedef {Object} Fix
* @property {string} action
@ -91,9 +96,9 @@ const seen = new Set();
/**
* @description Extension state
* @type {{ enabled: boolean }}
* @type {ContentState}
*/
let state = { enabled: true };
let state = { on: true };
/**
* @description Clean DOM
@ -115,8 +120,8 @@ function clean(elements, skipMatch) {
if (element instanceof HTMLDialogElement) element.close();
hide(element);
actions.add(new Date().getTime().toString());
dispatch({ type: 'SET_BADGE', value: actions.size });
actions.add(`${Date.now()}`);
dispatch({ type: 'UPDATE_BADGE', value: actions.size });
}
seen.add(element);
@ -295,7 +300,7 @@ function fix() {
for (const backdrop of backdrops) {
if (backdrop.children.length === 0 && !seen.has(backdrop)) {
actions.add(new Date().getTime().toString());
actions.add(`${Date.now()}`);
seen.add(backdrop);
hide(backdrop);
}
@ -366,7 +371,7 @@ function fix() {
t4Wrapper.removeAttribute('inert');
}
dispatch({ type: 'SET_BADGE', value: actions.size });
dispatch({ type: 'UPDATE_BADGE', value: actions.size });
}
/**
@ -390,7 +395,7 @@ function hide(element) {
function run(params = {}) {
const { containers, elements, skipMatch } = params;
if (document.body?.children.length && state.enabled && tokens.selectors.length) {
if (document.body?.children.length && state.on && tokens.selectors.length) {
fix();
if (elements?.length) {
@ -409,10 +414,10 @@ function run(params = {}) {
* @param {SetUpParams} [params]
*/
async function setUp(params = {}) {
state = (await dispatch({ hostname, type: 'GET_HOSTNAME_STATE' })) ?? state;
state = await dispatch({ hostname, type: 'GET_STATE' });
dispatch({ type: 'ENABLE_POPUP' });
if (state.enabled) {
if (state.on) {
const data = await dispatch({ hostname, type: 'GET_DATA' });
commonWords = data?.commonWords ?? commonWords;
@ -420,13 +425,15 @@ async function setUp(params = {}) {
skips = data?.skips ?? skips;
tokens = data?.tokens ?? tokens;
dispatch({ type: 'ENABLE_ICON' });
dispatch({ type: 'SET_BADGE', value: actions.size });
dispatch({ type: 'ENABLE_REPORT' });
dispatch({ hostname, type: 'ENABLE_ICON' });
dispatch({ type: 'UPDATE_BADGE', value: actions.size });
observer.observe(document.body ?? document.documentElement, options);
if (!params.skipRunFn) run({ containers: tokens.containers });
} else {
dispatch({ type: 'DISABLE_REPORT' });
dispatch({ type: 'DISABLE_ICON' });
dispatch({ type: 'SET_BADGE', value: actions.size });
dispatch({ type: 'UPDATE_BADGE', value: actions.size });
observer.disconnect();
}
}
@ -449,7 +456,7 @@ async function setUpAfterWaitForBody() {
* @type {MutationObserver}
*/
const observer = new MutationObserver((mutations) => {
if (!state.enabled || !tokens.selectors.length) {
if (!state.on || !tokens.selectors.length) {
return;
}
@ -466,7 +473,7 @@ const observer = new MutationObserver((mutations) => {
browser.runtime.onMessage.addListener(async (message) => {
switch (message.type) {
case 'INCREASE_ACTIONS_COUNT': {
actions.add(new Date().getTime().toString());
actions.add(`${Date.now()}`);
break;
}
}
@ -490,10 +497,14 @@ window.addEventListener('pageshow', async (event) => {
* @returns {void}
*/
window.addEventListener('visibilitychange', async () => {
if (document.visibilityState === 'visible' && !initiallyVisible) {
if (document.visibilityState === 'visible') {
if (!initiallyVisible) {
initiallyVisible = true;
await setUp();
}
dispatch({ type: state.on ? 'ENABLE_REPORT' : 'DISABLE_REPORT' });
}
});
/**

View File

@ -1,272 +0,0 @@
if (typeof browser === 'undefined') {
browser = chrome;
}
/**
* @description Report dialog ID
*/
const reportDialogId = 'report-dialog';
/**
* @description Report dialog outer HTML
*/
const reportDialogHtml = `
<dialog id="${reportDialogId}" tabindex="0">
<div class="report-dialog-header">
<div class="report-dialog-header-title">Cookie Dialog Monster</div>
<div class="report-dialog-close-button" role="button" tabindex="0">
<svg
fill="none"
height="20"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
viewBox="0 0 24 24"
width="20"
>
<line x1="18" y1="6" x2="6" y2="18" />
<line x1="6" y1="6" x2="18" y2="18" />
</svg>
</div>
</div>
<div class="report-dialog-body">
<div class="report-dialog-form-view">
<div class="report-dialog-body-text">
${browser.i18n.getMessage('reportDialog_bodyText')}
</div>
<div class="report-dialog-form">
<div class="report-dialog-input-group">
<div class="report-dialog-input-label" id="report-dialog-label-url">
${browser.i18n.getMessage('reportDialog_urlInputLabel')}
<span class="report-dialog-input-label-required">*</span>
</div>
<input
aria-labelledby="report-dialog-label-url"
aria-required="true"
class="report-dialog-input"
id="report-dialog-input-url"
/>
<div class="report-dialog-input-error" id="report-dialog-input-url-error">
${browser.i18n.getMessage('reportDialog_urlInputError')}
</div>
</div>
<div class="report-dialog-input-group">
<div class="report-dialog-input-label" id="report-dialog-label-reason">
${browser.i18n.getMessage('reportDialog_reasonInputLabel')}
<span class="report-dialog-input-label-required">*</span>
</div>
<textarea
aria-labelledby="report-dialog-label-reason"
aria-required="true"
class="report-dialog-input"
id="report-dialog-input-reason"
rows="4"
>${browser.i18n.getMessage('reportDialog_reasonInputPlaceholder')}</textarea>
<div class="report-dialog-input-error" id="report-dialog-input-reason-error">
${browser.i18n.getMessage('reportDialog_reasonInputError')}
</div>
</div>
<div class="report-dialog-submit-button" role="button" tabindex="0">
${browser.i18n.getMessage('contextMenu_reportOption')?.replace('...', '')}
</div>
</div>
</div>
<div class="report-dialog-submit-view" hidden>
<svg
fill="none"
height="48"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
stroke="var(--cookie-dialog-monster-color-success)"
viewBox="0 0 24 24"
width="48"
>
<path d="M22 11.08V12a10 10 0 1 1-5.93-9.14" />
<polyline points="22 4 12 14.01 9 11.01" />
</svg>
<div class="report-dialog-submit-text">
${browser.i18n.getMessage('reportDialog_submitText')}
</div>
<div class="report-dialog-submit-extra-text">
${browser.i18n.getMessage('reportDialog_submitExtraText')}
</div>
<div class="report-dialog-issue-button" role="button" tabindex="0">
${browser.i18n.getMessage('contextMenu_issueOption')}
</div>
</div>
</div>
</dialog>
`;
/**
* @description Dialog close button click handler
* @param {MouseEvent} event
*/
function closeButtonClickHandler(event) {
const dialog = document.getElementById(reportDialogId);
event.preventDefault();
dialog?.remove();
}
/**
* @description Hide report dialog
*/
function hideReportDialog() {
document.getElementById(reportDialogId)?.remove();
}
/**
* @description Input change handler
* @param {InputEvent} event
*/
function inputChangeHandler(event) {
event.currentTarget.removeAttribute('aria-invalid');
}
/**
* @description Input key down handler
* @param {KeyboardEvent} event
*/
function inputKeyDownHandler(event) {
if (event.key === 'Enter') {
event.preventDefault();
event.currentTarget.blur();
}
}
/**
* @description Show report dialog
*/
function showReportDialog() {
const existingDialog = document.getElementById(reportDialogId);
if (existingDialog) {
const submitButton = existingDialog.getElementsByClassName('report-dialog-submit-button')[0];
const urlInput = existingDialog.querySelector('#report-dialog-input-url');
existingDialog.showModal();
submitButton.setAttribute('aria-disabled', 'false');
urlInput.setAttribute('value', window.location.origin + window.location.pathname);
return;
}
const parser = new DOMParser();
const result = parser.parseFromString(reportDialogHtml, 'text/html');
const dialog = result.body.firstElementChild;
const closeButton = dialog.getElementsByClassName('report-dialog-close-button')[0];
const link = document.createElement('link');
const reasonInput = dialog?.querySelector('#report-dialog-input-reason');
const submitButton = dialog?.getElementsByClassName('report-dialog-submit-button')[0];
const urlInput = dialog?.querySelector('#report-dialog-input-url');
closeButton.addEventListener('click', closeButtonClickHandler);
urlInput.setAttribute('value', window.location.origin + window.location.pathname);
link.setAttribute('href', 'https://fonts.googleapis.com/css?family=Inter');
link.setAttribute('id', 'report-dialog-font');
link.setAttribute('rel', 'stylesheet');
reasonInput.addEventListener('input', inputChangeHandler);
reasonInput.addEventListener('keydown', inputKeyDownHandler);
submitButton.addEventListener('click', submitButtonClickHandler);
urlInput.addEventListener('input', inputChangeHandler);
urlInput.addEventListener('keydown', inputKeyDownHandler);
dispatch({ type: 'INSERT_DIALOG_CSS' });
document.body.appendChild(dialog);
document.head.appendChild(link);
dialog.showModal();
}
/**
* @description Dialog submit button click handler
* @param {MouseEvent} event
*/
async function submitButtonClickHandler(event) {
event.preventDefault();
if (event.currentTarget.getAttribute('aria-disabled') === 'true') {
return;
}
event.currentTarget.setAttribute('aria-disabled', 'true');
const dialog = document.getElementById(reportDialogId);
const reasonInput = dialog?.querySelector('#report-dialog-input-reason');
const reasonText = reasonInput?.value.trim();
const urlInput = dialog?.querySelector('#report-dialog-input-url');
const urlText = urlInput?.value.trim();
const errors = validateForm({ reason: reasonText, url: urlText });
if (errors) {
if (errors.reason) {
reasonInput?.setAttribute('aria-invalid', 'true');
reasonInput?.setAttribute('aria-errormessage', 'report-dialog-input-reason-error');
}
if (errors.url) {
urlInput?.setAttribute('aria-invalid', 'true');
urlInput?.setAttribute('aria-errormessage', 'report-dialog-input-url-error');
}
event.currentTarget.setAttribute('aria-disabled', 'false');
return;
}
const formView = dialog?.getElementsByClassName('report-dialog-form-view')[0];
const issueButton = dialog?.getElementsByClassName('report-dialog-issue-button')[0];
const submitView = dialog?.getElementsByClassName('report-dialog-submit-view')[0];
const userAgent = window.navigator.userAgent;
const issueUrl = await dispatch({ userAgent, reason: reasonText, url: urlText, type: 'REPORT' });
formView?.setAttribute('hidden', 'true');
issueButton?.addEventListener('click', () => window.open(issueUrl, '_blank'));
submitView?.removeAttribute('hidden');
}
/**
* @description Validate form
* @param {{ reason: string | undefined | undefined, url: string | undefined }} params
* @returns {{ reason: string | undefined, url: string | undefined } | undefined}
*/
function validateForm(params) {
const { reason, url } = params;
let errors = undefined;
if (!reason || reason.length < 10 || reason.length > 1000) {
errors = {
...(errors ?? {}),
reason: browser.i18n.getMessage('reportDialog_reasonInputError'),
};
}
try {
new URL(url);
} catch {
errors = {
...(errors ?? {}),
url: browser.i18n.getMessage('reportDialog_urlInputError'),
};
}
return errors;
}
/**
* @description Listen to messages
*/
browser.runtime.onMessage.addListener((message) => {
const isPage = window === window.top;
switch (message.type) {
case 'HIDE_REPORT_DIALOG':
if (isPage) hideReportDialog();
break;
case 'SHOW_REPORT_DIALOG':
if (isPage) showReportDialog();
break;
default:
break;
}
});

View File

@ -62,8 +62,8 @@ async function handleAddClick() {
if (exclusionValue?.trim() && (domainRx.test(exclusionValue) || exclusionValue === 'localhost')) {
const filterInputElement = document.getElementById('filter-input');
const state = { enabled: false };
await dispatch({ hostname: exclusionValue, state, type: 'SET_HOSTNAME_STATE' });
const state = { on: false };
await dispatch({ hostname: exclusionValue, state, type: 'UPDATE_STORE' });
exclusionList = [...new Set([...exclusionList, exclusionValue])].sort();
createList();
@ -80,8 +80,8 @@ 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' });
const state = { on: true };
await dispatch({ hostname: exclusionValue, state, type: 'UPDATE_STORE' });
}
exclusionList = [];
@ -128,9 +128,9 @@ async function handleDeleteClick(event) {
const filterInputElement = document.getElementById('filter-input');
const { value } = event.currentTarget.parentElement.dataset;
const itemElement = document.querySelector(`[data-value="${value}"]`);
const state = { enabled: true };
const state = { on: true };
await dispatch({ hostname: value, state, type: 'SET_HOSTNAME_STATE' });
await dispatch({ hostname: value, state, type: 'UPDATE_STORE' });
exclusionList = exclusionList.filter((exclusionValue) => exclusionValue !== value);
itemElement?.remove();
updateList(filterInputElement.value.trim());
@ -172,8 +172,8 @@ function handleFileChange(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' });
const state = { on: false };
await dispatch({ hostname: exclusionValue, state, type: 'UPDATE_STORE' });
}
if (newExclusionList.length) {

View File

@ -1,3 +1,15 @@
/**
* @typedef {Object} ExtensionState
* @property {boolean} on
* @property {ExtensionIssue} [issue]
*/
/**
* @typedef {Object} PopupState
* @extends {ExtensionState}
* @property {number} [tabId]
*/
if (typeof browser === 'undefined') {
browser = chrome;
}
@ -8,6 +20,11 @@ if (typeof browser === 'undefined') {
*/
const chromeUrl = 'https://chrome.google.com/webstore/detail/djcbfpkdhdkaflcigibkbpboflaplabg';
/**
* @description Shortcut to send messages to background script
*/
const dispatch = browser.runtime.sendMessage;
/**
* @description Edge Add-ons link
* @type {string}
@ -46,10 +63,24 @@ const isEdge = navigator.userAgent.indexOf('Edg') !== -1;
const isFirefox = navigator.userAgent.indexOf('Firefox') !== -1;
/**
* @description Extension state
* @type {{ enabled: boolean, tabId: number | undefined }}
* @description Popup state
* @type {PopupState}
*/
let state = { enabled: true, tabId: undefined };
let state = { on: true };
/**
* @description Close report form
* @returns {void}
*/
function handleCancelClick() {
const content = document.getElementsByClassName('content')[0];
const report = document.getElementsByClassName('report')[0];
if (content instanceof HTMLElement && report instanceof HTMLElement) {
content.style.removeProperty('display');
report.style.display = 'none';
}
}
/**
* @async
@ -57,15 +88,46 @@ let state = { enabled: true, tabId: undefined };
* @returns {Promise<void>}
*/
async function handleContentLoaded() {
const tab = await browser.runtime.sendMessage({ type: 'GET_TAB' });
const tab = await dispatch({ type: 'GET_TAB' });
const tabUrl = tab?.url ? new URL(tab.url) : undefined;
hostname = tab?.url
? new URL(tab.url).hostname.split('.').slice(-3).join('.').replace('www.', '')
: undefined;
hostname = tabUrl?.hostname.split('.').slice(-3).join('.').replace('www.', '');
const next = await browser.runtime.sendMessage({ hostname, type: 'GET_HOSTNAME_STATE' });
const next = await dispatch({ hostname, type: 'GET_STATE' });
state = { ...(next ?? state), tabId: tab?.id };
if (state.issue?.url) {
const issueBanner = document.getElementById('issue-banner');
issueBanner.removeAttribute('aria-hidden');
const issueBannerText = document.getElementById('issue-banner-text');
if (state.issue.flags.includes('wontfix'))
issueBannerText.innerText = browser.i18n.getMessage('popup_bannerIssueWontFix');
else issueBannerText.innerText = browser.i18n.getMessage('popup_bannerIssueOpen');
const issueBannerUrl = document.getElementById('issue-banner-url');
issueBannerUrl.setAttribute('href', state.issue.url);
} else {
const cancelButtonElement = document.getElementsByClassName('report-cancel-button')[0];
cancelButtonElement?.addEventListener('click', handleCancelClick);
const reasonInputElement = document.getElementById('report-input-reason');
reasonInputElement?.addEventListener('input', handleInputChange);
reasonInputElement?.addEventListener('keydown', handleInputKeyDown);
const reportButtonElement = document.getElementById('report-button');
reportButtonElement?.addEventListener('click', handleReportClick);
reportButtonElement?.removeAttribute('disabled');
const urlInputElement = document.getElementById('report-input-url');
urlInputElement?.addEventListener('input', handleInputChange);
urlInputElement?.addEventListener('keydown', handleInputKeyDown);
if (tabUrl) urlInputElement?.setAttribute('value', `${tabUrl.origin}${tabUrl.pathname}`);
const submitButtonElement = document.getElementsByClassName('report-submit-button')[0];
submitButtonElement?.addEventListener('click', handleSubmitButtonClick);
}
const hostTextElement = document.getElementById('host');
hostTextElement.innerText = hostname ?? 'unknown';
@ -83,7 +145,7 @@ async function handleContentLoaded() {
const powerButtonElement = document.getElementById('power-option');
powerButtonElement?.addEventListener('click', handlePowerToggle);
if (state.enabled) powerButtonElement?.setAttribute('data-value', 'on');
if (state.on) powerButtonElement?.setAttribute('data-value', 'on');
else powerButtonElement?.setAttribute('data-value', 'off');
const rateButtonElement = document.getElementById('rate-option');
@ -93,10 +155,10 @@ async function handleContentLoaded() {
else if (isFirefox) rateButtonElement?.setAttribute('data-href', firefoxUrl);
const settingsButtonElement = document.getElementById('settings-button');
settingsButtonElement.addEventListener('click', handleSettingsClick);
settingsButtonElement?.addEventListener('click', handleSettingsClick);
translate();
updateDatabaseVersion();
await updateDatabaseVersion();
}
/**
@ -116,12 +178,12 @@ async function handleDatabaseRefresh(event) {
target.setAttribute('data-refreshing', 'true');
target.setAttribute('aria-disabled', 'true');
await browser.runtime.sendMessage({ type: 'REFRESH_DATA' });
await dispatch({ type: 'REFRESH_DATA' });
checkIcon.style.setProperty('display', 'block');
spinnerIcon.style.setProperty('display', 'none');
target.removeAttribute('data-animation');
target.removeAttribute('data-refreshing');
updateDatabaseVersion();
await updateDatabaseVersion();
window.setTimeout(() => {
checkIcon.style.setProperty('display', 'none');
@ -131,6 +193,25 @@ async function handleDatabaseRefresh(event) {
}, 5000);
}
/**
* @description Input change handler
* @param {InputEvent} event
*/
function handleInputChange(event) {
event.currentTarget.removeAttribute('aria-invalid');
}
/**
* @description Input key down handler
* @param {KeyboardEvent} event
*/
function handleInputKeyDown(event) {
if (event.key === 'Enter') {
event.preventDefault();
event.currentTarget.blur();
}
}
/**
* @async
* @description Open a new tab
@ -146,17 +227,32 @@ async function handleLinkRedirect(event) {
}
/**
* @async
* @description Disable or enable extension on current page
* @returns {void}
*/
function handlePowerToggle() {
const next = { enabled: !state.enabled };
async function handlePowerToggle() {
const next = { on: !state.on };
browser.runtime.sendMessage({ hostname, state: next, type: 'SET_HOSTNAME_STATE' });
browser.tabs.reload(state.tabId, { bypassCache: true });
await dispatch({ hostname, state: next, type: 'UPDATE_STORE' });
await browser.tabs.reload(state.tabId, { bypassCache: true });
window.close();
}
/**
* @description Show report form
* @returns {void}
*/
function handleReportClick() {
const content = document.getElementsByClassName('content')[0];
const report = document.getElementsByClassName('report')[0];
if (content instanceof HTMLElement && report instanceof HTMLElement) {
content.style.display = 'none';
report.style.removeProperty('display');
}
}
/**
* @async
* @description Open options page
@ -166,6 +262,76 @@ async function handleSettingsClick() {
await browser.runtime.openOptionsPage();
}
/**
* @async
* @description Report submit button click handler
* @param {MouseEvent} event
*/
async function handleSubmitButtonClick(event) {
event.preventDefault();
if (event.currentTarget.getAttribute('aria-disabled') === 'true') {
return;
}
event.currentTarget.setAttribute('aria-disabled', 'true');
const reasonInput = document.getElementById('report-input-reason');
const reasonText = reasonInput?.value.trim();
const urlInput = document.getElementById('report-input-url');
const urlText = urlInput?.value.trim();
const errors = validateForm({ reason: reasonText, url: urlText });
if (errors) {
if (errors.reason) {
reasonInput?.setAttribute('aria-invalid', 'true');
reasonInput?.setAttribute('aria-errormessage', 'report-input-reason-error');
}
if (errors.url) {
urlInput?.setAttribute('aria-invalid', 'true');
urlInput?.setAttribute('aria-errormessage', 'report-input-url-error');
}
event.currentTarget.setAttribute('aria-disabled', 'false');
return;
}
const issueButtons = document.getElementsByClassName('report-issue-button');
const formView = document.getElementsByClassName('report-form-view')[0];
const userAgent = window.navigator.userAgent;
const response = await dispatch({ userAgent, reason: reasonText, url: urlText, type: 'REPORT' });
const hostname = new URL(urlText).hostname.split('.').slice(-3).join('.').replace('www.', '');
const issue = { expiresIn: Date.now() + 8 * 60 * 60 * 1000, flags: ['bug'], url: response.data };
if (response.success) {
const successView = document.getElementsByClassName('report-submit-success-view')[0];
await dispatch({ hostname, state: { issue }, type: 'UPDATE_STORE' });
await dispatch({ hostname, type: 'ENABLE_ICON' });
formView?.setAttribute('hidden', 'true');
issueButtons[1]?.addEventListener('click', () => window.open(response.data, '_blank'));
successView?.removeAttribute('hidden');
return;
}
if (response.data) {
const errorView = document.getElementsByClassName('report-submit-error-view')[0];
if (response.errors?.some((error) => error.includes('wontfix'))) {
issue.flags.push('wontfix');
}
await dispatch({ hostname, state: { issue }, type: 'UPDATE_STORE' });
errorView?.removeAttribute('hidden');
formView?.setAttribute('hidden', 'true');
issueButtons[0]?.addEventListener('click', () => window.open(response.data, '_blank'));
return;
}
window.close();
}
/**
* @description Apply translations to tags with i18n data attribute
* @returns {void}
@ -193,13 +359,41 @@ function translate() {
* @returns {Promise<void>}
*/
async function updateDatabaseVersion() {
const data = await browser.runtime.sendMessage({ hostname, type: 'GET_DATA' });
const data = await dispatch({ hostname, type: 'GET_DATA' });
const databaseVersionElement = document.getElementById('database-version');
if (data.version) databaseVersionElement.innerText = data.version;
else databaseVersionElement.style.setProperty('display', 'none');
}
/**
* @description Validate form
* @param {{ reason: string | undefined | undefined, url: string | undefined }} params
* @returns {{ reason: string | undefined, url: string | undefined } | undefined}
*/
function validateForm(params) {
const { reason, url } = params;
let errors = undefined;
if (!reason || reason.length < 10 || reason.length > 1000) {
errors = {
...(errors ?? {}),
reason: browser.i18n.getMessage('report_reasonInputError'),
};
}
try {
new URL(url);
} catch {
errors = {
...(errors ?? {}),
url: browser.i18n.getMessage('report_urlInputError'),
};
}
return errors;
}
/**
* @description Listen to document ready
* @listens document#DOMContentLoaded

View File

@ -1,276 +0,0 @@
:root {
--cookie-dialog-monster-color-error: #cc0000;
--cookie-dialog-monster-color-primary: #3dd9eb;
--cookie-dialog-monster-color-secondary: #34495e;
--cookie-dialog-monster-color-success: #5cb85c;
--cookie-dialog-monster-color-tertiary: #6b7280;
--cookie-dialog-monster-color-white: #ffffff;
}
#report-dialog {
background-color: var(--cookie-dialog-monster-color-white);
border: none;
border-radius: 4px;
box-sizing: border-box;
color: var(--cookie-dialog-monster-color-secondary);
font-size: 100%;
letter-spacing: normal;
margin: auto;
padding: 0px;
text-align: left;
width: 320px;
}
#report-dialog::backdrop {
background-color: rgba(0, 0, 0, 0.5);
}
#report-dialog * {
box-sizing: border-box;
}
#report-dialog div {
all: unset;
display: block;
box-sizing: border-box;
}
#report-dialog *::-moz-selection {
color: var(--cookie-dialog-monster-color-white);
background: var(--cookie-dialog-monster-color-tertiary);
}
#report-dialog *::selection {
color: var(--cookie-dialog-monster-color-white);
background: var(--cookie-dialog-monster-color-tertiary);
}
#report-dialog .report-dialog-body {
display: block;
font-size: 14px;
line-height: 1.2;
padding: 16px;
}
#report-dialog .report-dialog-body-text {
display: block;
font-family: Inter, Arial, Helvetica, sans-serif;
font-size: 14px;
line-height: 1.2;
margin: 0px;
padding: 0px;
}
#report-dialog .report-dialog-close-button {
align-items: center;
background-color: transparent;
border: none;
border-radius: 4px;
cursor: pointer;
display: inline-flex;
justify-content: center;
margin: 0px;
outline: none;
padding: 0px;
}
#report-dialog .report-dialog-close-button {
stroke: var(--cookie-dialog-monster-color-white);
}
#report-dialog .report-dialog-close-button:focus,
#report-dialog .report-dialog-close-button:hover > svg {
stroke: var(--cookie-dialog-monster-color-secondary);
}
#report-dialog .report-dialog-close-button:focus-visible {
box-shadow: initial;
transition: initial;
}
#report-dialog .report-dialog-close-button:focus,
#report-dialog .report-dialog-close-button:hover {
background-color: var(--cookie-dialog-monster-color-white);
}
#report-dialog .report-dialog-form {
display: grid;
gap: 10px;
}
#report-dialog .report-dialog-form-view {
display: flex;
flex-direction: column;
gap: 24px;
}
#report-dialog .report-dialog-form-view[hidden] {
display: none;
}
#report-dialog .report-dialog-header {
align-items: center;
background-color: var(--cookie-dialog-monster-color-secondary);
display: flex;
font-size: 16px;
height: 54px;
justify-content: space-between;
line-height: 1.2;
padding: 16px;
}
#report-dialog .report-dialog-header-title {
color: var(--cookie-dialog-monster-color-white);
font-family: Inter, Arial, Helvetica, sans-serif;
font-weight: 500;
}
#report-dialog .report-dialog-input {
all: unset;
border: 1px solid var(--cookie-dialog-monster-color-tertiary);
border-radius: 4px;
color: var(--cookie-dialog-monster-color-secondary);
cursor: text;
font-family: Inter, Arial, Helvetica, sans-serif;
font-size: 14px;
line-height: 1;
outline: none;
padding: 12px 8px;
}
#report-dialog .report-dialog-input:hover {
border-color: var(--cookie-dialog-monster-color-secondary);
}
#report-dialog .report-dialog-input:focus {
border-color: var(--cookie-dialog-monster-color-primary);
}
#report-dialog .report-dialog-input:focus-visible {
box-shadow: initial;
transition: initial;
}
#report-dialog .report-dialog-input::-webkit-scrollbar {
display: none;
}
#report-dialog .report-dialog-input[aria-invalid='true'] {
border-color: var(--cookie-dialog-monster-color-error);
}
#report-dialog .report-dialog-input[aria-invalid='true'] + .report-dialog-input-error {
visibility: visible;
}
#report-dialog .report-dialog-input[aria-multiline='false'] {
-ms-overflow-style: none;
display: flex;
height: 40px;
overflow-x: auto;
scrollbar-width: none;
text-wrap: nowrap;
}
#report-dialog .report-dialog-input[aria-multiline='true'] {
-ms-overflow-style: none;
height: 120px;
overflow-y: auto;
scrollbar-width: none;
}
#report-dialog .report-dialog-input-error {
color: var(--cookie-dialog-monster-color-error);
font-family: Inter, Arial, Helvetica, sans-serif;
font-size: 10px;
line-height: 1.2;
visibility: hidden;
}
#report-dialog .report-dialog-input-group {
display: grid;
gap: 4px;
}
#report-dialog .report-dialog-input-label {
color: var(--cookie-dialog-monster-color-secondary);
font-family: Inter, Arial, Helvetica, sans-serif;
font-size: 12px;
line-height: 1.2;
}
#report-dialog .report-dialog-input-label-required {
color: var(--cookie-dialog-monster-color-error);
}
#report-dialog .report-dialog-issue-button,
#report-dialog .report-dialog-submit-button {
align-items: center;
background-color: var(--cookie-dialog-monster-color-secondary);
border: 1px solid var(--cookie-dialog-monster-color-secondary);
border-radius: 4px;
color: var(--cookie-dialog-monster-color-white);
cursor: pointer;
display: flex;
font-family: Inter, Arial, Helvetica, sans-serif;
font-size: 14px;
height: 42px;
justify-content: center;
line-height: 1.2;
outline: none;
padding: 8px 16px;
text-align: center;
width: 100%;
}
#report-dialog .report-dialog-issue-button:focus,
#report-dialog .report-dialog-issue-button:hover,
#report-dialog .report-dialog-submit-button:focus,
#report-dialog .report-dialog-submit-button:hover {
background-color: var(--cookie-dialog-monster-color-white);
color: var(--cookie-dialog-monster-color-secondary);
}
#report-dialog .report-dialog-issue-button:focus-visible,
#report-dialog .report-dialog-submit-button:focus-visible {
box-shadow: initial;
transition: initial;
}
#report-dialog .report-dialog-issue-button[aria-disabled='true'],
#report-dialog .report-dialog-submit-button[aria-disabled='true'] {
background-color: var(--cookie-dialog-monster-color-tertiary);
border: 1px solid var(--cookie-dialog-monster-color-tertiary);
color: var(--cookie-dialog-monster-color-white);
cursor: not-allowed;
}
#report-dialog .report-dialog-submit-extra-text {
font-family: inherit;
font-size: 14px;
line-height: 1.2;
margin: 0px;
text-align: justify;
}
#report-dialog .report-dialog-submit-text {
font-family: inherit;
font-size: 18px;
line-height: 1.2;
margin: 0px;
text-align: center;
}
#report-dialog .report-dialog-submit-view {
align-items: center;
display: flex;
flex-direction: column;
font-family: Inter, Arial, Helvetica, sans-serif;
gap: 24px;
justify-content: center;
margin-top: 16px;
}
#report-dialog .report-dialog-submit-view[hidden] {
display: none;
}

View File

@ -40,6 +40,12 @@ button[data-variant='large'] {
padding: 8px;
}
@media only screen and (max-device-width: 768px) {
button[data-variant='large'] {
justify-content: flex-end;
}
}
button:focus,
button:hover {
background-color: var(--color-secondary);
@ -104,11 +110,18 @@ main {
.button-group {
display: flex;
justify-content: flex-end;
gap: 4px;
justify-content: flex-end;
margin-bottom: 4px;
}
@media only screen and (max-device-width: 768px) {
.button-group {
display: grid;
grid-template-columns: repeat(2, minmax(0px, 1fr));
}
}
#exclusion-list {
font-size: 14px;
list-style: none;

View File

@ -11,12 +11,16 @@
body {
box-sizing: border-box;
color: var(--color-tertiary);
display: flex;
flex-direction: column;
font-family: Inter, Arial, Helvetica, sans-serif;
width: 320px;
}
@media only screen and (max-device-width: 768px) {
body {
width: auto;
}
}
body * {
box-sizing: border-box;
}
@ -32,16 +36,22 @@ button {
outline: none;
padding: 2px;
transition: 0.4s;
}
button:focus,
button:hover {
&:focus:not(:disabled),
&:hover:not(:disabled) {
background-color: var(--color-white);
color: var(--color-secondary);
}
&:disabled {
cursor: not-allowed;
opacity: 0.5;
}
}
footer {
background-color: var(--color-secondary);
flex-shrink: 0;
font-size: 12px;
height: 4px;
margin-top: auto;
@ -53,13 +63,49 @@ header {
background-color: var(--color-secondary);
color: var(--color-white);
display: flex;
flex-shrink: 0;
font-size: 16px !important;
height: 48px;
justify-content: space-between;
padding: 0 16px;
& .header-actions {
display: flex;
gap: 8px;
& #report-button:focus:not(:disabled) > svg,
& #report-button:hover:not(:disabled) > svg {
color: var(--color-error);
}
}
}
@media only screen and (max-device-width: 768px) {
main {
margin: 0 auto;
max-width: 320px;
width: 100%;
}
}
main > .banner {
background-color: #f39c12;
color: #c0392b;
margin: 0px;
padding: 16px;
&[aria-hidden='true'] {
display: none;
}
& #issue-banner-url {
color: inherit;
display: inline-block;
vertical-align: middle;
}
}
main > .content {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 16px;
@ -142,6 +188,208 @@ popup-data-container {
text-align: center;
}
.report {
font-family: inherit;
font-size: 14px;
line-height: 1.2;
padding: 16px;
& .report-buttons {
margin-top: auto;
}
& .report-form {
display: grid;
gap: 10px;
}
& .report-form-view {
display: flex;
flex-direction: column;
gap: 16px;
}
& .report-form-view[hidden] {
display: none;
}
& .report-input {
all: unset;
border: 1px solid var(--color-tertiary);
border-radius: 4px;
color: var(--color-secondary);
cursor: text;
font-family: Inter, Arial, Helvetica, sans-serif;
font-size: 14px;
line-height: 1;
outline: none;
padding: 12px 8px;
}
& .report-input:hover {
border-color: var(--color-secondary);
}
& .report-input:focus {
border-color: var(--color-primary);
}
& .report-input:focus-visible {
box-shadow: initial;
transition: initial;
}
& .report-input::-webkit-scrollbar {
display: none;
}
& .report-input[aria-invalid='true'] {
border-color: var(--color-error);
}
& .report-input[aria-invalid='true'] + .report-input-error {
display: block;
}
& .report-input[aria-multiline='false'] {
-ms-overflow-style: none;
display: flex;
height: 40px;
overflow-x: auto;
scrollbar-width: none;
text-wrap: nowrap;
}
& .report-input[aria-multiline='true'] {
-ms-overflow-style: none;
height: 120px;
overflow-y: auto;
scrollbar-width: none;
}
& .report-input-error {
color: var(--color-error);
display: none;
font-family: Inter, Arial, Helvetica, sans-serif;
font-size: 10px;
line-height: 1.2;
}
& .report-input-group {
display: grid;
gap: 4px;
}
& .report-input-label {
color: var(--color-secondary);
font-family: Inter, Arial, Helvetica, sans-serif;
font-size: 12px;
line-height: 1.2;
}
& .report-input-label-required {
color: var(--color-error);
}
& .report-cancel-button {
align-items: center;
background-color: var(--color-white);
color: var(--color-secondary);
cursor: pointer;
display: flex;
font-family: Inter, Arial, Helvetica, sans-serif;
font-size: 14px;
justify-content: center;
line-height: 1.2;
margin-left: auto;
margin-right: auto;
margin-top: 16px;
outline: none;
padding: 0px;
text-align: center;
}
& .report-cancel-button:focus,
& .report-cancel-button:hover {
color: var(--color-error);
}
& .report-issue-button,
& .report-submit-button {
align-items: center;
background-color: var(--color-secondary);
border: 1px solid var(--color-secondary);
border-radius: 4px;
color: var(--color-white);
cursor: pointer;
display: flex;
font-family: Inter, Arial, Helvetica, sans-serif;
font-size: 14px;
height: 42px;
justify-content: center;
line-height: 1.2;
margin-top: 8px;
outline: none;
padding: 8px 16px;
text-align: center;
width: 100%;
}
& .report-issue-button:focus,
& .report-issue-button:hover,
& .report-submit-button:focus,
& .report-submit-button:hover {
background-color: var(--color-white);
color: var(--color-secondary);
}
& .report-issue-button:focus-visible,
& .report-submit-button:focus-visible {
box-shadow: initial;
transition: initial;
}
& .report-issue-button[aria-disabled='true'],
& .report-submit-button[aria-disabled='true'] {
background-color: var(--color-tertiary);
border: 1px solid var(--color-tertiary);
color: var(--color-white);
cursor: not-allowed;
}
& .report-submit-extra-text {
font-family: inherit;
font-size: 14px;
line-height: 1.2;
margin: 0px;
text-align: justify;
}
& .report-submit-text {
font-family: inherit;
font-size: 18px;
line-height: 1.2;
margin: 0px;
text-align: center;
}
& .report-submit-error-view,
& .report-submit-success-view {
align-items: center;
display: flex;
flex-direction: column;
font-family: Inter, Arial, Helvetica, sans-serif;
gap: 24px;
justify-content: center;
margin-top: 16px;
}
& .report-submit-error-view[hidden],
& .report-submit-success-view[hidden] {
display: none;
}
}
strong {
font-weight: bold;
}

View File

@ -15,6 +15,5 @@
"engines": {
"node": "20.x"
},
"packageManager": "yarn@4.1.0",
"license": "MIT"
"packageManager": "yarn@4.2.1"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 28 KiB

View File

@ -35,6 +35,6 @@
}
.image {
@apply self-center max-w-sm md:self-start rounded-lg shadow-2xl shrink-0 w-full;
@apply max-w-sm rounded-lg shadow-2xl shrink-0 w-full;
}
}

View File

@ -216,8 +216,8 @@
</a>
</div>
</div>
<div class="flex flex-col gap-8 md:flex-row md:gap-20 md:py-20 py-10">
<div class="md:mt-14">
<div class="flex flex-col gap-8 items-center md:flex-row md:gap-20 md:py-20 py-10">
<div>
<h2>A powerful popup to manage all from a single place</h2>
<p class="mt-8 text-gray-500 text-xl">
Disable the extension if you would like to accept cookies in a specific page, contribute
@ -227,9 +227,9 @@
</div>
<img alt="Extension Popup" class="image" src="/images/popup.png" />
</div>
<div class="flex flex-col-reverse gap-8 md:flex-row md:gap-20 md:py-20 py-10">
<div class="flex flex-col-reverse gap-8 items-center md:flex-row md:gap-20 md:py-20 py-10">
<img alt="Extension Report Button" class="image" src="/images/report.png" />
<div class="md:mt-14">
<div>
<h2>We are not perfect but we try</h2>
<p class="mt-8 text-gray-500 text-xl">
Report any page that works bad with our extension, just right-click anywhere on the page
@ -242,8 +242,23 @@
</p>
</div>
</div>
<div class="flex flex-col gap-8 md:flex-row md:gap-20 md:py-20 py-10">
<div class="md:mt-14">
<div class="flex flex-col-reverse gap-8 items-center md:flex-row md:gap-20 md:py-20 py-10">
<div>
<h2>Real-time issue tracking</h2>
<p class="mt-8 text-gray-500 text-xl">
Track issues as they happen with real-time GitHub updates. Each report submitted is
instantly recorded on our GitHub issues page, giving our team visibility to work on it
immediately.
</p>
<p class="mt-4 text-gray-500 text-xl">
You can view the progress, add comments, and even watch the repository to stay informed.
</p>
</div>
<img alt="GitHub Issue Tracking" class="image" src="/images/issue.png" />
</div>
<div class="flex flex-col gap-8 items-center md:flex-row md:gap-20 md:py-20 py-10">
<img alt="Extension Options" class="image" src="/images/options.png" />
<div>
<h2>Manage your exclusions</h2>
<p class="mt-8 text-gray-500 text-xl">
Clear, import and export your preferences with one click. Users have full control over
@ -254,7 +269,6 @@
implementations or where the extension may cause unintended side effects.
</p>
</div>
<img alt="Extension Options" class="image" src="/images/options.png" />
</div>
<div class="md:py-20 py-10">
<div class="md:text-center">
@ -526,7 +540,7 @@
version following
<a
class="underline"
href="https://git.wanhose.dev/wanhose/cookie-dialog-monster/src/branch/main/packages/browser-extension#installation-for-mozilla-firefox-users"
href="https://git.wanhose.dev/wanhose/cookie-dialog-monster/wiki/Step-by-step+installation+guide+for+Mozilla+Firefox.-"
id="firefox-guide-link"
target="_blank"
>
@ -540,7 +554,7 @@
the extension. We recommend you to follow
<a
class="underline"
href="https://git.wanhose.dev/wanhose/cookie-dialog-monster/src/branch/main/packages/browser-extension#installation-for-advanced-and-non-listed-browser-users"
href="https://git.wanhose.dev/wanhose/cookie-dialog-monster/wiki/Step-by-step+installation+guide+for+advanced+users+and+non-listed+browsers.-"
target="_blank"
>
this guide</a
@ -574,7 +588,7 @@
if (isMobile) {
firefoxGuideLink.href =
'https://git.wanhose.dev/wanhose/cookie-dialog-monster/src/branch/main/packages/browser-extension#installation-for-mozilla-firefox-mobile-users';
'https://git.wanhose.dev/wanhose/cookie-dialog-monster/wiki/Step-by-step+installation+guide+for+Mozilla+Firefox+Mobile.-';
firefoxLink.href = '/releases/latest-mozilla-mobile.xpi';
}
});