Compare commits
20 Commits
4.4.3
...
guidelines
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
97aea1c268 | ||
|
|
b70f50e1a0 | ||
|
|
4880227320 | ||
|
|
dfa21068f4 | ||
|
|
fd75a33e50 | ||
|
|
1409c563e2 | ||
|
|
588c42d579 | ||
|
|
d7ff6aa6a2 | ||
|
|
44266e508b | ||
|
|
c0f8f5e1d0 | ||
|
|
e948e1e569 | ||
|
|
5289e62d43 | ||
|
|
eda7aac5ef | ||
|
|
d9f4ab0d04 | ||
|
|
2665327729 | ||
|
|
4738c1897f | ||
|
|
cfbb194a61 | ||
|
|
9ad21e8ea1 | ||
|
|
941fc2985d | ||
|
|
463ce258bf |
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.3",
|
"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",
|
||||||
@@ -68,8 +79,31 @@
|
|||||||
"default_icon": {
|
"default_icon": {
|
||||||
"16": "icons/IconSponsorBlocker16px.png",
|
"16": "icons/IconSponsorBlocker16px.png",
|
||||||
"32": "icons/IconSponsorBlocker32px.png",
|
"32": "icons/IconSponsorBlocker32px.png",
|
||||||
"64": "icons/LogoSponsorBlocker64px.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":[
|
||||||
|
|||||||
6152
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": [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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"
|
||||||
},
|
},
|
||||||
@@ -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"
|
||||||
},
|
},
|
||||||
@@ -867,7 +945,10 @@
|
|||||||
"LearnMore": {
|
"LearnMore": {
|
||||||
"message": "Learn More"
|
"message": "Learn More"
|
||||||
},
|
},
|
||||||
"CopyDownvoteButtonInfo": {
|
"FullDetails": {
|
||||||
|
"message": "Full Details"
|
||||||
|
},
|
||||||
|
"CopyDownvoteButtonInfo": {
|
||||||
"message": "Downvotes and creates a local copy for you to resubmit"
|
"message": "Downvotes and creates a local copy for you to resubmit"
|
||||||
},
|
},
|
||||||
"OpenCategoryWikiPage": {
|
"OpenCategoryWikiPage": {
|
||||||
|
|||||||
@@ -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 |
@@ -175,6 +175,18 @@
|
|||||||
<option value="4">__MSG_noticeVisibilityMode4__</option>
|
<option value="4">__MSG_noticeVisibilityMode4__</option>
|
||||||
</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">
|
||||||
|
|||||||
@@ -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">
|
||||||
{this.props.text}
|
|
||||||
</p>
|
<td>
|
||||||
|
{this.props.icon ?
|
||||||
|
<img src={chrome.runtime.getURL(this.props.icon)} className="sponsorTimesInfoIcon" />
|
||||||
|
: null}
|
||||||
|
|
||||||
|
<span>
|
||||||
|
{this.props.text}
|
||||||
|
</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";
|
||||||
@@ -72,7 +72,7 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
|
|||||||
|
|
||||||
amountOfPreviousNotices: number;
|
amountOfPreviousNotices: number;
|
||||||
showInSecondSlot: boolean;
|
showInSecondSlot: boolean;
|
||||||
|
|
||||||
idSuffix: string;
|
idSuffix: string;
|
||||||
|
|
||||||
noticeRef: React.MutableRefObject<NoticeComponent>;
|
noticeRef: React.MutableRefObject<NoticeComponent>;
|
||||||
@@ -105,7 +105,7 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
|
|||||||
if (this.segments.length > 1) {
|
if (this.segments.length > 1) {
|
||||||
this.segments.sort((a, b) => a.segment[0] - b.segment[0]);
|
this.segments.sort((a, b) => a.segment[0] - b.segment[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is the suffix added at the end of every id
|
// This is the suffix added at the end of every id
|
||||||
for (const segment of this.segments) {
|
for (const segment of this.segments) {
|
||||||
this.idSuffix += segment.UUID;
|
this.idSuffix += segment.UUID;
|
||||||
@@ -168,7 +168,7 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
|
|||||||
noticeStyle.transform = "scale(0.8) translate(10%, 10%)";
|
noticeStyle.transform = "scale(0.8) translate(10%, 10%)";
|
||||||
}
|
}
|
||||||
|
|
||||||
// If it started out as smaller, always keep the
|
// If it started out as smaller, always keep the
|
||||||
// skip button there
|
// skip button there
|
||||||
const showFirstSkipButton = this.props.smaller || this.segments[0].actionType === ActionType.Mute;
|
const showFirstSkipButton = this.props.smaller || this.segments[0].actionType === ActionType.Mute;
|
||||||
const firstColumn = showFirstSkipButton ? (
|
const firstColumn = showFirstSkipButton ? (
|
||||||
@@ -181,7 +181,7 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
|
|||||||
showInSecondSlot={this.showInSecondSlot}
|
showInSecondSlot={this.showInSecondSlot}
|
||||||
idSuffix={this.idSuffix}
|
idSuffix={this.idSuffix}
|
||||||
fadeIn={true}
|
fadeIn={true}
|
||||||
startFaded={Config.config.noticeVisibilityMode >= NoticeVisbilityMode.FadedForAll
|
startFaded={Config.config.noticeVisibilityMode >= NoticeVisbilityMode.FadedForAll
|
||||||
|| (Config.config.noticeVisibilityMode >= NoticeVisbilityMode.FadedForAutoSkip && this.autoSkip)}
|
|| (Config.config.noticeVisibilityMode >= NoticeVisbilityMode.FadedForAutoSkip && this.autoSkip)}
|
||||||
timed={true}
|
timed={true}
|
||||||
maxCountdownTime={this.state.maxCountdownTime}
|
maxCountdownTime={this.state.maxCountdownTime}
|
||||||
@@ -205,7 +205,7 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
|
|||||||
key={0}>
|
key={0}>
|
||||||
|
|
||||||
{/* Vote Button Container */}
|
{/* Vote Button Container */}
|
||||||
{!this.state.thanksForVotingText ?
|
{!this.state.thanksForVotingText ?
|
||||||
<td id={"sponsorTimesVoteButtonsContainer" + this.idSuffix}
|
<td id={"sponsorTimesVoteButtonsContainer" + this.idSuffix}
|
||||||
className="sponsorTimesVoteButtonsContainer">
|
className="sponsorTimesVoteButtonsContainer">
|
||||||
|
|
||||||
@@ -268,7 +268,7 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
|
|||||||
? this.getSkipButton(1) : null}
|
? this.getSkipButton(1) : null}
|
||||||
|
|
||||||
{/* Never show button */}
|
{/* Never show button */}
|
||||||
{!this.autoSkip || this.props.startReskip ? "" :
|
{!this.autoSkip || this.props.startReskip ? "" :
|
||||||
<td className="sponsorSkipNoticeRightSection"
|
<td className="sponsorSkipNoticeRightSection"
|
||||||
key={1}>
|
key={1}>
|
||||||
<button className="sponsorSkipObject sponsorSkipNoticeButton sponsorSkipNoticeRightButton"
|
<button className="sponsorSkipObject sponsorSkipNoticeButton sponsorSkipNoticeRightButton"
|
||||||
@@ -343,7 +343,7 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
|
|||||||
}
|
}
|
||||||
|
|
||||||
getSkipButton(buttonIndex: number): JSX.Element {
|
getSkipButton(buttonIndex: number): JSX.Element {
|
||||||
if (this.state.showSkipButton[buttonIndex] && (this.segments.length > 1
|
if (this.state.showSkipButton[buttonIndex] && (this.segments.length > 1
|
||||||
|| this.segments[0].actionType !== ActionType.Poi
|
|| this.segments[0].actionType !== ActionType.Poi
|
||||||
|| this.props.unskipTime)) {
|
|| this.props.unskipTime)) {
|
||||||
|
|
||||||
@@ -365,8 +365,8 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
|
|||||||
className="sponsorSkipObject sponsorSkipNoticeButton"
|
className="sponsorSkipObject sponsorSkipNoticeButton"
|
||||||
style={style}
|
style={style}
|
||||||
onClick={() => this.prepAction(buttonIndex === 1 ? SkipNoticeAction.Unskip1 : SkipNoticeAction.Unskip0)}>
|
onClick={() => this.prepAction(buttonIndex === 1 ? SkipNoticeAction.Unskip1 : SkipNoticeAction.Unskip0)}>
|
||||||
{this.getSkipButtonText(buttonIndex, forceSeek ? ActionType.Skip : null)
|
{this.getSkipButtonText(buttonIndex, forceSeek ? ActionType.Skip : null)
|
||||||
+ (!forceSeek && this.state.showKeybindHint
|
+ (!forceSeek && this.state.showKeybindHint
|
||||||
? " (" + keybindToString(Config.config.skipKeybind) + ")" : "")}
|
? " (" + keybindToString(Config.config.skipKeybind) + ")" : "")}
|
||||||
</button>
|
</button>
|
||||||
</span>
|
</span>
|
||||||
@@ -379,7 +379,7 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
|
|||||||
for (let i = 0; i < this.segments.length; i++) {
|
for (let i = 0; i < this.segments.length; i++) {
|
||||||
elements.push(
|
elements.push(
|
||||||
<button className="sponsorSkipObject sponsorSkipNoticeButton"
|
<button className="sponsorSkipObject sponsorSkipNoticeButton"
|
||||||
style={{opacity: this.getSubmissionChooserOpacity(i),
|
style={{opacity: this.getSubmissionChooserOpacity(i),
|
||||||
color: this.getSubmissionChooserColor(i)}}
|
color: this.getSubmissionChooserColor(i)}}
|
||||||
onClick={() => this.performAction(i)}
|
onClick={() => this.performAction(i)}
|
||||||
key={"submission" + i + this.segments[i].category + this.idSuffix}>
|
key={"submission" + i + this.segments[i].category + this.idSuffix}>
|
||||||
@@ -404,7 +404,7 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
|
|||||||
getSubmissionChooserColor(index: number): string {
|
getSubmissionChooserColor(index: number): string {
|
||||||
const isDownvote = this.state.actionState == SkipNoticeAction.Downvote;
|
const isDownvote = this.state.actionState == SkipNoticeAction.Downvote;
|
||||||
const isCopyDownvote = this.state.actionState == SkipNoticeAction.CopyDownvote;
|
const isCopyDownvote = this.state.actionState == SkipNoticeAction.CopyDownvote;
|
||||||
const shouldWarnUser = Config.config.isVip && (isDownvote || isCopyDownvote)
|
const shouldWarnUser = Config.config.isVip && (isDownvote || isCopyDownvote)
|
||||||
&& this.segments[index].locked === 1;
|
&& this.segments[index].locked === 1;
|
||||||
|
|
||||||
return shouldWarnUser ? this.lockedColor : this.unselectedColor;
|
return shouldWarnUser ? this.lockedColor : this.unselectedColor;
|
||||||
@@ -480,8 +480,8 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Performs the action from the current state
|
* Performs the action from the current state
|
||||||
*
|
*
|
||||||
* @param index
|
* @param index
|
||||||
*/
|
*/
|
||||||
performAction(index: number, action?: SkipNoticeAction): void {
|
performAction(index: number, action?: SkipNoticeAction): void {
|
||||||
switch (action ?? this.state.actionState) {
|
switch (action ?? this.state.actionState) {
|
||||||
@@ -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();
|
||||||
@@ -723,7 +718,7 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
|
|||||||
messages
|
messages
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
addVoteButtonInfo(message: string): void {
|
addVoteButtonInfo(message: string): void {
|
||||||
this.setState({
|
this.setState({
|
||||||
thanksForVotingText: message
|
thanksForVotingText: message
|
||||||
@@ -786,7 +781,7 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
|
|||||||
case ActionType.Mute: {
|
case ActionType.Mute: {
|
||||||
return chrome.i18n.getMessage("unmute");
|
return chrome.i18n.getMessage("unmute");
|
||||||
}
|
}
|
||||||
case ActionType.Skip:
|
case ActionType.Skip:
|
||||||
default: {
|
default: {
|
||||||
return chrome.i18n.getMessage("unskip");
|
return chrome.i18n.getMessage("unskip");
|
||||||
}
|
}
|
||||||
@@ -799,7 +794,7 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
|
|||||||
case ActionType.Mute: {
|
case ActionType.Mute: {
|
||||||
return chrome.i18n.getMessage("mute");
|
return chrome.i18n.getMessage("mute");
|
||||||
}
|
}
|
||||||
case ActionType.Skip:
|
case ActionType.Skip:
|
||||||
default: {
|
default: {
|
||||||
return chrome.i18n.getMessage("reskip");
|
return chrome.i18n.getMessage("reskip");
|
||||||
}
|
}
|
||||||
@@ -812,7 +807,7 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
|
|||||||
case ActionType.Mute: {
|
case ActionType.Mute: {
|
||||||
return chrome.i18n.getMessage("mute");
|
return chrome.i18n.getMessage("mute");
|
||||||
}
|
}
|
||||||
case ActionType.Skip:
|
case ActionType.Skip:
|
||||||
default: {
|
default: {
|
||||||
return chrome.i18n.getMessage("skip");
|
return chrome.i18n.getMessage("skip");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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: {
|
||||||
@@ -167,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: {},
|
||||||
|
|
||||||
@@ -302,7 +304,7 @@ function configProxy(): { sync: SBConfig, local: SBStorage } {
|
|||||||
for (const key in changes) {
|
for (const key in changes) {
|
||||||
Config.cachedSyncConfig[key] = changes[key].newValue;
|
Config.cachedSyncConfig[key] = changes[key].newValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const callback of Config.configSyncListeners) {
|
for (const callback of Config.configSyncListeners) {
|
||||||
callback(changes);
|
callback(changes);
|
||||||
}
|
}
|
||||||
@@ -312,7 +314,7 @@ function configProxy(): { sync: SBConfig, local: SBStorage } {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const syncHandler: ProxyHandler<SBConfig> = {
|
const syncHandler: ProxyHandler<SBConfig> = {
|
||||||
set<K extends keyof SBConfig>(obj: SBConfig, prop: K, value: SBConfig[K]) {
|
set<K extends keyof SBConfig>(obj: SBConfig, prop: K, value: SBConfig[K]) {
|
||||||
Config.cachedSyncConfig[prop] = value;
|
Config.cachedSyncConfig[prop] = value;
|
||||||
@@ -329,10 +331,10 @@ function configProxy(): { sync: SBConfig, local: SBStorage } {
|
|||||||
|
|
||||||
return obj[prop] || data;
|
return obj[prop] || data;
|
||||||
},
|
},
|
||||||
|
|
||||||
deleteProperty(obj: SBConfig, prop: keyof SBConfig) {
|
deleteProperty(obj: SBConfig, prop: keyof SBConfig) {
|
||||||
chrome.storage.sync.remove(<string> prop);
|
chrome.storage.sync.remove(<string> prop);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -354,10 +356,10 @@ function configProxy(): { sync: SBConfig, local: SBStorage } {
|
|||||||
|
|
||||||
return obj[prop] || data;
|
return obj[prop] || data;
|
||||||
},
|
},
|
||||||
|
|
||||||
deleteProperty(obj: SBStorage, prop: keyof SBStorage) {
|
deleteProperty(obj: SBStorage, prop: keyof SBStorage) {
|
||||||
chrome.storage.local.remove(<string> prop);
|
chrome.storage.local.remove(<string> prop);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -381,7 +383,7 @@ function forceLocalUpdate(prop: string): void {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetchConfig(): Promise<void> {
|
async function fetchConfig(): Promise<void> {
|
||||||
await Promise.all([new Promise<void>((resolve) => {
|
await Promise.all([new Promise<void>((resolve) => {
|
||||||
chrome.storage.sync.get(null, function(items) {
|
chrome.storage.sync.get(null, function(items) {
|
||||||
Config.cachedSyncConfig = <SBConfig> <unknown> items;
|
Config.cachedSyncConfig = <SBConfig> <unknown> items;
|
||||||
@@ -389,7 +391,7 @@ async function fetchConfig(): Promise<void> {
|
|||||||
});
|
});
|
||||||
}), new Promise<void>((resolve) => {
|
}), new Promise<void>((resolve) => {
|
||||||
chrome.storage.local.get(null, function(items) {
|
chrome.storage.local.get(null, function(items) {
|
||||||
Config.cachedLocalStorage = <SBStorage> <unknown> items;
|
Config.cachedLocalStorage = <SBStorage> <unknown> items;
|
||||||
resolve();
|
resolve();
|
||||||
});
|
});
|
||||||
})]);
|
})]);
|
||||||
@@ -433,9 +435,9 @@ function migrateOldSyncFormats(config: SBConfig) {
|
|||||||
if (!config["autoSkipOnMusicVideosUpdate"]) {
|
if (!config["autoSkipOnMusicVideosUpdate"]) {
|
||||||
config["autoSkipOnMusicVideosUpdate"] = true;
|
config["autoSkipOnMusicVideosUpdate"] = true;
|
||||||
for (const selection of config.categorySelections) {
|
for (const selection of config.categorySelections) {
|
||||||
if (selection.name === "music_offtopic"
|
if (selection.name === "music_offtopic"
|
||||||
&& selection.option === CategorySkipOption.AutoSkip) {
|
&& selection.option === CategorySkipOption.AutoSkip) {
|
||||||
|
|
||||||
config.autoSkipOnMusicVideos = true;
|
config.autoSkipOnMusicVideos = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -321,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();
|
||||||
|
|
||||||
@@ -483,14 +480,7 @@ function startSponsorSchedule(includeIntersectingSegments = false, currentTime?:
|
|||||||
|
|
||||||
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;
|
||||||
|
|
||||||
@@ -544,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({
|
||||||
@@ -594,11 +584,23 @@ function startSponsorSchedule(includeIntersectingSegments = false, currentTime?:
|
|||||||
logDebug(`Starting timeout to skip ${video.currentTime} to skip at ${skipTime[0]}`);
|
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);
|
||||||
@@ -942,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;
|
||||||
}
|
}
|
||||||
@@ -957,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;
|
||||||
}
|
}
|
||||||
@@ -995,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.
|
||||||
@@ -1149,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})|\/c\/([a-zA-Z0-9_-]+)/)?.[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);
|
||||||
|
|||||||
@@ -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;
|
||||||
@@ -53,7 +50,7 @@ export class SkipButtonControlBar {
|
|||||||
this.skipIcon.id = "sbSkipIconControlBarImage";
|
this.skipIcon.id = "sbSkipIconControlBarImage";
|
||||||
|
|
||||||
this.textContainer = document.createElement("div");
|
this.textContainer = document.createElement("div");
|
||||||
|
|
||||||
this.container.appendChild(this.skipIcon);
|
this.container.appendChild(this.skipIcon);
|
||||||
this.container.appendChild(this.textContainer);
|
this.container.appendChild(this.textContainer);
|
||||||
this.container.addEventListener("click", () => this.toggleSkip());
|
this.container.addEventListener("click", () => this.toggleSkip());
|
||||||
@@ -73,7 +70,7 @@ export class SkipButtonControlBar {
|
|||||||
attachToPage(): void {
|
attachToPage(): void {
|
||||||
const mountingContainer = this.getMountingContainer();
|
const mountingContainer = this.getMountingContainer();
|
||||||
this.chapterText = document.querySelector(".ytp-chapter-container");
|
this.chapterText = document.querySelector(".ytp-chapter-container");
|
||||||
|
|
||||||
if (mountingContainer && !mountingContainer.contains(this.container)) {
|
if (mountingContainer && !mountingContainer.contains(this.container)) {
|
||||||
if (this.onMobileYouTube) {
|
if (this.onMobileYouTube) {
|
||||||
mountingContainer.appendChild(this.container);
|
mountingContainer.appendChild(this.container);
|
||||||
@@ -220,4 +217,3 @@ export class SkipButtonControlBar {
|
|||||||
this.container.style.left = this.left + "px";
|
this.container.style.left = this.left + "px";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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`)
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -62,7 +62,7 @@ function hexToRgb(hex: string): {r: number, g: number, b: number} {
|
|||||||
g: parseInt(result[2], 16),
|
g: parseInt(result[2], 16),
|
||||||
b: parseInt(result[3], 16)
|
b: parseInt(result[3], 16)
|
||||||
} : null;
|
} : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const GenericUtils = {
|
export const GenericUtils = {
|
||||||
wait,
|
wait,
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ window["SBLogs"] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export function logDebug(message: string) {
|
export function logDebug(message: string) {
|
||||||
window["SBLogs"].debug.push(message);
|
window["SBLogs"].debug.push(`[${new Date().toISOString()}] ${message}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function logWarn(message: string) {
|
export function logWarn(message: string) {
|
||||||
window["SBLogs"].warn.push(message);
|
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;
|
||||||
|
|
||||||
|
|||||||