mirror of
https://github.com/ajayyy/SponsorBlock.git
synced 2025-12-09 21:17:20 +03:00
Compare commits
83 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
510db57666 | ||
|
|
5ee6a2195d | ||
|
|
63d4c1aedb | ||
|
|
e9204be96f | ||
|
|
0863061665 | ||
|
|
8aea74160c | ||
|
|
d375a97e99 | ||
|
|
fe5499e80a | ||
|
|
598da2a7fe | ||
|
|
fcbeeb9fc1 | ||
|
|
d82ef63d89 | ||
|
|
a457a8009e | ||
|
|
7698be8462 | ||
|
|
738868da8d | ||
|
|
fc7fc693ed | ||
|
|
27f5997e5a | ||
|
|
45274f5c72 | ||
|
|
2bdfd3f39b | ||
|
|
9b9174ab9a | ||
|
|
3e3e9796b1 | ||
|
|
ff5fa4c724 | ||
|
|
b8ab05ccad | ||
|
|
93e440385f | ||
|
|
af66a77026 | ||
|
|
75607dea1c | ||
|
|
5b353b05ac | ||
|
|
3162ab93a1 | ||
|
|
b18f631d33 | ||
|
|
2e254cb917 | ||
|
|
77ce9433a7 | ||
|
|
509e54762f | ||
|
|
caeb347137 | ||
|
|
a2b054844a | ||
|
|
5b79d4ef48 | ||
|
|
3de66ebe23 | ||
|
|
60ef51b7f5 | ||
|
|
aa8ee02277 | ||
|
|
b927ebbbf7 | ||
|
|
d72d5dcbcb | ||
|
|
d9f703d808 | ||
|
|
a9cc43c586 | ||
|
|
844567dcdf | ||
|
|
52ed4f73f4 | ||
|
|
907bd68e4e | ||
|
|
f35afaf6bc | ||
|
|
85b1b51b76 | ||
|
|
9dc5449e37 | ||
|
|
6ea226c972 | ||
|
|
44f9ab9806 | ||
|
|
edd1011737 | ||
|
|
08558bfaeb | ||
|
|
4afc2c153a | ||
|
|
988905c155 | ||
|
|
51aab00985 | ||
|
|
84924b6364 | ||
|
|
93f02877a7 | ||
|
|
7baac9dcbf | ||
|
|
4045978b54 | ||
|
|
56bc3fca04 | ||
|
|
c571a9ecb6 | ||
|
|
1ad60720df | ||
|
|
e5fe99c89b | ||
|
|
3fc32a68c3 | ||
|
|
142cc2881f | ||
|
|
4de55ea5fe | ||
|
|
620e75517c | ||
|
|
cba26a42af | ||
|
|
f3f598d6c7 | ||
|
|
fe7d9986fa | ||
|
|
143ca6f6e0 | ||
|
|
69ce065588 | ||
|
|
bfa31429f1 | ||
|
|
66f0cc8883 | ||
|
|
1a0ac27e49 | ||
|
|
7b87ae7b08 | ||
|
|
9ab8e63b1d | ||
|
|
0e147134f3 | ||
|
|
8605e23fbb | ||
|
|
5f34a777f1 | ||
|
|
1f43d07e16 | ||
|
|
a88aaf4590 | ||
|
|
25f78ed55b | ||
|
|
26e73c515c |
4
.github/workflows/ci.yml
vendored
4
.github/workflows/ci.yml
vendored
@@ -12,7 +12,9 @@ jobs:
|
||||
# Initialization
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
- run: npm install
|
||||
with:
|
||||
node-version: '16'
|
||||
- run: npm ci
|
||||
- name: Copy configuration
|
||||
run: cp config.json.example config.json
|
||||
|
||||
|
||||
4
.github/workflows/release.yml
vendored
4
.github/workflows/release.yml
vendored
@@ -14,7 +14,9 @@ jobs:
|
||||
# Initialization
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
- run: npm install
|
||||
with:
|
||||
node-version: '16'
|
||||
- run: npm ci
|
||||
- name: Copy configuration
|
||||
run: cp config.json.example config.json
|
||||
|
||||
|
||||
20
.github/workflows/tests.yml
vendored
Normal file
20
.github/workflows/tests.yml
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
name: Tests
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
|
||||
build:
|
||||
name: Run tests
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
# Initialization
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: '16'
|
||||
- run: npm ci
|
||||
|
||||
- name: Run tests
|
||||
run: npm run test-without-building
|
||||
@@ -60,6 +60,8 @@ You can read the API docs [here](https://wiki.sponsor.ajay.app/index.php/API_Doc
|
||||
|
||||
# Building
|
||||
|
||||
You must have Node.js 16 installed.
|
||||
|
||||
Rename `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.
|
||||
|
||||
@@ -12,5 +12,17 @@
|
||||
"preview": ["skip"],
|
||||
"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",
|
||||
"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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "__MSG_fullName__",
|
||||
"short_name": "SponsorBlock",
|
||||
"version": "3.3.1",
|
||||
"version": "3.4",
|
||||
"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",
|
||||
|
||||
2234
package-lock.json
generated
2234
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -182,15 +182,15 @@
|
||||
"hideButtonsDescription": {
|
||||
"message": "Това скрива бутоните, които се показват в плейъра на YouTube за изпращане на сегменти за пропускане."
|
||||
},
|
||||
"showSkipButton": {
|
||||
"message": "Оставяне в плейъра на бутона за преминаване към акцента"
|
||||
},
|
||||
"showInfoButton": {
|
||||
"message": "Показване на бутона за информация в плейъра на YouTube"
|
||||
},
|
||||
"hideInfoButton": {
|
||||
"message": "Скриване на бутона за информация в плейъра на YouTube"
|
||||
},
|
||||
"whatInfoButton": {
|
||||
"message": "Това е бутонът, който отваря изскачащ прозорец в страницата на YouTube."
|
||||
},
|
||||
"autoHideInfoButton": {
|
||||
"message": "Автоматично скриване на бутона за информация"
|
||||
},
|
||||
@@ -200,9 +200,6 @@
|
||||
"showDeleteButton": {
|
||||
"message": "Показване на бутона за изтриване в плейъра на YouTube"
|
||||
},
|
||||
"whatDeleteButton": {
|
||||
"message": "Това е бутонът в плейъра на YouTube, който ще изчисти всичките ви неизпратени сегменти за текущия видеоклип."
|
||||
},
|
||||
"enableViewTracking": {
|
||||
"message": "Активиране проследяването на броя пропускания"
|
||||
},
|
||||
@@ -442,9 +439,6 @@
|
||||
"showUploadButton": {
|
||||
"message": "Показване на бутона за качване"
|
||||
},
|
||||
"whatUploadButton": {
|
||||
"message": "Този бутон се появява в плейъра на YouTube, след като сте избрали времева отметка и сте готови за изпращане."
|
||||
},
|
||||
"customServerAddress": {
|
||||
"message": "Адрес на сървъра на SponsorBlock"
|
||||
},
|
||||
@@ -816,5 +810,8 @@
|
||||
},
|
||||
"LearnMore": {
|
||||
"message": "Научете повече"
|
||||
},
|
||||
"SponsorTimeEditScrollNewFeature": {
|
||||
"message": "Използвайте колелото на мишката, докато държите курсора върху полето за редактиране, за да коригирате бързо времето. Комбинации с клавиша ctrl или shift могат да се използват за фина настройка на промените."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,15 +182,15 @@
|
||||
"hideButtonsDescription": {
|
||||
"message": "Skryje tlačítka, která se zobrazí v YouTube přehrávači pro přeskočení segmentů."
|
||||
},
|
||||
"showSkipButton": {
|
||||
"message": "Nechat tlačítko přeskočení na zvýraznění v přehrávači"
|
||||
},
|
||||
"showInfoButton": {
|
||||
"message": "Zobrazit informační tlačítko v YouTube přehrávači"
|
||||
},
|
||||
"hideInfoButton": {
|
||||
"message": "Skrýt informační tlačítko v YouTube přehrávači"
|
||||
},
|
||||
"whatInfoButton": {
|
||||
"message": "Toto je tlačítko, které otevře vyskakovací nabídku na YouTube stránce."
|
||||
},
|
||||
"autoHideInfoButton": {
|
||||
"message": "Automaticky skrýt informační tlačítko"
|
||||
},
|
||||
@@ -200,9 +200,6 @@
|
||||
"showDeleteButton": {
|
||||
"message": "Zobrazit tlačítko Odstranit v YouTube přehrávači"
|
||||
},
|
||||
"whatDeleteButton": {
|
||||
"message": "Toto je tlačítko v YouTube přehrávači, které odebere všechny vaše neodeslané segmenty v současném videu."
|
||||
},
|
||||
"enableViewTracking": {
|
||||
"message": "Povolit počítadlo přeskočení"
|
||||
},
|
||||
@@ -442,9 +439,6 @@
|
||||
"showUploadButton": {
|
||||
"message": "Zobrazit tlačítko Nahrát"
|
||||
},
|
||||
"whatUploadButton": {
|
||||
"message": "Toto tlačítko se objeví v YouTube přehrávači po vybrání časového razítka a po připravení k odeslání."
|
||||
},
|
||||
"customServerAddress": {
|
||||
"message": "Adresa serveru SponsorBlock"
|
||||
},
|
||||
@@ -816,5 +810,8 @@
|
||||
},
|
||||
"LearnMore": {
|
||||
"message": "Zjistit více"
|
||||
},
|
||||
"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."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,15 +182,15 @@
|
||||
"hideButtonsDescription": {
|
||||
"message": "Versteckt die Schaltflächen im YouTube-Videoplayer, um Segmente einzusenden."
|
||||
},
|
||||
"showSkipButton": {
|
||||
"message": "\"Zum Highlight springen\"-Knopf im Player behalten"
|
||||
},
|
||||
"showInfoButton": {
|
||||
"message": "Zeige Info-Knopf im Youtube-Videoplayer"
|
||||
},
|
||||
"hideInfoButton": {
|
||||
"message": "Deaktiviere Info-Knopf im Youtube-Videoplayer"
|
||||
},
|
||||
"whatInfoButton": {
|
||||
"message": "Dieser Knopf öffnet ein Pop-up auf der Youtube-Seite."
|
||||
},
|
||||
"autoHideInfoButton": {
|
||||
"message": "Info-Button automatisch ausblenden"
|
||||
},
|
||||
@@ -200,9 +200,6 @@
|
||||
"showDeleteButton": {
|
||||
"message": "Zeige den Löschen-Knopf im Youtube-Videoplayer"
|
||||
},
|
||||
"whatDeleteButton": {
|
||||
"message": "Dieser Knopf im YouTube-Videoplayer löscht alle nicht übermittelten Segmente für das aktuelle Video."
|
||||
},
|
||||
"enableViewTracking": {
|
||||
"message": "Aktiviere das Zählen übersprungener Segmente"
|
||||
},
|
||||
@@ -442,9 +439,6 @@
|
||||
"showUploadButton": {
|
||||
"message": "Upload-Knopf anzeigen"
|
||||
},
|
||||
"whatUploadButton": {
|
||||
"message": "Dieser Knopf erscheint im YouTube-Videoplayer, nachdem du ein Videosegment markiert hast und dazu bereit bist, es zu übermitteln."
|
||||
},
|
||||
"customServerAddress": {
|
||||
"message": "SponsorBlock Serveradresse"
|
||||
},
|
||||
@@ -816,5 +810,8 @@
|
||||
},
|
||||
"LearnMore": {
|
||||
"message": "Erfahre mehr"
|
||||
},
|
||||
"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."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -183,7 +183,7 @@
|
||||
"message": "This hides the buttons that appear on the YouTube player to submit skip segments."
|
||||
},
|
||||
"showSkipButton": {
|
||||
"message": "Keep Skip to Highlight Button on Player"
|
||||
"message": "Keep Skip To Highlight Button On Player"
|
||||
},
|
||||
"showInfoButton": {
|
||||
"message": "Show Info Button On YouTube Player"
|
||||
@@ -700,7 +700,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 +810,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."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,15 +182,15 @@
|
||||
"hideButtonsDescription": {
|
||||
"message": "Esto oculta los botones que aparecen en el reproductor de YouTube que se usan para enviar segmentos saltados."
|
||||
},
|
||||
"showSkipButton": {
|
||||
"message": "Mantener el Botón de \"Saltar a Destacado\" en el Reproductor"
|
||||
},
|
||||
"showInfoButton": {
|
||||
"message": "Mostrar botón de información en el reproductor de YouTube"
|
||||
},
|
||||
"hideInfoButton": {
|
||||
"message": "Ocultar botón de información en el reproductor de YouTube"
|
||||
},
|
||||
"whatInfoButton": {
|
||||
"message": "Este es el botón que abre una ventana en la página de YouTube."
|
||||
},
|
||||
"autoHideInfoButton": {
|
||||
"message": "Ocular automáticamente el Botón de Información"
|
||||
},
|
||||
@@ -200,9 +200,6 @@
|
||||
"showDeleteButton": {
|
||||
"message": "Mostrar botón de eliminar en el reproductor de YouTube"
|
||||
},
|
||||
"whatDeleteButton": {
|
||||
"message": "Este es el botón en el reproductor de YouTube que eliminará todos tus segmentos no enviados para el vídeo actual."
|
||||
},
|
||||
"enableViewTracking": {
|
||||
"message": "Habilitar el conteo de omisiones"
|
||||
},
|
||||
@@ -442,9 +439,6 @@
|
||||
"showUploadButton": {
|
||||
"message": "Mostrar botón de subida"
|
||||
},
|
||||
"whatUploadButton": {
|
||||
"message": "Este botón aparece en el reproductor de YouTube después de que has seleccionado una marca de tiempo y estas listo para enviar."
|
||||
},
|
||||
"customServerAddress": {
|
||||
"message": "Dirección del servidor SponsorBlock"
|
||||
},
|
||||
@@ -816,5 +810,8 @@
|
||||
},
|
||||
"LearnMore": {
|
||||
"message": "Aprenda Más"
|
||||
},
|
||||
"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."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,15 +182,15 @@
|
||||
"hideButtonsDescription": {
|
||||
"message": "See peidab nupud, mis kuvatakse YouTube'i mängijal vahelejätmiste segmentide saatmiseks."
|
||||
},
|
||||
"showSkipButton": {
|
||||
"message": "Hoia esiletõstuni vahelejätmise nuppu mängijal"
|
||||
},
|
||||
"showInfoButton": {
|
||||
"message": "Kuva YouTube'i mängijal infonupp"
|
||||
},
|
||||
"hideInfoButton": {
|
||||
"message": "Peida YouTube'i mängijal infonupp"
|
||||
},
|
||||
"whatInfoButton": {
|
||||
"message": "See on see nupp, mis avab YouTube'i lehel hüpiku."
|
||||
},
|
||||
"autoHideInfoButton": {
|
||||
"message": "Peida infonupp automaatselt"
|
||||
},
|
||||
@@ -200,9 +200,6 @@
|
||||
"showDeleteButton": {
|
||||
"message": "Kuva YouTube'i mängijal kustutusnupp"
|
||||
},
|
||||
"whatDeleteButton": {
|
||||
"message": "YouTube'i mängija nupp, mis tühjendab kõik sinu praeguse video saatmata segmendid."
|
||||
},
|
||||
"enableViewTracking": {
|
||||
"message": "Luba vahelejätmiste arvu jälgimine"
|
||||
},
|
||||
@@ -442,9 +439,6 @@
|
||||
"showUploadButton": {
|
||||
"message": "Kuva üleslaadimisnupp"
|
||||
},
|
||||
"whatUploadButton": {
|
||||
"message": "See nupp kuvatakse YouTube'i mängijal, kui oled ajatempli ära valinud ning saatmiseks valmis."
|
||||
},
|
||||
"customServerAddress": {
|
||||
"message": "SponsorBlocki serveri aadress"
|
||||
},
|
||||
@@ -771,5 +765,8 @@
|
||||
},
|
||||
"LearnMore": {
|
||||
"message": "Lisateave"
|
||||
},
|
||||
"SponsorTimeEditScrollNewFeature": {
|
||||
"message": "Kasuta hiirekursorit muutmiskasti kohal, et kiirelt aega reguleerida. Täpsemaks muutmiseks hoia kerimise ajal all Ctrl või Shift klahvi."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,6 +182,9 @@
|
||||
"message": "کار شما",
|
||||
"description": "Used to describe the section that will show you the statistics from your submissions."
|
||||
},
|
||||
"502": {
|
||||
"message": "به نظر میرسد سرور زیر فشار است. چند ثانیهی دیگر دوباره امتحان کنید."
|
||||
},
|
||||
"errorCode": {
|
||||
"message": "کد خطا: "
|
||||
},
|
||||
@@ -191,6 +194,12 @@
|
||||
"mute": {
|
||||
"message": "بیصدا"
|
||||
},
|
||||
"minLower": {
|
||||
"message": "دقیقه"
|
||||
},
|
||||
"hourLower": {
|
||||
"message": "ساعت"
|
||||
},
|
||||
"createdBy": {
|
||||
"message": "ایجاد شده توسط"
|
||||
},
|
||||
|
||||
@@ -182,15 +182,15 @@
|
||||
"hideButtonsDescription": {
|
||||
"message": "Tämä piilottaa YouTuben soittimessa näkyvät, ohitettavien aikojen lähettämiseen käytetyt painikkeet."
|
||||
},
|
||||
"showSkipButton": {
|
||||
"message": "Pidä \"Ohita kohtaan: Kohokohta\" -painike soittimessa"
|
||||
},
|
||||
"showInfoButton": {
|
||||
"message": "Näytä info-painike YouTuben soittimessa"
|
||||
},
|
||||
"hideInfoButton": {
|
||||
"message": "Piilota info-painike YouTuben soittimessa"
|
||||
},
|
||||
"whatInfoButton": {
|
||||
"message": "Tämä on painike, joka avaa ponnahdusikkunan YouTube-sivulla."
|
||||
},
|
||||
"autoHideInfoButton": {
|
||||
"message": "Piilota info-painike automaattisesti"
|
||||
},
|
||||
@@ -200,9 +200,6 @@
|
||||
"showDeleteButton": {
|
||||
"message": "Näytä poista-painike YouTuben soittimessa"
|
||||
},
|
||||
"whatDeleteButton": {
|
||||
"message": "Tämä on YouTuben soittimen painike, joka poistaa kaikki kyseisen videon sponsorointikohdat, joita et ole vielä lähettänyt."
|
||||
},
|
||||
"enableViewTracking": {
|
||||
"message": "Ota ohitusten lukumäärän seuranta käyttöön"
|
||||
},
|
||||
@@ -442,9 +439,6 @@
|
||||
"showUploadButton": {
|
||||
"message": "Näytä lähetä-painike"
|
||||
},
|
||||
"whatUploadButton": {
|
||||
"message": "Tämä painike ilmestyy YouTube-soittimeen, kun olet valinnut aikaleiman ja olet valmis lähettämään sen."
|
||||
},
|
||||
"customServerAddress": {
|
||||
"message": "SponsorBlock-palvelimen osoite"
|
||||
},
|
||||
@@ -816,5 +810,8 @@
|
||||
},
|
||||
"LearnMore": {
|
||||
"message": "Opi lisää"
|
||||
},
|
||||
"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."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,15 +182,15 @@
|
||||
"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"
|
||||
},
|
||||
"hideInfoButton": {
|
||||
"message": "Cacher le bouton Info sur le lecteur YouTube"
|
||||
},
|
||||
"whatInfoButton": {
|
||||
"message": "Il s'agit du bouton qui ouvre l'encart sur la page YouTube."
|
||||
},
|
||||
"autoHideInfoButton": {
|
||||
"message": "Masquer Automatiquement Le Button Info"
|
||||
},
|
||||
@@ -200,9 +200,6 @@
|
||||
"showDeleteButton": {
|
||||
"message": "Montrer le bouton Supprimer sur le lecteur YouTube"
|
||||
},
|
||||
"whatDeleteButton": {
|
||||
"message": "Il s'agit du bouton qui permet de supprimer tous les segments commerciaux depuis le lecteur YouTube."
|
||||
},
|
||||
"enableViewTracking": {
|
||||
"message": "Activer le suivi du nombre de sauts de segments"
|
||||
},
|
||||
@@ -309,7 +306,7 @@
|
||||
"message": "Passer {0} ?"
|
||||
},
|
||||
"mute_category": {
|
||||
"message": "Mute {0}?"
|
||||
"message": "Mettre en sourdine {0} ?"
|
||||
},
|
||||
"skip_to_category": {
|
||||
"message": "Passer à {0}?",
|
||||
@@ -442,9 +439,6 @@
|
||||
"showUploadButton": {
|
||||
"message": "Afficher le bouton de téléchargement"
|
||||
},
|
||||
"whatUploadButton": {
|
||||
"message": "Ce bouton apparaît sur le lecteur YouTube dès qu'un segment est prêt à être envoyé."
|
||||
},
|
||||
"customServerAddress": {
|
||||
"message": "Adresse du serveur SponsorBlock"
|
||||
},
|
||||
@@ -657,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 !"
|
||||
@@ -741,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."
|
||||
@@ -813,5 +810,8 @@
|
||||
},
|
||||
"LearnMore": {
|
||||
"message": "En savoir plus"
|
||||
},
|
||||
"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."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,9 +182,6 @@
|
||||
"hideInfoButton": {
|
||||
"message": "Info gomb elrejtése a YouTube lejátszón"
|
||||
},
|
||||
"whatInfoButton": {
|
||||
"message": "Ez a gomb felhoz egy felugró dobozt a YouTube oldalon."
|
||||
},
|
||||
"autoHideInfoButton": {
|
||||
"message": "Automatikus elrejtése az Információ Gombnak"
|
||||
},
|
||||
@@ -194,9 +191,6 @@
|
||||
"showDeleteButton": {
|
||||
"message": "Törlés gomb mutatása a YouTube lejátszón"
|
||||
},
|
||||
"whatDeleteButton": {
|
||||
"message": "Ez egy gomb a lejátszón, ami törli az összes beküldetlen szegmensét a jelenlegi videón."
|
||||
},
|
||||
"enableViewTracking": {
|
||||
"message": "Átugrás-számláló követés bekapcsolása"
|
||||
},
|
||||
@@ -371,9 +365,6 @@
|
||||
"showUploadButton": {
|
||||
"message": "Feltöltés gomb megjelenítése"
|
||||
},
|
||||
"whatUploadButton": {
|
||||
"message": "Ez a gomb a YouTube lejátszón jelenik meg, miután kiválasztott egy időtartamot és készen áll a beküldésre."
|
||||
},
|
||||
"customServerAddress": {
|
||||
"message": "SponsorBlock szerver címe"
|
||||
},
|
||||
|
||||
@@ -52,6 +52,9 @@
|
||||
"reskip": {
|
||||
"message": "Lewati Ulang"
|
||||
},
|
||||
"unmute": {
|
||||
"message": "Batalkan bisu"
|
||||
},
|
||||
"paused": {
|
||||
"message": "Dijeda"
|
||||
},
|
||||
@@ -85,6 +88,9 @@
|
||||
"noVideoID": {
|
||||
"message": "Video YouTube tidak ditemukan.\nJika terjadi kesalahan, segarkan halaman."
|
||||
},
|
||||
"refreshSegments": {
|
||||
"message": "Perbarui segmen"
|
||||
},
|
||||
"success": {
|
||||
"message": "Sukses!"
|
||||
},
|
||||
@@ -155,6 +161,9 @@
|
||||
"setUsername": {
|
||||
"message": "Atur Nama Pengguna"
|
||||
},
|
||||
"copyPublicID": {
|
||||
"message": "Salin UserID Publik"
|
||||
},
|
||||
"discordAdvert": {
|
||||
"message": "Gabung dengan server resmi discord untuk memberikan kritik dan saran!"
|
||||
},
|
||||
@@ -173,14 +182,17 @@
|
||||
"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"
|
||||
},
|
||||
"hideInfoButton": {
|
||||
"message": "Sembunyikan Tombol Info Di Pemutar Video YouTube"
|
||||
},
|
||||
"whatInfoButton": {
|
||||
"message": "Ini adalah tombol yang membuka popup di halaman YouTube."
|
||||
"autoHideInfoButton": {
|
||||
"message": "Otomatis Sembunyikan Tombol Info"
|
||||
},
|
||||
"hideDeleteButton": {
|
||||
"message": "Sembunyikan Tombol Hapus Di Pemutar Video YouTube"
|
||||
@@ -188,9 +200,6 @@
|
||||
"showDeleteButton": {
|
||||
"message": "Tampilkan Tombol Hapus Di Pemutar Video YouTube"
|
||||
},
|
||||
"whatDeleteButton": {
|
||||
"message": "Ini adalah tombol di pemutar YouTube yang akan menghapus semua segmen yang belum dikirim pada video."
|
||||
},
|
||||
"enableViewTracking": {
|
||||
"message": "Aktifkan Pelacakan Jumlah Lewati"
|
||||
},
|
||||
@@ -201,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."
|
||||
@@ -218,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."
|
||||
@@ -275,9 +299,15 @@
|
||||
"skip": {
|
||||
"message": "Lewati"
|
||||
},
|
||||
"mute": {
|
||||
"message": "Bisukan"
|
||||
},
|
||||
"skip_category": {
|
||||
"message": "Lewati {0}?"
|
||||
},
|
||||
"mute_category": {
|
||||
"message": "Bisukan {0}?"
|
||||
},
|
||||
"skip_to_category": {
|
||||
"message": "Lompat ke {0}?",
|
||||
"description": "Used for skipping to things (Skip to Highlight)"
|
||||
@@ -286,6 +316,10 @@
|
||||
"message": "{0} dilewati",
|
||||
"description": "Example: Sponsor Skipped"
|
||||
},
|
||||
"muted": {
|
||||
"message": "{0} Dibisukan",
|
||||
"description": "Example: Sponsor Muted"
|
||||
},
|
||||
"skipped_to_category": {
|
||||
"message": "Melewati ke {0}",
|
||||
"description": "Used for skipping to things (Skipped to Highlight)"
|
||||
@@ -338,6 +372,9 @@
|
||||
"changeUserID": {
|
||||
"message": "Impor/Ekspor UserID"
|
||||
},
|
||||
"whatChangeUserID": {
|
||||
"message": "Ini harus dirahasiakan. Ini seperti kata sandi dan tidak boleh dibagikan kepada siapa pun. Jika seseorang mempunyai ini, mereka bisa menyamar jadi anda. Jika anda mencari UserID publik anda, klik ikon papan tulis di popup."
|
||||
},
|
||||
"setUserID": {
|
||||
"message": "Atur UserID"
|
||||
},
|
||||
@@ -353,9 +390,22 @@
|
||||
"supportOtherSites": {
|
||||
"message": "Dukung Situs Youtube Pihak Ketiga"
|
||||
},
|
||||
"supportOtherSitesDescription": {
|
||||
"message": "Dukung klien YouTube pihak ketiga. Untuk mengaktifkan dukungan, anda harus menerima izin tambahan. Ini tidak akan bekerja di Mode Samaran di Chrome dan varian Chromium lainnya.",
|
||||
"description": "This replaces the 'supports Invidious' option because it now works on other YouTube sites such as Cloudtube"
|
||||
},
|
||||
"supportedSites": {
|
||||
"message": "Situs yang didukung: "
|
||||
},
|
||||
"optionsInfo": {
|
||||
"message": "Aktifkan dukungan Invidious, nonaktifkan lewati otomatis, tombol sembunyi dan lainnya."
|
||||
},
|
||||
"addInvidiousInstance": {
|
||||
"message": "Tambah Instansi Klien Pihak Ketiga"
|
||||
},
|
||||
"addInvidiousInstanceDescription": {
|
||||
"message": "Tambahkan instansi khusus. Ini harus diformat Hanya dengan domain. Contoh: invidious.ajay.app"
|
||||
},
|
||||
"add": {
|
||||
"message": "Tambah"
|
||||
},
|
||||
@@ -377,15 +427,18 @@
|
||||
"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?"
|
||||
},
|
||||
"showUploadButton": {
|
||||
"message": "Tampilkan Tombol Unggah"
|
||||
},
|
||||
"whatUploadButton": {
|
||||
"message": "Tombol ini muncul di pemutar video YouTube setelah anda memilih stempel waktu dan siap untuk dikirimkan."
|
||||
},
|
||||
"customServerAddress": {
|
||||
"message": "Alamat Server SponsorBlock"
|
||||
},
|
||||
@@ -519,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"
|
||||
},
|
||||
@@ -537,6 +596,9 @@
|
||||
"disable": {
|
||||
"message": "Nonaktif"
|
||||
},
|
||||
"autoSkip_POI": {
|
||||
"message": "Otomatis lewati ke awal"
|
||||
},
|
||||
"manualSkip_POI": {
|
||||
"message": "Tanya saat video dimuat"
|
||||
},
|
||||
@@ -546,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."
|
||||
},
|
||||
@@ -585,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!"
|
||||
},
|
||||
@@ -660,9 +728,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"
|
||||
},
|
||||
@@ -675,7 +754,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."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -188,9 +188,6 @@
|
||||
"hideInfoButton": {
|
||||
"message": "Nascondi il pulsante d'informazioni sopra al video"
|
||||
},
|
||||
"whatInfoButton": {
|
||||
"message": "Questo è il pulsante che apre un popup nella pagina YouTube."
|
||||
},
|
||||
"autoHideInfoButton": {
|
||||
"message": "Nascondi in automatico il Pulsante di Informazioni"
|
||||
},
|
||||
@@ -200,9 +197,6 @@
|
||||
"showDeleteButton": {
|
||||
"message": "Mostra il pulsante elimina"
|
||||
},
|
||||
"whatDeleteButton": {
|
||||
"message": "Questo è il pulsante che ti permette di cancellare tutti i segmenti non inviati del video attuale."
|
||||
},
|
||||
"enableViewTracking": {
|
||||
"message": "Attiva il conteggio dei salti"
|
||||
},
|
||||
@@ -442,9 +436,6 @@
|
||||
"showUploadButton": {
|
||||
"message": "Mostra Pulsante di Caricamento"
|
||||
},
|
||||
"whatUploadButton": {
|
||||
"message": "Questo pulsante appare sul riproduttore di YouTube dopo che hai selezionato un marcatore temporale e sei pronto ad inviarlo."
|
||||
},
|
||||
"customServerAddress": {
|
||||
"message": "Indirizzo Server SponsorBlock"
|
||||
},
|
||||
|
||||
@@ -182,9 +182,6 @@
|
||||
"hideInfoButton": {
|
||||
"message": "YouTubeプレーヤーの情報ボタンを隠す"
|
||||
},
|
||||
"whatInfoButton": {
|
||||
"message": "これはYouTubeのページ上でポップアップを開くためのボタンです。"
|
||||
},
|
||||
"autoHideInfoButton": {
|
||||
"message": "情報ボタンを自動的に隠す"
|
||||
},
|
||||
@@ -194,9 +191,6 @@
|
||||
"showDeleteButton": {
|
||||
"message": "YouTubeプレーヤーに削除ボタンを表示"
|
||||
},
|
||||
"whatDeleteButton": {
|
||||
"message": "これはYouTubeプレーヤー上のボタンで、現在の動画から未提出のセグメントを全て消去します。"
|
||||
},
|
||||
"enableViewTracking": {
|
||||
"message": "スキップ回数の統計を有効にする"
|
||||
},
|
||||
@@ -423,9 +417,6 @@
|
||||
"showUploadButton": {
|
||||
"message": "アップロードボタンを表示"
|
||||
},
|
||||
"whatUploadButton": {
|
||||
"message": "このボタンはタイムスタンプを選択して投稿の準備ができた後にYouTubeプレーヤーに表示されます。"
|
||||
},
|
||||
"customServerAddress": {
|
||||
"message": "SponsorBlock サーバーアドレス"
|
||||
},
|
||||
|
||||
@@ -182,15 +182,15 @@
|
||||
"hideButtonsDescription": {
|
||||
"message": "스킵할 구간을 제출하기 위해 YouTube 플레이어에 나타나는 버튼을 숨깁니다"
|
||||
},
|
||||
"showSkipButton": {
|
||||
"message": "플레이어에 하이라이트로 건너뛰기 버튼 표시"
|
||||
},
|
||||
"showInfoButton": {
|
||||
"message": "YouTube 플레이어에서 정보 버튼 표시하기"
|
||||
},
|
||||
"hideInfoButton": {
|
||||
"message": "YouTube 플레이어에서 정보 버튼 숨기기"
|
||||
},
|
||||
"whatInfoButton": {
|
||||
"message": "YouTube 페이지에 팝업으로 표시되는 버튼입니다"
|
||||
},
|
||||
"autoHideInfoButton": {
|
||||
"message": "정보 버튼 자동 숨김"
|
||||
},
|
||||
@@ -200,9 +200,6 @@
|
||||
"showDeleteButton": {
|
||||
"message": "YouTube 플레이어에서 삭제 버튼 표시하기"
|
||||
},
|
||||
"whatDeleteButton": {
|
||||
"message": "현재 영상에 제출되지 않은 구간을 YouTube 플레이어 내에서 지우는 버튼입니다"
|
||||
},
|
||||
"enableViewTracking": {
|
||||
"message": "스킵 개수 추적 활성화"
|
||||
},
|
||||
@@ -442,9 +439,6 @@
|
||||
"showUploadButton": {
|
||||
"message": "업로드 버튼 표시"
|
||||
},
|
||||
"whatUploadButton": {
|
||||
"message": "이 버튼은 타임 스탬프를 설정 후 제출 준비가 되었을 때 YouTube 플레이어에 나타납니다."
|
||||
},
|
||||
"customServerAddress": {
|
||||
"message": "SponsorBlock 서버 주소"
|
||||
},
|
||||
@@ -816,5 +810,8 @@
|
||||
},
|
||||
"LearnMore": {
|
||||
"message": "더보기"
|
||||
},
|
||||
"SponsorTimeEditScrollNewFeature": {
|
||||
"message": "편집 상자 위에 커서를 올린 채 스크롤하면 시간을 빠르게 조정할 수 있습니다. Ctrl이나 Shift 키를 누른 채로 스크롤하면 세밀한 조정이 가능합니다."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,18 +176,12 @@
|
||||
"hideInfoButton": {
|
||||
"message": "YouTube പ്ലെയറിൽ വിവര ബട്ടൺ മറയ്ക്കുക"
|
||||
},
|
||||
"whatInfoButton": {
|
||||
"message": "YouTube പേജിൽ ഒരു പോപ്പ്അപ്പ് തുറക്കുന്ന ബട്ടണാണിത്."
|
||||
},
|
||||
"hideDeleteButton": {
|
||||
"message": "YouTube പ്ലെയറിൽ ഇല്ലാതാക്കുക ബട്ടൺ മറയ്ക്കുക"
|
||||
},
|
||||
"showDeleteButton": {
|
||||
"message": "YouTube പ്ലെയറിൽ ഇല്ലാതാക്കുക ബട്ടൺ കാണിക്കുക"
|
||||
},
|
||||
"whatDeleteButton": {
|
||||
"message": "നിലവിലെ വീഡിയോയ്ക്കായി നിങ്ങൾ സമർപ്പിക്കാത്ത എല്ലാ സെഗ്മെന്റുകളും മായ്ക്കുന്ന YouTube പ്ലെയറിലെ ബട്ടൺ ഇതാണ്."
|
||||
},
|
||||
"enableViewTracking": {
|
||||
"message": "ക Count ണ്ട് ട്രാക്കിംഗ് ഒഴിവാക്കുക പ്രാപ്തമാക്കുക"
|
||||
},
|
||||
@@ -359,9 +353,6 @@
|
||||
"showUploadButton": {
|
||||
"message": "അപ്ലോഡ് ബട്ടൺ കാണിക്കുക"
|
||||
},
|
||||
"whatUploadButton": {
|
||||
"message": "നിങ്ങൾ ഒരു ടൈംസ്റ്റാമ്പ് തിരഞ്ഞെടുത്ത് സമർപ്പിക്കാൻ തയ്യാറായ ശേഷം ഈ ബട്ടൺ YouTube പ്ലെയറിൽ ദൃശ്യമാകും."
|
||||
},
|
||||
"customServerAddress": {
|
||||
"message": "സ്പോൺസർബ്ലോക്ക് സെർവർ വിലാസം"
|
||||
},
|
||||
|
||||
@@ -176,18 +176,12 @@
|
||||
"hideInfoButton": {
|
||||
"message": "Sembunyikan Butang Maklumat Pada Pemain YouTube"
|
||||
},
|
||||
"whatInfoButton": {
|
||||
"message": "Ini adalah butang yang membuka pop timbul di halaman YouTube."
|
||||
},
|
||||
"hideDeleteButton": {
|
||||
"message": "Sembunyikan Butang Padam Pada Pemain YouTube"
|
||||
},
|
||||
"showDeleteButton": {
|
||||
"message": "Tunjukkan Butang Padam Pada Pemain YouTube"
|
||||
},
|
||||
"whatDeleteButton": {
|
||||
"message": "Ini adalah butang pada pemain YouTube yang akan membersihkan semua segmen anda yang belum dihantar untuk video semasa."
|
||||
},
|
||||
"enableViewTracking": {
|
||||
"message": "Dayakan Skip Count Tracking"
|
||||
},
|
||||
@@ -359,9 +353,6 @@
|
||||
"showUploadButton": {
|
||||
"message": "Tunjukkan Butang Muat Naik"
|
||||
},
|
||||
"whatUploadButton": {
|
||||
"message": "Butang ini muncul di pemain YouTube setelah anda memilih cap waktu dan siap untuk dihantar."
|
||||
},
|
||||
"customServerAddress": {
|
||||
"message": "Alamat Pelayan Sponsorblock"
|
||||
},
|
||||
|
||||
@@ -182,15 +182,15 @@
|
||||
"hideButtonsDescription": {
|
||||
"message": "Dit verbergt de knoppen die verschijnen op de YouTube-speler om segmenten over te slaan."
|
||||
},
|
||||
"showSkipButton": {
|
||||
"message": "Knop voor \"overslaan naar hoogtepunt\" op speler houden"
|
||||
},
|
||||
"showInfoButton": {
|
||||
"message": "Info-knop op YouTube-speler weergeven"
|
||||
},
|
||||
"hideInfoButton": {
|
||||
"message": "Info-knop op YouTube-speler verbergen"
|
||||
},
|
||||
"whatInfoButton": {
|
||||
"message": "Dit is de knop die een pop-up opent op de YouTube-pagina."
|
||||
},
|
||||
"autoHideInfoButton": {
|
||||
"message": "Infoknop automatisch verbergen"
|
||||
},
|
||||
@@ -200,9 +200,6 @@
|
||||
"showDeleteButton": {
|
||||
"message": "Verwijderen-knop op YouTube-speler weergeven"
|
||||
},
|
||||
"whatDeleteButton": {
|
||||
"message": "Dit is de knop op de YouTube-speler die al uw niet-ingediende segmenten van de huidige video zal wissen."
|
||||
},
|
||||
"enableViewTracking": {
|
||||
"message": "Bijhouden van het aantal keren overslaan inschakelen"
|
||||
},
|
||||
@@ -442,9 +439,6 @@
|
||||
"showUploadButton": {
|
||||
"message": "Uploaden-knop weergeven"
|
||||
},
|
||||
"whatUploadButton": {
|
||||
"message": "Deze knop verschijnt op de YouTube-speler nadat u een tijdstempel heeft geselecteerd en klaar bent om in te dienen."
|
||||
},
|
||||
"customServerAddress": {
|
||||
"message": "SponsorBlock-serveradres"
|
||||
},
|
||||
@@ -816,5 +810,8 @@
|
||||
},
|
||||
"LearnMore": {
|
||||
"message": "Meer informatie"
|
||||
},
|
||||
"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."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,18 +176,12 @@
|
||||
"hideInfoButton": {
|
||||
"message": "Skjul infoknappen på YouTube-avspilleren"
|
||||
},
|
||||
"whatInfoButton": {
|
||||
"message": "Dette er knappen som åpner et oppsprett på YouTube-siden."
|
||||
},
|
||||
"hideDeleteButton": {
|
||||
"message": "Skjul Slett-knappen på YouTube-avspilleren"
|
||||
},
|
||||
"showDeleteButton": {
|
||||
"message": "Vis Slett-knappen på YouTube-avspilleren"
|
||||
},
|
||||
"whatDeleteButton": {
|
||||
"message": "Dette er knappen på YouTube-avspilleren som tømmer alle dine uinnsendte segmenter for den nåværende videoen."
|
||||
},
|
||||
"enableViewTracking": {
|
||||
"message": "Skru på telling av hopp"
|
||||
},
|
||||
@@ -359,9 +353,6 @@
|
||||
"showUploadButton": {
|
||||
"message": "Vis opplastingsknapp"
|
||||
},
|
||||
"whatUploadButton": {
|
||||
"message": "Denne knappen dukker opp på YouTube-avspilleren etter at du har valgt et tidsstempel og er klar til å sende inn."
|
||||
},
|
||||
"customServerAddress": {
|
||||
"message": "SponsorBlock-tjeneradresse"
|
||||
},
|
||||
|
||||
@@ -188,9 +188,6 @@
|
||||
"hideInfoButton": {
|
||||
"message": "Ukryj przycisk informacyjny na odtwarzaczu YouTube"
|
||||
},
|
||||
"whatInfoButton": {
|
||||
"message": "Jest to przycisk otwierający okienko pop-up na stronie YouTube."
|
||||
},
|
||||
"autoHideInfoButton": {
|
||||
"message": "Autoukrywanie przycisku informacji"
|
||||
},
|
||||
@@ -200,9 +197,6 @@
|
||||
"showDeleteButton": {
|
||||
"message": "Pokaż przycisk usuwania na odtwarzaczu YouTube"
|
||||
},
|
||||
"whatDeleteButton": {
|
||||
"message": "Ten przycisk na odtwarzaczu YouTube wyczyści wszystkie twoje niewysłane segmenty dla bieżącego filmu."
|
||||
},
|
||||
"enableViewTracking": {
|
||||
"message": "Włącz monitorowanie liczby pominięć"
|
||||
},
|
||||
@@ -442,9 +436,6 @@
|
||||
"showUploadButton": {
|
||||
"message": "Pokaż przycisk wysyłania"
|
||||
},
|
||||
"whatUploadButton": {
|
||||
"message": "Ten przycisk pojawia się na odtwarzaczu YouTube po wybraniu przedziału czasowego, gdy segment jest gotowy do wysłania."
|
||||
},
|
||||
"customServerAddress": {
|
||||
"message": "Adres serwera SponsorBlock"
|
||||
},
|
||||
|
||||
@@ -182,15 +182,15 @@
|
||||
"hideButtonsDescription": {
|
||||
"message": "Esta opção esconde os botões que aparecem para enviar segmentos no player do YouTube."
|
||||
},
|
||||
"showSkipButton": {
|
||||
"message": "Manter botão Pular para os Destaques no player"
|
||||
},
|
||||
"showInfoButton": {
|
||||
"message": "Mostrar botão de Informações no player do Youtube"
|
||||
},
|
||||
"hideInfoButton": {
|
||||
"message": "Esconder botão de Informações no player do Youtube"
|
||||
},
|
||||
"whatInfoButton": {
|
||||
"message": "Este é o botão que abre o popup na pagina do Youtube."
|
||||
},
|
||||
"autoHideInfoButton": {
|
||||
"message": "Esconder Automaticamente o Botão de Informação"
|
||||
},
|
||||
@@ -200,9 +200,6 @@
|
||||
"showDeleteButton": {
|
||||
"message": "Mostrar botão de Apagar no player do Youtube"
|
||||
},
|
||||
"whatDeleteButton": {
|
||||
"message": "Este é o botão que lhe permite saltar todos os patrocínios do player do Youtube."
|
||||
},
|
||||
"enableViewTracking": {
|
||||
"message": "Ativar Contador de Segmentos Pulados"
|
||||
},
|
||||
@@ -442,9 +439,6 @@
|
||||
"showUploadButton": {
|
||||
"message": "Mostrar botão de envio"
|
||||
},
|
||||
"whatUploadButton": {
|
||||
"message": "Este botão aparece no reprodutor do YouTube depois de ter selecionado um carimbo de data/hora e está pronto para ser enviado."
|
||||
},
|
||||
"customServerAddress": {
|
||||
"message": "Endereço do servidor do SponsorBlock"
|
||||
},
|
||||
@@ -656,6 +650,9 @@
|
||||
"message": "Para enviar os segmentos com a categoria de \"{0}\", você deve ativá-la nas opções. Você será redirecionado para as opções agora.",
|
||||
"description": "Used when submitting segments to only let them select a certain category if they have it enabled in the options."
|
||||
},
|
||||
"poiOnlyOneSegment": {
|
||||
"message": "Aviso: Este tipo de segmento pode ter no máximo um ativo por vez. Enviar múltiplos fará com que um aleatório seja mostrado."
|
||||
},
|
||||
"youMustSelectACategory": {
|
||||
"message": "Você deve selecionar uma categoria para todos os segmentos que você está enviando!"
|
||||
},
|
||||
|
||||
@@ -99,18 +99,12 @@
|
||||
"hideInfoButton": {
|
||||
"message": "Esconder botão de Informações no player do Youtube"
|
||||
},
|
||||
"whatInfoButton": {
|
||||
"message": "Este é o botão que abre o popup na pagina do Youtube."
|
||||
},
|
||||
"hideDeleteButton": {
|
||||
"message": "Esconder botão de Apagar no player do Youtube"
|
||||
},
|
||||
"showDeleteButton": {
|
||||
"message": "Mostrar botão de Apagar no player do Youtube"
|
||||
},
|
||||
"whatDeleteButton": {
|
||||
"message": "Este é o botão que lhe permite saltar todos os patrocínios do player do Youtube."
|
||||
},
|
||||
"showNotice": {
|
||||
"message": "Mostrar notificação outra vez"
|
||||
},
|
||||
|
||||
@@ -176,18 +176,12 @@
|
||||
"hideInfoButton": {
|
||||
"message": "Ascunde Butoanele De Informații Pe Playerul De YouTube"
|
||||
},
|
||||
"whatInfoButton": {
|
||||
"message": "Acesta este butonul care deschide popup-ul pe pagina de YouTube."
|
||||
},
|
||||
"hideDeleteButton": {
|
||||
"message": "Ascunde Butonul De Ștergere Pe Playerul De YouTube"
|
||||
},
|
||||
"showDeleteButton": {
|
||||
"message": "Arată Butonul De Ștergere Pe Playerul De YouTube"
|
||||
},
|
||||
"whatDeleteButton": {
|
||||
"message": "Acest buton de pe playerul de YouTube va șterge toate segmentele netrimise pentru videoclipul curent."
|
||||
},
|
||||
"enableViewTracking": {
|
||||
"message": "Activează Urmărirea Săriturilor"
|
||||
},
|
||||
@@ -359,9 +353,6 @@
|
||||
"showUploadButton": {
|
||||
"message": "Arată Butonul De Încărcare"
|
||||
},
|
||||
"whatUploadButton": {
|
||||
"message": "Acest buton apare pe playerul YouTube după ce ați selectat un marcaj de timp și sunteți gata să îl trimiteți."
|
||||
},
|
||||
"customServerAddress": {
|
||||
"message": "Adresa Serverului SponsorBlock"
|
||||
},
|
||||
|
||||
@@ -182,15 +182,15 @@
|
||||
"hideButtonsDescription": {
|
||||
"message": "Эта настройка скрывает кнопки для отправки сегментов, расположенные в плеере YouTube."
|
||||
},
|
||||
"showSkipButton": {
|
||||
"message": "Не скрывать кнопку \"Пропустить до важного\" в плеере YouTube"
|
||||
},
|
||||
"showInfoButton": {
|
||||
"message": "Показывать кнопку информации в плеере YouTube"
|
||||
},
|
||||
"hideInfoButton": {
|
||||
"message": "Скрыть кнопку информации в плеере YouTube"
|
||||
},
|
||||
"whatInfoButton": {
|
||||
"message": "Эта кнопка открывает всплывающее окно на странице YouTube."
|
||||
},
|
||||
"autoHideInfoButton": {
|
||||
"message": "Автоматически скрывать кнопку Информация"
|
||||
},
|
||||
@@ -200,9 +200,6 @@
|
||||
"showDeleteButton": {
|
||||
"message": "Показывать кнопку удаления в плеере YouTube"
|
||||
},
|
||||
"whatDeleteButton": {
|
||||
"message": "Эта кнопка позволяет Вам очистить все неотправленные сегменты в плеере YouTube для текущего видео."
|
||||
},
|
||||
"enableViewTracking": {
|
||||
"message": "Включить отслеживание количества пропусков сегментов"
|
||||
},
|
||||
@@ -442,9 +439,6 @@
|
||||
"showUploadButton": {
|
||||
"message": "Показывать кнопку отправки"
|
||||
},
|
||||
"whatUploadButton": {
|
||||
"message": "Эта кнопка появляется в плеере YouTube после того, как Вы выбрали отметку времени и готовы к отправке."
|
||||
},
|
||||
"customServerAddress": {
|
||||
"message": "Адрес сервера SponsorBlock"
|
||||
},
|
||||
@@ -816,5 +810,8 @@
|
||||
},
|
||||
"LearnMore": {
|
||||
"message": "Узнать больше"
|
||||
},
|
||||
"SponsorTimeEditScrollNewFeature": {
|
||||
"message": "Наведите курсор на поле редактирования и используйте колесо мыши для быстрой настройки времени. Клавиши Ctrl или Shift могут быть использованы для точной настройки."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,15 +182,15 @@
|
||||
"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"
|
||||
},
|
||||
"hideInfoButton": {
|
||||
"message": "Skryť info tlačidlo v YouTube prehrávači"
|
||||
},
|
||||
"whatInfoButton": {
|
||||
"message": "Toto tlačidlo zobrazí vyskakovacie okno na YouTube stránke."
|
||||
},
|
||||
"autoHideInfoButton": {
|
||||
"message": "Automaticky skryť tlačidlo Info"
|
||||
},
|
||||
@@ -200,9 +200,6 @@
|
||||
"showDeleteButton": {
|
||||
"message": "Zobraziť tlačidlo Zmazať v YouTube prehrávači"
|
||||
},
|
||||
"whatDeleteButton": {
|
||||
"message": "Toto tlačidlo v YouTube prehrávači zmaže všetky ešte neodoslané segmenty v aktuálnom videu."
|
||||
},
|
||||
"enableViewTracking": {
|
||||
"message": "Zapnúť počítanie preskočení"
|
||||
},
|
||||
@@ -230,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."
|
||||
@@ -427,9 +439,6 @@
|
||||
"showUploadButton": {
|
||||
"message": "Ukázať Nahrávacie Tlačidlo"
|
||||
},
|
||||
"whatUploadButton": {
|
||||
"message": "Toto tlačidlo sa zobrazí v YouTube prehrávači po tom ako označíte začiatok a koniec segmentu na odoslanie."
|
||||
},
|
||||
"customServerAddress": {
|
||||
"message": "Adresa serveru SponsorBlock"
|
||||
},
|
||||
|
||||
@@ -182,15 +182,15 @@
|
||||
"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"
|
||||
},
|
||||
"hideInfoButton": {
|
||||
"message": "Dölj Infoknapp På YouTube-spelaren"
|
||||
},
|
||||
"whatInfoButton": {
|
||||
"message": "Detta är knappen som öppnar popup-rutan på YouTube-sidan."
|
||||
},
|
||||
"autoHideInfoButton": {
|
||||
"message": "Dölj informationsknappen automatiskt"
|
||||
},
|
||||
@@ -200,9 +200,6 @@
|
||||
"showDeleteButton": {
|
||||
"message": "Visa knappen ta bort på YouTube-spelaren"
|
||||
},
|
||||
"whatDeleteButton": {
|
||||
"message": "Den här knappen på YouTube-spelaren rensar bort alla segment som ej har skickats in på aktuell video."
|
||||
},
|
||||
"enableViewTracking": {
|
||||
"message": "Aktivera spåra antalet hoppa över"
|
||||
},
|
||||
@@ -442,9 +439,6 @@
|
||||
"showUploadButton": {
|
||||
"message": "Visa uppladdningsknapp"
|
||||
},
|
||||
"whatUploadButton": {
|
||||
"message": "Denna knapp visas på YouTube-spelaren efter att du har valt en tidpunkt och är redo att rapportera."
|
||||
},
|
||||
"customServerAddress": {
|
||||
"message": "Serveradress för SponsorBlock"
|
||||
},
|
||||
@@ -816,5 +810,8 @@
|
||||
},
|
||||
"LearnMore": {
|
||||
"message": "Läs mer"
|
||||
},
|
||||
"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."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,14 +182,17 @@
|
||||
"hideButtonsDescription": {
|
||||
"message": "ஸ்கிப் பிரிவுகளைச் சமர்ப்பிக்க YouTube பிளேயரில் தோன்றும் பொத்தான்களை இது மறைக்கிறது."
|
||||
},
|
||||
"showSkipButton": {
|
||||
"message": "பிளேயரில் Skip To Highlight பொத்தானை வைக்கவும்"
|
||||
},
|
||||
"showInfoButton": {
|
||||
"message": "YouTube பிளேயரில் தகவல் பொத்தானைக் காட்டு"
|
||||
},
|
||||
"hideInfoButton": {
|
||||
"message": "YouTube பிளேயரில் தகவல் பொத்தானை மறைக்கவும்"
|
||||
},
|
||||
"whatInfoButton": {
|
||||
"message": "YouTube பக்கத்தில் ஒரு பாப்அப்பைத் திறக்கும் பொத்தான் இது."
|
||||
"autoHideInfoButton": {
|
||||
"message": "தகவல் பொத்தானை தானாக மறைக்கவும்"
|
||||
},
|
||||
"hideDeleteButton": {
|
||||
"message": "YouTube பிளேயரில் நீக்கு பொத்தானை மறைக்க"
|
||||
@@ -185,15 +200,15 @@
|
||||
"showDeleteButton": {
|
||||
"message": "YouTube பிளேயரில் நீக்கு பொத்தானைக் காட்டு"
|
||||
},
|
||||
"whatDeleteButton": {
|
||||
"message": "இது YouTube பிளேயரில் உள்ள பொத்தானாகும், இது தற்போதைய வீடியோவிற்கு நீங்கள் சமர்ப்பிக்காத அனைத்து பகுதிகளையும் அழிக்கும்."
|
||||
},
|
||||
"enableViewTracking": {
|
||||
"message": "ஸ்கிப் கவுண்ட் டிராக்கிங்கை இயக்கு"
|
||||
},
|
||||
"whatViewTracking": {
|
||||
"message": "இந்த அம்சம் பயனர்கள் தங்கள் சமர்ப்பிப்பு மற்றவர்களுக்கு எவ்வளவு உதவியது மற்றும் ஸ்பேம் தரவுத்தளத்தில் வரவில்லை என்பதை உறுதிப்படுத்த அப்வோட்களுடன் ஒரு மெட்ரிக்காகப் பயன்படுத்தப்படுவதை பயனர்களுக்குத் தெரியப்படுத்த நீங்கள் எந்த பகுதிகளைத் தவிர்த்துவிட்டீர்கள் என்பதைக் கண்காணிக்கிறது. ஒவ்வொரு முறையும் நீங்கள் ஒரு பகுதியைத் தவிர்க்கும்போது நீட்டிப்பு சேவையகத்திற்கு ஒரு செய்தியை அனுப்புகிறது. பார்வை எண்கள் துல்லியமாக இருக்க பெரும்பாலான மக்கள் இந்த அமைப்பை மாற்ற மாட்டார்கள் என்று நம்புகிறோம். :)"
|
||||
},
|
||||
"enableViewTrackingInPrivate": {
|
||||
"message": "தனிப்பட்ட/மறைநிலை தாவல்களில் ஸ்கிப் கவுண்ட் டிராக்கிங்கை இயக்கவும்"
|
||||
},
|
||||
"enableQueryByHashPrefix": {
|
||||
"message": "ஹாஷ் முன்னொட்டு மூலம் வினவல்"
|
||||
},
|
||||
@@ -212,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."
|
||||
@@ -235,6 +265,9 @@
|
||||
"setSkipShortcut": {
|
||||
"message": "ஒரு பகுதியைத் தவிர்ப்பதற்கான விசையை அமைக்கவும்"
|
||||
},
|
||||
"setStartSponsorShortcut": {
|
||||
"message": "துவக்க/நிறுத்த பிரிவு விசைப்பலகைக்கு விசையை அமைக்கவும்"
|
||||
},
|
||||
"setSubmitKeybind": {
|
||||
"message": "சமர்ப்பிக்கும் விசைப்பலகைக்கு விசையை அமைக்கவும்"
|
||||
},
|
||||
@@ -266,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": "ஆட்டோ ஸ்கிப்பை முடக்கு"
|
||||
},
|
||||
@@ -317,6 +372,9 @@
|
||||
"changeUserID": {
|
||||
"message": "உங்கள் பயனர் ஐடியை இறக்குமதி / ஏற்றுமதி செய்யுங்கள்"
|
||||
},
|
||||
"whatChangeUserID": {
|
||||
"message": "இதை தனிப்பட்டதாக வைத்திருக்க வேண்டும். இது கடவுச்சொல் போன்றது, அதை யாருடனும் பகிரக்கூடாது. யாரிடமாவது இது இருந்தால், அவர் உங்களைப் போல் ஆள்மாறாட்டம் செய்யலாம். உங்கள் பொது பயனர் IDயை நீங்கள் தேடுகிறீர்களானால், பாப்அப்பில் உள்ள கிளிப்போர்டு ஐகானைக் கிளிக் செய்யவும்."
|
||||
},
|
||||
"setUserID": {
|
||||
"message": "UserID ஐ அமைக்கவும்"
|
||||
},
|
||||
@@ -329,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": "சேர்"
|
||||
},
|
||||
@@ -353,15 +427,18 @@
|
||||
"minDurationDescription": {
|
||||
"message": "தொகுப்பு மதிப்பை விடக் குறைவான பகுதிகள் தவிர்க்கப்படாது அல்லது பிளேயரில் காண்பிக்கப்படாது."
|
||||
},
|
||||
"skipNoticeDuration": {
|
||||
"message": "அறிவிப்பு காலத்தை தவிர்க்கவும் (வினாடிகள்):"
|
||||
},
|
||||
"skipNoticeDurationDescription": {
|
||||
"message": "தவிர்க்கும் அறிவிப்பு குறைந்தபட்சம் இவ்வளவு நேரம் திரையில் இருக்கும். மேனுவல் ஸ்கிப்பிங்கிற்கு, இது நீண்ட நேரம் தெரியும்."
|
||||
},
|
||||
"shortCheck": {
|
||||
"message": "பின்வரும் சமர்ப்பிப்பு உங்கள் குறைந்தபட்ச கால விருப்பத்தை விட குறைவாக உள்ளது. இது ஏற்கனவே சமர்ப்பிக்கப்பட்டுள்ளது என்பதையும், இந்த விருப்பத்தின் காரணமாக புறக்கணிக்கப்படுவதையும் இது குறிக்கலாம். நீங்கள் சமர்ப்பிக்க விரும்புகிறீர்களா?"
|
||||
},
|
||||
"showUploadButton": {
|
||||
"message": "பதிவேற்ற பொத்தானைக் காட்டு"
|
||||
},
|
||||
"whatUploadButton": {
|
||||
"message": "நீங்கள் நேர முத்திரையைத் தேர்ந்தெடுத்து சமர்ப்பிக்கத் தயாரான பிறகு இந்த பொத்தான் YouTube பிளேயரில் தோன்றும்."
|
||||
},
|
||||
"customServerAddress": {
|
||||
"message": "ஸ்பான்சர் பிளாக் சேவையக முகவரி"
|
||||
},
|
||||
@@ -413,6 +490,9 @@
|
||||
"preview": {
|
||||
"message": "முன்னோட்ட"
|
||||
},
|
||||
"unsubmitted": {
|
||||
"message": "சமர்ப்பிக்கப்படவில்லை"
|
||||
},
|
||||
"inspect": {
|
||||
"message": "ஆய்வு செய்யுங்கள்"
|
||||
},
|
||||
@@ -477,6 +557,12 @@
|
||||
"category_outro_description": {
|
||||
"message": "வரவுகளை அல்லது YouTube எண்ட்கார்டுகள் தோன்றும் போது. தகவலுடன் முடிவுகளுக்கு அல்ல."
|
||||
},
|
||||
"category_preview": {
|
||||
"message": "முன்னோட்டம்/மறுபரிசீலனை"
|
||||
},
|
||||
"category_preview_description": {
|
||||
"message": "முந்தைய எபிசோடுகளின் விரைவான மறுபரிசீலனை அல்லது தற்போதைய வீடியோவில் பின்னர் என்ன வரப்போகிறது என்பதற்கான முன்னோட்டம். ஒன்றாக தொகுக்கப்பட்ட கிளிப்புகள், பேசப்பட்ட சுருக்கங்களுக்கு அல்ல."
|
||||
},
|
||||
"category_music_offtopic": {
|
||||
"message": "இசை: இசை அல்லாத பிரிவு"
|
||||
},
|
||||
@@ -486,6 +572,12 @@
|
||||
"category_music_offtopic_short": {
|
||||
"message": "இசை அல்லாதது"
|
||||
},
|
||||
"category_poi_highlight": {
|
||||
"message": "முன்னிலைப்படுத்த"
|
||||
},
|
||||
"category_poi_highlight_description": {
|
||||
"message": "பெரும்பாலான மக்கள் தேடும் வீடியோவின் பகுதி. \"வீடியோ x இல் தொடங்குகிறது\" போன்றது."
|
||||
},
|
||||
"category_livestream_messages": {
|
||||
"message": "லைவ்ஸ்ட்ரீம்: நன்கொடை / செய்தி அளவீடுகள்"
|
||||
},
|
||||
|
||||
@@ -176,18 +176,12 @@
|
||||
"hideInfoButton": {
|
||||
"message": "YouTube ప్లేయర్లో సమాచారం బటన్ను దాచండి"
|
||||
},
|
||||
"whatInfoButton": {
|
||||
"message": "ఇది YouTube పేజీలో పాపప్ను తెరిచే బటన్."
|
||||
},
|
||||
"hideDeleteButton": {
|
||||
"message": "YouTube ప్లేయర్లో తొలగించు బటన్ను దాచండి"
|
||||
},
|
||||
"showDeleteButton": {
|
||||
"message": "YouTube ప్లేయర్లో తొలగించు బటన్ను చూపించు"
|
||||
},
|
||||
"whatDeleteButton": {
|
||||
"message": "ఇది YouTube ప్లేయర్లోని బటన్, ఇది ప్రస్తుత వీడియో కోసం మీరు సమర్పించని అన్ని విభాగాలను క్లియర్ చేస్తుంది."
|
||||
},
|
||||
"enableViewTracking": {
|
||||
"message": "స్కిప్ కౌంట్ ట్రాకింగ్ను ప్రారంభించండి"
|
||||
},
|
||||
@@ -359,9 +353,6 @@
|
||||
"showUploadButton": {
|
||||
"message": "అప్లోడ్ బటన్ చూపించు"
|
||||
},
|
||||
"whatUploadButton": {
|
||||
"message": "మీరు టైమ్స్టాంప్ను ఎంచుకుని సమర్పించడానికి సిద్ధంగా ఉన్న తర్వాత ఈ బటన్ YouTube ప్లేయర్లో కనిపిస్తుంది."
|
||||
},
|
||||
"customServerAddress": {
|
||||
"message": "స్పాన్సర్బ్లాక్ సర్వర్ చిరునామా"
|
||||
},
|
||||
|
||||
@@ -188,9 +188,6 @@
|
||||
"hideInfoButton": {
|
||||
"message": "YouTube Oynatıcısındaki Bilgi Butonunu Gizle"
|
||||
},
|
||||
"whatInfoButton": {
|
||||
"message": "Bu, YouTube sayfasında açılan pencereyi açan butondur."
|
||||
},
|
||||
"autoHideInfoButton": {
|
||||
"message": "Bilgi düğmesini otomatik gizle"
|
||||
},
|
||||
@@ -200,9 +197,6 @@
|
||||
"showDeleteButton": {
|
||||
"message": "YouTube Oynatıcısında Silme Tuşunu Göster"
|
||||
},
|
||||
"whatDeleteButton": {
|
||||
"message": "Bu, YouTube oynatıcısındaki mevcut video için gönderilmemiş bölümleri temizleyen butondur."
|
||||
},
|
||||
"enableViewTracking": {
|
||||
"message": "Kısım Atlama Sayaç Takibine İzin Ver"
|
||||
},
|
||||
@@ -436,9 +430,6 @@
|
||||
"showUploadButton": {
|
||||
"message": "Karşıya Yükleme Butonunu Göster"
|
||||
},
|
||||
"whatUploadButton": {
|
||||
"message": "Bu buton, YouTube oynatıcısında bir zaman seçtiğiniz ve göndermeye hazır olduğunuzda gözükür."
|
||||
},
|
||||
"customServerAddress": {
|
||||
"message": "SponsorBlock Sunucu Adresi"
|
||||
},
|
||||
|
||||
@@ -182,15 +182,15 @@
|
||||
"hideButtonsDescription": {
|
||||
"message": "Це налаштування приховує кнопки для надсилання спонсорських вставок, які з'являються в плеєрі YouTube."
|
||||
},
|
||||
"showSkipButton": {
|
||||
"message": "Залишати кнопку \"Перейти до Основне\" на плеєрі"
|
||||
},
|
||||
"showInfoButton": {
|
||||
"message": "Показувати кнопку інформації в плеєрі YouTube"
|
||||
},
|
||||
"hideInfoButton": {
|
||||
"message": "Приховати кнопку інформації в плеєрі YouTube"
|
||||
},
|
||||
"whatInfoButton": {
|
||||
"message": "Ця кнопка відкриває спливаюче вікно на сторінці YouTube."
|
||||
},
|
||||
"autoHideInfoButton": {
|
||||
"message": "Кнопка \"Автоматично сховати інформацію\""
|
||||
},
|
||||
@@ -200,9 +200,6 @@
|
||||
"showDeleteButton": {
|
||||
"message": "Показувати кнопку видалення в плеєрі YouTube"
|
||||
},
|
||||
"whatDeleteButton": {
|
||||
"message": "Ця кнопка дозволяє очистити всі спонсорські вставки в плеєрі YouTube."
|
||||
},
|
||||
"enableViewTracking": {
|
||||
"message": "Увімкнути відстеження кількості пропусків сегментів"
|
||||
},
|
||||
@@ -442,9 +439,6 @@
|
||||
"showUploadButton": {
|
||||
"message": "Показувати кнопку надсилання"
|
||||
},
|
||||
"whatUploadButton": {
|
||||
"message": "Ця кнопка з'являється в плеєрі YouTube після того, як Ви вибрали позначку часу і готові до надсилання."
|
||||
},
|
||||
"customServerAddress": {
|
||||
"message": "Адреса сервера SponsorBlock"
|
||||
},
|
||||
@@ -597,7 +591,7 @@
|
||||
"message": "Пропуск вручну"
|
||||
},
|
||||
"showOverlay": {
|
||||
"message": "Показувати в смузі прокрутки"
|
||||
"message": "Показувати в смузі перемотування"
|
||||
},
|
||||
"disable": {
|
||||
"message": "Вимкнути"
|
||||
@@ -606,7 +600,7 @@
|
||||
"message": "Автоматический переход к началу"
|
||||
},
|
||||
"manualSkip_POI": {
|
||||
"message": "Спросите, когда видео загружается"
|
||||
"message": "Спитати поки відео завантажується"
|
||||
},
|
||||
"showOverlay_POI": {
|
||||
"message": "Показать на панели поиска"
|
||||
@@ -816,5 +810,8 @@
|
||||
},
|
||||
"LearnMore": {
|
||||
"message": "Дізнатися більше"
|
||||
},
|
||||
"SponsorTimeEditScrollNewFeature": {
|
||||
"message": "Навівши курсор на поле редагування, користуйтеся колесом прокрутки, щоб швидко відрегулювати час. Комбінації клавіш ctrl або shift можуть бути використані для точнішої настройки змін."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,15 +182,15 @@
|
||||
"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"
|
||||
},
|
||||
"hideInfoButton": {
|
||||
"message": "Không hiển thị nút thông tin trên trình chạy video Youtube"
|
||||
},
|
||||
"whatInfoButton": {
|
||||
"message": "Đây là nút để mở bảng popup trên trang Youtube."
|
||||
},
|
||||
"autoHideInfoButton": {
|
||||
"message": "Tự động ẩn nút Info"
|
||||
},
|
||||
@@ -200,9 +200,6 @@
|
||||
"showDeleteButton": {
|
||||
"message": "Hiển thị nút xóa trên trình chạy video Youtube"
|
||||
},
|
||||
"whatDeleteButton": {
|
||||
"message": "Đây là nút trên trình chạy video Youtube để xóa tất cả những đoạn quảng cáo chưa đăng của bạn trong video đang xem."
|
||||
},
|
||||
"enableViewTracking": {
|
||||
"message": "Bật tính năng theo dõi số quảng cáo được bỏ qua"
|
||||
},
|
||||
@@ -308,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"
|
||||
},
|
||||
@@ -423,9 +428,6 @@
|
||||
"showUploadButton": {
|
||||
"message": "Hiển thị nút tải lên"
|
||||
},
|
||||
"whatUploadButton": {
|
||||
"message": "Nút này xuất hiện trên trình chạy video Youtube sau khi bạn chọn mốc thời gian và sẵn sàng đăng đoạn quảng cáo."
|
||||
},
|
||||
"customServerAddress": {
|
||||
"message": "Địa chỉ máy chủ SponsorBlock"
|
||||
},
|
||||
@@ -722,6 +724,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."
|
||||
@@ -750,7 +755,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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,18 +179,12 @@
|
||||
"hideInfoButton": {
|
||||
"message": "在 Youtube 播放器上隐藏信息按钮"
|
||||
},
|
||||
"whatInfoButton": {
|
||||
"message": "此按钮用于在 Youtube 页面中打开弹窗。"
|
||||
},
|
||||
"hideDeleteButton": {
|
||||
"message": "在 Youtube 播放器上隐藏删除按钮"
|
||||
},
|
||||
"showDeleteButton": {
|
||||
"message": "在 Youtube 播放器上显示删除按钮"
|
||||
},
|
||||
"whatDeleteButton": {
|
||||
"message": "此按钮用于在 Youtube 播放器中清除所有赞助商广告。"
|
||||
},
|
||||
"enableViewTracking": {
|
||||
"message": "启用跳过次数统计跟踪"
|
||||
},
|
||||
@@ -365,9 +359,6 @@
|
||||
"showUploadButton": {
|
||||
"message": "显示上传按钮"
|
||||
},
|
||||
"whatUploadButton": {
|
||||
"message": "在您选择了时间并准备提交后,此按钮会出现在 Youtube 播放器中。"
|
||||
},
|
||||
"customServerAddress": {
|
||||
"message": "SponsorBlock 服务器地址"
|
||||
},
|
||||
|
||||
@@ -185,9 +185,6 @@
|
||||
"hideInfoButton": {
|
||||
"message": "在 YouTube 播放器上隱藏資訊按鈕"
|
||||
},
|
||||
"whatInfoButton": {
|
||||
"message": "這個按鈕可用來在 YouTube 頁面打開彈出視窗"
|
||||
},
|
||||
"autoHideInfoButton": {
|
||||
"message": "自動隱藏資訊按鈕"
|
||||
},
|
||||
@@ -197,9 +194,6 @@
|
||||
"showDeleteButton": {
|
||||
"message": "在 YouTube 播放器上顯示刪除按鈕"
|
||||
},
|
||||
"whatDeleteButton": {
|
||||
"message": "這個按鈕可用來在 YouTube 播放器清除所有未提交的片段"
|
||||
},
|
||||
"enableViewTracking": {
|
||||
"message": "啟用跳過次數追蹤"
|
||||
},
|
||||
@@ -396,9 +390,6 @@
|
||||
"showUploadButton": {
|
||||
"message": "顯示上傳按鈕"
|
||||
},
|
||||
"whatUploadButton": {
|
||||
"message": "在您選擇了時間範圍並準備提交後,此按鈕會出現在 YouTube 播放器中。"
|
||||
},
|
||||
"customServerAddress": {
|
||||
"message": "SponsorBlock 伺服器地址"
|
||||
},
|
||||
|
||||
@@ -217,7 +217,7 @@
|
||||
|
||||
/* if two are very close to eachother */
|
||||
.secondSkipNotice {
|
||||
bottom: 250px;
|
||||
bottom: 290px;
|
||||
}
|
||||
|
||||
.noticeLeftIcon {
|
||||
@@ -254,12 +254,16 @@
|
||||
|
||||
.sponsorTimesVoteButtonsContainer {
|
||||
float: left;
|
||||
|
||||
vertical-align:middle;
|
||||
padding: 2px 5px;
|
||||
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.sponsorTimesVoteButtonsContainer div{
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.sponsorSkipNoticeRightSection {
|
||||
right: 0;
|
||||
position: absolute;
|
||||
@@ -330,7 +334,8 @@
|
||||
}
|
||||
|
||||
.voteButton {
|
||||
height: 17px;
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.voteButton:hover {
|
||||
@@ -554,4 +559,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;
|
||||
}
|
||||
|
||||
|
||||
58
public/icons/thumbs_down_locked.svg
Normal file
58
public/icons/thumbs_down_locked.svg
Normal 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 |
@@ -46,6 +46,7 @@
|
||||
width: 330px;
|
||||
padding: 22px;
|
||||
text-align: center;
|
||||
margin-bottom: var(--ytd-margin-6x);
|
||||
}
|
||||
|
||||
#issueReporterTimeButtons > .votingButtons > .segmentTimeButton {
|
||||
|
||||
@@ -274,8 +274,8 @@ class NoticeComponent extends React.Component<NoticeProps, NoticeState> {
|
||||
if (countdownTime == 3) {
|
||||
//start fade out animation
|
||||
const notice = document.getElementById("sponsorSkipNotice" + this.idSuffix);
|
||||
notice.style.removeProperty("animation");
|
||||
notice.classList.add("sponsorSkipNoticeFadeOut");
|
||||
notice?.style.removeProperty("animation");
|
||||
notice?.classList.add("sponsorSkipNoticeFadeOut");
|
||||
}
|
||||
|
||||
this.setState({
|
||||
|
||||
@@ -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) {
|
||||
@@ -186,29 +210,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 +249,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 +277,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 +330,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}>
|
||||
@@ -305,10 +353,11 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
|
||||
return (
|
||||
<span className="sponsorSkipNoticeUnskipSection">
|
||||
<button id={"sponsorSkipUnskipButton" + this.idSuffix}
|
||||
className="sponsorSkipObject sponsorSkipNoticeButton"
|
||||
style={{marginLeft: "4px"}}
|
||||
onClick={() => this.prepAction(SkipNoticeAction.Unskip)}>
|
||||
|
||||
className="sponsorSkipObject sponsorSkipNoticeButton"
|
||||
style={{marginLeft: "4px",
|
||||
color: (this.state.actionState === SkipNoticeAction.Unskip) ? this.selectedColor : this.unselectedColor
|
||||
}}
|
||||
onClick={() => this.prepAction(SkipNoticeAction.Unskip)}>
|
||||
{this.state.skipButtonText + (this.state.showKeybindHint ? " (" + Config.config.skipKeybind + ")" : "")}
|
||||
</button>
|
||||
</span>
|
||||
@@ -318,20 +367,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 +409,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 +424,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 +439,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 +474,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 +634,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 +705,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 +722,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: {
|
||||
|
||||
@@ -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";
|
||||
@@ -46,7 +48,8 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
|
||||
|
||||
this.state = {
|
||||
editing: false,
|
||||
sponsorTimeEdits: [null, null]
|
||||
sponsorTimeEdits: [null, null],
|
||||
selectedCategory: DEFAULT_CATEGORY as Category
|
||||
};
|
||||
}
|
||||
|
||||
@@ -56,6 +59,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 +94,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 +108,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 +128,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 +149,14 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
|
||||
);
|
||||
} else {
|
||||
timeDisplay = (
|
||||
|
||||
<div id={"sponsorTimesContainer" + this.idSuffix}
|
||||
className="sponsorTimeDisplay"
|
||||
onClick={this.toggleEditTime.bind(this)}>
|
||||
onClick={this.toggleEditTime.bind(this)}
|
||||
onWheel={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>
|
||||
);
|
||||
}
|
||||
@@ -240,6 +236,67 @@ 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: 75 + "px",
|
||||
leftOffset: -318 + "px",
|
||||
backgroundColor: "rgba(28, 28, 28, 1.0)",
|
||||
htmlId: "sponsorTimesContainer" + this.idSuffix,
|
||||
buttonFunction: () => {Config.config.scrollToEditTimeUpdate = true}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
getCategoryOptions(): React.ReactElement[] {
|
||||
const elements = [(
|
||||
<option value={DEFAULT_CATEGORY}
|
||||
@@ -251,7 +308,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 +318,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)) {
|
||||
|
||||
@@ -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[],
|
||||
@@ -151,6 +159,8 @@ const Config: SBObject = {
|
||||
configListeners: [],
|
||||
defaults: {
|
||||
userID: null,
|
||||
isVip: false,
|
||||
lastIsVipUpdate: 0,
|
||||
segmentTimes: new SBMap("segmentTimes"),
|
||||
defaultCategory: "chooseACategory" as Category,
|
||||
whitelistedChannels: [],
|
||||
@@ -191,12 +201,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": {
|
||||
|
||||
107
src/content.ts
107
src/content.ts
@@ -16,6 +16,7 @@ import * as Chat from "./js-components/chat";
|
||||
import { getCategoryActionType } from "./utils/categoryUtils";
|
||||
import { SkipButtonControlBar } from "./js-components/skipButtonControlBar";
|
||||
import { Tooltip } from "./render/Tooltip";
|
||||
import { getStartTimeFromUrl } from "./utils/urlParser";
|
||||
|
||||
// Hack to get the CSS loaded on permission-based sites (Invidious)
|
||||
utils.wait(() => Config.config !== null, 5000, 10).then(addCSS);
|
||||
@@ -29,11 +30,14 @@ 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.
|
||||
@@ -119,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)
|
||||
@@ -229,6 +234,7 @@ function resetValues() {
|
||||
status: ChannelIDStatus.Fetching,
|
||||
id: null
|
||||
};
|
||||
lockedCategories = [];
|
||||
|
||||
//empty the preview bar
|
||||
if (previewBar !== null) {
|
||||
@@ -387,11 +393,11 @@ function durationChangeListener(): void {
|
||||
updateAdFlag();
|
||||
updatePreviewBar();
|
||||
|
||||
sponsorTimes = sponsorTimes.filter(segmentDurationFilter);
|
||||
if (sponsorTimes) sponsorTimes = sponsorTimes.filter(segmentDurationFilter);
|
||||
}
|
||||
|
||||
function segmentDurationFilter(segment: SponsorTime): boolean {
|
||||
return segment.videoDuration === 0 || video.duration === 0 || Math.abs(video.duration - segment.videoDuration) < 2;
|
||||
return segment.videoDuration === 0 || !video?.duration || Math.abs(video.duration - segment.videoDuration) < 2;
|
||||
}
|
||||
|
||||
function cancelSponsorSchedule(): void {
|
||||
@@ -459,7 +465,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;
|
||||
@@ -557,13 +563,17 @@ function setupVideoListeners() {
|
||||
switchingVideos = false;
|
||||
|
||||
video.addEventListener('play', () => {
|
||||
switchingVideos = false;
|
||||
|
||||
// If it is not the first event, then the only way to get to 0 is if there is a seek event
|
||||
// This check makes sure that changing the video resolution doesn't cause the extension to think it
|
||||
// gone back to the begining
|
||||
if (!firstEvent && video.currentTime === 0) return;
|
||||
firstEvent = false;
|
||||
|
||||
if (switchingVideos) {
|
||||
switchingVideos = false;
|
||||
// If already segments loaded before video, retry to skip starting segments
|
||||
if (sponsorTimes) startSkipScheduleCheckingForStartSponsors();
|
||||
}
|
||||
|
||||
// Check if an ad is playing
|
||||
updateAdFlag();
|
||||
@@ -602,7 +612,9 @@ function setupVideoListeners() {
|
||||
getCategoryActionType(segment.category) === CategoryActionType.POI &&
|
||||
video.currentTime - segment.segment[0] > 0 &&
|
||||
video.currentTime - segment.segment[0] < previewBar.getMinimumSize(true));
|
||||
if (currentPoiSegment && !skipNotices.some((notice) => notice.segments.some((s) => s.UUID === currentPoiSegment.UUID))) {
|
||||
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,
|
||||
@@ -744,6 +756,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 {
|
||||
@@ -766,24 +827,27 @@ function retryFetch(): void {
|
||||
* Ex. When segments are first loaded
|
||||
*/
|
||||
function startSkipScheduleCheckingForStartSponsors() {
|
||||
if (!switchingVideos) {
|
||||
if (!switchingVideos && sponsorTimes) {
|
||||
// See if there are any starting sponsors
|
||||
let startingSegmentTime = -1;
|
||||
let startingSegmentTime = getStartTimeFromUrl(document.URL) || -1;
|
||||
let found = false;
|
||||
let startingSegment: SponsorTime = null;
|
||||
for (const time of sponsorTimes) {
|
||||
if (time.segment[0] <= video.currentTime && time.segment[0] > startingSegmentTime && time.segment[1] > video.currentTime
|
||||
&& getCategoryActionType(time.category) === CategoryActionType.Skippable) {
|
||||
startingSegmentTime = time.segment[0];
|
||||
startingSegment = time;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (startingSegmentTime === -1) {
|
||||
if (!found) {
|
||||
for (const time of sponsorTimesSubmitting) {
|
||||
if (time.segment[0] <= video.currentTime && time.segment[0] > startingSegmentTime && time.segment[1] > video.currentTime
|
||||
&& getCategoryActionType(time.category) === CategoryActionType.Skippable) {
|
||||
startingSegmentTime = time.segment[0];
|
||||
startingSegment = time;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -840,7 +904,7 @@ function getYouTubeVideoID(url: string): string | boolean {
|
||||
if(url.startsWith("https://www.youtube.com/tv#/")) url = url.replace("#", "");
|
||||
|
||||
//Attempt to parse url
|
||||
let urlObject = null;
|
||||
let urlObject: URL = null;
|
||||
try {
|
||||
urlObject = new URL(url);
|
||||
} catch (e) {
|
||||
@@ -866,9 +930,10 @@ function getYouTubeVideoID(url: string): string | boolean {
|
||||
if (urlObject.searchParams.has("v") && ["/watch", "/watch/"].includes(urlObject.pathname) || urlObject.pathname.startsWith("/tv/watch")) {
|
||||
const id = urlObject.searchParams.get("v");
|
||||
return id.length == 11 ? id : false;
|
||||
} else if (urlObject.pathname.startsWith("/embed/")) {
|
||||
} else if (urlObject.pathname.startsWith("/embed/") || urlObject.pathname.startsWith("/shorts/")) {
|
||||
try {
|
||||
return urlObject.pathname.substr(7, 11);
|
||||
const id = urlObject.pathname.split("/")[2];
|
||||
if (id && id.length >= 11) return id.substr(0, 11);
|
||||
} catch (e) {
|
||||
console.error("[SB] Video ID not valid for " + url);
|
||||
return false;
|
||||
@@ -919,7 +984,7 @@ function updatePreviewBar(): void {
|
||||
});
|
||||
});
|
||||
|
||||
previewBar.set(previewBarSegments, video.duration)
|
||||
previewBar.set(previewBarSegments, video?.duration)
|
||||
|
||||
if (Config.config.showTimeWithSkips) {
|
||||
const skippedDuration = utils.getTimestampsDuration(previewBarSegments.map(({segment}) => segment));
|
||||
@@ -1387,7 +1452,7 @@ function getRealCurrentTime(): number {
|
||||
|
||||
if (playButtonSVGData === replaceSVGData) {
|
||||
// At the end of the video
|
||||
return video.duration;
|
||||
return video?.duration;
|
||||
} else {
|
||||
return video.currentTime;
|
||||
}
|
||||
@@ -1671,8 +1736,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);
|
||||
}
|
||||
@@ -1887,7 +1956,7 @@ function showTimeWithoutSkips(skippedDuration: number): void {
|
||||
display.appendChild(duration);
|
||||
}
|
||||
|
||||
const durationAfterSkips = utils.getFormattedTime(video.duration - skippedDuration)
|
||||
const durationAfterSkips = utils.getFormattedTime(video?.duration - skippedDuration)
|
||||
|
||||
duration.innerText = (durationAfterSkips == null || skippedDuration <= 0) ? "" : " (" + durationAfterSkips + ")";
|
||||
}
|
||||
|
||||
@@ -379,8 +379,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 +432,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
|
||||
|
||||
92
src/render/RectangleTooltip.tsx
Normal file
92
src/render/RectangleTooltip.tsx
Normal file
@@ -0,0 +1,92 @@
|
||||
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,
|
||||
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;
|
||||
|
||||
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}}
|
||||
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);
|
||||
}
|
||||
}
|
||||
18
src/svg-icons/pencil_svg.tsx
Normal file
18
src/svg-icons/pencil_svg.tsx
Normal 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;
|
||||
23
src/svg-icons/thumbs_down_svg.tsx
Normal file
23
src/svg-icons/thumbs_down_svg.tsx
Normal 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;
|
||||
22
src/svg-icons/thumbs_up_svg.tsx
Normal file
22
src/svg-icons/thumbs_up_svg.tsx
Normal 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;
|
||||
@@ -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;
|
||||
|
||||
11
src/utils.ts
11
src/utils.ts
@@ -189,14 +189,20 @@ export default class Utils {
|
||||
element.classList.add("animationDone");
|
||||
if (!rightSlide) element.classList.add("autoHideLeft");
|
||||
|
||||
let mouseEntered = false;
|
||||
|
||||
container.addEventListener("mouseenter", () => {
|
||||
mouseEntered = true;
|
||||
element.classList.remove("animationDone");
|
||||
|
||||
// Wait for next event loop
|
||||
setTimeout(() => element.classList.remove("hidden"), 10);
|
||||
setTimeout(() => {
|
||||
if (mouseEntered) element.classList.remove("hidden")
|
||||
}, 10);
|
||||
});
|
||||
|
||||
container.addEventListener("mouseleave", () => {
|
||||
mouseEntered = false;
|
||||
if (element.classList.contains("autoHiding")) {
|
||||
element.classList.add("hidden");
|
||||
}
|
||||
@@ -205,10 +211,12 @@ export default class Utils {
|
||||
|
||||
enableAutoHideAnimation(element: Element): void {
|
||||
element.classList.add("autoHiding");
|
||||
element.classList.add("hidden");
|
||||
}
|
||||
|
||||
disableAutoHideAnimation(element: Element): void {
|
||||
element.classList.remove("autoHiding");
|
||||
element.classList.remove("hidden");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -531,5 +539,4 @@ export default class Utils {
|
||||
|
||||
return hashHex;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
26
src/utils/urlParser.ts
Normal file
26
src/utils/urlParser.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
|
||||
export function getStartTimeFromUrl(url: string): number {
|
||||
const urlParams = new URLSearchParams(url);
|
||||
const time = urlParams?.get('t') || urlParams?.get('time_continue');
|
||||
|
||||
return urlTimeToSeconds(time);
|
||||
}
|
||||
|
||||
export function urlTimeToSeconds(time: string): number {
|
||||
if (!time) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const re = /(?:(\d{1,3})h)?(?:(\d{1,2})m)?(\d+)s?/;
|
||||
const match = re.exec(time);
|
||||
|
||||
if (match) {
|
||||
const hours = parseInt(match[1] ?? '0', 10);
|
||||
const minutes = parseInt(match[2] ?? '0', 10);
|
||||
const seconds = parseInt(match[3] ?? '0', 10);
|
||||
|
||||
return hours * 3600 + minutes * 60 + seconds;
|
||||
} else if (/\d+/.test(time)) {
|
||||
return parseInt(time, 10);
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,15 @@ import * as Chrome from "selenium-webdriver/chrome";
|
||||
import * as Path from "path";
|
||||
|
||||
test("Selenium Chrome test", async () => {
|
||||
const driver = await setup();
|
||||
let driver;
|
||||
try {
|
||||
driver = await setup();
|
||||
} catch (e) {
|
||||
console.warn("A browser is probably not installed, skipping selenium tests");
|
||||
console.warn(e);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await waitForInstall(driver);
|
||||
|
||||
27
test/urlParser.test.ts
Normal file
27
test/urlParser.test.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import { getStartTimeFromUrl } from '../src/utils/urlParser';
|
||||
|
||||
describe("getStartTimeFromUrl", () => {
|
||||
it("parses with a number", () => {
|
||||
expect(getStartTimeFromUrl("https://www.youtube.com/watch?v=dQw4w9WgXcQ&t=123")).toBe(123);
|
||||
});
|
||||
|
||||
it("parses with seconds", () => {
|
||||
expect(getStartTimeFromUrl("https://www.youtube.com/watch?v=dQw4w9WgXcQ&t=123s")).toBe(123);
|
||||
});
|
||||
|
||||
it("parses with minutes", () => {
|
||||
expect(getStartTimeFromUrl("https://www.youtube.com/watch?v=dQw4w9WgXcQ&t=23m3s")).toBe(23 * 60 + 3);
|
||||
});
|
||||
|
||||
it("parses with hours", () => {
|
||||
expect(getStartTimeFromUrl("https://www.youtube.com/watch?v=dQw4w9WgXcQ&t=1h2m3s")).toBe(1 * 60 * 60 + 2 * 60 + 3);
|
||||
});
|
||||
|
||||
it("works with time_continue", () => {
|
||||
expect(getStartTimeFromUrl("https://www.youtube.com/watch?v=dQw4w9WgXcQ&time_continue=123")).toBe(123);
|
||||
});
|
||||
|
||||
it("works with no time", () => {
|
||||
expect(getStartTimeFromUrl("https://www.youtube.com/watch?v=dQw4w9WgXcQ")).toBe(0);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user