Compare commits

...

101 Commits
3.3.3 ... 3.6

Author SHA1 Message Date
Ajay Ramachandran
20d0c05049 Update manifest.json 2021-11-08 19:29:55 -05:00
Ajay Ramachandran
96e4957f71 Add filler category and allow mute intro, outro, preview 2021-11-08 19:19:00 -05:00
Ajay Ramachandran
9c5eeac239 Merge pull request #1029 from opl-/docs/readme-building
Add more detail to building section of readme
2021-11-03 19:38:12 -04:00
Ajay Ramachandran
e685697bbb Add back info about adjusting config 2021-11-03 19:36:45 -04:00
Ajay Ramachandran
752e515a1c Merge pull request #1018 from FlorianZahn/fontSizeFixTooltip
Makes rectangleTooltip fontSize bigger
2021-11-02 00:08:26 -04:00
Ajay Ramachandran
ca0f68bb7d Merge pull request #1019 from FlorianZahn/roundSubmitTimes
unsubmitted segments are initialized rounded to 3 digits
2021-11-02 00:08:10 -04:00
Ajay Ramachandran
34884026d9 New Crowdin updates (#1014) 2021-11-02 00:07:08 -04:00
Ajay Ramachandran
7a38bf0c08 bump version 2021-11-02 00:06:56 -04:00
Ajay Ramachandran
5adcec2ca5 Remove segment duration filter
Close #1031 #989
2021-11-02 00:06:40 -04:00
Ajay Ramachandran
36989907a2 Remove highlight skipping by clicking near it
Closes #973
2021-10-30 22:02:21 -04:00
opl-
db55778fd8 Add more detail to building section of readme 2021-10-29 20:59:21 +02:00
Ajay Ramachandran
41be51b384 formatting fixes 2021-10-26 18:37:37 -04:00
Ajay Ramachandran
e87efe2c67 bump version 2021-10-23 15:09:47 -04:00
Ajay Ramachandran
069299e968 Merge pull request #1021 from opl-/fix/wheel-edits
Fix mouse wheel can enter edit mode
2021-10-22 23:11:22 -04:00
opl-
4d09a603fe Fix mouse wheel can enter edit mode 2021-10-23 00:52:52 +02:00
Ajay Ramachandran
8b595af5e9 Fix skip to highlight not hiding when none 2021-10-22 01:50:17 -04:00
Ajay Ramachandran
41739a8799 Merge branch 'master' of https://github.com/ajayyy/SponsorBlock 2021-10-22 01:29:47 -04:00
Ajay Ramachandran
23bebbca7c Fix help page on mobile 2021-10-22 01:29:46 -04:00
Ajay Ramachandran
5f2af12150 bump version 2021-10-21 22:39:15 -04:00
Ajay Ramachandran
628abd03f0 Added swiping away for skip to highlight on mobile 2021-10-21 22:33:49 -04:00
Ajay Ramachandran
8e254c5807 Make bigger buttons on mobile skip button 2021-10-21 22:11:26 -04:00
Ajay Ramachandran
0647576d6f Add animation for skip to highlight on mobile 2021-10-21 21:58:43 -04:00
Ajay Ramachandran
c803ae9499 Add skip to highlight to mobile 2021-10-21 01:30:52 -04:00
FlorianZahn
95f45312e1 support for multiple poi categories 2021-10-21 04:19:26 +02:00
FlorianZahn
9dda9a583d unsubmitted segments are initialized rounded to 3 digits 2021-10-21 03:14:45 +02:00
Ajay Ramachandran
d1e6421e5b Fix type errors 2021-10-20 19:33:48 -04:00
Ajay Ramachandran
bd0a6aaaad Hide submissions on mobile 2021-10-20 19:28:00 -04:00
Ajay Ramachandran
1e8b176c69 Allow finer tuned previewing 2021-10-19 22:57:46 -04:00
Ajay Ramachandran
14018798f7 Add wiki links to options 2021-10-19 19:10:27 -04:00
Ajay Ramachandran
a0d06ca6e8 Fix start time in preview bar in wrong place 2021-10-19 19:00:30 -04:00
FlorianZahn
95fe1eef6f Makes rectangleTooltip fontSize bigger 2021-10-19 21:38:44 +02:00
Ajay Ramachandran
38b1dda20b Add support for required segment parameter 2021-10-18 19:51:44 -04:00
Ajay Ramachandran
07cf1764dc bump version 2021-10-17 19:12:38 -04:00
Ajay Ramachandran
aeb9c5b203 New Crowdin updates (#1012) 2021-10-17 19:12:09 -04:00
Ajay Ramachandran
ad3f0c1a06 Don't filter segments when switching videos still
Fixes #989
2021-10-16 13:41:07 -04:00
Ajay Ramachandran
4bc180077e Fix segments sometimes displaying after the seek bar if at the end 2021-10-16 13:15:47 -04:00
Ajay Ramachandran
510db57666 bump version 2021-10-15 19:29:15 -04:00
Ajay Ramachandran
5ee6a2195d Merge pull request #1002 from maximmax42/patch-1
Added margin-bottom for #sponsorblockPopup
2021-10-15 19:28:54 -04:00
Ajay Ramachandran
63d4c1aedb New Crowdin updates (#990) 2021-10-15 19:01:03 -04:00
Ajay Ramachandran
e9204be96f Merge pull request #988 from FlorianZahn/copySegment
Copy segments into your unsubmitted and SkipNotice changes
2021-10-15 19:00:38 -04:00
Ajay Ramachandran
0863061665 Fix indentation in manifest 2021-10-15 18:57:36 -04:00
FlorianZahn
8aea74160c only change color if user isVip 2021-10-15 21:01:32 +02:00
FlorianZahn
d375a97e99 Vip Warning also in popup 2021-10-15 20:52:15 +02:00
Ajay Ramachandran
fe5499e80a Code style fixes and react errors 2021-10-15 00:56:48 -04:00
Ajay Ramachandran
598da2a7fe Merge branch 'copySegment' of https://github.com/florianzahn/sponsorblock into pr/FlorianZahn/988 2021-10-15 00:31:09 -04:00
Ajay Ramachandran
fcbeeb9fc1 Remove extra segment lookup and use lockbyhash lookup 2021-10-15 00:31:07 -04:00
FlorianZahn
d82ef63d89 fix loading text not displaying upon voting 2021-10-14 19:05:36 +02:00
FlorianZahn
a457a8009e SkipNotice countdown now updates again on config update 2021-10-14 08:05:55 +02:00
FlorianZahn
7698be8462 Remove merge mistake 2021-10-14 07:21:07 +02:00
FlorianZahn
738868da8d Merge branch 'master' into copySegment 2021-10-14 07:16:55 +02:00
Ajay Ramachandran
fc7fc693ed Fix getting locked category 2021-10-13 23:57:59 -04:00
Ajay Ramachandran
27f5997e5a Add return types to vip fetching functions 2021-10-13 23:34:25 -04:00
Ajay Ramachandran
45274f5c72 Wait for vip info to be fetched 2021-10-13 23:32:52 -04:00
Ajay Ramachandran
2bdfd3f39b Merge branch 'copySegment' of https://github.com/florianzahn/sponsorblock into pr/FlorianZahn/988 2021-10-13 23:25:48 -04:00
Ajay Ramachandran
9b9174ab9a Simplify vip info fetching 2021-10-13 23:25:46 -04:00
FlorianZahn
3e3e9796b1 syntax error
Co-authored-by: Ajay Ramachandran <dev@ajay.app>
2021-10-14 05:19:18 +02:00
Ajay Ramachandran
ff5fa4c724 Move config values and close notice 2021-10-13 23:14:51 -04:00
Ajay Ramachandran
b8ab05ccad Merge pull request #985 from FlorianZahn/editSegmentTimesByScrolling
Scrolling over the edit-segment-time component will change them.
2021-10-13 22:37:31 -04:00
FlorianZahn
93e440385f Removed console.log and redundancy 2021-10-14 02:16:04 +02:00
FlorianZahn
af66a77026 Fixed logic mistake if undovotes are ever implemented 2021-10-14 02:11:15 +02:00
Maxim
75607dea1c Added margin-bottom for #sponsorblockPopup
This margin is to separate popup window from playlist/related videos list
2021-10-13 22:48:07 +05:00
FlorianZahn
5b353b05ac replaced tab with 4 spaces 2021-10-13 06:22:50 +02:00
FlorianZahn
3162ab93a1 Formatting 2021-10-13 06:19:48 +02:00
FlorianZahn
b18f631d33 better if/else readability
Co-authored-by: Ajay Ramachandran <dev@ajay.app>
2021-10-13 06:14:03 +02:00
FlorianZahn
2e254cb917 prettier spaces
Co-authored-by: Ajay Ramachandran <dev@ajay.app>
2021-10-13 06:13:32 +02:00
FlorianZahn
77ce9433a7 removed response.ok for response === 200 2021-10-13 06:08:14 +02:00
FlorianZahn
509e54762f Merge branch 'master' of https://github.com/ajayyy/SponsorBlock into editSegmentTimesByScrolling 2021-10-13 06:02:50 +02:00
FlorianZahn
caeb347137 Merge branch 'master' of https://github.com/ajayyy/SponsorBlock into copySegment 2021-10-13 05:55:21 +02:00
Ajay Ramachandran
a2b054844a Fix unsubmitted segments sometimes not skipping 2021-10-11 22:22:36 -04:00
Ajay Ramachandran
5b79d4ef48 Merge branch 'master' of https://github.com/ajayyy/SponsorBlock 2021-10-11 19:02:22 -04:00
Ajay Ramachandran
3de66ebe23 Potentially fix info button reappearing 2021-10-11 19:02:20 -04:00
FlorianZahn
60ef51b7f5 I forgot to change the 24h countdown back to 24h instead of 1 seconds 2021-10-11 03:50:19 +02:00
FlorianZahn
aa8ee02277 Added colored text if a category is locked for submitting and changing category 2021-10-11 03:49:14 +02:00
FlorianZahn
b927ebbbf7 Lint fixes 2021-10-10 10:56:27 +02:00
FlorianZahn
d72d5dcbcb Lint fixes 2021-10-10 10:50:35 +02:00
FlorianZahn
d9f703d808 Vip warning added when downvoting. sry that it is in the same branch, but this is the most current UI 2021-10-10 10:47:47 +02:00
FlorianZahn
a9cc43c586 Changed heigt of 2nd notice. Minor changes. Upvoting lets downvoted segment reappear 2021-10-10 00:41:21 +02:00
FlorianZahn
844567dcdf Lit fixes 2021-10-09 08:13:02 +02:00
FlorianZahn
52ed4f73f4 SkipNotice now remembers what has already been voted. Also nicer highlighting of current selection. 2021-10-09 08:08:46 +02:00
FlorianZahn
907bd68e4e Buttons now change color depending on state. Added colorPalette config entry 2021-10-09 02:43:39 +02:00
FlorianZahn
6ea226c972 Added string to the language file 2021-10-06 23:38:06 +02:00
FlorianZahn
44f9ab9806 changed let to const 2021-10-06 23:16:53 +02:00
FlorianZahn
edd1011737 margin in ContinueVoting 2021-10-06 23:13:10 +02:00
FlorianZahn
08558bfaeb Merge branch 'copySegment' of https://github.com/FlorianZahn/SponsorBlock into copySegment 2021-10-06 23:08:22 +02:00
FlorianZahn
4afc2c153a Restart Voting button. Wiki links. SkipNotice Improvements 2021-10-06 23:02:26 +02:00
FlorianZahn
988905c155 Update config.ts 2021-10-06 16:33:11 +02:00
FlorianZahn
51aab00985 Update config.ts 2021-10-06 08:31:18 +02:00
FlorianZahn
84924b6364 Update SkipNoticeComponent.tsx 2021-10-06 08:29:45 +02:00
FlorianZahn
93f02877a7 copy segments basics done 2021-10-06 08:15:15 +02:00
FlorianZahn
c571a9ecb6 made the tool tip fully opaque for better readability 2021-10-04 21:37:15 +02:00
FlorianZahn
1ad60720df empty function fix 2021-10-04 21:04:02 +02:00
FlorianZahn
e5fe99c89b Changed empty arrow function to empty function 2021-10-04 20:24:52 +02:00
FlorianZahn
3fc32a68c3 Changing the time a little manually opens a popup 2021-10-04 20:20:04 +02:00
FlorianZahn
142cc2881f added step modifier ctrl 2021-10-04 14:26:24 +02:00
FlorianZahn
4de55ea5fe Scroll amount now 1/1000th while pressing "shift" 2021-10-04 04:24:14 +02:00
FlorianZahn
620e75517c Now handeling deltaY=0 and shrunk down code 2021-10-03 22:11:33 +02:00
FlorianZahn
cba26a42af combined similar code into function. More readable function names 2021-10-03 21:50:02 +02:00
FlorianZahn
f3f598d6c7 combined similar code into function. More readable function names 2021-10-03 21:48:12 +02:00
FlorianZahn
fe7d9986fa Boolean --> boolean; var --> let 2021-10-03 21:23:33 +02:00
FlorianZahn
143ca6f6e0 Highlight time stamps are synchronized when scorlling 2021-10-03 21:19:06 +02:00
FlorianZahn
69ce065588 Scrolling over the segment times will change them 2021-10-03 20:56:10 +02:00
58 changed files with 2003 additions and 336 deletions

View File

@@ -60,21 +60,24 @@ You can read the API docs [here](https://wiki.sponsor.ajay.app/index.php/API_Doc
# Building
You must have Node.js 16 installed.
You must have [Node.js 16](https://nodejs.org/) and npm installed.
Rename `config.json.example` to `config.json` and adjust configuration as desired.
1. Copy the file `config.json.example` to `config.json` and adjust configuration as desired.
There are also other build scripts available. Install `npm`, then run `npm install` in the repository to install dependencies.
- You will need to repeat this step in the future if you get build errors related to `CompileConfig`. This can happen for example when a new category is added.
Run `npm run build` to generate a Chrome extension.
2. Run `npm install` in the repository to install dependencies.
Use `npm run build:firefox` to generate a Firefox extension.
3. Run `npm run build:dev` (for Chrome) or `npm run build:dev:firefox` (for Firefox) to generate a development version of the extension with source maps.
The result is in `dist`. This can be loaded as an unpacked extension
- You can also run `npm run build` (for Chrome) or `npm run build:firefox` (for Firefox) to generate a production build.
## Developing with a clean profile
4. The built extension is now in `dist/`. You can load it in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/#manifest) or in Firefox as a [temporary extension](https://developer.mozilla.org/en-US/docs/Tools/about:debugging#loading_a_temporary_extension).
### Developing with a clean profile and hot reloading
Run `npm run dev` (for Chrome) or `npm run dev:firefox` (for Firefox) to run the extension using a clean browser profile with hot reloading. This uses [`web-ext run`](https://extensionworkshop.com/documentation/develop/web-ext-command-reference/#commands).
Run `npm run dev` to run the extension using a clean browser profile with hot reloading. Use `npm run dev:firefox` for Firefox. This uses [`web-ext run`](https://extensionworkshop.com/documentation/develop/web-ext-command-reference/#commands).
Known chromium bug: Extension is not loaded properly on first start. Visit `chrome://extensions/` and reload the extension.
For Firefox for Android, use `npm run dev:firefox-android -- --adb-device <ip-address of the device>`. See the [Firefox documentation](https://extensionworkshop.com/documentation/develop/developing-extensions-for-firefox-for-android/#debug-your-extension) for more information.

View File

@@ -2,15 +2,29 @@
"serverAddress": "https://sponsor.ajay.app",
"testingServerAddress": "https://sponsor.ajay.app/test",
"serverAddressComment": "This specifies the default SponsorBlock server to connect to",
"categoryList": ["sponsor", "selfpromo", "interaction", "poi_highlight", "intro", "outro", "preview", "music_offtopic"],
"categoryList": ["sponsor", "selfpromo", "interaction", "poi_highlight", "intro", "outro", "preview", "filler", "music_offtopic"],
"categorySupport": {
"sponsor": ["skip", "mute"],
"selfpromo": ["skip", "mute"],
"interaction": ["skip", "mute"],
"intro": ["skip"],
"outro": ["skip"],
"preview": ["skip"],
"intro": ["skip", "mute"],
"outro": ["skip", "mute"],
"preview": ["skip", "mute"],
"filler": ["skip", "mute"],
"music_offtopic": ["skip"],
"poi_highlight": ["skip"]
},
"wikiLinks": {
"sponsor": "https://wiki.sponsor.ajay.app/w/Sponsor",
"selfpromo": "https://wiki.sponsor.ajay.app/w/Unpaid/Self_Promotion",
"interaction": "https://wiki.sponsor.ajay.app/w/Interaction_Reminder_(Subscribe)",
"intro": "https://wiki.sponsor.ajay.app/w/Intermission/Intro_Animation",
"outro": "https://wiki.sponsor.ajay.app/w/Endcards/Credits",
"preview": "https://wiki.sponsor.ajay.app/w/Preview/Recap",
"filler": "https://wiki.sponsor.ajay.app/w/Filler_Tangent",
"music_offtopic": "https://wiki.sponsor.ajay.app/w/Music:_Non-Music_Section",
"poi_highlight": "https://wiki.sponsor.ajay.app/w/Highlight",
"guidelines": "https://wiki.sponsor.ajay.app/w/Guidelines",
"mute": "https://wiki.sponsor.ajay.app/w/Mute_Segment"
}
}

View File

@@ -1,7 +1,7 @@
{
"name": "__MSG_fullName__",
"short_name": "SponsorBlock",
"version": "3.3.3",
"version": "3.6",
"default_locale": "en",
"description": "__MSG_Description__",
"homepage_url": "https://sponsor.ajay.app",
@@ -37,6 +37,7 @@
"icons/upvote.png",
"icons/downvote.png",
"icons/thumbs_down.svg",
"icons/thumbs_down_locked.svg",
"icons/thumbs_up.svg",
"icons/help.svg",
"icons/report.png",

View File

@@ -4,7 +4,7 @@
"description": "Name of the extension."
},
"Description": {
"message": "Прескачайте спонсорства, напомняния за абониране, и други неща в YouTube клипове. Докладвайте спонсорства на клиповете които гледате, за да спестите време на други потребители.",
"message": "Прескачайте спонсорства, напомняния за абониране и други неща в клипове в YouTube. Докладвайте спонсорства в клиповете, които гледате, за да спестите време на други потребители.",
"description": "Description of the extension."
},
"400": {
@@ -23,7 +23,7 @@
"message": "сегмент"
},
"Segments": {
"message": "сегменти"
"message": "сегмента"
},
"upvoteButtonInfo": {
"message": "Одобряване на това предложение"
@@ -86,7 +86,7 @@
"message": "Отказ от създаването на сегмент"
},
"noVideoID": {
"message": "Не е намерен видеоклип в YouTube.\nАко това е неправилно, опреснете раздела."
"message": "Не е намерен видеоклип в YouTube.\nАко това не е правилно, опреснете раздела."
},
"refreshSegments": {
"message": "Опресняване на сегментите"
@@ -131,7 +131,7 @@
"message": "Изпратени сегменти"
},
"savedPeopleFrom": {
"message": "Вие сте помогнали на хората да пропуснат "
"message": "Помогнахте на хората да пропуснат "
},
"viewLeaderboard": {
"message": "Класиране"
@@ -156,7 +156,7 @@
"message": "Това се използва на страницата с публичната статистика, за да покаже колко сте допринесли. Вижте го"
},
"Username": {
"message": "Потребителско име"
"message": "Потребител"
},
"setUsername": {
"message": "Задайте потребителско име"
@@ -528,7 +528,7 @@
"message": "Платена промоция, платени препоръки и директни реклами. Не за самореклама или безплатни препоръки за каузи/създатели/уебсайтове/продукти, които се харесват на автора."
},
"category_selfpromo": {
"message": "Неплатени/Самореклама"
"message": "Неплатена/Самореклама"
},
"category_selfpromo_description": {
"message": "Подобно на „спонсорство“, но за безплатна реклама или самореклама. Това включва търговия със стоки, дарения или информация с кого каналът има сътрудничество."
@@ -700,7 +700,7 @@
"message": "Грешно/Неправилно време"
},
"incorrectCategory": {
"message": "Грешна категория"
"message": "Промяна на категорията"
},
"nonMusicCategoryOnMusic": {
"message": "Това видео е категоризирано като музика. Сигурни ли сте, че това има спонсор? Ако това всъщност е „Немузикален сегмент“, отворете опциите на разширението и активирайте тази категория. След това можете да изпратите този сегмент като „Немузикален“ вместо като спонсор. Моля, прочетете указанията, ако сте объркани."
@@ -810,5 +810,23 @@
},
"LearnMore": {
"message": "Научете повече"
},
"CopyDownvoteButtonInfo": {
"message": "Гласуване против и създаване на локално копие, за да го изпратите отново"
},
"OpenCategoryWikiPage": {
"message": "Отваряне на wiki страницата на тази категория."
},
"CopyAndDownvote": {
"message": "Копиране и гласуване против"
},
"ContinueVoting": {
"message": "Продължаване на гласуването"
},
"ChangeCategoryTooltip": {
"message": "Това незабавно ще се приложи към вашите сегменти"
},
"SponsorTimeEditScrollNewFeature": {
"message": "Използвайте колелото на мишката, докато държите курсора върху полето за редактиране, за да коригирате бързо времето. Комбинации с клавиша ctrl или shift могат да се използват за фина настройка на промените."
}
}

View File

@@ -700,7 +700,7 @@
"message": "Nesprávné / špatné časování"
},
"incorrectCategory": {
"message": "Špatná kategorie"
"message": "Změnit kategorii"
},
"nonMusicCategoryOnMusic": {
"message": "Toto video je kategorizováno jako hudba. Jste si jisti, že je v něm sponzorská sekce? Pokud se opravdu jedná o \"Nehudební segment\", otevřete nastavení a povolte tuto kategorii. Poté budete moct odeslat segment jako \"Nehudební\" místo sponzorského. Pokud jste zmateni, přečtěte si prosím pokyny."
@@ -810,5 +810,23 @@
},
"LearnMore": {
"message": "Zjistit více"
},
"CopyDownvoteButtonInfo": {
"message": "Zahlasuje proti a vytvoří pro vás lokální kopii pro opětovné odeslání"
},
"OpenCategoryWikiPage": {
"message": "Otevřít wiki stránku této kategorie."
},
"CopyAndDownvote": {
"message": "Zkopírovat a hlasovat proti"
},
"ContinueVoting": {
"message": "Pokračovat v hlasování"
},
"ChangeCategoryTooltip": {
"message": "Toto bude okamžitě platit pro vaše segmenty"
},
"SponsorTimeEditScrollNewFeature": {
"message": "Použijte kolečko myši při přechodu přes editační okno pro rychlou úpravu času. Kombinace kláves Ctrl nebo Shift mohou být použity k doladění změn."
}
}

View File

@@ -52,6 +52,9 @@
"reskip": {
"message": "Spring over"
},
"unmute": {
"message": "Lyd til"
},
"paused": {
"message": "Sat på pause"
},
@@ -115,7 +118,29 @@
"submitCheck": {
"message": "Er du sikker på, at du vil indsende dette?"
},
"whitelistChannel": {
"message": "Hvidliste kanal"
},
"removeFromWhitelist": {
"message": "Fjern kanal fra hvidliste"
},
"voteOnTime": {
"message": "Stem På Et Segment"
},
"Submissions": {
"message": "Indsendelser"
},
"savedPeopleFrom": {
"message": "Du har reddet folk fra "
},
"viewLeaderboard": {
"message": "Topliste"
},
"recordTimesDescription": {
"message": "Indsend"
},
"submissionEditHint": {
"message": "Sektionsredigering vises, når du klikker på afsend",
"description": "Appears in the popup to inform them that editing has been moved to the video player."
}
}

View File

@@ -183,7 +183,7 @@
"message": "Versteckt die Schaltflächen im YouTube-Videoplayer, um Segmente einzusenden."
},
"showSkipButton": {
"message": "Behalte \"Zum Highlight springen\"-Knopf in der Navigationsleiste"
"message": "\"Zum Highlight springen\"-Knopf im Player behalten"
},
"showInfoButton": {
"message": "Zeige Info-Knopf im Youtube-Videoplayer"
@@ -573,7 +573,7 @@
"message": "Musikvideoteile ohne Musik"
},
"category_poi_highlight": {
"message": "Hervorheben"
"message": "Highlight"
},
"category_poi_highlight_description": {
"message": "Der Teil des Videos, nach dem die meisten Leute suchen, ähnlich wie \"Video startet bei x\" Kommentare."
@@ -700,7 +700,7 @@
"message": "Nicht korrekt oder falsches Timing"
},
"incorrectCategory": {
"message": "Falsche Kategorie"
"message": "Kategorie ändern"
},
"nonMusicCategoryOnMusic": {
"message": "Dieses Video ist als Musikvideo kategorisiert. Bist du dir sicher, dass es ein gesponsertes Videosegment hat? Wenn dies tatsächlich ein Musikvideoteil ohne Musik ist, öffne die Optionen von SponsorBlock und aktiviere diese Kategorie. Danach kannst du dieses Segment als solches markieren. Bitte lese die Richtlinien, wenn du dir nicht sicher bist."
@@ -810,5 +810,23 @@
},
"LearnMore": {
"message": "Erfahre mehr"
},
"CopyDownvoteButtonInfo": {
"message": "Meldet als unzulässig und erstellt eine lokale Kopie zur späteren Einreichung"
},
"OpenCategoryWikiPage": {
"message": "Den Wiki-Artikel dieser Kategorie aufrufen."
},
"CopyAndDownvote": {
"message": "Kopieren und abwerten"
},
"ContinueVoting": {
"message": "Bewerten fortsetzen"
},
"ChangeCategoryTooltip": {
"message": "Dies wirkt sich sofort auf eigene Segmente aus"
},
"SponsorTimeEditScrollNewFeature": {
"message": "Benutze das Mausrad während der Mauszeiger über dem Eingabefeld schwebt um die Zeit schnell anzupassen. Benutze Strg bzw. Shift für gröbere/genauere Änderungen."
}
}

View File

@@ -139,9 +139,6 @@
"chooseACategory": {
"message": "Επιλέξτε μια κατηγορία"
},
"incorrectCategory": {
"message": "Λάθος κατηγορία"
},
"multipleSegments": {
"message": "Πολλαπλά Τμήματα"
},

View File

@@ -563,6 +563,15 @@
"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."
},
"category_filler": {
"message": "Filler Tangent"
},
"category_filler_description": {
"message": "Tangential scenes added only for filler or humor that are not required to understand the main content of the video. This should not include segments providing context or background details."
},
"category_filler_short": {
"message": "Filler"
},
"category_music_offtopic": {
"message": "Music: Non-Music Section"
},
@@ -700,7 +709,7 @@
"message": "Incorrect/Wrong Timing"
},
"incorrectCategory": {
"message": "Wrong Category"
"message": "Change Category"
},
"nonMusicCategoryOnMusic": {
"message": "This video is categorized as music. Are you sure this has a sponsor? If this is actually a \"Non-Music segment\", open up the extension options and enable this category. Then, you can submit this segment as \"Non-Music\" instead of sponsor. Please read the guidelines if you are confused."
@@ -810,5 +819,23 @@
},
"LearnMore": {
"message": "Learn More"
},
"CopyDownvoteButtonInfo": {
"message": "Downvotes and creates a local copy for you to resubmit"
},
"OpenCategoryWikiPage": {
"message": "Open this category's wiki page."
},
"CopyAndDownvote": {
"message": "Copy and downvote"
},
"ContinueVoting": {
"message": "Continue Voting"
},
"ChangeCategoryTooltip": {
"message": "This will instantly apply to your segments"
},
"SponsorTimeEditScrollNewFeature": {
"message": "Use your mousewheel while hovering over the edit box to quickly adjust the time. Combinations of the ctrl or shift key can be used to fine tune the changes."
}
}

View File

@@ -700,7 +700,7 @@
"message": "Tiempo incorrecto/equivocado"
},
"incorrectCategory": {
"message": "Categoría Incorrecta"
"message": "Cambiar Categoría"
},
"nonMusicCategoryOnMusic": {
"message": "Este video está clasificado como música. ¿Estás seguro de que esto tiene un sponsor? Si esto es realmente un \"Segmento Sin Música\", abre las opciones de la extensión y activa esta categoría. Entonces, puedes enviar este segmento como \"Sin Música\" en lugar de sponsor. Por favor, lee las instrucciones si estás confundido/a."
@@ -810,5 +810,23 @@
},
"LearnMore": {
"message": "Aprenda Más"
},
"CopyDownvoteButtonInfo": {
"message": "Vota negativamente y crea una copia local para que la puedas volver a enviar"
},
"OpenCategoryWikiPage": {
"message": "Abrir la página de la wiki de esta categoría."
},
"CopyAndDownvote": {
"message": "Copiar y votar negativamente"
},
"ContinueVoting": {
"message": "Continuar Votando"
},
"ChangeCategoryTooltip": {
"message": "Esto se aplicará instantáneamente a tus segmentos"
},
"SponsorTimeEditScrollNewFeature": {
"message": "Utilice la rueda del ratón mientras pasa el cursor por encima del cuadro de edición para ajustar el tiempo. Se pueden utilizar combinaciones de la tecla ctrl o shift para afinar los cambios."
}
}

View File

@@ -700,7 +700,7 @@
"message": "Sobimatu/vale ajastus"
},
"incorrectCategory": {
"message": "Vale kategooria"
"message": "Muuda kategooriat"
},
"nonMusicCategoryOnMusic": {
"message": "See video on muusikana kategoriseeritud. Kas oled kindel, et sellel on sponsor? Kui see on tegelikult \"mitte-muusika segment\", ava laienduse valikud ning luba see kategooria. Seejärel saad selle segmendi saata \"mitte-muusika\" kategoorias. Segaduse korral palun loe üle juhised."
@@ -765,5 +765,23 @@
},
"LearnMore": {
"message": "Lisateave"
},
"CopyDownvoteButtonInfo": {
"message": "Annab vastuhääle ja loob kohaliku koopia, mida saad uuesti saata"
},
"OpenCategoryWikiPage": {
"message": "Ava selle kategooria vikileht."
},
"CopyAndDownvote": {
"message": "Kopeeri ja anna vastuhääl"
},
"ContinueVoting": {
"message": "Jätka hääletamist"
},
"ChangeCategoryTooltip": {
"message": "See rakendub sinu segmentidele koheselt"
},
"SponsorTimeEditScrollNewFeature": {
"message": "Kasuta hiirekursorit muutmiskasti kohal, et kiirelt aega reguleerida. Täpsemaks muutmiseks hoia kerimise ajal all Ctrl või Shift klahvi."
}
}

View File

@@ -700,7 +700,7 @@
"message": "Virheellinen/väärä aika"
},
"incorrectCategory": {
"message": "Väärä kategoria"
"message": "Vaihda kategoria"
},
"nonMusicCategoryOnMusic": {
"message": "Tämä video on luokiteltu musiikiksi. Oletko varma, että siinä on sponsori? Jos tämä on oikeasti \"Musiikiton segmentti\", avaa laajennuksen asetukset ja ota tämä kategoria käyttöön. Sitten voit lähettää tämän segmentin oikeassa kategoriassa. Lue säännöt, jos olet vielä hämilläsi."
@@ -810,5 +810,23 @@
},
"LearnMore": {
"message": "Opi lisää"
},
"CopyDownvoteButtonInfo": {
"message": "Äänestää alas ja luo paikallisen kopion, jonka voit lähettää uudelleen"
},
"OpenCategoryWikiPage": {
"message": "Avaa tämän kategorian wiki-sivu."
},
"CopyAndDownvote": {
"message": "Kopioi ja äänestä alas"
},
"ContinueVoting": {
"message": "Jatka äänestystä"
},
"ChangeCategoryTooltip": {
"message": "Tämä vaikuttaa sinun segmentteihin välittömästi"
},
"SponsorTimeEditScrollNewFeature": {
"message": "Käytä hiiren rullaa samalla kun osoitin on muokkauslaatikon päällä säätääksesi aikaa nopeasti. Ctrl- tai Shift-näppäimen yhdistelmiä voi käyttää muutoksien hienosäätelyyn."
}
}

View File

@@ -182,6 +182,9 @@
"hideButtonsDescription": {
"message": "Cela permet de cacher du lecteur YouTube les boutons utilisés pour soumettre des segments commerciaux. Je peux \ncomprendre que certaines personnes les trouvent perturbants. Au lieu d'utiliser ces boutons, cette fenêtre peut être utilisée \npour soumettre des segments commerciaux. Pour cacher la notification, utilisez le bouton \"Ne plus montrer\" sur la notification. Vous pouvez toujours réactiver ces paramètres plus tard."
},
"showSkipButton": {
"message": "Conserver le bouton \"Aller au point d'intérêt\" sur le lecteur"
},
"showInfoButton": {
"message": "Montrer le bouton Info sur le lecteur YouTube"
},
@@ -303,7 +306,7 @@
"message": "Passer {0} ?"
},
"mute_category": {
"message": "Mute {0}?"
"message": "Mettre en sourdine {0} ?"
},
"skip_to_category": {
"message": "Passer à {0}?",
@@ -648,7 +651,7 @@
"description": "Used when submitting segments to only let them select a certain category if they have it enabled in the options."
},
"poiOnlyOneSegment": {
"message": "Avertissement: Ce type de segment peut avoir au maximum un seul actif à la fois. En soumettant plusieurs segments, un seul aléatoire sera affiché."
"message": "Avertissement : Ce type de segment ne peut avoir qu'un seul segment actif à la fois. Si vous en soumettez plusieurs, le choix sera fait au hasard."
},
"youMustSelectACategory": {
"message": "Vous devez sélectionner une catégorie pour tous les segments que vous soumettez !"
@@ -697,7 +700,7 @@
"message": "Segment de mauvaise qualité"
},
"incorrectCategory": {
"message": "Mauvaise catégorie"
"message": "Changer de catégorie"
},
"nonMusicCategoryOnMusic": {
"message": "Cette vidéo est catégorisée comme de la musique. Êtes-vous sûr qu'elle est sponsorisée? S'il s'agit en fait d'un \"Segment non musical\", allez dans les options de l'extension et activez cette catégorie. Ensuite, vous pourrez soumettre ce segment en tant que \"Segment non musical\" au lieu de sponsor. Lisez les instructions en cas de confusion."
@@ -732,6 +735,9 @@
"hideForever": {
"message": "Cacher pour toujours"
},
"warningChatInfo": {
"message": "Vous avez reçu un avertissement et ne pouvez pas soumettre de segments temporairement. Cela signifie que nous avons remarqué que vous commettiez des erreurs courantes qui ne sont pas malveillantes. Veuillez simplement confirmer que vous comprenez les règles et nous supprimerons l'avertissement. Vous pouvez également rejoindre cette discussion en utilisant discord.gg/SponsorBlock ou matrix.to/#/#sponsor:ajay.app"
},
"voteRejectedWarning": {
"message": "Le vote a été rejeté en raison d'un avertissement. Cliquez pour ouvrir un chat et y mettre fin , ou revenez plus tard lorsque vous avez le temps.",
"description": "This is an integrated chat panel that will appearing allowing them to talk to the Discord/Matrix chat without leaving their browser."
@@ -804,5 +810,23 @@
},
"LearnMore": {
"message": "En savoir plus"
},
"CopyDownvoteButtonInfo": {
"message": "Vote négatif et crée une copie locale que vous pouvez soumettre à nouveau"
},
"OpenCategoryWikiPage": {
"message": "Ouvrez la page wiki de cette catégorie."
},
"CopyAndDownvote": {
"message": "Copier et voter contre"
},
"ContinueVoting": {
"message": "Continuer à voter"
},
"ChangeCategoryTooltip": {
"message": "Cela s'appliquera instantanément à vos segments"
},
"SponsorTimeEditScrollNewFeature": {
"message": "Utilisez la molette de votre souris en survolant la boîte d'édition pour ajuster rapidement le minutage. Les combinaisons de touches Ctrl ou Shift peuvent être utilisées pour affiner les modifications."
}
}

View File

@@ -52,6 +52,9 @@
"reskip": {
"message": "Preskoči opet"
},
"unmute": {
"message": "Uključi zvuk"
},
"paused": {
"message": "Pauzirano"
},
@@ -79,6 +82,15 @@
"sponsorEnd": {
"message": "Isječak završava sada"
},
"sponsorCancel": {
"message": "Otkaži Kreiranje Segmenta"
},
"noVideoID": {
"message": "Nijedan YouTube video nije pronađen.\nAko ovo nije točno, osvježite karticu."
},
"refreshSegments": {
"message": "Osvježi segmente"
},
"success": {
"message": "Uspjeh!"
},
@@ -97,15 +109,33 @@
"openPopup": {
"message": "Otvori okvir SponsorBlock"
},
"closePopup": {
"message": "Zatvori izbornik"
},
"SubmitTimes": {
"message": "Podnesi isječke"
},
"submitCheck": {
"message": "Jesi li siguran da želiš unijeti ovo?"
},
"whitelistChannel": {
"message": "Dopusti kanal"
},
"removeFromWhitelist": {
"message": "Izbaci kanal iz bijele liste"
},
"voteOnTime": {
"message": "Glasaj za isječak"
},
"Submissions": {
"message": "Podnesci"
},
"savedPeopleFrom": {
"message": "Sačuvali ste ljude od"
},
"viewLeaderboard": {
"message": "Ljestvica"
},
"recordTimesDescription": {
"message": "Pošalji"
},
@@ -113,21 +143,54 @@
"message": "Uređivanje dijela prikazat će se nakon što pritisneš gumb za slanje",
"description": "Appears in the popup to inform them that editing has been moved to the video player."
},
"popupHint": {
"message": "Savjet: Možete namjestiti tipke za podnošenje u opcijama"
},
"clearTimesButton": {
"message": "Očisti vremena"
},
"submitTimesButton": {
"message": "Unesi vremena"
},
"publicStats": {
"message": "Ovo se koristi na stranici sa javnim statistikama da se pokaže koliko se pridonijeli. Pogledajte"
},
"Username": {
"message": "Korisničko ime"
},
"setUsername": {
"message": "Postavi korisničko ime"
},
"copyPublicID": {
"message": "Kopiraj javni UserID"
},
"discordAdvert": {
"message": "Pridružite nam se u službenoj Discord zajednici i pošaljite svoje prijedloge i povrate informacije!"
},
"hideThis": {
"message": "Sakrijte ovo"
},
"Options": {
"message": "Opcije"
},
"showButtons": {
"message": "Pokažite gumbove na YouTube Player-u"
},
"hideButtons": {
"message": "Sakrite gumbove na YouTube Player-u"
},
"hideButtonsDescription": {
"message": "Ovo sakrije gumbove za pridonose segmenta za preskočiti koje se pokažu na YouTuve Player-u."
},
"showSkipButton": {
"message": "Ostavite gumb za preskakanje"
},
"showInfoButton": {
"message": "Pokažite gumb za Informacije na YouTube Player-u"
},
"hideInfoButton": {
"message": "Sakrijte gumb za Informacije na YouTube Player-u"
},
"showSkipNotice": {
"message": "Pokaži obavijest nakon preskakanja isječka"
},
@@ -309,9 +372,6 @@
"downvoteDescription": {
"message": "Neispravno/krivo vrijeme"
},
"incorrectCategory": {
"message": "Kriva kategorija"
},
"nonMusicCategoryOnMusic": {
"message": "Ovaj je video kategoriziran kao glazba. Je li stvarno ima sponzora? Ako je ovo zapravo „Ne-glazbeni segment”, otvori opcije proširenja i aktiviraj ovu kategoriju. Zatim ovaj segment možeš posalti kao „Ne-glazbeni” umjesto sponzora. Pročitaj smjernice ako nešto nije jasno."
},

View File

@@ -52,6 +52,9 @@
"reskip": {
"message": "Újra-átugrás"
},
"unmute": {
"message": "Némítás feloldása"
},
"paused": {
"message": "Szüneteltetve"
},
@@ -158,6 +161,9 @@
"setUsername": {
"message": "Felhasználónév megadása"
},
"copyPublicID": {
"message": "Nyilvános UserID másolása"
},
"discordAdvert": {
"message": "Csatlakozzon a hivatalos discord szerverhez, hogy javaslatokat és visszajelzést adhasson!"
},
@@ -176,6 +182,9 @@
"hideButtonsDescription": {
"message": "Ez elrejti az átugrandó szegmensek megjelöléséhez használt gombokat a YouTube lejátszón."
},
"showSkipButton": {
"message": "Kiemeléshez ugrás gomb maradjon a lejátszón"
},
"showInfoButton": {
"message": "Info gomb mutatása a YouTube lejátszón"
},
@@ -197,6 +206,9 @@
"whatViewTracking": {
"message": "Ez a funkció követi, mely szegmenseket ugrotta át, hogy más felhasználók megtudhassák mennyit segítettek a bejelentéseik és a szavazatokkal együtt egy mértékegységként van használva, hogy ne kerülhessen spam az adatbázisba. A bővítmény küld egy üzenetet a szervernek, minden alkalommal, mikor átugrik egy szegmenst. Remélhetőleg nem sokan állítják át ezt a beállítást, hogy a számok pontosak maradhassanak. :)"
},
"enableViewTrackingInPrivate": {
"message": "Átugrások számlálásának engedélyezése privát/inkognitó füleken"
},
"enableQueryByHashPrefix": {
"message": "Lekérdezés Hash előtaggal"
},
@@ -215,6 +227,21 @@
"showSkipNotice": {
"message": "Jelezzen, ha egy szegmens át lett ugorva"
},
"noticeVisibilityMode0": {
"message": "Teljes méretű átugrási értesítők"
},
"noticeVisibilityMode1": {
"message": "Kis méretű átugrási értesítők Auto átugrás esetén"
},
"noticeVisibilityMode2": {
"message": "Csak kis méretű átugrási értesítők"
},
"noticeVisibilityMode3": {
"message": "Halvány átugrási értesítők Auto átugrás esetén"
},
"noticeVisibilityMode4": {
"message": "Csak halvány átugrási értesítők"
},
"longDescription": {
"message": "A SponsorBlock-al átugorhatja a szponzorokat, introkat, outrokat, feliratkozás emlékeztetőket és a YouTube videók többi idegesítő részeit. A SponsorBlock egy közösség által vezérelt böngészőbővítmény, ami lehetővé tesz bárkit arra, hogy megjelölhesse egy szponzor vagy más szegmens kezdő és végpontjait. Ha megosztja ezt az információt, mindenki más ennek a bővítménynek a birtokában egyenesen átugorja majd ezt a szponzorszegmenst. Emellett például a zene videók nem-zene részei is átugorhatóak.",
"description": "Full description of the extension on the store pages."
@@ -238,6 +265,9 @@
"setSkipShortcut": {
"message": "Billentyű beállítása szegmens átugráshoz"
},
"setStartSponsorShortcut": {
"message": "Billentyű beállítása a szegmens kezdéséhez/befejezéséhez"
},
"setSubmitKeybind": {
"message": "Billentyű beállítása a beküldés gombhoz"
},
@@ -269,9 +299,31 @@
"skip": {
"message": "Átugrás"
},
"mute": {
"message": "Némítás"
},
"skip_category": {
"message": "Átugorja ezt: {0}?"
},
"mute_category": {
"message": "{0} némítása?"
},
"skip_to_category": {
"message": "Ugrás ide: {0}?",
"description": "Used for skipping to things (Skip to Highlight)"
},
"skipped": {
"message": "{0} átugorva",
"description": "Example: Sponsor Skipped"
},
"muted": {
"message": "{0} némítva",
"description": "Example: Sponsor Muted"
},
"skipped_to_category": {
"message": "Ide ugorva: {0}",
"description": "Used for skipping to things (Skipped to Highlight)"
},
"disableAutoSkip": {
"message": "Auto átugrás kikapcsolása"
},
@@ -320,6 +372,9 @@
"changeUserID": {
"message": "UserID importálása / exportálása"
},
"whatChangeUserID": {
"message": "Ez privát információnak minősül. Ez olyan, mint egy jelszó, így nem ajánlott megosztani senkivel. Ha valakinek birtokában van, megszemélyesítheti önt. Ha a nyilvános userID-ját keresi, kattintson a vágólap ikonra a felugró ablakban."
},
"setUserID": {
"message": "UserID beállítása"
},
@@ -335,9 +390,22 @@
"supportOtherSites": {
"message": "Harmadik fél Youtube oldalainak támogatása"
},
"supportOtherSitesDescription": {
"message": "Harmadik fél YouTube oldalainak támogatása. A támogatás bekapcsolásához el kell fogadnia az extra engedélyeket. NEM működik inkognitó módban Chrome-ban és egyéb Chromium változatokban.",
"description": "This replaces the 'supports Invidious' option because it now works on other YouTube sites such as Cloudtube"
},
"supportedSites": {
"message": "Támogatott oldalak: "
},
"optionsInfo": {
"message": "Invidious támogatás engedélyezése, autoátugrás kikapcsolása, gombok eltűntetése és több."
},
"addInvidiousInstance": {
"message": "Harmadik fél kliens példányának hozzáadása"
},
"addInvidiousInstanceDescription": {
"message": "Egyedi példány hozzáadása. Formátuma CSAK a domain legyen. Például: invidious.ajay.app"
},
"add": {
"message": "Hozzáadás"
},
@@ -359,6 +427,12 @@
"minDurationDescription": {
"message": "A beállított értéknél rövidebb szegmenseket nem ugorja át és nem jeleníti meg a lejátszó."
},
"skipNoticeDuration": {
"message": "Átugrási értesítés hossza (másodpercek):"
},
"skipNoticeDurationDescription": {
"message": "Az átugrási értesítés ennyi ideig marad a képernyőn. Manuális átugrásnál tovább is látható maradhat."
},
"shortCheck": {
"message": "A következő szegmens rövidebb, mint az Ön által beállított minimális időtartam. Ez azt jelentheti, hogy már beküldhették, csak emiatt az opció miatt Önnek figyelmen kívül marad. Biztosan beküldi?"
},
@@ -486,9 +560,15 @@
"category_preview": {
"message": "Előzetes/Ismétlés"
},
"category_preview_description": {
"message": "Az előző részekben történtek rövid ismétlése, vagy a videó további tartalmának előzetese. Összevágott jelenetekhez, nem szóbeli összegzéshez."
},
"category_music_offtopic": {
"message": "Zene: nem-zene szegmens"
},
"category_music_offtopic_description": {
"message": "Csak videóklipekhez. Ezt csak videóklipek olyan részeihez szabad használni, amiket nem fed le a többi kategória."
},
"category_music_offtopic_short": {
"message": "Nem-Zene"
},
@@ -516,9 +596,28 @@
"disable": {
"message": "Kikapcsol"
},
"autoSkip_POI": {
"message": "Auto ugrás a kezdetéhez"
},
"manualSkip_POI": {
"message": "Kérdezzen rá a videó betöltésekor"
},
"showOverlay_POI": {
"message": "Megjelenítés a keresősávban"
},
"autoSkipOnMusicVideos": {
"message": "Minden szegmens automatikus átugrása, ha van nem-zene szegmens"
},
"muteSegments": {
"message": "Szegmensek engedélyezése, amelyek lenémítják a hangot az átugrás helyett"
},
"colorFormatIncorrect": {
"message": "A szín helytelenül van formázva. Egy 3 vagy 6 számjegyből álló hex kódnak kell lennie egy kettőskereszttel az elején."
},
"previewColor": {
"message": "Beküldetlen színe",
"description": "Referring to submissions that have not been sent to the server yet."
},
"seekBarColor": {
"message": "Keresősáv színe"
},
@@ -547,6 +646,13 @@
"chooseACategory": {
"message": "Válasszon kategóriát"
},
"enableThisCategoryFirst": {
"message": "Hogy \"{0}\" kategóriájú szegmenst küldhessen be, először engedélyeznie kell a beállításokban. Most átirányításra kerül a beállításokhoz.",
"description": "Used when submitting segments to only let them select a certain category if they have it enabled in the options."
},
"poiOnlyOneSegment": {
"message": "Figyelem: Az ilyen típusú szegmensekből egyszerre csak egy lehet aktív. Több beküldése esetén véletlenszerűen az egyik fog megjelenni."
},
"youMustSelectACategory": {
"message": "Minden szegmenshez kategóriát kell választania beküldés előtt!"
},
@@ -559,9 +665,28 @@
"hiddenDueToDuration": {
"message": "elrejtve: túl rövid"
},
"channelDataNotFound": {
"description": "This error appears in an alert when they try to whitelist a channel and the extension is unable to determine what channel they are looking at.",
"message": "A csatorna ID még nem került betöltésre. Ha beágyazott videót használ, próbálja meg inkább a YouTube oldalon keresztül. Ezt okozhatja még a YouTube elrendezésének változása is. Ha így gondolja, hagyjon egy kommentet itt:"
},
"videoInfoFetchFailed": {
"message": "Úgy tűnik, valami korlátozza a SponsorBlock hozzáférését a videó adataihoz. További információkért látogasson el ide: https://github.com/ajayyy/SponsorBlock/issues/741 (angol nyelvű)."
},
"youtubePermissionRequest": {
"message": "Úgy tűnik, a SponsorBlock nem tud csatlakozni a YouTube API-hoz. A javításhoz fogadja el a megjelenő engedélykérést, várjon néhány másodpercet, majd töltse újra az oldalt."
},
"acceptPermission": {
"message": "Engedély jóváhagyása"
},
"permissionRequestSuccess": {
"message": "Engedélykérés sikeres!"
},
"permissionRequestFailed": {
"message": "Engedélykérés sikertelen. Nem nyomott az elutasításra?"
},
"adblockerIssueWhitelist": {
"message": "Ha nem sikerül megoldani a problémát, kapcsolja ki a \"Csatorna ellenőrzése átugrás előtt\" opciót, mert a SponsorBlock nem tudja megszerezni a csatorna-információkat ehhez a videóhoz"
},
"forceChannelCheck": {
"message": "Csatorna ellenőrzése átugrás előtt"
},
@@ -575,7 +700,7 @@
"message": "Helytelen/rossz időzítés"
},
"incorrectCategory": {
"message": "Hibás kategória"
"message": "Kategória módosítása"
},
"nonMusicCategoryOnMusic": {
"message": "Ez a videó zeneként van kategorizálva. Biztos benne, hogy ennek van szponzora? Ha ez valójában egy \"nem-zene szegmens\", nyissa meg a bővítmény beállításait és kapcsolja be azt a kategóriát. Ezt követően elküldheti ezt a szegmenst \"nem-zene\"-ként szponzor helyett. Amennyiben nem érti, kérjük olvassa el az irányelveket."
@@ -603,28 +728,105 @@
"message": "Értettem",
"description": "Used as the button to dismiss a tooltip"
},
"experiementOptOut": {
"message": "Minden további kísérlet elutasítása",
"description": "This is used in a popup about a new experiment to get a list of unlisted videos to back up since all unlisted videos uploaded before 2017 will be set to private."
},
"hideForever": {
"message": "Eltüntetés örökre"
},
"warningChatInfo": {
"message": "Ön figyelmeztetést kapott, és ideiglenesen nem tud szegmenseket beküldeni. Ez azt jelenti, hogy észrevettük, hogy néhány ártalmatlan gyakori hibát vétett. Kérjük erősítse meg, hogy megértette a szabályokat és eltávolítjuk a figyelmeztetést. Ehhez a beszélgetéshez csatlakozhat a discord.gg/SponsorBlock vagy matrix.to/#/#sponsor:ajay.app címeken is."
},
"voteRejectedWarning": {
"message": "Szavazás visszautasítva figyelmeztetés miatt. Kattintson, hogy megnyisson egy beszélgetést a tisztázásához, vagy jöjjön vissza később, amikor ideje van.",
"description": "This is an integrated chat panel that will appearing allowing them to talk to the Discord/Matrix chat without leaving their browser."
},
"Donate": {
"message": "Támogatás"
},
"hideDonationLink": {
"message": "Támogatás link elrejtése"
},
"helpPageThanksForInstalling": {
"message": "Köszönjük, hogy telepítette a SponsorBlockot."
},
"helpPageReviewOptions": {
"message": "Kérjük, nézze át az alábbi beállításokat"
},
"helpPageFeatureDisclaimer": {
"message": "Sok funkció le van tiltva alapból. Ha át akar ugrani bevezetőket, záróképernyőket, Invidioust használna, stb., engedélyezze őket alább. Lehetőség van a felület különböző elemeinek elrejtésére/megjelenítésére is."
},
"helpPageHowSkippingWorks": {
"message": "Az átugrás működése"
},
"helpPageHowSkippingWorks1": {
"message": "A videók szegmensei automatikusan átugrásra kerülnek, ha szerepelnek az adatbázisban. Megnyithatja a felugró ablakot a bővítmény ikonjára kattintva, hogy megtekinthesse őket."
},
"helpPageHowSkippingWorks2": {
"message": "Ahányszor átugrik egy szegmenst, kapni fog egy értesítést. Ha rossznak tűnik az időzítés, szavazza le a leszavazás gombra kattintva! A felugró ablakban is szavazhat."
},
"Submitting": {
"message": "Küldés"
},
"helpPageSubmitting1": {
"message": "Beküldeni lehet a felugró ablakban a \"Szegmens eleje\" gombra kattintva, vagy a videó lejátszón lévő gombokkal."
},
"helpPageSubmitting2": {
"message": "A lejátszás gomb megnyomása jelezte a szegmens kezdetét és a stop gomb megnyomása jelzi a végét. Több szponzort is előkészíthet, mielőtt a beküldésre nyomna. A feltöltés gombra kattintva beküldésre kerülnek a szegmensek. A szemetesre kattintva kitörlődnek."
},
"Editing": {
"message": "Szerkesztés"
},
"helpPageEditing1": {
"message": "Ha hibázott, szerkesztheti, vagy törölheti a szegmenseit, a felfele nyílra kattintást követően."
},
"helpPageTooSlow": {
"message": "Ez túl lassú"
},
"helpPageTooSlow1": {
"message": "Vannak gyorsbillentyűk is, ha használni szeretné őket. Nyomja meg a pontosvessző billentyűt egy szponzor szegmens elejének/végének jelzéséhez és nyomja meg a vesszőt a beküldéshez. Ezek módosíthatók a beállításokban. Ha nem QWERTY-t használ, valószínűleg szükséges lesz megváltoztatnia a billentyűket."
},
"helpPageCopyOfDatabase": {
"message": "Szerezhetek egy másolatot az adatbázisról? Mi történik, ha eltűnik a fejlesztő?"
},
"helpPageCopyOfDatabase1": {
"message": "Az adatbázis nyilvános, és elérhető itt:"
},
"helpPageCopyOfDatabase2": {
"message": "A forráskód szabadon elérhető. Tehát még ha valami történne is velem, a beküldések nem vesznek el."
},
"helpPageNews": {
"message": "Hírek és hogyan készül"
},
"helpPageSourceCode": {
"message": "Hol szerezhetem meg a forráskódot?"
},
"Credits": {
"message": "Készítők"
},
"highlightNewFeature": {
"message": "Új! Juss a videó lényegéhez csak egy kattintással, az új kiemelés kategóriával"
},
"LearnMore": {
"message": "Tudj meg többet"
},
"CopyDownvoteButtonInfo": {
"message": "Leszavazza és készít egy helyi másolatot, amit beküldhet"
},
"OpenCategoryWikiPage": {
"message": "A kategória wiki lapjának megnyitása."
},
"CopyAndDownvote": {
"message": "Másol és leszavaz"
},
"ContinueVoting": {
"message": "Szavazás folytatása"
},
"ChangeCategoryTooltip": {
"message": "Ez azonnal érvényes lesz a szegmenseire"
},
"SponsorTimeEditScrollNewFeature": {
"message": "Használja egérgörgőjét a szerkesztő mező fölött, hogy gyorsan módosíthassa az időt. A ctrl vagy shift billentyűk kombinációjával finomhangolhatja a változás mértékét."
}
}

View File

@@ -53,7 +53,7 @@
"message": "Lewati Ulang"
},
"unmute": {
"message": "Bunyikan"
"message": "Batalkan bisu"
},
"paused": {
"message": "Dijeda"
@@ -89,7 +89,7 @@
"message": "Video YouTube tidak ditemukan.\nJika terjadi kesalahan, segarkan halaman."
},
"refreshSegments": {
"message": "Segarkan segmen"
"message": "Perbarui segmen"
},
"success": {
"message": "Sukses!"
@@ -182,6 +182,9 @@
"hideButtonsDescription": {
"message": "Ini akan menyembunyikan tombol yang muncul di pemutar YouTube untuk mengirimkan segmen yang dilewati."
},
"showSkipButton": {
"message": "Tetap lewati ke tombol Highlight di Pemutar"
},
"showInfoButton": {
"message": "Tampilkan Tombol Info Di Pemutar Video YouTube"
},
@@ -207,7 +210,7 @@
"message": "Aktifkan Pelacakan Jumlah Lewati Pada Tab Privat/Penyamaran"
},
"enableQueryByHashPrefix": {
"message": "Query By Hash Prefix"
"message": "Kueri dengan Hash Prefix"
},
"whatQueryByHashPrefix": {
"message": "Daripada meminta segmen dari server menggunakan videoID, 4 huruf pertama dari hash dari videoID dikirim. Server akan mengirim kembali data untuk semua video dengan hash yang mirip."
@@ -224,6 +227,21 @@
"showSkipNotice": {
"message": "Tampilkan pemberitahuan setelah melewati segmen"
},
"noticeVisibilityMode0": {
"message": "Lewati maklumat ukuran penuh"
},
"noticeVisibilityMode1": {
"message": "Maklumat lewati kecil untuk lewati otomatis"
},
"noticeVisibilityMode2": {
"message": "Lewati semua maklumat kecil"
},
"noticeVisibilityMode3": {
"message": "Pudar maklumat lewati untuk semua lewati otomatis"
},
"noticeVisibilityMode4": {
"message": "Lewati semua maklumat pudar"
},
"longDescription": {
"message": "SponsorBlock membuat anda melewati sponsor, intro, outro, pengingat berlangganan dan segmen mengganggu lainnya di video YouTube. SponsorBlock adalah ekstensi browser crowdsourced yang membolehkan siapa saja mengirim waktu awal dan akhir dari segmen sponsor dan segmen video YouTube lainnya. Setelah seseorang mengirim informasi ini, orang lain yang memakai ekstensi ini akan melewati segmen sponsor di video yang sama. Anda juga dapat melewati bagian non-musik di musik video.",
"description": "Full description of the extension on the store pages."
@@ -383,7 +401,10 @@
"message": "Aktifkan dukungan Invidious, nonaktifkan lewati otomatis, tombol sembunyi dan lainnya."
},
"addInvidiousInstance": {
"message": "Tambah Instance Klien Pihak Ketiga"
"message": "Tambah Instansi Klien Pihak Ketiga"
},
"addInvidiousInstanceDescription": {
"message": "Tambahkan instansi khusus. Ini harus diformat Hanya dengan domain. Contoh: invidious.ajay.app"
},
"add": {
"message": "Tambah"
@@ -406,6 +427,12 @@
"minDurationDescription": {
"message": "Segmen yang lebih kecil dari nilai yang diatur tidak akan dilewati atau tampil di pemutar."
},
"skipNoticeDuration": {
"message": "Lewati maklumat berdurasi (detik):"
},
"skipNoticeDurationDescription": {
"message": "Maklumat lewati akan tetap di layar setidaknya selama ini. Untuk lewati manual, mungkin akan terlihat lebih lama."
},
"shortCheck": {
"message": "Submisi ini lebih pendek dari opsi durasi minimalmu. Ini dapat berarti ini sudah dikirim, dan hanya akan diabaikan karena opsi ini. Apakah anda yakin ingin mengirim?"
},
@@ -545,6 +572,12 @@
"category_music_offtopic_short": {
"message": "Non-Musik"
},
"category_poi_highlight": {
"message": "Sorotan"
},
"category_poi_highlight_description": {
"message": "Bagian video yang banyak orang lihat. Sama untuk komentar \"Video dimulai di x\"."
},
"category_livestream_messages": {
"message": "Livestream: Baca Pesan/Donasi"
},
@@ -563,6 +596,9 @@
"disable": {
"message": "Nonaktif"
},
"autoSkip_POI": {
"message": "Otomatis lewati ke awal"
},
"manualSkip_POI": {
"message": "Tanya saat video dimuat"
},
@@ -572,6 +608,9 @@
"autoSkipOnMusicVideos": {
"message": "Lewati semua segmen secara otomatis ketika ada segmen non-music"
},
"muteSegments": {
"message": "Perbolehkan segmen untuk bisu daripada melewati"
},
"colorFormatIncorrect": {
"message": "Warna anda tidak diformat dengan benar. Harusnya terdiri dari 3 atau 6 digit kode heksa dengan tagar di awal."
},
@@ -611,6 +650,9 @@
"message": "Untuk mengirimkan segmen dengan kategori \"{0}\", Anda harus mengaktifkannya di opsi. Anda akan diarahkan ke opsi sekarang.",
"description": "Used when submitting segments to only let them select a certain category if they have it enabled in the options."
},
"poiOnlyOneSegment": {
"message": "Perhatian: Tipe segmen ini hanya bisa maksimum aktif satu kali. Mengirimkan beberapa dapat mengakibatkan muncul pada kondisi acak."
},
"youMustSelectACategory": {
"message": "Anda harus memilih kategori untuk semua segmen yang anda kirimkan!"
},
@@ -657,9 +699,6 @@
"downvoteDescription": {
"message": "Salah, Waktu Tidak Tepat"
},
"incorrectCategory": {
"message": "Salah Kategori"
},
"nonMusicCategoryOnMusic": {
"message": "Video ini dikategorikan sebagai musik. Apakah anda yakin ini berisi sponsor? Jika ini ternyata adalah \"Segmen non-musik\", buka pengaturan ekstensi dan aktifkan kategorinya. Lalu, anda bisa mengirim segmen ini sebagai \"Non-musik\" bukannya sponsor. Harap membaca panduan jika anda kebingungan."
},
@@ -686,9 +725,20 @@
"message": "Mengerti",
"description": "Used as the button to dismiss a tooltip"
},
"experiementOptOut": {
"message": "Tidak ikut eksperimen masa depan",
"description": "This is used in a popup about a new experiment to get a list of unlisted videos to back up since all unlisted videos uploaded before 2017 will be set to private."
},
"hideForever": {
"message": "Sembunyikan selamanya"
},
"warningChatInfo": {
"message": "Anda mendapatkan peringatan dan tidak bisa mengirim segmen sementara. Ini dikarenakan kami melihat kamu melakukan beberapa kesalahan yang umum, mohon konfirmasi bahwa kamu mengerti perundangan dan kami akan hapus peringatan. Kamu bisa bergabung ke obrolan menggunakan discord.gg/SponsorBlock atau matrix.io/#/#sponsor:ajay.app"
},
"voteRejectedWarning": {
"message": "Suara ditolak karena peringatan. Klik untuk buka obrolan untuk menyelesaikannya, atau kembali beberapa saat lagi ketika ada waktu.",
"description": "This is an integrated chat panel that will appearing allowing them to talk to the Discord/Matrix chat without leaving their browser."
},
"Donate": {
"message": "Donasi"
},
@@ -701,7 +751,64 @@
"helpPageReviewOptions": {
"message": "Haram ditinjau opsi di bawah ini"
},
"helpPageFeatureDisclaimer": {
"message": "Banyak fitur yang dinonaktifkan secara bawaan. Jika kamu ingin lewati mula, akhir, gunakan Invidious, dll, aktifkan mereka dibawah ini.\nKamu bisa menyembunyikan/menghadirkan elemen UI."
},
"helpPageHowSkippingWorks": {
"message": "Cara kerja melewati segmen"
},
"helpPageHowSkippingWorks1": {
"message": "Segmen video akan otomatis dilewati jika ditemukan di databasis. Kamu bisa buka munculan dengan klik ikon ekstensi untuk mendapatkan pratinjau apa adanya."
},
"helpPageHowSkippingWorks2": {
"message": "Kapanpun kamu melewati segmen, kamu akan mendapatkan maklumat. Jika waktu terlihat salah dapat menyuarakan turun dengan klik turun-suara! Kamu juga bisa menyuarakan di maklumat."
},
"Submitting": {
"message": "Mengirim"
},
"helpPageSubmitting1": {
"message": "Mengirim bisa baik dilakukan di maklumat dengan menekan tombol \"Mulai Segmen Sekarang\" atau di pemutar video dengan tombol di pemutar."
},
"helpPageSubmitting2": {
"message": "Klik tombol putar indikasikan memulai segmen dan klik tombol ikon stop indikasikan mengakhiri. Kamu bisa persiapkan beberapa sponsor sebelum menekan kirim. Klik tombol unggah akan mengirimkan. Klik tombol sampah akan menghapuskan."
},
"Editing": {
"message": "Sunting"
},
"helpPageEditing1": {
"message": "Jika kamu mengacaukan, kamu bisa sunting atau hapus segmen setelah klik tombol panah atas."
},
"helpPageTooSlow": {
"message": "Ini terlalu lambat"
},
"helpPageTooSlow1": {
"message": "Terdapat tombol pintas jika kamu ingin menggunakannya. Tekan tombol semikolon untuk indikasi mulai/akhir segmen sponsor dan tekan tombol kutip untuk mengirimkan. Ini bisa diganti di opsi. Jika kamu tidak menggunakan QWERTY, kamu dimungkinkan harus mengubah tombol."
},
"helpPageCopyOfDatabase": {
"message": "Bisakah saya mendapatkan salinan Databasis? Apa yang terjadi jika kamu tiada?"
},
"helpPageCopyOfDatabase1": {
"message": "Databasis adalah publik dan tersedia di"
},
"helpPageCopyOfDatabase2": {
"message": "Sumber kode tersedia secara bebas. Jadi, jika sesuatu terjadi pada saya, pengajuan kamu tidak akan hilang."
},
"helpPageNews": {
"message": "Berita dan bagaimana ini diciptakan"
},
"helpPageSourceCode": {
"message": "Dimana saya mendapatkankan sumber kode?"
},
"Credits": {
"message": "Kredit"
},
"highlightNewFeature": {
"message": "Baru! Dapat ke poin video dengan satu klik dengan kategori highlight terbaru"
},
"LearnMore": {
"message": "Pelajari Lebih Lanjut"
},
"SponsorTimeEditScrollNewFeature": {
"message": "Gunakan roda mouse ketika berada di kotak edit untuk mengatur waktu dengan cepat. Kombinasi dengan tombol [Ctrl + Shift] bisa digunakan untuk perubahan yang halus."
}
}

View File

@@ -696,9 +696,6 @@
"downvoteDescription": {
"message": "Tempo Non Corretto/Errato"
},
"incorrectCategory": {
"message": "Categoria Errata"
},
"nonMusicCategoryOnMusic": {
"message": "Questo video è classificato come musica. Sei sicuro che questo video contenga uno sponsor? Se questo è in realtà un \"Segmento Non-Musica\", apri le opzioni di questa estensione e abilita questa categoria. Quindi, è possibile inviare questo segmento come \"Non-Music\" invece di sponsor. Si prega di leggere la guida se si è confusi."
},

View File

@@ -52,6 +52,9 @@
"reskip": {
"message": "再スキップ"
},
"unmute": {
"message": "ミュート解除"
},
"paused": {
"message": "一時停止中"
},
@@ -80,13 +83,13 @@
"message": "セグメント終了を記録"
},
"sponsorCancel": {
"message": "区間の作成を取り止める"
"message": "セグメントの作成を取り消す"
},
"noVideoID": {
"message": "YouTube動画が見つかりませんでした。\nこれが正しくない場合は、タブを再読み込みしてください。"
},
"refreshSegments": {
"message": "区域を更新"
"message": "セグメントを更新"
},
"success": {
"message": "成功しました!"
@@ -158,6 +161,9 @@
"setUsername": {
"message": "ユーザー名を設定"
},
"copyPublicID": {
"message": "パブリックユーザIDをコピー"
},
"discordAdvert": {
"message": "公式Discordサーバーに参加して意見やフィードバックをお寄せください"
},
@@ -176,6 +182,9 @@
"hideButtonsDescription": {
"message": "YouTube再生画面のセグメント提出ボタンを非表示にします。"
},
"showSkipButton": {
"message": "プレイヤーの「ハイライトまでスキップ」ボタン表示を維持する"
},
"showInfoButton": {
"message": "YouTubeプレーヤーの情報ボタンを表示する"
},
@@ -219,19 +228,19 @@
"message": "セグメントがスキップされた後に通知を表示する"
},
"noticeVisibilityMode0": {
"message": "飛び越し通知(全体)"
"message": "標準サイズのスキップ通知"
},
"noticeVisibilityMode1": {
"message": "自動飛び越し通知(小)"
"message": "自動スキップ通知を小型化"
},
"noticeVisibilityMode2": {
"message": "すべての飛び越し通知(小)"
"message": "すべてのスキップ通知を小型化"
},
"noticeVisibilityMode3": {
"message": "表示の終了した自動飛び越し通知"
"message": "自動スキップ通知を透過"
},
"noticeVisibilityMode4": {
"message": "表示の終了した全ての飛び越し通知"
"message": "すべてのスキップ通知を透過"
},
"longDescription": {
"message": "SponsorBlockはスポンサー、イントロ、アウトロ、チャンネル登録のお願いなど、YouTube動画の煩わしい部分をスキップします。SponsorBlockはYouTube動画のスポンサー付きセグメントなどの開始時間と終了時間を誰でも投稿できる、クラウドソースのブラウザ拡張機能です。一人がセグメントの情報を送信すると、この拡張機能を使用している他の全員が、スポンサー付きセグメントをスキップできるようになります。また、ミュージックビデオの音楽がない部分をスキップすることもできます。",
@@ -290,9 +299,15 @@
"skip": {
"message": "スキップ"
},
"mute": {
"message": "ミュート"
},
"skip_category": {
"message": "{0} をスキップしますか?"
},
"mute_category": {
"message": "{0} をミュートしますか?"
},
"skip_to_category": {
"message": "{0}まで飛び越しますか?",
"description": "Used for skipping to things (Skip to Highlight)"
@@ -301,6 +316,10 @@
"message": "{0}を飛び越しました",
"description": "Example: Sponsor Skipped"
},
"muted": {
"message": "{0} ミュート済み",
"description": "Example: Sponsor Muted"
},
"skipped_to_category": {
"message": "{0}まで飛び越しました",
"description": "Used for skipping to things (Skipped to Highlight)"
@@ -353,6 +372,9 @@
"changeUserID": {
"message": "ユーザーIDのインポート/エクスポート"
},
"whatChangeUserID": {
"message": "この情報を誰にも開示しないでください。これはパスワードのように、誰とも共有するべきではありません。 誰かがこれを持っている場合、あなたになりすますことができます。パブリックユーザーIDを探している場合は、ポップアップのクリップボードアイコンをクリックしてください。"
},
"setUserID": {
"message": "ユーザーIDを設定"
},
@@ -551,10 +573,10 @@
"message": "音楽以外の部分"
},
"category_poi_highlight": {
"message": "強調表示"
"message": "ハイライト"
},
"category_poi_highlight_description": {
"message": "ほとんどの人が必要としている動画の箇所。「xx:xx 開始」というようなコメントと類似。"
"message": "多くの人が求めている動画の部分。「動画はXからスタート」のようなコメントです。"
},
"category_livestream_messages": {
"message": "ライブ配信: 寄付/メッセージの読み上げ"
@@ -575,7 +597,7 @@
"message": "無効"
},
"autoSkip_POI": {
"message": "動画の開始時刻まで飛び越し"
"message": "冒頭へ自動スキップ"
},
"manualSkip_POI": {
"message": "動画を読み込んだ際に確認する"
@@ -586,6 +608,9 @@
"autoSkipOnMusicVideos": {
"message": "非音楽区域がある場合,全区域を自動的に飛び越す"
},
"muteSegments": {
"message": "スキップする代わりに音声をミュートしてセグメントを許可"
},
"colorFormatIncorrect": {
"message": "カラーコードの書式が間違っています。 #から始まる3桁または6桁の16進数コードでなければなりません。"
},
@@ -625,6 +650,9 @@
"message": "\"{0}\" のカテゴリでセグメントを送信するには、オプションでセグメントを有効にする必要があります。オプション画面にリダイレクトします。",
"description": "Used when submitting segments to only let them select a certain category if they have it enabled in the options."
},
"poiOnlyOneSegment": {
"message": "警告: このタイプのセグメントは一度に最大一つだけ有効にすることができます。複数送信するとランダムなものが表示されます。"
},
"youMustSelectACategory": {
"message": "送信するすべてのセグメントにカテゴリを選択する必要があります!"
},
@@ -672,7 +700,7 @@
"message": "不正確あるいは間違った時刻です"
},
"incorrectCategory": {
"message": "カテゴリが違います"
"message": "カテゴリーを変更してください"
},
"nonMusicCategoryOnMusic": {
"message": "この動画は音楽として分類されています。本当にこの動画にスポンサー部分がありますか? 本セグメントが本当に「音楽以外の区域」だった場合は、設定画面からこの分類を有効にしてください。その後、「スポンサー部分」の代わりに「音楽以外のセグメント」としてセグメントを提出できます。よく分からない場合は、ガイドラインを参照してください。"
@@ -707,6 +735,9 @@
"hideForever": {
"message": "二度と表示しない"
},
"warningChatInfo": {
"message": "警告のためにあなたは一時的にセグメントを提出することができなくなりました。これはあなたが悪意のない一般的なミスを犯していることに私たちが気づいた事を意味します、ルールを理解していることを確認していただければこの警告を解除します。discord.gg/SponsorBlock または matrix.to/#/#sponsor:ajay.app を使ってこのチャットに参加することもできます。"
},
"voteRejectedWarning": {
"message": "警告により投票が拒否されました。クリックして運営に連絡するか,少し時間を置いてからやりなおしてください。",
"description": "This is an integrated chat panel that will appearing allowing them to talk to the Discord/Matrix chat without leaving their browser."
@@ -738,9 +769,30 @@
"Submitting": {
"message": "提出中"
},
"helpPageSubmitting1": {
"message": "提出するにはポップアップの「セグメント開始を記録」ボタン、またはビデオプレーヤー内にあるボタンを押してください。"
},
"helpPageSubmitting2": {
"message": "再生ボタンをクリックするとセグメントの開始、停止アイコンをクリックすると終了となります。 複数のスポンサーを用意してから送信ボタンを押すことができます。アップロードボタンをクリックすると提出されます。ゴミ箱をクリックすると削除されます。"
},
"Editing": {
"message": "編集中"
},
"helpPageEditing1": {
"message": "もし失敗しても、上矢印ボタンをクリックすれば、セグメントを編集・削除することができます。"
},
"helpPageTooSlow": {
"message": "遅すぎます"
},
"helpPageTooSlow1": {
"message": "利用可能なホットキーがあります。セミコロンキーを押してスポンサーセグメントの開始/終了を示し、アポストロフィキーを押して送信します。これらはオプションで変更できます。QWERTYを使わない場合は、キーバインドを変更したほうがいいでしょう。"
},
"helpPageCopyOfDatabase": {
"message": "データベースのコピーを取得できますか? あなたがいなくなった場合はどうなりますか?"
},
"helpPageCopyOfDatabase1": {
"message": "データベースは公開されており、次の場所で利用できます:"
},
"helpPageCopyOfDatabase2": {
"message": "ソースコードは自由に利用できます。運営になにがあろうとも,あなたの貢献(提出された区域)が失われることはありません。"
},
@@ -753,7 +805,28 @@
"Credits": {
"message": "謝辞"
},
"highlightNewFeature": {
"message": "新機能! 新しいハイライトカテゴリを使用し、動画の要点にワンクリックで\n移動できます。"
},
"LearnMore": {
"message": "さらに詳しく"
},
"CopyDownvoteButtonInfo": {
"message": "反対票を投じ、再提出するためにローカルコピーを作成します。"
},
"OpenCategoryWikiPage": {
"message": "このカテゴリーのWikiページを開きます。"
},
"CopyAndDownvote": {
"message": "コピーして反対票を投じる"
},
"ContinueVoting": {
"message": "投票を続ける"
},
"ChangeCategoryTooltip": {
"message": "この変更は即座にあなたのセグメントに適用されます"
},
"SponsorTimeEditScrollNewFeature": {
"message": "編集ボックスにカーソルを合わせながらマウスホイールを使用すると、時間をすばやく調整できます。 CtrlキーまたはShiftキーの組み合わせを使用して変更を微調整できます。"
}
}

View File

@@ -700,7 +700,7 @@
"message": "잘못된 타이밍입니다"
},
"incorrectCategory": {
"message": "잘못된 카테고리입니다"
"message": "카테고리 변경"
},
"nonMusicCategoryOnMusic": {
"message": "이 영상은 음악 영상으로 분류됩니다. 정말로 스폰서가 있는 것이 확실한가요? 만약 음악 이외의 구간인 경우, 확장 옵션을 열어 이 카테고리를 활성화 하세요. 그리고, 이 구간을 스폰서 대신 음악이 아닌 구간으로 제출하세요. 헷갈릴 경우 가이드라인을 읽으세요."
@@ -810,5 +810,23 @@
},
"LearnMore": {
"message": "더보기"
},
"CopyDownvoteButtonInfo": {
"message": "반대에 투표한 뒤 다시 제출할 수 있도록 미제출 사본을 생성합니다"
},
"OpenCategoryWikiPage": {
"message": "해당 카테고리의 위키 페이지를 엽니다."
},
"CopyAndDownvote": {
"message": "복사 및 반대"
},
"ContinueVoting": {
"message": "계속 투표"
},
"ChangeCategoryTooltip": {
"message": "당신의 구간에 즉시 적용될 것입니다"
},
"SponsorTimeEditScrollNewFeature": {
"message": "편집 상자 위에 커서를 올린 채 스크롤하면 시간을 빠르게 조정할 수 있습니다. Ctrl이나 Shift 키를 누른 채로 스크롤하면 세밀한 조정이 가능합니다."
}
}

View File

@@ -554,9 +554,6 @@
"downvoteDescription": {
"message": "തെറ്റായ / തെറ്റായ സമയം"
},
"incorrectCategory": {
"message": "തെറ്റായ വിഭാഗം"
},
"nonMusicCategoryOnMusic": {
"message": "ഈ വീഡിയോയെ സംഗീതമായി വർഗ്ഗീകരിച്ചിരിക്കുന്നു. ഇതിന് ഒരു സ്പോൺസർ ഉണ്ടെന്ന് നിങ്ങൾക്ക് ഉറപ്പാണോ? ഇത് യഥാർത്ഥത്തിൽ \"സംഗീതേതര വിഭാഗമാണ്\" എങ്കിൽ, വിപുലീകരണ ഓപ്ഷനുകൾ തുറന്ന് ഈ വിഭാഗം പ്രാപ്തമാക്കുക. തുടർന്ന്, സ്പോൺസറിന് പകരം \"നോൺ-മ്യൂസിക്\" എന്ന് നിങ്ങൾക്ക് ഈ സെഗ്മെന്റ് സമർപ്പിക്കാൻ കഴിയും. നിങ്ങൾ ആശയക്കുഴപ്പത്തിലാണെങ്കിൽ ദയവായി മാർഗ്ഗനിർദ്ദേശങ്ങൾ വായിക്കുക."
},

View File

@@ -554,9 +554,6 @@
"downvoteDescription": {
"message": "Pemasaan Tidak Betul / Salah"
},
"incorrectCategory": {
"message": "Kategori Salah"
},
"nonMusicCategoryOnMusic": {
"message": "Video ini dikategorikan sebagai muzik. Adakah anda pasti ini mempunyai penaja? Sekiranya ini sebenarnya adalah \"Segmen Bukan Muzik\", buka pilihan peluasan dan aktifkan kategori ini. Kemudian, anda boleh menghantar segmen ini sebagai \"Bukan Muzik\" dan bukannya penaja. Sila baca panduan sekiranya anda keliru."
},

View File

@@ -700,7 +700,7 @@
"message": "Verkeerde timing"
},
"incorrectCategory": {
"message": "Verkeerde categorie"
"message": "Categorie wijzigen"
},
"nonMusicCategoryOnMusic": {
"message": "Deze video is gecategoriseerd als muziek. Weet u zeker dat dit een sponsor heeft? Als dit eigenlijk een \"niet-muzieksegment\" is, open dan de extensie-opties en schakel deze categorie in. Vervolgens kunt u dit segment indienen als \"niet-muziek\" in plaats van als sponsor. Lees de richtlijnen als u in de war bent."
@@ -810,5 +810,23 @@
},
"LearnMore": {
"message": "Meer informatie"
},
"CopyDownvoteButtonInfo": {
"message": "Doet een downvote en maakt een lokale kopie aan die u opnieuw kunt indienen"
},
"OpenCategoryWikiPage": {
"message": "Wikipagina van deze categorie openen."
},
"CopyAndDownvote": {
"message": "Kopiëren en downvote doen"
},
"ContinueVoting": {
"message": "Doorgaan met stemmen"
},
"ChangeCategoryTooltip": {
"message": "Dit is direct van toepassing op uw segmenten"
},
"SponsorTimeEditScrollNewFeature": {
"message": "Gebruik het muiswiel terwijl u over het invoerveld beweegt om de tijd snel aan te passen. Combinaties van de ctrl- of shift-toets kunnen worden gebruikt om de wijzigingen te verfijnen."
}
}

View File

@@ -566,9 +566,6 @@
"downvoteDescription": {
"message": "Feil tidtaking"
},
"incorrectCategory": {
"message": "Feil kategori"
},
"nonMusicCategoryOnMusic": {
"message": "Denne videoen er kategorisert som musikk. Er du sikker på at dette har en sponsor? Hvis det egentlig er et \"Ikke-musikk-segment\", åpne opp innstillingene til utvidelsen og skru på denne kategorien. Deretter kan du sende dette segmentet som \"Ikke-musikk\" i stedet for som sponsing. Vennligst les retningslinjene hvis du er forvirret."
},

View File

@@ -182,6 +182,9 @@
"hideButtonsDescription": {
"message": "Ta opcja ukrywa przyciski do zamieszczania segmentów pojawiające się na odtwarzaczu YouTube."
},
"showSkipButton": {
"message": "Kontynuuj wyświetlanie przycisku pomijania"
},
"showInfoButton": {
"message": "Pokaż przycisk informacyjny na odtwarzaczu YouTube"
},
@@ -697,7 +700,7 @@
"message": "Niepoprawne/Zły czas"
},
"incorrectCategory": {
"message": "Zła kategoria"
"message": "Zmień kategorię"
},
"nonMusicCategoryOnMusic": {
"message": "Ten film jest skategoryzowany jako muzyka. Czy masz pewność, że jest tutaj sponsor? Jeśli w rzeczywistości jest to „Sekcja Niemuzyczna”, otwórz opcje rozszerzenia i włącz tę kategorię. Wtedy będziesz w stanie zamieścić ten segment jako „Bez Muzyki” zamiast sponsora. Przeczytaj proszę wytyczne, jeśli masz wątpliwości."
@@ -807,5 +810,23 @@
},
"LearnMore": {
"message": "Dowiedz się więcej"
},
"CopyDownvoteButtonInfo": {
"message": "Minusuje i tworzy lokalną kopię, abyś mógł przesłać poprawioną wersję"
},
"OpenCategoryWikiPage": {
"message": "Otwórz stronę wiki dla tej kategorii."
},
"CopyAndDownvote": {
"message": "Skopiuj i zminusuj"
},
"ContinueVoting": {
"message": "Kontynuuj głosowanie"
},
"ChangeCategoryTooltip": {
"message": "To natychmiastowo zostanie zastosowane do twoich segmentów"
},
"SponsorTimeEditScrollNewFeature": {
"message": "Użyj scroll'a myszy po najechaniu nad pole edycji, aby szybko dostosować czas. Kombinacje z ctrl'em i shift'em mogą być użyte, aby doszlifować zmiany."
}
}

View File

@@ -700,7 +700,7 @@
"message": "Tempo errado ou incorreto"
},
"incorrectCategory": {
"message": "Categoria errada"
"message": "Mudar Categoria"
},
"nonMusicCategoryOnMusic": {
"message": "Este vídeo é categorizado como música. Tem certeza de que isto tem um patrocinador? Se este é realmente um \"Segmento Não Musical\", abra as opções da extensão e habilite esta categoria. Assim você pode enviar este segmento como \"Não-Musical\" ao invés de patrocinador. Por favor leia as diretrizes se estiver confuso."
@@ -810,5 +810,23 @@
},
"LearnMore": {
"message": "Saiba mais"
},
"CopyDownvoteButtonInfo": {
"message": "Dá voto negativo e cria uma cópia local para você reenviar"
},
"OpenCategoryWikiPage": {
"message": "Abrir a wiki dessa categoria."
},
"CopyAndDownvote": {
"message": "Copiar e dar voto negativo"
},
"ContinueVoting": {
"message": "Continuar Votando"
},
"ChangeCategoryTooltip": {
"message": "Isto irá aplicar instantaneamente seus segmentos"
},
"SponsorTimeEditScrollNewFeature": {
"message": "Use a roda do mouse enquanto mantêm o cursor sobre a caixa de edição para ajustar o tempo rapidamente. Combinações das teclas ctrl e shift podem ser usadas para refinar as mudanças."
}
}

View File

@@ -551,9 +551,6 @@
"downvoteDescription": {
"message": "Timpi Incorecți/Greșiți"
},
"incorrectCategory": {
"message": "Categorie Greșită"
},
"nonMusicCategoryOnMusic": {
"message": "Acest videoclip este categorisit ca muzică. Ești sigur ca există un sponsor? Dacă acesta este defapt un segment non-muzical, deschideți opțiunile extensiei și activați această categorie. Apoi, puteți trimite acest segment ca non-muzical în loc de sponsol. Vă rugăm să citiți ghidul dacă sunteți confuz."
},

View File

@@ -183,7 +183,7 @@
"message": "Эта настройка скрывает кнопки для отправки сегментов, расположенные в плеере YouTube."
},
"showSkipButton": {
"message": "Показывать кнопку \"Пропустить до важного\" в плеере"
"message": "Не скрывать кнопку \"Пропустить до важного\" в плеере YouTube"
},
"showInfoButton": {
"message": "Показывать кнопку информации в плеере YouTube"
@@ -700,7 +700,7 @@
"message": "Не нужен/неверно указано время"
},
"incorrectCategory": {
"message": "Неверная категория"
"message": "Изменить категорию"
},
"nonMusicCategoryOnMusic": {
"message": "Это видео классифицировано как музыкальное. Вы уверены, что в нём есть спонсоры? Если на самом деле это \"Сегмент без музыки\", откройте параметры расширения и включите эту категорию. Затем вы можете отправить этот сегмент как \"Без музыки\", а не как спонсора. Пожалуйста, прочтите руководство, если вы запутались."
@@ -810,5 +810,23 @@
},
"LearnMore": {
"message": "Узнать больше"
},
"CopyDownvoteButtonInfo": {
"message": "Голосует против и создаёт локальную копию сегмента для повторной отправки"
},
"OpenCategoryWikiPage": {
"message": "Открыть вики-страницу этой категории."
},
"CopyAndDownvote": {
"message": "Скопировать и проголосовать против"
},
"ContinueVoting": {
"message": "Продолжить голосование"
},
"ChangeCategoryTooltip": {
"message": "Это мгновенно применится к вашим сегментам"
},
"SponsorTimeEditScrollNewFeature": {
"message": "Наведите курсор на поле редактирования и используйте колесо мыши для быстрой настройки времени. Клавиши Ctrl или Shift могут быть использованы для точной настройки."
}
}

View File

@@ -182,6 +182,9 @@
"hideButtonsDescription": {
"message": "Skryje tlačidlá pre preskočenie segmentov, ktoré sa zobrazujú v YouTube prehrávači."
},
"showSkipButton": {
"message": "Zobrazovať tlačidlo preskočiť na hlavný obsah videa"
},
"showInfoButton": {
"message": "Zobraziť info tlačidlo v YouTube prehrávači"
},
@@ -224,6 +227,21 @@
"showSkipNotice": {
"message": "Zobraziť upozornenie pri preskočení segmentu"
},
"noticeVisibilityMode0": {
"message": "Veľké upozornenia o preskočení"
},
"noticeVisibilityMode1": {
"message": "Malé upozornenia o automatickom preskočení"
},
"noticeVisibilityMode2": {
"message": "Malé upozornenia o všetkých preskočeniach"
},
"noticeVisibilityMode3": {
"message": "Priehľadné upozornenia o automatickom preskočení"
},
"noticeVisibilityMode4": {
"message": "Priehľadné upozornenia o všetkých preskočeniach"
},
"longDescription": {
"message": "SponsorBlock umožňuje preskočiť sponzorov, úvodné časti, záverečné časti, pripomienky na odber, nehudobné časti videoklipov alebo iné otravné časti YouTube videí. SponsorBlock je crowdsourceové rozšírenie prehliadača, pomocou ktorého môže ktokoľvek označiť začiatok a koniec takéhoto segmentu. Po odoslaní potom všetci ostatní s týmto rozšírením tieto segmenty automaticky preskočia.",
"description": "Full description of the extension on the store pages."
@@ -682,7 +700,7 @@
"message": "Nesprávne/Zlé načasovanie"
},
"incorrectCategory": {
"message": "Nesprávna kategória"
"message": "Zmeniť kategóriu"
},
"nonMusicCategoryOnMusic": {
"message": "Toto video je kategorizované ako hudobné. Ste si istý, že obsahuje sponzora? Ak sa skutočne jedná o časť bez hudby, otvorte možnosti rozšírenia a povoľte túto kategóriu. Potom môžete tento segment uložiť ako kategóriu \"Bez hudby\" namiesto sponzora. Ak si neviete rady, tak si prosím prečítajte pravidlá."
@@ -792,5 +810,23 @@
},
"LearnMore": {
"message": "Zistiť viac"
},
"CopyDownvoteButtonInfo": {
"message": "Dá palec dole a vytvorí kópiu, aby ste mohli segment znova odoslať"
},
"OpenCategoryWikiPage": {
"message": "Otvoriť wiki stránku tejto kategórie."
},
"CopyAndDownvote": {
"message": "Skopírovať a dať palec dole"
},
"ContinueVoting": {
"message": "Pokračovať v hodnotení"
},
"ChangeCategoryTooltip": {
"message": "Týmto ihneď vykonáte zmeny v segmentoch"
},
"SponsorTimeEditScrollNewFeature": {
"message": "Čas môžete rýchlo zmeniť kolieskom myši, ak je kurozor nad zadávacím políčkom. Pre jemné zmeny pritom držte kláves ctrl alebo shift."
}
}

View File

@@ -182,6 +182,9 @@
"hideButtonsDescription": {
"message": "Detta döljer knapparna på YouTube-spelaren som du kan skicka in segment med som ska hoppas över."
},
"showSkipButton": {
"message": "Behåll knappen hoppa till markerat på spelaren"
},
"showInfoButton": {
"message": "Visa Infoknapp På YouTube-spelaren"
},
@@ -697,7 +700,7 @@
"message": "Fel/Fel tidsintervall"
},
"incorrectCategory": {
"message": "Fel kategori"
"message": "Ändra kategori"
},
"nonMusicCategoryOnMusic": {
"message": "Den här videon kategoriseras som musik. Är du säker på att denna har en sponsor? Om detta faktiskt är ett \"icke-musiksegment\", öppna tilläggsalternativen och aktivera denna kategori. Då kan du skicka in detta segment som \"icke-musik\" i stället för sponsor. Läs riktlinjerna om något är oklart."
@@ -807,5 +810,23 @@
},
"LearnMore": {
"message": "Läs mer"
},
"CopyDownvoteButtonInfo": {
"message": "Rösta ner och skapar en lokal kopia för dig att skicka igen"
},
"OpenCategoryWikiPage": {
"message": "Öppna denna kategoris wiki-sida."
},
"CopyAndDownvote": {
"message": "Kopiera och rösta ner"
},
"ContinueVoting": {
"message": "Fortsätt rösta"
},
"ChangeCategoryTooltip": {
"message": "Detta kommer omedelbart att verkställas till dina segment"
},
"SponsorTimeEditScrollNewFeature": {
"message": "Använd mushjulet medan du håller muspekaren över redigeringsrutan för att snabbt justera tiden. Kombinationer av CTRL- eller SKIFT-tangenten kan användas för att finjustera tiden."
}
}

View File

@@ -52,6 +52,9 @@
"reskip": {
"message": "ரெஸ்கிப்"
},
"unmute": {
"message": "ஒலியடக்கு"
},
"paused": {
"message": "இடைநிறுத்தப்பட்டது"
},
@@ -79,9 +82,15 @@
"sponsorEnd": {
"message": "பிரிவு இப்போது முடிகிறது"
},
"sponsorCancel": {
"message": "உருவாக்கும் பகுதியை ரத்து செய்"
},
"noVideoID": {
"message": "YouTube வீடியோ எதுவும் கிடைக்கவில்லை.\nஇது தவறாக இருந்தால், தாவலைப் புதுப்பிக்கவும்."
},
"refreshSegments": {
"message": "பிரிவுகளைப் புதுப்பிக்கவும்"
},
"success": {
"message": "வெற்றி!"
},
@@ -152,6 +161,9 @@
"setUsername": {
"message": "பயனர்பெயரை அமைக்கவும்"
},
"copyPublicID": {
"message": "பொது பயனர் IDயை நகலெடுக்கவும்"
},
"discordAdvert": {
"message": "பரிந்துரைகள் மற்றும் கருத்துக்களை வழங்க அதிகாரப்பூர்வ டிஸ்கார்ட் சேவையகத்தில் சேர வாருங்கள்!"
},
@@ -170,12 +182,18 @@
"hideButtonsDescription": {
"message": "ஸ்கிப் பிரிவுகளைச் சமர்ப்பிக்க YouTube பிளேயரில் தோன்றும் பொத்தான்களை இது மறைக்கிறது."
},
"showSkipButton": {
"message": "பிளேயரில் Skip To Highlight பொத்தானை வைக்கவும்"
},
"showInfoButton": {
"message": "YouTube பிளேயரில் தகவல் பொத்தானைக் காட்டு"
},
"hideInfoButton": {
"message": "YouTube பிளேயரில் தகவல் பொத்தானை மறைக்கவும்"
},
"autoHideInfoButton": {
"message": "தகவல் பொத்தானை தானாக மறைக்கவும்"
},
"hideDeleteButton": {
"message": "YouTube பிளேயரில் நீக்கு பொத்தானை மறைக்க"
},
@@ -188,6 +206,9 @@
"whatViewTracking": {
"message": "இந்த அம்சம் பயனர்கள் தங்கள் சமர்ப்பிப்பு மற்றவர்களுக்கு எவ்வளவு உதவியது மற்றும் ஸ்பேம் தரவுத்தளத்தில் வரவில்லை என்பதை உறுதிப்படுத்த அப்வோட்களுடன் ஒரு மெட்ரிக்காகப் பயன்படுத்தப்படுவதை பயனர்களுக்குத் தெரியப்படுத்த நீங்கள் எந்த பகுதிகளைத் தவிர்த்துவிட்டீர்கள் என்பதைக் கண்காணிக்கிறது. ஒவ்வொரு முறையும் நீங்கள் ஒரு பகுதியைத் தவிர்க்கும்போது நீட்டிப்பு சேவையகத்திற்கு ஒரு செய்தியை அனுப்புகிறது. பார்வை எண்கள் துல்லியமாக இருக்க பெரும்பாலான மக்கள் இந்த அமைப்பை மாற்ற மாட்டார்கள் என்று நம்புகிறோம். :)"
},
"enableViewTrackingInPrivate": {
"message": "தனிப்பட்ட/மறைநிலை தாவல்களில் ஸ்கிப் கவுண்ட் டிராக்கிங்கை இயக்கவும்"
},
"enableQueryByHashPrefix": {
"message": "ஹாஷ் முன்னொட்டு மூலம் வினவல்"
},
@@ -206,6 +227,21 @@
"showSkipNotice": {
"message": "ஒரு பிரிவு தவிர்க்கப்பட்ட பிறகு அறிவிப்பைக் காட்டு"
},
"noticeVisibilityMode0": {
"message": "முழு அளவு தவிர்க்கும் அறிவிப்புகள்"
},
"noticeVisibilityMode1": {
"message": "ஆட்டோ ஸ்கிப்பிற்கான சிறிய ஸ்கிப் அறிவிப்புகள்"
},
"noticeVisibilityMode2": {
"message": "அனைத்து சிறிய தவிர்க்கும் அறிவிப்புகள்"
},
"noticeVisibilityMode3": {
"message": "ஆட்டோ ஸ்கிப்பிற்கான மங்கலான தவிர்க்கும் அறிவிப்புகள்"
},
"noticeVisibilityMode4": {
"message": "அனைத்து மங்கலான தவிர்க்கும் அறிவிப்புகள்"
},
"longDescription": {
"message": "ஸ்பான்சர்கள், அறிமுகங்கள், அவுட்ரோஸ், சந்தா நினைவூட்டல்கள் மற்றும் YouTube வீடியோக்களின் பிற எரிச்சலூட்டும் பகுதிகளைத் தவிர்க்க ஸ்பான்சர் பிளாக் உங்களை அனுமதிக்கிறது. ஸ்பான்சர் பிளாக் என்பது ஒரு கூட்ட நெரிசலான உலாவி நீட்டிப்பாகும், இது ஸ்பான்சர் செய்யப்பட்ட பிரிவுகளின் தொடக்க மற்றும் இறுதி நேரங்களையும் YouTube வீடியோக்களின் பிற பிரிவுகளையும் எவரும் சமர்ப்பிக்கலாம். ஒரு நபர் இந்த தகவலைச் சமர்ப்பித்தவுடன், இந்த நீட்டிப்பு உள்ள மற்றவர்கள் ஸ்பான்சர் செய்யப்பட்ட பிரிவைத் தவிர்த்து விடுவார்கள். இசை வீடியோக்களின் இசை அல்லாத பிரிவுகளையும் நீங்கள் தவிர்க்கலாம்.",
"description": "Full description of the extension on the store pages."
@@ -229,6 +265,9 @@
"setSkipShortcut": {
"message": "ஒரு பகுதியைத் தவிர்ப்பதற்கான விசையை அமைக்கவும்"
},
"setStartSponsorShortcut": {
"message": "துவக்க/நிறுத்த பிரிவு விசைப்பலகைக்கு விசையை அமைக்கவும்"
},
"setSubmitKeybind": {
"message": "சமர்ப்பிக்கும் விசைப்பலகைக்கு விசையை அமைக்கவும்"
},
@@ -260,9 +299,31 @@
"skip": {
"message": "தவிர்"
},
"mute": {
"message": "ஒலியடக்கு"
},
"skip_category": {
"message": "{0} ஐ தவிர்?"
},
"mute_category": {
"message": "{0} ஐ ஒலியடக்கவா?"
},
"skip_to_category": {
"message": "{0} க்குச் செல்லவா?",
"description": "Used for skipping to things (Skip to Highlight)"
},
"skipped": {
"message": "{0} தவிர்க்கப்பட்டது",
"description": "Example: Sponsor Skipped"
},
"muted": {
"message": "{0} ஒலியடக்கப்பட்டது",
"description": "Example: Sponsor Muted"
},
"skipped_to_category": {
"message": "{0} தவிர்க்கப்பட்டது",
"description": "Used for skipping to things (Skipped to Highlight)"
},
"disableAutoSkip": {
"message": "ஆட்டோ ஸ்கிப்பை முடக்கு"
},
@@ -311,6 +372,9 @@
"changeUserID": {
"message": "உங்கள் பயனர் ஐடியை இறக்குமதி / ஏற்றுமதி செய்யுங்கள்"
},
"whatChangeUserID": {
"message": "இதை தனிப்பட்டதாக வைத்திருக்க வேண்டும். இது கடவுச்சொல் போன்றது, அதை யாருடனும் பகிரக்கூடாது. யாரிடமாவது இது இருந்தால், அவர் உங்களைப் போல் ஆள்மாறாட்டம் செய்யலாம். உங்கள் பொது பயனர் IDயை நீங்கள் தேடுகிறீர்களானால், பாப்அப்பில் உள்ள கிளிப்போர்டு ஐகானைக் கிளிக் செய்யவும்."
},
"setUserID": {
"message": "UserID ஐ அமைக்கவும்"
},
@@ -323,9 +387,25 @@
"keybindCurrentlySet": {
"message": ". இது தற்போது அமைக்கப்பட்டுள்ளது:"
},
"supportOtherSites": {
"message": "3 வது தரப்பு YouTube-தளங்களை ஆதரிக்கவும்"
},
"supportOtherSitesDescription": {
"message": "மூன்றாம் தரப்பு YouTube தளங்களை ஆதரிக்கவும். ஆதரவை இயக்க, நீங்கள் கூடுதல் அனுமதிகளை ஏற்க வேண்டும். இது Chrome மற்றும் பிற Chromium வகைகளில் தனிப்பட்ட தாவல்களில் வேலை செய்யாது.",
"description": "This replaces the 'supports Invidious' option because it now works on other YouTube sites such as Cloudtube"
},
"supportedSites": {
"message": "ஆதரிக்கப்படும் தளங்கள்: "
},
"optionsInfo": {
"message": "ஆக்கிரமிப்பு ஆதரவை இயக்கு, ஆட்டோஸ்கிப்பை முடக்கு, பொத்தான்களை மறை மற்றும் பலவற்றை."
},
"addInvidiousInstance": {
"message": "3 வது தரப்பு தளங்களை சேர்க்கவும்"
},
"addInvidiousInstanceDescription": {
"message": "தனிப்பட்ட தளங்களை சேர்க்கவும். இது Domain வடிவமைப்பில் இருக்க வேண்டும். உதாரணம்: invidious.ajay.app"
},
"add": {
"message": "சேர்"
},
@@ -347,6 +427,12 @@
"minDurationDescription": {
"message": "தொகுப்பு மதிப்பை விடக் குறைவான பகுதிகள் தவிர்க்கப்படாது அல்லது பிளேயரில் காண்பிக்கப்படாது."
},
"skipNoticeDuration": {
"message": "அறிவிப்பு காலத்தை தவிர்க்கவும் (வினாடிகள்):"
},
"skipNoticeDurationDescription": {
"message": "தவிர்க்கும் அறிவிப்பு குறைந்தபட்சம் இவ்வளவு நேரம் திரையில் இருக்கும். மேனுவல் ஸ்கிப்பிங்கிற்கு, இது நீண்ட நேரம் தெரியும்."
},
"shortCheck": {
"message": "பின்வரும் சமர்ப்பிப்பு உங்கள் குறைந்தபட்ச கால விருப்பத்தை விட குறைவாக உள்ளது. இது ஏற்கனவே சமர்ப்பிக்கப்பட்டுள்ளது என்பதையும், இந்த விருப்பத்தின் காரணமாக புறக்கணிக்கப்படுவதையும் இது குறிக்கலாம். நீங்கள் சமர்ப்பிக்க விரும்புகிறீர்களா?"
},
@@ -404,6 +490,9 @@
"preview": {
"message": "முன்னோட்ட"
},
"unsubmitted": {
"message": "சமர்ப்பிக்கப்படவில்லை"
},
"inspect": {
"message": "ஆய்வு செய்யுங்கள்"
},
@@ -468,6 +557,12 @@
"category_outro_description": {
"message": "வரவுகளை அல்லது YouTube எண்ட்கார்டுகள் தோன்றும் போது. தகவலுடன் முடிவுகளுக்கு அல்ல."
},
"category_preview": {
"message": "முன்னோட்டம்/மறுபரிசீலனை"
},
"category_preview_description": {
"message": "முந்தைய எபிசோடுகளின் விரைவான மறுபரிசீலனை அல்லது தற்போதைய வீடியோவில் பின்னர் என்ன வரப்போகிறது என்பதற்கான முன்னோட்டம். ஒன்றாக தொகுக்கப்பட்ட கிளிப்புகள், பேசப்பட்ட சுருக்கங்களுக்கு அல்ல."
},
"category_music_offtopic": {
"message": "இசை: இசை அல்லாத பிரிவு"
},
@@ -477,6 +572,12 @@
"category_music_offtopic_short": {
"message": "இசை அல்லாதது"
},
"category_poi_highlight": {
"message": "முன்னிலைப்படுத்த"
},
"category_poi_highlight_description": {
"message": "பெரும்பாலான மக்கள் தேடும் வீடியோவின் பகுதி. \"வீடியோ x இல் தொடங்குகிறது\" போன்றது."
},
"category_livestream_messages": {
"message": "லைவ்ஸ்ட்ரீம்: நன்கொடை / செய்தி அளவீடுகள்"
},
@@ -554,9 +655,6 @@
"downvoteDescription": {
"message": "தவறான / தவறான நேரம்"
},
"incorrectCategory": {
"message": "தவறான வகை"
},
"nonMusicCategoryOnMusic": {
"message": "இந்த வீடியோ இசை என வகைப்படுத்தப்பட்டுள்ளது. இதற்கு ஒரு ஸ்பான்சர் இருப்பதை நீங்கள் உறுதியாக நம்புகிறீர்களா? இது உண்மையில் \"இசை அல்லாத பிரிவு\" என்றால், நீட்டிப்பு விருப்பங்களைத் திறந்து இந்த வகையை இயக்கவும். பின்னர், நீங்கள் இந்த பகுதியை ஸ்பான்சருக்கு பதிலாக \"இசை அல்லாதது\" என்று சமர்ப்பிக்கலாம். நீங்கள் குழப்பமாக இருந்தால் வழிகாட்டுதல்களைப் படிக்கவும்."
},

View File

@@ -554,9 +554,6 @@
"downvoteDescription": {
"message": "తప్పు / తప్పు సమయం"
},
"incorrectCategory": {
"message": "తప్పు వర్గం"
},
"nonMusicCategoryOnMusic": {
"message": "ఈ వీడియోను సంగీతంగా వర్గీకరించారు. దీనికి స్పాన్సర్ ఉందని మీరు ఖచ్చితంగా అనుకుంటున్నారా? ఇది వాస్తవానికి \"నాన్-మ్యూజిక్ సెగ్మెంట్\" అయితే, పొడిగింపు ఎంపికలను తెరిచి ఈ వర్గాన్ని ప్రారంభించండి. అప్పుడు, మీరు ఈ విభాగాన్ని స్పాన్సర్‌కు బదులుగా \"నాన్-మ్యూజిక్\" గా సమర్పించవచ్చు. మీరు గందరగోళంలో ఉంటే దయచేసి మార్గదర్శకాలను చదవండి."
},

View File

@@ -690,9 +690,6 @@
"downvoteDescription": {
"message": "Hatalı/Yanlış Zaman"
},
"incorrectCategory": {
"message": "Yanlış Kategori"
},
"nonMusicCategoryOnMusic": {
"message": "Bu video müzik olarak sınıflandırılmıştır. Bunun bir sponsor olduğundan emin misin? Bu aslında bir \"Müzik Dışı bölüm\" ise, uzantı seçeneklerini açın ve bu kategoriyi etkinleştirin. Ardından, bu kısmı sponsor yerine \"Müzik Olmayan\" olarak gönderebilirsiniz. Kafanız karıştıysa lütfen yönergeleri okuyun."
},

View File

@@ -309,7 +309,7 @@
"message": "Вимкнути звук {0}?"
},
"skip_to_category": {
"message": "Пропустить до {0}?",
"message": "Пропустити до {0}?",
"description": "Used for skipping to things (Skip to Highlight)"
},
"skipped": {
@@ -576,7 +576,7 @@
"message": "Основне"
},
"category_poi_highlight_description": {
"message": "Часть видео, которую ищут большинство людей. Аналогично комментарию «Видео начинается с X:XX»."
"message": "Частина відео яку шукає більшість людей (Аналогічно коментарю \"Відео починається з Х:ХХ\")."
},
"category_livestream_messages": {
"message": "Прямі трансляції: пожертвування/читання повідомлення"
@@ -597,13 +597,13 @@
"message": "Вимкнути"
},
"autoSkip_POI": {
"message": "Автоматический переход к началу"
"message": "Автоматично перейти до початку"
},
"manualSkip_POI": {
"message": "Спитати поки відео завантажується"
},
"showOverlay_POI": {
"message": "Показать на панели поиска"
"message": "Показати в смузі перемотування"
},
"autoSkipOnMusicVideos": {
"message": "Автоматично пропустити усі сегменти, якщо присутній сегмент без музики"
@@ -700,7 +700,7 @@
"message": "Невірно вказано час"
},
"incorrectCategory": {
"message": "Невірна категорія"
"message": "Змінити категорію"
},
"nonMusicCategoryOnMusic": {
"message": "Це відео класифіковано як музичне. Ви впевнені, що в ньому є спонсори? Якщо насправді це \"Сегмент без музики\", відкрийте параметри розширення і увімкніть цю категорію. Потім ви можете надіслати цей сегмент як \"Без музики\", а не як спонсора. Будь ласка, прочитайте керівництво, якщо ви заплуталися."
@@ -810,5 +810,23 @@
},
"LearnMore": {
"message": "Дізнатися більше"
},
"CopyDownvoteButtonInfo": {
"message": "Голосує проти та створює локальну копію для повторного надсилання"
},
"OpenCategoryWikiPage": {
"message": "Відкрити вікі-сторінку цієї категорії."
},
"CopyAndDownvote": {
"message": "Скопіювати та проголосувати проти"
},
"ContinueVoting": {
"message": "Продовжити голосування"
},
"ChangeCategoryTooltip": {
"message": "Це миттєво буде застосовано до ваших сегментів"
},
"SponsorTimeEditScrollNewFeature": {
"message": "Навівши курсор на поле редагування, користуйтеся колесом прокрутки, щоб швидко відрегулювати час. Комбінації клавіш ctrl або shift можуть бути використані для точнішої настройки змін."
}
}

View File

@@ -182,6 +182,9 @@
"hideButtonsDescription": {
"message": "Không hiển thị nút trên trình chạy video Youtube để đăng đoạn quảng cáo."
},
"showSkipButton": {
"message": "Giữ nút bỏ qua Highlight trên trình phát player"
},
"showInfoButton": {
"message": "Hiển thị nút thông tin trên trình chạy video Youtube"
},
@@ -302,6 +305,14 @@
"skip_category": {
"message": "Bỏ qua {0}?"
},
"skipped": {
"message": "{0} đã bỏ qua",
"description": "Example: Sponsor Skipped"
},
"muted": {
"message": "{0} đã ngắt tiếng (Muted)",
"description": "Example: Sponsor Muted"
},
"disableAutoSkip": {
"message": "Tắt tự động bỏ qua"
},
@@ -677,14 +688,11 @@
"downvoteDescription": {
"message": "Phân đoạn sai / không đúng"
},
"incorrectCategory": {
"message": "Sai thể loại"
},
"nonMusicCategoryOnMusic": {
"message": "Video này đã được phân loại là âm nhạc. Bạn có chắc đây là quảng cáo nhà tài trợ không? Nếu đây là phân đoạn \"Không phải nhạc\", hãy mở Cài đặt tiện ích và bật lựa chọn đó. Rồi bạn có thể đăng tải phân đoạn lên dưới danh mục \"Không phải nhạc\" thay vì \"Quảng cáo nhà tài trợ\". Hãy đọc Hướng dẫn nếu bạn vẫn còn vướng mắc"
},
"multipleSegments": {
"message": "Nhiều đoạn"
"message": "Nhiều phân đoạn"
},
"guidelines": {
"message": "Hướng dẫn"
@@ -713,6 +721,9 @@
"hideForever": {
"message": "Ẩn vĩnh viễn"
},
"warningChatInfo": {
"message": "Bạn đã nhận được một cảnh báo và tạm thời không thể gửi các phân đoạn. Bạn đã mắc lỗi trong việc tạo phân đoạn quá nhiều lần (có thể là chọn sai kiểu phân đoạn hoặc sai thời gian phân đoạn). Chúng tôi muốn bạn nhận ra điều đó để giúp bạn không mắc lỗi trong tương lai. Bạn có thể gặp các Vip User tại đây: discord.gg/SponsorBlock hoặc matrix.to/#/#sponsor:ajay.app. Bọn họ sẽ giúp bạn gỡ cảnh báo sau khi bạn đã hiểu ra lỗi sai của bạn"
},
"voteRejectedWarning": {
"message": "Bỏ phiếu bị từ chối do có cảnh báo. Nhấp để mở cuộc trò chuyện để giải quyết hoặc quay lại sau.",
"description": "This is an integrated chat panel that will appearing allowing them to talk to the Discord/Matrix chat without leaving their browser."
@@ -741,7 +752,49 @@
"helpPageHowSkippingWorks2": {
"message": "Bất cứ khi nào bỏ qua một phân đoạn, bạn sẽ nhận được 1 cửa sổ thông báo bât. Nếu phân đoạn có vẻ sai, hãy bỏ phiếu bằng cách nhấp vào nút downvote! Bạn cũng có thể bỏ phiếu trong cửa sổ bật lên khi nhấn vào biểu tượng tiện ích mở rộng. Và bạn có thể tắt việc hiển thị bảng thông báo này trong phần cài đặt tiện ích."
},
"Submitting": {
"message": "Gửi lên"
},
"helpPageSubmitting1": {
"message": "Việc gửi một phân đoạn mới có thể được thực hiện trong cửa sổ bật lên bằng cách nhấn vào nút \"Đoạn quảng cáo bắt đầu vào lúc này\" hoặc trong trình phát video bằng các nút trên thanh trình phát."
},
"helpPageSubmitting2": {
"message": "Bạn nhấp 1 lần vào nút \"Đoạn quảng cáo bắt đầu vào lúc này\" để bắt đầu 1 phân đoạn, nhấn 2 lần để đánh dấu kết thúc phân đoạn đó. Bạn có thể chuẩn bị nhiều phân đoạn trước khi nhấn gửi. Nhấp vào nút \"Đăng đoạn quảng cáo\" sẽ gửi. Nhấp vào nút \"Xoá đoạn quảng cáo\" để xóa."
},
"Editing": {
"message": "Chỉnh sửa"
},
"helpPageEditing1": {
"message": "Nếu bạn muốn chỉnh sửa thời gian phân đoạn hoặc kiểu của phân đoạn, bạn có thể chỉnh sửa hoặc xóa các phân đoạn của mình sau khi nhấp vào nút \"Đăng đoạn quảng cáo\"."
},
"helpPageTooSlow": {
"message": "Quá chậm"
"message": "Nếu như bạn cảm thấy thao tác ở trên quá chậm..."
},
"helpPageTooSlow1": {
"message": "Bạn có thể sử dụng các hotkeys - phím nóng. Nhấn phím dấu chấm phẩy (;) để chỉ ra điểm bắt đầu / kết thúc của phân đoạn nhà tài trợ và nhấp vào dấu nháy đơn (') để gửi. Nếu bạn không sử dụng QWERTY, có lẽ bạn nên thay đổi keybinding bằng cách vào phần cài đặt của tiện ích."
},
"helpPageCopyOfDatabase": {
"message": "Tôi có thể lấy bản sao của database không? Điều gì xảy ra nếu có chuyện tệ (server chết, chủ nhân trang web mất, ...)?"
},
"helpPageCopyOfDatabase1": {
"message": "Database được công khai và luôn có sẵn tại "
},
"helpPageCopyOfDatabase2": {
"message": "Mã nguồn mở cũng luôn có sẵn. Vì vậy, ngay cả khi có điều gì đó tệ, các phân đoạn cũng sẽ không biến mất."
},
"helpPageNews": {
"message": "Tôi có thể cập nhật tin tức ở đâu?"
},
"helpPageSourceCode": {
"message": "Bạn có thể tìm thấy source code ở đâu?"
},
"Credits": {
"message": "Lời cảm ơn đến"
},
"highlightNewFeature": {
"message": "Tính năng mới! Đi đến đoạn quan trọng của video chỉ với 1 cú click với dạng phân đoạn Highlight"
},
"LearnMore": {
"message": "Tìm hiểu thêm"
}
}

View File

@@ -566,9 +566,6 @@
"downvoteDescription": {
"message": "不正确/错误的时间"
},
"incorrectCategory": {
"message": "错误的类别"
},
"nonMusicCategoryOnMusic": {
"message": "此视频的分类为音乐。 您确定其中包含赞助商广告吗?如果这是“非音乐片段”,请打开扩展选项并启用此类别。 之后,您可以以“非音乐”而不是赞助商广告类别提交此片段。如果您不太明白,请阅读指南。"
},

View File

@@ -632,9 +632,6 @@
"downvoteDescription": {
"message": "不正確/錯誤的時間"
},
"incorrectCategory": {
"message": "錯誤的類別"
},
"nonMusicCategoryOnMusic": {
"message": "這個影片被分類為音樂。您確定這有贊助內容嗎?如果這其實是\"非音樂片段\"的話,開啟擴充功能設定並啟用這個類別。接下來您即可提交這個片段為\"非音樂片段\"。如果您感到困惑,請閱讀方針"
},

View File

@@ -1,3 +1,7 @@
.hidden {
display: none;
}
#previewbar {
overflow: visible;
padding: 0;
@@ -217,7 +221,7 @@
/* if two are very close to eachother */
.secondSkipNotice {
bottom: 250px;
bottom: 290px;
}
.noticeLeftIcon {
@@ -254,12 +258,16 @@
.sponsorTimesVoteButtonsContainer {
float: left;
vertical-align:middle;
padding: 2px 5px;
margin-right: 4px;
}
.sponsorTimesVoteButtonsContainer div{
display: inline-block;
}
.sponsorSkipNoticeRightSection {
right: 0;
position: absolute;
@@ -286,6 +294,10 @@
float: right;
}
.sponsorSkipNoticeCloseButton.biggerCloseButton {
padding: 20px;
}
.sponsorSkipMessage {
font-size: 14px;
font-weight: bold;
@@ -294,6 +306,7 @@
margin-top: auto;
display: inline-block;
margin-right: 10px;
margin-bottom: auto;
}
.sponsorSkipInfo {
@@ -330,7 +343,8 @@
}
.voteButton {
height: 17px;
height: 24px;
width: 24px;
cursor: pointer;
}
.voteButton:hover {
@@ -521,12 +535,35 @@ input::-webkit-inner-spin-button {
.skipButtonControlBarContainer {
cursor: pointer;
display: flex;
color: white;
}
.skipButtonControlBarContainer.hidden {
display: none !important;
}
.skipButtonControlBarContainer.mobile {
bottom: 30%;
margin-left: 5px;
position: absolute;
height: 20px;
background-color: #00000030;
opacity: 0.5;
border-radius: 10px;
padding: 4px;
}
.skipButtonControlBarContainer.mobile.textDisabled {
padding: 0;
background-color: transparent;
}
.skipButtonControlBarContainer.mobile > div {
margin: auto;
margin-left: 5px;
}
#sbSkipIconControlBarImage {
height: 60%;
top: 0px;
@@ -535,6 +572,11 @@ input::-webkit-inner-spin-button {
margin: auto;
}
.mobile #sbSkipIconControlBarImage {
height: 100%;
width: 20px;
}
.sponsorBlockTooltip {
position: absolute;
background-color: rgba(28, 28, 28, 0.7);
@@ -554,4 +596,19 @@ input::-webkit-inner-spin-button {
border-width: 15px;
border-style: solid;
border-color: rgba(28, 28, 28, 0.7) transparent transparent transparent;
}
}
.sponsorBlockLockedColor {
color: #ffc83d;
}
.sponsorBlockRectangleTooltip {
position: absolute;
border-radius: 5px;
padding: 10px;
min-width: 250px;
min-height: 75px;
white-space: normal;
line-height: 1.5em;
}

View File

@@ -3,6 +3,7 @@
<head>
<title> SponsorBlock </title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link href="styles.css" rel="stylesheet"/>
@@ -39,7 +40,7 @@
__MSG_helpPageFeatureDisclaimer__
</p>
<iframe src="../options/options.html#embed" width="100%" height="500px" style="border: none"></iframe>
<iframe class="optionsFrame" src="../options/options.html#embed" style="border: none"></iframe>
<h1>__MSG_helpPageHowSkippingWorks__</h1>
@@ -56,14 +57,12 @@
__MSG_helpPageHowSkippingWorks2__
</p>
<div class="center"><img height="120px" src="images/voting on notice.gif"></div>
<div class="center"><img src="images/voting on notice.gif"></div>
<h1>__MSG_Submitting__</h1>
<p class="projectPreview">
<span class="projectPreviewImageLargeRight">
<img src="https://i.imgur.com/A1ilk6x.gif">
</span>
<img class="projectPreviewImageLarge" src="https://i.imgur.com/A1ilk6x.gif">
__MSG_helpPageSubmitting1__

View File

@@ -40,14 +40,6 @@ body {
transform: translateY(-20%);
}
.projectPreviewImageLargeRight {
position: absolute;
right: -210px;
width: 200px;
top: 50%;
transform: translateY(-50%);
}
.createdBy {
font-size: 14px;
text-align: center;
@@ -142,18 +134,9 @@ p,li,code,a {
overflow-wrap: break-word;
}
@media screen and (orientation:portrait) {
p,li,code,a {
max-width: 100%;
}
.projectPreviewImage {
position: unset;
width: 130px;
display: block;
margin: auto;
transform: none;
}
.optionsFrame {
width: 100%;
height: 500px;
}
.previewImage {
@@ -187,4 +170,33 @@ svg {
#sbDonate {
font-size: 10px;
}
@media screen and (orientation:portrait) {
.projectPreviewImage {
position: unset;
width: 50%;
display: block;
margin: auto;
transform: none;
}
.projectPreviewImageLarge {
position: unset;
left: 0;
width: 50%;
display: block;
margin: auto;
transform: unset;
}
.container {
max-width: 100%;
margin: 5px;
text-align: center;
}
p,li,code,a {
text-align: center;
}
}

View File

@@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
height="24"
viewBox="0 0 24 24"
width="24"
version="1.1"
id="svg6"
sodipodi:docname="thumbs_down.svg"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)">
<metadata
id="metadata12">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs10" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="730"
inkscape:window-height="480"
id="namedview8"
showgrid="false"
inkscape:zoom="9.8333333"
inkscape:cx="12"
inkscape:cy="12"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="0"
inkscape:current-layer="svg6" />
<path
d="M0 0h24v24H0z"
fill="none"
id="path2" />
<path
d="M15 3H6c-.83 0-1.54.5-1.84 1.22l-3.02 7.05c-.09.23-.14.47-.14.73v2c0 1.1.9 2 2 2h6.31l-.95 4.57-.03.32c0 .41.17.79.44 1.06L9.83 23l6.59-6.59c.36-.36.58-.86.58-1.41V5c0-1.1-.9-2-2-2zm4 0v12h4V3h-4z"
id="path4"
style="fill:#ffc83d" />
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@@ -46,6 +46,7 @@
width: 330px;
padding: 22px;
text-align: center;
margin-bottom: var(--ytd-margin-6x);
}
#issueReporterTimeButtons > .votingButtons > .segmentTimeButton {

View File

@@ -1,6 +1,7 @@
import * as React from "react";
import Config from "../config"
import * as CompileConfig from "../../config.json";
import { Category, CategorySkipOption } from "../types";
import { getCategoryActionType } from "../utils/categoryUtils";
@@ -93,6 +94,10 @@ class CategorySkipOptionsComponent extends React.Component<CategorySkipOptionsPr
<td
colSpan={2}>
{chrome.i18n.getMessage("category_" + this.props.category + "_description")}
{' '}
<a href={CompileConfig.wikiLinks[this.props.category]} target="_blank" rel="noreferrer">
{`${chrome.i18n.getMessage("LearnMore")}`}
</a>
</td>
</tr>

View File

@@ -33,6 +33,7 @@ export interface NoticeProps {
zIndex?: number,
style?: React.CSSProperties
biggerCloseButton?: boolean;
}
export interface NoticeState {
@@ -151,7 +152,8 @@ class NoticeComponent extends React.Component<NoticeProps, NoticeState> {
{/* Close button */}
<img src={chrome.extension.getURL("icons/close.png")}
className="sponsorSkipObject sponsorSkipNoticeButton sponsorSkipNoticeCloseButton sponsorSkipNoticeRightButton"
className={"sponsorSkipObject sponsorSkipNoticeButton sponsorSkipNoticeCloseButton sponsorSkipNoticeRightButton"
+ (this.props.biggerCloseButton ? " biggerCloseButton" : "")}
onClick={() => this.close()}>
</img>
</td>

View File

@@ -4,14 +4,22 @@ import Config from "../config"
import { Category, ContentContainer, CategoryActionType, SponsorHideType, SponsorTime, NoticeVisbilityMode, ActionType } from "../types";
import NoticeComponent from "./NoticeComponent";
import NoticeTextSelectionComponent from "./NoticeTextSectionComponent";
import SubmissionNotice from "../render/SubmissionNotice";
import Utils from "../utils";
const utils = new Utils();
import { getCategoryActionType, getSkippingText } from "../utils/categoryUtils";
import ThumbsUpSvg from "../svg-icons/thumbs_up_svg";
import ThumbsDownSvg from "../svg-icons/thumbs_down_svg";
import PencilSvg from "../svg-icons/pencil_svg";
export enum SkipNoticeAction {
None,
Upvote,
Downvote,
CategoryVote,
CopyDownvote,
Unskip
}
@@ -43,7 +51,7 @@ export interface SkipNoticeState {
skipButtonCallback?: (index: number) => void;
showSkipButton?: boolean;
downvoting?: boolean;
editing?: boolean;
choosingCategory?: boolean;
thanksForVotingText?: string; //null until the voting buttons should be hidden
@@ -52,6 +60,10 @@ export interface SkipNoticeState {
showKeybindHint?: boolean;
smaller?: boolean;
voted?: SkipNoticeAction[];
copied?: SkipNoticeAction[];
}
class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeState> {
@@ -69,6 +81,10 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
noticeRef: React.MutableRefObject<NoticeComponent>;
categoryOptionRef: React.RefObject<HTMLSelectElement>;
selectedColor: string;
unselectedColor: string;
lockedColor: string;
// Used to update on config change
configListener: () => void;
@@ -94,12 +110,16 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
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) {
this.idSuffix += segment.UUID;
}
this.idSuffix += this.amountOfPreviousNotices;
this.selectedColor = Config.config.colorPalette.red;
this.unselectedColor = Config.config.colorPalette.white;
this.lockedColor = Config.config.colorPalette.locked;
// Setup state
this.state = {
noticeTitle,
@@ -115,7 +135,7 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
skipButtonCallback: (index) => this.unskip(index),
showSkipButton: true,
downvoting: false,
editing: false,
choosingCategory: false,
thanksForVotingText: null,
@@ -123,7 +143,11 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
showKeybindHint: this.props.showKeybindHint ?? true,
smaller: this.props.smaller ?? false
smaller: this.props.smaller ?? false,
// Keep track of what segment the user interacted with.
voted: new Array(this.props.segments.length).fill(SkipNoticeAction.None),
copied: new Array(this.props.segments.length).fill(SkipNoticeAction.None),
}
if (!this.autoSkip) {
@@ -164,6 +188,7 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
maxCountdownTime={this.state.maxCountdownTime}
videoSpeed={() => this.contentContainer().v?.playbackRate}
style={noticeStyle}
biggerCloseButton={this.contentContainer().onMobileYouTube}
ref={this.noticeRef}
closeListener={() => this.closeListener()}
smaller={this.state.smaller}
@@ -186,29 +211,38 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
key={0}>
{/* Vote Button Container */}
{!this.state.thanksForVotingText ?
{!this.state.thanksForVotingText ?
<td id={"sponsorTimesVoteButtonsContainer" + this.idSuffix}
className="sponsorTimesVoteButtonsContainer">
{/* Upvote Button */}
<img id={"sponsorTimesDownvoteButtonsContainer" + this.idSuffix}
className="sponsorSkipObject voteButton"
style={{marginRight: "10px"}}
src={chrome.extension.getURL("icons/thumbs_up.svg")}
title={chrome.i18n.getMessage("upvoteButtonInfo")}
onClick={() => this.prepAction(SkipNoticeAction.Upvote)}>
</img>
<div id={"sponsorTimesDownvoteButtonsContainerUpvote" + this.idSuffix}
className="voteButton"
style={{marginRight: "5px"}}
title={chrome.i18n.getMessage("upvoteButtonInfo")}
onClick={() => this.prepAction(SkipNoticeAction.Upvote)}>
<ThumbsUpSvg fill={(this.state.actionState === SkipNoticeAction.Upvote) ? this.selectedColor : this.unselectedColor} />
</div>
{/* Report Button */}
<img id={"sponsorTimesDownvoteButtonsContainer" + this.idSuffix}
className="sponsorSkipObject voteButton"
src={chrome.extension.getURL("icons/thumbs_down.svg")}
title={chrome.i18n.getMessage("reportButtonInfo")}
onClick={() => this.adjustDownvotingState(true)}>
</img>
<div id={"sponsorTimesDownvoteButtonsContainerDownvote" + this.idSuffix}
className="voteButton"
style={{marginRight: "5px", marginLeft: "5px"}}
title={chrome.i18n.getMessage("reportButtonInfo")}
onClick={() => this.prepAction(SkipNoticeAction.Downvote)}>
<ThumbsDownSvg fill={this.downvoteButtonColor(SkipNoticeAction.Downvote)} />
</div>
{/* Copy and Downvote Button */}
<div id={"sponsorTimesDownvoteButtonsContainerCopyDownvote" + this.idSuffix}
className="voteButton"
style={{marginLeft: "5px"}}
onClick={() => this.openEditingOptions()}>
<PencilSvg fill={this.state.editing === true
|| this.state.actionState === SkipNoticeAction.CopyDownvote
|| this.state.choosingCategory === true
? this.selectedColor : this.unselectedColor} />
</div>
</td>
:
@@ -216,7 +250,22 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
<td id={"sponsorTimesVoteButtonInfoMessage" + this.idSuffix}
className="sponsorTimesInfoMessage sponsorTimesVoteButtonMessage"
style={{marginRight: "10px"}}>
{this.state.thanksForVotingText}
{/* Submitted string */}
<span style={{marginRight: "10px"}}>
{this.state.thanksForVotingText}
</span>
{/* Continue Voting Button */}
<button id={"sponsorTimesContinueVotingContainer" + this.idSuffix}
className="sponsorSkipObject sponsorSkipNoticeButton"
title={"Continue Voting"}
onClick={() => this.setState({
thanksForVotingText: null,
messages: []
})}>
{chrome.i18n.getMessage("ContinueVoting")}
</button>
</td>
}
@@ -229,45 +278,46 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
key={1}>
<button className="sponsorSkipObject sponsorSkipNoticeButton sponsorSkipNoticeRightButton"
onClick={this.contentContainer().dontShowNoticeAgain}>
{chrome.i18n.getMessage("Hide")}
</button>
</td>
}
</tr>),
/* Downvote Options Row */
(this.state.downvoting &&
<tr id={"sponsorSkipNoticeDownvoteOptionsRow" + this.idSuffix}
/* Edit Segments Row */
(this.state.editing && !this.state.thanksForVotingText && !(this.state.choosingCategory || this.state.actionState === SkipNoticeAction.CopyDownvote) &&
<tr id={"sponsorSkipNoticeEditSegmentsRow" + this.idSuffix}
key={2}>
<td id={"sponsorTimesDownvoteOptionsContainer" + this.idSuffix}>
<td id={"sponsorTimesEditSegmentsContainer" + this.idSuffix}>
{/* Normal downvote */}
{/* Copy Segment */}
<button className="sponsorSkipObject sponsorSkipNoticeButton"
onClick={() => this.prepAction(SkipNoticeAction.Downvote)}>
{chrome.i18n.getMessage("downvoteDescription")}
title={chrome.i18n.getMessage("CopyDownvoteButtonInfo")}
style={{color: this.downvoteButtonColor(SkipNoticeAction.Downvote)}}
onClick={() => this.prepAction(SkipNoticeAction.CopyDownvote)}>
{chrome.i18n.getMessage("CopyAndDownvote")}
</button>
{/* Category vote */}
<button className="sponsorSkipObject sponsorSkipNoticeButton"
onClick={() => this.openCategoryChooser()}>
title={chrome.i18n.getMessage("ChangeCategoryTooltip")}
style={{color: (this.state.actionState === SkipNoticeAction.CategoryVote && this.state.editing == true) ? this.selectedColor : this.unselectedColor}}
onClick={() => this.resetStateToStart(SkipNoticeAction.CategoryVote, true, true)}>
{chrome.i18n.getMessage("incorrectCategory")}
</button>
</td>
</tr>
),
/* Category Chooser Row */
(this.state.choosingCategory &&
(this.state.choosingCategory && !this.state.thanksForVotingText &&
<tr id={"sponsorSkipNoticeCategoryChooserRow" + this.idSuffix}
key={3}>
<td>
{/* Category Selector */}
<select id={"sponsorTimeCategories" + this.idSuffix}
className="sponsorTimeCategories sponsorTimeEditSelector"
defaultValue={this.segments[0].category} //Just default to the first segment, as we don't know which they'll choose
defaultValue={this.segments[0].category}
ref={this.categoryOptionRef}>
{this.getCategoryOptions()}
@@ -281,13 +331,12 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
{chrome.i18n.getMessage("submit")}
</button>
}
</td>
</tr>
),
/* Segment Chooser Row */
(this.state.actionState !== SkipNoticeAction.None &&
(this.state.actionState !== SkipNoticeAction.None && this.segments.length > 1 && !this.state.thanksForVotingText &&
<tr id={"sponsorSkipNoticeSubmissionOptionsRow" + this.idSuffix}
key={4}>
<td id={"sponsorTimesSubmissionOptionsContainer" + this.idSuffix}>
@@ -302,13 +351,22 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
if (this.state.showSkipButton && (this.segments.length > 1
|| getCategoryActionType(this.segments[0].category) !== CategoryActionType.POI
|| this.props.unskipTime)) {
const style: React.CSSProperties = {
marginLeft: "4px",
color: (this.state.actionState === SkipNoticeAction.Unskip) ? this.selectedColor : this.unselectedColor
};
if (this.contentContainer().onMobileYouTube) {
style.padding = "20px";
style.minWidth = "100px";
}
return (
<span className="sponsorSkipNoticeUnskipSection">
<button id={"sponsorSkipUnskipButton" + this.idSuffix}
className="sponsorSkipObject sponsorSkipNoticeButton"
style={{marginLeft: "4px"}}
onClick={() => this.prepAction(SkipNoticeAction.Unskip)}>
className="sponsorSkipObject sponsorSkipNoticeButton"
style={style}
onClick={() => this.prepAction(SkipNoticeAction.Unskip)}>
{this.state.skipButtonText + (this.state.showKeybindHint ? " (" + Config.config.skipKeybind + ")" : "")}
</button>
</span>
@@ -318,20 +376,40 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
getSubmissionChooser(): JSX.Element[] {
const elements: JSX.Element[] = [];
for (let i = 0; i < this.segments.length; i++) {
elements.push(
<button className="sponsorSkipObject sponsorSkipNoticeButton"
style={{opacity: this.getSubmissionChooserOpacity(i),
color: this.getSubmissionChooserColor(i)}}
onClick={() => this.performAction(i)}
key={"submission" + i + this.segments[i].category + this.idSuffix}>
{(i + 1) + ". " + chrome.i18n.getMessage("category_" + this.segments[i].category)}
</button>
);
}
return elements;
}
getSubmissionChooserOpacity(index: number): number {
const isUpvote = this.state.actionState === SkipNoticeAction.Upvote;
const isDownvote = this.state.actionState == SkipNoticeAction.Downvote;
const isCopyDownvote = this.state.actionState == SkipNoticeAction.CopyDownvote;
const shouldBeGray: boolean = (isUpvote && this.state.voted[index] == SkipNoticeAction.Upvote) ||
(isDownvote && this.state.voted[index] == SkipNoticeAction.Downvote) ||
(isCopyDownvote && this.state.copied[index] == SkipNoticeAction.CopyDownvote);
return shouldBeGray ? 0.35 : 1;
}
getSubmissionChooserColor(index: number): string {
const isDownvote = this.state.actionState == SkipNoticeAction.Downvote;
const isCopyDownvote = this.state.actionState == SkipNoticeAction.CopyDownvote;
const shouldWarnUser = Config.config.isVip && (isDownvote || isCopyDownvote)
&& this.segments[index].locked === 1;
return shouldWarnUser ? this.lockedColor : this.unselectedColor;
}
onMouseEnter(): void {
if (this.state.smaller) {
this.setState({
@@ -340,16 +418,6 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
}
}
prepAction(action: SkipNoticeAction): void {
if (this.segments.length === 1) {
this.performAction(0, action);
} else {
this.setState({
actionState: action
});
}
}
getMessageBoxes(): JSX.Element[] {
if (this.state.messages.length === 0) {
// Add a spacer if there is no text
@@ -365,8 +433,8 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
for (let i = 0; i < this.state.messages.length; i++) {
elements.push(
<tr>
<td>
<tr key={i + "_messageBox"}>
<td key={i + "_messageBox"}>
<NoticeTextSelectionComponent idSuffix={this.idSuffix}
text={this.state.messages[i]}
onClick={this.state.messageOnClick}
@@ -380,6 +448,33 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
return elements;
}
prepAction(action: SkipNoticeAction): void {
if (this.segments.length === 1) {
this.performAction(0, action);
} else {
switch (action ?? this.state.actionState) {
case SkipNoticeAction.None:
this.resetStateToStart();
break;
case SkipNoticeAction.Upvote:
this.resetStateToStart(SkipNoticeAction.Upvote);
break;
case SkipNoticeAction.Downvote:
this.resetStateToStart(SkipNoticeAction.Downvote);
break;
case SkipNoticeAction.CategoryVote:
this.resetStateToStart(SkipNoticeAction.CategoryVote, true, true);
break;
case SkipNoticeAction.CopyDownvote:
this.resetStateToStart(SkipNoticeAction.CopyDownvote, true);
break;
case SkipNoticeAction.Unskip:
this.resetStateToStart(SkipNoticeAction.Unskip);
break;
}
}
}
/**
* Performs the action from the current state
*
@@ -388,74 +483,110 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
performAction(index: number, action?: SkipNoticeAction): void {
switch (action ?? this.state.actionState) {
case SkipNoticeAction.None:
this.noAction(index);
break;
case SkipNoticeAction.Upvote:
this.contentContainer().vote(1, this.segments[index].UUID, undefined, this);
this.upvote(index);
break;
case SkipNoticeAction.Downvote:
this.contentContainer().vote(0, this.segments[index].UUID, undefined, this);
this.downvote(index);
break;
case SkipNoticeAction.CategoryVote:
this.contentContainer().vote(undefined, this.segments[index].UUID, this.categoryOptionRef.current.value as Category, this)
this.categoryVote(index);
break;
case SkipNoticeAction.CopyDownvote:
this.copyDownvote(index);
break;
case SkipNoticeAction.Unskip:
this.state.skipButtonCallback(index);
this.unskipAction(index);
break;
default:
this.resetStateToStart();
break;
}
}
noAction(index: number): void {
const voted = this.state.voted;
voted[index] = SkipNoticeAction.None;
this.setState({
actionState: SkipNoticeAction.None
voted
});
}
adjustDownvotingState(value: boolean): void {
if (!value) this.clearConfigListener();
upvote(index: number): void {
if (this.segments.length === 1) this.resetStateToStart();
this.contentContainer().vote(1, this.segments[index].UUID, undefined, this);
}
downvote(index: number): void {
if (this.segments.length === 1) this.resetStateToStart();
this.contentContainer().vote(0, this.segments[index].UUID, undefined, this);
}
categoryVote(index: number): void {
this.contentContainer().vote(undefined, this.segments[index].UUID, this.categoryOptionRef.current.value as Category, this)
}
copyDownvote(index: number): void {
const sponsorVideoID = this.props.contentContainer().sponsorVideoID;
const sponsorTimesSubmitting : SponsorTime = {
segment: this.segments[index].segment,
UUID: null,
category: this.segments[index].category,
actionType: this.segments[index].actionType,
source: 2
};
const segmentTimes = Config.config.segmentTimes.get(sponsorVideoID) || [];
segmentTimes.push(sponsorTimesSubmitting);
Config.config.segmentTimes.set(sponsorVideoID, segmentTimes);
this.props.contentContainer().sponsorTimesSubmitting.push(sponsorTimesSubmitting);
this.props.contentContainer().updatePreviewBar();
this.props.contentContainer().resetSponsorSubmissionNotice();
this.props.contentContainer().updateEditButtonsOnPlayer();
this.contentContainer().vote(0, this.segments[index].UUID, undefined, this);
const copied = this.state.copied;
copied[index] = SkipNoticeAction.CopyDownvote;
this.setState({
downvoting: value,
choosingCategory: false
copied
});
}
clearConfigListener(): void {
if (this.configListener) {
Config.configListeners.splice(Config.configListeners.indexOf(this.configListener), 1);
this.configListener = null;
}
unskipAction(index: number): void {
this.state.skipButtonCallback(index);
}
openCategoryChooser(): void {
// Add as a config listener
this.configListener = () => this.forceUpdate();
Config.configListeners.push(this.configListener);
this.setState({
choosingCategory: true,
downvoting: false
}, () => {
if (this.segments.length > 1) {
// Use the action selectors as a submit button
this.prepAction(SkipNoticeAction.CategoryVote);
}
});
openEditingOptions(): void {
this.resetStateToStart(undefined, true);
}
getCategoryOptions(): React.ReactElement[] {
const elements = [];
const categories = CompileConfig.categoryList.filter((cat => getCategoryActionType(cat as Category) === CategoryActionType.Skippable));
const categories = (CompileConfig.categoryList.filter((cat => getCategoryActionType(cat as Category) === CategoryActionType.Skippable))) as Category[];
for (const category of categories) {
elements.push(
<option value={category}
key={category}>
key={category}
className={this.getCategoryNameClass(category)}>
{chrome.i18n.getMessage("category_" + category)}
</option>
);
}
return elements;
}
getCategoryNameClass(category: string): string {
return this.props.contentContainer().lockedCategories.includes(category) ? "sponsorBlockLockedColor" : ""
}
unskip(index: number): void {
this.contentContainer().unskipSponsorTime(this.segments[index], this.props.unskipTime);
@@ -512,21 +643,42 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
}
afterVote(segment: SponsorTime, type: number, category: Category): void {
const index = utils.getSponsorIndexFromUUID(this.segments, segment.UUID);
const wikiLinkText = CompileConfig.wikiLinks[segment.category];
const voted = this.state.voted;
switch (type) {
case 0:
this.clearConfigListener();
this.setNoticeInfoMessageWithOnClick(() => window.open(wikiLinkText), chrome.i18n.getMessage("OpenCategoryWikiPage"));
voted[index] = SkipNoticeAction.Downvote;
break;
case 1:
voted[index] = SkipNoticeAction.Upvote;
break;
case 20:
voted[index] = SkipNoticeAction.None;
break;
}
this.setState({
voted
});
this.addVoteButtonInfo(chrome.i18n.getMessage("voted"));
if (type === 0) {
this.setNoticeInfoMessage(chrome.i18n.getMessage("hitGoBack"));
this.adjustDownvotingState(false);
}
// Change the sponsor locally
if (segment) {
if (type === 0) {
segment.hidden = SponsorHideType.Downvoted;
} else if (category) {
segment.category = category;
segment.category = category; // This is the actual segment on the video page
this.segments[index].category = category; //this is the segment inside the skip notice.
} else if (type === 1) {
segment.hidden = SponsorHideType.Visible;
}
this.contentContainer().updatePreviewBar();
}
}
@@ -562,6 +714,13 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
this.props.closeListener();
}
clearConfigListener(): void {
if (this.configListener) {
Config.configListeners.splice(Config.configListeners.indexOf(this.configListener), 1);
this.configListener = null;
}
}
unmutedListener(): void {
if (this.props.segments.length === 1
&& this.props.segments[0].actionType === ActionType.Mute
@@ -572,6 +731,26 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
}
}
resetStateToStart(actionState: SkipNoticeAction = SkipNoticeAction.None, editing = false, choosingCategory = false): void {
this.setState({
actionState: actionState,
editing: editing,
choosingCategory: choosingCategory,
thanksForVotingText: null,
messages: []
});
}
downvoteButtonColor(downvoteType: SkipNoticeAction): string {
// Also used for "Copy and Downvote"
if (this.segments.length > 1) {
return (this.state.actionState === downvoteType) ? this.selectedColor : this.unselectedColor;
} else {
// You dont have segment selectors so the lockbutton needs to be colored and cannot be selected.
return Config.config.isVip && this.segments[0].locked === 1 ? this.lockedColor : this.unselectedColor;
}
}
private getUnskipText(): string {
switch (this.props.segments[0].actionType) {
case ActionType.Mute: {

View File

@@ -5,6 +5,7 @@ import { ActionType, ActionTypes, Category, CategoryActionType, ContentContainer
import Utils from "../utils";
import { getCategoryActionType } from "../utils/categoryUtils";
import SubmissionNoticeComponent from "./SubmissionNoticeComponent";
import { RectangleTooltip } from "../render/RectangleTooltip";
const utils = new Utils();
@@ -23,6 +24,7 @@ export interface SponsorTimeEditProps {
export interface SponsorTimeEditState {
editing: boolean;
sponsorTimeEdits: [string, string];
selectedCategory: Category;
}
const DEFAULT_CATEGORY = "chooseACategory";
@@ -36,6 +38,9 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
configUpdateListener: () => void;
previousSkipType: CategoryActionType;
timeBeforeChangingToPOI: number; // Initialized when first selecting POI
constructor(props: SponsorTimeEditProps) {
super(props);
@@ -44,9 +49,11 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
this.idSuffix = this.props.idSuffix;
this.previousSkipType = CategoryActionType.Skippable;
this.state = {
editing: false,
sponsorTimeEdits: [null, null]
sponsorTimeEdits: [null, null],
selectedCategory: DEFAULT_CATEGORY as Category
};
}
@@ -56,6 +63,11 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
event.stopPropagation();
});
// Prevent scrolling while changing times
document.getElementById("sponsorTimesContainer" + this.idSuffix).addEventListener('wheel', function (event) {
event.preventDefault();
}, {passive: false});
// Add as a config listener
if (!this.configUpdateListener) {
this.configUpdateListener = () => this.configUpdate();
@@ -86,7 +98,6 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
node.style.setProperty("text-shadow", "none", "important");
}
};
// Create time display
let timeDisplay: JSX.Element;
const sponsorTime = this.props.contentContainer().sponsorTimesSubmitting[this.props.index];
@@ -101,20 +112,13 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
onClick={() => this.setTimeToNow(0)}>
{chrome.i18n.getMessage("bracketNow")}
</span>
<input id={"submittingTime0" + this.idSuffix}
className="sponsorTimeEdit sponsorTimeEditInput"
ref={oldYouTubeDarkStyles}
type="text"
value={this.state.sponsorTimeEdits[0]}
onChange={(e) => {
const sponsorTimeEdits = this.state.sponsorTimeEdits;
sponsorTimeEdits[0] = e.target.value;
if (getCategoryActionType(sponsorTime.category) === CategoryActionType.POI) sponsorTimeEdits[1] = e.target.value;
this.setState({sponsorTimeEdits});
this.saveEditTimes();
}}>
onChange={(e) => {this.handleOnChange(0, e, sponsorTime, e.target.value)}}
onWheel={(e) => {this.changeTimesWhenScrolling(0, e, sponsorTime)}}>
</input>
{getCategoryActionType(sponsorTime.category) === CategoryActionType.Skippable ? (
@@ -128,14 +132,8 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
ref={oldYouTubeDarkStyles}
type="text"
value={this.state.sponsorTimeEdits[1]}
onChange={(e) => {
const sponsorTimeEdits = this.state.sponsorTimeEdits;
sponsorTimeEdits[1] = e.target.value;
this.setState({sponsorTimeEdits});
this.saveEditTimes();
}}>
onChange={(e) => {this.handleOnChange(1, e, sponsorTime, e.target.value)}}
onWheel={(e) => {this.changeTimesWhenScrolling(1, e, sponsorTime)}}>
</input>
<span id={"nowButton1" + this.idSuffix}
@@ -155,12 +153,13 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
);
} else {
timeDisplay = (
<div id={"sponsorTimesContainer" + this.idSuffix}
className="sponsorTimeDisplay"
onClick={this.toggleEditTime.bind(this)}>
{utils.getFormattedTime(segment[0], true) +
((!isNaN(segment[1]) && getCategoryActionType(sponsorTime.category) === CategoryActionType.Skippable)
? " " + chrome.i18n.getMessage("to") + " " + utils.getFormattedTime(segment[1], true) : "")}
? " " + chrome.i18n.getMessage("to") + " " + utils.getFormattedTime(segment[1], true) : "")}
</div>
);
}
@@ -216,7 +215,7 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
{(!isNaN(segment[1]) && getCategoryActionType(sponsorTime.category) === CategoryActionType.Skippable) ? (
<span id={"sponsorTimePreviewButton" + this.idSuffix}
className="sponsorTimeEditButton"
onClick={this.previewTime.bind(this)}>
onClick={(e) => this.previewTime(e.ctrlKey, e.shiftKey)}>
{chrome.i18n.getMessage("preview")}
</span>
): ""}
@@ -240,6 +239,70 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
);
}
handleOnChange(index: number, e: React.ChangeEvent, sponsorTime: SponsorTime, targetValue: string): void {
const sponsorTimeEdits = this.state.sponsorTimeEdits;
// check if change is small engough to show tooltip
const before = utils.getFormattedTimeToSeconds(sponsorTimeEdits[index]);
const after = utils.getFormattedTimeToSeconds(targetValue);
const difference = Math.abs(before - after);
if (0 < difference && difference< 0.5) this.showToolTip();
sponsorTimeEdits[index] = targetValue;
if (index === 0 && getCategoryActionType(sponsorTime.category) === CategoryActionType.POI) sponsorTimeEdits[1] = targetValue;
this.setState({sponsorTimeEdits});
this.saveEditTimes();
}
changeTimesWhenScrolling(index: number, e: React.WheelEvent, sponsorTime: SponsorTime): void {
let step = 0;
// shift + ctrl = 1
// ctrl = 0.1
// default = 0.01
// shift = 0.001
if (e.shiftKey) {
step = (e.ctrlKey) ? 1 : 0.001;
} else {
step = (e.ctrlKey) ? 0.1 : 0.01;
}
const sponsorTimeEdits = this.state.sponsorTimeEdits;
let timeAsNumber = utils.getFormattedTimeToSeconds(this.state.sponsorTimeEdits[index]);
if (timeAsNumber !== null && e.deltaY != 0) {
if (e.deltaY < 0) {
timeAsNumber += step;
} else if (timeAsNumber >= step) {
timeAsNumber -= step;
} else {
timeAsNumber = 0;
}
sponsorTimeEdits[index] = utils.getFormattedTime(timeAsNumber, true);
if (getCategoryActionType(sponsorTime.category) === CategoryActionType.POI) sponsorTimeEdits[1] = sponsorTimeEdits[0];
this.setState({sponsorTimeEdits});
this.saveEditTimes();
}
}
showToolTip(): void {
if (!Config.config.scrollToEditTimeUpdate && document.getElementById("sponsorRectangleTooltip" + "sponsorTimesContainer" + this.idSuffix) === null) {
const element = document.getElementById("sponsorTimesContainer" + this.idSuffix);
new RectangleTooltip({
text: chrome.i18n.getMessage("SponsorTimeEditScrollNewFeature"),
referenceNode: element.parentElement,
prependElement: element,
timeout: 15,
bottomOffset: 0 + "px",
leftOffset: -318 + "px",
backgroundColor: "rgba(28, 28, 28, 1.0)",
htmlId: "sponsorTimesContainer" + this.idSuffix,
buttonFunction: () => { Config.config.scrollToEditTimeUpdate = true },
fontSize: "14px",
maxHeight: "200px"
});
}
}
getCategoryOptions(): React.ReactElement[] {
const elements = [(
<option value={DEFAULT_CATEGORY}
@@ -251,7 +314,8 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
for (const category of (this.props.categoryList ?? CompileConfig.categoryList)) {
elements.push(
<option value={category}
key={category}>
key={category}
className={this.getCategoryLockedClass(category)}>
{chrome.i18n.getMessage("category_" + category)}
</option>
);
@@ -260,6 +324,10 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
return elements;
}
getCategoryLockedClass(category: string): string {
return this.props.contentContainer().lockedCategories.includes(category) ? "sponsorBlockLockedColor" : "";
}
categorySelectionChange(event: React.ChangeEvent<HTMLSelectElement>): void {
// See if show more categories was pressed
if (event.target.value !== DEFAULT_CATEGORY && !Config.config.categorySelections.some((category) => category.name === event.target.value)) {
@@ -277,6 +345,7 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
}
if (getCategoryActionType(event.target.value as Category) === CategoryActionType.POI) {
if (this.previousSkipType === CategoryActionType.Skippable) this.timeBeforeChangingToPOI = utils.getFormattedTimeToSeconds(this.state.sponsorTimeEdits[1]);
this.setTimeTo(1, null);
this.props.contentContainer().updateEditButtonsOnPlayer();
@@ -284,8 +353,11 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
.some((segment, i) => segment.category === event.target.value && i !== this.props.index)) {
alert(chrome.i18n.getMessage("poiOnlyOneSegment"));
}
} else if (getCategoryActionType(event.target.value as Category) === CategoryActionType.Skippable && this.previousSkipType === CategoryActionType.POI) {
this.setTimeTo(1, this.timeBeforeChangingToPOI);
}
this.previousSkipType = getCategoryActionType(event.target.value as Category);
this.saveEditTimes();
}
@@ -374,13 +446,17 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
this.props.contentContainer().updatePreviewBar();
}
previewTime(): void {
previewTime(ctrlPressed = false, shiftPressed = false): void {
const sponsorTimes = this.props.contentContainer().sponsorTimesSubmitting;
const index = this.props.index;
const skipTime = sponsorTimes[index].segment[0];
this.props.contentContainer().previewTime(skipTime - (2 * this.props.contentContainer().v.playbackRate));
let seekTime = 2;
if (ctrlPressed) seekTime = 0.5;
if (shiftPressed) seekTime = 0.25;
this.props.contentContainer().previewTime(skipTime - (seekTime * this.props.contentContainer().v.playbackRate));
}
inspectTime(): void {

View File

@@ -3,7 +3,9 @@ import { Category, CategorySelection, CategorySkipOption, NoticeVisbilityMode, P
interface SBConfig {
userID: string,
/** Contains unsubmitted segments that the user has created. */
isVip: boolean,
lastIsVipUpdate: number,
/* Contains unsubmitted segments that the user has created. */
segmentTimes: SBMap<string, SponsorTime[]>,
defaultCategory: Category,
whitelistedChannels: string[],
@@ -43,7 +45,13 @@ interface SBConfig {
showDonationLink: boolean,
autoHideInfoButton: boolean,
autoSkipOnMusicVideos: boolean,
highlightCategoryUpdate: boolean
highlightCategoryUpdate: boolean,
colorPalette: {
red: string,
white: string,
locked: string
},
scrollToEditTimeUpdate: boolean,
// What categories should be skipped
categorySelections: CategorySelection[],
@@ -67,6 +75,8 @@ interface SBConfig {
"preview-music_offtopic": PreviewBarOption,
"poi_highlight": PreviewBarOption,
"preview-poi_highlight": PreviewBarOption,
"filler": PreviewBarOption,
"preview-filler": PreviewBarOption,
}
}
@@ -151,6 +161,8 @@ const Config: SBObject = {
configListeners: [],
defaults: {
userID: null,
isVip: false,
lastIsVipUpdate: 0,
segmentTimes: new SBMap("segmentTimes"),
defaultCategory: "chooseACategory" as Category,
whitelistedChannels: [],
@@ -191,12 +203,19 @@ const Config: SBObject = {
autoHideInfoButton: true,
autoSkipOnMusicVideos: false,
highlightCategoryUpdate: false, // TODO: Remove this once update is done
scrollToEditTimeUpdate: false, // false means the tooltip will be shown
categorySelections: [{
name: "sponsor" as Category,
option: CategorySkipOption.AutoSkip
}],
colorPalette: {
red: "#780303",
white: "#ffffff",
locked: "#ffc83d"
},
// Preview bar
barTypes: {
"preview-chooseACategory": {
@@ -266,6 +285,14 @@ const Config: SBObject = {
"preview-poi_highlight": {
color: "#9b044c",
opacity: "0.7"
},
"filler": {
color: "#7300FF",
opacity: "0.9"
},
"preview-filler": {
color: "#2E0066",
opacity: "0.7"
}
}
},

View File

@@ -17,6 +17,7 @@ import { getCategoryActionType } from "./utils/categoryUtils";
import { SkipButtonControlBar } from "./js-components/skipButtonControlBar";
import { Tooltip } from "./render/Tooltip";
import { getStartTimeFromUrl } from "./utils/urlParser";
import { getControls } from "./utils/pageUtils";
// Hack to get the CSS loaded on permission-based sites (Invidious)
utils.wait(() => Config.config !== null, 5000, 10).then(addCSS);
@@ -30,12 +31,13 @@ let sponsorVideoID: VideoID = null;
// List of open skip notices
const skipNotices: SkipNotice[] = [];
let activeSkipKeybindElement: ToggleSkippable = null;
let lastPOISkip = 0;
// JSON video info
let videoInfo: VideoInfo = null;
//the channel this video is about
// The channel this video is about
let channelIDInfo: ChannelIDInfo;
// Locked Categories in this tab, like: ["sponsor","intro","outro"]
let lockedCategories: Category[] = [];
// Skips are scheduled to ensure precision.
// Skips are rescheduled every seeking event.
@@ -121,7 +123,8 @@ const skipNoticeContentContainer: ContentContainer = () => ({
updateEditButtonsOnPlayer,
previewTime,
videoInfo,
getRealCurrentTime: getRealCurrentTime
getRealCurrentTime: getRealCurrentTime,
lockedCategories
});
// value determining when to count segment as skipped and send telemetry to server (percent based)
@@ -148,7 +151,8 @@ function messageListener(request: Message, sender: unknown, sendResponse: (respo
//send the sponsor times along with if it's found
sendResponse({
found: sponsorDataFound,
sponsorTimes: sponsorTimes
sponsorTimes: sponsorTimes,
onMobileYouTube
});
if (!request.updating && popupInitialised && document.getElementById("sponsorBlockPopupContainer") != null) {
@@ -188,7 +192,8 @@ function messageListener(request: Message, sender: unknown, sendResponse: (respo
case "refreshSegments":
sponsorsLookup(sponsorVideoID, false).then(() => sendResponse({
found: sponsorDataFound,
sponsorTimes: sponsorTimes
sponsorTimes: sponsorTimes,
onMobileYouTube
}));
return true;
@@ -231,6 +236,7 @@ function resetValues() {
status: ChannelIDStatus.Fetching,
id: null
};
lockedCategories = [];
//empty the preview bar
if (previewBar !== null) {
@@ -332,6 +338,8 @@ async function videoIDChange(id) {
function handleMobileControlsMutations(): void {
updateVisibilityOfPlayerControlsButton();
skipButtonControlBar?.updateMobileControls();
if (previewBar !== null) {
if (document.body.contains(previewBar.container)) {
const progressBarBackground = document.querySelector<HTMLElement>(".progress-bar-background");
@@ -388,12 +396,6 @@ function createPreviewBar(): void {
function durationChangeListener(): void {
updateAdFlag();
updatePreviewBar();
if (sponsorTimes) sponsorTimes = sponsorTimes.filter(segmentDurationFilter);
}
function segmentDurationFilter(segment: SponsorTime): boolean {
return segment.videoDuration === 0 || !video?.duration || Math.abs(video.duration - segment.videoDuration) < 2;
}
function cancelSponsorSchedule(): void {
@@ -461,7 +463,7 @@ function startSponsorSchedule(includeIntersectingSegments = false, currentTime?:
}
// Don't skip if this category should not be skipped
if (!shouldSkip(currentSkip) && skipInfo.array !== sponsorTimesSubmitting) return;
if (!shouldSkip(currentSkip) && !sponsorTimesSubmitting?.some((segment) => segment.segment === currentSkip.segment)) return;
const skippingFunction = () => {
let forcedSkipTime: number = null;
@@ -602,24 +604,6 @@ function setupVideoListeners() {
startSponsorSchedule();
}
if (!Config.config.dontShowNotice) {
const currentPoiSegment = sponsorTimes?.find((segment) =>
getCategoryActionType(segment.category) === CategoryActionType.POI &&
video.currentTime - segment.segment[0] > 0 &&
video.currentTime - segment.segment[0] < previewBar.getMinimumSize(true));
if (currentPoiSegment && lastPOISkip < Date.now() - 3000
&& !skipNotices.some((notice) => notice.segments.some((s) => s.UUID === currentPoiSegment.UUID))) {
lastPOISkip = Date.now();
skipToTime({
v: video,
skipTime: currentPoiSegment.segment,
skippingSegments: [currentPoiSegment],
openNotice: true,
forceAutoSkip: true
});
}
}
});
video.addEventListener('ratechange', () => startSponsorSchedule());
// Used by videospeed extension (https://github.com/igrigorik/videospeed/pull/740)
@@ -645,7 +629,8 @@ function setupSkipButtonControlBar() {
skippingSegments: [segment],
openNotice: true,
forceAutoSkip: true
})
}),
onMobileYouTube
});
}
@@ -671,19 +656,31 @@ async function sponsorsLookup(id: string, keepOldSubmissions = true) {
categories.push(categorySelection.name);
}
const extraRequestData: Record<string, unknown> = {};
const windowHash = window.location.hash.substr(1);
if (windowHash) {
const params: Record<string, unknown> = windowHash.split('&').reduce((acc, param) => {
const [key, value] = param.split('=');
acc[key] = value;
return acc;
}, {});
if (params.requiredSegment) extraRequestData.requiredSegment = params.requiredSegment;
}
// Check for hashPrefix setting
const hashPrefix = (await utils.getHash(id, 1)).substr(0, 4);
const response = await utils.asyncRequestToServer('GET', "/api/skipSegments/" + hashPrefix, {
categories,
actionTypes: Config.config.muteSegments ? [ActionType.Skip, ActionType.Mute] : [ActionType.Skip],
userAgent: `${chrome.runtime.id}`
userAgent: `${chrome.runtime.id}`,
...extraRequestData
});
if (response?.ok) {
const recievedSegments: SponsorTime[] = JSON.parse(response.responseText)
?.filter((video) => video.videoID === id)
?.map((video) => video.segments)[0]
?.filter(segmentDurationFilter);
?.map((video) => video.segments)[0];
if (!recievedSegments || !recievedSegments.length) {
// return if no video found
retryFetch();
@@ -752,6 +749,55 @@ async function sponsorsLookup(id: string, keepOldSubmissions = true) {
sponsorLookupRetries++;
}
lookupVipInformation(id);
}
function lookupVipInformation(id: string): void {
updateVipInfo().then((isVip) => {
if (isVip) {
lockedCategoriesLookup(id);
}
});
}
async function updateVipInfo(): Promise<boolean> {
const currentTime = Date.now();
const lastUpdate = Config.config.lastIsVipUpdate;
if (currentTime - lastUpdate > 1000 * 60 * 60 * 72) { // 72 hours
Config.config.lastIsVipUpdate = currentTime;
const response = await utils.asyncRequestToServer("GET", "/api/isUserVIP", { userID: Config.config.userID});
if (response.ok) {
let isVip = false;
try {
const vipResponse = JSON.parse(response.responseText)?.vip;
if (typeof(vipResponse) === "boolean") {
isVip = vipResponse;
}
} catch (e) { } //eslint-disable-line no-empty
Config.config.isVip = isVip;
return isVip;
}
}
return Config.config.isVip;
}
async function lockedCategoriesLookup(id: string): Promise<void> {
const hashPrefix = (await utils.getHash(id, 1)).substr(0, 4);
const response = await utils.asyncRequestToServer("GET", "/api/lockCategories/" + hashPrefix);
if (response.ok) {
try {
const categoriesResponse = JSON.parse(response.responseText).filter((lockInfo) => lockInfo.videoID === id)[0]?.categories;
if (Array.isArray(categoriesResponse)) {
lockedCategories = categoriesResponse;
}
} catch (e) { } //eslint-disable-line no-empty
}
}
function retryFetch(): void {
@@ -1180,6 +1226,7 @@ function skipToTime({v, skipTime, skippingSegments, openNotice, forceAutoSkip, u
&& skippingSegments.length === 1
&& getCategoryActionType(skippingSegments[0].category) === CategoryActionType.POI) {
skipButtonControlBar.enable(skippingSegments[0], !Config.config.highlightCategoryUpdate ? 15 : 0);
if (onMobileYouTube) skipButtonControlBar.setShowKeybindHint(false);
if (!Config.config.highlightCategoryUpdate) {
new Tooltip({
@@ -1200,6 +1247,7 @@ function skipToTime({v, skipTime, skippingSegments, openNotice, forceAutoSkip, u
//send out the message saying that a sponsor message was skipped
if (!Config.config.dontShowNotice || !autoSkip) {
const newSkipNotice = new SkipNotice(skippingSegments, autoSkip, skipNoticeContentContainer, unskipTime);
if (onMobileYouTube) newSkipNotice.setShowKeybindHint(false);
skipNotices.push(newSkipNotice);
activeSkipKeybindElement?.setShowKeybindHint(false);
@@ -1287,27 +1335,6 @@ function shouldSkip(segment: SponsorTime): boolean {
(Config.config.autoSkipOnMusicVideos && sponsorTimes?.some((s) => s.category === "music_offtopic"));
}
function getControls(): HTMLElement | false {
const controlsSelectors = [
// YouTube
".ytp-right-controls",
// Mobile YouTube
".player-controls-top",
// Invidious/videojs video element's controls element
".vjs-control-bar",
];
for (const controlsSelector of controlsSelectors) {
const controls = document.querySelectorAll(controlsSelector);
if (controls && controls.length > 0) {
return <HTMLElement> controls[controls.length - 1];
}
}
return false;
}
/** Creates any missing buttons on the YouTube player if possible. */
async function createButtons(): Promise<void> {
if (onMobileYouTube) return;
@@ -1406,9 +1433,10 @@ function getRealCurrentTime(): number {
}
function startOrEndTimingNewSegment() {
const roundedTime = Math.round((getRealCurrentTime() + Number.EPSILON) * 1000) / 1000;
if (!isSegmentCreationInProgress()) {
sponsorTimesSubmitting.push({
segment: [getRealCurrentTime()],
segment: [roundedTime],
UUID: null,
category: Config.config.defaultCategory,
actionType: ActionType.Skip,
@@ -1418,7 +1446,7 @@ function startOrEndTimingNewSegment() {
// Finish creating the new segment
const existingSegment = getIncompleteSegment();
const existingTime = existingSegment.segment[0];
const currentTime = getRealCurrentTime();
const currentTime = roundedTime;
// Swap timestamps if the user put the segment end before the start
existingSegment.segment = [Math.min(existingTime, currentTime), Math.max(existingTime, currentTime)];
@@ -1683,8 +1711,12 @@ function resetSponsorSubmissionNotice() {
}
function submitSponsorTimes() {
if (submissionNotice !== null) return;
if (submissionNotice !== null){
submissionNotice.close();
submissionNotice = null;
return;
}
if (sponsorTimesSubmitting !== undefined && sponsorTimesSubmitting.length > 0) {
submissionNotice = new SubmissionNotice(skipNoticeContentContainer, sendSubmitMessage);
}

View File

@@ -197,8 +197,11 @@ class PreviewBar {
if (!this.onMobileYouTube) bar.style.opacity = Config.config.barTypes[fullCategoryName]?.opacity;
bar.style.position = "absolute";
const duration = segment[1] - segment[0];
if (segment[1] - segment[0] > 0) bar.style.width = this.timeToPercentage(segment[1] - segment[0]);
bar.style.left = this.timeToPercentage(segment[0]);
const time = segment[1] ? Math.min(this.videoDuration - Math.max(0, duration), segment[0]) : segment[0];
bar.style.left = this.timeToPercentage(time);
return bar;
}

View File

@@ -7,6 +7,7 @@ const utils = new Utils();
export interface SkipButtonControlBarProps {
skip: (segment: SponsorTime) => void;
onMobileYouTube: boolean;
}
export class SkipButtonControlBar {
@@ -18,18 +19,31 @@ export class SkipButtonControlBar {
segment: SponsorTime;
showKeybindHint = true;
onMobileYouTube: boolean;
enabled = false;
timeout: NodeJS.Timeout;
duration = 0;
skip: (segment: SponsorTime) => void;
// Used if on mobile page
hideButton: () => void;
showButton: () => void;
// Used by mobile only for swiping away
left = 0;
swipeStart = 0;
constructor(props: SkipButtonControlBarProps) {
this.skip = props.skip;
this.onMobileYouTube = props.onMobileYouTube;
this.container = document.createElement("div");
this.container.classList.add("skipButtonControlBarContainer");
this.container.classList.add("hidden");
if (this.onMobileYouTube) this.container.classList.add("mobile");
this.skipIcon = document.createElement("img");
this.skipIcon.src = chrome.runtime.getURL("icons/skipIcon.svg");
@@ -43,6 +57,11 @@ export class SkipButtonControlBar {
this.container.addEventListener("click", () => this.toggleSkip());
this.container.addEventListener("mouseenter", () => this.stopTimer());
this.container.addEventListener("mouseleave", () => this.startTimer());
if (this.onMobileYouTube) {
this.container.addEventListener("touchstart", (e) => this.handleTouchStart(e));
this.container.addEventListener("touchmove", (e) => this.handleTouchMove(e));
this.container.addEventListener("touchend", () => this.handleTouchEnd());
}
}
getElement(): HTMLElement {
@@ -50,21 +69,38 @@ export class SkipButtonControlBar {
}
attachToPage(): void {
const leftControlsContainer = document.querySelector(".ytp-left-controls");
const mountingContainer = this.getMountingContainer();
this.chapterText = document.querySelector(".ytp-chapter-container");
if (leftControlsContainer && !leftControlsContainer.contains(this.container)) {
leftControlsContainer.insertBefore(this.container, this.chapterText);
if (Config.config.autoHideInfoButton) {
utils.setupAutoHideAnimation(this.skipIcon, leftControlsContainer, false, false);
if (mountingContainer && !mountingContainer.contains(this.container)) {
if (this.onMobileYouTube) {
mountingContainer.appendChild(this.container);
} else {
mountingContainer.insertBefore(this.container, this.chapterText);
}
if (Config.config.autoHideInfoButton && !this.onMobileYouTube) {
utils.setupAutoHideAnimation(this.skipIcon, mountingContainer, false, false);
} else {
const { hide, show } = utils.setupCustomHideAnimation(this.skipIcon, mountingContainer, false, false);
this.hideButton = hide;
this.showButton = show;
}
}
}
private getMountingContainer(): HTMLElement {
if (!this.onMobileYouTube) {
return document.querySelector(".ytp-left-controls");
} else {
return document.getElementById("player-container-id");
}
}
enable(segment: SponsorTime, duration?: number): void {
if (duration) this.duration = duration;
this.segment = segment;
this.enabled = true;
this.refreshText();
this.textContainer?.classList?.remove("hidden");
@@ -103,6 +139,8 @@ export class SkipButtonControlBar {
this.chapterText?.classList?.remove("hidden");
this.getChapterPrefix()?.classList?.remove("hidden");
this.enabled = false;
}
toggleSkip(): void {
@@ -116,12 +154,28 @@ export class SkipButtonControlBar {
return;
}
this.container.classList.add("textDisabled");
this.textContainer?.classList?.add("hidden");
this.chapterText?.classList?.remove("hidden");
this.getChapterPrefix()?.classList?.add("hidden");
utils.enableAutoHideAnimation(this.skipIcon);
if (this.onMobileYouTube) {
this.hideButton();
}
}
updateMobileControls(): void {
const overlay = document.getElementById("player-control-overlay");
if (overlay && this.enabled) {
if (overlay?.classList?.contains("pointer-events-off")) {
this.hideButton();
} else {
this.showButton();
}
}
}
private getTitle(): string {
@@ -131,5 +185,37 @@ export class SkipButtonControlBar {
private getChapterPrefix(): HTMLElement {
return document.querySelector(".ytp-chapter-title-prefix");
}
// Swiping away on mobile
private handleTouchStart(event: TouchEvent): void {
this.swipeStart = event.touches[0].clientX;
}
// Swiping away on mobile
private handleTouchMove(event: TouchEvent): void {
const distanceMoved = this.swipeStart - event.touches[0].clientX;
this.left = Math.min(-distanceMoved, 0);
this.updateLeftStyle();
}
// Swiping away on mobile
private handleTouchEnd(): void {
if (this.left < -this.container.offsetWidth / 2) {
this.disableText();
// Don't let animation play
this.skipIcon.style.display = "none";
setTimeout(() => this.skipIcon.style.removeProperty("display"), 200);
}
this.left = 0;
this.updateLeftStyle();
}
// Swiping away on mobile
private updateLeftStyle() {
this.container.style.left = this.left + "px";
}
}

View File

@@ -31,9 +31,10 @@ interface IsInfoFoundMessage {
export type Message = BaseMessage & (DefaultMessage | BoolValueMessage | IsInfoFoundMessage);
interface IsInfoFoundMessageResponse {
export interface IsInfoFoundMessageResponse {
found: boolean;
sponsorTimes: SponsorTime[];
onMobileYouTube: boolean;
}
interface GetVideoIdResponse {

View File

@@ -2,7 +2,7 @@ import Config from "./config";
import Utils from "./utils";
import { SponsorTime, SponsorHideType, CategoryActionType } from "./types";
import { Message, MessageResponse } from "./messageTypes";
import { Message, MessageResponse, IsInfoFoundMessageResponse } from "./messageTypes";
import { showDonationLink } from "./utils/configUtils";
import { getCategoryActionType } from "./utils/categoryUtils";
const utils = new Utils();
@@ -278,7 +278,7 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> {
}, (tabs) => onTabs(tabs, updating));
}
function infoFound(request: { found: boolean, sponsorTimes: SponsorTime[] }) {
function infoFound(request: IsInfoFoundMessageResponse) {
if (chrome.runtime.lastError) {
//This page doesn't have the injected content script, or at least not yet
displayNoVideo();
@@ -289,6 +289,7 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> {
if (request != undefined) {
//remove loading text
PageElements.mainControls.style.display = "flex";
if (request.onMobileYouTube) PageElements.mainControls.classList.add("hidden");
PageElements.whitelistButton.classList.remove("hidden");
PageElements.loadingIndicator.style.display = "none";
@@ -379,8 +380,10 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> {
container.removeChild(container.firstChild);
}
const isVip = Config.config.isVip;
for (let i = 0; i < segmentTimes.length; i++) {
const UUID = segmentTimes[i].UUID;
const locked = segmentTimes[i].locked;
const sponsorTimeButton = document.createElement("button");
sponsorTimeButton.className = "segmentTimeButton popupElement";
@@ -430,7 +433,7 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> {
const downvoteButton = document.createElement("img");
downvoteButton.id = "sponsorTimesDownvoteButtonsContainer" + UUID;
downvoteButton.className = "voteButton";
downvoteButton.src = chrome.runtime.getURL("icons/thumbs_down.svg");
downvoteButton.src = locked && isVip ? chrome.runtime.getURL("icons/thumbs_down_locked.svg") : chrome.runtime.getURL("icons/thumbs_down.svg");
downvoteButton.addEventListener("click", () => vote(0, UUID));
//uuid button

View File

@@ -0,0 +1,95 @@
import * as React from "react";
import * as ReactDOM from "react-dom";
export interface RectangleTooltipProps {
text: string,
link?: string,
referenceNode: HTMLElement,
prependElement?: HTMLElement, // Element to append before
bottomOffset?: string,
leftOffset?: string,
timeout?: number,
htmlId?: string,
maxHeight?: string,
maxWidth?: string,
backgroundColor?: string,
fontSize?: string,
buttonFunction?: () => void;
}
export class RectangleTooltip {
text: string;
container: HTMLDivElement;
timer: NodeJS.Timeout;
constructor(props: RectangleTooltipProps) {
props.bottomOffset ??= "0px";
props.leftOffset ??= "0px";
props.maxHeight ??= "100px";
props.maxWidth ??= "300px";
props.backgroundColor ??= "rgba(28, 28, 28, 0.7)";
this.text = props.text;
props.fontSize ??= "10px";
this.container = document.createElement('div');
props.htmlId ??= props.text;
this.container.id = "sponsorRectangleTooltip" + props.htmlId;
this.container.style.display = "relative";
if (props.prependElement) {
props.referenceNode.insertBefore(this.container, props.prependElement);
} else {
props.referenceNode.appendChild(this.container);
}
if (props.timeout) {
this.timer = setTimeout(() => this.close(), props.timeout * 1000);
}
ReactDOM.render(
<div style={{
bottom: props.bottomOffset,
left: props.leftOffset,
maxHeight: props.maxHeight,
maxWidth: props.maxWidth,
backgroundColor: props.backgroundColor,
fontSize: props.fontSize}}
className="sponsorBlockRectangleTooltip" >
<div>
<img className="sponsorSkipLogo sponsorSkipObject"
src={chrome.extension.getURL("icons/IconSponsorBlocker256px.png")}>
</img>
<span className="sponsorSkipObject">
{this.text + (props.link ? ". " : "")}
{props.link ?
<a style={{textDecoration: "underline"}}
target="_blank"
rel="noopener noreferrer"
href={props.link}>
{chrome.i18n.getMessage("LearnMore")}
</a>
: null}
</span>
</div>
<button className="sponsorSkipObject sponsorSkipNoticeButton"
style ={{float: "right" }}
onClick={() => {
if (props.buttonFunction) props.buttonFunction();
this.close();
}}>
{chrome.i18n.getMessage("GotIt")}
</button>
</div>,
this.container
)
}
close(): void {
ReactDOM.unmountComponentAtNode(this.container);
this.container.remove();
if (this.timer) clearTimeout(this.timer);
}
}

View File

@@ -0,0 +1,18 @@
import * as React from "react";
const pencilSvg = ({
fill = "#ffffff"
}): JSX.Element => (
<svg
xmlns="http://www.w3.org/2000/svg"
width="18"
height="18"
viewBox="0 0 24 24"
fill={fill}
>
<path
d="M14.1 7.1l2.9 2.9L6.1 20.7l-3.6.7.7-3.6L14.1 7.1zm0-2.8L1.4 16.9 0 24l7.1-1.4L19.8 9.9l-5.7-5.7zm7.1 4.3L24 5.7 18.3 0l-2.8 2.8 5.7 5.7z"></path>
</svg>
);
export default pencilSvg;

View File

@@ -0,0 +1,23 @@
import * as React from "react";
const thumbsDownSvg = ({
fill = "#ffffff"
}): JSX.Element => (
<svg
xmlns="http://www.w3.org/2000/svg"
width="18"
height="18"
fill={fill}
viewBox="0 0 24 24"
>
<path
fill="none"
d="M0 0h24v24H0z">
</path>
<path
d="M15 3H6c-.83 0-1.54.5-1.84 1.22l-3.02 7.05c-.09.23-.14.47-.14.73v2c0 1.1.9 2 2 2h6.31l-.95 4.57-.03.32c0 .41.17.79.44 1.06L9.83 23l6.59-6.59c.36-.36.58-.86.58-1.41V5c0-1.1-.9-2-2-2zm4 0v12h4V3h-4z"
></path>
</svg>
);
export default thumbsDownSvg;

View File

@@ -0,0 +1,22 @@
import * as React from "react";
const thumbsUpSvg = ({
fill = "#ffffff"
}): JSX.Element => (
<svg
xmlns="http://www.w3.org/2000/svg"
width="18"
height="18"
fill={fill}
viewBox="0 0 24 24"
>
<path
fill="none"
d="M0 0h24v24H0V0z"></path>
<path
d="M1 21h4V9H1v12zm22-11c0-1.1-.9-2-2-2h-6.31l.95-4.57.03-.32c0-.41-.17-.79-.44-1.06L14.17 1 7.59 7.59C7.22 7.95 7 8.45 7 9v10c0 1.1.9 2 2 2h9c.83 0 1.54-.5 1.84-1.22l3.02-7.05c.09-.23.14-.47.14-.73v-2z"
></path>
</svg>
);
export default thumbsUpSvg;

View File

@@ -20,7 +20,8 @@ export interface ContentContainer {
updateEditButtonsOnPlayer: () => void,
previewTime: (time: number, unpause?: boolean) => void,
videoInfo: VideoInfo,
getRealCurrentTime: () => number
getRealCurrentTime: () => number,
lockedCategories: string[]
}
}
@@ -74,6 +75,7 @@ export enum SponsorSourceType {
export interface SponsorTime {
segment: [number] | [number, number];
UUID: SegmentUUID;
locked?: number;
category: Category;
actionType: ActionType;

View File

@@ -183,24 +183,38 @@ export default class Utils {
}
}
setupAutoHideAnimation(element: Element, container: Element, enabled = true, rightSlide = true): void {
setupCustomHideAnimation(element: Element, container: Element, enabled = true, rightSlide = true): { hide: () => void, show: () => void } {
if (enabled) element.classList.add("autoHiding");
element.classList.add("hidden");
element.classList.add("animationDone");
if (!rightSlide) element.classList.add("autoHideLeft");
container.addEventListener("mouseenter", () => {
element.classList.remove("animationDone");
let mouseEntered = false;
// Wait for next event loop
setTimeout(() => element.classList.remove("hidden"), 10);
});
container.addEventListener("mouseleave", () => {
if (element.classList.contains("autoHiding")) {
element.classList.add("hidden");
return {
hide: () => {
mouseEntered = false;
if (element.classList.contains("autoHiding")) {
element.classList.add("hidden");
}
},
show: () => {
mouseEntered = true;
element.classList.remove("animationDone");
// Wait for next event loop
setTimeout(() => {
if (mouseEntered) element.classList.remove("hidden")
}, 10);
}
});
};
}
setupAutoHideAnimation(element: Element, container: Element, enabled = true, rightSlide = true): void {
const { hide, show } = this.setupCustomHideAnimation(element, container, enabled, rightSlide);
container.addEventListener("mouseleave", () => hide());
container.addEventListener("mouseenter", () => show());
}
enableAutoHideAnimation(element: Element): void {
@@ -533,5 +547,4 @@ export default class Utils {
return hashHex;
}
}

20
src/utils/pageUtils.ts Normal file
View File

@@ -0,0 +1,20 @@
export function getControls(): HTMLElement | false {
const controlsSelectors = [
// YouTube
".ytp-right-controls",
// Mobile YouTube
".player-controls-top",
// Invidious/videojs video element's controls element
".vjs-control-bar",
];
for (const controlsSelector of controlsSelectors) {
const controls = document.querySelectorAll(controlsSelector);
if (controls && controls.length > 0) {
return <HTMLElement> controls[controls.length - 1];
}
}
return false;
}