diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..f6c3d7e --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,28 @@ +name: "Build" +on: + push: + branches: + - main + pull_request: + +jobs: + build: + name: "Build" + runs-on: ubuntu-latest + steps: + - name: "Checkout" + uses: actions/checkout@v1 + + - name: "web-ext build" + id: web-ext-build + uses: kewisch/action-web-ext@v1 + with: + cmd: build + source: . + filename: "{name}-{version}.xpi" + + - name: "Upload Artifact" + uses: actions/upload-artifact@v3 + with: + name: target.xpi + path: ${{ steps.web-ext-build.outputs.target }} diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..8332263 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,21 @@ +name: "Lint" +on: + push: + branches: + - main + pull_request: + +jobs: + lint: + name: "Lint" + runs-on: ubuntu-latest + steps: + - name: "Checkout" + uses: actions/checkout@v1 + + - name: "web-ext lint" + uses: kewisch/action-web-ext@v1 + with: + cmd: lint + source: . + channel: listed diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..c14ae40 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,38 @@ +name: "Release" +on: + push: + tags: + - '*.*.*' + +jobs: + sign: + name: "Release" + runs-on: ubuntu-latest + steps: + - name: "Checkout" + uses: actions/checkout@v1 + + - name: "web-ext build" + id: web-ext-build + uses: kewisch/action-web-ext@v1 + with: + cmd: build + source: . + + - name: "web-ext sign" + id: web-ext-sign + uses: kewisch/action-web-ext@v1 + with: + cmd: sign + source: ${{ steps.web-ext-build.outputs.target }} + channel: unlisted + apiKey: ${{ secrets.AMO_SIGN_KEY }} + apiSecret: ${{ secrets.AMO_SIGN_SECRET }} + timeout: 900000 + + - name: "Create Release" + uses: softprops/action-gh-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + files: ${{ steps.web-ext-sign.outputs.target }} diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..1bcf4a1 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Jiří Barouš + +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 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. diff --git a/_locales/en/messages.json b/_locales/en/messages.json new file mode 100644 index 0000000..eae4f0d --- /dev/null +++ b/_locales/en/messages.json @@ -0,0 +1,67 @@ +{ + "extensionName": { + "message": "List Unsubscribe", + "description": "Name of the extension." + }, + + "extensionDescription": { + "message": "Adds a button to unsubscribe from newsletters and other bulk email that has the List-Unsubscribe header.", + "description": "Description of the extension." + }, + + "unsubButtonLabel": { + "message": "Unsubscribe", + "description": "The unsubscribe toolbar button label." + }, + + "noUnsub": { + "message": "No unsubscribe header found.", + "description": "Shown when no List-Unsubscribe header was found in the message." + }, + + "unsubLink": { + "message": "Unsubscribe link: ", + "description": "A visible label for the unsubscribe link." + }, + + "unsubConfirmPrompt": { + "message": "Are you sure you want to unsubscribe from this mailing list?", + "description": "A prompt that asks the user to confirm that they want continue with the one-click unsubscribe." + }, + + "confirmOneClick": { + "message": "One-click unsubscribe", + "description": "A button label to confirm the one-click unsubscribe." + }, + + "confirmOpenLink": { + "message": "Open link", + "description": "A button label to open the unsubscribe link in the browser." + }, + + "confirmComposeEmail": { + "message": "Compose email", + "description": "A button label to compose an email to unsubscribe." + }, + + "oneClickInProgress": { + "message": "Unsubscribe request in progress...", + "description": "A message shown when the one-click unsubscribe is pending." + }, + + "oneClickSuccess": { + "message": "Unsubscribe request sent.", + "description": "A message shown when the one-click unsubscribe was successful." + }, + + "oneClickFailure": { + "message": "Unsubscribe request failed: $ERROR$", + "description": "A message shown when the one-click unsubscribe failed.", + "placeholders": { + "error": { + "content": "$1", + "example": "404 Not Found" + } + } + } +} diff --git a/background.js b/background.js new file mode 100644 index 0000000..d86aba0 --- /dev/null +++ b/background.js @@ -0,0 +1,14 @@ +browser.mailTabs.onSelectedMessagesChanged.addListener(async (tab, messageList) => { + if (messageList.messages.length !== 1) { + browser.messageDisplayAction.disable() + return + } + + const message = await browser.messages.getFull(messageList.messages[0].id) + if (message.headers.hasOwnProperty('list-unsubscribe')) { + browser.messageDisplayAction.enable() + return + } + + browser.messageDisplayAction.disable() +}) diff --git a/icons/icon_48.png b/icons/icon_48.png new file mode 100644 index 0000000..b030c1d Binary files /dev/null and b/icons/icon_48.png differ diff --git a/icons/icon_96.png b/icons/icon_96.png new file mode 100644 index 0000000..ee770ac Binary files /dev/null and b/icons/icon_96.png differ diff --git a/manifest.json b/manifest.json new file mode 100644 index 0000000..9778ff7 --- /dev/null +++ b/manifest.json @@ -0,0 +1,37 @@ +{ + "name": "__MSG_extensionName__", + "version": "1.0.0", + "description": "__MSG_extensionDescription__", + "author": "Amunak", + "homepage_url": "https://github.com/Amunak/thunderbird-list-unsubscribe-addon", + "background": { + "scripts": [ + "background.js" + ] + }, + "browser_specific_settings": { + "gecko": { + "id": "list-unsubscribe@addons.amunak.net", + "strict_min_version": "112.0" + } + }, + "default_locale": "en", + "icons": { + "48": "icons/icon_48.png", + "96": "icons/icon_96.png" + }, + "manifest_version": 2, + "message_display_action": { + "default_icon": "icons/icon_48.png", + "default_title": "__MSG_unsubButtonLabel__", + "default_popup": "popup.html" + }, + "permissions": [ + "http://*/*", + "https://*/*", + "messagesRead", + "accountsRead", + "clipboardWrite", + "webRequest" + ] +} diff --git a/popup.css b/popup.css new file mode 100644 index 0000000..b1e2b62 --- /dev/null +++ b/popup.css @@ -0,0 +1,23 @@ +body, html { + margin: 0; + padding: 0; +} + +code { + font-size: .875em; + color: #d63384; + word-wrap: break-word; +} + +.popup-page { + padding: .5rem; +} + +.popup-page div { + margin: 1rem 0; +} + +button { + margin: 0; + margin-right: .5rem; +} diff --git a/popup.html b/popup.html new file mode 100644 index 0000000..4e4f5fa --- /dev/null +++ b/popup.html @@ -0,0 +1,16 @@ + + +
+ +