mirror of
https://github.com/ajayyy/SponsorBlock.git
synced 2025-12-25 08:58:27 +03:00
Compare commits
42 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
457bd15e17 | ||
|
|
cc1b8ee499 | ||
|
|
4a9ed1348e | ||
|
|
5595420be6 | ||
|
|
191e9ceb6f | ||
|
|
1e26faa57c | ||
|
|
030256c9e1 | ||
|
|
77eff12d9b | ||
|
|
2967fce013 | ||
|
|
db1def623a | ||
|
|
140e324bf1 | ||
|
|
f0bf051259 | ||
|
|
2ec47d52cd | ||
|
|
50002cfbbd | ||
|
|
6ccd4b8b37 | ||
|
|
c0894afff9 | ||
|
|
09f244150c | ||
|
|
efec8b320c | ||
|
|
e6ea9f77e9 | ||
|
|
0813aa4ba3 | ||
|
|
ba575f6b8d | ||
|
|
ff9b2338e0 | ||
|
|
d2bb4b38e3 | ||
|
|
760c08dd0c | ||
|
|
50517eb462 | ||
|
|
e77425c21e | ||
|
|
f63abb053d | ||
|
|
7b5703aa04 | ||
|
|
d641066312 | ||
|
|
44ca8d47d8 | ||
|
|
d5f41bf4ad | ||
|
|
73e8926444 | ||
|
|
5ad694af65 | ||
|
|
d7f7acb219 | ||
|
|
8d82a6a3e6 | ||
|
|
88a8fda566 | ||
|
|
995fe072bd | ||
|
|
8cdbebd6de | ||
|
|
94af8ab301 | ||
|
|
be3a4a4e91 | ||
|
|
1c17464c94 | ||
|
|
8896c5707a |
68
.github/workflows/release.yml
vendored
68
.github/workflows/release.yml
vendored
@@ -1,6 +1,8 @@
|
|||||||
name: Upload Release Build
|
name: Upload Release Build
|
||||||
|
|
||||||
on: release
|
on:
|
||||||
|
release:
|
||||||
|
types: [published]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
|
||||||
@@ -9,22 +11,68 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
# Build Artifacts
|
# Initialization
|
||||||
- uses: actions/checkout@v1
|
- uses: actions/checkout@v1
|
||||||
- name: Build Artifacts
|
- uses: actions/setup-node@v1
|
||||||
uses: ./.github/workflows/ci.yml
|
- run: npm install
|
||||||
|
- name: Copy configuration
|
||||||
|
run: cp config.json.example config.json
|
||||||
|
|
||||||
|
# Create Chrome artifacts
|
||||||
|
- name: Create Chrome artifacts
|
||||||
|
run: npm run build:chrome
|
||||||
|
- uses: actions/upload-artifact@v1
|
||||||
|
with:
|
||||||
|
name: ChromeExtension
|
||||||
|
path: dist
|
||||||
|
- run: mkdir ./builds
|
||||||
|
- uses: montudor/action-zip@v0.1.0
|
||||||
|
with:
|
||||||
|
args: zip -qq -r ./builds/ChromeExtension.zip ./dist
|
||||||
|
|
||||||
|
# Create Firefox artifacts
|
||||||
|
- name: Create Firefox artifacts
|
||||||
|
run: npm run build:firefox
|
||||||
|
- uses: actions/upload-artifact@v1
|
||||||
|
with:
|
||||||
|
name: FirefoxExtension
|
||||||
|
path: dist
|
||||||
|
- uses: montudor/action-zip@v0.1.0
|
||||||
|
with:
|
||||||
|
args: zip -qq -r ./builds/FirefoxExtension.zip ./dist
|
||||||
|
|
||||||
|
# Create Beta artifacts (Builds with the name changed to beta)
|
||||||
|
- name: Create Chrome Beta artifacts
|
||||||
|
run: npm run build:chrome -- --env.stream=beta
|
||||||
|
- uses: actions/upload-artifact@v1
|
||||||
|
with:
|
||||||
|
name: ChromeExtensionBeta
|
||||||
|
path: dist
|
||||||
|
- uses: montudor/action-zip@v0.1.0
|
||||||
|
with:
|
||||||
|
args: zip -qq -r ./builds/ChromeExtensionBeta.zip ./dist
|
||||||
|
|
||||||
|
- name: Create Firefox Beta artifacts
|
||||||
|
run: npm run build:firefox -- --env.stream=beta
|
||||||
|
- uses: actions/upload-artifact@v1
|
||||||
|
with:
|
||||||
|
name: FirefoxExtensionBeta
|
||||||
|
path: dist
|
||||||
|
- uses: montudor/action-zip@v0.1.0
|
||||||
|
with:
|
||||||
|
args: zip -qq -r ./builds/FirefoxExtensionBeta.zip ./dist
|
||||||
|
|
||||||
# Upload each release asset
|
# Upload each release asset
|
||||||
- name: Upload to release
|
- name: Upload to release
|
||||||
uses: JasonEtco/upload-to-release@master
|
uses: Shopify/upload-to-release@master
|
||||||
with:
|
with:
|
||||||
args: ./builds/ChromeExtension.zip
|
args: builds/ChromeExtension.zip
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
- name: Upload to release
|
- name: Upload to release
|
||||||
uses: JasonEtco/upload-to-release@master
|
uses: Shopify/upload-to-release@master
|
||||||
with:
|
with:
|
||||||
args: ./builds/FirefoxExtension.zip
|
args: builds/FirefoxExtension.zip
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
|||||||
24
README.md
24
README.md
@@ -40,32 +40,30 @@ The backend server code is available here: https://github.com/ajayyy/SponsorBloc
|
|||||||
|
|
||||||
It is a simple Sqlite database that will hold all the timing data.
|
It is a simple Sqlite database that will hold all the timing data.
|
||||||
|
|
||||||
To make sure that this project doesn't die, I have made the database publicly downloadable at https://api.sponsor.ajay.app/database.db. So, you can download a backup or get archive.org to take a backup for you if you want.
|
To make sure that this project doesn't die, I have made the database publicly downloadable at https://sponsor.ajay.app/database.db. You can download a backup or get archive.org to take a backup for you if you want.
|
||||||
|
|
||||||
Hopefully this project can be combined with projects like [this](https://github.com/Sponsoff/sponsorship_remover) and use this data to create a neural network to predict when sponsored segments happen. That project is sadly abandoned now, so I have decided to attempt to revive this idea.
|
The dataset and API are now being used in some [ports](https://github.com/ajayyy/SponsorBlock/wiki/Unofficial-Ports) as well as a [neural network](https://github.com/andrewzlee/NeuralBlock).
|
||||||
|
|
||||||
|
A [previous project](https://github.com/Sponsoff/sponsorship_remover) attempted to create a neural network to predict when sponsored segments happen. That project is sadly abandoned now, so I have decided to attempt to revive this idea starting from a crowd-sourced system instead.
|
||||||
|
|
||||||
# API
|
# API
|
||||||
|
|
||||||
You can read the API docs [here](https://github.com/ajayyy/SponsorBlockServer#api-docs).
|
You can read the API docs [here](https://github.com/ajayyy/SponsorBlockServer#api-docs).
|
||||||
|
|
||||||
# Build Yourself
|
# Building
|
||||||
|
|
||||||
You can load this project as an unpacked extension. Make sure to rename the `config.json.example` file to `config.json` before installing.
|
There are also other build scripts available. Install `npm`, then run `npm install` in the repository to install dependencies.
|
||||||
|
|
||||||
There are also other build scripts available. Install `npm`, then run `npm install` in the repository.
|
Run `npm run build` to generate a Chrome extension.
|
||||||
|
|
||||||
|
Use `npm run build:firefox` to generate a Firefox extension.
|
||||||
|
|
||||||
|
The result is in `dist`. This can be loaded as an unpacked extension
|
||||||
|
|
||||||
## Developing with a clean profile
|
## Developing with a clean profile
|
||||||
|
|
||||||
Run `npm run dev` to run the extension using a clean browser profile with hot reloading. Use `npm run dev:firefox` for Firefox. This uses [`web-ext run`](https://extensionworkshop.com/documentation/develop/web-ext-command-reference/#commands).
|
Run `npm run dev` to run the extension using a clean browser profile with hot reloading. Use `npm run dev:firefox` for Firefox. This uses [`web-ext run`](https://extensionworkshop.com/documentation/develop/web-ext-command-reference/#commands).
|
||||||
|
|
||||||
## Packing
|
|
||||||
|
|
||||||
Run `npm run build` to generate a packed Chrome extension.
|
|
||||||
|
|
||||||
Use `npm run build:firefox` to generate a Firefox extension.
|
|
||||||
|
|
||||||
The result is in `dist`.
|
|
||||||
|
|
||||||
# Credit
|
# Credit
|
||||||
|
|
||||||
The awesome [Invidious API](https://github.com/omarroth/invidious/wiki/API) previously was used.
|
The awesome [Invidious API](https://github.com/omarroth/invidious/wiki/API) previously was used.
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "__MSG_fullName__",
|
"name": "__MSG_fullName__",
|
||||||
"short_name": "__MSG_Name__",
|
"short_name": "__MSG_Name__",
|
||||||
"version": "1.2.18",
|
"version": "1.2.22",
|
||||||
"default_locale": "en",
|
"default_locale": "en",
|
||||||
"description": "__MSG_Description__",
|
"description": "__MSG_Description__",
|
||||||
"content_scripts": [{
|
"content_scripts": [{
|
||||||
|
|||||||
@@ -425,5 +425,20 @@
|
|||||||
},
|
},
|
||||||
"mobileUpdateInfo": {
|
"mobileUpdateInfo": {
|
||||||
"message": "m.youtube.com is now supported"
|
"message": "m.youtube.com is now supported"
|
||||||
|
},
|
||||||
|
"exportOptions": {
|
||||||
|
"message": "Import/Export All Options"
|
||||||
|
},
|
||||||
|
"whatExportOptions": {
|
||||||
|
"message": "This is your entire configuration in JSON. This includes your userID, so be sure to share this wisely."
|
||||||
|
},
|
||||||
|
"setOptions": {
|
||||||
|
"message": "Set Options"
|
||||||
|
},
|
||||||
|
"exportOptionsWarning": {
|
||||||
|
"message": "Warning: Changing the options is permanent and can break your install. Are you sure you would like to do this? Make sure to backup your old one just in case."
|
||||||
|
},
|
||||||
|
"incorrectlyFormattedOptions": {
|
||||||
|
"message": "This JSON is not formatted correctly. Your options have not been changed."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -308,6 +308,32 @@
|
|||||||
<br/>
|
<br/>
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
|
<div option-type="private-text-change" sync-option="*" confirm-message="exportOptionsWarning">
|
||||||
|
<div class="option-button trigger-button">
|
||||||
|
__MSG_exportOptions__
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
<div class="small-description">__MSG_whatExportOptions__</div>
|
||||||
|
|
||||||
|
<div class="option-hidden-section hidden">
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
<input class="option-text-box" type="text">
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
<div class="option-button text-change-set">
|
||||||
|
__MSG_setOptions__
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
|
||||||
<div option-type="text-change" sync-option="serverAddress">
|
<div option-type="text-change" sync-option="serverAddress">
|
||||||
<label class="text-label-container">
|
<label class="text-label-container">
|
||||||
<div>__MSG_customServerAddress__</div>
|
<div>__MSG_customServerAddress__</div>
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
import * as Types from "./types";
|
import * as Types from "./types";
|
||||||
|
|
||||||
import Config from "./config";
|
import Config from "./config";
|
||||||
|
// Make the config public for debugging purposes
|
||||||
|
(<any> window).SB = Config;
|
||||||
|
|
||||||
import Utils from "./utils";
|
import Utils from "./utils";
|
||||||
var utils = new Utils({
|
var utils = new Utils({
|
||||||
|
|||||||
@@ -84,13 +84,8 @@ class SBMap<T, U> extends Map {
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
toJSON() {
|
|
||||||
return Array.from(this.entries());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var Config: SBObject = {
|
var Config: SBObject = {
|
||||||
/**
|
/**
|
||||||
* Callback function when an option is updated
|
* Callback function when an option is updated
|
||||||
@@ -131,14 +126,14 @@ var Config: SBObject = {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* A SBMap cannot be stored in the chrome storage.
|
* A SBMap cannot be stored in the chrome storage.
|
||||||
* This data will be encoded into an array instead as specified by the toJSON function.
|
* This data will be encoded into an array instead
|
||||||
*
|
*
|
||||||
* @param data
|
* @param data
|
||||||
*/
|
*/
|
||||||
function encodeStoredItem(data) {
|
function encodeStoredItem(data) {
|
||||||
// if data is SBMap convert to json for storing
|
// if data is SBMap convert to json for storing
|
||||||
if(!(data instanceof SBMap)) return data;
|
if(!(data instanceof SBMap)) return data;
|
||||||
return JSON.stringify(data);
|
return Array.from(data.entries());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -148,18 +143,30 @@ function encodeStoredItem(data) {
|
|||||||
* @param {*} data
|
* @param {*} data
|
||||||
*/
|
*/
|
||||||
function decodeStoredItem(id: string, data) {
|
function decodeStoredItem(id: string, data) {
|
||||||
if(typeof data !== "string") return data;
|
if (!Config.defaults[id]) return data;
|
||||||
|
|
||||||
try {
|
if (Config.defaults[id] instanceof SBMap) {
|
||||||
let str = JSON.parse(data);
|
try {
|
||||||
|
let jsonData: any = data;
|
||||||
|
|
||||||
if(!Array.isArray(str)) return data;
|
// Check if data is stored in the old format for SBMap (a JSON string)
|
||||||
return new SBMap(id, str);
|
if (typeof data === "string") {
|
||||||
} catch(e) {
|
try {
|
||||||
|
jsonData = JSON.parse(data);
|
||||||
|
} catch(e) {
|
||||||
|
// Continue normally (out of this if statement)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If all else fails, return the data
|
if (!Array.isArray(jsonData)) return data;
|
||||||
return data;
|
return new SBMap(id, jsonData);
|
||||||
|
} catch(e) {
|
||||||
|
console.error("Failed to parse SBMap: " + id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If all else fails, return the data
|
||||||
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
function configProxy(): any {
|
function configProxy(): any {
|
||||||
|
|||||||
@@ -45,7 +45,12 @@ var lastPreviewBarUpdate;
|
|||||||
var durationListenerSetUp = false;
|
var durationListenerSetUp = false;
|
||||||
|
|
||||||
// Is the video currently being switched
|
// Is the video currently being switched
|
||||||
var switchingVideos = false;
|
var switchingVideos = null;
|
||||||
|
|
||||||
|
// Used by the play and playing listeners to make sure two aren't
|
||||||
|
// called at the same time
|
||||||
|
var lastCheckTime = 0;
|
||||||
|
var lastCheckVideoTime = -1;
|
||||||
|
|
||||||
//the channel this video is about
|
//the channel this video is about
|
||||||
var channelURL;
|
var channelURL;
|
||||||
@@ -238,6 +243,9 @@ document.onkeydown = function(e: KeyboardEvent){
|
|||||||
}
|
}
|
||||||
|
|
||||||
function resetValues() {
|
function resetValues() {
|
||||||
|
lastCheckTime = 0;
|
||||||
|
lastCheckVideoTime = -1;
|
||||||
|
|
||||||
//reset sponsor times
|
//reset sponsor times
|
||||||
sponsorTimes = null;
|
sponsorTimes = null;
|
||||||
UUIDs = [];
|
UUIDs = [];
|
||||||
@@ -250,6 +258,8 @@ function resetValues() {
|
|||||||
|
|
||||||
//reset sponsor data found check
|
//reset sponsor data found check
|
||||||
sponsorDataFound = false;
|
sponsorDataFound = false;
|
||||||
|
|
||||||
|
switchingVideos = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function videoIDChange(id) {
|
async function videoIDChange(id) {
|
||||||
@@ -264,8 +274,6 @@ async function videoIDChange(id) {
|
|||||||
//id is not valid
|
//id is not valid
|
||||||
if (!id) return;
|
if (!id) return;
|
||||||
|
|
||||||
switchingVideos = true;
|
|
||||||
|
|
||||||
// Wait for options to be ready
|
// Wait for options to be ready
|
||||||
await utils.wait(() => Config.config !== null, 5000, 1);
|
await utils.wait(() => Config.config !== null, 5000, 1);
|
||||||
|
|
||||||
@@ -449,7 +457,7 @@ function startSponsorSchedule(currentTime?: number): void {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentTime === undefined) currentTime = video.currentTime;
|
if (currentTime === undefined || currentTime === null) currentTime = video.currentTime;
|
||||||
|
|
||||||
let skipInfo = getNextSkipIndex(currentTime);
|
let skipInfo = getNextSkipIndex(currentTime);
|
||||||
|
|
||||||
@@ -459,11 +467,19 @@ function startSponsorSchedule(currentTime?: number): void {
|
|||||||
let timeUntilSponsor = skipTime[0] - currentTime;
|
let timeUntilSponsor = skipTime[0] - currentTime;
|
||||||
|
|
||||||
let skippingFunction = () => {
|
let skippingFunction = () => {
|
||||||
|
let forcedSkipTime: number = null;
|
||||||
|
|
||||||
if (video.currentTime >= skipTime[0] && video.currentTime < skipTime[1]) {
|
if (video.currentTime >= skipTime[0] && video.currentTime < skipTime[1]) {
|
||||||
skipToTime(video, skipInfo.index, skipInfo.array, skipInfo.openNotice);
|
skipToTime(video, skipInfo.index, skipInfo.array, skipInfo.openNotice);
|
||||||
|
|
||||||
|
if (Config.config.disableAutoSkip) {
|
||||||
|
forcedSkipTime = skipTime[0] + 0.001;
|
||||||
|
} else {
|
||||||
|
forcedSkipTime = skipTime[1];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
startSponsorSchedule();
|
startSponsorSchedule(forcedSkipTime);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (timeUntilSponsor <= 0) {
|
if (timeUntilSponsor <= 0) {
|
||||||
@@ -493,7 +509,23 @@ function sponsorsLookup(id: string, channelIDPromise?) {
|
|||||||
|
|
||||||
video.addEventListener('play', () => {
|
video.addEventListener('play', () => {
|
||||||
switchingVideos = false;
|
switchingVideos = false;
|
||||||
startSponsorSchedule();
|
|
||||||
|
// Make sure it doesn't get double called with the playing event
|
||||||
|
if (lastCheckVideoTime !== video.currentTime && Date.now() - lastCheckTime > 2000) {
|
||||||
|
lastCheckTime = Date.now();
|
||||||
|
lastCheckVideoTime = video.currentTime;
|
||||||
|
|
||||||
|
startSponsorSchedule();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
video.addEventListener('playing', () => {
|
||||||
|
// Make sure it doesn't get double called with the play event
|
||||||
|
if (lastCheckVideoTime !== video.currentTime && Date.now() - lastCheckTime > 2000) {
|
||||||
|
lastCheckTime = Date.now();
|
||||||
|
lastCheckVideoTime = video.currentTime;
|
||||||
|
|
||||||
|
startSponsorSchedule();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
video.addEventListener('seeked', () => {
|
video.addEventListener('seeked', () => {
|
||||||
if (!video.paused) startSponsorSchedule();
|
if (!video.paused) startSponsorSchedule();
|
||||||
@@ -848,16 +880,14 @@ function skipToTime(v, index, sponsorTimes, openNotice) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//send telemetry that a this sponsor was skipped
|
//send telemetry that a this sponsor was skipped
|
||||||
if (Config.config.trackViewCount && !sponsorSkipped[index]) {
|
if (Config.config.trackViewCount && !sponsorSkipped[index] && !Config.config.disableAutoSkip) {
|
||||||
utils.sendRequestToServer("POST", "/api/viewedVideoSponsorTime?UUID=" + currentUUID);
|
utils.sendRequestToServer("POST", "/api/viewedVideoSponsorTime?UUID=" + currentUUID);
|
||||||
|
|
||||||
if (!Config.config.disableAutoSkip) {
|
// Count this as a skip
|
||||||
// Count this as a skip
|
Config.config.minutesSaved = Config.config.minutesSaved + (sponsorTimes[index][1] - sponsorTimes[index][0]) / 60;
|
||||||
Config.config.minutesSaved = Config.config.minutesSaved + (sponsorTimes[index][1] - sponsorTimes[index][0]) / 60;
|
Config.config.skipCount = Config.config.skipCount + 1;
|
||||||
Config.config.skipCount = Config.config.skipCount + 1;
|
|
||||||
|
|
||||||
sponsorSkipped[index] = true;
|
sponsorSkipped[index] = true;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
import Config from "../config";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The notice that tells the user that a sponsor was just skipped
|
* The notice that tells the user that a sponsor was just skipped
|
||||||
*/
|
*/
|
||||||
@@ -305,7 +307,7 @@ class SkipNotice {
|
|||||||
if (this.manualSkip) {
|
if (this.manualSkip) {
|
||||||
this.changeNoticeTitle(chrome.i18n.getMessage("noticeTitle"));
|
this.changeNoticeTitle(chrome.i18n.getMessage("noticeTitle"));
|
||||||
|
|
||||||
this.contentContainer().vote(1, this.UUID, this);
|
if (Config.config.autoUpvote) this.contentContainer().vote(1, this.UUID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
import Config from "./config";
|
import Config from "./config";
|
||||||
|
// Make the config public for debugging purposes
|
||||||
|
(<any> window).SB = Config;
|
||||||
|
|
||||||
import Utils from "./utils";
|
import Utils from "./utils";
|
||||||
var utils = new Utils();
|
var utils = new Utils();
|
||||||
@@ -72,7 +74,7 @@ async function init() {
|
|||||||
|
|
||||||
textChangeInput.value = Config.config[textChangeOption];
|
textChangeInput.value = Config.config[textChangeOption];
|
||||||
|
|
||||||
textChangeSetButton.addEventListener("click", () => {
|
textChangeSetButton.addEventListener("click", async () => {
|
||||||
// See if anything extra must be done
|
// See if anything extra must be done
|
||||||
switch (textChangeOption) {
|
switch (textChangeOption) {
|
||||||
case "serverAddress":
|
case "serverAddress":
|
||||||
@@ -84,6 +86,18 @@ async function init() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Permission needed on Firefox
|
||||||
|
if (utils.isFirefox()) {
|
||||||
|
let permissionSuccess = await new Promise((resolve, reject) => {
|
||||||
|
chrome.permissions.request({
|
||||||
|
origins: [textChangeInput.value + "/"],
|
||||||
|
permissions: []
|
||||||
|
}, resolve);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!permissionSuccess) return;
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -259,6 +273,8 @@ function invidiousOnClick(checkbox: HTMLInputElement, option: string) {
|
|||||||
if (!granted) {
|
if (!granted) {
|
||||||
Config.config[option] = false;
|
Config.config[option] = false;
|
||||||
checkbox.checked = false;
|
checkbox.checked = false;
|
||||||
|
} else {
|
||||||
|
checkbox.checked = true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@@ -346,14 +362,49 @@ function activatePrivateTextChange(element: HTMLElement) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
textBox.value = Config.config[option];
|
let result = Config.config[option];
|
||||||
|
|
||||||
|
// See if anything extra must be done
|
||||||
|
switch (option) {
|
||||||
|
case "*":
|
||||||
|
result = JSON.stringify(Config.localConfig);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
textBox.value = result;
|
||||||
|
|
||||||
let setButton = element.querySelector(".text-change-set");
|
let setButton = element.querySelector(".text-change-set");
|
||||||
setButton.addEventListener("click", () => {
|
setButton.addEventListener("click", () => {
|
||||||
let confirmMessage = element.getAttribute("confirm-message");
|
let confirmMessage = element.getAttribute("confirm-message");
|
||||||
|
|
||||||
if (confirmMessage === null || confirm(chrome.i18n.getMessage(confirmMessage))) {
|
if (confirmMessage === null || confirm(chrome.i18n.getMessage(confirmMessage))) {
|
||||||
Config.config[option] = textBox.value;
|
|
||||||
|
// See if anything extra must be done
|
||||||
|
switch (option) {
|
||||||
|
case "*":
|
||||||
|
try {
|
||||||
|
let newConfig = JSON.parse(textBox.value);
|
||||||
|
for (const key in newConfig) {
|
||||||
|
Config.config[key] = newConfig[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
init();
|
||||||
|
|
||||||
|
if (newConfig.supportInvidious) {
|
||||||
|
let checkbox = <HTMLInputElement> document.querySelector("#support-invidious > label > label > input");
|
||||||
|
|
||||||
|
checkbox.checked = true;
|
||||||
|
invidiousOnClick(checkbox, "supportInvidious");
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (e) {
|
||||||
|
alert(chrome.i18n.getMessage("incorrectlyFormattedOptions"));
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Config.config[option] = textBox.value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user