Compare commits
39 Commits
4.4
...
guidelines
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
97aea1c268 | ||
|
|
b70f50e1a0 | ||
|
|
4880227320 | ||
|
|
dfa21068f4 | ||
|
|
fd75a33e50 | ||
|
|
1409c563e2 | ||
|
|
588c42d579 | ||
|
|
d7ff6aa6a2 | ||
|
|
44266e508b | ||
|
|
c0f8f5e1d0 | ||
|
|
e948e1e569 | ||
|
|
5289e62d43 | ||
|
|
eda7aac5ef | ||
|
|
d9f4ab0d04 | ||
|
|
2665327729 | ||
|
|
4738c1897f | ||
|
|
cfbb194a61 | ||
|
|
9ad21e8ea1 | ||
|
|
941fc2985d | ||
|
|
e2da071761 | ||
|
|
c20c9ac64a | ||
|
|
2d59f3825c | ||
|
|
fb8b7a7d19 | ||
|
|
d992cc7a3c | ||
|
|
f8fecf5174 | ||
|
|
3007cddce9 | ||
|
|
2b3c812f8a | ||
|
|
61535fac95 | ||
|
|
4182595436 | ||
|
|
97e30e4001 | ||
|
|
6763fd3b4b | ||
|
|
a39ec76340 | ||
|
|
f68282decc | ||
|
|
160de56a71 | ||
|
|
bd4fbcc93d | ||
|
|
f1839eef94 | ||
|
|
3e3abf36e5 | ||
|
|
463ce258bf | ||
|
|
a64deb2e18 |
34
.eslintrc.js
@@ -1,34 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
env: {
|
|
||||||
browser: true,
|
|
||||||
es2021: true,
|
|
||||||
node: true,
|
|
||||||
jest: true,
|
|
||||||
jasmine: true,
|
|
||||||
},
|
|
||||||
extends: [
|
|
||||||
"eslint:recommended",
|
|
||||||
"plugin:react/recommended",
|
|
||||||
"plugin:@typescript-eslint/recommended",
|
|
||||||
],
|
|
||||||
parser: "@typescript-eslint/parser",
|
|
||||||
parserOptions: {
|
|
||||||
ecmaFeatures: {
|
|
||||||
jsx: true,
|
|
||||||
},
|
|
||||||
ecmaVersion: 12,
|
|
||||||
sourceType: "module",
|
|
||||||
},
|
|
||||||
plugins: ["react", "@typescript-eslint"],
|
|
||||||
rules: {
|
|
||||||
// TODO: Remove warn rules when not needed anymore
|
|
||||||
"no-self-assign": "off",
|
|
||||||
"@typescript-eslint/no-empty-interface": "off",
|
|
||||||
"react/prop-types": [2, { ignore: ['children'] }]
|
|
||||||
},
|
|
||||||
settings: {
|
|
||||||
react: {
|
|
||||||
version: "detect",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
33
.eslintrc.json
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
{
|
||||||
|
"env": {
|
||||||
|
"browser": true,
|
||||||
|
"es2021": true,
|
||||||
|
"node": true,
|
||||||
|
"jest": true
|
||||||
|
},
|
||||||
|
"extends": [
|
||||||
|
"eslint:recommended",
|
||||||
|
"plugin:react/recommended",
|
||||||
|
"plugin:@typescript-eslint/recommended"
|
||||||
|
],
|
||||||
|
"parser": "@typescript-eslint/parser",
|
||||||
|
"parserOptions": {
|
||||||
|
"ecmaFeatures": {
|
||||||
|
"jsx": true
|
||||||
|
},
|
||||||
|
"ecmaVersion": 12,
|
||||||
|
"sourceType": "module"
|
||||||
|
},
|
||||||
|
"plugins": ["react", "@typescript-eslint"],
|
||||||
|
"rules": {
|
||||||
|
"@typescript-eslint/no-unused-vars": "error",
|
||||||
|
"no-self-assign": "off",
|
||||||
|
"@typescript-eslint/no-empty-interface": "off",
|
||||||
|
"react/prop-types": [2, { "ignore": ["children"] }]
|
||||||
|
},
|
||||||
|
"settings": {
|
||||||
|
"react": {
|
||||||
|
"version": "detect"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,4 +5,5 @@ module.exports = {
|
|||||||
"transform": {
|
"transform": {
|
||||||
"^.+\\.ts$": "ts-jest"
|
"^.+\\.ts$": "ts-jest"
|
||||||
},
|
},
|
||||||
|
"reporters": ["github-actions"]
|
||||||
};
|
};
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "__MSG_fullName__",
|
"name": "__MSG_fullName__",
|
||||||
"short_name": "SponsorBlock",
|
"short_name": "SponsorBlock",
|
||||||
"version": "4.4",
|
"version": "4.4.5",
|
||||||
"default_locale": "en",
|
"default_locale": "en",
|
||||||
"description": "__MSG_Description__",
|
"description": "__MSG_Description__",
|
||||||
"homepage_url": "https://sponsor.ajay.app",
|
"homepage_url": "https://sponsor.ajay.app",
|
||||||
@@ -34,6 +34,7 @@
|
|||||||
"icons/settings.svg",
|
"icons/settings.svg",
|
||||||
"icons/pencil.svg",
|
"icons/pencil.svg",
|
||||||
"icons/check.svg",
|
"icons/check.svg",
|
||||||
|
"icons/check-smaller.svg",
|
||||||
"icons/upvote.png",
|
"icons/upvote.png",
|
||||||
"icons/downvote.png",
|
"icons/downvote.png",
|
||||||
"icons/thumbs_down.svg",
|
"icons/thumbs_down.svg",
|
||||||
@@ -50,6 +51,16 @@
|
|||||||
"icons/heart.svg",
|
"icons/heart.svg",
|
||||||
"icons/visible.svg",
|
"icons/visible.svg",
|
||||||
"icons/not_visible.svg",
|
"icons/not_visible.svg",
|
||||||
|
"icons/money.svg",
|
||||||
|
"icons/segway.png",
|
||||||
|
"icons/close-smaller.svg",
|
||||||
|
"icons/right-arrow.svg",
|
||||||
|
"icons/campaign.svg",
|
||||||
|
"icons/star.svg",
|
||||||
|
"icons/lightbulb.svg",
|
||||||
|
"icons/bolt.svg",
|
||||||
|
"icons/stopwatch.svg",
|
||||||
|
"icons/music-note.svg",
|
||||||
"icons/PlayerInfoIconSponsorBlocker.svg",
|
"icons/PlayerInfoIconSponsorBlocker.svg",
|
||||||
"icons/PlayerDeleteIconSponsorBlocker.svg",
|
"icons/PlayerDeleteIconSponsorBlocker.svg",
|
||||||
"popup.html",
|
"popup.html",
|
||||||
@@ -64,7 +75,35 @@
|
|||||||
],
|
],
|
||||||
"browser_action": {
|
"browser_action": {
|
||||||
"default_title": "SponsorBlock",
|
"default_title": "SponsorBlock",
|
||||||
"default_popup": "popup.html"
|
"default_popup": "popup.html",
|
||||||
|
"default_icon": {
|
||||||
|
"16": "icons/IconSponsorBlocker16px.png",
|
||||||
|
"32": "icons/IconSponsorBlocker32px.png",
|
||||||
|
"64": "icons/LogoSponsorBlocker64px.png",
|
||||||
|
"128": "icons/LogoSponsorBlocker128px.png"
|
||||||
|
},
|
||||||
|
"theme_icons": [
|
||||||
|
{
|
||||||
|
"light": "icons/IconSponsorBlocker16px.png",
|
||||||
|
"dark": "icons/IconSponsorBlocker16px.png",
|
||||||
|
"size": 16
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"light": "icons/IconSponsorBlocker32px.png",
|
||||||
|
"dark": "icons/IconSponsorBlocker32px.png",
|
||||||
|
"size": 32
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"light": "icons/LogoSponsorBlocker64px.png",
|
||||||
|
"dark": "icons/LogoSponsorBlocker64px.png",
|
||||||
|
"size": 64
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"light": "icons/LogoSponsorBlocker128px.png",
|
||||||
|
"dark": "icons/LogoSponsorBlocker128px.png",
|
||||||
|
"size": 128
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"background": {
|
"background": {
|
||||||
"scripts":[
|
"scripts":[
|
||||||
|
|||||||
6138
package-lock.json
generated
41
package.json
@@ -3,39 +3,40 @@
|
|||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "background.js",
|
"main": "background.js",
|
||||||
|
"type": "module",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
"react-dom": "^17.0.2"
|
"react-dom": "^17.0.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/chrome": "^0.0.180",
|
"@types/chrome": "^0.0.188",
|
||||||
"@types/firefox-webext-browser": "^94.0.1",
|
"@types/firefox-webext-browser": "^94.0.1",
|
||||||
"@types/jest": "^27.4.1",
|
"@types/jest": "^27.5.1",
|
||||||
"@types/react": "^17.0.43",
|
"@types/react": "^17.0.43",
|
||||||
"@types/react-dom": "^17.0.14",
|
"@types/react-dom": "^17.0.14",
|
||||||
"@types/selenium-webdriver": "^4.0.18",
|
"@types/selenium-webdriver": "^4.1.0",
|
||||||
"@types/wicg-mediasession": "^1.1.3",
|
"@types/wicg-mediasession": "^1.1.3",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.17.0",
|
"@typescript-eslint/eslint-plugin": "^5.26.0",
|
||||||
"@typescript-eslint/parser": "^5.17.0",
|
"@typescript-eslint/parser": "^5.26.0",
|
||||||
"chromedriver": "^100.0.0",
|
"chromedriver": "^101.0.0",
|
||||||
"concurrently": "^7.0.0",
|
"concurrently": "^7.2.1",
|
||||||
"copy-webpack-plugin": "^10.2.4",
|
"copy-webpack-plugin": "^11.0.0",
|
||||||
"eslint": "^8.12.0",
|
"eslint": "^8.16.0",
|
||||||
"eslint-plugin-react": "^7.29.4",
|
"eslint-plugin-react": "^7.30.0",
|
||||||
"fork-ts-checker-webpack-plugin": "^7.2.1",
|
"fork-ts-checker-webpack-plugin": "^7.2.11",
|
||||||
"jest": "^27.5.1",
|
"jest": "^28.1.0",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^3.0.2",
|
||||||
"schema-utils": "^4.0.0",
|
"schema-utils": "^4.0.0",
|
||||||
"selenium-webdriver": "^4.1.1",
|
"selenium-webdriver": "^4.1.2",
|
||||||
"speed-measure-webpack-plugin": "^1.5.0",
|
"speed-measure-webpack-plugin": "^1.5.0",
|
||||||
"ts-jest": "^27.1.4",
|
"ts-jest": "^28.0.3",
|
||||||
"ts-loader": "^9.2.8",
|
"ts-loader": "^9.3.0",
|
||||||
"ts-node": "^10.7.0",
|
"ts-node": "^10.8.0",
|
||||||
"typescript": "4.6",
|
"typescript": "4.7",
|
||||||
"web-ext": "^6.8.0",
|
"web-ext": "^6.8.0",
|
||||||
"webpack": "^5.64.4",
|
"webpack": "^5.72.1",
|
||||||
"webpack-cli": "^4.9.2",
|
"webpack-cli": "^4.9.2",
|
||||||
"webpack-merge": "^4.2.2"
|
"webpack-merge": "^5.8.0"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"web-run": "npm run web-run:chrome",
|
"web-run": "npm run web-run:chrome",
|
||||||
@@ -65,7 +66,7 @@
|
|||||||
"lint:fix": "eslint src --fix"
|
"lint:fix": "eslint src --fix"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=12.20.0"
|
"node": ">=16"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -101,7 +101,7 @@
|
|||||||
"message": "It seems the server is down. Contact the dev immediately."
|
"message": "It seems the server is down. Contact the dev immediately."
|
||||||
},
|
},
|
||||||
"connectionError": {
|
"connectionError": {
|
||||||
"message": "A connection error has occured. Error code: "
|
"message": "A connection error has occurred. Error code: "
|
||||||
},
|
},
|
||||||
"clearTimes": {
|
"clearTimes": {
|
||||||
"message": "Clear Segments"
|
"message": "Clear Segments"
|
||||||
@@ -239,6 +239,9 @@
|
|||||||
"showSkipNotice": {
|
"showSkipNotice": {
|
||||||
"message": "Show Notice After A Segment Is Skipped"
|
"message": "Show Notice After A Segment Is Skipped"
|
||||||
},
|
},
|
||||||
|
"showCategoryGuidelines": {
|
||||||
|
"message": "Show Category Help"
|
||||||
|
},
|
||||||
"noticeVisibilityMode0": {
|
"noticeVisibilityMode0": {
|
||||||
"message": "Full Size Skip Notices"
|
"message": "Full Size Skip Notices"
|
||||||
},
|
},
|
||||||
@@ -356,7 +359,7 @@
|
|||||||
"message": "Show Time With Skips Removed"
|
"message": "Show Time With Skips Removed"
|
||||||
},
|
},
|
||||||
"showTimeWithSkipsDescription": {
|
"showTimeWithSkipsDescription": {
|
||||||
"message": "This time appears in brackets next to the current time on below the seekbar. This shows the total video duration minus any segments. This includes segments marked as only \"Show In Seekbar\"."
|
"message": "This time appears in brackets next to the current time on below the Seek Bar. This shows the total video duration minus any segments. This includes segments marked as only \"Show In Seek Bar\"."
|
||||||
},
|
},
|
||||||
"youHaveSkipped": {
|
"youHaveSkipped": {
|
||||||
"message": "You've skipped "
|
"message": "You've skipped "
|
||||||
@@ -542,18 +545,39 @@
|
|||||||
"message": "to",
|
"message": "to",
|
||||||
"description": "Used between segments. Example: 1:20 to 1:30"
|
"description": "Used between segments. Example: 1:20 to 1:30"
|
||||||
},
|
},
|
||||||
|
"generic_guideline1": {
|
||||||
|
"message": "Include segue transitions"
|
||||||
|
},
|
||||||
|
"generic_guideline2": {
|
||||||
|
"message": "Plays as if nothing was skipped"
|
||||||
|
},
|
||||||
"category_sponsor": {
|
"category_sponsor": {
|
||||||
"message": "Sponsor"
|
"message": "Sponsor"
|
||||||
},
|
},
|
||||||
"category_sponsor_description": {
|
"category_sponsor_description": {
|
||||||
"message": "Paid promotion, paid referrals and direct advertisements. Not for self-promotion or free shoutouts to causes/creators/websites/products they like."
|
"message": "Paid promotion, paid referrals and direct advertisements. Not for self-promotion or free shoutouts to causes/creators/websites/products they like."
|
||||||
},
|
},
|
||||||
|
"category_sponsor_guideline1": {
|
||||||
|
"message": "Paid promotions"
|
||||||
|
},
|
||||||
|
"category_sponsor_guideline2": {
|
||||||
|
"message": "Not for donations or custom merch"
|
||||||
|
},
|
||||||
"category_selfpromo": {
|
"category_selfpromo": {
|
||||||
"message": "Unpaid/Self Promotion"
|
"message": "Unpaid/Self Promotion"
|
||||||
},
|
},
|
||||||
"category_selfpromo_description": {
|
"category_selfpromo_description": {
|
||||||
"message": "Similar to \"sponsor\" except for unpaid or self promotion. This includes sections about merchandise, donations, or information about who they collaborated with."
|
"message": "Similar to \"sponsor\" except for unpaid or self promotion. This includes sections about merchandise, donations, or information about who they collaborated with."
|
||||||
},
|
},
|
||||||
|
"category_selfpromo_guideline1": {
|
||||||
|
"message": "Donations, memberships and custom merch"
|
||||||
|
},
|
||||||
|
"category_selfpromo_guideline2": {
|
||||||
|
"message": "Free shoutouts that don't add to the video"
|
||||||
|
},
|
||||||
|
"category_selfpromo_guideline3": {
|
||||||
|
"message": "Not for corporate designed products and merch"
|
||||||
|
},
|
||||||
"category_exclusive_access": {
|
"category_exclusive_access": {
|
||||||
"message": "Exclusive Access"
|
"message": "Exclusive Access"
|
||||||
},
|
},
|
||||||
@@ -564,12 +588,24 @@
|
|||||||
"message": "This video showcases a product, service or location that they've received free or subsidized access to",
|
"message": "This video showcases a product, service or location that they've received free or subsidized access to",
|
||||||
"description": "Short description for this category"
|
"description": "Short description for this category"
|
||||||
},
|
},
|
||||||
|
"category_exclusive_access_guideline1": {
|
||||||
|
"message": "Entire video showcases something where recieved free or subsidized access"
|
||||||
|
},
|
||||||
"category_interaction": {
|
"category_interaction": {
|
||||||
"message": "Interaction Reminder (Subscribe)"
|
"message": "Interaction Reminder (Subscribe)"
|
||||||
},
|
},
|
||||||
"category_interaction_description": {
|
"category_interaction_description": {
|
||||||
"message": "When there is a short reminder to like, subscribe or follow them in the middle of content. If it is long or about something specific, it should be under self promotion instead."
|
"message": "When there is a short reminder to like, subscribe or follow them in the middle of content. If it is long or about something specific, it should be under self promotion instead."
|
||||||
},
|
},
|
||||||
|
"category_interaction_guideline1": {
|
||||||
|
"message": "Short reminders to like, subscribe or follow"
|
||||||
|
},
|
||||||
|
"category_interaction_guideline2": {
|
||||||
|
"message": "Includes indirect reminders to comment"
|
||||||
|
},
|
||||||
|
"category_interaction_guideline3": {
|
||||||
|
"message": "Not for general promotion, only calls to action"
|
||||||
|
},
|
||||||
"category_interaction_short": {
|
"category_interaction_short": {
|
||||||
"message": "Interaction Reminder"
|
"message": "Interaction Reminder"
|
||||||
},
|
},
|
||||||
@@ -582,18 +618,36 @@
|
|||||||
"category_intro_short": {
|
"category_intro_short": {
|
||||||
"message": "Intermission"
|
"message": "Intermission"
|
||||||
},
|
},
|
||||||
|
"category_intro_guideline1": {
|
||||||
|
"message": "Interval without actual content"
|
||||||
|
},
|
||||||
|
"category_intro_guideline2": {
|
||||||
|
"message": "Not for transitions with information"
|
||||||
|
},
|
||||||
"category_outro": {
|
"category_outro": {
|
||||||
"message": "Endcards/Credits"
|
"message": "Endcards/Credits"
|
||||||
},
|
},
|
||||||
"category_outro_description": {
|
"category_outro_description": {
|
||||||
"message": "Credits or when the YouTube endcards appear. Not for conclusions with information."
|
"message": "Credits or when the YouTube endcards appear. Not for conclusions with information."
|
||||||
},
|
},
|
||||||
|
"category_outro_guideline1": {
|
||||||
|
"message": "Don't include content, even if endcards are on screen"
|
||||||
|
},
|
||||||
"category_preview": {
|
"category_preview": {
|
||||||
"message": "Preview/Recap"
|
"message": "Preview/Recap"
|
||||||
},
|
},
|
||||||
"category_preview_description": {
|
"category_preview_description": {
|
||||||
"message": "Quick recap of previous episodes, or a preview of what's coming up later in the current video. Meant for edited together clips, not for spoken summaries."
|
"message": "Quick recap of previous episodes, or a preview of what's coming up later in the current video. Meant for edited together clips, not for spoken summaries."
|
||||||
},
|
},
|
||||||
|
"category_preview_guideline1": {
|
||||||
|
"message": "Clips that appear later, or in a future video"
|
||||||
|
},
|
||||||
|
"category_preview_guideline2": {
|
||||||
|
"message": "Recap of a previous video"
|
||||||
|
},
|
||||||
|
"category_preview_guideline3": {
|
||||||
|
"message": "Not for sections that add additional content"
|
||||||
|
},
|
||||||
"category_filler": {
|
"category_filler": {
|
||||||
"message": "Filler Tangent/Jokes"
|
"message": "Filler Tangent/Jokes"
|
||||||
},
|
},
|
||||||
@@ -603,6 +657,15 @@
|
|||||||
"category_filler_short": {
|
"category_filler_short": {
|
||||||
"message": "Filler"
|
"message": "Filler"
|
||||||
},
|
},
|
||||||
|
"category_filler_guideline1": {
|
||||||
|
"message": "Tangential scenes only for filler or humor"
|
||||||
|
},
|
||||||
|
"category_filler_guideline2": {
|
||||||
|
"message": "Distractions, bloopers, replays"
|
||||||
|
},
|
||||||
|
"category_filler_guideline3": {
|
||||||
|
"message": "Not for scenes required to understand the topic"
|
||||||
|
},
|
||||||
"category_music_offtopic": {
|
"category_music_offtopic": {
|
||||||
"message": "Music: Non-Music Section"
|
"message": "Music: Non-Music Section"
|
||||||
},
|
},
|
||||||
@@ -612,12 +675,27 @@
|
|||||||
"category_music_offtopic_short": {
|
"category_music_offtopic_short": {
|
||||||
"message": "Non-Music"
|
"message": "Non-Music"
|
||||||
},
|
},
|
||||||
|
"category_music_offtopic_guideline1": {
|
||||||
|
"message": "Sections not in official releases"
|
||||||
|
},
|
||||||
|
"category_music_offtopic_guideline2": {
|
||||||
|
"message": "Non-music in a live performance"
|
||||||
|
},
|
||||||
"category_poi_highlight": {
|
"category_poi_highlight": {
|
||||||
"message": "Highlight"
|
"message": "Highlight"
|
||||||
},
|
},
|
||||||
"category_poi_highlight_description": {
|
"category_poi_highlight_description": {
|
||||||
"message": "The part of the video that most people are looking for. Similar to \"Video starts at x\" comments."
|
"message": "The part of the video that most people are looking for. Similar to \"Video starts at x\" comments."
|
||||||
},
|
},
|
||||||
|
"category_poi_highlight_guideline1": {
|
||||||
|
"message": "Section most people are looking for"
|
||||||
|
},
|
||||||
|
"category_poi_highlight_guideline2": {
|
||||||
|
"message": "Can help skip past context"
|
||||||
|
},
|
||||||
|
"category_poi_highlight_guideline3": {
|
||||||
|
"message": "Can skip to the title or thumbnail"
|
||||||
|
},
|
||||||
"category_livestream_messages": {
|
"category_livestream_messages": {
|
||||||
"message": "Livestream: Donation/Message Readings"
|
"message": "Livestream: Donation/Message Readings"
|
||||||
},
|
},
|
||||||
@@ -866,6 +944,9 @@
|
|||||||
},
|
},
|
||||||
"LearnMore": {
|
"LearnMore": {
|
||||||
"message": "Learn More"
|
"message": "Learn More"
|
||||||
|
},
|
||||||
|
"FullDetails": {
|
||||||
|
"message": "Full Details"
|
||||||
},
|
},
|
||||||
"CopyDownvoteButtonInfo": {
|
"CopyDownvoteButtonInfo": {
|
||||||
"message": "Downvotes and creates a local copy for you to resubmit"
|
"message": "Downvotes and creates a local copy for you to resubmit"
|
||||||
@@ -947,5 +1028,11 @@
|
|||||||
},
|
},
|
||||||
"openOptionsPage": {
|
"openOptionsPage": {
|
||||||
"message": "Open options page"
|
"message": "Open options page"
|
||||||
|
},
|
||||||
|
"resetToDefault": {
|
||||||
|
"message": "Reset settings to default"
|
||||||
|
},
|
||||||
|
"confirmResetToDefault": {
|
||||||
|
"message": "Are you sure you want to reset all settings to their default values? This cannot be undone."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -186,7 +186,7 @@
|
|||||||
"message": "Detta döljer knapparna på YouTube-spelaren som du kan skicka in segment med som ska hoppas över."
|
"message": "Detta döljer knapparna på YouTube-spelaren som du kan skicka in segment med som ska hoppas över."
|
||||||
},
|
},
|
||||||
"showSkipButton": {
|
"showSkipButton": {
|
||||||
"message": "Behåll knappen hoppa till markerat på spelaren"
|
"message": "Behåll knappen hoppa till höjdpunkt på spelaren"
|
||||||
},
|
},
|
||||||
"showInfoButton": {
|
"showInfoButton": {
|
||||||
"message": "Visa Infoknapp På YouTube-spelaren"
|
"message": "Visa Infoknapp På YouTube-spelaren"
|
||||||
@@ -613,7 +613,7 @@
|
|||||||
"message": "Icke-musik"
|
"message": "Icke-musik"
|
||||||
},
|
},
|
||||||
"category_poi_highlight": {
|
"category_poi_highlight": {
|
||||||
"message": "Markera"
|
"message": "Höjdpunkt"
|
||||||
},
|
},
|
||||||
"category_poi_highlight_description": {
|
"category_poi_highlight_description": {
|
||||||
"message": "Den del av videon som de flesta letar efter. Liknande kommentarer \"Video börjar på x\"."
|
"message": "Den del av videon som de flesta letar efter. Liknande kommentarer \"Video börjar på x\"."
|
||||||
|
|||||||
@@ -156,9 +156,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.sponsorSkipNoticeParent, .sponsorSkipNotice {
|
.sponsorSkipNoticeParent, .sponsorSkipNotice {
|
||||||
min-width: 350px;
|
|
||||||
max-width: 50%;
|
|
||||||
|
|
||||||
border-spacing: 5px 10px;
|
border-spacing: 5px 10px;
|
||||||
padding-left: 5px;
|
padding-left: 5px;
|
||||||
padding-right: 5px;
|
padding-right: 5px;
|
||||||
@@ -166,6 +163,15 @@
|
|||||||
border-collapse: unset;
|
border-collapse: unset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sponsorSkipNoticeParent {
|
||||||
|
min-width: 350px;
|
||||||
|
max-width: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sponsorSkipNotice {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.sponsorSkipNoticeTableContainer {
|
.sponsorSkipNoticeTableContainer {
|
||||||
background-color: rgba(28, 28, 28, 0.9);
|
background-color: rgba(28, 28, 28, 0.9);
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
@@ -177,7 +183,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.sponsorSkipNoticeLimitWidth {
|
.sponsorSkipNoticeLimitWidth {
|
||||||
min-width: calc(100% - 50px);
|
max-width: calc(100% - 50px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.sponsorSkipNotice .hidden {
|
.sponsorSkipNotice .hidden {
|
||||||
@@ -347,6 +353,22 @@
|
|||||||
color: rgb(235, 235, 235);
|
color: rgb(235, 235, 235);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sb-guidelines-notice .sponsorTimesInfoMessage td {
|
||||||
|
padding-left: 5px;
|
||||||
|
padding-top: 2px;
|
||||||
|
padding-bottom: 2px;
|
||||||
|
font-size: 15px;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sponsorTimesInfoIcon {
|
||||||
|
width: 30px;
|
||||||
|
padding-right: 10px;
|
||||||
|
padding-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
.segmentSummary {
|
.segmentSummary {
|
||||||
outline: none !important;
|
outline: none !important;
|
||||||
}
|
}
|
||||||
|
|||||||
37
public/icons/bolt.svg
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
height="48"
|
||||||
|
width="48"
|
||||||
|
version="1.1"
|
||||||
|
id="svg4"
|
||||||
|
sodipodi:docname="bolt.svg"
|
||||||
|
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04, custom)"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<defs
|
||||||
|
id="defs8" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview6"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="13.125"
|
||||||
|
inkscape:cx="24"
|
||||||
|
inkscape:cy="24"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="983"
|
||||||
|
inkscape:window-x="482"
|
||||||
|
inkscape:window-y="768"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="svg4" />
|
||||||
|
<path
|
||||||
|
d="M19.95 42 22 27.9H14.7Q14.15 27.9 13.9 27.4Q13.65 26.9 13.9 26.45L26.15 6H28.2L26.15 20.05H33.35Q33.9 20.05 34.175 20.55Q34.45 21.05 34.2 21.5L22 42Z"
|
||||||
|
id="path2"
|
||||||
|
style="fill:#ffffff" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.2 KiB |
37
public/icons/campaign.svg
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
height="48"
|
||||||
|
width="48"
|
||||||
|
version="1.1"
|
||||||
|
id="svg4"
|
||||||
|
sodipodi:docname="campaign.svg"
|
||||||
|
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04, custom)"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<defs
|
||||||
|
id="defs8" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview6"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="13.125"
|
||||||
|
inkscape:cx="24"
|
||||||
|
inkscape:cy="24"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="983"
|
||||||
|
inkscape:window-x="482"
|
||||||
|
inkscape:window-y="768"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="svg4" />
|
||||||
|
<path
|
||||||
|
d="M36.5 25.5V22.5H44V25.5ZM39 40 32.95 35.5 34.75 33.1 40.8 37.6ZM34.9 14.85 33.1 12.45 39 8 40.8 10.4ZM10.5 38V30H7Q5.75 30 4.875 29.125Q4 28.25 4 27V21Q4 19.75 4.875 18.875Q5.75 18 7 18H16L26 12V36L16 30H13.5V38ZM28 30.7V17.3Q29.35 18.5 30.175 20.225Q31 21.95 31 24Q31 26.05 30.175 27.775Q29.35 29.5 28 30.7Z"
|
||||||
|
id="path2"
|
||||||
|
style="fill:#ffffff" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.3 KiB |
38
public/icons/check-smaller.svg
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
version="1.1"
|
||||||
|
id="svg4"
|
||||||
|
sodipodi:docname="check-smaller.svg"
|
||||||
|
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04, custom)"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<defs
|
||||||
|
id="defs8" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview6"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="26.25"
|
||||||
|
inkscape:cx="12.038095"
|
||||||
|
inkscape:cy="12"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="983"
|
||||||
|
inkscape:window-x="482"
|
||||||
|
inkscape:window-y="768"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="svg4" />
|
||||||
|
<path
|
||||||
|
fill="#ffffff"
|
||||||
|
d="M 17.69347,4.9833775 9.9421192,12.940517 6.3065298,9.5107153 3.7684768,12.048769 9.9421192,18.016623 20.231523,7.5214304 Z"
|
||||||
|
id="path2"
|
||||||
|
style="stroke-width:0.68596" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.2 KiB |
37
public/icons/close-smaller.svg
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
height="48"
|
||||||
|
width="48"
|
||||||
|
version="1.1"
|
||||||
|
id="svg4"
|
||||||
|
sodipodi:docname="close-smaller.svg"
|
||||||
|
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04, custom)"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<defs
|
||||||
|
id="defs8" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview6"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="13.125"
|
||||||
|
inkscape:cx="24"
|
||||||
|
inkscape:cy="24"
|
||||||
|
inkscape:window-width="1366"
|
||||||
|
inkscape:window-height="731"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="0"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="svg4" />
|
||||||
|
<path
|
||||||
|
d="M12.45 37.65 10.35 35.55 21.9 24 10.35 12.45 12.45 10.35 24 21.9 35.55 10.35 37.65 12.45 26.1 24 37.65 35.55 35.55 37.65 24 26.1Z"
|
||||||
|
id="path2"
|
||||||
|
style="fill:#ffffff" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.1 KiB |
37
public/icons/lightbulb.svg
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
height="48"
|
||||||
|
width="48"
|
||||||
|
version="1.1"
|
||||||
|
id="svg4"
|
||||||
|
sodipodi:docname="lightbulb.svg"
|
||||||
|
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04, custom)"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<defs
|
||||||
|
id="defs8" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview6"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="13.125"
|
||||||
|
inkscape:cx="24"
|
||||||
|
inkscape:cy="24"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="983"
|
||||||
|
inkscape:window-x="482"
|
||||||
|
inkscape:window-y="768"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="svg4" />
|
||||||
|
<path
|
||||||
|
d="M24 44Q22.3 44 21.125 42.825Q19.95 41.65 19.95 39.95H28.05Q28.05 41.65 26.875 42.825Q25.7 44 24 44ZM15.9 36.85V33.85H32.1V36.85ZM16.15 30.8Q12.85 28.65 10.925 25.425Q9 22.2 9 18.15Q9 12.05 13.45 7.6Q17.9 3.15 24 3.15Q30.1 3.15 34.55 7.6Q39 12.05 39 18.15Q39 22.2 37.1 25.425Q35.2 28.65 31.85 30.8Z"
|
||||||
|
id="path2"
|
||||||
|
style="fill:#ffffff" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.3 KiB |
37
public/icons/money.svg
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
height="48"
|
||||||
|
width="48"
|
||||||
|
version="1.1"
|
||||||
|
id="svg4"
|
||||||
|
sodipodi:docname="money.svg"
|
||||||
|
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04, custom)"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<defs
|
||||||
|
id="defs8" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview6"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="6.5625"
|
||||||
|
inkscape:cx="37.942857"
|
||||||
|
inkscape:cy="29.714286"
|
||||||
|
inkscape:window-width="1366"
|
||||||
|
inkscape:window-height="731"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="0"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="svg4" />
|
||||||
|
<path
|
||||||
|
d="M 22.070204,47.757552 V 42.214123 Q 18.308592,41.554191 15.89984,39.343419 13.491088,37.132647 12.435197,33.766994 l 3.695619,-1.517844 q 1.121884,3.167674 3.233667,4.718514 2.111782,1.55084 5.081476,1.55084 3.167674,0 5.213463,-1.583837 2.045789,-1.583837 2.045789,-4.355551 0,-2.903701 -1.814813,-4.487538 -1.814813,-1.583836 -6.830296,-3.233666 -4.75151,-1.517844 -7.094269,-4.025586 -2.342759,-2.507741 -2.342759,-6.269354 0,-3.629626 2.342759,-6.0713741 2.342759,-2.4417484 6.104371,-2.7717144 V 0.24244792 h 3.959592 V 5.7198835 q 2.969694,0.329966 5.114473,1.9467994 2.144779,1.6168335 3.266663,4.1245751 l -3.695619,1.583837 q -0.923905,-2.111783 -2.474745,-3.068684 -1.55084,-0.9569014 -4.058582,-0.9569014 -3.035687,0 -4.817503,1.3858574 -1.781817,1.385857 -1.781817,3.761612 0,2.507742 1.979796,4.058582 1.979796,1.55084 7.325246,3.20067 4.487537,1.385857 6.632316,3.992589 2.144779,2.606731 2.144779,6.566323 0,4.157572 -2.441748,6.69831 -2.441749,2.540738 -7.193259,3.266663 v 5.477436 z"
|
||||||
|
id="path2"
|
||||||
|
style="fill:#ffffff;stroke-width:1.31986" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.0 KiB |
37
public/icons/music-note.svg
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
height="48"
|
||||||
|
width="48"
|
||||||
|
version="1.1"
|
||||||
|
id="svg4"
|
||||||
|
sodipodi:docname="music-note.svg"
|
||||||
|
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04, custom)"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<defs
|
||||||
|
id="defs8" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview6"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="13.125"
|
||||||
|
inkscape:cx="24"
|
||||||
|
inkscape:cy="24"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="983"
|
||||||
|
inkscape:window-x="482"
|
||||||
|
inkscape:window-y="768"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="svg4" />
|
||||||
|
<path
|
||||||
|
d="M19.65 42Q16.5 42 14.325 39.825Q12.15 37.65 12.15 34.5Q12.15 31.35 14.325 29.175Q16.5 27 19.65 27Q21.05 27 22.175 27.4Q23.3 27.8 24.15 28.5V6H35.85V12.75H27.15V34.5Q27.15 37.65 24.975 39.825Q22.8 42 19.65 42Z"
|
||||||
|
id="path2"
|
||||||
|
style="fill:#ffffff" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.2 KiB |
37
public/icons/right-arrow.svg
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
height="48"
|
||||||
|
width="48"
|
||||||
|
version="1.1"
|
||||||
|
id="svg4"
|
||||||
|
sodipodi:docname="right-arrow.svg"
|
||||||
|
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04, custom)"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<defs
|
||||||
|
id="defs8" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview6"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="13.125"
|
||||||
|
inkscape:cx="24.07619"
|
||||||
|
inkscape:cy="24"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="983"
|
||||||
|
inkscape:window-x="482"
|
||||||
|
inkscape:window-y="768"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="svg4" />
|
||||||
|
<path
|
||||||
|
d="M 17.039265,39.62264 14.838095,37.382164 28.320259,23.9 14.838095,10.417836 17.039265,8.1773601 32.761905,23.9 Z"
|
||||||
|
id="path2"
|
||||||
|
style="fill:#ffffff;stroke-width:0.786132" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.2 KiB |
BIN
public/icons/segway.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
37
public/icons/star.svg
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
height="48"
|
||||||
|
width="48"
|
||||||
|
version="1.1"
|
||||||
|
id="svg4"
|
||||||
|
sodipodi:docname="star.svg"
|
||||||
|
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04, custom)"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<defs
|
||||||
|
id="defs8" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview6"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="13.125"
|
||||||
|
inkscape:cx="24"
|
||||||
|
inkscape:cy="24"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="983"
|
||||||
|
inkscape:window-x="482"
|
||||||
|
inkscape:window-y="768"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="svg4" />
|
||||||
|
<path
|
||||||
|
d="M11.65 44 16.3 28.8 4 20H19.2L24 4L28.8 20H44L31.7 28.8L36.35 44L24 34.6Z"
|
||||||
|
id="path2"
|
||||||
|
style="fill:#ffffff" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.1 KiB |
37
public/icons/stopwatch.svg
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
height="48"
|
||||||
|
width="48"
|
||||||
|
version="1.1"
|
||||||
|
id="svg4"
|
||||||
|
sodipodi:docname="stopwatch.svg"
|
||||||
|
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04, custom)"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<defs
|
||||||
|
id="defs8" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview6"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="13.125"
|
||||||
|
inkscape:cx="24"
|
||||||
|
inkscape:cy="24"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="983"
|
||||||
|
inkscape:window-x="482"
|
||||||
|
inkscape:window-y="768"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="svg4" />
|
||||||
|
<path
|
||||||
|
d="M14.45 34Q16.3 35.95 18.8 36.975Q21.3 38 24 38Q29.85 38 33.925 33.925Q38 29.85 38 24Q38 18.15 33.925 14.075Q29.85 10 24 10V24ZM24 44Q19.75 44 16.1 42.475Q12.45 40.95 9.75 38.25Q7.05 35.55 5.525 31.9Q4 28.25 4 24Q4 19.8 5.525 16.15Q7.05 12.5 9.75 9.8Q12.45 7.1 16.1 5.55Q19.75 4 24 4Q28.2 4 31.85 5.55Q35.5 7.1 38.2 9.8Q40.9 12.5 42.45 16.15Q44 19.8 44 24Q44 28.25 42.45 31.9Q40.9 35.55 38.2 38.25Q35.5 40.95 31.85 42.475Q28.2 44 24 44Z"
|
||||||
|
id="path2"
|
||||||
|
style="fill:#ffffff" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.4 KiB |
@@ -176,6 +176,18 @@
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div data-type="toggle" data-sync="showCategoryGuidelines">
|
||||||
|
<div class="switch-container">
|
||||||
|
<label class="switch">
|
||||||
|
<input id="showCategoryGuidelines" type="checkbox" checked>
|
||||||
|
<span class="slider round"></span>
|
||||||
|
</label>
|
||||||
|
<label class="switch-label" for="showCategoryGuidelines">
|
||||||
|
__MSG_showCategoryGuidelines__
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div data-type="toggle" data-toggle-type="reverse" data-sync="hideVideoPlayerControls">
|
<div data-type="toggle" data-toggle-type="reverse" data-sync="hideVideoPlayerControls">
|
||||||
<div class="switch-container">
|
<div class="switch-container">
|
||||||
<label class="switch">
|
<label class="switch">
|
||||||
@@ -368,6 +380,12 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div data-type="button-press" data-sync="resetToDefault" data-confirm-message="confirmResetToDefault">
|
||||||
|
<div class="option-button trigger-button">
|
||||||
|
__MSG_resetToDefault__
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="advanced" class="option-group hidden">
|
<div id="advanced" class="option-group hidden">
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ export interface NoticeProps {
|
|||||||
|
|
||||||
smaller?: boolean,
|
smaller?: boolean,
|
||||||
limitWidth?: boolean,
|
limitWidth?: boolean,
|
||||||
|
extraClass?: string,
|
||||||
|
|
||||||
// Callback for when this is closed
|
// Callback for when this is closed
|
||||||
closeListener: () => void,
|
closeListener: () => void,
|
||||||
@@ -35,8 +36,6 @@ export interface NoticeProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface NoticeState {
|
export interface NoticeState {
|
||||||
noticeTitle: string,
|
|
||||||
|
|
||||||
maxCountdownTime: () => number,
|
maxCountdownTime: () => number,
|
||||||
|
|
||||||
countdownTime: number,
|
countdownTime: number,
|
||||||
@@ -54,9 +53,13 @@ class NoticeComponent extends React.Component<NoticeProps, NoticeState> {
|
|||||||
|
|
||||||
amountOfPreviousNotices: number;
|
amountOfPreviousNotices: number;
|
||||||
|
|
||||||
|
parentRef: React.RefObject<HTMLDivElement>;
|
||||||
|
|
||||||
constructor(props: NoticeProps) {
|
constructor(props: NoticeProps) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
|
this.parentRef = React.createRef();
|
||||||
|
|
||||||
const maxCountdownTime = () => {
|
const maxCountdownTime = () => {
|
||||||
if (this.props.maxCountdownTime) return this.props.maxCountdownTime();
|
if (this.props.maxCountdownTime) return this.props.maxCountdownTime();
|
||||||
else return Config.config.skipNoticeDuration;
|
else return Config.config.skipNoticeDuration;
|
||||||
@@ -71,8 +74,6 @@ class NoticeComponent extends React.Component<NoticeProps, NoticeState> {
|
|||||||
|
|
||||||
// Setup state
|
// Setup state
|
||||||
this.state = {
|
this.state = {
|
||||||
noticeTitle: props.noticeTitle,
|
|
||||||
|
|
||||||
maxCountdownTime,
|
maxCountdownTime,
|
||||||
|
|
||||||
//the countdown until this notice closes
|
//the countdown until this notice closes
|
||||||
@@ -97,9 +98,11 @@ class NoticeComponent extends React.Component<NoticeProps, NoticeState> {
|
|||||||
return (
|
return (
|
||||||
<div id={"sponsorSkipNotice" + this.idSuffix}
|
<div id={"sponsorSkipNotice" + this.idSuffix}
|
||||||
className={"sponsorSkipObject sponsorSkipNoticeParent"
|
className={"sponsorSkipObject sponsorSkipNoticeParent"
|
||||||
+ (this.props.showInSecondSlot ? " secondSkipNotice" : "")}
|
+ (this.props.showInSecondSlot ? " secondSkipNotice" : "")
|
||||||
|
+ (this.props.extraClass ? ` ${this.props.extraClass}` : "")}
|
||||||
onMouseEnter={(e) => this.onMouseEnter(e) }
|
onMouseEnter={(e) => this.onMouseEnter(e) }
|
||||||
onMouseLeave={() => this.timerMouseLeave()}
|
onMouseLeave={() => this.timerMouseLeave()}
|
||||||
|
ref={this.parentRef}
|
||||||
style={noticeStyle} >
|
style={noticeStyle} >
|
||||||
<div className={"sponsorSkipNoticeTableContainer"
|
<div className={"sponsorSkipNoticeTableContainer"
|
||||||
+ (this.props.fadeIn ? " sponsorSkipNoticeFadeIn" : "")
|
+ (this.props.fadeIn ? " sponsorSkipNoticeFadeIn" : "")
|
||||||
@@ -123,7 +126,7 @@ class NoticeComponent extends React.Component<NoticeProps, NoticeState> {
|
|||||||
style={{float: "left"}}
|
style={{float: "left"}}
|
||||||
className="sponsorSkipMessage sponsorSkipObject">
|
className="sponsorSkipMessage sponsorSkipObject">
|
||||||
|
|
||||||
{this.state.noticeTitle}
|
{this.props.noticeTitle}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
{this.props.firstColumn}
|
{this.props.firstColumn}
|
||||||
@@ -344,12 +347,6 @@ class NoticeComponent extends React.Component<NoticeProps, NoticeState> {
|
|||||||
if (!silent) this.props.closeListener();
|
if (!silent) this.props.closeListener();
|
||||||
}
|
}
|
||||||
|
|
||||||
changeNoticeTitle(title: string): void {
|
|
||||||
this.setState({
|
|
||||||
noticeTitle: title
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
addNoticeInfoMessage(message: string, message2 = ""): void {
|
addNoticeInfoMessage(message: string, message2 = ""): void {
|
||||||
//TODO: Replace
|
//TODO: Replace
|
||||||
|
|
||||||
@@ -384,6 +381,10 @@ class NoticeComponent extends React.Component<NoticeProps, NoticeState> {
|
|||||||
document.querySelector("#sponsorSkipNotice" + this.idSuffix + " > tbody").insertBefore(thanksForVotingText2, document.getElementById("sponsorSkipNoticeSpacer" + this.idSuffix));
|
document.querySelector("#sponsorSkipNotice" + this.idSuffix + " > tbody").insertBefore(thanksForVotingText2, document.getElementById("sponsorSkipNoticeSpacer" + this.idSuffix));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getElement(): React.RefObject<HTMLDivElement> {
|
||||||
|
return this.parentRef;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default NoticeComponent;
|
export default NoticeComponent;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
|
|
||||||
export interface NoticeTextSelectionProps {
|
export interface NoticeTextSelectionProps {
|
||||||
|
icon?: string,
|
||||||
text: string,
|
text: string,
|
||||||
idSuffix: string,
|
idSuffix: string,
|
||||||
onClick?: (event: React.MouseEvent) => unknown
|
onClick?: (event: React.MouseEvent) => unknown
|
||||||
@@ -24,12 +25,21 @@ class NoticeTextSelectionComponent extends React.Component<NoticeTextSelectionPr
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<p id={"sponsorTimesInfoMessage" + this.props.idSuffix}
|
<tr id={"sponsorTimesInfoMessage" + this.props.idSuffix}
|
||||||
onClick={this.props.onClick}
|
onClick={this.props.onClick}
|
||||||
style={style}
|
style={style}
|
||||||
className="sponsorTimesInfoMessage">
|
className="sponsorTimesInfoMessage">
|
||||||
|
|
||||||
|
<td>
|
||||||
|
{this.props.icon ?
|
||||||
|
<img src={chrome.runtime.getURL(this.props.icon)} className="sponsorTimesInfoIcon" />
|
||||||
|
: null}
|
||||||
|
|
||||||
|
<span>
|
||||||
{this.props.text}
|
{this.props.text}
|
||||||
</p>
|
</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import * as CompileConfig from "../../config.json";
|
import * as CompileConfig from "../../config.json";
|
||||||
import Config from "../config"
|
import Config from "../config"
|
||||||
import { Category, ContentContainer, SponsorHideType, SponsorTime, NoticeVisbilityMode, ActionType, SponsorSourceType, SegmentUUID } from "../types";
|
import { Category, ContentContainer, SponsorTime, NoticeVisbilityMode, ActionType, SponsorSourceType, SegmentUUID } from "../types";
|
||||||
import NoticeComponent from "./NoticeComponent";
|
import NoticeComponent from "./NoticeComponent";
|
||||||
import NoticeTextSelectionComponent from "./NoticeTextSectionComponent";
|
import NoticeTextSelectionComponent from "./NoticeTextSectionComponent";
|
||||||
import Utils from "../utils";
|
import Utils from "../utils";
|
||||||
@@ -617,11 +617,6 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
|
|||||||
countdownTime: Config.config.skipNoticeDuration
|
countdownTime: Config.config.skipNoticeDuration
|
||||||
};
|
};
|
||||||
|
|
||||||
// See if the title should be changed
|
|
||||||
if (!this.autoSkip) {
|
|
||||||
newState.noticeTitle = chrome.i18n.getMessage("noticeTitle");
|
|
||||||
}
|
|
||||||
|
|
||||||
//reset countdown
|
//reset countdown
|
||||||
this.setState(newState, () => {
|
this.setState(newState, () => {
|
||||||
this.noticeRef.current.resetCountdown();
|
this.noticeRef.current.resetCountdown();
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ export interface SponsorTimeEditProps {
|
|||||||
|
|
||||||
submissionNotice: SubmissionNoticeComponent;
|
submissionNotice: SubmissionNoticeComponent;
|
||||||
categoryList?: Category[];
|
categoryList?: Category[];
|
||||||
|
categoryChangeListener?: (index: number, category: Category) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SponsorTimeEditState {
|
export interface SponsorTimeEditState {
|
||||||
@@ -365,9 +366,10 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
|
|||||||
}
|
}
|
||||||
|
|
||||||
categorySelectionChange(event: React.ChangeEvent<HTMLSelectElement>): void {
|
categorySelectionChange(event: React.ChangeEvent<HTMLSelectElement>): void {
|
||||||
|
const chosenCategory = event.target.value as Category;
|
||||||
|
|
||||||
// See if show more categories was pressed
|
// See if show more categories was pressed
|
||||||
if (event.target.value !== DEFAULT_CATEGORY && !Config.config.categorySelections.some((category) => category.name === event.target.value)) {
|
if (event.target.value !== DEFAULT_CATEGORY && !Config.config.categorySelections.some((category) => category.name === event.target.value)) {
|
||||||
const chosenCategory = event.target.value;
|
|
||||||
event.target.value = DEFAULT_CATEGORY;
|
event.target.value = DEFAULT_CATEGORY;
|
||||||
|
|
||||||
// Alert that they have to enable this category first
|
// Alert that they have to enable this category first
|
||||||
@@ -381,8 +383,12 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
|
|||||||
}
|
}
|
||||||
|
|
||||||
const sponsorTime = this.props.contentContainer().sponsorTimesSubmitting[this.props.index];
|
const sponsorTime = this.props.contentContainer().sponsorTimesSubmitting[this.props.index];
|
||||||
this.handleReplacingLostTimes(event.target.value as Category, sponsorTime.actionType, sponsorTime);
|
this.handleReplacingLostTimes(chosenCategory, sponsorTime.actionType, sponsorTime);
|
||||||
this.saveEditTimes();
|
this.saveEditTimes();
|
||||||
|
|
||||||
|
if (this.props.categoryChangeListener) {
|
||||||
|
this.props.categoryChangeListener(this.props.index, chosenCategory);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
actionTypeSelectionChange(event: React.ChangeEvent<HTMLSelectElement>): void {
|
actionTypeSelectionChange(event: React.ChangeEvent<HTMLSelectElement>): void {
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import Config from "../config"
|
import Config from "../config"
|
||||||
import { ContentContainer } from "../types";
|
import GenericNotice from "../render/GenericNotice";
|
||||||
|
import { Category, ContentContainer } from "../types";
|
||||||
|
import * as CompileConfig from "../../config.json";
|
||||||
|
|
||||||
import NoticeComponent from "./NoticeComponent";
|
import NoticeComponent from "./NoticeComponent";
|
||||||
import NoticeTextSelectionComponent from "./NoticeTextSectionComponent";
|
import NoticeTextSelectionComponent from "./NoticeTextSectionComponent";
|
||||||
import SponsorTimeEditComponent from "./SponsorTimeEditComponent";
|
import SponsorTimeEditComponent from "./SponsorTimeEditComponent";
|
||||||
|
import { getGuidelineInfo } from "../utils/constants";
|
||||||
|
|
||||||
export interface SubmissionNoticeProps {
|
export interface SubmissionNoticeProps {
|
||||||
// Contains functions and variables from the content script needed by the skip notice
|
// Contains functions and variables from the content script needed by the skip notice
|
||||||
@@ -32,6 +35,8 @@ class SubmissionNoticeComponent extends React.Component<SubmissionNoticeProps, S
|
|||||||
|
|
||||||
videoObserver: MutationObserver;
|
videoObserver: MutationObserver;
|
||||||
|
|
||||||
|
guidelinesReminder: GenericNotice;
|
||||||
|
|
||||||
constructor(props: SubmissionNoticeProps) {
|
constructor(props: SubmissionNoticeProps) {
|
||||||
super(props);
|
super(props);
|
||||||
this.noticeRef = React.createRef();
|
this.noticeRef = React.createRef();
|
||||||
@@ -128,6 +133,7 @@ class SubmissionNoticeComponent extends React.Component<SubmissionNoticeProps, S
|
|||||||
index={i}
|
index={i}
|
||||||
contentContainer={this.props.contentContainer}
|
contentContainer={this.props.contentContainer}
|
||||||
submissionNotice={this}
|
submissionNotice={this}
|
||||||
|
categoryChangeListener={this.categoryChangeListener.bind(this)}
|
||||||
ref={timeRef}>
|
ref={timeRef}>
|
||||||
</SponsorTimeEditComponent>
|
</SponsorTimeEditComponent>
|
||||||
);
|
);
|
||||||
@@ -154,6 +160,7 @@ class SubmissionNoticeComponent extends React.Component<SubmissionNoticeProps, S
|
|||||||
}
|
}
|
||||||
|
|
||||||
cancel(): void {
|
cancel(): void {
|
||||||
|
this.guidelinesReminder?.close();
|
||||||
this.noticeRef.current.close(true);
|
this.noticeRef.current.close(true);
|
||||||
|
|
||||||
this.contentContainer().resetSponsorSubmissionNotice();
|
this.contentContainer().resetSponsorSubmissionNotice();
|
||||||
@@ -190,6 +197,45 @@ class SubmissionNoticeComponent extends React.Component<SubmissionNoticeProps, S
|
|||||||
|
|
||||||
this.cancel();
|
this.cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
categoryChangeListener(index: number, category: Category): void {
|
||||||
|
const dialogWidth = this.noticeRef?.current?.getElement()?.current?.offsetWidth;
|
||||||
|
if (category !== "chooseACategory" && Config.config.showCategoryGuidelines
|
||||||
|
&& this.contentContainer().v.offsetWidth > dialogWidth * 2) {
|
||||||
|
const options = {
|
||||||
|
title: chrome.i18n.getMessage(`category_${category}`),
|
||||||
|
textBoxes: getGuidelineInfo(category),
|
||||||
|
buttons: [{
|
||||||
|
name: chrome.i18n.getMessage("FullDetails"),
|
||||||
|
listener: () => window.open(CompileConfig.wikiLinks[category])
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: chrome.i18n.getMessage("Hide"),
|
||||||
|
listener: () => {
|
||||||
|
Config.config.showCategoryGuidelines = false;
|
||||||
|
this.guidelinesReminder?.close();
|
||||||
|
this.guidelinesReminder = null;
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
timed: false,
|
||||||
|
style: {
|
||||||
|
right: `${dialogWidth + 10}px`,
|
||||||
|
},
|
||||||
|
extraClass: "sb-guidelines-notice"
|
||||||
|
};
|
||||||
|
|
||||||
|
if (options.textBoxes) {
|
||||||
|
if (this.guidelinesReminder) {
|
||||||
|
this.guidelinesReminder.update(options);
|
||||||
|
} else {
|
||||||
|
this.guidelinesReminder = new GenericNotice(null, "GuidelinesReminder", options);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.guidelinesReminder?.close();
|
||||||
|
this.guidelinesReminder = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default SubmissionNoticeComponent;
|
export default SubmissionNoticeComponent;
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import Config from "../config";
|
|
||||||
import { Category, SegmentUUID, SponsorTime } from "../types";
|
|
||||||
|
|
||||||
export interface TooltipProps {
|
export interface TooltipProps {
|
||||||
text: string;
|
text: string;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import * as CompileConfig from "../config.json";
|
import * as CompileConfig from "../config.json";
|
||||||
import * as invidiousList from "../ci/invidiouslist.json";
|
import * as invidiousList from "../ci/invidiouslist.json";
|
||||||
import { Category, CategorySelection, CategorySkipOption, NoticeVisbilityMode, PreviewBarOption, SponsorTime, StorageChangesObject, UnEncodedSegmentTimes as UnencodedSegmentTimes, Keybind, HashedValue, VideoID, SponsorHideType } from "./types";
|
import { Category, CategorySelection, CategorySkipOption, NoticeVisbilityMode, PreviewBarOption, SponsorTime, StorageChangesObject, Keybind, HashedValue, VideoID, SponsorHideType } from "./types";
|
||||||
import { keybindEquals } from "./utils/configUtils";
|
import { keybindEquals } from "./utils/configUtils";
|
||||||
|
|
||||||
interface SBConfig {
|
interface SBConfig {
|
||||||
@@ -55,6 +55,7 @@ interface SBConfig {
|
|||||||
scrollToEditTimeUpdate: boolean,
|
scrollToEditTimeUpdate: boolean,
|
||||||
categoryPillUpdate: boolean,
|
categoryPillUpdate: boolean,
|
||||||
darkMode: boolean,
|
darkMode: boolean,
|
||||||
|
showCategoryGuidelines: boolean,
|
||||||
|
|
||||||
// Used to cache calculated text color info
|
// Used to cache calculated text color info
|
||||||
categoryPillColors: {
|
categoryPillColors: {
|
||||||
@@ -113,6 +114,7 @@ export interface SBObject {
|
|||||||
local: SBStorage;
|
local: SBStorage;
|
||||||
forceSyncUpdate(prop: string): void;
|
forceSyncUpdate(prop: string): void;
|
||||||
forceLocalUpdate(prop: string): void;
|
forceLocalUpdate(prop: string): void;
|
||||||
|
resetToDefault(): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Config: SBObject = {
|
const Config: SBObject = {
|
||||||
@@ -166,6 +168,7 @@ const Config: SBObject = {
|
|||||||
scrollToEditTimeUpdate: false, // false means the tooltip will be shown
|
scrollToEditTimeUpdate: false, // false means the tooltip will be shown
|
||||||
categoryPillUpdate: false,
|
categoryPillUpdate: false,
|
||||||
darkMode: true,
|
darkMode: true,
|
||||||
|
showCategoryGuidelines: true,
|
||||||
|
|
||||||
categoryPillColors: {},
|
categoryPillColors: {},
|
||||||
|
|
||||||
@@ -289,7 +292,8 @@ const Config: SBObject = {
|
|||||||
config: null,
|
config: null,
|
||||||
local: null,
|
local: null,
|
||||||
forceSyncUpdate,
|
forceSyncUpdate,
|
||||||
forceLocalUpdate
|
forceLocalUpdate,
|
||||||
|
resetToDefault
|
||||||
};
|
};
|
||||||
|
|
||||||
// Function setup
|
// Function setup
|
||||||
@@ -522,6 +526,16 @@ function addDefaults() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function resetToDefault() {
|
||||||
|
chrome.storage.sync.set({
|
||||||
|
...Config.syncDefaults,
|
||||||
|
userID: Config.config.userID,
|
||||||
|
minutesSaved: Config.config.minutesSaved,
|
||||||
|
skipCount: Config.config.skipCount,
|
||||||
|
sponsorTimesContributed: Config.config.sponsorTimesContributed
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Sync config
|
// Sync config
|
||||||
setupConfig();
|
setupConfig();
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import { isSafari, keybindEquals } from "./utils/configUtils";
|
|||||||
import { CategoryPill } from "./render/CategoryPill";
|
import { CategoryPill } from "./render/CategoryPill";
|
||||||
import { AnimationUtils } from "./utils/animationUtils";
|
import { AnimationUtils } from "./utils/animationUtils";
|
||||||
import { GenericUtils } from "./utils/genericUtils";
|
import { GenericUtils } from "./utils/genericUtils";
|
||||||
|
import { logDebug } from "./utils/logger";
|
||||||
|
|
||||||
// Hack to get the CSS loaded on permission-based sites (Invidious)
|
// Hack to get the CSS loaded on permission-based sites (Invidious)
|
||||||
utils.wait(() => Config.config !== null, 5000, 10).then(addCSS);
|
utils.wait(() => Config.config !== null, 5000, 10).then(addCSS);
|
||||||
@@ -275,6 +276,7 @@ function resetValues() {
|
|||||||
switchingVideos = false;
|
switchingVideos = false;
|
||||||
} else {
|
} else {
|
||||||
switchingVideos = true;
|
switchingVideos = true;
|
||||||
|
logDebug("Setting switching videos to true (reset data)");
|
||||||
}
|
}
|
||||||
|
|
||||||
firstEvent = true;
|
firstEvent = true;
|
||||||
@@ -319,9 +321,6 @@ async function videoIDChange(id) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get new video info
|
|
||||||
// getVideoInfo(); // Seems to have been replaced
|
|
||||||
|
|
||||||
// Update whitelist data when the video data is loaded
|
// Update whitelist data when the video data is loaded
|
||||||
whitelistCheck();
|
whitelistCheck();
|
||||||
|
|
||||||
@@ -448,6 +447,8 @@ function videoOnReadyListener(): void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function cancelSponsorSchedule(): void {
|
function cancelSponsorSchedule(): void {
|
||||||
|
logDebug("Pausing skipping");
|
||||||
|
|
||||||
if (currentSkipSchedule !== null) {
|
if (currentSkipSchedule !== null) {
|
||||||
clearTimeout(currentSkipSchedule);
|
clearTimeout(currentSkipSchedule);
|
||||||
currentSkipSchedule = null;
|
currentSkipSchedule = null;
|
||||||
@@ -470,21 +471,16 @@ function startSponsorSchedule(includeIntersectingSegments = false, currentTime?:
|
|||||||
// Reset lastCheckVideoTime
|
// Reset lastCheckVideoTime
|
||||||
lastCheckVideoTime = -1;
|
lastCheckVideoTime = -1;
|
||||||
lastCheckTime = 0;
|
lastCheckTime = 0;
|
||||||
console.warn("[SB] Ad playing, pausing skipping");
|
logDebug("[SB] Ad playing, pausing skipping");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logDebug(`Considering to start skipping: ${!video}, ${video?.paused}`);
|
||||||
|
|
||||||
if (!video || video.paused) return;
|
if (!video || video.paused) return;
|
||||||
if (currentTime === undefined || currentTime === null) {
|
if (currentTime === undefined || currentTime === null) {
|
||||||
const virtualTime = lastTimeFromWaitingEvent ?? (lastKnownVideoTime.videoTime ?
|
currentTime = getVirtualTime();
|
||||||
(performance.now() - lastKnownVideoTime.preciseTime) / 1000 + lastKnownVideoTime.videoTime : null);
|
|
||||||
if ((lastTimeFromWaitingEvent || !utils.isFirefox())
|
|
||||||
&& !isSafari() && virtualTime && Math.abs(virtualTime - video.currentTime) < 0.6){
|
|
||||||
currentTime = virtualTime;
|
|
||||||
} else {
|
|
||||||
currentTime = video.currentTime;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
lastTimeFromWaitingEvent = null;
|
lastTimeFromWaitingEvent = null;
|
||||||
|
|
||||||
@@ -506,6 +502,7 @@ function startSponsorSchedule(includeIntersectingSegments = false, currentTime?:
|
|||||||
|
|
||||||
const skipInfo = getNextSkipIndex(currentTime, includeIntersectingSegments, includeNonIntersectingSegments);
|
const skipInfo = getNextSkipIndex(currentTime, includeIntersectingSegments, includeNonIntersectingSegments);
|
||||||
|
|
||||||
|
logDebug(`Ready to start skipping: ${skipInfo.index} at ${currentTime}`);
|
||||||
if (skipInfo.index === -1) return;
|
if (skipInfo.index === -1) return;
|
||||||
|
|
||||||
const currentSkip = skipInfo.array[skipInfo.index];
|
const currentSkip = skipInfo.array[skipInfo.index];
|
||||||
@@ -526,6 +523,8 @@ function startSponsorSchedule(includeIntersectingSegments = false, currentTime?:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logDebug(`Next step in starting skipping: ${!shouldSkip(currentSkip)}, ${!sponsorTimesSubmitting?.some((segment) => segment.segment === currentSkip.segment)}`);
|
||||||
|
|
||||||
// Don't skip if this category should not be skipped
|
// Don't skip if this category should not be skipped
|
||||||
if (!shouldSkip(currentSkip) && !sponsorTimesSubmitting?.some((segment) => segment.segment === currentSkip.segment)) return;
|
if (!shouldSkip(currentSkip) && !sponsorTimesSubmitting?.some((segment) => segment.segment === currentSkip.segment)) return;
|
||||||
|
|
||||||
@@ -535,7 +534,7 @@ function startSponsorSchedule(includeIntersectingSegments = false, currentTime?:
|
|||||||
let forcedIncludeNonIntersectingSegments = true;
|
let forcedIncludeNonIntersectingSegments = true;
|
||||||
|
|
||||||
if (incorrectVideoCheck(videoID, currentSkip)) return;
|
if (incorrectVideoCheck(videoID, currentSkip)) return;
|
||||||
forceVideoTime ||= video.currentTime;
|
forceVideoTime ||= Math.max(video.currentTime, getVirtualTime());
|
||||||
|
|
||||||
if (forceVideoTime >= skipTime[0] && forceVideoTime < skipTime[1]) {
|
if (forceVideoTime >= skipTime[0] && forceVideoTime < skipTime[1]) {
|
||||||
skipToTime({
|
skipToTime({
|
||||||
@@ -566,6 +565,8 @@ function startSponsorSchedule(includeIntersectingSegments = false, currentTime?:
|
|||||||
// Use interval instead of timeout near the end to combat imprecise video time
|
// Use interval instead of timeout near the end to combat imprecise video time
|
||||||
const startIntervalTime = performance.now();
|
const startIntervalTime = performance.now();
|
||||||
const startVideoTime = Math.max(currentTime, video.currentTime);
|
const startVideoTime = Math.max(currentTime, video.currentTime);
|
||||||
|
logDebug(`Starting setInterval skipping ${video.currentTime} to skip at ${skipTime[0]}`);
|
||||||
|
|
||||||
currentSkipInterval = setInterval(() => {
|
currentSkipInterval = setInterval(() => {
|
||||||
const intervalDuration = performance.now() - startIntervalTime;
|
const intervalDuration = performance.now() - startIntervalTime;
|
||||||
if (intervalDuration >= delayTime || video.currentTime >= skipTime[0]) {
|
if (intervalDuration >= delayTime || video.currentTime >= skipTime[0]) {
|
||||||
@@ -580,12 +581,26 @@ function startSponsorSchedule(includeIntersectingSegments = false, currentTime?:
|
|||||||
}
|
}
|
||||||
}, 1);
|
}, 1);
|
||||||
} else {
|
} else {
|
||||||
|
logDebug(`Starting timeout to skip ${video.currentTime} to skip at ${skipTime[0]}`);
|
||||||
|
|
||||||
// Schedule for right before to be more precise than normal timeout
|
// Schedule for right before to be more precise than normal timeout
|
||||||
currentSkipSchedule = setTimeout(skippingFunction, Math.max(0, delayTime - 100));
|
currentSkipSchedule = setTimeout(skippingFunction, Math.max(0, delayTime - 150));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getVirtualTime(): number {
|
||||||
|
const virtualTime = lastTimeFromWaitingEvent ?? (lastKnownVideoTime.videoTime ?
|
||||||
|
(performance.now() - lastKnownVideoTime.preciseTime) / 1000 + lastKnownVideoTime.videoTime : null);
|
||||||
|
|
||||||
|
if ((lastTimeFromWaitingEvent || !utils.isFirefox())
|
||||||
|
&& !isSafari() && virtualTime && Math.abs(virtualTime - video.currentTime) < 0.6) {
|
||||||
|
return virtualTime;
|
||||||
|
} else {
|
||||||
|
return video.currentTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function inMuteSegment(currentTime: number): boolean {
|
function inMuteSegment(currentTime: number): boolean {
|
||||||
const checkFunction = (segment) => segment.actionType === ActionType.Mute && segment.segment[0] <= currentTime && segment.segment[1] > currentTime;
|
const checkFunction = (segment) => segment.actionType === ActionType.Mute && segment.segment[0] <= currentTime && segment.segment[1] > currentTime;
|
||||||
return sponsorTimes?.some(checkFunction) || sponsorTimesSubmitting.some(checkFunction);
|
return sponsorTimes?.some(checkFunction) || sponsorTimesSubmitting.some(checkFunction);
|
||||||
@@ -656,6 +671,8 @@ function setupVideoListeners() {
|
|||||||
if (!Config.config.disableSkipping) {
|
if (!Config.config.disableSkipping) {
|
||||||
switchingVideos = false;
|
switchingVideos = false;
|
||||||
|
|
||||||
|
let startedWaiting = false;
|
||||||
|
|
||||||
video.addEventListener('play', () => {
|
video.addEventListener('play', () => {
|
||||||
// If it is not the first event, then the only way to get to 0 is if there is a seek event
|
// If it is not the first event, then the only way to get to 0 is if there is a seek event
|
||||||
// This check makes sure that changing the video resolution doesn't cause the extension to think it
|
// This check makes sure that changing the video resolution doesn't cause the extension to think it
|
||||||
@@ -667,6 +684,8 @@ function setupVideoListeners() {
|
|||||||
|
|
||||||
if (switchingVideos) {
|
if (switchingVideos) {
|
||||||
switchingVideos = false;
|
switchingVideos = false;
|
||||||
|
logDebug("Setting switching videos to false");
|
||||||
|
|
||||||
// If already segments loaded before video, retry to skip starting segments
|
// If already segments loaded before video, retry to skip starting segments
|
||||||
if (sponsorTimes) startSkipScheduleCheckingForStartSponsors();
|
if (sponsorTimes) startSkipScheduleCheckingForStartSponsors();
|
||||||
}
|
}
|
||||||
@@ -687,6 +706,12 @@ function setupVideoListeners() {
|
|||||||
video.addEventListener('playing', () => {
|
video.addEventListener('playing', () => {
|
||||||
updateVirtualTime();
|
updateVirtualTime();
|
||||||
|
|
||||||
|
if (startedWaiting) {
|
||||||
|
startedWaiting = false;
|
||||||
|
logDebug(`[SB] Playing event after buffering: ${Math.abs(lastCheckVideoTime - video.currentTime) > 0.3
|
||||||
|
|| (lastCheckVideoTime !== video.currentTime && Date.now() - lastCheckTime > 2000)}`);
|
||||||
|
}
|
||||||
|
|
||||||
// Make sure it doesn't get double called with the play event
|
// Make sure it doesn't get double called with the play event
|
||||||
if (Math.abs(lastCheckVideoTime - video.currentTime) > 0.3
|
if (Math.abs(lastCheckVideoTime - video.currentTime) > 0.3
|
||||||
|| (lastCheckVideoTime !== video.currentTime && Date.now() - lastCheckTime > 2000)) {
|
|| (lastCheckVideoTime !== video.currentTime && Date.now() - lastCheckTime > 2000)) {
|
||||||
@@ -726,9 +751,10 @@ function setupVideoListeners() {
|
|||||||
};
|
};
|
||||||
video.addEventListener('pause', () => paused());
|
video.addEventListener('pause', () => paused());
|
||||||
video.addEventListener('waiting', () => {
|
video.addEventListener('waiting', () => {
|
||||||
paused();
|
logDebug("[SB] Not skipping due to buffering");
|
||||||
|
startedWaiting = true;
|
||||||
|
|
||||||
console.warn("[SB] Not skipping due to buffering");
|
paused();
|
||||||
});
|
});
|
||||||
|
|
||||||
startSponsorSchedule();
|
startSponsorSchedule();
|
||||||
@@ -918,12 +944,10 @@ function startSkipScheduleCheckingForStartSponsors() {
|
|||||||
// See if there are any starting sponsors
|
// See if there are any starting sponsors
|
||||||
let startingSegmentTime = getStartTimeFromUrl(document.URL) || -1;
|
let startingSegmentTime = getStartTimeFromUrl(document.URL) || -1;
|
||||||
let found = false;
|
let found = false;
|
||||||
let startingSegment: SponsorTime = null;
|
|
||||||
for (const time of sponsorTimes) {
|
for (const time of sponsorTimes) {
|
||||||
if (time.segment[0] <= video.currentTime && time.segment[0] > startingSegmentTime && time.segment[1] > video.currentTime
|
if (time.segment[0] <= video.currentTime && time.segment[0] > startingSegmentTime && time.segment[1] > video.currentTime
|
||||||
&& time.actionType !== ActionType.Poi) {
|
&& time.actionType !== ActionType.Poi) {
|
||||||
startingSegmentTime = time.segment[0];
|
startingSegmentTime = time.segment[0];
|
||||||
startingSegment = time;
|
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -933,7 +957,6 @@ function startSkipScheduleCheckingForStartSponsors() {
|
|||||||
if (time.segment[0] <= video.currentTime && time.segment[0] > startingSegmentTime && time.segment[1] > video.currentTime
|
if (time.segment[0] <= video.currentTime && time.segment[0] > startingSegmentTime && time.segment[1] > video.currentTime
|
||||||
&& time.actionType !== ActionType.Poi) {
|
&& time.actionType !== ActionType.Poi) {
|
||||||
startingSegmentTime = time.segment[0];
|
startingSegmentTime = time.segment[0];
|
||||||
startingSegment = time;
|
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -971,26 +994,6 @@ function startSkipScheduleCheckingForStartSponsors() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the video info for the current tab from YouTube
|
|
||||||
*
|
|
||||||
* TODO: Replace
|
|
||||||
*/
|
|
||||||
async function getVideoInfo(): Promise<void> {
|
|
||||||
const result = await utils.asyncRequestToCustomServer("GET", "https://www.youtube.com/get_video_info?video_id=" + sponsorVideoID + "&html5=1&c=TVHTML5&cver=7.20190319");
|
|
||||||
|
|
||||||
if (result.ok) {
|
|
||||||
const decodedData = decodeURIComponent(result.responseText).match(/player_response=([^&]*)/)[1];
|
|
||||||
if (!decodedData) {
|
|
||||||
console.error("[SB] Failed at getting video info from YouTube.");
|
|
||||||
console.error("[SB] Data returned from YouTube: " + result.responseText);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
videoInfo = JSON.parse(decodedData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getYouTubeVideoID(document: Document): string | boolean {
|
function getYouTubeVideoID(document: Document): string | boolean {
|
||||||
const url = document.URL;
|
const url = document.URL;
|
||||||
// clips should never skip, going from clip to full video has no indications.
|
// clips should never skip, going from clip to full video has no indications.
|
||||||
@@ -1125,7 +1128,7 @@ async function whitelistCheck() {
|
|||||||
?? document.querySelector("a.ytp-title-channel-logo") // YouTube Embed
|
?? document.querySelector("a.ytp-title-channel-logo") // YouTube Embed
|
||||||
?? document.querySelector(".channel-profile #channel-name")?.parentElement.parentElement // Invidious
|
?? document.querySelector(".channel-profile #channel-name")?.parentElement.parentElement // Invidious
|
||||||
?? document.querySelector("a.slim-owner-icon-and-title")) // Mobile YouTube
|
?? document.querySelector("a.slim-owner-icon-and-title")) // Mobile YouTube
|
||||||
?.getAttribute("href")?.match(/\/channel\/(UC[a-zA-Z0-9_-]{22})/)[1];
|
?.getAttribute("href")?.match(/\/(?:channel|c|user)\/(UC[a-zA-Z0-9_-]{22}|[a-zA-Z0-9_-]+)/)?.[1];
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await utils.wait(() => !!getChannelID(), 6000, 20);
|
await utils.wait(() => !!getChannelID(), 6000, 20);
|
||||||
@@ -1133,14 +1136,12 @@ async function whitelistCheck() {
|
|||||||
channelIDInfo = {
|
channelIDInfo = {
|
||||||
status: ChannelIDStatus.Found,
|
status: ChannelIDStatus.Found,
|
||||||
id: getChannelID().match(/^\/?([^\s/]+)/)[0]
|
id: getChannelID().match(/^\/?([^\s/]+)/)[0]
|
||||||
}
|
};
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
channelIDInfo = {
|
channelIDInfo = {
|
||||||
status: ChannelIDStatus.Failed,
|
status: ChannelIDStatus.Failed,
|
||||||
id: null
|
id: null
|
||||||
}
|
};
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//see if this is a whitelisted channel
|
//see if this is a whitelisted channel
|
||||||
|
|||||||
@@ -2,10 +2,7 @@ import Config from "../config";
|
|||||||
import { SponsorTime } from "../types";
|
import { SponsorTime } from "../types";
|
||||||
import { getSkippingText } from "../utils/categoryUtils";
|
import { getSkippingText } from "../utils/categoryUtils";
|
||||||
import { keybindToString } from "../utils/configUtils";
|
import { keybindToString } from "../utils/configUtils";
|
||||||
|
|
||||||
import Utils from "../utils";
|
|
||||||
import { AnimationUtils } from "../utils/animationUtils";
|
import { AnimationUtils } from "../utils/animationUtils";
|
||||||
const utils = new Utils();
|
|
||||||
|
|
||||||
export interface SkipButtonControlBarProps {
|
export interface SkipButtonControlBarProps {
|
||||||
skip: (segment: SponsorTime) => void;
|
skip: (segment: SponsorTime) => void;
|
||||||
@@ -172,10 +169,10 @@ export class SkipButtonControlBar {
|
|||||||
const overlay = document.getElementById("player-control-overlay");
|
const overlay = document.getElementById("player-control-overlay");
|
||||||
|
|
||||||
if (overlay && this.enabled) {
|
if (overlay && this.enabled) {
|
||||||
if (overlay?.classList?.contains("pointer-events-off")) {
|
if (overlay?.classList?.contains("fadein")) {
|
||||||
this.hideButton();
|
|
||||||
} else {
|
|
||||||
this.showButton();
|
this.showButton();
|
||||||
|
} else {
|
||||||
|
this.hideButton();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -220,4 +217,3 @@ export class SkipButtonControlBar {
|
|||||||
this.container.style.left = this.left + "px";
|
this.container.style.left = this.left + "px";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -232,12 +232,22 @@ async function init() {
|
|||||||
}
|
}
|
||||||
case "button-press": {
|
case "button-press": {
|
||||||
const actionButton = optionsElements[i].querySelector(".trigger-button");
|
const actionButton = optionsElements[i].querySelector(".trigger-button");
|
||||||
|
const confirmMessage = optionsElements[i].getAttribute("data-confirm-message");
|
||||||
|
|
||||||
|
actionButton.addEventListener("click", () => {
|
||||||
|
if (confirmMessage !== null && !confirm(chrome.i18n.getMessage(confirmMessage))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
switch (optionsElements[i].getAttribute("data-sync")) {
|
switch (optionsElements[i].getAttribute("data-sync")) {
|
||||||
case "copyDebugInformation":
|
case "copyDebugInformation":
|
||||||
actionButton.addEventListener("click", copyDebugOutputToClipboard);
|
copyDebugOutputToClipboard();
|
||||||
|
break;
|
||||||
|
case "resetToDefault":
|
||||||
|
Config.resetToDefault();
|
||||||
|
window.location.reload();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,12 +13,19 @@ export interface ButtonListener {
|
|||||||
listener: (e?: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void
|
listener: (e?: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface TextBox {
|
||||||
|
icon: string,
|
||||||
|
text: string
|
||||||
|
}
|
||||||
|
|
||||||
export interface NoticeOptions {
|
export interface NoticeOptions {
|
||||||
title: string,
|
title: string,
|
||||||
textBoxes?: string[],
|
textBoxes?: TextBox[],
|
||||||
buttons?: ButtonListener[],
|
buttons?: ButtonListener[],
|
||||||
fadeIn?: boolean,
|
fadeIn?: boolean,
|
||||||
timed?: boolean
|
timed?: boolean
|
||||||
|
style?: React.CSSProperties;
|
||||||
|
extraClass?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class GenericNotice {
|
export default class GenericNotice {
|
||||||
@@ -27,9 +34,11 @@ export default class GenericNotice {
|
|||||||
|
|
||||||
noticeElement: HTMLDivElement;
|
noticeElement: HTMLDivElement;
|
||||||
noticeRef: React.MutableRefObject<NoticeComponent>;
|
noticeRef: React.MutableRefObject<NoticeComponent>;
|
||||||
|
idSuffix: string;
|
||||||
|
|
||||||
constructor(contentContainer: ContentContainer, idSuffix: string, options: NoticeOptions) {
|
constructor(contentContainer: ContentContainer, idSuffix: string, options: NoticeOptions) {
|
||||||
this.noticeRef = React.createRef();
|
this.noticeRef = React.createRef();
|
||||||
|
this.idSuffix = idSuffix;
|
||||||
|
|
||||||
this.contentContainer = contentContainer;
|
this.contentContainer = contentContainer;
|
||||||
|
|
||||||
@@ -40,39 +49,47 @@ export default class GenericNotice {
|
|||||||
|
|
||||||
referenceNode.prepend(this.noticeElement);
|
referenceNode.prepend(this.noticeElement);
|
||||||
|
|
||||||
|
this.update(options);
|
||||||
|
}
|
||||||
|
|
||||||
|
update(options: NoticeOptions): void {
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<NoticeComponent
|
<NoticeComponent
|
||||||
noticeTitle={options.title}
|
noticeTitle={options.title}
|
||||||
idSuffix={idSuffix}
|
idSuffix={this.idSuffix}
|
||||||
fadeIn={options.fadeIn ?? true}
|
fadeIn={options.fadeIn ?? true}
|
||||||
timed={options.timed ?? true}
|
timed={options.timed ?? true}
|
||||||
ref={this.noticeRef}
|
ref={this.noticeRef}
|
||||||
|
style={options.style}
|
||||||
|
extraClass={options.extraClass}
|
||||||
closeListener={() => this.close()} >
|
closeListener={() => this.close()} >
|
||||||
|
|
||||||
{this.getMessageBox(idSuffix, options.textBoxes)}
|
{this.getMessageBox(this.idSuffix, options.textBoxes)}
|
||||||
|
|
||||||
<tr id={"sponsorSkipNoticeSpacer" + idSuffix}
|
<tr id={"sponsorSkipNoticeSpacer" + this.idSuffix}
|
||||||
className="sponsorBlockSpacer">
|
className="sponsorBlockSpacer">
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<div className="sponsorSkipNoticeRightSection"
|
<tr className="sponsorSkipNoticeRightSection"
|
||||||
style={{position: "relative"}}>
|
style={{position: "relative"}}>
|
||||||
|
<td>
|
||||||
{this.getButtons(options.buttons)}
|
{this.getButtons(options.buttons)}
|
||||||
</div>
|
</td>
|
||||||
|
</tr>
|
||||||
</NoticeComponent>,
|
</NoticeComponent>,
|
||||||
this.noticeElement
|
this.noticeElement
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
getMessageBox(idSuffix: string, textBoxes: string[]): JSX.Element[] {
|
getMessageBox(idSuffix: string, textBoxes: TextBox[]): JSX.Element[] {
|
||||||
if (textBoxes) {
|
if (textBoxes) {
|
||||||
const result = [];
|
const result = [];
|
||||||
for (let i = 0; i < textBoxes.length; i++) {
|
for (let i = 0; i < textBoxes.length; i++) {
|
||||||
result.push(
|
result.push(
|
||||||
<NoticeTextSelectionComponent idSuffix={idSuffix}
|
<NoticeTextSelectionComponent idSuffix={idSuffix}
|
||||||
key={i}
|
key={i}
|
||||||
text={textBoxes[i]} />
|
icon={textBoxes[i].icon}
|
||||||
|
text={textBoxes[i].text} />
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
141
src/utils/constants.ts
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
import { TextBox } from "../render/GenericNotice";
|
||||||
|
import { Category } from "../types";
|
||||||
|
|
||||||
|
export function getGuidelineInfo(category: Category): TextBox[] {
|
||||||
|
switch (category) {
|
||||||
|
case "sponsor":
|
||||||
|
return [{
|
||||||
|
icon: "icons/money.svg",
|
||||||
|
text: chrome.i18n.getMessage(`category_${category}_guideline1`)
|
||||||
|
}, {
|
||||||
|
icon: "icons/close-smaller.svg",
|
||||||
|
text: chrome.i18n.getMessage(`category_${category}_guideline2`)
|
||||||
|
}, {
|
||||||
|
icon: "icons/segway.png",
|
||||||
|
text: chrome.i18n.getMessage(`generic_guideline1`)
|
||||||
|
}, {
|
||||||
|
icon: "icons/right-arrow.svg",
|
||||||
|
text: chrome.i18n.getMessage(`generic_guideline2`)
|
||||||
|
}];
|
||||||
|
case "selfpromo":
|
||||||
|
return [{
|
||||||
|
icon: "icons/money.svg",
|
||||||
|
text: chrome.i18n.getMessage(`category_${category}_guideline1`)
|
||||||
|
}, {
|
||||||
|
icon: "icons/campaign.svg",
|
||||||
|
text: chrome.i18n.getMessage(`category_${category}_guideline2`)
|
||||||
|
}, {
|
||||||
|
icon: "icons/close-smaller.svg",
|
||||||
|
text: chrome.i18n.getMessage(`category_${category}_guideline3`)
|
||||||
|
}, {
|
||||||
|
icon: "icons/segway.png",
|
||||||
|
text: chrome.i18n.getMessage(`generic_guideline1`)
|
||||||
|
}, {
|
||||||
|
icon: "icons/right-arrow.svg",
|
||||||
|
text: chrome.i18n.getMessage(`generic_guideline2`)
|
||||||
|
}];
|
||||||
|
case "exclusive_access":
|
||||||
|
return [{
|
||||||
|
icon: "icons/money.svg",
|
||||||
|
text: chrome.i18n.getMessage(`category_${category}_guideline1`)
|
||||||
|
}];
|
||||||
|
case "interaction":
|
||||||
|
return [{
|
||||||
|
icon: "icons/lightbulb.svg",
|
||||||
|
text: chrome.i18n.getMessage(`category_${category}_guideline1`)
|
||||||
|
}, {
|
||||||
|
icon: "icons/lightbulb.svg",
|
||||||
|
text: chrome.i18n.getMessage(`category_${category}_guideline2`)
|
||||||
|
}, {
|
||||||
|
icon: "icons/close-smaller.svg",
|
||||||
|
text: chrome.i18n.getMessage(`category_${category}_guideline3`)
|
||||||
|
}, {
|
||||||
|
icon: "icons/segway.png",
|
||||||
|
text: chrome.i18n.getMessage(`generic_guideline1`)
|
||||||
|
}, {
|
||||||
|
icon: "icons/right-arrow.svg",
|
||||||
|
text: chrome.i18n.getMessage(`generic_guideline2`)
|
||||||
|
}];
|
||||||
|
case "intro":
|
||||||
|
return [{
|
||||||
|
icon: "icons/check-smaller.svg",
|
||||||
|
text: chrome.i18n.getMessage(`category_${category}_guideline1`)
|
||||||
|
}, {
|
||||||
|
icon: "icons/close-smaller.svg",
|
||||||
|
text: chrome.i18n.getMessage(`category_${category}_guideline2`)
|
||||||
|
}, {
|
||||||
|
icon: "icons/segway.png",
|
||||||
|
text: chrome.i18n.getMessage(`generic_guideline1`)
|
||||||
|
}, {
|
||||||
|
icon: "icons/right-arrow.svg",
|
||||||
|
text: chrome.i18n.getMessage(`generic_guideline2`)
|
||||||
|
}];
|
||||||
|
case "outro":
|
||||||
|
return [{
|
||||||
|
icon: "icons/close-smaller.svg",
|
||||||
|
text: chrome.i18n.getMessage(`category_${category}_guideline1`)
|
||||||
|
}, {
|
||||||
|
icon: "icons/segway.png",
|
||||||
|
text: chrome.i18n.getMessage(`generic_guideline1`)
|
||||||
|
}, {
|
||||||
|
icon: "icons/right-arrow.svg",
|
||||||
|
text: chrome.i18n.getMessage(`generic_guideline2`)
|
||||||
|
}];
|
||||||
|
case "preview":
|
||||||
|
return [{
|
||||||
|
icon: "icons/check-smaller.svg",
|
||||||
|
text: chrome.i18n.getMessage(`category_${category}_guideline1`)
|
||||||
|
}, {
|
||||||
|
icon: "icons/check-smaller.svg",
|
||||||
|
text: chrome.i18n.getMessage(`category_${category}_guideline2`)
|
||||||
|
}, {
|
||||||
|
icon: "icons/close-smaller.svg",
|
||||||
|
text: chrome.i18n.getMessage(`category_${category}_guideline3`)
|
||||||
|
}, {
|
||||||
|
icon: "icons/segway.png",
|
||||||
|
text: chrome.i18n.getMessage(`generic_guideline1`)
|
||||||
|
}, {
|
||||||
|
icon: "icons/right-arrow.svg",
|
||||||
|
text: chrome.i18n.getMessage(`generic_guideline2`)
|
||||||
|
}];
|
||||||
|
case "filler":
|
||||||
|
return [{
|
||||||
|
icon: "icons/stopwatch.svg",
|
||||||
|
text: chrome.i18n.getMessage(`category_${category}_guideline1`)
|
||||||
|
}, {
|
||||||
|
icon: "icons/stopwatch.svg",
|
||||||
|
text: chrome.i18n.getMessage(`category_${category}_guideline2`)
|
||||||
|
}, {
|
||||||
|
icon: "icons/close-smaller.svg",
|
||||||
|
text: chrome.i18n.getMessage(`category_${category}_guideline3`)
|
||||||
|
}, {
|
||||||
|
icon: "icons/segway.png",
|
||||||
|
text: chrome.i18n.getMessage(`generic_guideline1`)
|
||||||
|
}, {
|
||||||
|
icon: "icons/right-arrow.svg",
|
||||||
|
text: chrome.i18n.getMessage(`generic_guideline2`)
|
||||||
|
}];
|
||||||
|
case "music_offtopic":
|
||||||
|
return [{
|
||||||
|
icon: "icons/music-note.svg",
|
||||||
|
text: chrome.i18n.getMessage(`category_${category}_guideline1`)
|
||||||
|
}, {
|
||||||
|
icon: "icons/music-note.svg",
|
||||||
|
text: chrome.i18n.getMessage(`category_${category}_guideline2`)
|
||||||
|
}, {
|
||||||
|
icon: "icons/right-arrow.svg",
|
||||||
|
text: chrome.i18n.getMessage(`generic_guideline2`)
|
||||||
|
}];
|
||||||
|
case "poi_highlight":
|
||||||
|
return [{
|
||||||
|
icon: "icons/star.svg",
|
||||||
|
text: chrome.i18n.getMessage(`category_${category}_guideline1`)
|
||||||
|
}, {
|
||||||
|
icon: "icons/bolt.svg",
|
||||||
|
text: chrome.i18n.getMessage(`category_${category}_guideline2`)
|
||||||
|
}, {
|
||||||
|
icon: "icons/bolt.svg",
|
||||||
|
text: chrome.i18n.getMessage(`category_${category}_guideline3`)
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
}
|
||||||
12
src/utils/logger.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
window["SBLogs"] = {
|
||||||
|
debug: [],
|
||||||
|
warn: []
|
||||||
|
};
|
||||||
|
|
||||||
|
export function logDebug(message: string) {
|
||||||
|
window["SBLogs"].debug.push(`[${new Date().toISOString()}] ${message}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function logWarn(message: string) {
|
||||||
|
window["SBLogs"].warn.push(`[${new Date().toISOString()}] ${message}`);
|
||||||
|
}
|
||||||
@@ -1,12 +1,15 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
const webpack = require("webpack");
|
import webpack from "webpack"
|
||||||
const path = require('path');
|
import path from "path"
|
||||||
const CopyPlugin = require('copy-webpack-plugin');
|
import { fileURLToPath } from "url"
|
||||||
const BuildManifest = require('./webpack.manifest');
|
import CopyPlugin from "copy-webpack-plugin"
|
||||||
const srcDir = '../src/';
|
import BuildManifest from "./webpack.manifest.cjs";
|
||||||
const fs = require("fs");
|
const srcDir = "../src/";
|
||||||
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
|
import fs from "fs";
|
||||||
|
import ForkTsCheckerWebpackPlugin from "fork-ts-checker-webpack-plugin";
|
||||||
|
|
||||||
|
const __filename = fileURLToPath(import.meta.url)
|
||||||
|
const __dirname = path.dirname(__filename)
|
||||||
|
|
||||||
const edgeLanguages = [
|
const edgeLanguages = [
|
||||||
"de",
|
"de",
|
||||||
@@ -24,7 +27,7 @@ const edgeLanguages = [
|
|||||||
"zh_CN"
|
"zh_CN"
|
||||||
]
|
]
|
||||||
|
|
||||||
module.exports = env => ({
|
export default env => ({
|
||||||
entry: {
|
entry: {
|
||||||
popup: path.join(__dirname, srcDir + 'popup.ts'),
|
popup: path.join(__dirname, srcDir + 'popup.ts'),
|
||||||
background: path.join(__dirname, srcDir + 'background.ts'),
|
background: path.join(__dirname, srcDir + 'background.ts'),
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
import { merge } from "webpack-merge";
|
||||||
const merge = require('webpack-merge');
|
import common from './webpack.common.js';
|
||||||
const common = require('./webpack.common.js');
|
|
||||||
|
|
||||||
module.exports = env => merge(common(env), {
|
export default env => merge(common(env), {
|
||||||
devtool: 'inline-source-map',
|
devtool: 'inline-source-map',
|
||||||
mode: 'development'
|
mode: 'development'
|
||||||
});
|
});
|
||||||
@@ -1,8 +1,7 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
import { merge } from "webpack-merge";
|
||||||
const merge = require('webpack-merge');
|
import common from './webpack.common.js';
|
||||||
const common = require('./webpack.common.js');
|
|
||||||
|
|
||||||
module.exports = env => {
|
export default env => {
|
||||||
let mode = "production";
|
let mode = "production";
|
||||||
env.mode = mode;
|
env.mode = mode;
|
||||||
|
|
||||||
|
|||||||