mirror of
https://github.com/ajayyy/SponsorBlock.git
synced 2025-12-12 06:27:14 +03:00
Compare commits
28 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3ee2e2517a | ||
|
|
dd7f227305 | ||
|
|
c1d3c7d680 | ||
|
|
fae6d0d0cf | ||
|
|
60d106fc52 | ||
|
|
a4df2eab8f | ||
|
|
7a50167222 | ||
|
|
e48d956577 | ||
|
|
efec6a113f | ||
|
|
0121a2aebd | ||
|
|
e223d12520 | ||
|
|
27e8e83c59 | ||
|
|
c7f254db70 | ||
|
|
85c3cd4a81 | ||
|
|
8d9042aeeb | ||
|
|
373edf883d | ||
|
|
7ed01a181e | ||
|
|
4119fd8433 | ||
|
|
cc7d7c0a0c | ||
|
|
61b39a99db | ||
|
|
98f776fa3a | ||
|
|
75f426f456 | ||
|
|
67b510e628 | ||
|
|
7cc0847db1 | ||
|
|
b92132bf47 | ||
|
|
6b4da25847 | ||
|
|
529db4d6ca | ||
|
|
d132342ffe |
@@ -49,7 +49,7 @@ const reliableCheck = mapped
|
||||
.filter(instance => instance.url.includes(instance.name))
|
||||
|
||||
// finally map to array
|
||||
const result: string[] = reliableCheck.map(instance => instance.name)
|
||||
const result: string[] = reliableCheck.map(instance => instance.name).sort()
|
||||
writeFile(join(__dirname, "./invidiouslist.json"), JSON.stringify(result), (err) => {
|
||||
if (err) return console.log(err);
|
||||
})
|
||||
@@ -1 +1 @@
|
||||
["yewtu.be","vid.puffyan.us","invidious.snopyta.org","inv.riverside.rocks","invidious-us.kavin.rocks","invidious.osi.kr","tube.cthd.icu","invidious.flokinet.to","yt.artemislena.eu","invidious.mutahar.rocks","invidious.esmailelbob.xyz","youtube.076.ne.jp","invidious.weblibre.org","invidious.namazso.eu","invidious.kavin.rocks"]
|
||||
["inv.cthd.icu","inv.riverside.rocks","invidio.xamh.de","invidious.kavin.rocks","invidious.namazso.eu","invidious.osi.kr","invidious.snopyta.org","vid.puffyan.us","yewtu.be","youtube.076.ne.jp","yt.artemislena.eu"]
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "__MSG_fullName__",
|
||||
"short_name": "SponsorBlock",
|
||||
"version": "4.6",
|
||||
"version": "4.6.3",
|
||||
"default_locale": "en",
|
||||
"description": "__MSG_Description__",
|
||||
"homepage_url": "https://sponsor.ajay.app",
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "background.js",
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2"
|
||||
|
||||
@@ -164,6 +164,9 @@
|
||||
"copyPublicID": {
|
||||
"message": "نسخ معرف المستخدم العام"
|
||||
},
|
||||
"copySegmentID": {
|
||||
"message": "نسخ معرف الجزء"
|
||||
},
|
||||
"discordAdvert": {
|
||||
"message": "انضم إلى سيرفر \"ديسكورد\" الرسمي لتقديم اقتراحات وتعليقات!"
|
||||
},
|
||||
@@ -200,6 +203,9 @@
|
||||
"showDeleteButton": {
|
||||
"message": "إظهار زر \"حذف\" على مشغّل اليوتيوب"
|
||||
},
|
||||
"enableViewTracking": {
|
||||
"message": "تمكين تتبع مرات التخطي"
|
||||
},
|
||||
"showNotice": {
|
||||
"message": "إظهار الإشعار مرة أخرى"
|
||||
},
|
||||
@@ -401,12 +407,18 @@
|
||||
"Donate": {
|
||||
"message": "تبرع"
|
||||
},
|
||||
"considerDonating": {
|
||||
"message": "ساعد في تمويل التطوير"
|
||||
},
|
||||
"hideDonationLink": {
|
||||
"message": "إخفاء رابط التبرع"
|
||||
},
|
||||
"darkModeOptionsPage": {
|
||||
"message": "الوضع الداكن في صفحة الخيارات"
|
||||
},
|
||||
"helpPageThanksForInstalling": {
|
||||
"message": "شكرا على تثبيت SponsorBlock."
|
||||
},
|
||||
"Editing": {
|
||||
"message": "التعديل"
|
||||
},
|
||||
|
||||
@@ -186,7 +186,7 @@
|
||||
"message": "Versteckt die Schaltflächen im YouTube-Videoplayer, um Segmente einzusenden."
|
||||
},
|
||||
"showSkipButton": {
|
||||
"message": "\"Zum Highlight springen\"-Button im Youtube-Player anzeigen"
|
||||
"message": "Behalte \"Zum Highlight springen\"-Knopf in der Leiste"
|
||||
},
|
||||
"showInfoButton": {
|
||||
"message": "Zeige Info-Knopf im Youtube-Videoplayer"
|
||||
@@ -867,7 +867,7 @@
|
||||
"message": "Dauerhaft verbergen"
|
||||
},
|
||||
"warningChatInfo": {
|
||||
"message": "Du hast eine Warnung erhalten und kannst vorübergehend keine Segmente einreichen. Uns ist nämlich aufgefallen, dass du nicht bösartige Fehler in deinen Einreichungen machst. Bitte bestätige, dass du die Regeln verstanden hast. Darauffolgend können wir die Warnung entfernen. Du kannst diesem Chat auch mit discord.gg/SponsorBlock oder matrix.to/#/#sponsor:ajay.app beitreten"
|
||||
"message": "Du hast eine Warnung erhalten und kannst vorübergehend keine Segmente einreichen. Dies bedeutet, dass du Fehler gemacht hast welche nicht bösartig sind, bitte bestätige, dass du die Regeln verstanden hast, wir werden dann die Warnung entfernen. Du kannst diesem Chat auch mit discord.gg/SponsorBlock oder matrix.to/#/#sponsor:ajay.app beitreten"
|
||||
},
|
||||
"voteRejectedWarning": {
|
||||
"message": "Abstimmung wegen einer Warnung abgelehnt. Klicke hier um einen Chat zu öffnen, oder versuch es später erneut, wenn du Zeit hast.",
|
||||
@@ -964,7 +964,7 @@
|
||||
"message": "Dies wirkt sich sofort auf eigene Segmente aus"
|
||||
},
|
||||
"downvote": {
|
||||
"message": "Negativ bewertet"
|
||||
"message": "Dagegen stimmen"
|
||||
},
|
||||
"upvote": {
|
||||
"message": "Positiv bewerten"
|
||||
|
||||
@@ -239,6 +239,9 @@
|
||||
"showSkipNotice": {
|
||||
"message": "Notifier après qu'un segment ait été sauté"
|
||||
},
|
||||
"showCategoryGuidelines": {
|
||||
"message": "Affiche l'aide de la catégorie"
|
||||
},
|
||||
"noticeVisibilityMode0": {
|
||||
"message": "Notifications de passage"
|
||||
},
|
||||
@@ -542,18 +545,39 @@
|
||||
"message": "à",
|
||||
"description": "Used between segments. Example: 1:20 to 1:30"
|
||||
},
|
||||
"generic_guideline1": {
|
||||
"message": "Inclure les transitions entre les segments"
|
||||
},
|
||||
"generic_guideline2": {
|
||||
"message": "Jouer comme si rien n'avait été passé"
|
||||
},
|
||||
"category_sponsor": {
|
||||
"message": "Message sponsorisé"
|
||||
},
|
||||
"category_sponsor_description": {
|
||||
"message": "Promotion rémunérée, parrainage rémunéré et publicité directe. Pas pour l'autopromotion ou les présentations gratuites de causes, de créateurs, de sites web ou de produits qu'ils aiment."
|
||||
},
|
||||
"category_sponsor_guideline1": {
|
||||
"message": "Promotions rémunérées"
|
||||
},
|
||||
"category_sponsor_guideline2": {
|
||||
"message": "Pas pour les dons ou les produits dérivés"
|
||||
},
|
||||
"category_selfpromo": {
|
||||
"message": "Non rémunéré/autopromotion"
|
||||
},
|
||||
"category_selfpromo_description": {
|
||||
"message": "Semblable aux \"messages commerciaux\", excepté pour la promotion non rémunérée ou l'autopromotion. Cela inclut les marchandises, les dons et les informations sur leurs collaborateurs."
|
||||
},
|
||||
"category_selfpromo_guideline1": {
|
||||
"message": "Dons, abonnements (payant) et produits dérivés"
|
||||
},
|
||||
"category_selfpromo_guideline2": {
|
||||
"message": "Remerciements gratuits qui n'apportent aucune information à la vidéo"
|
||||
},
|
||||
"category_selfpromo_guideline3": {
|
||||
"message": "Pas pour des produits dérivés fait par des marques"
|
||||
},
|
||||
"category_exclusive_access": {
|
||||
"message": "Accès exclusif"
|
||||
},
|
||||
@@ -564,12 +588,24 @@
|
||||
"message": "Cette vidéo présente un produit, un service ou un lieu pour lequel un accès gratuit ou subventionné a été reçu",
|
||||
"description": "Short description for this category"
|
||||
},
|
||||
"category_exclusive_access_guideline1": {
|
||||
"message": "Toute la vidéo présente quelque chose dont le créateur a eu un accès gratuit ou subventionné"
|
||||
},
|
||||
"category_interaction": {
|
||||
"message": "Rappel d'interaction (abonnement)"
|
||||
},
|
||||
"category_interaction_description": {
|
||||
"message": "Lorsqu'il y a un bref rappel pour aimer, s'abonner ou les suivre parmi le contenu. Si le message est long ou porte sur quelque chose de spécifique, cela devrait plutôt être classé comme une autopromotion."
|
||||
},
|
||||
"category_interaction_guideline1": {
|
||||
"message": "Rappels courts à like, s'abonner ou suivre"
|
||||
},
|
||||
"category_interaction_guideline2": {
|
||||
"message": "Inclut des rappels indirects à commenter"
|
||||
},
|
||||
"category_interaction_guideline3": {
|
||||
"message": "Pas pour la promotion générale, seulement les appels à l'interaction"
|
||||
},
|
||||
"category_interaction_short": {
|
||||
"message": "Rappel d'interaction"
|
||||
},
|
||||
@@ -582,18 +618,36 @@
|
||||
"category_intro_short": {
|
||||
"message": "Entracte"
|
||||
},
|
||||
"category_intro_guideline1": {
|
||||
"message": "Intervalle sans contenu réel"
|
||||
},
|
||||
"category_intro_guideline2": {
|
||||
"message": "Pas pour les transitions avec des informations"
|
||||
},
|
||||
"category_outro": {
|
||||
"message": "Générique de fin"
|
||||
},
|
||||
"category_outro_description": {
|
||||
"message": "Crédits ou écrans de fin YouTube. Pas pour les conclusions contenant des informations."
|
||||
},
|
||||
"category_outro_guideline1": {
|
||||
"message": "Ne dois pas inclure de contenu, même si les écrans de fin sont apparus"
|
||||
},
|
||||
"category_preview": {
|
||||
"message": "Aperçu/Résumé"
|
||||
},
|
||||
"category_preview_description": {
|
||||
"message": "Résumé rapide des épisodes précédents, ou aperçu de ce qui se passera plus tard dans la vidéo en cours. Pour les plans collectifs édités, pas pour les résumés parlés."
|
||||
},
|
||||
"category_preview_guideline1": {
|
||||
"message": "Clips apparaissant plus tard ou dans une prochaine vidéo"
|
||||
},
|
||||
"category_preview_guideline2": {
|
||||
"message": "Récapitulatif d'une vidéo précédente"
|
||||
},
|
||||
"category_preview_guideline3": {
|
||||
"message": "Pas pour les sections qui ajoutent du contenu supplémentaire"
|
||||
},
|
||||
"category_filler": {
|
||||
"message": "Digressions/Blagues"
|
||||
},
|
||||
@@ -603,6 +657,15 @@
|
||||
"category_filler_short": {
|
||||
"message": "Remplissage"
|
||||
},
|
||||
"category_filler_guideline1": {
|
||||
"message": "Scènes digressives uniquement pour le remplissage ou l'humour"
|
||||
},
|
||||
"category_filler_guideline2": {
|
||||
"message": "Distractions, bêtisiers, replays"
|
||||
},
|
||||
"category_filler_guideline3": {
|
||||
"message": "Pas pour les scènes requises pour comprendre le sujet"
|
||||
},
|
||||
"category_music_offtopic": {
|
||||
"message": "Musique : Segment non musical"
|
||||
},
|
||||
@@ -612,12 +675,27 @@
|
||||
"category_music_offtopic_short": {
|
||||
"message": "Hors musique"
|
||||
},
|
||||
"category_music_offtopic_guideline1": {
|
||||
"message": "Sections qui ne sont pas dans la musique officielle"
|
||||
},
|
||||
"category_music_offtopic_guideline2": {
|
||||
"message": "Pas de musique pendant les concerts en direct"
|
||||
},
|
||||
"category_poi_highlight": {
|
||||
"message": "Point essentiel"
|
||||
},
|
||||
"category_poi_highlight_description": {
|
||||
"message": "La partie de la vidéo que la plupart des gens veulent voir. Similaire à \"la vidéo commence à x mins\"."
|
||||
},
|
||||
"category_poi_highlight_guideline1": {
|
||||
"message": "Section la plus regardée"
|
||||
},
|
||||
"category_poi_highlight_guideline2": {
|
||||
"message": "Peut sauter le contexte"
|
||||
},
|
||||
"category_poi_highlight_guideline3": {
|
||||
"message": "Peut passer au sujet cité dans le titre ou la miniature"
|
||||
},
|
||||
"category_livestream_messages": {
|
||||
"message": "Stream : lecture de dons et messages"
|
||||
},
|
||||
@@ -867,6 +945,9 @@
|
||||
"LearnMore": {
|
||||
"message": "En savoir plus"
|
||||
},
|
||||
"FullDetails": {
|
||||
"message": "Tous les détails"
|
||||
},
|
||||
"CopyDownvoteButtonInfo": {
|
||||
"message": "Vote contre et crée une copie locale à soumettre à nouveau"
|
||||
},
|
||||
|
||||
@@ -186,7 +186,7 @@
|
||||
"message": "Nasconde i pulsanti che appaiono sul video per inviare i segmenti da nascondere."
|
||||
},
|
||||
"showSkipButton": {
|
||||
"message": "Mantieni Salta Per Evidenziare il Pulsante Sul Lettore"
|
||||
"message": "Mantieni l'Highlight del Video sulla Barra del Video"
|
||||
},
|
||||
"showInfoButton": {
|
||||
"message": "Mostra il pulsante delle informazioni sopra al video"
|
||||
@@ -216,7 +216,7 @@
|
||||
"message": "Memorizza i voti negativi del segmento"
|
||||
},
|
||||
"whatTrackDownvotes": {
|
||||
"message": "Qualsiasi segmento voti negativamente rimarrà nascosto anche dopo aver ricaricato"
|
||||
"message": "Segmenti votati negativamente rimarranno nascosti anche dopo aver ricaricato la pagina"
|
||||
},
|
||||
"trackDownvotesWarning": {
|
||||
"message": "Attenzione: Disabilitarlo eliminerà tutti i voti negativi precedentemente memorizzati"
|
||||
@@ -282,7 +282,7 @@
|
||||
"description": "Keybind label"
|
||||
},
|
||||
"setStartSponsorShortcut": {
|
||||
"message": "Inizio/Fine segmento",
|
||||
"message": "Inizia/Finisci segmento",
|
||||
"description": "Keybind label"
|
||||
},
|
||||
"setSubmitKeybind": {
|
||||
@@ -290,7 +290,7 @@
|
||||
"description": "Keybind label"
|
||||
},
|
||||
"keybindDescription": {
|
||||
"message": "Selezionare una chiave digitandola e scegliere qualsiasi tasto modificatore che si desidera utilizzare."
|
||||
"message": "Seleziona un tasto digitandolo e scegli qualsiasi tasto modificatore che desideri utilizzare."
|
||||
},
|
||||
"0": {
|
||||
"message": "Timeout della connessione. Controlla la tua connessione a Internet. Se internet sta funzionando, il server è probabilmente sovraccarico oppure giù."
|
||||
@@ -328,7 +328,7 @@
|
||||
"message": "Silenziare {0}?"
|
||||
},
|
||||
"skip_to_category": {
|
||||
"message": "Saltare a {0}?",
|
||||
"message": "Salta a {0}?",
|
||||
"description": "Used for skipping to things (Skip to Highlight)"
|
||||
},
|
||||
"skipped": {
|
||||
@@ -595,7 +595,7 @@
|
||||
"message": "Promemoria d'Interazione (Iscrizione)"
|
||||
},
|
||||
"category_interaction_description": {
|
||||
"message": "Quando nel punto centrale del contenuto è presente un breve promemoria per aggiunta di mi piace, iscrizione o seguito. Se dovesse risultare esteso o riguardare qualcosa di specifico, potrebbe essere un'autopromozione."
|
||||
"message": "Quando nel punto centrale del contenuto è presente un breve promemoria per like, iscrizione o follow. Se dovesse risultare esteso o riguardante qualcosa di specifico, potrebbe essere auto-promozione."
|
||||
},
|
||||
"category_interaction_guideline1": {
|
||||
"message": "Brevi promemoria per mi piace, iscrizioni o follow"
|
||||
@@ -607,16 +607,16 @@
|
||||
"message": "Non per promozione generale, solo chiamata all'azione"
|
||||
},
|
||||
"category_interaction_short": {
|
||||
"message": "Promemoria di Interazione"
|
||||
"message": "Promemoria d'Interazione"
|
||||
},
|
||||
"category_intro": {
|
||||
"message": "Animazione Interruzione/Introduzione"
|
||||
"message": "Intermezzo/Intro Animata"
|
||||
},
|
||||
"category_intro_description": {
|
||||
"message": "Un intervallo senza contenuto effettivo. Potrebbe essere una pausa, una schermata statica, un'animazione ripetuta. Non dovrebbe essere usato per transizioni contenenti informazioni."
|
||||
},
|
||||
"category_intro_short": {
|
||||
"message": "Interruzione"
|
||||
"message": "Intermezzo"
|
||||
},
|
||||
"category_intro_guideline1": {
|
||||
"message": "Intervallo senza contenuto effettivo"
|
||||
@@ -655,10 +655,10 @@
|
||||
"message": "Le scene riempitive sono aggiunte solo per riempire o per umorismo che non sono richieste per comprendere il contenuto principale del video. Questo non dovrebbe includere segmenti che forniscono contesto o dettagli di sfondo."
|
||||
},
|
||||
"category_filler_short": {
|
||||
"message": "Riempimento"
|
||||
"message": "Filler"
|
||||
},
|
||||
"category_filler_guideline1": {
|
||||
"message": "Scene non correlate usate solo per riempimenti o umorismo"
|
||||
"message": "Scene non correlate usate solo per filler o umorismo"
|
||||
},
|
||||
"category_filler_guideline2": {
|
||||
"message": "Distrazioni, blooper, replay"
|
||||
@@ -682,13 +682,13 @@
|
||||
"message": "Sezioni senza musica in una performance dal vivo"
|
||||
},
|
||||
"category_poi_highlight": {
|
||||
"message": "Evidenzia"
|
||||
"message": "Highlight"
|
||||
},
|
||||
"category_poi_highlight_description": {
|
||||
"message": "La parte del video che gran parte delle persone stanno cercando. Simile ai commenti \"Il video inizia a x\"."
|
||||
},
|
||||
"category_poi_highlight_guideline1": {
|
||||
"message": "La sezione che la maggior parte delle persone sta cercando"
|
||||
"message": "La parte che la maggior parte delle persone sta cercando"
|
||||
},
|
||||
"category_poi_highlight_guideline2": {
|
||||
"message": "Può ignorare il contesto"
|
||||
@@ -816,7 +816,7 @@
|
||||
"message": "Forza controllo canale prima di andare avanti"
|
||||
},
|
||||
"whatForceChannelCheck": {
|
||||
"message": "Per impostazione predefinita, si salteranno subito i segmenti prima che si sappia anche che canale è. Per impostazione predefinita, alcuni segmenti all'inizio del video potrebbero essere saltati sui canali sulla whitelist. Abilitare questa opzione impedirà questo, ma fare saltare tutti hanno un leggero ritardo in quanto ottenere il channelID può richiedere un certo tempo. Questo ritardo potrebbe essere invisibile se si dispone di internet veloce."
|
||||
"message": "Di default, verranno saltati i segmenti subito, anche prima che si sappia il canale. Di default, alcuni segmenti all'inizio del video potrebbero essere saltati sui canali nella whitelist. L'attivazione di questa opzione eviterà che ciò accada, ma ogni salto avrà un leggero ritardo in quanto ottenere l'ID del canale può richiedere un certo tempo. Questo ritardo potrebbe essere impercettibile se si dispone di una connessione internet veloce."
|
||||
},
|
||||
"forceChannelCheckPopup": {
|
||||
"message": "Considera l'Attivazione dell'opzione \"Forza la Verifica del Canale Prima del Salto\""
|
||||
|
||||
@@ -1 +1,25 @@
|
||||
{}
|
||||
{
|
||||
"fullName": {
|
||||
"message": "SponsorBlock priekš YouTube - Izlaid sponsorus",
|
||||
"description": "Name of the extension."
|
||||
},
|
||||
"Description": {
|
||||
"message": "Izlaidiet sponsorus, abonēšanas lūgumus un vairāk, skatoties YouTube video. Ziņojiet par sponsoriem video, kurus jūs skatāties, lai ietaupītu citu laiku.",
|
||||
"description": "Description of the extension."
|
||||
},
|
||||
"400": {
|
||||
"message": "Serveris ziņo, ka šis pieprasījums ir nederīgs"
|
||||
},
|
||||
"429": {
|
||||
"message": "Jūs esat aizsūtījis pārāk daudz sponsoru laika sprīžus šim video; vai esat pārliecināts, ka šeit ir tik daudz?"
|
||||
},
|
||||
"409": {
|
||||
"message": "Šis jau ir ticis aizsūtīts iepriekš"
|
||||
},
|
||||
"channelWhitelisted": {
|
||||
"message": "Kanāls iekļauts baltajā sarakstā!"
|
||||
},
|
||||
"Segment": {
|
||||
"message": "segments"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
"message": "Pomiń"
|
||||
},
|
||||
"unmute": {
|
||||
"message": "Odcisz"
|
||||
"message": "Anuluj wyciszenie"
|
||||
},
|
||||
"paused": {
|
||||
"message": "Zatrzymany"
|
||||
@@ -246,16 +246,16 @@
|
||||
"message": "Pełnowymiarowe powiadomienia o przewinięciu"
|
||||
},
|
||||
"noticeVisibilityMode1": {
|
||||
"message": "Małe powiadomienia o automatycznym pomijaniu"
|
||||
"message": "Małe powiadomienia o automatycznym przewinięciu"
|
||||
},
|
||||
"noticeVisibilityMode2": {
|
||||
"message": "Małe powiadomienia o przewinięciu"
|
||||
},
|
||||
"noticeVisibilityMode3": {
|
||||
"message": "Znikające powiadomienia o automatycznym pomijaniu"
|
||||
"message": "Półprzezroczyste powiadomienie o automatycznym przewinięciu"
|
||||
},
|
||||
"noticeVisibilityMode4": {
|
||||
"message": "Znikające powiadomienia o pomijaniu"
|
||||
"message": "Półprzezroczyste powiadomienie dla wszystkich przewinięć"
|
||||
},
|
||||
"longDescription": {
|
||||
"message": "SponsorBlock pozwala pomijać sponsorów, intra, outra, przypomnienia o subskrypcjach i inne irytujące fragmenty filmów na YouTube. SponsorBlock jest opartym na crowdsourcingu rozszerzeniem do przeglądarki, które pozwala każdemu zgłosić początek i koniec segmentów sponsorowanych oraz innych segmentów w filmach na YouTube. Kiedy ktoś już zamieści te informacje, wszyscy pozostali z tym rozszerzeniem będą pomijać segment sponsorowany. Możesz również pomijać fragmenty teledysków bez muzyki.",
|
||||
@@ -549,7 +549,7 @@
|
||||
"message": "Zawiera płynne przejścia"
|
||||
},
|
||||
"generic_guideline2": {
|
||||
"message": "Odtwarza się, jakby nic nie zostało pominięte"
|
||||
"message": "Pominięcie bez zauważalnego przeskoku"
|
||||
},
|
||||
"category_sponsor": {
|
||||
"message": "Sponsor"
|
||||
@@ -649,7 +649,7 @@
|
||||
"message": "Nie dla sekcji, które zawierają potrzebne informacje"
|
||||
},
|
||||
"category_filler": {
|
||||
"message": "Wypełniacz nietematyczny/Żart"
|
||||
"message": "Wypełniacz nietematyczny/żart"
|
||||
},
|
||||
"category_filler_description": {
|
||||
"message": "Sceny nietematyczne dodawane tylko jako wypełniacz lub dla humoru, które nie są wymagane do zrozumienia głównej treści filmu. Nie powinno to obejmować segmentów zawierających informacje kontekstowe lub szczegółowe."
|
||||
@@ -664,7 +664,7 @@
|
||||
"message": "Rozpraszacze, wpadki, powtórki"
|
||||
},
|
||||
"category_filler_guideline3": {
|
||||
"message": "Nie dla scen wymaganych, by zrozumieć temat"
|
||||
"message": "Nie nadaje się do scen wymaganych do zrozumienia tematu"
|
||||
},
|
||||
"category_music_offtopic": {
|
||||
"message": "Muzyka: Sekcja niemuzyczna"
|
||||
@@ -691,10 +691,10 @@
|
||||
"message": "Część filmu, której szuka większość osób"
|
||||
},
|
||||
"category_poi_highlight_guideline2": {
|
||||
"message": "Może pomijać kontekst"
|
||||
"message": "Może pomóc pominąć kontekst"
|
||||
},
|
||||
"category_poi_highlight_guideline3": {
|
||||
"message": "Może pomijać do tytułu lub miniaturki"
|
||||
"message": "Może pominąć do karty tytułowej lub miniaturki"
|
||||
},
|
||||
"category_livestream_messages": {
|
||||
"message": "Transmisja live: Dotacja/Czytanie wiadomości"
|
||||
@@ -737,7 +737,7 @@
|
||||
"description": "Referring to the category pill that is now shown on videos that are entirely sponsor or entirely selfpromo"
|
||||
},
|
||||
"previewColor": {
|
||||
"message": "Nieprzesłany kolor",
|
||||
"message": "Kolor nieprzesłanego segmentu",
|
||||
"description": "Referring to submissions that have not been sent to the server yet."
|
||||
},
|
||||
"seekBarColor": {
|
||||
@@ -1007,7 +1007,7 @@
|
||||
"description": "Appears in Options as a tab header for advanced/niche options. To fit inside the button, it should not be longer than ~20-25 characters (depending on their width)."
|
||||
},
|
||||
"noticeVisibilityLabel": {
|
||||
"message": "Pomiń wygląd wpisu",
|
||||
"message": "Wygląd okna pomijania",
|
||||
"description": "Option label"
|
||||
},
|
||||
"unbind": {
|
||||
|
||||
@@ -239,6 +239,9 @@
|
||||
"showSkipNotice": {
|
||||
"message": "Показувати сповіщення після пропуску сегмента"
|
||||
},
|
||||
"showCategoryGuidelines": {
|
||||
"message": "Показати Довідку по Категоріях"
|
||||
},
|
||||
"noticeVisibilityMode0": {
|
||||
"message": "Повнорозмірні сповіщення про пропуски"
|
||||
},
|
||||
|
||||
@@ -239,6 +239,9 @@
|
||||
"showSkipNotice": {
|
||||
"message": "Hiển thị thông báo sau khi bỏ qua phân đoạn"
|
||||
},
|
||||
"showCategoryGuidelines": {
|
||||
"message": "Hiển thị Danh mục Trợ giúp"
|
||||
},
|
||||
"noticeVisibilityMode0": {
|
||||
"message": "Thông báo bỏ qua với kích thước đầy đủ"
|
||||
},
|
||||
@@ -542,18 +545,36 @@
|
||||
"message": "đến",
|
||||
"description": "Used between segments. Example: 1:20 to 1:30"
|
||||
},
|
||||
"generic_guideline2": {
|
||||
"message": "Chơi như thể không có gì bị bỏ qua"
|
||||
},
|
||||
"category_sponsor": {
|
||||
"message": "Nhà tài trợ"
|
||||
},
|
||||
"category_sponsor_description": {
|
||||
"message": "Nội dung được trả tiền để quảng cáo, giới thiệu và quảng cáo trực tiếp. Không phải là quảng cáo không trả công hay được đề cập miễn phí."
|
||||
},
|
||||
"category_sponsor_guideline1": {
|
||||
"message": "Quảng cáo trả phí"
|
||||
},
|
||||
"category_sponsor_guideline2": {
|
||||
"message": "Không dành cho các khoản đóng góp"
|
||||
},
|
||||
"category_selfpromo": {
|
||||
"message": "Quảng cáo không trả công/Tự quảng cáo"
|
||||
},
|
||||
"category_selfpromo_description": {
|
||||
"message": "Tương tự như 'nhà tài trợ' ngoại trừ việc quảng cáo không được trả tiền hay tự quảng cáo. Điều này bao gồm các phần hàng hóa, đóng góp, hoặc thông tin về người mà họ hợp tác cùng."
|
||||
},
|
||||
"category_selfpromo_guideline1": {
|
||||
"message": "Quyên góp, tư cách thành viên và hàng hóa tùy chỉnh"
|
||||
},
|
||||
"category_selfpromo_guideline2": {
|
||||
"message": "Lời cảm ơn miễn phí không thêm vào video"
|
||||
},
|
||||
"category_selfpromo_guideline3": {
|
||||
"message": "Không dành cho các sản phẩm và hàng hóa do công ty thiết kế"
|
||||
},
|
||||
"category_exclusive_access": {
|
||||
"message": "Truy cập riêng"
|
||||
},
|
||||
@@ -564,12 +585,24 @@
|
||||
"message": "Video này giới thiệu sản phẩm, dịch vụ hoặc vị trí mà họ đã nhận được quyền truy cập miễn phí hoặc được trợ cấp",
|
||||
"description": "Short description for this category"
|
||||
},
|
||||
"category_exclusive_access_guideline1": {
|
||||
"message": "Toàn bộ video giới thiệu nội dung nào đó có quyền truy cập miễn phí hoặc được trợ cấp"
|
||||
},
|
||||
"category_interaction": {
|
||||
"message": "Nhắc tương tác (Đăng ký)"
|
||||
},
|
||||
"category_interaction_description": {
|
||||
"message": "Nhắc nhở người xem Thích, Đăng ký hoặc Theo dõi. Nếu nó dài hoặc là một cái gì cụ thể, nó nên là danh mục \"Tự quảng cáo\"."
|
||||
},
|
||||
"category_interaction_guideline1": {
|
||||
"message": "Lời nhắc ngắn gọn để thích, đăng ký hoặc theo dõi"
|
||||
},
|
||||
"category_interaction_guideline2": {
|
||||
"message": "Bao gồm lời nhắc gián tiếp để nhận xét"
|
||||
},
|
||||
"category_interaction_guideline3": {
|
||||
"message": "Không dành cho quảng cáo chung, chỉ dành cho lời kêu gọi hành động"
|
||||
},
|
||||
"category_interaction_short": {
|
||||
"message": "Nhắc nhở tương tác"
|
||||
},
|
||||
@@ -582,18 +615,36 @@
|
||||
"category_intro_short": {
|
||||
"message": "Tạm ngừng"
|
||||
},
|
||||
"category_intro_guideline1": {
|
||||
"message": "Khoảng thời gian không có nội dung thực tế"
|
||||
},
|
||||
"category_intro_guideline2": {
|
||||
"message": "Không dành cho chuyển tiếp với thông tin"
|
||||
},
|
||||
"category_outro": {
|
||||
"message": "Màn hình kết thúc/Danh đề"
|
||||
},
|
||||
"category_outro_description": {
|
||||
"message": "Credits hoặc khi thẻ màn hình kết thúc của YouTube xuất hiện. Không dùng với những đoạn có thông tin."
|
||||
},
|
||||
"category_outro_guideline1": {
|
||||
"message": "Không bao gồm nội dung, ngay cả khi thẻ kết thúc ở trên màn hình"
|
||||
},
|
||||
"category_preview": {
|
||||
"message": "Xem trước/Tóm tắt"
|
||||
},
|
||||
"category_preview_description": {
|
||||
"message": "Tóm tắt nhanh về tập trước/tập sau trong 1 chuỗi video (series) dài (hoặc cũng có thể là tóm tắt trước về video sắp chiếu)."
|
||||
},
|
||||
"category_preview_guideline1": {
|
||||
"message": "Các clip xuất hiện sau đó hoặc trong một video trong tương lai"
|
||||
},
|
||||
"category_preview_guideline2": {
|
||||
"message": "Tóm tắt video trước đó"
|
||||
},
|
||||
"category_preview_guideline3": {
|
||||
"message": "Không dành cho các phần thêm nội dung bổ sung"
|
||||
},
|
||||
"category_filler_description": {
|
||||
"message": "Tập hợp các cảnh không bắt buộc để xem trong video. Điều này không bao gồm các đoạn chứa nội dung hoặc nói về ngữ cảnh của video."
|
||||
},
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
transition: transform .1s cubic-bezier(0,0,0.2,1);
|
||||
}
|
||||
|
||||
.ytm-progress-bar > #previewbar {
|
||||
.progress-bar-line > #previewbar {
|
||||
height: 3px;
|
||||
}
|
||||
|
||||
|
||||
@@ -111,8 +111,6 @@ class CategorySkipOptionsComponent extends React.Component<CategorySkipOptionsPr
|
||||
skipOptionSelected(event: React.ChangeEvent<HTMLSelectElement>): void {
|
||||
let option: CategorySkipOption;
|
||||
|
||||
this.removeCurrentCategorySelection();
|
||||
|
||||
switch (event.target.value) {
|
||||
case "disable":
|
||||
return;
|
||||
@@ -130,28 +128,17 @@ class CategorySkipOptionsComponent extends React.Component<CategorySkipOptionsPr
|
||||
break;
|
||||
}
|
||||
|
||||
Config.config.categorySelections.push({
|
||||
name: this.props.category,
|
||||
option: option
|
||||
});
|
||||
|
||||
// Forces the Proxy to send this to the chrome storage API
|
||||
Config.config.categorySelections = Config.config.categorySelections;
|
||||
}
|
||||
|
||||
/** Removes this category from the config list of category selections */
|
||||
removeCurrentCategorySelection(): void {
|
||||
// Remove it if it exists
|
||||
for (let i = 0; i < Config.config.categorySelections.length; i++) {
|
||||
if (Config.config.categorySelections[i].name === this.props.category) {
|
||||
Config.config.categorySelections.splice(i, 1);
|
||||
|
||||
// Forces the Proxy to send this to the chrome storage API
|
||||
Config.config.categorySelections = Config.config.categorySelections;
|
||||
|
||||
break;
|
||||
}
|
||||
const existingSelection = Config.config.categorySelections.find(selection => selection.name === this.props.category);
|
||||
if (existingSelection) {
|
||||
existingSelection.option = option;
|
||||
} else {
|
||||
Config.config.categorySelections.push({
|
||||
name: this.props.category,
|
||||
option: option
|
||||
});
|
||||
}
|
||||
|
||||
Config.forceSyncUpdate("categorySelections");
|
||||
}
|
||||
|
||||
getCategorySkipOptions(): JSX.Element[] {
|
||||
|
||||
108
src/content.ts
108
src/content.ts
@@ -65,8 +65,8 @@ const videosWithEventListeners: HTMLVideoElement[] = [];
|
||||
const controlsWithEventListeners: HTMLElement[] = []
|
||||
|
||||
// This misleading variable name will be fixed soon
|
||||
let onInvidious;
|
||||
let onMobileYouTube;
|
||||
let onInvidious: boolean;
|
||||
let onMobileYouTube: boolean;
|
||||
|
||||
//the video id of the last preview bar update
|
||||
let lastPreviewBarUpdate;
|
||||
@@ -74,9 +74,6 @@ let lastPreviewBarUpdate;
|
||||
// Is the video currently being switched
|
||||
let switchingVideos = null;
|
||||
|
||||
// Made true every videoID change
|
||||
let firstEvent = false;
|
||||
|
||||
// Used by the play and playing listeners to make sure two aren't
|
||||
// called at the same time
|
||||
let lastCheckTime = 0;
|
||||
@@ -100,7 +97,10 @@ const playerButtons: Record<string, {button: HTMLButtonElement, image: HTMLImage
|
||||
// Direct Links after the config is loaded
|
||||
utils.wait(() => Config.config !== null, 1000, 1).then(() => videoIDChange(getYouTubeVideoID(document)));
|
||||
// wait for hover preview to appear, and refresh attachments if ever found
|
||||
window.addEventListener("DOMContentLoaded", () => utils.waitForElement(".ytp-inline-preview-ui").then(() => refreshVideoAttachments()));
|
||||
window.addEventListener("DOMContentLoaded", () => {
|
||||
utils.waitForElement(".ytp-inline-preview-ui").then(() => refreshVideoAttachments())
|
||||
utils.waitForElement("[data-sessionlink='feature=player-title']").then(() => videoIDChange(getYouTubeVideoID(document)))
|
||||
});
|
||||
addPageListeners();
|
||||
addHotkeyListener();
|
||||
|
||||
@@ -117,6 +117,9 @@ let submissionNotice: SubmissionNotice = null;
|
||||
// If there is an advert playing (or about to be played), this is true
|
||||
let isAdPlaying = false;
|
||||
|
||||
let lastResponseStatus: number;
|
||||
let retryCount = 0;
|
||||
|
||||
// Contains all of the functions and variables needed by the skip notice
|
||||
const skipNoticeContentContainer: ContentContainer = () => ({
|
||||
vote,
|
||||
@@ -163,6 +166,7 @@ function messageListener(request: Message, sender: unknown, sendResponse: (respo
|
||||
//send the sponsor times along with if it's found
|
||||
sendResponse({
|
||||
found: sponsorDataFound,
|
||||
status: lastResponseStatus,
|
||||
sponsorTimes: sponsorTimes,
|
||||
onMobileYouTube
|
||||
});
|
||||
@@ -202,8 +206,12 @@ function messageListener(request: Message, sender: unknown, sendResponse: (respo
|
||||
submitSponsorTimes();
|
||||
break;
|
||||
case "refreshSegments":
|
||||
// update video on refresh if videoID invalid
|
||||
if (!sponsorVideoID) videoIDChange(getYouTubeVideoID(document));
|
||||
// fetch segments
|
||||
sponsorsLookup(false).then(() => sendResponse({
|
||||
found: sponsorDataFound,
|
||||
status: lastResponseStatus,
|
||||
sponsorTimes: sponsorTimes,
|
||||
onMobileYouTube
|
||||
}));
|
||||
@@ -267,6 +275,7 @@ if (!Config.configSyncListeners.includes(contentConfigUpdateListener)) {
|
||||
function resetValues() {
|
||||
lastCheckTime = 0;
|
||||
lastCheckVideoTime = -1;
|
||||
retryCount = 0;
|
||||
|
||||
//reset sponsor times
|
||||
sponsorTimes = null;
|
||||
@@ -296,8 +305,6 @@ function resetValues() {
|
||||
logDebug("Setting switching videos to true (reset data)");
|
||||
}
|
||||
|
||||
firstEvent = true;
|
||||
|
||||
// Reset advert playing flag
|
||||
isAdPlaying = false;
|
||||
|
||||
@@ -413,7 +420,7 @@ function createPreviewBar(): void {
|
||||
isVisibleCheck: true
|
||||
}, {
|
||||
// For new mobile YouTube (#1287)
|
||||
selector: ".ytm-progress-bar",
|
||||
selector: ".progress-bar-line",
|
||||
isVisibleCheck: true
|
||||
}, {
|
||||
// For Desktop YouTube
|
||||
@@ -562,6 +569,19 @@ function startSponsorSchedule(includeIntersectingSegments = false, currentTime?:
|
||||
openNotice: skipInfo.openNotice
|
||||
});
|
||||
|
||||
// These are segments that start at the exact same time but need seperate notices
|
||||
for (const extra of skipInfo.extraIndexes) {
|
||||
const extraSkip = skipInfo.array[extra];
|
||||
if (shouldSkip(extraSkip)) {
|
||||
skipToTime({
|
||||
v: video,
|
||||
skipTime: [extraSkip.scheduledTime, extraSkip.segment[1]],
|
||||
skippingSegments: [extraSkip],
|
||||
openNotice: skipInfo.openNotice
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (utils.getCategorySelection(currentSkip.category)?.option === CategorySkipOption.ManualSkip
|
||||
|| currentSkip.actionType === ActionType.Mute) {
|
||||
forcedSkipTime = skipTime[0] + 0.001;
|
||||
@@ -695,8 +715,8 @@ function setupVideoListeners() {
|
||||
// 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 (video.readyState <= HTMLMediaElement.HAVE_CURRENT_DATA
|
||||
&& video.currentTime === 0) return;
|
||||
|
||||
updateVirtualTime();
|
||||
|
||||
@@ -828,7 +848,6 @@ async function sponsorsLookup(keepOldSubmissions = true) {
|
||||
const hashParams = getHashParams();
|
||||
if (hashParams.requiredSegment) extraRequestData.requiredSegment = hashParams.requiredSegment;
|
||||
|
||||
// Check for hashPrefix setting
|
||||
const hashPrefix = (await utils.getHash(sponsorVideoID, 1)).slice(0, 4) as VideoID & HashedValue;
|
||||
const response = await utils.asyncRequestToServer('GET', "/api/skipSegments/" + hashPrefix, {
|
||||
categories,
|
||||
@@ -837,13 +856,16 @@ async function sponsorsLookup(keepOldSubmissions = true) {
|
||||
...extraRequestData
|
||||
});
|
||||
|
||||
// store last response status
|
||||
lastResponseStatus = response?.status;
|
||||
|
||||
if (response?.ok) {
|
||||
const recievedSegments: SponsorTime[] = JSON.parse(response.responseText)
|
||||
?.filter((video) => video.videoID === sponsorVideoID)
|
||||
?.map((video) => video.segments)[0];
|
||||
if (!recievedSegments || !recievedSegments.length) {
|
||||
// return if no video found
|
||||
retryFetch();
|
||||
retryFetch(404);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -904,8 +926,8 @@ async function sponsorsLookup(keepOldSubmissions = true) {
|
||||
//otherwise the listener can handle it
|
||||
updatePreviewBar();
|
||||
}
|
||||
} else if (response?.status === 404) {
|
||||
retryFetch();
|
||||
} else {
|
||||
retryFetch(lastResponseStatus);
|
||||
}
|
||||
|
||||
if (Config.config.isVip) {
|
||||
@@ -939,16 +961,23 @@ async function lockedCategoriesLookup(): Promise<void> {
|
||||
}
|
||||
}
|
||||
|
||||
function retryFetch(): void {
|
||||
function retryFetch(errorCode: number): void {
|
||||
if (!Config.config.refetchWhenNotFound) return;
|
||||
|
||||
sponsorDataFound = false;
|
||||
|
||||
if (errorCode !== 404 && retryCount > 1) {
|
||||
// Too many errors (50x), give up
|
||||
return;
|
||||
}
|
||||
|
||||
retryCount++;
|
||||
|
||||
const delay = errorCode === 404 ? (10000 + Math.random() * 30000) : (2000 + Math.random() * 10000);
|
||||
setTimeout(() => {
|
||||
if (sponsorVideoID && sponsorTimes?.length === 0) {
|
||||
sponsorsLookup();
|
||||
}
|
||||
}, 10000 + Math.random() * 30000);
|
||||
}, delay);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1176,13 +1205,33 @@ async function whitelistCheck() {
|
||||
* Returns info about the next upcoming sponsor skip
|
||||
*/
|
||||
function getNextSkipIndex(currentTime: number, includeIntersectingSegments: boolean, includeNonIntersectingSegments: boolean):
|
||||
{array: ScheduledTime[], index: number, endIndex: number, openNotice: boolean} {
|
||||
{array: ScheduledTime[], index: number, endIndex: number, extraIndexes: number[], openNotice: boolean} {
|
||||
|
||||
const autoSkipSorter = (segment: ScheduledTime) => {
|
||||
const skipOption = utils.getCategorySelection(segment.category)?.option;
|
||||
if (skipOption === CategorySkipOption.AutoSkip
|
||||
&& segment.actionType === ActionType.Skip) {
|
||||
return 0;
|
||||
} else if (skipOption !== CategorySkipOption.ShowOverlay) {
|
||||
return 1;
|
||||
} else {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
const { includedTimes: submittedArray, scheduledTimes: sponsorStartTimes } =
|
||||
getStartTimes(sponsorTimes, includeIntersectingSegments, includeNonIntersectingSegments);
|
||||
const { scheduledTimes: sponsorStartTimesAfterCurrentTime } = getStartTimes(sponsorTimes, includeIntersectingSegments, includeNonIntersectingSegments, currentTime, true, true);
|
||||
|
||||
const minSponsorTimeIndex = sponsorStartTimes.indexOf(Math.min(...sponsorStartTimesAfterCurrentTime));
|
||||
// This is an array in-case multiple segments have the exact same start time
|
||||
const minSponsorTimeIndexes = GenericUtils.indexesOf(sponsorStartTimes, Math.min(...sponsorStartTimesAfterCurrentTime));
|
||||
// Find auto skipping segments if possible, sort by duration otherwise
|
||||
const minSponsorTimeIndex = minSponsorTimeIndexes.sort(
|
||||
(a, b) => ((autoSkipSorter(submittedArray[a]) - autoSkipSorter(submittedArray[b]))
|
||||
|| (submittedArray[a].segment[1] - submittedArray[a].segment[0]) - (submittedArray[b].segment[1] - submittedArray[b].segment[0])))[0] ?? -1;
|
||||
// Store extra indexes for the non-auto skipping segments if others occur at the exact same start time
|
||||
const extraIndexes = minSponsorTimeIndexes.filter((i) => i === minSponsorTimeIndex || autoSkipSorter(submittedArray[i]) !== 0);
|
||||
|
||||
const endTimeIndex = getLatestEndTimeIndex(submittedArray, minSponsorTimeIndex);
|
||||
|
||||
const { includedTimes: unsubmittedArray, scheduledTimes: unsubmittedSponsorStartTimes } =
|
||||
@@ -1198,6 +1247,7 @@ function getNextSkipIndex(currentTime: number, includeIntersectingSegments: bool
|
||||
array: submittedArray,
|
||||
index: minSponsorTimeIndex,
|
||||
endIndex: endTimeIndex,
|
||||
extraIndexes, // Segments at same time that need seperate notices
|
||||
openNotice: true
|
||||
};
|
||||
} else {
|
||||
@@ -1205,6 +1255,7 @@ function getNextSkipIndex(currentTime: number, includeIntersectingSegments: bool
|
||||
array: unsubmittedArray,
|
||||
index: minUnsubmittedSponsorTimeIndex,
|
||||
endIndex: previewEndTimeIndex,
|
||||
extraIndexes: [], // No manual things for unsubmitted
|
||||
openNotice: false
|
||||
};
|
||||
}
|
||||
@@ -1519,9 +1570,9 @@ async function createButtons(): Promise<void> {
|
||||
controls = await utils.wait(getControls).catch();
|
||||
|
||||
// Add button if does not already exist in html
|
||||
createButton("startSegment", "sponsorStart", () => closeInfoMenuAnd(() => startOrEndTimingNewSegment()), "PlayerStartIconSponsorBlocker.svg");
|
||||
createButton("cancelSegment", "sponsorCancel", () => closeInfoMenuAnd(() => cancelCreatingSegment()), "PlayerCancelSegmentIconSponsorBlocker.svg");
|
||||
createButton("delete", "clearTimes", () => closeInfoMenuAnd(() => clearSponsorTimes()), "PlayerDeleteIconSponsorBlocker.svg");
|
||||
createButton("startSegment", "sponsorStart", () => startOrEndTimingNewSegment(), "PlayerStartIconSponsorBlocker.svg");
|
||||
createButton("cancelSegment", "sponsorCancel", () => cancelCreatingSegment(), "PlayerCancelSegmentIconSponsorBlocker.svg");
|
||||
createButton("delete", "clearTimes", () => clearSponsorTimes(), "PlayerDeleteIconSponsorBlocker.svg");
|
||||
createButton("submit", "SubmitTimes", submitSponsorTimes, "PlayerUploadIconSponsorBlocker.svg");
|
||||
createButton("info", "openPopup", openInfoMenu, "PlayerInfoIconSponsorBlocker.svg");
|
||||
|
||||
@@ -1742,17 +1793,6 @@ function closeInfoMenu() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The content script currently has no way to notify the info menu of changes. As a workaround we close it, thus making it query the new information when reopened.
|
||||
*
|
||||
* This function and all its uses should be removed when this issue is fixed.
|
||||
* */
|
||||
function closeInfoMenuAnd<T>(func: () => T): T {
|
||||
closeInfoMenu();
|
||||
|
||||
return func();
|
||||
}
|
||||
|
||||
function clearSponsorTimes() {
|
||||
const currentVideoID = sponsorVideoID;
|
||||
|
||||
|
||||
@@ -63,6 +63,7 @@ export type Message = BaseMessage & (DefaultMessage | BoolValueMessage | IsInfoF
|
||||
|
||||
export interface IsInfoFoundMessageResponse {
|
||||
found: boolean;
|
||||
status: number;
|
||||
sponsorTimes: SponsorTime[];
|
||||
onMobileYouTube: boolean;
|
||||
}
|
||||
@@ -89,7 +90,7 @@ export type MessageResponse =
|
||||
| GetChannelIDResponse
|
||||
| SponsorStartResponse
|
||||
| IsChannelWhitelistedResponse
|
||||
| Record<string, never>
|
||||
| Record<never, never> // empty object response {}
|
||||
| VoteResponse;
|
||||
|
||||
export interface VoteResponse {
|
||||
|
||||
@@ -598,8 +598,9 @@ async function setTextOption(option: string, element: HTMLElement, value: string
|
||||
function downloadConfig() {
|
||||
const file = document.createElement("a");
|
||||
const jsonData = JSON.parse(JSON.stringify(Config.cachedSyncConfig));
|
||||
file.setAttribute("href", "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(jsonData)));
|
||||
file.setAttribute("download", "SponsorBlockConfig.json");
|
||||
const dateTimeString = new Date().toJSON().replace("T", "_").replace(/:/g, ".").replace(/.\d+Z/g, "")
|
||||
file.setAttribute("href", `data:text/json;charset=utf-8,${encodeURIComponent(JSON.stringify(jsonData))}`);
|
||||
file.setAttribute("download", `SponsorBlockConfig_${dateTimeString}.json`);
|
||||
document.body.append(file);
|
||||
file.click();
|
||||
file.remove();
|
||||
@@ -673,4 +674,4 @@ function copyDebugOutputToClipboard() {
|
||||
|
||||
function isIncognitoAllowed(): Promise<boolean> {
|
||||
return new Promise((resolve) => chrome.extension.isAllowedIncognitoAccess(resolve));
|
||||
}
|
||||
}
|
||||
|
||||
20
src/popup.ts
20
src/popup.ts
@@ -1,7 +1,7 @@
|
||||
import Config from "./config";
|
||||
|
||||
import Utils from "./utils";
|
||||
import { SponsorTime, SponsorHideType, ActionType } from "./types";
|
||||
import { SponsorTime, SponsorHideType, ActionType, StorageChangesObject } from "./types";
|
||||
import { Message, MessageResponse, IsInfoFoundMessageResponse } from "./messageTypes";
|
||||
import { showDonationLink } from "./utils/configUtils";
|
||||
import { AnimationUtils } from "./utils/animationUtils";
|
||||
@@ -133,6 +133,9 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> {
|
||||
getSegmentsFromContentScript(false);
|
||||
await utils.wait(() => Config.config !== null && allowPopup, 5000, 5);
|
||||
document.querySelector("body").style.removeProperty("visibility");
|
||||
if (!Config.configSyncListeners.includes(contentConfigUpdateListener)) {
|
||||
Config.configSyncListeners.push(contentConfigUpdateListener);
|
||||
}
|
||||
|
||||
PageElements.sbCloseButton.addEventListener("click", () => {
|
||||
sendTabMessage({
|
||||
@@ -364,8 +367,10 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> {
|
||||
PageElements.videoFound.innerHTML = chrome.i18n.getMessage("sponsorFound");
|
||||
|
||||
displayDownloadedSponsorTimes(request);
|
||||
} else {
|
||||
} else if (request.status == 404 || request.status == 200) {
|
||||
PageElements.videoFound.innerHTML = chrome.i18n.getMessage("sponsor404");
|
||||
} else {
|
||||
PageElements.videoFound.innerHTML = chrome.i18n.getMessage("connectionError") + request.status;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -917,7 +922,16 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> {
|
||||
return (days > 0 ? days + chrome.i18n.getMessage("dayAbbreviation") + " " : "") + (hours > 0 ? hours + chrome.i18n.getMessage("hourAbbreviation") + " " : "") + (minutes % 60).toFixed(1);
|
||||
}
|
||||
|
||||
//end of function
|
||||
function contentConfigUpdateListener(changes: StorageChangesObject) {
|
||||
for (const key in changes) {
|
||||
switch(key) {
|
||||
case "unsubmittedSegments":
|
||||
sponsorTimes = Config.config.unsubmittedSegments[currentVideoID] ?? [];
|
||||
updateSegmentEditingUI();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
runThePopup();
|
||||
|
||||
@@ -64,8 +64,17 @@ function hexToRgb(hex: string): {r: number, g: number, b: number} {
|
||||
} : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* List of all indexes that have the specified value
|
||||
* https://stackoverflow.com/a/54954694/1985387
|
||||
*/
|
||||
function indexesOf<T>(array: T[], value: T): number[] {
|
||||
return array.map((v, i) => v === value ? i : -1).filter(i => i !== -1);
|
||||
}
|
||||
|
||||
export const GenericUtils = {
|
||||
wait,
|
||||
getErrorMessage,
|
||||
getLuminance
|
||||
getLuminance,
|
||||
indexesOf
|
||||
}
|
||||
18
tsconfig-production.json
Normal file
18
tsconfig-production.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"target": "es6",
|
||||
"noImplicitAny": false,
|
||||
"sourceMap": false,
|
||||
"outDir": "dist/js",
|
||||
"noEmitOnError": false,
|
||||
"typeRoots": [ "node_modules/@types" ],
|
||||
"resolveJsonModule": true,
|
||||
"jsx": "react",
|
||||
"lib": [
|
||||
"es2019",
|
||||
"dom",
|
||||
"dom.iterable"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -3,14 +3,14 @@
|
||||
"module": "commonjs",
|
||||
"target": "es6",
|
||||
"noImplicitAny": false,
|
||||
"sourceMap": false,
|
||||
"sourceMap": true,
|
||||
"outDir": "dist/js",
|
||||
"noEmitOnError": false,
|
||||
"typeRoots": [ "node_modules/@types" ],
|
||||
"resolveJsonModule": true,
|
||||
"jsx": "react",
|
||||
"lib": [
|
||||
"es2019",
|
||||
"es2019",
|
||||
"dom",
|
||||
"dom.iterable"
|
||||
]
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
import webpack from "webpack"
|
||||
import path from "path"
|
||||
import { fileURLToPath } from "url"
|
||||
import CopyPlugin from "copy-webpack-plugin"
|
||||
import BuildManifest from "./webpack.manifest.cjs";
|
||||
const srcDir = "../src/";
|
||||
import fs from "fs";
|
||||
import ForkTsCheckerWebpackPlugin from "fork-ts-checker-webpack-plugin";
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url)
|
||||
const __dirname = path.dirname(__filename)
|
||||
const webpack = require("webpack");
|
||||
const path = require('path');
|
||||
const CopyPlugin = require('copy-webpack-plugin');
|
||||
const BuildManifest = require('./webpack.manifest');
|
||||
const srcDir = '../src/';
|
||||
const fs = require("fs");
|
||||
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
|
||||
|
||||
const edgeLanguages = [
|
||||
"de",
|
||||
@@ -27,7 +24,7 @@ const edgeLanguages = [
|
||||
"zh_CN"
|
||||
]
|
||||
|
||||
export default env => ({
|
||||
module.exports = env => ({
|
||||
entry: {
|
||||
popup: path.join(__dirname, srcDir + 'popup.ts'),
|
||||
background: path.join(__dirname, srcDir + 'background.ts'),
|
||||
@@ -53,7 +50,8 @@ export default env => ({
|
||||
exclude: /node_modules/,
|
||||
options: {
|
||||
// disable type checker for user in fork plugin
|
||||
transpileOnly: true
|
||||
transpileOnly: true,
|
||||
configFile: env.mode === "production" ? "tsconfig-production.json" : "tsconfig.json"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { merge } from "webpack-merge";
|
||||
import common from './webpack.common.js';
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
const merge = require('webpack-merge');
|
||||
const common = require('./webpack.common.js');
|
||||
|
||||
export default env => merge(common(env), {
|
||||
module.exports = env => merge(common(env), {
|
||||
devtool: 'inline-source-map',
|
||||
mode: 'development'
|
||||
});
|
||||
@@ -1,7 +1,8 @@
|
||||
import { merge } from "webpack-merge";
|
||||
import common from './webpack.common.js';
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
const { merge } = require('webpack-merge');
|
||||
const common = require('./webpack.common.js');
|
||||
|
||||
export default env => {
|
||||
module.exports = env => {
|
||||
let mode = "production";
|
||||
env.mode = mode;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user