kopia lustrzana https://github.com/lartsch/FediAct
Porównaj commity
99 Commity
Autor | SHA1 | Data |
---|---|---|
Lartsch | 22e3be13cb | |
Lartsch | 97f9c10872 | |
Lartsch | 053af951bc | |
Lartsch | e0fbc804cc | |
Lartsch | 6a9028afe0 | |
Rich Lafferty | 2289637543 | |
Rich Lafferty | 8766852c9d | |
Lartsch | 75cd8bb25a | |
Melody | 7050e7b735 | |
Lartsch | f42eb8fd28 | |
Freeplayg | 15d59f96ea | |
Freeplayg | 6889c46fc0 | |
lartsch | 2522f3f05c | |
lartsch | 0e20ff2f98 | |
lartsch | f23e7be502 | |
lartsch | 95ec910c99 | |
lartsch | b6e75774b9 | |
lartsch | 90ad7818f4 | |
lartsch | 0276c2e06a | |
lartsch | 8926e8ad80 | |
Lartsch | 80cbbdf631 | |
Freeplayg | 79a2e068a0 | |
Lartsch | 8a347f3afd | |
Lartsch | 7e56a3dc86 | |
Lartsch | 5508847693 | |
Lartsch | 5f2ebeaa43 | |
Lartsch | 34a1e3964c | |
Lartsch | 5c4f23ac75 | |
Lartsch | 7f6fd11715 | |
Lartsch | e87bd47439 | |
lartsch | 8624ca560f | |
lartsch | 222b6b9809 | |
lartsch | 999b0ded7b | |
lartsch | 89f4d7d423 | |
Lartsch | d59b6d0ea5 | |
Lartsch | df1115891d | |
Kara de la Marck | e1b24eeb11 | |
Freeplayg | 1d77003d08 | |
Lartsch | 6c9209ce61 | |
Lartsch | f600741d1f | |
Lartsch | b9aa91c130 | |
Lartsch | b1fa9f1f94 | |
Freeplayg | 115ba5503a | |
Levi | c734b16252 | |
Levi | dfff64b98c | |
Lartsch | 4bc6b568df | |
Lartsch | ababef902c | |
Freeplay | 6a83649c98 | |
Freeplayg | 712e0c08c5 | |
Freeplayg | 2d9a99ead3 | |
Freeplayg | 2c99b76e41 | |
Freeplayg | e2d0ec34a6 | |
lartsch | 3a5809d73d | |
lartsch | 379b67569b | |
lartsch | 7d774079ef | |
lartsch | de4f1ad1dd | |
Lartsch | 1b545b7750 | |
Lartsch | 3aed3ee81c | |
lartsch | 608e336141 | |
lartsch | 85dab0ce6a | |
lartsch | d99d7bf48c | |
lartsch | 4616f38bda | |
lartsch | 65f560b110 | |
Lartsch | 2dbce769f0 | |
Lartsch | 42f51bd72a | |
Lartsch | 4e296ec9dc | |
Lartsch | 5c3a948907 | |
lartsch | 8f2450f79b | |
lartsch | 4718d82610 | |
lartsch | 6ccd307c6e | |
lartsch | ff0a65943e | |
Lartsch | 0efe348b1d | |
Lartsch | 9321998193 | |
Lartsch | e6bee33825 | |
lartsch | 250e0b0ec0 | |
lartsch | 73ccc91136 | |
lartsch | 627df5c0ed | |
lartsch | 145326f783 | |
Lartsch | 77b565e1b2 | |
lartsch | 76f0369816 | |
lartsch | e7bc57fea7 | |
lartsch | 683de3ca4b | |
Lartsch | b95443bb90 | |
Lartsch | 279a0ca275 | |
Lartsch | eabecbd5fa | |
lartsch | 9badcc11f1 | |
lartsch | f8ceb4c460 | |
lartsch | 16d55bb4f9 | |
lartsch | 6634889224 | |
Lartsch | d20db0faa6 | |
Freeplayg | af0922ce77 | |
Freeplayg | efec20c9c4 | |
Freeplayg | d4e7d4fb98 | |
Lartsch | d953ceb87f | |
Lartsch | 43d670445a | |
Lartsch | 3626ca6258 | |
Lartsch | 013d476497 | |
Lartsch | 60cf9ceb7c | |
lartsch | 9645dfb8b3 |
134
README.md
134
README.md
|
@ -1,100 +1,90 @@
|
|||
> **Note**
|
||||
> LOOKING FOR AN ACTIVE MAINTAINER TO TAKE CARE OF THIS PROJECT!
|
||||
> FediAct requires some major updates/rewriting to resolve issues, increase performance/reliability and to be easier to maintain, for which I do not have time currently. Please leave a message/issue.
|
||||
|
||||
# FediAct (v0.9.8)
|
||||
A Chrome/Firefox extension that simplifies follow and post interactions on Mastodon instances other than your own.
|
||||
A Chrome/Firefox extension that simplifies follow and post interactions on Mastodon servers other than your own.
|
||||
|
||||
**Features**:
|
||||
- Supports Mastodon v3 + v4 (some features v4 only)
|
||||
- Follow, boost, bookmark, reply, fav, vote polls and mute/block on external instances while only being logged in to your home instance
|
||||
- Show following status and toot status (boosted, faved, bookmarked) on external instances
|
||||
- Single click to execute action only, double click to redirect to content on home instance
|
||||
- Reply button on external instances always redirects to home instance and enters reply-mode
|
||||
- Hide muted content on external instances if enabled
|
||||
- Customizable
|
||||
|
||||
**Supported browsers**:
|
||||
- All up-to-date Chromium browsers, including Kiwi and Yandex browsers on Android
|
||||
- Up-to-date Firefox (v107+), including Firefox Nightly on Android, Orion on iOS (untested)
|
||||
|
||||
**Important notes**:
|
||||
- Data is processed locally only
|
||||
- Performance depends on your home instance and to some degree on the external instance you are browsing (read more [below](#additional-notes))
|
||||
- Some toots cannot be resolved to your home (in cases where searching for the post manually would not work either)
|
||||
- Follow, boost, bookmark, reply, fav, vote polls and mute/block on external servers while only being logged in to your home server
|
||||
- Show following state and toot state (boosted, faved, bookmarked, voted) on external servers
|
||||
- Single click to execute action only, double click to redirect to content on home server
|
||||
- Reply button on external servers always redirects to home server and enters reply-mode
|
||||
- Hide muted content on external servers if enabled
|
||||
- Needs nothing more than your home server domain to work
|
||||
|
||||
## Navigation
|
||||
* [Installation](#installation)
|
||||
* [Setup](#setup)
|
||||
* [FAQ](#faq)
|
||||
* [Screenshots / GIFs](#screenshots--gifs)
|
||||
* [Manual installation](#manual-installation)
|
||||
* [Install in Firefox for Android](#install-in-firefox-for-android)
|
||||
* [Additional notes](#additional-notes)
|
||||
* [Todos / Planned features](#todos--planned-features)
|
||||
* [Contributing](#contributing)
|
||||
- [Installation](#installation)
|
||||
- [Setup](#setup)
|
||||
- [FAQ](#faq)
|
||||
- [Screenshots / GIFs](#screenshots--gifs)
|
||||
- [Manual installation](#manual-installation)
|
||||
- [Install in Firefox for Android](#install-in-firefox-for-android)
|
||||
- [Additional notes](#additional-notes)
|
||||
- [Todos / Planned features](#todos--planned-features)
|
||||
- [Contributing](#contributing)
|
||||
|
||||
## Installation
|
||||
|
||||
[link-chrome]: https://chrome.google.com/webstore/detail/fediact/lmpcajpkjcclkjbliapfjfolocffednm 'Version published on Chrome Web Store'
|
||||
[link-firefox]: https://addons.mozilla.org/en-US/firefox/addon/fediact/ 'Version published on Mozilla Add-ons'
|
||||
|
||||
[<img src="https://raw.githubusercontent.com/alrra/browser-logos/90fdf03c/src/chrome/chrome.svg" width="48" alt="Chrome" valign="middle">][link-chrome] [<img valign="middle" src="https://img.shields.io/chrome-web-store/v/lmpcajpkjcclkjbliapfjfolocffednm.svg?label=%20">][link-chrome]
|
||||
and other Chromium browsers
|
||||
[<img src="https://raw.githubusercontent.com/alrra/browser-logos/90fdf03c/src/chrome/chrome.svg" width="48" alt="Chrome" valign="middle">][link-chrome] [<img valign="middle" src="https://img.shields.io/chrome-web-store/v/lmpcajpkjcclkjbliapfjfolocffednm.svg?label=%20"> Chrome Webstore][link-chrome]
|
||||
All up-to-date Chromium browsers, including Kiwi and Yandex browsers on Android
|
||||
|
||||
[<img src="https://raw.githubusercontent.com/alrra/browser-logos/90fdf03c/src/firefox/firefox.svg" width="48" alt="Firefox" valign="middle">][link-firefox] [<img valign="middle" src="https://img.shields.io/amo/v/fediact.svg?label=%20%20">][link-firefox]
|
||||
including Nightly for Android, Orion on iOS (untested)
|
||||
[<img src="https://raw.githubusercontent.com/alrra/browser-logos/90fdf03c/src/firefox/firefox.svg" width="48" alt="Firefox" valign="middle">][link-firefox] [<img valign="middle" src="https://img.shields.io/amo/v/fediact.svg?label=%20%20"> Mozilla Addon Store][link-firefox]
|
||||
Up-to-date Firefox (v107+), including Firefox Nightly on Android
|
||||
|
||||
> **Note**
|
||||
>
|
||||
> - **If webstore release is outdated, use the [manual installation method](#manual-installation) to install the latest version**
|
||||
> - **Special installation steps for [Firefox on Android](#install-in-firefox-for-android)**
|
||||
|
||||
If you like this addon, please consider donating: [paypal.me/lartsch](https://paypal.me/lartsch)
|
||||
**Please note:**
|
||||
- If webstore release is outdated, use the [manual installation method](#manual-installation) to install the latest version
|
||||
- Special installation steps for [Firefox on Android](#install-in-firefox-for-android)
|
||||
- Chrome store updates take 1-2 days longer
|
||||
- If you like this addon, please consider donating: [paypal.me/lartsch](https://paypal.me/lartsch)
|
||||
|
||||
## Setup
|
||||
|
||||
1. Make sure you are logged in to your home instance
|
||||
1. Make sure you are logged in to your home server
|
||||
2. Click the extension icon or open its settings page
|
||||
3. Set your home instance (required)
|
||||
3. Set your home server domain (required)
|
||||
4. Check out the other settings (optional)
|
||||
5. Click the "Submit" button to save
|
||||
5. Click the "Save" button to save
|
||||
|
||||
If you have set your home instance correctly, you can now interact on other Mastodon instances.
|
||||
If you have set your home server correctly, you can now interact on other Mastodon servers.
|
||||
|
||||
### Options explained
|
||||
|
||||
**Redirect settings**
|
||||
|
||||
- Enable (default: on): Set if redirects (when replying or double-clicking) should be performed at all
|
||||
- Prompt (default: off): Set if a prompt should be displayed before redirecting, including the URL
|
||||
- Open in (default: same tab): Set if redirects should happen in the same or a new tab
|
||||
|
||||
**Other**
|
||||
|
||||
- Actions (default: on): Set if actions (following, boosting, etc.) should be performed when clicking or double clicking - _**Usage tip:** Disable this if you only want redirects on double click or when replying without automatically performing the action_
|
||||
- Hide muted/blocked (default: off): If enabled, your blocked/muted users/instances will be synched every 60 seconds and all matching toots, boosts and toots with mentions will be hidden - _**Note:** There are cases where hiding can fail and this is disabled by default because it can decrease performance_
|
||||
- API delay (default: on): If enabled, there can only be one API request to your home instance per 500ms - _**Note:** Disabling this will likely result in the extension not working because your home instance uses rate limiting if too many requests come from your IP. 500ms has proven to prevent error 429 for the instances I have tested_
|
||||
|
||||
**Mode**
|
||||
- Run if logged in (default: off): Enable FediAct on external instances if you are logged in there as well
|
||||
- Blacklist (default) / Whitelist: Run the extension on _all_ domains except those on the blacklist / Run the extension on _no_ domains except those on the whitelist
|
||||
**Please note:**
|
||||
- If FediAct is running, a small icon will be displayed in the bottom right corner
|
||||
- Also, it is indicated while content is resolving or when it could not be resolved
|
||||
- Performance depends on your home server and the external server you are browsing (read more [below](#additional-notes))
|
||||
- Some toots can't be resolved to your home (e.g. when searching the post manually wouldn't work either)
|
||||
- It's NOT recommended to disable the API delay (servers use rate limiting and might block your IP)
|
||||
|
||||
## FAQ
|
||||
**Why does it need permission for all websites?**
|
||||
|
||||
The addon needs to determine whether or not the site you are currently browsing is a Mastodon instance. For that to work, it requires access to all sites. Otherwise, each existing Mastodon instance would have to be explicitly added.
|
||||
> The addon needs to determine whether or not the site you are currently browsing is a Mastodon server. For that to work, it requires access to all sites. Otherwise, each existing Mastodon server would have to be explicitly added.
|
||||
|
||||
**Can I use this on Android?**
|
||||
|
||||
Yes! There are three options that I am aware of: Kiwi Browser (Chromium with add-on support), Yandex Browser and Firefox Nightly (see [below](#install-in-firefox-for-android))
|
||||
> Yes! There are three options that I am aware of: Kiwi Browser, Yandex Browser and Firefox Nightly (see [below](#install-in-firefox-for-android))
|
||||
|
||||
**Can I use this on iOS?**
|
||||
|
||||
There is only one **untested** way to use FediAct on iOS: [Orion Browser](https://apps.apple.com/gb/app/orion-browser-by-kagi/id1484498200). I can not test it myself as I own no Apple devices and this is not guaranteed to work - I can't give support for this. As of now, this addon does **not** support Safari. Safari support will not happen at this time since Apple wants 99$ per year for the [Developer Program membership](https://developer.apple.com/support/compare-memberships), which is a requirement.
|
||||
> Currently not in a reliable way, but:
|
||||
> - It's possible that Orion Browser can soon be used (see issue [#16](https://github.com/Lartsch/FediAct/issues/16))
|
||||
> - There are plans for Safari support (see issue [#17](https://github.com/Lartsch/FediAct/issues/17))
|
||||
|
||||
**Can you add feature XY?**
|
||||
|
||||
Feel free to create an issue here on GitHub and I will look into it.
|
||||
> Feel free to create an issue here on GitHub and I will look into it.
|
||||
|
||||
**Is this safe to use?**
|
||||
|
||||
> This project is open source. Anyone with some programming knowledge can check out the source code, either here on GitHub or by extracting the addon file from the addon stores. You can also make improvements.
|
||||
> Considering the implementation, I am not aware of any risks. Efforts were made to prevent servers from abusing this addon to perform actions on the user's behalf. It does not require your username or password. All data is stored in your browser locally, with the API token being the only sensitive data. This token is **only** sent to your home server. No other data ever leaves your device. All requests are made from the background script, out-of-scope for websites you visit.
|
||||
|
||||
## Screenshots / GIFs
|
||||
v0.8.0
|
||||
v0.9.8
|
||||
<details>
|
||||
<summary>Extension popup / settings</summary>
|
||||
<img src="https://github.com/lartsch/FediAct/blob/main/img/settings.png?raw=true">
|
||||
|
@ -141,17 +131,18 @@ I included all of the default add-ons in the custom collection, so you will not
|
|||
## Additional notes
|
||||
1. Support for other Fedi software is planned
|
||||
2. There are several reasons why resolving/interacting might not work including:
|
||||
- Not being logged in to your home instance
|
||||
- Element identifiers have changed / the instance uses an unsupported flavour
|
||||
- The external instance you are browsing or the originating instance of a toot is not Mastodon
|
||||
- Your home instance has strong rate limiting and limited your IP
|
||||
- Your home instance / the external instance / the original instance of a toot have defederated / are moderated
|
||||
- Not being logged in to your home server
|
||||
- Element identifiers have changed / the server uses an unsupported flavour
|
||||
- The external server you are browsing or the originating server of a toot is not Mastodon
|
||||
- Your home server has strong rate limiting and limited your IP
|
||||
- Your home server / the external server / the original server of a toot have defederated / are moderated
|
||||
- The toot has not yet federated to your home instace (follow the account and toots should start federating)
|
||||
- The instance you are browsing does not use 302 redirects for external toots
|
||||
- The network conditions of your home instance or the external instance are bad (slow speed)
|
||||
- That a toot is set to unlisted on its original instance may play a role
|
||||
- The server you are browsing does not use 302 redirects for external toots
|
||||
- The network conditions of your home server or the external server are bad (slow speed)
|
||||
- That a toot is set to unlisted on its original server may play a role
|
||||
3. There can be delays because API calls have to be made and it is tries to avoid error 429 (too many requests). Especially if a page has many toots or you are scrolling through a feed really fast.
|
||||
4. If the extension fails to resolve content, the affected buttons will behave as if the extension weren't active (popup modal) and a notice ("Unresolved") is added to the toot
|
||||
5. If "Collect errors" is enabled (Chrome), there can be uncatched errors being displayed for FediAct. This is not relevant to functionality.
|
||||
|
||||
## Todos / Planned features
|
||||
Check out the [GitHub project](https://github.com/users/Lartsch/projects/2) to see planned features and todos. They are sorted from most important to least important.
|
||||
|
@ -160,5 +151,6 @@ Check out the [GitHub project](https://github.com/users/Lartsch/projects/2) to s
|
|||
Feel free to create [issues](https://github.com/Lartsch/FediAct/issues) for bugs and feature suggestions. Even better: Create pull requests for whatever improvements you can make! :)
|
||||
|
||||
## Thanks to...
|
||||
@raikasdev because I stole his fix for cross-browser storage API support
|
||||
@rosemarydotworld because I customized and use his awesome jQuery.DOMNodeAppear where MutationObservers and delegation failed
|
||||
- @raikasdev because I stole his fix for cross-browser storage API support
|
||||
- @rosemarydotworld because I customized and use his awesome jQuery.DOMNodeAppear where MutationObservers and delegation failed
|
||||
- All the direct [contributors](https://github.com/Lartsch/FediAct/graphs/contributors) to this repository!
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "FediAct",
|
||||
"version": "0.9.8.1",
|
||||
"version": "0.9.8.7",
|
||||
"description": "Simplifies interactions on other Mastodon instances than your own. Visit https://github.com/lartsch/FediAct for more.",
|
||||
"manifest_version": 2,
|
||||
"content_scripts": [
|
||||
|
@ -13,7 +13,7 @@
|
|||
"src/inject.min.js"
|
||||
],
|
||||
"css": [
|
||||
"src/styles.min.css"
|
||||
"src/content_styles.min.css"
|
||||
],
|
||||
"run_at": "document_start"
|
||||
}
|
||||
|
@ -37,7 +37,7 @@
|
|||
"browser_action": {
|
||||
"default_popup": "src/popup.html",
|
||||
"default_icon": "src/icon/48.png",
|
||||
"default_title": "FediFollow settings"
|
||||
"default_title": "FediAct settings"
|
||||
},
|
||||
"icons": {
|
||||
"48": "src/icon/48.png"
|
||||
|
|
BIN
img/settings.png
BIN
img/settings.png
Plik binarny nie jest wyświetlany.
Przed Szerokość: | Wysokość: | Rozmiar: 38 KiB Po Szerokość: | Wysokość: | Rozmiar: 15 KiB |
BIN
img/showcase.gif
BIN
img/showcase.gif
Plik binarny nie jest wyświetlany.
Przed Szerokość: | Wysokość: | Rozmiar: 6.2 MiB Po Szerokość: | Wysokość: | Rozmiar: 2.4 MiB |
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "FediAct",
|
||||
"version": "0.9.8.1",
|
||||
"version": "0.9.8.7",
|
||||
"description": "Simplifies interactions on other Mastodon instances than your own. Visit https://github.com/lartsch/FediAct for more.",
|
||||
"manifest_version": 3,
|
||||
"content_scripts": [
|
||||
|
@ -13,7 +13,7 @@
|
|||
"src/inject.min.js"
|
||||
],
|
||||
"css": [
|
||||
"src/styles.min.css"
|
||||
"src/content_styles.min.css"
|
||||
],
|
||||
"run_at": "document_start"
|
||||
}
|
||||
|
@ -36,9 +36,9 @@
|
|||
"action": {
|
||||
"default_popup": "src/popup.html",
|
||||
"default_icon": "src/icon/48.png",
|
||||
"default_title": "FediFollow settings"
|
||||
"default_title": "FediAct settings"
|
||||
},
|
||||
"icons": {
|
||||
"48": "src/icon/48.png"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
5
pack.sh
5
pack.sh
|
@ -1,5 +1,6 @@
|
|||
# RUN FROM MAIN DIR
|
||||
# USE ./pack.sh <VERSION>
|
||||
# NOTE: requires uglifyjs and uglifycss in PATH
|
||||
|
||||
# remove all minified files (excluding lib folder) and zip files
|
||||
find . -type d -name lib -prune -o -type f -name "*.min.js" -o -type f -name "*.min.css" -o -type f -name "*.zip" | grep -v "/lib" | tr '\n' '\0' | xargs -r0 rm
|
||||
|
@ -8,5 +9,5 @@ find . -type d -name lib -prune -o -type f -name "*.js" -exec bash -c 'uglifyjs
|
|||
# minify all css files, excluding lib folder
|
||||
find . -type d -name lib -prune -o -type f -name "*.css" -exec bash -c 'uglifycss $1 > "$(echo $1 | rev | cut -f 2- -d '.' | rev).min.css"' _ {} \;
|
||||
# zip release files
|
||||
zip -r "fediact-$1-chrome.zip" ./ -x "firefox/*" -x "img/*" -x ".git/*" -x "README.md" -x "NOTES.md" -x ".gitignore" -x "pack.sh" -x "LICENSE" -x "src/background.js" -x "src/inject.js" -x "src/popup.js" -x "src/styles.css" 1>/dev/null
|
||||
cd firefox && zip -r "../fediact-$1-firefox.zip" ./ -x "src/background.js" -x "src/inject.js" -x "src/popup.js" -x "src/styles.css" 1>/dev/null
|
||||
zip -r "fediact-$1-chrome.zip" ./ -x "firefox/*" -x "img/*" -x ".git/*" -x "README.md" -x "NOTES.md" -x ".gitignore" -x "pack.sh" -x "LICENSE" -x "src/background.js" -x "src/inject.js" -x "src/popup.js" -x "src/content_styles.css" -x "src/popup_styles.css" 1>/dev/null
|
||||
cd firefox && zip -r "../fediact-$1-firefox.zip" ./ -x "src/background.js" -x "src/inject.js" -x "src/popup.js" -x "src/content_styles.css" -x "src/popup_styles.css" 1>/dev/null
|
||||
|
|
|
@ -1,17 +1,16 @@
|
|||
var browser, chrome, settings
|
||||
const enableConsoleLog = true
|
||||
const enableConsoleLog = false
|
||||
const logPrepend = "[FediAct]"
|
||||
const tokenInterval = 1 // minutes
|
||||
const mutesApi = "/api/v1/mutes"
|
||||
const blocksApi = "/api/v1/blocks"
|
||||
const domainBlocksApi = "/api/v1/domain_blocks"
|
||||
const timeout = 15000
|
||||
|
||||
const tokenRegex = /"access_token":".*?",/gm
|
||||
|
||||
// required settings keys with defauls
|
||||
const settingsDefaults = {
|
||||
fediact_homeinstance: null
|
||||
fediact_homeinstance: null,
|
||||
fediact_token: null
|
||||
}
|
||||
|
||||
// wrapper to prepend to log messages
|
||||
|
@ -22,7 +21,7 @@ function log(text) {
|
|||
}
|
||||
|
||||
// get redirect url (it will be the url on the toot authors home instance)
|
||||
async function resolveToot(url) {
|
||||
async function resolveExternalTootHome(url) {
|
||||
return new Promise(async function(resolve) {
|
||||
try {
|
||||
const controller = new AbortController()
|
||||
|
@ -44,6 +43,60 @@ async function resolveToot(url) {
|
|||
})
|
||||
}
|
||||
|
||||
// get redirect url (it will be the url on the toot authors home instance)
|
||||
async function generalRequest(data) {
|
||||
return new Promise(async function(resolve) {
|
||||
try {
|
||||
const controller = new AbortController()
|
||||
const timeoutId = setTimeout(() => {
|
||||
log("Timed out")
|
||||
controller.abort()
|
||||
}, timeout)
|
||||
if (data[3]) {
|
||||
// json body provided, post as body to target
|
||||
data[2]["User-Agent"] = "FediAct Service"
|
||||
data[2]["Content-Type"] = "application/json"
|
||||
var res = await fetch(data[1], {
|
||||
method: data[0],
|
||||
signal: controller.signal,
|
||||
// if json body is provided, there is also header data
|
||||
headers: data[2],
|
||||
body: JSON.stringify(data[3])
|
||||
})
|
||||
} else if (data[2]) {
|
||||
// header data provided
|
||||
data[2]["User-Agent"] = "FediAct Service"
|
||||
var res = await fetch(data[1], {
|
||||
method: data[0],
|
||||
signal: controller.signal,
|
||||
headers: data[2]
|
||||
})
|
||||
} else {
|
||||
var res = await fetch(data[1], {
|
||||
method: data[0],
|
||||
signal: controller.signal,
|
||||
headers: {"User-Agent": "FediAct Service"}
|
||||
})
|
||||
}
|
||||
clearTimeout(timeoutId)
|
||||
if (res.status >= 200 && res.status < 300 ) {
|
||||
const contentType = res.headers.get("content-type")
|
||||
if (contentType && contentType.indexOf("application/json") !== -1) {
|
||||
var restext = await res.text()
|
||||
resolve(restext)
|
||||
} else {
|
||||
resolve(false)
|
||||
}
|
||||
} else {
|
||||
resolve(false)
|
||||
}
|
||||
} catch(e) {
|
||||
log(e)
|
||||
resolve(false)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// fetch API token here (will use logged in session automatically)
|
||||
async function fetchBearerToken() {
|
||||
return new Promise(async function(resolve) {
|
||||
|
@ -85,51 +138,59 @@ async function fetchBearerToken() {
|
|||
// this is only done here in the bg script so we have data available on load of pages without first performing 3 (!) requests
|
||||
// otherwise this would lead to problems with element detection / low performance (espcially v3 instances)
|
||||
// mutes/blocks are updated in content script on page context changes and after performing mutes/block actions
|
||||
async function fetchMutesAndBlocks() {
|
||||
function fetchMutesAndBlocks() {
|
||||
return new Promise(async function(resolve) {
|
||||
// set empty initially
|
||||
[settings.fediact_mutes, settings.fediact_blocks, settings.fediact_domainblocks] = [[],[],[]]
|
||||
var [mutes, blocks, domainblocks] = await Promise.all([
|
||||
fetch("https://" + settings.fediact_homeinstance + mutesApi, {headers: {"Authorization": "Bearer "+settings.fediact_token}}).then((response) => response.json()),
|
||||
fetch("https://" + settings.fediact_homeinstance + blocksApi, {headers: {"Authorization": "Bearer "+settings.fediact_token}}).then((response) => response.json()),
|
||||
fetch("https://" + settings.fediact_homeinstance + domainBlocksApi, {headers: {"Authorization": "Bearer "+settings.fediact_token}}).then((response) => response.json())
|
||||
])
|
||||
if (mutes.length) {
|
||||
settings.fediact_mutes.push(...mutes.map(acc => acc.acct))
|
||||
try {
|
||||
// set empty initially
|
||||
[settings.fediact_mutes, settings.fediact_blocks, settings.fediact_domainblocks] = [[],[],[]]
|
||||
var [mutes, blocks, domainblocks] = await Promise.all([
|
||||
fetch("https://" + settings.fediact_homeinstance + mutesApi, {headers: {"Authorization": "Bearer "+settings.fediact_token}}).then((response) => response.json()),
|
||||
fetch("https://" + settings.fediact_homeinstance + blocksApi, {headers: {"Authorization": "Bearer "+settings.fediact_token}}).then((response) => response.json()),
|
||||
fetch("https://" + settings.fediact_homeinstance + domainBlocksApi, {headers: {"Authorization": "Bearer "+settings.fediact_token}}).then((response) => response.json())
|
||||
])
|
||||
if (mutes.length) {
|
||||
settings.fediact_mutes.push(...mutes.map(acc => acc.acct))
|
||||
}
|
||||
if (blocks.length) {
|
||||
settings.fediact_blocks.push(...blocks.map(acc => acc.acct))
|
||||
}
|
||||
if (domainblocks.length) {
|
||||
settings.fediact_domainblocks = domainblocks
|
||||
}
|
||||
resolve(true)
|
||||
} catch {
|
||||
resolve(false)
|
||||
}
|
||||
if (blocks.length) {
|
||||
settings.fediact_blocks.push(...blocks.map(acc => acc.acct))
|
||||
}
|
||||
if (domainblocks.length) {
|
||||
settings.fediact_domainblocks = domainblocks
|
||||
}
|
||||
resolve(true)
|
||||
})
|
||||
}
|
||||
|
||||
async function fetchData() {
|
||||
async function fetchData(token, mutesblocks) {
|
||||
return new Promise(async function(resolve) {
|
||||
var resolved = false
|
||||
try {
|
||||
settings = await (browser || chrome).storage.local.get(settingsDefaults)
|
||||
if (settings.fediact_homeinstance) {
|
||||
if (token || mutesblocks) {
|
||||
if (token || !(settings.fediact_token)) {
|
||||
await fetchBearerToken()
|
||||
}
|
||||
if (mutesblocks) {
|
||||
await fetchMutesAndBlocks()
|
||||
}
|
||||
try {
|
||||
await (browser || chrome).storage.local.set(settings)
|
||||
resolved = true
|
||||
} catch {
|
||||
log(e)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log("Home instance not set")
|
||||
}
|
||||
} catch(e) {
|
||||
log(e)
|
||||
resolve(false)
|
||||
return
|
||||
}
|
||||
if (settings.fediact_homeinstance) {
|
||||
await fetchBearerToken()
|
||||
await fetchMutesAndBlocks()
|
||||
} else {
|
||||
log("Home instance not set")
|
||||
resolve(false)
|
||||
return
|
||||
}
|
||||
try {
|
||||
await (browser || chrome).storage.local.set(settings)
|
||||
resolve(true)
|
||||
} catch {
|
||||
log(e)
|
||||
}
|
||||
resolve(resolved)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -147,21 +208,30 @@ async function reloadListeningScripts() {
|
|||
}
|
||||
|
||||
// fetch api token right after install (mostly for debugging, when the ext. is reloaded)
|
||||
chrome.runtime.onInstalled.addListener(fetchData)
|
||||
chrome.runtime.onInstalled.addListener(function(){fetchData(true, true)})
|
||||
// and also every 3 minutes
|
||||
chrome.alarms.create('refresh', { periodInMinutes: tokenInterval })
|
||||
chrome.alarms.onAlarm.addListener(fetchData)
|
||||
chrome.alarms.onAlarm.addListener(function(){fetchData(true, true)})
|
||||
|
||||
// different listeners for inter-script communication
|
||||
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
|
||||
// the content script gave us an url to perform a 302 redirect with
|
||||
if(request.url) {
|
||||
resolveToot(request.url).then(sendResponse)
|
||||
if(request.externaltoot) {
|
||||
resolveExternalTootHome(request.externaltoot).then(sendResponse)
|
||||
return true
|
||||
}
|
||||
// the content script gave us an url to perform a 302 redirect with
|
||||
if(request.requestdata) {
|
||||
generalRequest(request.requestdata).then(sendResponse)
|
||||
return true
|
||||
}
|
||||
// immediately fetch api token after settings are updated
|
||||
if (request.updatedsettings) {
|
||||
fetchData().then(reloadListeningScripts)
|
||||
fetchData(true, true).then(reloadListeningScripts)
|
||||
return true
|
||||
}
|
||||
if (request.updatemutedblocked) {
|
||||
fetchData(false, true).then(sendResponse)
|
||||
return true
|
||||
}
|
||||
// when the content script starts to process on a site, listen for tab changes (url)
|
||||
|
|
|
@ -1 +1 @@
|
|||
var browser,chrome,i;const n=!0,a="[FediAct]",t=1,c="/api/v1/mutes",s="/api/v1/blocks",o="/api/v1/domain_blocks",r=15e3,d=/"access_token":".*?",/gm,u={fediact_homeinstance:null};function h(t){n&&console.log(a+" "+t)}async function f(i){return new Promise(async function(e){try{const a=new AbortController;var t=setTimeout(()=>{h("Timed out"),a.abort()},r),n=await fetch(i,{method:"HEAD",signal:a.signal});clearTimeout(t),n.redirected?e(n.url):e(!1)}catch(t){h(t),e(!1)}})}async function l(){return new Promise(async function(e){var t="https://"+i.fediact_homeinstance;try{var n=await(await fetch(t)).text()}catch(t){return h(t),void e(!1)}if(n){t=n.match(d);if(t){var n=t[0].search(/"access_token":"/),a=t[0].search(/",/);if(-1<n&&-1<a){t=t[0].substring(n+=16,a);if(16<t.length)return i.fediact_token=t,void e(!0)}}}i.fediact_token=null,h("Token could not be found."),e(!1)})}async function m(){return new Promise(async function(t){[i.fediact_mutes,i.fediact_blocks,i.fediact_domainblocks]=[[],[],[]];var[e,n,a]=await Promise.all([fetch("https://"+i.fediact_homeinstance+c,{headers:{Authorization:"Bearer "+i.fediact_token}}).then(t=>t.json()),fetch("https://"+i.fediact_homeinstance+s,{headers:{Authorization:"Bearer "+i.fediact_token}}).then(t=>t.json()),fetch("https://"+i.fediact_homeinstance+o,{headers:{Authorization:"Bearer "+i.fediact_token}}).then(t=>t.json())]);e.length&&i.fediact_mutes.push(...e.map(t=>t.acct)),n.length&&i.fediact_blocks.push(...n.map(t=>t.acct)),a.length&&(i.fediact_domainblocks=a),t(!0)})}async function g(){return new Promise(async function(n){try{i=await(browser||chrome).storage.local.get(u)}catch(t){return h(t),void n(!1)}if(i.fediact_homeinstance){await l(),await m();try{await(browser||chrome).storage.local.set(i),n(!0)}catch{h(e)}}else h("Home instance not set"),n(!1)})}async function _(){chrome.tabs.query({},async function(t){for(var e=0;e<t.length;++e)try{chrome.tabs.sendMessage(t[e].id,{updatedfedisettings:!0})}catch(t){continue}})}chrome.runtime.onInstalled.addListener(g),chrome.alarms.create("refresh",{periodInMinutes:t}),chrome.alarms.onAlarm.addListener(g),chrome.runtime.onMessage.addListener((t,a,e)=>t.url?(f(t.url).then(e),!0):t.updatedsettings?(g().then(_),!0):void(t.running&&chrome.tabs.onUpdated.addListener(async function(t,e,n){if(t===a.tab.id&&e.url)try{await chrome.tabs.sendMessage(t,{urlchanged:e.url})}catch(t){h(t)}})));
|
||||
var browser,chrome,c;const a=!1,n="[FediAct]",t=1,i="/api/v1/mutes",s="/api/v1/blocks",o="/api/v1/domain_blocks",r=15e3,d=/"access_token":".*?",/gm,u={fediact_homeinstance:null,fediact_token:null};function h(t){a&&console.log(n+" "+t)}async function f(i){return new Promise(async function(e){try{const n=new AbortController;var t=setTimeout(()=>{h("Timed out"),n.abort()},r),a=await fetch(i,{method:"HEAD",signal:n.signal});clearTimeout(t),a.redirected?e(a.url):e(!1)}catch(t){h(t),e(!1)}})}async function l(c){return new Promise(async function(e){try{const i=new AbortController;var t,a,n=setTimeout(()=>{h("Timed out"),i.abort()},r);t=c[3]?(c[2]["User-Agent"]="FediAct Service",c[2]["Content-Type"]="application/json",await fetch(c[1],{method:c[0],signal:i.signal,headers:c[2],body:JSON.stringify(c[3])})):c[2]?(c[2]["User-Agent"]="FediAct Service",await fetch(c[1],{method:c[0],signal:i.signal,headers:c[2]})):await fetch(c[1],{method:c[0],signal:i.signal,headers:{"User-Agent":"FediAct Service"}}),clearTimeout(n),200<=t.status&&t.status<300&&(a=t.headers.get("content-type"))&&-1!==a.indexOf("application/json")?e(await t.text()):e(!1)}catch(t){h(t),e(!1)}})}async function m(){return new Promise(async function(e){var t="https://"+c.fediact_homeinstance;try{var a=await(await fetch(t)).text()}catch(t){return h(t),void e(!1)}if(a){t=a.match(d);if(t){var a=t[0].search(/"access_token":"/),n=t[0].search(/",/);if(-1<a&&-1<n){t=t[0].substring(a+=16,n);if(16<t.length)return c.fediact_token=t,void e(!0)}}}c.fediact_token=null,h("Token could not be found."),e(!1)})}function g(){return new Promise(async function(t){try{[c.fediact_mutes,c.fediact_blocks,c.fediact_domainblocks]=[[],[],[]];var[e,a,n]=await Promise.all([fetch("https://"+c.fediact_homeinstance+i,{headers:{Authorization:"Bearer "+c.fediact_token}}).then(t=>t.json()),fetch("https://"+c.fediact_homeinstance+s,{headers:{Authorization:"Bearer "+c.fediact_token}}).then(t=>t.json()),fetch("https://"+c.fediact_homeinstance+o,{headers:{Authorization:"Bearer "+c.fediact_token}}).then(t=>t.json())]);e.length&&c.fediact_mutes.push(...e.map(t=>t.acct)),a.length&&c.fediact_blocks.push(...a.map(t=>t.acct)),n.length&&(c.fediact_domainblocks=n),t(!0)}catch{t(!1)}})}async function y(n,i){return new Promise(async function(t){var a=!1;try{if((c=await(browser||chrome).storage.local.get(u)).fediact_homeinstance){if(n||i){!n&&c.fediact_token||await m(),i&&await g();try{await(browser||chrome).storage.local.set(c),a=!0}catch{h(e)}}}else h("Home instance not set")}catch(t){h(t)}t(a)})}async function p(){chrome.tabs.query({},async function(t){for(var e=0;e<t.length;++e)try{chrome.tabs.sendMessage(t[e].id,{updatedfedisettings:!0})}catch(t){continue}})}chrome.runtime.onInstalled.addListener(function(){y(!0,!0)}),chrome.alarms.create("refresh",{periodInMinutes:t}),chrome.alarms.onAlarm.addListener(function(){y(!0,!0)}),chrome.runtime.onMessage.addListener((t,n,e)=>t.externaltoot?(f(t.externaltoot).then(e),!0):t.requestdata?(l(t.requestdata).then(e),!0):t.updatedsettings?(y(!0,!0).then(p),!0):t.updatemutedblocked?(y(!1,!0).then(e),!0):void(t.running&&chrome.tabs.onUpdated.addListener(async function(t,e,a){if(t===n.tab.id&&e.url)try{await chrome.tabs.sendMessage(t,{urlchanged:e.url})}catch(t){h(t)}})));
|
|
@ -0,0 +1,299 @@
|
|||
/*
|
||||
Normal stylings
|
||||
*/
|
||||
|
||||
:root { /* Modal Vars */
|
||||
--bg: #eee;
|
||||
--fg: #494949;
|
||||
--border: rgba(120,120,130,0.3);
|
||||
--hover: rgba(100,100,130,0.2);
|
||||
--confirmation: rgb(38, 133, 0);
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--bg: #24262d;
|
||||
--fg: white;
|
||||
}
|
||||
}
|
||||
|
||||
/* Styles for the mute/block modal popup */
|
||||
|
||||
.fediactmodal {
|
||||
position: fixed;
|
||||
z-index: 99999;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
background-color: rgba(0,0,0,0.4);
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
font-size: 1rem;
|
||||
-webkit-animation: fa_fadeIn .2s;
|
||||
animation: fa_fadeIn .2s;
|
||||
}
|
||||
|
||||
.fediactmodalinner {
|
||||
background-color: var(--bg);
|
||||
border: 1px solid var(--border);
|
||||
width: 80%;
|
||||
max-width: 300px;
|
||||
margin: auto;
|
||||
padding: .4em;
|
||||
border-radius: 8px;
|
||||
-webkit-animation: fa_scaleInSmall .2s;
|
||||
animation: fa_scaleInSmall .2s;
|
||||
}
|
||||
.fediactmodalitem {
|
||||
position: relative;
|
||||
display: block;
|
||||
padding: .7em;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
-webkit-transition: background-color .4s;
|
||||
-o-transition: background-color .4s;
|
||||
transition: background-color .4s;
|
||||
}
|
||||
.fediactmodalitem:hover, .fediactmodalitem:focus-within {
|
||||
background-color: var(--hover);
|
||||
}
|
||||
.fediactmodallink {
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-webkit-box-align: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
color: var(--fg);
|
||||
margin: -.7em;
|
||||
padding: .7em;
|
||||
border-radius: inherit;
|
||||
-webkit-box-shadow: inset 0 0 0 var(--confirmation);
|
||||
box-shadow: inset 0 0 0 var(--confirmation);
|
||||
-webkit-transition: padding .2s, color .2s, -webkit-box-shadow .2s cubic-bezier(.2,.2,0,1);
|
||||
transition: padding .2s, color .2s, -webkit-box-shadow .2s cubic-bezier(.2,.2,0,1);
|
||||
-o-transition: padding .2s, color .2s, box-shadow .2s cubic-bezier(.2,.2,0,1);
|
||||
transition: padding .2s, color .2s, box-shadow .2s cubic-bezier(.2,.2,0,1);
|
||||
transition: padding .2s, color .2s, box-shadow .2s cubic-bezier(.2,.2,0,1), -webkit-box-shadow .2s cubic-bezier(.2,.2,0,1);
|
||||
}
|
||||
.fediactmodallink span:not(:first-of-type) {
|
||||
position: absolute;
|
||||
right: .7em;
|
||||
font-size: .8em;
|
||||
padding: .2em .4em;
|
||||
border-radius: 4px;
|
||||
background-color: white;
|
||||
color: var(--confirmation);
|
||||
-webkit-animation: fa_scaleInFadeSmall .2s;
|
||||
animation: fa_scaleInFadeSmall .2s;
|
||||
}
|
||||
.fediactmodallink.activated {
|
||||
-webkit-box-shadow: inset 300px 0 0 var(--confirmation);
|
||||
box-shadow: inset 300px 0 0 var(--confirmation);
|
||||
color: white;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* Styles for "resolving..." indicator */
|
||||
.fediactprocessing {
|
||||
display: inline-block;
|
||||
height: 1.2em;
|
||||
width: 1.2em;
|
||||
background: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/Pgo8IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPgo8c3ZnIHdpZHRoPSI0MHB4IiBoZWlnaHQ9IjQwcHgiIHZpZXdCb3g9IjAgMCA0MCA0MCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4bWw6c3BhY2U9InByZXNlcnZlIiBzdHlsZT0iZmlsbC1ydWxlOmV2ZW5vZGQ7Y2xpcC1ydWxlOmV2ZW5vZGQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS1taXRlcmxpbWl0OjEuNDE0MjE7IiB4PSIwcHgiIHk9IjBweCI+CiAgICA8ZGVmcz4KICAgICAgICA8c3R5bGUgdHlwZT0idGV4dC9jc3MiPjwhW0NEQVRBWwogICAgICAgICAgICBALXdlYmtpdC1rZXlmcmFtZXMgc3BpbiB7CiAgICAgICAgICAgICAgZnJvbSB7CiAgICAgICAgICAgICAgICAtd2Via2l0LXRyYW5zZm9ybTogcm90YXRlKDBkZWcpCiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIHRvIHsKICAgICAgICAgICAgICAgIC13ZWJraXQtdHJhbnNmb3JtOiByb3RhdGUoLTM1OWRlZykKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgQGtleWZyYW1lcyBzcGluIHsKICAgICAgICAgICAgICBmcm9tIHsKICAgICAgICAgICAgICAgIHRyYW5zZm9ybTogcm90YXRlKDBkZWcpCiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIHRvIHsKICAgICAgICAgICAgICAgIHRyYW5zZm9ybTogcm90YXRlKC0zNTlkZWcpCiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIHN2ZyB7CiAgICAgICAgICAgICAgICAtd2Via2l0LXRyYW5zZm9ybS1vcmlnaW46IDUwJSA1MCU7CiAgICAgICAgICAgICAgICAtd2Via2l0LWFuaW1hdGlvbjogc3BpbiAxLjVzIGxpbmVhciBpbmZpbml0ZTsKICAgICAgICAgICAgICAgIC13ZWJraXQtYmFja2ZhY2UtdmlzaWJpbGl0eTogaGlkZGVuOwogICAgICAgICAgICAgICAgYW5pbWF0aW9uOiBzcGluIDEuNXMgbGluZWFyIGluZmluaXRlOwogICAgICAgICAgICB9CiAgICAgICAgXV0+PC9zdHlsZT4KICAgIDwvZGVmcz4KICAgIDxnIGlkPSJvdXRlciI+CiAgICAgICAgPGc+CiAgICAgICAgICAgIDxwYXRoIGQ9Ik0yMCwwQzIyLjIwNTgsMCAyMy45OTM5LDEuNzg4MTMgMjMuOTkzOSwzLjk5MzlDMjMuOTkzOSw2LjE5OTY4IDIyLjIwNTgsNy45ODc4MSAyMCw3Ljk4NzgxQzE3Ljc5NDIsNy45ODc4MSAxNi4wMDYxLDYuMTk5NjggMTYuMDA2MSwzLjk5MzlDMTYuMDA2MSwxLjc4ODEzIDE3Ljc5NDIsMCAyMCwwWiIgc3R5bGU9ImZpbGw6YmxhY2s7Ii8+CiAgICAgICAgPC9nPgogICAgICAgIDxnPgogICAgICAgICAgICA8cGF0aCBkPSJNNS44NTc4Niw1Ljg1Nzg2QzcuNDE3NTgsNC4yOTgxNSA5Ljk0NjM4LDQuMjk4MTUgMTEuNTA2MSw1Ljg1Nzg2QzEzLjA2NTgsNy40MTc1OCAxMy4wNjU4LDkuOTQ2MzggMTEuNTA2MSwxMS41MDYxQzkuOTQ2MzgsMTMuMDY1OCA3LjQxNzU4LDEzLjA2NTggNS44NTc4NiwxMS41MDYxQzQuMjk4MTUsOS45NDYzOCA0LjI5ODE1LDcuNDE3NTggNS44NTc4Niw1Ljg1Nzg2WiIgc3R5bGU9ImZpbGw6cmdiKDIxMCwyMTAsMjEwKTsiLz4KICAgICAgICA8L2c+CiAgICAgICAgPGc+CiAgICAgICAgICAgIDxwYXRoIGQ9Ik0yMCwzMi4wMTIyQzIyLjIwNTgsMzIuMDEyMiAyMy45OTM5LDMzLjgwMDMgMjMuOTkzOSwzNi4wMDYxQzIzLjk5MzksMzguMjExOSAyMi4yMDU4LDQwIDIwLDQwQzE3Ljc5NDIsNDAgMTYuMDA2MSwzOC4yMTE5IDE2LjAwNjEsMzYuMDA2MUMxNi4wMDYxLDMzLjgwMDMgMTcuNzk0MiwzMi4wMTIyIDIwLDMyLjAxMjJaIiBzdHlsZT0iZmlsbDpyZ2IoMTMwLDEzMCwxMzApOyIvPgogICAgICAgIDwvZz4KICAgICAgICA8Zz4KICAgICAgICAgICAgPHBhdGggZD0iTTI4LjQ5MzksMjguNDkzOUMzMC4wNTM2LDI2LjkzNDIgMzIuNTgyNCwyNi45MzQyIDM0LjE0MjEsMjguNDkzOUMzNS43MDE5LDMwLjA1MzYgMzUuNzAxOSwzMi41ODI0IDM0LjE0MjEsMzQuMTQyMUMzMi41ODI0LDM1LjcwMTkgMzAuMDUzNiwzNS43MDE5IDI4LjQ5MzksMzQuMTQyMUMyNi45MzQyLDMyLjU4MjQgMjYuOTM0MiwzMC4wNTM2IDI4LjQ5MzksMjguNDkzOVoiIHN0eWxlPSJmaWxsOnJnYigxMDEsMTAxLDEwMSk7Ii8+CiAgICAgICAgPC9nPgogICAgICAgIDxnPgogICAgICAgICAgICA8cGF0aCBkPSJNMy45OTM5LDE2LjAwNjFDNi4xOTk2OCwxNi4wMDYxIDcuOTg3ODEsMTcuNzk0MiA3Ljk4NzgxLDIwQzcuOTg3ODEsMjIuMjA1OCA2LjE5OTY4LDIzLjk5MzkgMy45OTM5LDIzLjk5MzlDMS43ODgxMywyMy45OTM5IDAsMjIuMjA1OCAwLDIwQzAsMTcuNzk0MiAxLjc4ODEzLDE2LjAwNjEgMy45OTM5LDE2LjAwNjFaIiBzdHlsZT0iZmlsbDpyZ2IoMTg3LDE4NywxODcpOyIvPgogICAgICAgIDwvZz4KICAgICAgICA8Zz4KICAgICAgICAgICAgPHBhdGggZD0iTTUuODU3ODYsMjguNDkzOUM3LjQxNzU4LDI2LjkzNDIgOS45NDYzOCwyNi45MzQyIDExLjUwNjEsMjguNDkzOUMxMy4wNjU4LDMwLjA1MzYgMTMuMDY1OCwzMi41ODI0IDExLjUwNjEsMzQuMTQyMUM5Ljk0NjM4LDM1LjcwMTkgNy40MTc1OCwzNS43MDE5IDUuODU3ODYsMzQuMTQyMUM0LjI5ODE1LDMyLjU4MjQgNC4yOTgxNSwzMC4wNTM2IDUuODU3ODYsMjguNDkzOVoiIHN0eWxlPSJmaWxsOnJnYigxNjQsMTY0LDE2NCk7Ii8+CiAgICAgICAgPC9nPgogICAgICAgIDxnPgogICAgICAgICAgICA8cGF0aCBkPSJNMzYuMDA2MSwxNi4wMDYxQzM4LjIxMTksMTYuMDA2MSA0MCwxNy43OTQyIDQwLDIwQzQwLDIyLjIwNTggMzguMjExOSwyMy45OTM5IDM2LjAwNjEsMjMuOTkzOUMzMy44MDAzLDIzLjk5MzkgMzIuMDEyMiwyMi4yMDU4IDMyLjAxMjIsMjBDMzIuMDEyMiwxNy43OTQyIDMzLjgwMDMsMTYuMDA2MSAzNi4wMDYxLDE2LjAwNjFaIiBzdHlsZT0iZmlsbDpyZ2IoNzQsNzQsNzQpOyIvPgogICAgICAgIDwvZz4KICAgICAgICA8Zz4KICAgICAgICAgICAgPHBhdGggZD0iTTI4LjQ5MzksNS44NTc4NkMzMC4wNTM2LDQuMjk4MTUgMzIuNTgyNCw0LjI5ODE1IDM0LjE0MjEsNS44NTc4NkMzNS43MDE5LDcuNDE3NTggMzUuNzAxOSw5Ljk0NjM4IDM0LjE0MjEsMTEuNTA2MUMzMi41ODI0LDEzLjA2NTggMzAuMDUzNiwxMy4wNjU4IDI4LjQ5MzksMTEuNTA2MUMyNi45MzQyLDkuOTQ2MzggMjYuOTM0Miw3LjQxNzU4IDI4LjQ5MzksNS44NTc4NloiIHN0eWxlPSJmaWxsOnJnYig1MCw1MCw1MCk7Ii8+CiAgICAgICAgPC9nPgogICAgPC9nPgo8L3N2Zz4K') no-repeat center center;
|
||||
background-size: 1em 1em;
|
||||
padding-left: 10px; /* for instances where action bar is not full width */
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
/* Styles for unresolved indicator */
|
||||
|
||||
.fediactunresolved {
|
||||
display: inline-block;
|
||||
height: 1.2em;
|
||||
width: 1.2em;
|
||||
color: orange;
|
||||
font-weight: bold;
|
||||
padding-right: 10px;
|
||||
padding-left: 10px
|
||||
}
|
||||
|
||||
/* Styles for after a poll was voted */
|
||||
|
||||
.fediactvoted {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.fediactvoted > a {
|
||||
font-weight: bold !important;
|
||||
color: orange !important;
|
||||
}
|
||||
|
||||
/* Inserted in the bottom right of any external instance where FediAct is running */
|
||||
|
||||
.fediacticon {
|
||||
height: 32px;
|
||||
width: 32px;
|
||||
position: fixed;
|
||||
z-index: 99998;
|
||||
bottom: 50px;
|
||||
right: 20px;
|
||||
background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAAAXNSR0IArs4c6QAAAARzQklUCAgICHwIZIgAAA1ISURBVGhD1VoJdFTlFf7em0z2hYQlkEBYDCYsglCO4IIrKi5YVKpAFSUQNwixPbVae6QKIlg2RSKtK3hAj4KgoHVBqSIuBaQeoUKIYliyEQIh6ySZea/f/d97yWQykwCHnmP/k5fAm3+5393/e0fLGDjCREfD5BR5XC4gKgFadCLQqQcQ1w1aXBfrXVQ8EBEDhEVBc0cAehjn85FheAGfF6a3AWiqBxpqAU81zLpKmDUVQHU5zBNFAP+P+pNqLjTNejoYWkgAhg8IjwaS0qAl94fWtR+0Tt0BIZ6EakKgTkDOIQIQ9hOKJYoe+eVHnKzjWaaAbKxTIMzKYpjHCmGWFQDHDvI9ActZQUZwAN5GaL2GQvvVLdC69APIUU0IlcPkfFMIkL9BKG0mMthxIslgVMjegsv+nGeZsrevEWb5zzC/2wjz5+2ULiUbMAIAcCOKXRtyA1wjJ1pTfU2tOdaRTM/W50ptDdLjJjAdBkEYO9cCZK7/aA2ACPXRWdDSLyGDbVadgh6eLZqD7mNL2SQIs2AbjK9WWTZkjxYA5LQ2ejr0wddQkraqKD35hQzSZIpq5W+FsSWv2UFYAGhEWuYVcI2ZZXkJou1wODrrTHTsosOFYju2vp/uWmEs7dH3+Qswd3+oDNsC0CkFrusfgRaTZG3ZjtqIcfmommEuDVFhGtwuHU2GAU+TiSafCf7XMvggI9haL9fWn8JatZ2jTg018G2cC1QWEcCA4aY2YgL04fQ47RAvnzWS8mi3C9edG4vL+8WiZ4KbADRFeHGVF5/+VI2PC6pR02ginO8dhyNrZU4EAV+fEafW9rLXev3X/liDqgYDEX5r2/DBViVj13qYO9YRwKALTNf4J+gu+7bDeWoZqTm/RxRmX5mMjC7hbSVlc2dfeQMe33IUe0rrmyUhnB/YLRKPX5XMv7Yr9JeSvbagogFP/rMcO4vqoLfnjumdzIqD8G2aRwCXTjBd42ZDCyNR7Yj+hsx4/HF0VyRFS3Q120pLOGPpHyrqvJi9uQzbDtYqqV/SJ4bAu6F7HF1iB2urGnyY/9lRvL+vKjRD5Sy6U+OjRdAGTHzc1EdNtnxuEABCQNcYF1ZO6IVendzQSaAzzZCNlEHamYb9gY8v95R5MHNjETxeEy/d3BPndY8kVy3bkHVWILSOdN6roMyXhyubcN+7RTh8kp4xuDEpR+PbtQHawAfXmFq/kS35h98CWVzb5CPnu+GeC5KsJEBcmTIo+TFR12iANIJqiyi3TiO20Mic5V9XoM5rKMk59uWjLnqarDU0CbVGAWgO7tba13adwJwtZYgJd7UN3iovC4N58N8EMPtTU+vci9DbSkB0Nzpcx8Y7+yA51t2KG3UkYt2ek9hyoAbVHh9iI3Rc1jcWEwYnID7CylvqOUeIiSaRMmTNG99XYlthLU5yTXykC5dSvW4f0gkx9hybNyivbcK41w6itpEuPlAzlAQZ2E6WEMCCnaYWyUySwrPk2jK85NawlCisua1Xyya2a3lp53Es/KJceQz/ldNHJCH3ImaoQcbftlcg7xtmn5YA1WmN9EKzLuyMGaPsNQ4JJHLKuiPYfqQObsui/Ya12mRE1gYt2mMiTIyr7WiknMcNiMOi63qoA0XU4o2Ee3evO4yfKpiX+O0tc2IosQ/v6oPEKDuVtret9Hgx9tVC1FAKrcjhoh7xYXhrUm8kUCJCq9iIzPnzx6WUchXCRdeCDQnAg5bu5ezgkbeBAG4fkoC5Y5KbAYgO/3yiEdkbjuBYLdPggI0lVrwwvicu7cuU2/5M5nx1qA5T3z5MibU+S+YI6NWUct/EcGVDDoB5n5VjFW1B4kfQIUA7AjBpaAKeoP92JCAAfiTnBcCJ+tYA5JgaGvXi63tg/MD4VgD+kV+NmZuKEUdi/UHLmkgSuPq2NKR3bg3gqc/LsfLbdgDw4qMNeiY/kInNYEUCoQBM33AYlfWWkTpDbE0MeuF1Kbh1cGsAm/ZWY9Z7Rcpw/a8RAkA4vOYMAJhNnv9XALYR81pKFdpHRQquY79YCSg3Si/E+7Q2aMl/THUBDzJ+0QCYSpsVh8SN7qYbtZOzABBnCuCvY1NwS4ANvEcbyH3/LNmASEAAlOwjgIXfm3JJOFsSqKIRL7sxVcUPfzf64f4a3PfOESREnQUjdlKJA/+SSPwtI3Ec6W8biU9XAsIEiQMX945BelK4pH2KL5LdSOzYyhQiPEgcOG0vpCQQBuOHzQQwZ5upJXQLmgudCQAhWC4p/Gk1JMLK5SdwnJkbtbyQb/ubBPDYJ6bWJe2sAggeNoO/PWMADKi+LcsJ4JFNptYjU1XHAt2pSGCiRGLewlpF4uMSidsGstMhvDn42YFMRWKqnX8qMX9riEgs6TqDmG/Tk+3fBwSApMePXt6VF3kJF1Ixg9LnHKYFktSFDOOniMaRwIu89EguZBUApTigYfG2Y1jzXWXbXEgAVB0lgDm8kWXnmfp5Y60KXEBAk6QqkaE/hdmi6LQcJgRLCiy3pkA9P0Wag9pB70S3KgQ4Z4i5lFR7cZz5VptsWtxC4bcwPlnGctDEv5iuUb8NfaUUooOwWQ46W0U72T+YJNUZtn9sztvl6svh+2gxcHAXL/Vjs82wa39/asWsM2Vxu+sk93eKBC0TFShTR2qnQ7jynM30mh7ex3mX0JnNshyPgi9QeZw39IwLx5mum+eyph8VeCH7n5DbelMpkrnQ4OXZATLQNR/TbA+uzdyIx66Yw2spK4acI6Vmr8QsAjS8VLmMoaNN162sr8QnnwbBjsBDXDROaSepaGjo27kA4wev46WGDQ97nVx5dpcMxdu7JyMpqgJXZ36A2IZ8eo+vMWZMGc7pV6/CrooGGZnDTdcNf4LWc8jpS0AZhx8YhedUQFlrMrvtwbyxD7FKV8jg57Z2omHpmgvfFI1EzlsroB/bj6aC7TCZNtw9aR+y7y2GHknyDZY1+VeVFvWRk6Cff5ODqUP+mV6PIlSTDo7U71VBh3HElEcpr+UUQg1173Xhrgv+jpxRy7D1yMVYuTMXpmTFTWxqUMfL8o+h9LtC6OX57EZ5MDW7FA/MKEZUtIH589Iw/qYKpA/mpV6Ku1racOjX5JIkCo9G0tEwDuyA8eVKIDEVWhJLMgndoSUkQ4tlZcFNUG5mty55SJBy7H47EphGl200NSHrohWYdcnLWPjBZLy0fgzCawqtjkz5AeieE6wWsvrMTHnylFI89IfDqKp14dmlqXh9VTLWrv8B6QNtANKk0298FHoiiQmS1LUCRO4aJXthvL+AU2lSKoKzDiTAJS0XZyCtID6aVDtUH00e7uLjXIk3BsuCjY2YnrUfudkHsCQvBS8+1wPuMPbJVIWL3sVm5NTsEkydViL+B88s6omN67sonqx8bR8yHAmo/sCI38AlJUaG6HYdvERB3oR8G59g2e5Eiw04NUYViawbU/NwAonzjr0ww6ch+4Fi5PJZspwA8lLhdlui0vh5fb2Ou0n8jJxiREQZWEC12fAmK3zcVviQ82Ax0jPq7P6A6Cul4LptIVRqHUiAvwjsz3xbX4a5h02GEJehDtWQR7YASCWAFAKwUnoBcPsdZXj44SOoptosXZSKNSu7IyaWqYs0Uji8BCHK0rrFNOAq6JdlW3l8qDDrlPXqK+Hb/CxQ/EPIFmh7IAwSkn2/SKCIErAAhIezykEhTMkqpbcpUeFtCdXm3bW0LTF8ep6MAbXo19eDrVs7oa5WApnT6FZxm5Wxqx+E3nt4+x7JuVSzKW18tRrmj1+SJWxi2x1Fq0kd6AzsfEGpk8Eg5EP2jBLkzjzaDMBNAHFxPqx+Yy9SejXgqblpeGdtV9sH0MXoJpasKMCwjHrk/K4fvt8V6wfAYVdiT7jom5VHcdxHSGlwCo3N4N3U/OlrNqb3W912sSMxVum4N+9BQxaA4ezks1FuxqdiWtY+5N7ymW0DlgRk3HFXGcqOuvHOuq6IiWlRm7AwE3mv5OP8/vW4f1Y6du0IBkDsoUsfuEZPUx16VbW2LKutRihJCAi6SzFu6eGyf6UAyL8VAPuqKt5I7EUAMH4YeiSmjVqOnJHLsYQeyLEB0XEnlMg3G/yHAHj+1XwMO7cO987sHwKAWkHCWLHWL7oTWv/RKtlS7jKUbTSnq3YybCX19tkOcOsaaAVqeiFDR9bI5zBrVB4WL0vByyu6IyLCbpiEMB5RobxX9mM4vU8HAOwdSISWfjG0Yb+GxqAlUlA9ZCUR+1dgrh2YTrT53AInnM4a9Rxmjnweq9Z0xdKne6pQEuqCJNvG0gste3E/BqR5cF+OqBArHx1+W0XUIJKV5uQM1sEzofNLH5DEL5rfUFF9NYm2oin+eVEAGWLQjgrKfk11TBcqcFny65gzZTV8LgNFB9j/ZWxoL5OSeJDW24OjpeHInn4uSop5g+sQgCNOJzaILktDJLazSiPUw6/dQHrMkbGMxJFMzSOb8yP1FZt6NuzqjrOjUso0gelCRaH6io0btZh8Rymy7ilBJIkLxX2HBOHBoQOReHp+GnZ8w+Ix48V/AVFU3fKxDtrWAAAAAElFTkSuQmCC');
|
||||
background-size: 32px 32px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.fediactsettings_onsite {
|
||||
position: fixed;
|
||||
z-index: 99998;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
background-color: rgba(0,0,0,0.4);
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.fediactsettings_onsite .fediactsettings_onsite_inner {
|
||||
position: absolute;
|
||||
bottom: 15px;
|
||||
right: 15px;
|
||||
padding: 10px 15px;
|
||||
background: white;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.fediactsettings_onsite .fediactsettings_onsite_inner a {
|
||||
color: blue !important;
|
||||
}
|
||||
|
||||
/* keyframes fa_*/
|
||||
|
||||
@-webkit-keyframes fa_fadeIn {
|
||||
from {
|
||||
-webkit-filter: opacity(0);
|
||||
filter: opacity(0);
|
||||
}
|
||||
}
|
||||
@keyframes fa_fadeIn {
|
||||
from {
|
||||
-webkit-filter: opacity(0);
|
||||
filter: opacity(0);
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes fa_fadeOut {
|
||||
to {
|
||||
-webkit-filter: opacity(0);
|
||||
filter: opacity(0);
|
||||
}
|
||||
}
|
||||
@keyframes fa_fadeOut {
|
||||
to {
|
||||
-webkit-filter: opacity(0);
|
||||
filter: opacity(0);
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes fa_scaleInSmall {
|
||||
from {
|
||||
-webkit-transform: scale(.98);
|
||||
transform: scale(.98);
|
||||
}
|
||||
}
|
||||
@keyframes fa_scaleInSmall {
|
||||
from {
|
||||
-webkit-transform: scale(.98);
|
||||
transform: scale(.98);
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes fa_scaleInFadeSmall {
|
||||
from {
|
||||
-webkit-transform: scale(.98);
|
||||
transform: scale(.98);
|
||||
-webkit-filter: opacity(0);
|
||||
filter: opacity(0);
|
||||
}
|
||||
}
|
||||
@keyframes fa_scaleInFadeSmall {
|
||||
from {
|
||||
-webkit-transform: scale(.98);
|
||||
transform: scale(.98);
|
||||
-webkit-filter: opacity(0);
|
||||
filter: opacity(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
We insert these styles for the DOMNodeAppeared function as separate stylesheet (see manifest) to fix
|
||||
Firefox blocking script-inserted <style> elements due to the site's CSP (long time bug)
|
||||
*/
|
||||
|
||||
@-moz-keyframes fa_nodeInserted {
|
||||
from {
|
||||
opacity: 1;
|
||||
} to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes fa_nodeInserted {
|
||||
from {
|
||||
opacity: 1;
|
||||
} to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
@-ms-keyframes fa_nodeInserted {
|
||||
from {
|
||||
opacity: 1;
|
||||
} to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
@-o-keyframes fa_nodeInserted {
|
||||
from {
|
||||
opacity: 1;
|
||||
} to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
@keyframes fa_nodeInserted {
|
||||
from {
|
||||
opacity: 1;
|
||||
} to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
div.status,
|
||||
div.detailed-status,
|
||||
div.detailed-status__action-bar,
|
||||
div.account__header button.logo-button,
|
||||
div.account__header button.button--follow,
|
||||
div.public-account-header a.logo-button,
|
||||
div.account-card a.logo-button,
|
||||
div.directory-card a.icon-button,
|
||||
div.detailed-status a.logo-button,
|
||||
button.remote-button,
|
||||
script#initial-state {
|
||||
-webkit-animation-name: fa_nodeInserted !important;
|
||||
-webkit-animation-duration: 0.001s !important;
|
||||
-ms-animation-name: fa_nodeInserted !important;
|
||||
-ms-animation-duration: 0.001s !important;
|
||||
-moz-animation-name: fa_nodeInserted !important;
|
||||
-moz-animation-duration: 0.001s !important;
|
||||
-o-animation-name: fa_nodeInserted !important;
|
||||
-o-animation-duration: 0.001s !important;
|
||||
animation-name: fa_nodeInserted !important;
|
||||
animation-duration: 0.001s !important;
|
||||
}
|
File diff suppressed because one or more lines are too long
453
src/inject.js
453
src/inject.js
|
@ -2,7 +2,7 @@
|
|||
// =-=-=-=-=-= CONSTANTS =-==-=-=-=
|
||||
// =-=-=-=-==-=-=-=-==-=-=-=-==-=-=
|
||||
|
||||
const followButtonPaths = ["div.account__header button.logo-button","div.public-account-header a.logo-button","div.account-card a.logo-button","div.directory-card a.icon-button", "div.detailed-status a.logo-button", "button.remote-button", "div.account__header button.button--follow"]
|
||||
const followButtonPaths = ["div.account__header button.logo-button","div.public-account-header a.logo-button","div.account-card a.logo-button","div.directory-card a.icon-button", "div.directory__card a.icon-button", "div.detailed-status a.logo-button", "button.remote-button", "div.account__header button.button--follow"]
|
||||
const profileNamePaths = ["div.account__header__tabs__name small", "div.public-account-header__tabs__name small", "div.detailed-status span.display-name__account", "div.display-name > span", "a.user-screen-name", "div.profile-info-panel small"]
|
||||
const domainRegex = /^([a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,}$/
|
||||
const handleExtractUrlRegex = /^(?<domain>https?:\/\/(?:\.?[a-z0-9-]+)+(?:\.[a-z]+){1})?\/?@(?<handle>\w+)(?:@(?<handledomain>(?:[\w-]+\.)+?\w+))?(?:\/(?<tootid>\d+))?\/?$/
|
||||
|
@ -17,10 +17,10 @@ const mutesApi = "/api/v1/mutes"
|
|||
const blocksApi = "/api/v1/blocks"
|
||||
const domainBlocksApi = "/api/v1/domain_blocks"
|
||||
const pollsApi = "/api/v1/polls"
|
||||
const apiDelay = 500
|
||||
const apiDelay = 600
|
||||
const maxTootCache = 200
|
||||
const modalHtml = '<div class="fediactmodal"><div class="fediactmodalinner"><ul class="fediactmodallist"></ul></div></div>'
|
||||
const timeout = 15000
|
||||
const maxAsyncRequests = 10
|
||||
|
||||
// settings keys with defauls
|
||||
var settings = {}
|
||||
|
@ -79,7 +79,7 @@ function log(text) {
|
|||
// catch all animationstart events
|
||||
$(document).on('animationstart webkitAnimationStart oanimationstart MSAnimationStart', function(e){
|
||||
// check if the animatonname equals our animation and if the element is one of our selectors
|
||||
if (e.originalEvent.animationName == 'nodeInserted' && $(e.target).is(selector)) {
|
||||
if (e.originalEvent.animationName == 'fa_nodeInserted' && $(e.target).is(selector)) {
|
||||
if (typeof callback == 'function') {
|
||||
// return the complete object in the callback
|
||||
callback(e)
|
||||
|
@ -125,69 +125,60 @@ var getUrlParameter = function getUrlParameter(sParam) {
|
|||
return false
|
||||
}
|
||||
|
||||
// promisified xhr for api calls
|
||||
async function makeRequest(method, url, extraheaders, jsonbody) {
|
||||
// try to prevent error 429 too many request by delaying home instance requests
|
||||
if (~url.indexOf(settings.fediact_homeinstance) && settings.fediact_enabledelay) {
|
||||
// get current time
|
||||
var currenttime = Date.now()
|
||||
// get difference of current time and time of last request
|
||||
var difference = currenttime - tmpSettings.lasthomerequest
|
||||
// if difference is smaller than our set api delay value...
|
||||
if (difference < apiDelay) {
|
||||
// ... then wait the time required to reach the api delay value...
|
||||
await new Promise(resolve => {
|
||||
setTimeout(function() {
|
||||
resolve()
|
||||
}, apiDelay-difference)
|
||||
})
|
||||
}
|
||||
// TODO: move this to the top? or get new Date.now() here?
|
||||
tmpSettings.lasthomerequest = currenttime
|
||||
const asyncLimit = (fn, n) => {
|
||||
let pendingPromises = []
|
||||
return async function (...args) {
|
||||
while (pendingPromises.length >= n) {
|
||||
await Promise.race(pendingPromises).catch(() => {})
|
||||
}
|
||||
const p = fn.apply(this, args)
|
||||
pendingPromises.push(p)
|
||||
await p.catch(() => {})
|
||||
pendingPromises = pendingPromises.filter(pending => pending !== p)
|
||||
return p
|
||||
}
|
||||
// return a new promise...
|
||||
return new Promise(function (resolve) {
|
||||
// create xhr
|
||||
let xhr = new XMLHttpRequest()
|
||||
// open it with the method and url specified
|
||||
xhr.open(method, url)
|
||||
// set timeout
|
||||
xhr.timeout = timeout
|
||||
// set extra headers if any were given
|
||||
if (extraheaders) {
|
||||
for (var key in extraheaders) {
|
||||
xhr.setRequestHeader(key, extraheaders[key])
|
||||
}
|
||||
|
||||
// promisified xhr for api calls
|
||||
function makeRequest(method, url, extraheaders, jsonbody) {
|
||||
return new Promise(async function(resolve) {
|
||||
// try to prevent error 429 too many request by delaying home instance requests
|
||||
if (~url.indexOf(settings.fediact_homeinstance) && settings.fediact_enabledelay) {
|
||||
// get current time
|
||||
var currenttime = Date.now()
|
||||
// get difference of current time and time of last request
|
||||
var difference = currenttime - tmpSettings.lasthomerequest
|
||||
// if difference is smaller than our set api delay value...
|
||||
if (difference < apiDelay) {
|
||||
// ... then wait the time required to reach the api delay value...
|
||||
await new Promise(resolve => {
|
||||
setTimeout(function() {
|
||||
resolve()
|
||||
}, apiDelay-difference)
|
||||
})
|
||||
}
|
||||
tmpSettings.lasthomerequest = Date.now()
|
||||
}
|
||||
// on load, check if status is OK...
|
||||
xhr.onload = function () {
|
||||
if (this.status >= 200 && this.status < 300) {
|
||||
// is ok, resolve promise with response
|
||||
resolve(xhr.responseText)
|
||||
} else {
|
||||
// nope, resolve false
|
||||
resolve(false)
|
||||
}
|
||||
}
|
||||
xhr.ontimeout = function() {
|
||||
log("Timed out")
|
||||
resolve(false)
|
||||
try {
|
||||
await chrome.runtime.sendMessage({requestdata: [method, url, extraheaders, jsonbody]}, function(response) {
|
||||
if(response) {
|
||||
resolve(response)
|
||||
} else {
|
||||
resolve(false)
|
||||
}
|
||||
})
|
||||
} catch (e) {
|
||||
// if we encounter an error here, it is likely since the extension context got invalidated, so reload the page
|
||||
log(e)
|
||||
log("Reloading page, extension likely got updated or reloaded.")
|
||||
location.reload()
|
||||
}
|
||||
// on any error, resolve false
|
||||
xhr.onerror = function() {
|
||||
log("Request to " + url + " failed.")
|
||||
resolve(false)
|
||||
}
|
||||
// send the request
|
||||
if (jsonbody) {
|
||||
xhr.setRequestHeader("Content-Type","application/json")
|
||||
xhr.send(JSON.stringify(jsonbody))
|
||||
} else {
|
||||
xhr.send()
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// wrap so there are never more than 10 concurrent requests
|
||||
const requestAsyncLimited = asyncLimit(makeRequest, maxAsyncRequests)
|
||||
|
||||
// Escape characters used for regex
|
||||
function escapeRegExp(string) {
|
||||
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
|
||||
|
@ -202,6 +193,16 @@ function replaceAll(str, find, replace) {
|
|||
function redirectTo(url) {
|
||||
// check if redirects are enabled at all
|
||||
if (settings.fediact_redirects) {
|
||||
if (settings.fediact_target == "_self") {
|
||||
/* If browser back button was used, flush cache */
|
||||
(function () {
|
||||
window.onpageshow = function(event) {
|
||||
if (event.persisted) {
|
||||
window.location.reload();
|
||||
}
|
||||
};
|
||||
})()
|
||||
}
|
||||
// check if alert before redirect is enabled and show the prompt if so
|
||||
if (settings.fediact_alert) {
|
||||
if (!confirm("Redirecting to " + url)) {
|
||||
|
@ -228,89 +229,94 @@ function redirectTo(url) {
|
|||
// =-=-=-=-= INTERACTIONS =-=-=-=-=
|
||||
// =-=-=-=-==-=-=-=-==-=-=-=-==-=-=
|
||||
|
||||
async function executeAction(id, action, polldata) {
|
||||
async function executeAction(data, action, polldata) {
|
||||
var requestUrl, condition, jsonbody, after
|
||||
var method = "POST"
|
||||
switch (action) {
|
||||
case 'copy':
|
||||
// special action. only copy to clipboard and return
|
||||
navigator.clipboard.writeText(data)
|
||||
return true
|
||||
case 'domainblock':
|
||||
requestUrl = 'https://' + settings.fediact_homeinstance + domainBlocksApi + "?domain=" + id
|
||||
requestUrl = 'https://' + settings.fediact_homeinstance + domainBlocksApi + "?domain=" + data
|
||||
condition = function(response) {if(response){return true}}
|
||||
after = function() {updateMutedBlocked()}
|
||||
after = async function() {await updateMutedBlocked()}
|
||||
break
|
||||
case 'domainunblock':
|
||||
requestUrl = 'https://' + settings.fediact_homeinstance + domainBlocksApi + "?domain=" + id
|
||||
requestUrl = 'https://' + settings.fediact_homeinstance + domainBlocksApi + "?domain=" + data
|
||||
condition = function(response) {if(response){return true}}
|
||||
method = "DELETE"
|
||||
after = function() {updateMutedBlocked()}
|
||||
after = async function() {await updateMutedBlocked()}
|
||||
break
|
||||
case 'mute':
|
||||
requestUrl = 'https://' + settings.fediact_homeinstance + accountsApi + "/" + id + "/mute"
|
||||
requestUrl = 'https://' + settings.fediact_homeinstance + accountsApi + "/" + data + "/mute"
|
||||
condition = function(response) {return response.muting}
|
||||
after = function() {updateMutedBlocked()}
|
||||
after = async function() {await updateMutedBlocked()}
|
||||
break
|
||||
case 'unmute':
|
||||
requestUrl = 'https://' + settings.fediact_homeinstance + accountsApi + "/" + id + "/unmute"
|
||||
requestUrl = 'https://' + settings.fediact_homeinstance + accountsApi + "/" + data + "/unmute"
|
||||
condition = function(response) {return !response.muting}
|
||||
after = function() {updateMutedBlocked()}
|
||||
after = async function() {await updateMutedBlocked()}
|
||||
break
|
||||
case 'block':
|
||||
requestUrl = 'https://' + settings.fediact_homeinstance + accountsApi + "/" + id + "/block"
|
||||
requestUrl = 'https://' + settings.fediact_homeinstance + accountsApi + "/" + data + "/block"
|
||||
condition = function(response) {return response.blocking}
|
||||
after = function() {updateMutedBlocked()}
|
||||
after = async function() {await updateMutedBlocked()}
|
||||
break
|
||||
case 'unblock':
|
||||
requestUrl = 'https://' + settings.fediact_homeinstance + accountsApi + "/" + id + "/unblock"
|
||||
requestUrl = 'https://' + settings.fediact_homeinstance + accountsApi + "/" + data + "/unblock"
|
||||
condition = function(response) {return !response.blocking}
|
||||
after = function() {updateMutedBlocked()}
|
||||
after = async function() {await updateMutedBlocked()}
|
||||
break
|
||||
case 'vote':
|
||||
requestUrl = 'https://' + settings.fediact_homeinstance + pollsApi + "/" + id + "/votes"
|
||||
requestUrl = 'https://' + settings.fediact_homeinstance + pollsApi + "/" + data + "/votes"
|
||||
condition = function(response) {return response.voted}
|
||||
jsonbody = polldata
|
||||
break
|
||||
case 'follow':
|
||||
requestUrl = 'https://' + settings.fediact_homeinstance + accountsApi + "/" + id + "/follow"
|
||||
requestUrl = 'https://' + settings.fediact_homeinstance + accountsApi + "/" + data + "/follow"
|
||||
condition = function(response) {return response.following || response.requested}
|
||||
break
|
||||
case 'boost':
|
||||
requestUrl = 'https://' + settings.fediact_homeinstance + statusApi + "/" + id + "/reblog"
|
||||
requestUrl = 'https://' + settings.fediact_homeinstance + statusApi + "/" + data + "/reblog"
|
||||
condition = function(response) {return response.reblogged}
|
||||
break
|
||||
case 'favourite':
|
||||
requestUrl = 'https://' + settings.fediact_homeinstance + statusApi + "/" + id + "/favourite"
|
||||
requestUrl = 'https://' + settings.fediact_homeinstance + statusApi + "/" + data + "/favourite"
|
||||
condition = function(response) {return response.favourited}
|
||||
break
|
||||
case 'bookmark':
|
||||
requestUrl = 'https://' + settings.fediact_homeinstance + statusApi + "/" + id + "/bookmark"
|
||||
requestUrl = 'https://' + settings.fediact_homeinstance + statusApi + "/" + data + "/bookmark"
|
||||
condition = function(response) {return response.bookmarked}
|
||||
break
|
||||
case 'unfollow':
|
||||
requestUrl = 'https://' + settings.fediact_homeinstance + accountsApi + "/" + id + "/unfollow"
|
||||
requestUrl = 'https://' + settings.fediact_homeinstance + accountsApi + "/" + data + "/unfollow"
|
||||
condition = function(response) {return !response.following && !response.requested}
|
||||
break
|
||||
case 'unboost':
|
||||
requestUrl = 'https://' + settings.fediact_homeinstance + statusApi + "/" + id + "/unreblog"
|
||||
requestUrl = 'https://' + settings.fediact_homeinstance + statusApi + "/" + data + "/unreblog"
|
||||
condition = function(response) {return !response.reblogged}
|
||||
break
|
||||
case 'unfavourite':
|
||||
requestUrl = 'https://' + settings.fediact_homeinstance + statusApi + "/" + id + "/unfavourite"
|
||||
requestUrl = 'https://' + settings.fediact_homeinstance + statusApi + "/" + data + "/unfavourite"
|
||||
condition = function(response) {return !response.favourited}
|
||||
break
|
||||
case 'unbookmark':
|
||||
requestUrl = 'https://' + settings.fediact_homeinstance + statusApi + "/" + id + "/unbookmark"
|
||||
requestUrl = 'https://' + settings.fediact_homeinstance + statusApi + "/" + data + "/unbookmark"
|
||||
condition = function(response) {return !response.bookmarked}
|
||||
break
|
||||
default:
|
||||
log("No valid action specified."); break
|
||||
log("No valid action specified.")
|
||||
return
|
||||
}
|
||||
if (requestUrl) {
|
||||
var response = await makeRequest(method, requestUrl, tmpSettings.tokenheader, jsonbody)
|
||||
var response = await requestAsyncLimited(method, requestUrl, tmpSettings.tokenheader, jsonbody)
|
||||
if (response) {
|
||||
// convert to json object
|
||||
response = JSON.parse(response)
|
||||
if (condition(response)) {
|
||||
if (after !== undefined) {
|
||||
after()
|
||||
await after()
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
@ -328,7 +334,7 @@ async function isFollowingHomeInstance(ids) {
|
|||
requestUrl += "id[]=" + id.toString() + "&"
|
||||
}
|
||||
// make the request
|
||||
var responseFollowing = await makeRequest("GET", requestUrl, tmpSettings.tokenheader, null)
|
||||
var responseFollowing = await requestAsyncLimited("GET", requestUrl, tmpSettings.tokenheader, null)
|
||||
// fill response array according to id amount with false
|
||||
const follows = Array(ids.length).fill(false)
|
||||
// parse the response
|
||||
|
@ -400,7 +406,7 @@ function checkAllMutedBlocked(handle) {
|
|||
// Return the user id on the users home instance
|
||||
async function resolveHandleToHome(handle) {
|
||||
var requestUrl = 'https://' + settings.fediact_homeinstance + accountsApi + "/search?q=" + handle + "&resolve=true&limit=1&exclude_unreviewed=false"
|
||||
var searchResponse = await makeRequest("GET", requestUrl, tmpSettings.tokenheader, null)
|
||||
var searchResponse = await requestAsyncLimited("GET", requestUrl, tmpSettings.tokenheader, null)
|
||||
if (searchResponse) {
|
||||
searchResponse = JSON.parse(searchResponse)
|
||||
if (searchResponse[0].id) {
|
||||
|
@ -414,7 +420,7 @@ async function resolveHandleToHome(handle) {
|
|||
// resolve a toot to the users home instance
|
||||
async function resolveTootToHome(searchstring) {
|
||||
var requestUrl = 'https://' + settings.fediact_homeinstance + searchApi + "/?q=" + searchstring + "&resolve=true&limit=1&exclude_unreviewed=false"
|
||||
var response = await makeRequest("GET", requestUrl, tmpSettings.tokenheader, null)
|
||||
var response = await requestAsyncLimited("GET", requestUrl, tmpSettings.tokenheader, null)
|
||||
if (response) {
|
||||
response = JSON.parse(response)
|
||||
// do we have a status as result?
|
||||
|
@ -443,7 +449,7 @@ function resolveTootToExternalHome(tooturl) {
|
|||
if (tooturl) {
|
||||
return new Promise(async function(resolve) {
|
||||
try {
|
||||
await chrome.runtime.sendMessage({url: tooturl}, function(response) {
|
||||
await chrome.runtime.sendMessage({externaltoot: tooturl}, function(response) {
|
||||
if(response) {
|
||||
resolve(response)
|
||||
} else {
|
||||
|
@ -519,24 +525,28 @@ function addToProcessedToots(toot) {
|
|||
return tmpSettings.processed.length - 1
|
||||
}
|
||||
|
||||
async function updateMutedBlocked() {
|
||||
// set empty initially
|
||||
[settings.fediact_mutes, settings.fediact_blocks, settings.fediact_domainblocks] = [[],[],[]]
|
||||
var [mutes, blocks, domainblocks] = await Promise.all([
|
||||
fetch("https://" + settings.fediact_homeinstance + mutesApi, {headers: {"Authorization": "Bearer "+settings.fediact_token}}).then((response) => response.json()),
|
||||
fetch("https://" + settings.fediact_homeinstance + blocksApi, {headers: {"Authorization": "Bearer "+settings.fediact_token}}).then((response) => response.json()),
|
||||
fetch("https://" + settings.fediact_homeinstance + domainBlocksApi, {headers: {"Authorization": "Bearer "+settings.fediact_token}}).then((response) => response.json())
|
||||
])
|
||||
if (mutes.length) {
|
||||
settings.fediact_mutes.push(...mutes.map(acc => acc.acct))
|
||||
}
|
||||
if (blocks.length) {
|
||||
settings.fediact_blocks.push(...blocks.map(acc => acc.acct))
|
||||
}
|
||||
if (domainblocks.length) {
|
||||
settings.fediact_domainblocks = domainblocks
|
||||
}
|
||||
updateSettings()
|
||||
function updateMutedBlocked() {
|
||||
return new Promise(async function(resolve) {
|
||||
try {
|
||||
await chrome.runtime.sendMessage({updatemutedblocked: true}, async function(response) {
|
||||
if (response) {
|
||||
if (!await getSettings()) {
|
||||
// but reload if settings are invalid
|
||||
location.reload()
|
||||
} else {
|
||||
resolve(true)
|
||||
}
|
||||
} else {
|
||||
resolve(false)
|
||||
}
|
||||
})
|
||||
} catch (e) {
|
||||
// if we encounter an error here, it is likely since the extension context got invalidated, so reload the page
|
||||
log(e)
|
||||
log("Reloading page, extension likely got updated or reloaded.")
|
||||
location.reload()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function showModal(settings) {
|
||||
|
@ -544,37 +554,80 @@ function showModal(settings) {
|
|||
var baseEl = $(modalHtml)
|
||||
var appendTo = $(baseEl).find("ul")
|
||||
for (const entry of settings) {
|
||||
var nameUppercase = entry[0].charAt(0).toUpperCase() + entry[0].slice(1);
|
||||
var append = "<li class='fediactmodalitem'><a class='fediactmodallink' fediactaction='" + entry[0] + "' fediactid='" + entry[1] + "'>" + nameUppercase + "</a></li>"
|
||||
var append = "<li class='fediactmodalitem'><a class='fediactmodallink' fediactaction='" + entry[0] + "' fediactdata='" + entry[1] + "'><span>" + entry[2] + "</span></a></li>"
|
||||
$(appendTo).append($(append))
|
||||
}
|
||||
$("body").append($(baseEl))
|
||||
$("body").on("click", function(e) {
|
||||
async function handleModalEvent(e) {
|
||||
if (e.originalEvent.isTrusted) {
|
||||
if ($(e.target).is(".fediactmodal li, .fediactmodal li a")) {
|
||||
if ($(e.target).is(".fediactmodal li")) {
|
||||
e.target = $(e.target).find("a")
|
||||
if ($(e.target).is(".fediactmodal li, .fediactmodal li *")) {
|
||||
if (!$(e.target).is(".fediactmodal li a")) {
|
||||
if ($(e.target).find("a").length) {
|
||||
e.target = $(e.target).find("a")
|
||||
} else {
|
||||
e.target = $(e.target).closest("a")
|
||||
}
|
||||
}
|
||||
var action = $(e.target).attr("fediactaction")
|
||||
var id = $(e.target).attr("fediactid")
|
||||
var done = executeAction(id, action, null)
|
||||
var data = $(e.target).attr("fediactdata")
|
||||
var done = await executeAction(data, action, null)
|
||||
if (done) {
|
||||
$(e.target).addClass("activated")
|
||||
$(e.target).append("<span>Done!</span>")
|
||||
$(baseEl).css("animation", "fadeOut .2s .7s forwards")
|
||||
$(baseEl).find(".fediactmodalinner").css("animation", "scaleInFade .2s .7s forwards reverse")
|
||||
await new Promise(resolve => {
|
||||
setTimeout(function() {
|
||||
resolve()
|
||||
}, 1000)
|
||||
})
|
||||
$(baseEl).remove()
|
||||
$("body").off()
|
||||
$("body").off("click", handleModalEvent)
|
||||
} else {
|
||||
alert("Failed to " + action)
|
||||
$(e.target).css("--confirmation", "red")
|
||||
$(e.target).addClass("activated")
|
||||
$(e.target).append("<span>Failed</span>")
|
||||
$(baseEl).css("animation", "fadeOut .2s .7s forwards")
|
||||
$(baseEl).find(".fediactmodalinner").css("animation", "scaleInFade .2s .7s forwards reverse")
|
||||
await new Promise(resolve => {
|
||||
setTimeout(function() {
|
||||
resolve()
|
||||
}, 1000)
|
||||
})
|
||||
$(baseEl).remove()
|
||||
$("body").off("click", handleModalEvent)
|
||||
}
|
||||
} else if ($(e.target).is(".fediactmodalinner")) {
|
||||
$.noop()
|
||||
} else {
|
||||
$(baseEl).remove()
|
||||
$("body").off()
|
||||
$("body").off("click", handleModalEvent)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
$("body").on("click", handleModalEvent)
|
||||
}
|
||||
|
||||
function addFediElements() {
|
||||
if (!$(".fediactrunning").length) {
|
||||
$("body").append("<div class='fediactrunning'><span>FediAct running</span> - <a target='" + settings.fediact_target + "' href='https://" + settings.fediact_homeinstance + "'>Go home</a></div>")
|
||||
if (!$(".fediacticon").length) {
|
||||
$("body").append("<div class='fediacticon'></div>")
|
||||
$("body").append("<div class='fediactsettings_onsite'><div class='fediactsettings_onsite_inner'><a href='https://" + settings.fediact_homeinstance + "' target='" + settings.fediact_target + "'>Go home</a></div></div>")
|
||||
function fediSettingsHandler(e) {
|
||||
try {
|
||||
if (e.originalEvent.isTrusted) {
|
||||
if ($(e.target).is("div.fediacticon")) {
|
||||
$("div.fediacticon").hide()
|
||||
$("div.fediactsettings_onsite").show()
|
||||
} else {
|
||||
$("div.fediactsettings_onsite").hide()
|
||||
$("div.fediacticon").show()
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
$.noop()
|
||||
}
|
||||
}
|
||||
$("body").on("click", fediSettingsHandler)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -753,6 +806,7 @@ async function processToots() {
|
|||
addFediElements()
|
||||
// extra step for detailed status elements to select the correct parent
|
||||
if ($(el).is("div.detailed-status") && $(el).closest("div.focusable").length) {
|
||||
var isDetailed = true
|
||||
el = $(el).closest("div.focusable")
|
||||
}
|
||||
// get toot data
|
||||
|
@ -769,6 +823,7 @@ async function processToots() {
|
|||
// do we have one of those?
|
||||
if (internalIdentifier) {
|
||||
var homeResolveStrings = []
|
||||
var hasHiddenPoll = false
|
||||
// check if id is already cached
|
||||
var cacheIndex = isInProcessedToots(internalIdentifier)
|
||||
// get all button elements of this toot
|
||||
|
@ -776,14 +831,26 @@ async function processToots() {
|
|||
if (!$(favButton).length) {
|
||||
favButton = $(el).find("a.icon-button:has(i.fa-star), a.detailed-status__link:has(i.fa-star)")
|
||||
}
|
||||
$("<span class='fediactprocessing'>Resolving...</span>").insertAfter($(favButton))
|
||||
if (isDetailed) {
|
||||
$("<div class='detailed-status__button fediactprocessingdetailed'><span class='fediactprocessing'></span></div>").insertAfter($(favButton).parent())
|
||||
} else {
|
||||
$("<span class='fediactprocessing'></span>").insertAfter($(favButton))
|
||||
}
|
||||
var boostButton = $(el).find("button:has(i.fa-retweet)").first()
|
||||
if (!$(boostButton).length) {
|
||||
boostButton = $(el).find("a.icon-button:has(i.fa-retweet), a.detailed-status__link:has(i.fa-retweet)")
|
||||
}
|
||||
var bookmarkButton = $(el).find("button:has(i.fa-bookmark)").first()
|
||||
var replyButton = $(el).find("button:has(i.fa-reply), button:has(i.fa-reply-all), a.icon-button:has(i.fa-reply), a.icon-button:has(i.fa-reply-all)").first()
|
||||
var spoilerButton = $(el).find('button[class*="show-more"]').first()
|
||||
var voteButton = $(el).find("div.poll button").first()
|
||||
if ($(spoilerButton).length) {
|
||||
$(spoilerButton).click()
|
||||
if ($(el).find("div.poll").length) {
|
||||
hasHiddenPoll = true
|
||||
}
|
||||
$(spoilerButton).click()
|
||||
}
|
||||
var moreButton = $(el).find("button:has(i.fa-ellipsis-h,i.fa-ellipsis-fw,i.fa-ellipsis-v)").first()
|
||||
// handles process when a vote button is clicked
|
||||
async function pollAction(id, redirect, e) {
|
||||
|
@ -820,6 +887,9 @@ async function processToots() {
|
|||
var actionExecuted = await executeAction(id, action, null)
|
||||
if (actionExecuted) {
|
||||
if (cacheIndex) {
|
||||
console.log(cacheIndex)
|
||||
console.log(tmpSettings.processed[cacheIndex])
|
||||
console.log(tmpSettings.processed)
|
||||
// set interacted to true
|
||||
tmpSettings.processed[cacheIndex][11] = true
|
||||
}
|
||||
|
@ -860,17 +930,46 @@ async function processToots() {
|
|||
// handles initialization of element styles
|
||||
function initStyles(tootdata) {
|
||||
// always remove any existing "Unresolved" indicator from the element first
|
||||
$(el).find(".fediactunresolved").remove()
|
||||
$(el).find(".fediactprocessing").remove()
|
||||
$(el).find(".fediactunresolveddetailed, .fediactunresolved").remove()
|
||||
$(el).find(".fediactprocessingdetailed, .fediactprocessing").remove()
|
||||
// is the toot unresolved?
|
||||
if (!tootdata[1]) {
|
||||
// yes, then add the Unresolved indicator
|
||||
$("<span class='fediactunresolved'>Unresolved</span>").insertAfter($(favButton))
|
||||
if (isDetailed) {
|
||||
$("<div class='detailed-status__button fediactunresolveddetailed'><span class='fediactunresolved'>X</span></div>").insertAfter($(favButton).parent())
|
||||
} else {
|
||||
$("<span class='fediactunresolved'>X</span>").insertAfter($(favButton))
|
||||
}
|
||||
} else {
|
||||
// otherwise start processing button styles (if enabled OR if the toot was already interacted with, to restore the state while still on the same page)
|
||||
// first enable the bookmark button (is disabled on external instances)
|
||||
$(bookmarkButton).removeClass("disabled").removeAttr("disabled")
|
||||
$(moreButton).removeClass("disabled").removeAttr("disabled")
|
||||
// special care for polls that are hidden behind a CW
|
||||
if (tootdata[13]) {
|
||||
// click initially to show content
|
||||
$(spoilerButton).click()
|
||||
$(spoilerButton).find("span").text("Show less")
|
||||
// set voteButton
|
||||
voteButton = $(el).find("div.poll button").first()
|
||||
// set handling for all new clicks
|
||||
$(spoilerButton).on("click", function(e) {
|
||||
// prevent default etc.
|
||||
e.preventDefault()
|
||||
e.stopImmediatePropagation()
|
||||
var spanText = $(spoilerButton).find("span")
|
||||
if ($(spanText).text() == "Show less") {
|
||||
$(spanText).text("Show more")
|
||||
} else {
|
||||
$(spanText).text("Show less")
|
||||
}
|
||||
// toggle the css manually to hide/show the content/poll
|
||||
toggleInlineCss($(el).find("div.poll").first(),[["display","block","none"]], "fedihideshow")
|
||||
toggleInlineCss($(el).find("div.status__content__text").first(),[["display","block","none"]], "fedihideshow")
|
||||
})
|
||||
// click again so it is hidden by default, like usually
|
||||
$(spoilerButton).click()
|
||||
}
|
||||
$(voteButton).removeAttr("disabled")
|
||||
// set the toot buttons to active, depending on the state of the resolved toot and if the element already has the active class
|
||||
if (tootdata[4]) {
|
||||
|
@ -918,20 +1017,22 @@ async function processToots() {
|
|||
if (e.originalEvent.isTrusted) {
|
||||
var modalLinks = []
|
||||
if (isBlocked(tootdata[1])) {
|
||||
modalLinks.push(["unblock",tootdata[6]])
|
||||
modalLinks.push(["unblock",tootdata[6],"Unblock user"])
|
||||
} else {
|
||||
modalLinks.push(["block",tootdata[6]])
|
||||
modalLinks.push(["block",tootdata[6],"Block user"])
|
||||
}
|
||||
if (isMuted(tootdata[1])) {
|
||||
modalLinks.push(["unmute",tootdata[6]])
|
||||
modalLinks.push(["unmute",tootdata[6],"Unmute user"])
|
||||
} else {
|
||||
modalLinks.push(["mute",tootdata[6]])
|
||||
modalLinks.push(["mute",tootdata[6],"Mute user"])
|
||||
}
|
||||
if (isDomainBlocked(tootdata[1])) {
|
||||
modalLinks.push(["domainunblock",domain])
|
||||
modalLinks.push(["domainunblock",domain,"Unblock domain"])
|
||||
} else {
|
||||
modalLinks.push(["domainblock",domain])
|
||||
modalLinks.push(["domainblock",domain,"Block domain"])
|
||||
}
|
||||
modalLinks.push(["copy",tootdata[12],"Copy URL"])
|
||||
modalLinks.push(["copy",tootdata[7],"Copy home URL"])
|
||||
showModal(modalLinks)
|
||||
}
|
||||
})
|
||||
|
@ -1078,8 +1179,9 @@ async function processToots() {
|
|||
// set the redirect to home instance URL in @ format
|
||||
var redirectUrl = 'https://' + settings.fediact_homeinstance + "/@" + resolvedToot[0] + "/" + resolvedToot[1]
|
||||
// prepare the cache entry / toot data entry
|
||||
var fullEntry = [internalIdentifier, ...resolvedToot, redirectUrl, true, ...poll, false]
|
||||
// 0: internal identifier; 1: toot home acct / false 2: toot home id 3: toot reblogged 4: toot favourited 5: toot bookmarked 6: home account id 7: redirect url 8: ??? crap! 9: poll id / false 10: poll voted 11: interacted
|
||||
var fullEntry = [internalIdentifier, ...resolvedToot, redirectUrl, true, ...poll, false, homeResolveString, hasHiddenPoll]
|
||||
// 0: internal identifier; 1: toot home acct / false 2: toot home id 3: toot reblogged 4: toot favourited 5: toot bookmarked 6: home account id
|
||||
// 7: redirect url 8: ??? crap! 9: poll id / false 10: poll voted 11: interacted 12: original URL that was resolved 13: has hidden poll?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1138,7 +1240,7 @@ async function processProfile() {
|
|||
// for mastodon v3 - v4 does not show follow buttons / account cards on /explore
|
||||
async function process(el) {
|
||||
addFediElements()
|
||||
var fullHandle
|
||||
var fullHandle, icon
|
||||
var action = "follow"
|
||||
var moreButton = $(el).siblings("button:has(i.fa-ellipsis-fw,i.fa-ellipsis-v,i.fa-ellipsis-h)")
|
||||
// wrapper for follow/unfollow action
|
||||
|
@ -1148,12 +1250,24 @@ async function processProfile() {
|
|||
var response = await executeAction(id, action, null)
|
||||
// if action was successful, update button text and action value according to performed action
|
||||
if (action == "follow" && response) {
|
||||
$(el).text("Unfollow")
|
||||
if ($(icon).length) {
|
||||
$(icon).removeClass("fa-user-plus").addClass("fa-user")
|
||||
$(el).append("-")
|
||||
$(el).attr("title","Unfollow")
|
||||
} else {
|
||||
$(el).text("Unfollow")
|
||||
}
|
||||
action = "unfollow"
|
||||
return true
|
||||
// repeat for unfollow action
|
||||
} else if (action == "unfollow" && response) {
|
||||
$(el).text("Follow")
|
||||
if ($(icon).length) {
|
||||
$(icon).removeClass("fa-user").addClass("fa-user-plus")
|
||||
$(el).contents().filter((_, node) => node.nodeType === 3).remove()
|
||||
$(el).attr("title","Follow")
|
||||
} else {
|
||||
$(el).text("Follow")
|
||||
}
|
||||
action = "follow"
|
||||
return true
|
||||
}
|
||||
|
@ -1165,6 +1279,9 @@ async function processProfile() {
|
|||
// for mastodon v3 explore page
|
||||
if ($(el).closest("div.account-card").length) {
|
||||
fullHandle = $(el).closest("div.account-card").find("div.display-name > span").text().trim()
|
||||
} else if($(el).closest("div.directory__card").length) {
|
||||
fullHandle = $(el).closest("div.directory__card").find("div.display-name > span").text().trim()
|
||||
icon = $(el).find("i").first()
|
||||
} else {
|
||||
// for all other pages, where only one of the selection elements is present
|
||||
for (const selector of profileNamePaths) {
|
||||
|
@ -1180,7 +1297,7 @@ async function processProfile() {
|
|||
// do we have a full handle?
|
||||
if (fullHandle) {
|
||||
if (!tmpSettings.processedFollow.includes(fullHandle)) {
|
||||
$("<span class='fediactprocessing'>Resolving... </span>").insertBefore($(el))
|
||||
$("<span class='fediactprocessing'></span>").insertBefore($(el))
|
||||
// yes, so resolve it to a user id on our homeinstance
|
||||
var resolvedHandle = await resolveHandleToHome(fullHandle)
|
||||
if (resolvedHandle) {
|
||||
|
@ -1190,12 +1307,19 @@ async function processProfile() {
|
|||
}
|
||||
var domainsplit = fullHandle.split("@")
|
||||
var domain = domainsplit.pop() || domainsplit.pop()
|
||||
var redirectUrl = 'https://' + settings.fediact_homeinstance + '/@' + resolvedHandle[1]
|
||||
// successfully resolved
|
||||
// ... then check if user is already following
|
||||
var isFollowing = await isFollowingHomeInstance([resolvedHandle[0]])
|
||||
// update button text and action if already following
|
||||
if (isFollowing[0]) {
|
||||
$(el).text("Unfollow")
|
||||
if ($(icon).length) {
|
||||
$(icon).removeClass("fa-user-plus").addClass("fa-user")
|
||||
$(el).append("-")
|
||||
$(el).attr("title","Unfollow")
|
||||
} else {
|
||||
$(el).text("Unfollow")
|
||||
}
|
||||
action = "unfollow"
|
||||
}
|
||||
$(moreButton).on("click", function(e){
|
||||
|
@ -1205,20 +1329,21 @@ async function processProfile() {
|
|||
if (e.originalEvent.isTrusted) {
|
||||
var modalLinks = []
|
||||
if (isBlocked(fullHandle)) {
|
||||
modalLinks.push(["unblock",resolvedHandle[0]])
|
||||
modalLinks.push(["unblock",resolvedHandle[0],"Unblock user"])
|
||||
} else {
|
||||
modalLinks.push(["block",resolvedHandle[0]])
|
||||
modalLinks.push(["block",resolvedHandle[0],"Block user"])
|
||||
}
|
||||
if (isMuted(fullHandle)) {
|
||||
modalLinks.push(["unmute",resolvedHandle[0]])
|
||||
modalLinks.push(["unmute",resolvedHandle[0],"Unmute user"])
|
||||
} else {
|
||||
modalLinks.push(["mute",resolvedHandle[0]])
|
||||
modalLinks.push(["mute",resolvedHandle[0],"Mute user"])
|
||||
}
|
||||
if (isDomainBlocked(fullHandle)) {
|
||||
modalLinks.push(["domainunblock",domain])
|
||||
modalLinks.push(["domainunblock",domain,"Unblock domain"])
|
||||
} else {
|
||||
modalLinks.push(["domainblock",domain])
|
||||
modalLinks.push(["domainblock",domain,"Block domain"])
|
||||
}
|
||||
modalLinks.push(["copy",redirectUrl,"Copy home URL"])
|
||||
showModal(modalLinks)
|
||||
}
|
||||
})
|
||||
|
@ -1240,12 +1365,20 @@ async function processProfile() {
|
|||
clearTimeout(timer)
|
||||
var done = await execFollow(resolvedHandle[0])
|
||||
if (done) {
|
||||
var saveText = $(el).text()
|
||||
var redirectUrl = 'https://' + settings.fediact_homeinstance + '/@' + resolvedHandle[1]
|
||||
$(el).text("Redirecting...")
|
||||
if ($(icon).length) {
|
||||
var classes = $(icon).attr("class")
|
||||
$(icon).removeClass("fa-user").removeClass("fa-user-plus").addClass("fa-arrow-right")
|
||||
} else {
|
||||
var saveText = $(el).text()
|
||||
$(el).text("Redirecting...")
|
||||
}
|
||||
setTimeout(function() {
|
||||
redirectTo(redirectUrl)
|
||||
$(el).text(saveText)
|
||||
if ($(icon).length) {
|
||||
$(icon).attr("class", classes)
|
||||
} else {
|
||||
$(el).text(saveText)
|
||||
}
|
||||
}, 1000)
|
||||
} else {
|
||||
log("Action failed.")
|
||||
|
@ -1368,7 +1501,8 @@ async function checkSite() {
|
|||
// last check - and probably the most accurate to determine if it actually is mastadon
|
||||
var requestUrl = location.protocol + '//' + location.hostname + instanceApi
|
||||
// call instance api to confirm its mastodon and get normalized handle uri
|
||||
var response = await makeRequest("GET", requestUrl, null, null)
|
||||
var response = await requestAsyncLimited("GET", requestUrl, null, null)
|
||||
// todo: add basic check for "mastodon" string in response
|
||||
if (response) {
|
||||
var uri = JSON.parse(response).uri
|
||||
if (uri) {
|
||||
|
@ -1380,7 +1514,7 @@ async function checkSite() {
|
|||
}
|
||||
// at this point, we know that it's mastodon and the background processor should start running
|
||||
if (!backgroundProcessor()) {
|
||||
log("Could not start background process")
|
||||
log("Could not start background processor.")
|
||||
return false
|
||||
}
|
||||
// if option is enabled, check if logged in on that instance and stop
|
||||
|
@ -1407,7 +1541,13 @@ async function backgroundProcessor() {
|
|||
tmpSettings.processed = []
|
||||
tmpSettings.processedFollow = []
|
||||
tmpSettings.isProcessing = []
|
||||
$(".fediactrunning").remove()
|
||||
$(".fediacticon").remove()
|
||||
$(".fediactsettings_onsite").remove()
|
||||
try {
|
||||
$("body").off("click", fediSettingsHandler)
|
||||
} catch {
|
||||
$.noop()
|
||||
}
|
||||
// rerun getSettings to keep mutes/blocks up to date while not reloading the page
|
||||
if (!await getSettings()) {
|
||||
// but reload if settings are invalid
|
||||
|
@ -1437,6 +1577,7 @@ function getSettings() {
|
|||
} catch(e) {
|
||||
log(e)
|
||||
resolve(false)
|
||||
return
|
||||
}
|
||||
if (settings) {
|
||||
// validate settings
|
||||
|
@ -1451,14 +1592,6 @@ function getSettings() {
|
|||
})
|
||||
}
|
||||
|
||||
async function updateSettings() {
|
||||
await (browser || chrome).storage.local.set(settings)
|
||||
if (!await getSettings()) {
|
||||
// but reload if settings are invalid
|
||||
location.reload()
|
||||
}
|
||||
}
|
||||
|
||||
// run wrapper
|
||||
async function run() {
|
||||
// validate settings
|
||||
|
|
File diff suppressed because one or more lines are too long
167
src/popup.html
167
src/popup.html
|
@ -1,62 +1,127 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
.hide {
|
||||
display: none;
|
||||
}
|
||||
label.pad {
|
||||
margin-bottom: 4px;
|
||||
display: block;
|
||||
}
|
||||
p {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
</style>
|
||||
<link rel="stylesheet" href="chrome://browser/content/extension.css">
|
||||
<meta name="color-scheme" content="dark light">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<script src="lib/jquery-3.6.1.min.js"></script>
|
||||
<script src="popup.min.js"></script>
|
||||
<link rel="stylesheet" href="popup_styles.min.css">
|
||||
</head>
|
||||
<body style="min-width: 350px; font-size:12px; padding: 10px">
|
||||
<div id="mhi-wrapper">
|
||||
<div id="mhi-containers">
|
||||
<body>
|
||||
<div id="mhi-wrapper">
|
||||
<div id="mhi-containers">
|
||||
<form id="fediact-settings">
|
||||
<p><b>Home instance</b></p>
|
||||
<label class="pad" for="homeinstance">Make sure you are logged in to the instance you set here:</label>
|
||||
<input type="text" id="homeinstance" name="homeinstance" placeholder="example.social"><br>
|
||||
<p><b>Redirect settings</b></p>
|
||||
<input type="checkbox" id="redirects" name="redirects">
|
||||
<label for="redirects">Enable</label><br>
|
||||
<input type="checkbox" id="alert" name="alert">
|
||||
<label for="alert">Prompt</label><br>
|
||||
<label style="padding-right: 5px" for="target">Open in...</label>
|
||||
<select style="margin-top: 5px;" name="target" id="target" selected="_blank">
|
||||
<option id="target_blank" value="_blank">New tab</option>
|
||||
<option id="target_self" value="_self">Same tab</option>
|
||||
</select><br>
|
||||
<p><b>Other</b></p>
|
||||
<input type="checkbox" id="autoaction" name="autoaction">
|
||||
<label for="autoaction">Actions</label><br>
|
||||
<input type="checkbox" id="hidemuted" name="hidemuted">
|
||||
<label for="hidemuted">Hide muted/blocked</label><br>
|
||||
<input type="checkbox" id="delay" name="delay">
|
||||
<label for="delay">API delay</label><br>
|
||||
<p><b>Mode</b></p>
|
||||
<input type="checkbox" id="runifloggedin" name="runifloggedin">
|
||||
<label for="runifloggedin">Run if logged in</label><br>
|
||||
<label style="padding-right: 5px" for="mode">Use...</label>
|
||||
<select style="margin-top: 5px;" name="mode" id="mode" selected="blacklist">
|
||||
<option id="blacklist" value="blacklist">Blacklist</option>
|
||||
<option id="whitelist" value="whitelist">Whitelist</option>
|
||||
</select><br>
|
||||
<div style="margin-top: 5px;" class="hide" id="blacklist_input">
|
||||
<textarea id="blacklist_content" name="blacklist_content" placeholder="example.social example2.social"></textarea><br>
|
||||
<div class="scroller">
|
||||
<fieldset aria-labelledby="homeServerDomainLabel">
|
||||
<div class="row">
|
||||
<label for="homeinstance">
|
||||
<legend id="homeServerDomainLabel"><h1>Home Server Domain</h1></legend>
|
||||
<span>
|
||||
Make sure you are logged in to your home server
|
||||
</span>
|
||||
</label>
|
||||
<div class="text-input-container">
|
||||
<span>https://</span>
|
||||
<input type="text" id="homeinstance" name="homeinstance" placeholder="example.social">
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<legend>Redirect Settings</legend>
|
||||
<div class="row">
|
||||
<label for="redirects">Enable
|
||||
<span>
|
||||
Redirect on double click and reply
|
||||
</span>
|
||||
</label>
|
||||
<input type="checkbox" id="redirects" name="redirects">
|
||||
</div>
|
||||
<div class="row">
|
||||
<label for="alert">Prompt
|
||||
<span>
|
||||
Show confirmation dialog before redirecting
|
||||
</span>
|
||||
</label>
|
||||
<input type="checkbox" id="alert" name="alert">
|
||||
</div>
|
||||
<div class="row">
|
||||
<label for="target">Open in...</label>
|
||||
<select name="target" id="target" selected="_blank">
|
||||
<option id="target_blank" value="_blank">New tab </option>
|
||||
<option id="target_self" value="_self">Same tab </option>
|
||||
</select>
|
||||
</div>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<legend>Other Settings</legend>
|
||||
<div class="row">
|
||||
<label for="autoaction">Actions
|
||||
<span>
|
||||
Enable follow, boost, etc. on other servers
|
||||
</span>
|
||||
</label>
|
||||
<input type="checkbox" id="autoaction" name="autoaction">
|
||||
</div>
|
||||
<div class="row">
|
||||
<label for="hidemuted">Hide muted/blocked
|
||||
<span>
|
||||
Can fail / decrease performance in some cases
|
||||
</span>
|
||||
</label>
|
||||
<input type="checkbox" id="hidemuted" name="hidemuted">
|
||||
</div>
|
||||
<div class="row">
|
||||
<label for="delay">API delay
|
||||
<span>
|
||||
Only allow one API request every 500ms
|
||||
</span>
|
||||
</label>
|
||||
<input type="checkbox" id="delay" name="delay">
|
||||
</div>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<legend>Mode</legend>
|
||||
<div class="row">
|
||||
<label for="runifloggedin">Ignore sessions
|
||||
<span>
|
||||
Run FediAct on instances where I'm logged in
|
||||
</span>
|
||||
</label>
|
||||
<input type="checkbox" id="runifloggedin" name="runifloggedin">
|
||||
</div>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<legend>Filtered servers</legend>
|
||||
<div class="row">
|
||||
<label for="mode">Mode
|
||||
<span class="hide" id="allowlabel">
|
||||
Only run on the following domains...
|
||||
</span>
|
||||
<span class="hide" id="denylabel">
|
||||
Run on all domains except the following...
|
||||
</span>
|
||||
</label>
|
||||
<select name="mode" id="mode" selected="blacklist">
|
||||
<option id="blacklist" value="blacklist">Denylist </option>
|
||||
<option id="whitelist" value="whitelist">Allowlist </option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="hide textarea-container" id="blacklist_input">
|
||||
<textarea id="blacklist_content" name="blacklist_content" placeholder="example.social example2.social"></textarea>
|
||||
</div>
|
||||
<div class="hide textarea-container" id="whitelist_input">
|
||||
<textarea id="whitelist_content" name="whitelist_content" placeholder="example.social example2.social"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<input type="submit" value="Save">
|
||||
<span id="indicator" style="display:none">Settings saved!</span>
|
||||
<span><a target="_blank" href="https://github.com/lartsch/FediAct">More info / help on Github</a></span>
|
||||
</div>
|
||||
<div style="margin-top: 5px;" class="hide" id="whitelist_input">
|
||||
<textarea id="whitelist_content" name="whitelist_content" placeholder="example.social example2.social"></textarea><br>
|
||||
</div><br>
|
||||
<input type="submit" value="Submit">
|
||||
<span id="indicator" style="display:none">Settings saved!</span>
|
||||
<br><br><span>Information and help at <a target="_blank" href="https://github.com/lartsch/FediAct">github.com/lartsch/FediAct</a></span><br>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
|
18
src/popup.js
18
src/popup.js
|
@ -75,18 +75,24 @@ function popupTasks() {
|
|||
$("input#runifloggedin").prop('checked', settings.fediact_runifloggedin)
|
||||
// both containers are hidden by default
|
||||
if ($("select#mode").val() == "whitelist") {
|
||||
$("div#whitelist_input").show()
|
||||
$("div#whitelist_input").removeClass("hide")
|
||||
$("span#allowlabel").removeClass("hide")
|
||||
} else {
|
||||
$("div#blacklist_input").show()
|
||||
$("div#blacklist_input").removeClass("hide")
|
||||
$("span#denylabel").removeClass("hide")
|
||||
}
|
||||
// check changes of the select to update whitelist/blacklist input
|
||||
$("select#mode").change(function() {
|
||||
if ($("select#mode").val() == "whitelist") {
|
||||
$("div#blacklist_input").hide()
|
||||
$("div#whitelist_input").show()
|
||||
$("div#blacklist_input").addClass("hide")
|
||||
$("span#denylabel").addClass("hide")
|
||||
$("div#whitelist_input").removeClass("hide")
|
||||
$("span#allowlabel").removeClass("hide")
|
||||
} else {
|
||||
$("div#whitelist_input").hide()
|
||||
$("div#blacklist_input").show()
|
||||
$("div#whitelist_input").addClass("hide")
|
||||
$("span#allowlabel").addClass("hide")
|
||||
$("div#blacklist_input").removeClass("hide")
|
||||
$("span#denylabel").removeClass("hide")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
const t={fediact_homeinstance:null,fediact_alert:!1,fediact_mode:"blacklist",fediact_whitelist:null,fediact_blacklist:null,fediact_target:"_self",fediact_autoaction:!0,fediact_redirects:!0,fediact_enabledelay:!0,fediact_hidemuted:!1,fediact_runifloggedin:!1};var browser,chrome,i;const a=!0,c="[FediAct]";function d(e){a&&console.log(c+" "+e)}function n(){async function t(){i.fediact_homeinstance=$("input#homeinstance").val().trim().toLowerCase(),i.fediact_alert=$("input#alert").is(":checked"),i.fediact_mode=$("select#mode").val(),i.fediact_whitelist=$("textarea#whitelist_content").val(),i.fediact_blacklist=$("textarea#blacklist_content").val(),i.fediact_target=$("select#target").val(),i.fediact_autoaction=$("input#autoaction").is(":checked"),i.fediact_redirects=$("input#redirects").is(":checked"),i.fediact_enabledelay=$("input#delay").is(":checked"),i.fediact_hidemuted=$("input#hidemuted").is(":checked"),i.fediact_runifloggedin=$("input#runifloggedin").is(":checked");try{await(browser||chrome).storage.local.set(i)}catch{return d(e),!1}$("span#indicator").show(),setTimeout(function(){$("span#indicator").hide()},1500)}$(document).ready(function(){$("input#homeinstance").val(i.fediact_homeinstance),$("textarea#blacklist_content").val(i.fediact_blacklist),$("textarea#whitelist_content").val(i.fediact_whitelist),$("select#mode").val(i.fediact_mode),$("select#target").val(i.fediact_target),$("input#alert").prop("checked",i.fediact_alert),$("input#autoaction").prop("checked",i.fediact_autoaction),$("input#redirects").prop("checked",i.fediact_redirects),$("input#delay").prop("checked",i.fediact_enabledelay),$("input#hidemuted").prop("checked",i.fediact_hidemuted),$("input#runifloggedin").prop("checked",i.fediact_runifloggedin),("whitelist"==$("select#mode").val()?$("div#whitelist_input"):$("div#blacklist_input")).show(),$("select#mode").change(function(){("whitelist"==$("select#mode").val()?($("div#blacklist_input").hide(),$("div#whitelist_input")):($("div#whitelist_input").hide(),$("div#blacklist_input"))).show()}),$("form#fediact-settings").on("submit",async function(e){e.preventDefault(),t();try{await chrome.runtime.sendMessage({updatedsettings:!0})}catch(e){d(e)}})})}async function l(){try{i=await(browser||chrome).storage.local.get(t)}catch(e){return d(e),!1}i&&n()}l();
|
||||
const t={fediact_homeinstance:null,fediact_alert:!1,fediact_mode:"blacklist",fediact_whitelist:null,fediact_blacklist:null,fediact_target:"_self",fediact_autoaction:!0,fediact_redirects:!0,fediact_enabledelay:!0,fediact_hidemuted:!1,fediact_runifloggedin:!1};var browser,chrome,i;const a=!0,c="[FediAct]";function d(e){a&&console.log(c+" "+e)}function l(){async function t(){i.fediact_homeinstance=$("input#homeinstance").val().trim().toLowerCase(),i.fediact_alert=$("input#alert").is(":checked"),i.fediact_mode=$("select#mode").val(),i.fediact_whitelist=$("textarea#whitelist_content").val(),i.fediact_blacklist=$("textarea#blacklist_content").val(),i.fediact_target=$("select#target").val(),i.fediact_autoaction=$("input#autoaction").is(":checked"),i.fediact_redirects=$("input#redirects").is(":checked"),i.fediact_enabledelay=$("input#delay").is(":checked"),i.fediact_hidemuted=$("input#hidemuted").is(":checked"),i.fediact_runifloggedin=$("input#runifloggedin").is(":checked");try{await(browser||chrome).storage.local.set(i)}catch{return d(e),!1}$("span#indicator").show(),setTimeout(function(){$("span#indicator").hide()},1500)}$(document).ready(function(){$("input#homeinstance").val(i.fediact_homeinstance),$("textarea#blacklist_content").val(i.fediact_blacklist),$("textarea#whitelist_content").val(i.fediact_whitelist),$("select#mode").val(i.fediact_mode),$("select#target").val(i.fediact_target),$("input#alert").prop("checked",i.fediact_alert),$("input#autoaction").prop("checked",i.fediact_autoaction),$("input#redirects").prop("checked",i.fediact_redirects),$("input#delay").prop("checked",i.fediact_enabledelay),$("input#hidemuted").prop("checked",i.fediact_hidemuted),$("input#runifloggedin").prop("checked",i.fediact_runifloggedin),("whitelist"==$("select#mode").val()?($("div#whitelist_input").removeClass("hide"),$("span#allowlabel")):($("div#blacklist_input").removeClass("hide"),$("span#denylabel"))).removeClass("hide"),$("select#mode").change(function(){("whitelist"==$("select#mode").val()?($("div#blacklist_input").addClass("hide"),$("span#denylabel").addClass("hide"),$("div#whitelist_input").removeClass("hide"),$("span#allowlabel")):($("div#whitelist_input").addClass("hide"),$("span#allowlabel").addClass("hide"),$("div#blacklist_input").removeClass("hide"),$("span#denylabel"))).removeClass("hide")}),$("form#fediact-settings").on("submit",async function(e){e.preventDefault(),t();try{await chrome.runtime.sendMessage({updatedsettings:!0})}catch(e){d(e)}})})}async function n(){try{i=await(browser||chrome).storage.local.get(t)}catch(e){return d(e),!1}i&&l()}n();
|
|
@ -0,0 +1,227 @@
|
|||
html, body {
|
||||
margin: 0;
|
||||
height: var(--popup-height);
|
||||
min-width: 300px;
|
||||
max-height: 900px;
|
||||
}
|
||||
html {
|
||||
--highlight: rgba(130,130,150,0.1);
|
||||
--confirmation: rgb(38, 133, 0);
|
||||
--hover: rgba(120,120,130,0.15);
|
||||
--border: rgba(120,120,130,0.3);
|
||||
--border-2: rgba(130,130,150,0.3);
|
||||
--radius: 12px;
|
||||
--popup-height: 450px;
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-box-direction: normal;
|
||||
-ms-flex-direction: column;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
}
|
||||
body {
|
||||
-webkit-box-flex: 1;
|
||||
-ms-flex-positive: 1;
|
||||
flex-grow: 1;
|
||||
min-height: var(--popup-height);
|
||||
}
|
||||
.hide {
|
||||
display: none;
|
||||
}
|
||||
h1 {
|
||||
font-size: 1em;
|
||||
margin-block: .2em;
|
||||
}
|
||||
h2 {
|
||||
font-size: 1em;
|
||||
}
|
||||
#mhi-wrapper, #mhi-containers {
|
||||
display: contents;
|
||||
}
|
||||
form {
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-box-direction: normal;
|
||||
-ms-flex-direction: column;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
}
|
||||
.scroller {
|
||||
height: 0;
|
||||
overflow-y: auto;
|
||||
-webkit-box-flex: 1;
|
||||
-ms-flex-positive: 1;
|
||||
flex-grow: 1;
|
||||
padding: 10px;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
fieldset {
|
||||
all: unset;
|
||||
display: block;
|
||||
}
|
||||
legend {
|
||||
all: unset;
|
||||
}
|
||||
fieldset > legend, summary {
|
||||
margin-inline: .6em;
|
||||
padding-top: .6em;
|
||||
margin-bottom: .4em;
|
||||
font-weight: 700;
|
||||
}
|
||||
.row {
|
||||
background-color: var(--highlight);
|
||||
padding: .8em;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-ms-flex-wrap: wrap;
|
||||
flex-wrap: wrap;
|
||||
margin-bottom: 2px;
|
||||
position: relative;
|
||||
gap: .4em;
|
||||
-webkit-transition: background-color .1s;
|
||||
-o-transition: background-color .1s;
|
||||
transition: background-color .1s;
|
||||
}
|
||||
.row:hover, .row:focus-within {
|
||||
background: var(--hover);
|
||||
}
|
||||
.row:first-of-type {
|
||||
border-top-left-radius: var(--radius);
|
||||
border-top-right-radius: var(--radius);
|
||||
}
|
||||
.row:last-of-type {
|
||||
border-bottom-left-radius: var(--radius);
|
||||
border-bottom-right-radius: var(--radius);
|
||||
}
|
||||
label {
|
||||
width: 0;
|
||||
-webkit-box-flex: 9999;
|
||||
-ms-flex-positive: 9999;
|
||||
flex-grow: 9999;
|
||||
}
|
||||
label::before { /* Make entire .row clickable */
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
}
|
||||
label span {
|
||||
display: block;
|
||||
font-size: .9em;
|
||||
opacity: .7;
|
||||
margin-top: .2em;
|
||||
}
|
||||
.text-input-container {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: calc(var(--radius) / 2);
|
||||
overflow: hidden;
|
||||
}
|
||||
.text-input-container span {
|
||||
padding: .7em;
|
||||
background-color: var(--highlight);
|
||||
}
|
||||
.text-input-container input {
|
||||
border: 0 !important;
|
||||
border-radius: 0 !important;
|
||||
outline: 0;
|
||||
}
|
||||
.text-input-container:focus-within {
|
||||
outline: auto; /* This is the browser's default focus outline */
|
||||
}
|
||||
input, textarea, select {
|
||||
border: 1px solid var(--border);
|
||||
padding: .7em;
|
||||
border-radius: calc(var(--radius) / 2);
|
||||
font-size: inherit;
|
||||
-webkit-box-flex: 1;
|
||||
-ms-flex-positive: 1;
|
||||
flex-grow: 1;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
}
|
||||
.textarea-container {
|
||||
width: calc(100% - .14em);
|
||||
border-radius: inherit;
|
||||
}
|
||||
textarea {
|
||||
resize: vertical;
|
||||
width: 100%;
|
||||
}
|
||||
select {
|
||||
margin-block: -.8em;
|
||||
padding-block: .4em;
|
||||
border: 0;
|
||||
background: none;
|
||||
text-align: right;
|
||||
}
|
||||
.footer {
|
||||
padding: 10px;
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-ms-flex-wrap: wrap;
|
||||
flex-wrap: wrap;
|
||||
-webkit-box-align: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
-webkit-box-pack: justify;
|
||||
-ms-flex-pack: justify;
|
||||
justify-content: space-between;
|
||||
border-top: 1px dashed var(--border-2);
|
||||
position: relative;
|
||||
background-color: var(--highlight);
|
||||
-webkit-box-shadow: 0 0 24px rgba(0,0,0,0.1);
|
||||
box-shadow: 0 0 24px rgba(0,0,0,0.1);
|
||||
}
|
||||
[type="submit"] {
|
||||
-webkit-box-flex: 0;
|
||||
-ms-flex-positive: 0;
|
||||
flex-grow: 0;
|
||||
padding-inline: 2em;
|
||||
}
|
||||
[type="submit"]:not(:hover):not(:focus) {
|
||||
background: none;
|
||||
}
|
||||
.footer span {
|
||||
width: 0;
|
||||
-webkit-box-flex: 1;
|
||||
-ms-flex-positive: 1;
|
||||
flex-grow: 1;
|
||||
text-align: right;
|
||||
padding-inline: 1em;
|
||||
}
|
||||
.footer a {
|
||||
opacity: .7;
|
||||
text-underline-offset: .2em;
|
||||
color: inherit;
|
||||
}
|
||||
#indicator {
|
||||
-webkit-box-ordinal-group: 0;
|
||||
-ms-flex-order: -1;
|
||||
order: -1;
|
||||
width: calc(100% + 20px);
|
||||
font-weight: 600;
|
||||
padding: .7em;
|
||||
margin: -10px;
|
||||
margin-bottom: 8px;
|
||||
background-color: var(--confirmation);
|
||||
text-align: center;
|
||||
color: white;
|
||||
}
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body {
|
||||
color: white;
|
||||
background-color: #1c1b22;
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
html,body{margin:0;height:var(--popup-height);min-width:300px;max-height:900px}html{--highlight:rgba(130,130,150,0.1);--confirmation:#268500;--hover:rgba(120,120,130,0.15);--border:rgba(120,120,130,0.3);--border-2:rgba(130,130,150,0.3);--radius:12px;--popup-height:450px;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;height:100%}body{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;min-height:var(--popup-height)}.hide{display:none}h1{font-size:1em;margin-block:.2em}h2{font-size:1em}#mhi-wrapper,#mhi-containers{display:contents}form{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;height:100%}.scroller{height:0;overflow-y:auto;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;padding:10px;-webkit-box-sizing:border-box;box-sizing:border-box}fieldset{all:unset;display:block}legend{all:unset}fieldset>legend,summary{margin-inline:.6em;padding-top:.6em;margin-bottom:.4em;font-weight:700}.row{background-color:var(--highlight);padding:.8em;-webkit-box-sizing:border-box;box-sizing:border-box;display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-bottom:2px;position:relative;gap:.4em;-webkit-transition:background-color .1s;-o-transition:background-color .1s;transition:background-color .1s}.row:hover,.row:focus-within{background:var(--hover)}.row:first-of-type{border-top-left-radius:var(--radius);border-top-right-radius:var(--radius)}.row:last-of-type{border-bottom-left-radius:var(--radius);border-bottom-right-radius:var(--radius)}label{width:0;-webkit-box-flex:9999;-ms-flex-positive:9999;flex-grow:9999}label::before{content:"";position:absolute;inset:0}label span{display:block;font-size:.9em;opacity:.7;margin-top:.2em}.text-input-container{width:100%;display:flex;border:1px solid var(--border);border-radius:calc(var(--radius) / 2);overflow:hidden}.text-input-container span{padding:.7em;background-color:var(--highlight)}.text-input-container input{border:0 !important;border-radius:0 !important;outline:0}.text-input-container:focus-within{outline:auto}input,textarea,select{border:1px solid var(--border);padding:.7em;border-radius:calc(var(--radius) / 2);font-size:inherit;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-webkit-box-sizing:border-box;box-sizing:border-box;position:relative;z-index:2}.textarea-container{width:calc(100% - .14em);border-radius:inherit}textarea{resize:vertical;width:100%}select{margin-block:-.8em;padding-block:.4em;border:0;background:0;text-align:right}.footer{padding:10px;display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;border-top:1px dashed var(--border-2);position:relative;background-color:var(--highlight);-webkit-box-shadow:0 0 24px rgba(0,0,0,0.1);box-shadow:0 0 24px rgba(0,0,0,0.1)}[type="submit"]{-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0;padding-inline:2em}[type="submit"]:not(:hover):not(:focus){background:0}.footer span{width:0;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;text-align:right;padding-inline:1em}.footer a{opacity:.7;text-underline-offset:.2em;color:inherit}#indicator{-webkit-box-ordinal-group:0;-ms-flex-order:-1;order:-1;width:calc(100% + 20px);font-weight:600;padding:.7em;margin:-10px;margin-bottom:8px;background-color:var(--confirmation);text-align:center;color:white}@media(prefers-color-scheme:dark){body{color:white;background-color:#1c1b22}}
|
154
src/styles.css
154
src/styles.css
|
@ -1,154 +0,0 @@
|
|||
/*
|
||||
Normal stylings
|
||||
*/
|
||||
|
||||
.fediactmodal {
|
||||
position: fixed;
|
||||
z-index: 99999;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
background-color: rgba(0,0,0,0.4);
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.fediactmodalinner {
|
||||
background-color: #494949;
|
||||
border: 1px solid #888;
|
||||
width: 50%;
|
||||
max-width: 300px;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
position: absolute;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.fediactmodallist {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.fediactmodalitem {
|
||||
cursor: pointer;
|
||||
width: 100%;
|
||||
padding: 5px 10px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.fediactmodallink {
|
||||
font-size: 16px;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.fediactprocessing {
|
||||
color: white;
|
||||
padding-right: 10px;
|
||||
padding-left: 10px
|
||||
}
|
||||
|
||||
.fediactunresolved {
|
||||
color: orange;
|
||||
padding-right: 10px;
|
||||
padding-left: 10px
|
||||
}
|
||||
|
||||
.fediactvoted {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.fediactvoted > a {
|
||||
font-weight: bold;
|
||||
color: orange
|
||||
}
|
||||
|
||||
.fediactrunning {
|
||||
position: fixed;
|
||||
z-index: 99998;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: rgba(0,0,0,0.7);
|
||||
color: white;
|
||||
margin: 0;
|
||||
padding: 10px 15px;
|
||||
}
|
||||
|
||||
.fediactrunning span {
|
||||
color: green;
|
||||
}
|
||||
|
||||
.fediactrunning a {
|
||||
color: white;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
We insert these styles for the DOMNodeAppeared function as separate stylesheet (see manifest) to fix
|
||||
Firefox blocking script-inserted <style> elements due to the site's CSP (long time bug)
|
||||
*/
|
||||
|
||||
@-moz-keyframes nodeInserted {
|
||||
from {
|
||||
opacity: 1;
|
||||
} to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes nodeInserted {
|
||||
from {
|
||||
opacity: 1;
|
||||
} to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
@-ms-keyframes nodeInserted {
|
||||
from {
|
||||
opacity: 1;
|
||||
} to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
@-o-keyframes nodeInserted {
|
||||
from {
|
||||
opacity: 1;
|
||||
} to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
@keyframes nodeInserted {
|
||||
from {
|
||||
opacity: 1;
|
||||
} to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
div.status,
|
||||
div.detailed-status,
|
||||
div.detailed-status__action-bar,
|
||||
div.account__header button.logo-button,
|
||||
div.account__header button.button--follow,
|
||||
div.public-account-header a.logo-button,
|
||||
div.account-card a.logo-button,
|
||||
div.directory-card a.icon-button,
|
||||
div.detailed-status a.logo-button,
|
||||
button.remote-button,
|
||||
script#initial-state {
|
||||
-webkit-animation-name: nodeInserted !important;
|
||||
-webkit-animation-duration: 0.001s !important;
|
||||
-ms-animation-name: nodeInserted !important;
|
||||
-ms-animation-duration: 0.001s !important;
|
||||
-moz-animation-name: nodeInserted !important;
|
||||
-moz-animation-duration: 0.001s !important;
|
||||
-o-animation-name: nodeInserted !important;
|
||||
-o-animation-duration: 0.001s !important;
|
||||
animation-name: nodeInserted !important;
|
||||
animation-duration: 0.001s !important;
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
.fediactmodal{position:fixed;z-index:99999;left:0;top:0;width:100%;height:100%;overflow:auto;background-color:rgba(0,0,0,0.4);margin:0;padding:0}.fediactmodalinner{background-color:#494949;border:1px solid #888;width:50%;max-width:300px;left:50%;top:50%;transform:translate(-50%,-50%);position:absolute;margin:0;padding:0}.fediactmodallist{width:100%;margin:0;padding:0}.fediactmodalitem{cursor:pointer;width:100%;padding:5px 10px;box-sizing:border-box}.fediactmodallink{font-size:16px;cursor:pointer;text-decoration:none;color:white}.fediactprocessing{color:white;padding-right:10px;padding-left:10px}.fediactunresolved{color:orange;padding-right:10px;padding-left:10px}.fediactvoted{font-style:italic}.fediactvoted>a{font-weight:bold;color:orange}.fediactrunning{position:fixed;z-index:99998;right:0;bottom:0;background-color:rgba(0,0,0,0.7);color:white;margin:0;padding:10px 15px}.fediactrunning span{color:green}.fediactrunning a{color:white}@-moz-keyframes nodeInserted{from{opacity:1}to{opacity:1}}@-webkit-keyframes nodeInserted{from{opacity:1}to{opacity:1}}@-ms-keyframes nodeInserted{from{opacity:1}to{opacity:1}}@-o-keyframes nodeInserted{from{opacity:1}to{opacity:1}}@keyframes nodeInserted{from{opacity:1}to{opacity:1}}div.status,div.detailed-status,div.detailed-status__action-bar,div.account__header button.logo-button,div.account__header button.button--follow,div.public-account-header a.logo-button,div.account-card a.logo-button,div.directory-card a.icon-button,div.detailed-status a.logo-button,button.remote-button,script#initial-state{-webkit-animation-name:nodeInserted !important;-webkit-animation-duration:.001s !important;-ms-animation-name:nodeInserted !important;-ms-animation-duration:.001s !important;-moz-animation-name:nodeInserted !important;-moz-animation-duration:.001s !important;-o-animation-name:nodeInserted !important;-o-animation-duration:.001s !important;animation-name:nodeInserted !important;animation-duration:.001s !important}
|
Ładowanie…
Reference in New Issue