Compare commits

...

35 Commits

Author SHA1 Message Date
Ajay
14da4b5fcc Merge branch 'master' of https://github.com/ajayyy/SponsorBlock 2023-05-08 20:16:50 -04:00
Ajay
9d6e23d171 Fix margin issue on category pill tooltip 2023-05-08 20:16:44 -04:00
Ajay Ramachandran
68a6286af6 Merge pull request #1715 from Blueberryy/master
Add notice time to translation file
2023-05-08 17:10:55 -04:00
Ajay Ramachandran
7960fde155 Add description to translation 2023-05-08 17:08:02 -04:00
Ajay Ramachandran
afe7271419 New Crowdin updates (#1733) 2023-05-08 17:06:22 -04:00
Ajay
c6c3bd3a3d bump version 2023-05-08 17:03:49 -04:00
Ajay
f2482ee973 Add auto-config import to clickbait extension, move more funcs to shared lib
Also fix a isSafari call
2023-05-08 17:02:49 -04:00
Ajay
71dd4a97bf Fix SponsorBlock on latest YouTube layout 2023-05-07 23:56:55 -04:00
Ajay Ramachandran
d8ca29a18b Update funding 2023-05-06 23:35:45 -04:00
Ajay
4d7018a017 Fix safari check not running function
Should make Firefox more precise
2023-05-06 20:05:43 -04:00
Ajay
ca24e82a6d Fix skip looping
Fixes #1747
2023-05-06 20:04:17 -04:00
Ajay Ramachandran
186fa7af61 Merge pull request #1739 from mini-bomba/invidious-duration-without-skips
Show time with skips removed on invidious
2023-05-03 11:52:37 -04:00
mini-bomba
75b406cb5b Show time with skips removed on invidious 2023-05-02 21:42:09 +02:00
Ajay
d20b46f3ef bump version 2023-04-30 20:32:59 -04:00
Ajay
b2f3605571 Fix submit button in fullscreen and theater mode 2023-04-30 18:13:38 -04:00
Ajay
da1be6c87b bump version 2023-04-30 16:49:45 -04:00
Ajay
62a60daac7 Fix preview bar not being created on video element change if not created previously 2023-04-30 14:54:50 -04:00
Ajay
45d45b0068 Fix preview bar not appearing on all videos 2023-04-30 14:35:37 -04:00
Blueberryy
4cae6e8f41 Real fix by mini-bomba
@mini-bomba

Co-Authored-By: mini-bomba <55105495+mini-bomba@users.noreply.github.com>
2023-04-29 15:52:24 +05:00
Ajay
d3fa735481 Don't show harmful vote option for non chapters 2023-04-27 22:29:08 -04:00
Ajay Ramachandran
052a805a98 Merge pull request #1729 from ajayyy/dependabot/npm_and_yarn/xml2js-and-web-ext-0.5.0
Bump xml2js and web-ext
2023-04-27 15:22:06 -04:00
Ajay Ramachandran
6e8c406da9 New Crowdin updates (#1722) 2023-04-27 15:20:11 -04:00
dependabot[bot]
6e6c3819e5 Bump xml2js and web-ext
Bumps [xml2js](https://github.com/Leonidas-from-XIV/node-xml2js) to 0.5.0 and updates ancestor dependency [web-ext](https://github.com/mozilla/web-ext). These dependencies need to be updated together.


Updates `xml2js` from 0.4.23 to 0.5.0
- [Release notes](https://github.com/Leonidas-from-XIV/node-xml2js/releases)
- [Commits](https://github.com/Leonidas-from-XIV/node-xml2js/commits/0.5.0)

Updates `web-ext` from 7.5.0 to 7.6.2
- [Release notes](https://github.com/mozilla/web-ext/releases)
- [Commits](https://github.com/mozilla/web-ext/compare/7.5.0...7.6.2)

---
updated-dependencies:
- dependency-name: xml2js
  dependency-type: indirect
- dependency-name: web-ext
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-27 19:18:54 +00:00
Ajay
2b739e33e6 bump version 2023-04-27 15:18:34 -04:00
Ajay
7768447ab0 Upgrade maze-utils, move video element refreshes to lib 2023-04-27 15:18:17 -04:00
Ajay
e31efbbf81 Fix looped videos sometimes not skipping start segment
Fixes  #1723
2023-04-21 22:16:13 -04:00
Blueberryy
dc0d7d7e45 Another fix NoticeComponent.tsx 2023-04-20 18:58:11 +05:00
Blueberryy
ade4214b25 fIX messages.json 2023-04-20 18:50:23 +05:00
Blueberryy
6bc4c686ec FIX NoticeComponent.tsx 2023-04-20 18:49:22 +05:00
Ajay Ramachandran
ab7dfe80f7 Merge pull request #1721 from biot/received
Spelling fix
2023-04-19 17:35:43 -04:00
Bert Vermeulen
c5f549f937 Spelling fix 2023-04-19 19:26:45 +02:00
Ajay
a7aa4042ff Fix video labels showing all categories regardless of settings 2023-04-17 20:29:52 -04:00
Ajay
8136a53981 Fix wrapping issue on safari 2023-04-17 20:02:11 -04:00
Blueberryy
1b714470de add translatable s in notice 2023-04-11 23:03:29 +05:00
Blueberryy
32fd64ee25 add translatable s in notice 2023-04-11 23:03:23 +05:00
44 changed files with 626 additions and 1062 deletions

2
.github/FUNDING.yml vendored
View File

@@ -1,3 +1,3 @@
github: ajayyy-org
patreon: ajayyy
custom: [buy.ajay.app/l/sponsorblock, sponsor.ajay.app/donate]
custom: [sponsor.ajay.app/donate]

View File

@@ -30,5 +30,11 @@
"guidelines": "https://wiki.sponsor.ajay.app/w/Guidelines",
"mute": "https://wiki.sponsor.ajay.app/w/Mute_Segment",
"chapter": "https://wiki.sponsor.ajay.app/w/Chapter"
}
},
"extensionCommunicationAllowList": [
"enamippconapkdmgfgjchkhakpfinmaj",
"deArrow@ajay.app",
"deArrowBETA@ajay.app",
"app.ajay.dearrow.extension"
]
}

View File

@@ -1,7 +1,7 @@
{
"name": "__MSG_fullName__",
"short_name": "SponsorBlock",
"version": "5.4.1",
"version": "5.4.6",
"default_locale": "en",
"description": "__MSG_Description__",
"homepage_url": "https://sponsor.ajay.app",

1213
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -4,7 +4,7 @@
"description": "",
"main": "background.js",
"dependencies": {
"@ajayyy/maze-utils": "1.1.11",
"@ajayyy/maze-utils": "1.1.25",
"content-scripts-register-polyfill": "^4.0.2",
"react": "^18.2.0",
"react-dom": "^18.2.0"
@@ -34,7 +34,7 @@
"ts-loader": "^9.4.2",
"ts-node": "^10.9.1",
"typescript": "4.9",
"web-ext": "^7.5.0",
"web-ext": "^7.6.2",
"webpack": "^5.75.0",
"webpack-cli": "^4.10.0",
"webpack-merge": "^5.8.0"

View File

@@ -1215,8 +1215,5 @@
},
"exportSegmentsAsURL": {
"message": "Del som URL"
},
"segmentFetchFailureWarning": {
"message": "Advarsel: Serveren har endnu ikke svaret med segmenter. Der kan faktisk være segmenter på denne video, der allerede er indsendt, men du har bare ikke modtaget dem på grund af problemer med serveren."
}
}

View File

@@ -1231,7 +1231,7 @@
"message": "Als URL teilen"
},
"segmentFetchFailureWarning": {
"message": "Warnung: Der Server hat noch nicht mit Segmenten geantwortet. Möglicherweise gibt es bereits Segmente zu diesem Video, aber du hast sie aufgrund von Problemen mit dem Server noch nicht erhalten."
"message": "Warnung: Der Server hat noch nicht mit Segmenten geantwortet. Möglicherweise gibt es in diesem Video bereits übermittelte Segmente, aber du hast sie aufgrund von Serverproblemen noch nicht erhalten."
},
"allowScrollingToEdit": {
"message": "Scrollen zum Bearbeiten von Zeiten erlauben"

View File

@@ -1231,9 +1231,13 @@
"message": "Share as URL"
},
"segmentFetchFailureWarning": {
"message": "Warning: The server hasn't responded with segments yet. There might actually be segments on this video already submitted but you just haven't recieved them due to issues with the server."
"message": "Warning: The server hasn't responded with segments yet. There might actually be segments on this video already submitted but you just haven't received them due to issues with the server."
},
"allowScrollingToEdit": {
"message": "Allow Scrolling To Edit Times"
},
"NoticeTimeAfterSkip": {
"message": "{seconds}s",
"description": "This is used on the popup to show how much time left. It will look like \"5s\". The word {seconds} will be replaced, so keep it here. Translations should only change the \"s\""
}
}

View File

@@ -17,7 +17,7 @@
"message": "Esto ya ha sido enviado antes"
},
"channelWhitelisted": {
"message": "¡Canal Permitido!"
"message": "¡Canal permitido!"
},
"Segment": {
"message": "segmento"
@@ -604,7 +604,7 @@
"message": "Promociones pagadas"
},
"category_sponsor_guideline2": {
"message": "No para donaciones o merchandising"
"message": "No para donaciones o mercancía personalizada"
},
"category_selfpromo": {
"message": "Promoción Propia/No Remunerada"
@@ -613,13 +613,13 @@
"message": "Similar a \"sponsor\", excepto que para la promoción propia o no remunerada. Esto incluye secciones sobre mercancía, donaciones o información sobre con quiénes colaboraron."
},
"category_selfpromo_guideline1": {
"message": "Donaciones, afiliaciones y merchandising"
"message": "Donaciones, membresías y mercancía personalizada"
},
"category_selfpromo_guideline2": {
"message": "Comentarios inútiles que no aportan nada al vídeo"
"message": "Agradecimientos gratuitos que no contribuyen al video"
},
"category_selfpromo_guideline3": {
"message": "No para productos y merchandising de empresas"
"message": "No para productos ni mercancía diseñados por empresas"
},
"category_exclusive_access": {
"message": "Acceso Exclusivo"
@@ -641,13 +641,13 @@
"message": "Cuando hay un breve recordatorio para dar me gusta, suscribirse o seguirlos en medio del contenido. Si es largo o sobre algo específico, debería estar bajo promoción propia en su lugar."
},
"category_interaction_guideline1": {
"message": "Recordatorios breves para darle a me gusta, suscribirse o seguir"
"message": "Recordatorios breves para darle me gusta, suscribirse o seguir"
},
"category_interaction_guideline2": {
"message": "Incluye recordatorios indirectos para comentar"
},
"category_interaction_guideline3": {
"message": "No para promoción general, solo peticiones de actuación"
"message": "No para promoción general, solo llamadas a la acción"
},
"category_interaction_short": {
"message": "Recordatorio de Interacción"
@@ -680,13 +680,13 @@
"message": "Vista previa/Recapitulación"
},
"category_preview_description": {
"message": "Colección de vídeos que muestran lo que se verá en este vídeo o en otros vídeos de una serie en la que toda esta información se repite más adelante en el vídeo."
"message": "Colección de clips que muestran lo que vendrá en este video u otros videos en una serie en la cual toda la información es repetida en el video."
},
"category_preview_guideline1": {
"message": "Vídeos que aparecen más tarde, o en un vídeo futuro"
"message": "Clips que aparecen más tarde o en un video futuro"
},
"category_preview_guideline2": {
"message": "Recopilación de un vídeo anterior"
"message": "Recapitulación de un video anterior"
},
"category_preview_guideline3": {
"message": "No para secciones que añaden contenido adicional"
@@ -722,7 +722,7 @@
"message": "Secciones que no están en versiones oficiales"
},
"category_music_offtopic_guideline2": {
"message": "Sin música en un espectáculo en directo"
"message": "Secciones sin música en un espectáculo en vivo"
},
"category_poi_highlight": {
"message": "Destacado"

View File

@@ -1230,9 +1230,6 @@
"exportSegmentsAsURL": {
"message": "Jaga URLina"
},
"segmentFetchFailureWarning": {
"message": "Tähelepanu: Server ei ole veel segmente edastanud. Sellel videol võivad olla esitatud segmendid, aga te pole neid serveri tõrke tõttu kätte saanud."
},
"allowScrollingToEdit": {
"message": "Luba aegade muutmiseks kerimine"
}

View File

@@ -1231,7 +1231,7 @@
"message": "Jaa URL-osoitteena"
},
"segmentFetchFailureWarning": {
"message": "Varoitus: Palvelin ei ole vielä toimittanut osiotietoja. Video saattaa sisältää jo lähetettyjä osioita, mutta et vain ole vielä vastaanottanut niitä palvelinongelmien takia."
"message": "Varoitus: Palvelin ei ole vielä toimittanut osiotietoja. Video saattaa sisältää jo ilmoitettuja osioita, mutta et vain ole vielä vastaanottanut niitä palvelinongelmien takia."
},
"allowScrollingToEdit": {
"message": "Salli aikojen muokkaaminen skrollaamalla"

View File

@@ -153,7 +153,7 @@
"message": "Soumissions"
},
"savedPeopleFrom": {
"message": "Vous avez sauvé les utilisateurices de "
"message": "Vous avez sauvé les utilisateurs de "
},
"viewLeaderboard": {
"message": "Classement"
@@ -226,7 +226,7 @@
"message": "Activer le suivi du nombre de sauts de segments"
},
"whatViewTracking": {
"message": "Cette fonctionnalité enregistre les segments que vous sautez, de manière à informer leur auteurice que leur soumission a été utile, et est également utilisée en complément des votes afin d'éviter l'enregistrement de spams dans la base de données. SponsorBlock envoie un message au serveur à chaque fois que vous passez un segment. Pour garder des statistiques représentatives, nous espérons que la plupart des gens ne modifiront pas ce paramètre. :)"
"message": "Cette fonctionnalité enregistre les segments que vous avez sautés afin d'informer leur auteur à quel point leur soumission a été utile. Elle est aussi utilisée en complément des votes positifs pour empêcher la soumission de spams dans la base de données. SponsorBlock envoie un message au serveur à chaque fois que vous passez un segment. Nous espérons que la plupart des utilisateurs ne modifieront pas ce paramètre afin de conserver des statistiques aussi représentatives que possible. :)"
},
"enableViewTrackingInPrivate": {
"message": "Activer le décompte du nombre de segments sautés dans les onglets de navigation privée/incognito"
@@ -424,7 +424,7 @@
"message": "Importer/Exporter Votre ID privé d'utilisateur"
},
"whatChangeUserID": {
"message": "Il doit rester privé. 0 l'instar d'un mot de passe, il ne doit être partagé avec personne. Si une autre personne est en possession de cette information, elle peut usurper votre identité SponsorBlock. Si vous cherchez votre UserID public, cliquez sur l'icône du presse-papiers dans l'encart."
"message": "Cela doit rester privé. À l'instar d'un mot de passe, il ne doit être partagé avec personne. Si une autre personne est en possession de cette donnée, elle peut usurper votre identité SponsorBlock. Si vous cherchez votre UserID public, cliquez sur l'icône du presse-papiers dans l'encart."
},
"setUserID": {
"message": "Définir l'ID privé d'utilisateur"
@@ -1230,9 +1230,6 @@
"exportSegmentsAsURL": {
"message": "Partager un URL"
},
"segmentFetchFailureWarning": {
"message": "Attention : Le serveur n'a pas encore répondu avec les segments. Il se peut qu'il y ait des segments sur cette vidéo déjà soumise, mais vous ne les avez tout simplement pas reçus en raison de problèmes avec le serveur."
},
"allowScrollingToEdit": {
"message": "Autoriser l'utilisation de la molette pour modifier les temps"
}

View File

@@ -773,8 +773,5 @@
},
"exportSegmentsAsURL": {
"message": "שיתוף כקישור"
},
"segmentFetchFailureWarning": {
"message": "אזהרה: השרת עדיין לא הגיב עם מקטעים. ייתכן שלמעשה יש מקטעים בסרטון הזה שכבר נשלחו אבל פשוט לא קיבלת אותם בגלל בעיות בשרת."
}
}

View File

@@ -128,6 +128,9 @@
"closeIcon": {
"message": "Ikona za zatvaranje"
},
"OpenSubmissionMenu": {
"message": "Otvori preglednik prijava"
},
"sortSegments": {
"message": "Razvrstaj isječke"
},

View File

@@ -1219,9 +1219,6 @@
"exportSegmentsAsURL": {
"message": "Bagikan sebagai Tautan"
},
"segmentFetchFailureWarning": {
"message": "Peringatan: Server belum merespon dengan segmen. Mungkin sebenarnya sudah ada segmen di video ini namun Anda belum menerimanya karena ada masalah dengan server."
},
"allowScrollingToEdit": {
"message": "Izinkan Menggulir Untuk Menyunting Waktu"
}

View File

@@ -1230,9 +1230,6 @@
"exportSegmentsAsURL": {
"message": "Condividi URL"
},
"segmentFetchFailureWarning": {
"message": "Attenzione: il server non ha ancora fornito i segmenti. Questo video potrebbe avere dei segmenti inviati, ma forse non sono stati ricevuti a causa di problemi del server."
},
"allowScrollingToEdit": {
"message": "Usa la Rotella per Modificare i Tempi"
}

View File

@@ -1231,7 +1231,7 @@
"message": "URLとして共有"
},
"segmentFetchFailureWarning": {
"message": "警告: サーバーまだセグメント応答していません。この動画に対するセグメントはすでに提出されているものの、サーバーの問題によりそれが受信できていないだけという可能性あります。"
"message": "警告: サーバーまだセグメントへの応答していません。実際には、この動画のセグメントは既に送信済みかもしれません。一方、単にサーバーの問題により受信できていない可能性あります。"
},
"allowScrollingToEdit": {
"message": "スクロールで時間を編集できるようにする"

View File

@@ -1215,8 +1215,5 @@
},
"exportSegmentsAsURL": {
"message": "Kongsi sebagai URL"
},
"segmentFetchFailureWarning": {
"message": "Amaran: Pelayan belum membalas dengan segmen lagi. Mungkin sebenarnya ada segmen di video ini sudah dihantar tetapi anda hanya belum menerimanya kerana isu dengan pelayan."
}
}

View File

@@ -1226,9 +1226,6 @@
"exportSegmentsAsURL": {
"message": "Delen als URL"
},
"segmentFetchFailureWarning": {
"message": "Waarschuwing: de server heeft nog niet gereageerd met segmenten. Misschien zijn er al segmenten van deze video ingediend, maar heeft u ze nog niet ontvangen door problemen met de server."
},
"allowScrollingToEdit": {
"message": "Scrollen toestaan om tijdstippen te bewerken"
}

View File

@@ -1231,7 +1231,7 @@
"message": "Udostępnij jako adres URL"
},
"segmentFetchFailureWarning": {
"message": "Ostrzeżenie: Serwer nie odpowiedział jeszcze na segmenty. Być może segmenty na tym filmie są już wysłane, ale po prostu nie otrzymałeś ich z powodu problemów z serwerem."
"message": "Ostrzeżenie: Serwer nie odpowiedział jeszcze na segmenty. Być może segmenty na tym filmie są już wysłane, ale po prostu nie otrzymano ich z powodu problemów z serwerem."
},
"allowScrollingToEdit": {
"message": "Zezwalaj na scroll'owanie do edycji czasów"

View File

@@ -14,10 +14,10 @@
"message": "Você enviou muitos segmentos para esse vídeo, tem certeza de que são tantos assim?"
},
"409": {
"message": "Isso já foi enviado antes"
"message": "Esse segmento já foi enviado."
},
"channelWhitelisted": {
"message": "Canal adicionado à lista branca!"
"message": "Canal adicionado à lista de permissões!"
},
"Segment": {
"message": "segmento"
@@ -141,10 +141,10 @@
"message": "Você tem certeza que deseja enviar isto?"
},
"whitelistChannel": {
"message": "Adicionar canal à lista branca"
"message": "Adicionar canal à lista de permissões"
},
"removeFromWhitelist": {
"message": "Remover canal da lista branca"
"message": "Remover canal da lista de permissões"
},
"voteOnTime": {
"message": "Votar em um segmento"
@@ -181,7 +181,7 @@
"message": "Definir nome de usuário"
},
"copyPublicID": {
"message": "Copiar ID pública de usuário"
"message": "Copiar ID de usuário pública"
},
"copySegmentID": {
"message": "Copiar ID do segmento"
@@ -268,13 +268,13 @@
"message": "Mostrar categoria de ajuda"
},
"noticeVisibilityMode0": {
"message": "Avisos de pulo em tamanho completo"
"message": "Avisos de pulo de duração normal"
},
"noticeVisibilityMode1": {
"message": "Avisos de pulo pequeno no pulo automático"
"message": "Avisos de pulo automático, mesmo pequenos"
},
"noticeVisibilityMode2": {
"message": "Todos os avisos de pulo pequeno"
"message": "Todos os avisos de pulo, mesmo de curta duração"
},
"noticeVisibilityMode3": {
"message": "Avisos de pulo semitransparente no pulo automático"
@@ -342,7 +342,7 @@
"message": "O servidor parece estar sobrecarregado. Tente novamente em alguns segundos."
},
"errorCode": {
"message": "Código de erro: "
"message": "Código do erro: "
},
"skip": {
"message": "Pular"
@@ -365,11 +365,11 @@
"description": "Used for skipping to things (Skip to Highlight)"
},
"skipped": {
"message": "{0} Pulado (a)",
"message": "{0} pulado",
"description": "Example: Sponsor Skipped"
},
"muted": {
"message": "{0} Silenciado",
"message": "{0} silenciado",
"description": "Example: Sponsor Muted"
},
"skipped_to_category": {
@@ -414,7 +414,7 @@
"description": "You've saved people from 887,362 segments (236d 15h 5.3 minutes of their lives)."
},
"youHaveSavedTimeEnd": {
"message": " das vidas dos outros",
"message": " de suas vidas",
"description": "You've saved people from 887,362 segments (236d 15h 5.3 minutes of their lives)."
},
"statusReminder": {
@@ -554,7 +554,7 @@
"message": "Deletar"
},
"preview": {
"message": "Pré-visualizar"
"message": "Prévia"
},
"unsubmitted": {
"message": "Não enviado"
@@ -572,7 +572,7 @@
"message": "Erro ao copiar para a área de transferência"
},
"copyDebugInformationOptions": {
"message": "Copia informações para a área de transferência para serem fornecidas a um desenvolvedor quando houver um bug / quando solicitado pelo desenvolvedor. Informações sensíveis como seu ID de usuário, canais na lista de permissões e endereço personalizado do servidor foram removidos. No entanto, ele contém informações como seu useragent, navegador, sistema operacional e número de versão da extensão. "
"message": "Copia informações para a área de transferência para serem fornecidas a um desenvolvedor quando houver um bug ou quando solicitado por um desenvolvedor. Informações sensíveis como seu ID de usuário, canais na lista de permissões e endereço personalizado do servidor foram removidos. No entanto, ele contém informações como seu useragent, navegador, sistema operacional e número de versão da extensão. "
},
"copyDebugInformationComplete": {
"message": "A informação de depuração foi copiada para a área de transferência. Sinta-se à vontade para remover qualquer informação que prefira não compartilhar. Salve em um arquivo de texto ou cole-a no relatório de erro."
@@ -607,7 +607,7 @@
"message": "Não é para doações ou mercadoria personalizada"
},
"category_selfpromo": {
"message": "Não-pago/Auto-promoção"
"message": "Não-pago/Autopromoção"
},
"category_selfpromo_description": {
"message": "Similar a \"patrocinador\", exceto para não-pago ou auto-promoção. Isso inclui seções sobre mercadorias, doações ou informações sobre com quem eles colaboraram."
@@ -622,7 +622,7 @@
"message": "Não é para produtos de origem corporativa ou mercadorias"
},
"category_exclusive_access": {
"message": "Acesso Exclusivo"
"message": "Acesso exclusivo"
},
"category_exclusive_access_description": {
"message": "Apenas para rotular vídeos inteiros. Usado quando um vídeo apresenta um produto, serviço ou local ao qual eles receberam acesso gratuito ou subsidiado."
@@ -635,7 +635,7 @@
"message": "Todo o vídeo promove algo de acesso gratuito ou subsidiado"
},
"category_interaction": {
"message": "Lembrete de Interação (Inscrever-se)"
"message": "Lembrete de interação (inscrever-se)"
},
"category_interaction_description": {
"message": "Quando houver um pequeno lembrete para curtir, inscrever-se ou seguir no meio do conteúdo. Se é longo ou sobre algo em específico, deveria estar sob auto-promoção."
@@ -650,10 +650,10 @@
"message": "Não é para promoção geral, apenas um chamado para à ação"
},
"category_interaction_short": {
"message": "Lembrete de Interação"
"message": "Lembrete de interação"
},
"category_intro": {
"message": "Intervalo/Animação de Introdução"
"message": "Intervalo/Vinheta de abertura"
},
"category_intro_description": {
"message": "Um intervalo sem conteúdo real. Pode ser uma pausa, um quadro estático, uma animação repetitiva. Isso não deve ser usado em transições que contenham informação."
@@ -677,7 +677,7 @@
"message": "Não inclui conteúdo, mesmo que cartões de finalização estejam na tela"
},
"category_preview": {
"message": "Pré-visualização/Recapitulação"
"message": "Prévia/Recapitulação"
},
"category_preview_description": {
"message": "Coleção de clipes que mostram o que está por vir neste vídeo ou em outros vídeos em uma série onde todas as informações são repetidas mais tarde no vídeo."
@@ -710,13 +710,13 @@
"message": "Não é para cenas necessárias para o entendimento do tópico"
},
"category_music_offtopic": {
"message": "Música: Seção Não Musical"
"message": "Música: trecho sem música"
},
"category_music_offtopic_description": {
"message": "Apenas para uso em vídeos musicais. Deve ser usado exclusivamente para seções de vídeos musicais que já não pertençam à outra categoria."
},
"category_music_offtopic_short": {
"message": "Não Musical"
"message": "Sem música"
},
"category_music_offtopic_guideline1": {
"message": "Seções que não estão nos lançamentos oficiais"
@@ -767,7 +767,7 @@
"message": "Pular manualmente"
},
"showOverlay": {
"message": "Mostrar barra de progresso"
"message": "Mostrar na barra de progresso"
},
"disable": {
"message": "Desativar"
@@ -788,7 +788,7 @@
"message": "Mostrar capítulos"
},
"autoSkipOnMusicVideos": {
"message": "Pular automaticamente todos os segmentos quando há um segmento não musical"
"message": "Pular automaticamente todos os segmentos quando houver trechos sem música"
},
"muteSegments": {
"message": "Permitir segmentos que silenciem o áudio ao invés de pular"
@@ -822,7 +822,7 @@
"message": "Seus envios e votos NÃO SERÃO ENVIADOS para o servidor principal. Use isso apenas para testes."
},
"testingServerWarning": {
"message": "Todas os envios e votos NÃO SERÃO ENVIADOS para o servidor principal enquanto se conecta ao servidor de teste. Certifique-se de desativar isso quando você quiser fazer envios reais."
"message": "Todos os envios e votos NÃO SERÃO ENVIADOS para o servidor principal quando conectado ao servidor de teste. Desative quando você quiser fazer envios reais."
},
"bracketNow": {
"message": "(Agora)"
@@ -861,7 +861,7 @@
},
"channelDataNotFound": {
"description": "This error appears in an alert when they try to whitelist a channel and the extension is unable to determine what channel they are looking at.",
"message": "O ID do canal ainda não foi carregado. Se você estiver usando um vídeo embutido, tente usar a página inicial do YouTube. Isso também pode ser causado por mudanças no layout do YouTube, se você acreditar que este é o caso, faça um comentário aqui:"
"message": "O ID do canal ainda não foi carregado. Se você estiver usando um vídeo incorporado, tente usar a página inicial do YouTube. Isso também pode ser causado por mudanças no layout do YouTube, se este for o caso, comente aqui:"
},
"invidiousPermissionRefresh": {
"message": "O navegador revogou a permissão necessária para funcionar em Invidious e em outros sites de terceiros. Por favor, clique no botão abaixo para reativar essa permissão."
@@ -876,13 +876,13 @@
"message": "Falha na solicitação de permissão, você clicou em negar?"
},
"adblockerIssueWhitelist": {
"message": "Se você não consegue resolver isso, desative a configuração 'Forçar verificação do canal antes de pular', pois o SponsorBlock não pode recuperar as informações deste vídeo"
"message": "Se você não consegue resolver isso, desative a opção 'Forçar verificação do canal antes de pular', pois o SponsorBlock não pode recuperar as informações deste vídeo"
},
"forceChannelCheck": {
"message": "Forçar verificação do canal antes de pular"
},
"whatForceChannelCheck": {
"message": "Por padrão, isso pulará os segmentos imediatamente, mesmo antes de saber qual é o canal. Por padrão, alguns seguimentos no inicio do vídeo podem ser ignorados nos canais da lista branca. Habilitar esta opção evitará isso, mas fará com que todos os pulos tenham um ligeiro atraso, já que obter o ID do canal pode levar algum tempo. Este atraso pode não ser perceptível se você tiver internet rápida."
"message": "Por padrão, ele pulará segmentos imediatamente antes mesmo de saber qual é o canal. Alguns segmentos no início do vídeo podem ser ignorados nos canais da lista de permissões. A ativação dessa opção evitará isso, mas irá fazer com que todos os pulos tenham um pequeno atraso, pois a obtenção do ID do canal pode levar algum tempo. Esse atraso pode ser imperceptível se você possuir uma internet rápida."
},
"forceChannelCheckPopup": {
"message": "Considere ativar \"Forçar verificação do canal antes de pular\""
@@ -901,7 +901,7 @@
"message": "Mudar categoria"
},
"nonMusicCategoryOnMusic": {
"message": "Este vídeo é categorizado como musical. Tem certeza de que tem um patrocinador? Se este é realmente um \"Segmento Não Musical\", abra as opções da extensão e habilite esta categoria. Assim você pode enviar este segmento como \"Não Musical\" ao invés de patrocinador. Por favor leia as diretrizes se estiver confuso."
"message": "Esse vídeo é categorizado como música. Tem certeza de que é patrocinado? Se realmente for um trecho sem música, abra as opções da extensão e ative a categoria. Assim, você pode enviar esse segmento como \"sem música\" em vez de \"patrocinador\". Leia as diretrizes se tiver dúvidas."
},
"multipleSegments": {
"message": "Múltiplos segmentos"
@@ -1097,7 +1097,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": "Aparência da notificação de pulo",
"message": "Quando mostrar aviso de pulo",
"description": "Option label"
},
"unbind": {
@@ -1231,7 +1231,7 @@
"message": "Compartilhar como URL"
},
"segmentFetchFailureWarning": {
"message": "Aviso: O servidor ainda não respondeu com segmentos. Na verdade, pode haver segmentos neste vídeo já enviados, mas você não os recebeu devido a problemas com o servidor."
"message": "Alerta: o servidor ainda não respondeu com segmentos. Pode ser que os segmentos desse vídeo já tenham sido enviados, mas ainda não foram recebidos devido a problemas do servidor."
},
"allowScrollingToEdit": {
"message": "Permitir rolagem para editar tempos"

View File

@@ -252,6 +252,9 @@
"whatRefetchWhenNotFound": {
"message": "Se o vídeo for novo e nenhum segmento for encontrado, continuaremos a monitorizar enquanto assiste."
},
"enableShowCategoryWithoutPermission": {
"message": "Mostrar categorias no menu de submissão mesmo sem permissão de submissão"
},
"whatShowCategoryWithoutPermission": {
"message": "Algumas categorias requerem permissão para submeter devido aos requisitos mínimos de reputação"
},
@@ -273,6 +276,16 @@
"noticeVisibilityMode2": {
"message": "Todos os avisos de ignorar em tamanho pequeno"
},
"noticeVisibilityMode3": {
"message": "Avisos pequenos quando ignorado automaticamente"
},
"noticeVisibilityMode4": {
"message": "Todos os avisos de ignorar em tamanho pequeno"
},
"longDescription": {
"message": "SponsorBlock permite-lhe ignorar os patrocinadores, intros, outros, lembretes de subscrição, e outras partes irritantes dos vídeos do YouTube. SponsorBlock é uma extensão de browser de origem pública que permite a qualquer pessoa submeter o tempo de início e fim dos segmentos patrocinados e outros segmentos dos vídeos do YouTube. Uma vez que uma pessoa submeta esta informação, todos os outros com esta extensão saltarão diretamente sobre o segmento patrocinado. Também se pode saltar sobre secções não musicais de vídeos musicais.",
"description": "Full description of the extension on the store pages."
},
"website": {
"message": "Site",
"description": "Used on Firefox Store Page"
@@ -281,6 +294,18 @@
"message": "Código-fonte",
"description": "Used on Firefox Store Page"
},
"noticeUpdate": {
"message": "O aviso foi atualizado!",
"description": "The first line of the message displayed after the notice was upgraded."
},
"noticeUpdate2": {
"message": "Se mesmo assim não gostar, carregue no botão nunca mostrar.",
"description": "The second line of the message displayed after the notice was upgraded."
},
"setSkipShortcut": {
"message": "Saltar segmento",
"description": "Keybind label"
},
"setStartSponsorShortcut": {
"message": "Iniciar/parar segmento",
"description": "Keybind label"
@@ -297,6 +322,22 @@
"message": "Capítulo anterior",
"description": "Keybind label"
},
"keybindDescription": {
"message": "Selecione uma chave digitando-a e escolha qualquer chave modificadora que deseje utilizar."
},
"0": {
"message": "Tempo limite de conexão. Verifique a sua conexão com a internet. Se a sua internet está a funcionar, o servidor provavelmente está sobrecarregado ou desligado."
},
"disableSkipping": {
"message": "Saltar está ativado"
},
"enableSkipping": {
"message": "Saltar está desativado"
},
"yourWork": {
"message": "O seu trabalho",
"description": "Used to describe the section that will show you the statistics from your submissions."
},
"502": {
"message": "O servidor parece estar sobrecarregado. Tente novamente em alguns segundos."
},
@@ -331,6 +372,10 @@
"message": "{0} silenciado",
"description": "Example: Sponsor Muted"
},
"skipped_to_category": {
"message": "Avançar para {0}",
"description": "Used for skipping to things (Skipped to Highlight)"
},
"minLower": {
"message": "minuto"
},
@@ -351,6 +396,9 @@
"message": " das suas vidas",
"description": "You've saved people from 887,362 segments (236d 15h 5.3 minutes of their lives)."
},
"statusReminder": {
"message": "Verificar status.sponsor.ajay.app para estado do servidor."
},
"setUserID": {
"message": "Definir UserID Privado"
},
@@ -563,5 +611,8 @@
},
"openOptionsPage": {
"message": "Abrir página de opções"
},
"segmentFetchFailureWarning": {
"message": "Aviso: O servidor ainda não respondeu com segmentos. Pode, na verdade, estarem segmentos já submetidos neste vídeo, mas não os tenha recebido devido a problemas com o servidor."
}
}

View File

@@ -1219,9 +1219,6 @@
"exportSegmentsAsURL": {
"message": "Distribuie ca URL"
},
"segmentFetchFailureWarning": {
"message": "Atenție: Serverul nu a răspuns încă cu segmente. Ar putea fi segmente în acest videoclip deja trimise, dar pur și simplu nu le-ai primit din cauza problemelor cu serverul."
},
"allowScrollingToEdit": {
"message": "Permite derularea la Editarea Timpilor"
}

View File

@@ -1231,7 +1231,7 @@
"message": "Поделиться ссылкой"
},
"segmentFetchFailureWarning": {
"message": "Внимание: Сервер еще не прислал существующие сегменты. В этом видео уже могут быть отправленные сегменты, но вы их ещё не получили из-за проблем с сервером."
"message": "Внимание: Сервер ещё не прислал существующие сегменты. Для этого видео уже могут быть существующие сегменты, но вы их ещё не получили из-за проблем с сервером."
},
"allowScrollingToEdit": {
"message": "Разрешить прокрутку для редактирования времени"

View File

@@ -1211,8 +1211,5 @@
"videoID": {
"message": "ID videa",
"description": "Header of the unsubmitted segments list"
},
"segmentFetchFailureWarning": {
"message": "Varovanie: Zo servera sa ešte nenahrali segmenty. V tomto videu už môžu byť vytvorené segmenty, ale vzhľadom na problémy so serverom ešte nemuseli byť nahraté."
}
}

View File

@@ -797,6 +797,10 @@
"message": "Video bütünüyle bir reklamsa simge göster",
"description": "Referring to the category pill that is now shown on videos that are entirely sponsor or entirely selfpromo"
},
"fullVideoLabelsOnThumbnails": {
"message": "Etiketleri, video küçük resimlerinde de göster",
"description": "Referring to the category pill that is shown on videos that are entirely sponsor or entirely selfpromo on recommended videos, in searches or on the homepage."
},
"previewColor": {
"message": "Gönderilmemiş Renk",
"description": "Referring to submissions that have not been sent to the server yet."
@@ -1227,7 +1231,7 @@
"message": "URL olarak paylaş"
},
"segmentFetchFailureWarning": {
"message": "Uyarı: Sunucu henüz bölümlerle yanıt vermedi. Aslında bu videoda zaten gönderilmiş bölümler olabilir, ancak sunucudaki sorunlar nedeniyle bunları almadınız."
"message": "Dikkat: Sunucu henüz kısımlarla yanıt vermedi. Aslında bu videoda zaten gönderilmiş bölümler olabilir, ancak sunucudaki sorunlar nedeniyle bunları almadınız."
},
"allowScrollingToEdit": {
"message": "Zamanları Düzenlemek İçin Kaydırmaya İzin Ver"

View File

@@ -1230,9 +1230,6 @@
"exportSegmentsAsURL": {
"message": "Поділитися посиланням"
},
"segmentFetchFailureWarning": {
"message": "Попередження: сервер ще не завантажив сегменти. Можливо, у цьому відео вже є сегменти, але ви просто не отримали їх через проблеми з сервером."
},
"allowScrollingToEdit": {
"message": "Дозволити прокручування для редагування часу"
}

View File

@@ -131,6 +131,9 @@
"closeIcon": {
"message": "關閉圖示"
},
"OpenSubmissionMenu": {
"message": "開啟提交選單"
},
"sortSegments": {
"message": "排序片段"
},

View File

@@ -187,6 +187,10 @@ div:hover > .sponsorBlockChapterBar {
margin-right: var(--skip-notice-margin);
}
.sponsorSkipObjectFirst {
margin-left: 0;
}
.sponsorSkipLogo {
height: 18px;
@@ -783,6 +787,10 @@ input::-webkit-inner-spin-button {
align-items: center;
}
.sponsorBlockCategoryPillTitle {
white-space: nowrap;
}
.categoryPillClose {
display: none;
height: 10px;

View File

@@ -79,6 +79,20 @@ chrome.runtime.onMessage.addListener(function (request, sender, callback) {
}
});
chrome.runtime.onMessageExternal.addListener((request, sender, callback) => {
if (CompileConfig.extensionCommunicationAllowList.includes(sender.id)) {
if (request.message === "requestConfig") {
callback({
userID: Config.config.userID,
allowExpirements: Config.config.allowExpirements,
showDonationLink: Config.config.showDonationLink,
showUpsells: Config.config.showUpsells,
darkMode: Config.config.darkMode,
})
}
}
});
chrome.runtime.onConnect.addListener((port) => {
if (port.name === "popup") {
chrome.tabs.query({

View File

@@ -1,6 +1,6 @@
import * as React from "react";
import Config from "../config";
import { Category, SegmentUUID, SponsorTime } from "../types";
import { ActionType, Category, SegmentUUID, SponsorTime } from "../types";
import ThumbsUpSvg from "../svg-icons/thumbs_up_svg";
import ThumbsDownSvg from "../svg-icons/thumbs_down_svg";
@@ -65,35 +65,39 @@ class ChapterVoteComponent extends React.Component<ChapterVoteProps, ChapterVote
this.tooltip.close();
this.tooltip = null;
} else {
const referenceNode = chapterNode?.parentElement?.parentElement;
if (referenceNode) {
const outerBounding = referenceNode.getBoundingClientRect();
const buttonBounding = (e.target as HTMLElement)?.parentElement?.getBoundingClientRect();
this.tooltip = new Tooltip({
referenceNode: chapterNode?.parentElement?.parentElement,
prependElement: chapterNode?.parentElement,
showLogo: false,
showGotIt: false,
bottomOffset: `${outerBounding.height + 25}px`,
leftOffset: `${buttonBounding.x - outerBounding.x}px`,
extraClass: "centeredSBTriangle",
buttons: [
{
name: chrome.i18n.getMessage("incorrectVote"),
listener: (event) => this.vote(event, 0, e.target as HTMLElement).then(() => {
this.tooltip?.close();
this.tooltip = null;
})
}, {
name: chrome.i18n.getMessage("harmfulVote"),
listener: (event) => this.vote(event, 30, e.target as HTMLElement).then(() => {
this.tooltip?.close();
this.tooltip = null;
})
}
]
});
if (this.state.segment?.actionType === ActionType.Chapter) {
const referenceNode = chapterNode?.parentElement?.parentElement;
if (referenceNode) {
const outerBounding = referenceNode.getBoundingClientRect();
const buttonBounding = (e.target as HTMLElement)?.parentElement?.getBoundingClientRect();
this.tooltip = new Tooltip({
referenceNode: chapterNode?.parentElement?.parentElement,
prependElement: chapterNode?.parentElement,
showLogo: false,
showGotIt: false,
bottomOffset: `${outerBounding.height + 25}px`,
leftOffset: `${buttonBounding.x - outerBounding.x}px`,
extraClass: "centeredSBTriangle",
buttons: [
{
name: chrome.i18n.getMessage("incorrectVote"),
listener: (event) => this.vote(event, 0, e.target as HTMLElement).then(() => {
this.tooltip?.close();
this.tooltip = null;
})
}, {
name: chrome.i18n.getMessage("harmfulVote"),
listener: (event) => this.vote(event, 30, e.target as HTMLElement).then(() => {
this.tooltip?.close();
this.tooltip = null;
})
}
]
});
}
} else {
this.vote(e, 0, e.target as HTMLElement)
}
}
}}>

View File

@@ -195,7 +195,7 @@ class NoticeComponent extends React.Component<NoticeProps, NoticeState> {
id={"skipNoticeTimerText" + this.idSuffix}
key="skipNoticeTimerText"
className={this.state.countdownMode !== CountdownMode.Timer ? "hidden" : ""} >
{this.state.countdownTime + "s"}
{chrome.i18n.getMessage("NoticeTimeAfterSkip").replace("{seconds}", this.state.countdownTime.toString())}
</span>
),(
<img

View File

@@ -7,13 +7,13 @@ import NoticeTextSelectionComponent from "./NoticeTextSectionComponent";
import Utils from "../utils";
const utils = new Utils();
import { getSkippingText } from "../utils/categoryUtils";
import { keybindToString } from "../utils/configUtils";
import ThumbsUpSvg from "../svg-icons/thumbs_up_svg";
import ThumbsDownSvg from "../svg-icons/thumbs_down_svg";
import PencilSvg from "../svg-icons/pencil_svg";
import { downvoteButtonColor, SkipNoticeAction } from "../utils/noticeUtils";
import { generateUserID } from "@ajayyy/maze-utils/lib/setup";
import { keybindToString } from "@ajayyy/maze-utils/lib/config";
enum SkipButtonState {
Undo, // Unskip

View File

@@ -1,9 +1,8 @@
import * as React from "react";
import { createRoot, Root } from 'react-dom/client';
import Config from "../../config";
import { Keybind } from "../../types";
import KeybindDialogComponent from "./KeybindDialogComponent";
import { keybindEquals, keybindToString, formatKey } from "../../utils/configUtils";
import { formatKey, Keybind, keybindEquals, keybindToString } from "@ajayyy/maze-utils/lib/config";
export interface KeybindProps {
option: string;

View File

@@ -1,8 +1,7 @@
import * as React from "react";
import { ChangeEvent } from "react";
import Config from "../../config";
import { Keybind } from "../../types";
import { keybindEquals, formatKey } from "../../utils/configUtils";
import { Keybind, formatKey, keybindEquals } from "@ajayyy/maze-utils/lib/config";
export interface KeybindDialogProps {
option: string;

View File

@@ -1,8 +1,7 @@
import * as CompileConfig from "../config.json";
import * as invidiousList from "../ci/invidiouslist.json";
import { Category, CategorySelection, CategorySkipOption, NoticeVisbilityMode, PreviewBarOption, SponsorTime, Keybind, VideoID, SponsorHideType } from "./types";
import { keybindEquals } from "./utils/configUtils";
import { ProtoConfig } from "@ajayyy/maze-utils/lib/config";
import { Category, CategorySelection, CategorySkipOption, NoticeVisbilityMode, PreviewBarOption, SponsorTime, VideoID, SponsorHideType } from "./types";
import { Keybind, ProtoConfig, keybindEquals } from "@ajayyy/maze-utils/lib/config";
import { HashedValue } from "@ajayyy/maze-utils/lib/hash";
export interface Permission {

View File

@@ -6,7 +6,6 @@ import {
ChannelIDInfo,
ChannelIDStatus,
ContentContainer,
Keybind,
ScheduledTime,
SegmentUUID,
SkipToTimeParams,
@@ -26,7 +25,6 @@ import { Message, MessageResponse, VoteResponse } from "./messageTypes";
import { SkipButtonControlBar } from "./js-components/skipButtonControlBar";
import { getStartTimeFromUrl } from "./utils/urlParser";
import { getControls, getExistingChapters, getHashParams, isVisible } from "./utils/pageUtils";
import { isSafari, keybindEquals } from "./utils/configUtils";
import { CategoryPill } from "./render/CategoryPill";
import { AnimationUtils } from "./utils/animationUtils";
import { GenericUtils } from "./utils/genericUtils";
@@ -34,10 +32,10 @@ import { logDebug } from "./utils/logger";
import { importTimes } from "./utils/exporter";
import { ChapterVote } from "./render/ChapterVote";
import { openWarningDialog } from "./utils/warnings";
import { waitFor } from "@ajayyy/maze-utils";
import { isFirefoxOrSafari, waitFor } from "@ajayyy/maze-utils";
import { getFormattedTime } from "@ajayyy/maze-utils/lib/formating";
import { setupVideoMutationListener, getChannelIDInfo, getVideo, refreshVideoAttachments, getIsAdPlaying, getIsLivePremiere, setIsAdPlaying, checkVideoIDChange, getVideoID, getYouTubeVideoID, setupVideoModule, checkIfNewVideoID, isOnInvidious, isOnMobileYouTube } from "@ajayyy/maze-utils/lib/video";
import { StorageChangesObject } from "@ajayyy/maze-utils/lib/config";
import { getChannelIDInfo, getVideo, getIsAdPlaying, getIsLivePremiere, setIsAdPlaying, checkVideoIDChange, getVideoID, getYouTubeVideoID, setupVideoModule, checkIfNewVideoID, isOnInvidious, isOnMobileYouTube } from "@ajayyy/maze-utils/lib/video";
import { Keybind, StorageChangesObject, isSafari, keybindEquals } from "@ajayyy/maze-utils/lib/config";
import { findValidElement } from "@ajayyy/maze-utils/lib/dom"
import { getHash, HashedValue } from "@ajayyy/maze-utils/lib/hash";
import { generateUserID } from "@ajayyy/maze-utils/lib/setup";
@@ -661,6 +659,11 @@ async function startSponsorSchedule(includeIntersectingSegments = false, current
forcedSkipTime = forceVideoTime + 0.001;
}
// Don't pretend to be earlier than we are, could result in loops
if (forcedSkipTime !== null && forceVideoTime > forcedSkipTime) {
forcedSkipTime = null;
}
startSponsorSchedule(forcedIncludeIntersectingSegments, forcedSkipTime, forcedIncludeNonIntersectingSegments);
};
@@ -670,7 +673,7 @@ async function startSponsorSchedule(includeIntersectingSegments = false, current
let delayTime = timeUntilSponsor * 1000 * (1 / getVideo().playbackRate);
if (delayTime < 300) {
let forceStartIntervalTime: number | null = null;
if (utils.isFirefox() && !isSafari() && delayTime > 100) {
if (isFirefoxOrSafari() && !isSafari() && delayTime > 100) {
forceStartIntervalTime = await waitForNextTimeChange();
}
@@ -687,7 +690,7 @@ async function startSponsorSchedule(includeIntersectingSegments = false, current
currentSkipInterval = setInterval(() => {
// Estimate delay, but only take the current time right after a change
// Current time remains the same for many "frames" on Firefox
if (utils.isFirefox() && !lastKnownVideoTime.fromPause && startWaitingForReportedTimeToChange
if (isFirefoxOrSafari() && !lastKnownVideoTime.fromPause && startWaitingForReportedTimeToChange
&& reportedVideoTimeAtStart !== getVideo().currentTime) {
startWaitingForReportedTimeToChange = false;
const delay = getVirtualTime() - getVideo().currentTime;
@@ -697,7 +700,7 @@ async function startSponsorSchedule(includeIntersectingSegments = false, current
const intervalDuration = performance.now() - startIntervalTime;
if (intervalDuration + skipBuffer * 1000 >= delayTime || getVideo().currentTime >= skipTime[0]) {
clearInterval(currentSkipInterval);
if (!utils.isFirefox() && !getVideo().muted) {
if (!isFirefoxOrSafari() && !getVideo().muted) {
// Workaround for more accurate skipping on Chromium
getVideo().muted = true;
getVideo().muted = false;
@@ -709,7 +712,7 @@ async function startSponsorSchedule(includeIntersectingSegments = false, current
} else {
logDebug(`Starting timeout to skip ${getVideo().currentTime} to skip at ${skipTime[0]}`);
const offset = (utils.isFirefox() && !isSafari ? 300 : 150);
const offset = (isFirefoxOrSafari() && !isSafari() ? 300 : 150);
// Schedule for right before to be more precise than normal timeout
currentSkipSchedule = setTimeout(skippingFunction, Math.max(0, delayTime - offset));
}
@@ -863,7 +866,12 @@ function setupVideoListeners() {
updateVirtualTime();
clearWaitingTime();
startSponsorSchedule();
// Sometimes looped videos loop back to almost zero, but not quite
if (getVideo().loop && getVideo().currentTime < 0.2) {
startSponsorSchedule(false, 0);
} else {
startSponsorSchedule();
}
} else {
updateActiveSegment(getVideo().currentTime);
@@ -919,7 +927,7 @@ function updateVirtualTime() {
lastKnownVideoTime.preciseTime = performance.now();
// If on Firefox, wait for the second time change (time remains fixed for many "frames" for privacy reasons)
if (utils.isFirefox()) {
if (isFirefoxOrSafari()) {
let count = 0;
let rawCount = 0;
let lastTime = lastKnownVideoTime.videoTime;
@@ -988,7 +996,6 @@ function setupCategoryPill() {
async function sponsorsLookup(keepOldSubmissions = true) {
if (lookupWaiting) return;
if (!getVideo() || !isVisible(getVideo())) refreshVideoAttachments();
//there is still no video here
if (!getVideo()) {
lookupWaiting = true;
@@ -999,8 +1006,6 @@ async function sponsorsLookup(keepOldSubmissions = true) {
return;
}
setupVideoMutationListener();
const categories: string[] = Config.config.categorySelections.map((category) => category.name);
const extraRequestData: Record<string, unknown> = {};
@@ -1019,7 +1024,7 @@ async function sponsorsLookup(keepOldSubmissions = true) {
lastResponseStatus = response?.status;
if (response?.ok) {
const recievedSegments: SponsorTime[] = JSON.parse(response.responseText)
const receivedSegments: SponsorTime[] = JSON.parse(response.responseText)
?.filter((video) => video.videoID === getVideoID())
?.map((video) => video.segments)?.[0]
?.map((segment) => ({
@@ -1027,7 +1032,7 @@ async function sponsorsLookup(keepOldSubmissions = true) {
source: SponsorSourceType.Server
}))
?.sort((a, b) => a.segment[0] - b.segment[0]);
if (recievedSegments && recievedSegments.length) {
if (receivedSegments && receivedSegments.length) {
sponsorDataFound = true;
// Check if any old submissions should be kept
@@ -1035,13 +1040,13 @@ async function sponsorsLookup(keepOldSubmissions = true) {
for (let i = 0; i < sponsorTimes.length; i++) {
if (sponsorTimes[i].source === SponsorSourceType.Local) {
// This is a user submission, keep it
recievedSegments.push(sponsorTimes[i]);
receivedSegments.push(sponsorTimes[i]);
}
}
}
const oldSegments = sponsorTimes || [];
sponsorTimes = recievedSegments;
sponsorTimes = receivedSegments;
existingChaptersImported = false;
// Hide all submissions smaller than the minimum duration
@@ -1188,7 +1193,7 @@ function retryFetch(errorCode: number): void {
*/
function startSkipScheduleCheckingForStartSponsors() {
// switchingVideos is ignored in Safari due to event fire order. See #1142
if ((!switchingVideos || isSafari) && sponsorTimes) {
if ((!switchingVideos || isSafari()) && sponsorTimes) {
// See if there are any starting sponsors
let startingSegmentTime = getStartTimeFromUrl(document.URL) || -1;
let found = false;
@@ -1333,9 +1338,9 @@ function videoElementChange(newVideo: boolean): void {
if (previewBar && !utils.findReferenceNode()?.contains(previewBar.container)) {
previewBar.remove();
previewBar = null;
createPreviewBar();
}
createPreviewBar();
}
/**
@@ -2165,10 +2170,10 @@ async function sendSubmitMessage() {
const newSegments = sponsorTimesSubmitting;
try {
const recievedNewSegments = JSON.parse(response.responseText);
if (recievedNewSegments?.length === newSegments.length) {
for (let i = 0; i < recievedNewSegments.length; i++) {
newSegments[i].UUID = recievedNewSegments[i].UUID;
const receivedNewSegments = JSON.parse(response.responseText);
if (receivedNewSegments?.length === newSegments.length) {
for (let i = 0; i < receivedNewSegments.length; i++) {
newSegments[i].UUID = receivedNewSegments[i].UUID;
newSegments[i].source = SponsorSourceType.Server;
}
}
@@ -2343,7 +2348,7 @@ function hotkeyListener(e: KeyboardEvent): void {
* Adds the CSS to the page if needed. Required on optional sites with Chrome.
*/
function addCSS() {
if (!utils.isFirefox() && Config.config.invidiousInstances.includes(new URL(document.URL).host)) {
if (!isFirefoxOrSafari() && Config.config.invidiousInstances.includes(new URL(document.URL).host)) {
window.addEventListener("DOMContentLoaded", () => {
const head = document.getElementsByTagName("head")[0];
@@ -2373,14 +2378,15 @@ function updateAdFlag(): void {
}
function showTimeWithoutSkips(skippedDuration: number): void {
if (isOnInvidious()) return;
if (isNaN(skippedDuration) || skippedDuration < 0) {
skippedDuration = 0;
}
// YouTube player time display
const displayClass = isOnMobileYouTube() ? "ytm-time-display" : "ytp-time-display.notranslate"
const displayClass =
isOnInvidious() ? "vjs-duration" :
isOnMobileYouTube() ? "ytm-time-display" :
"ytp-time-display.notranslate";
const display = document.querySelector(`.${displayClass}`);
if (!display) return;
@@ -2391,7 +2397,7 @@ function showTimeWithoutSkips(skippedDuration: number): void {
if (duration === null) {
duration = document.createElement('span');
duration.id = durationID;
duration.classList.add(displayClass);
if (!isOnInvidious()) duration.classList.add(displayClass);
display.appendChild(duration);
}

View File

@@ -1,8 +1,8 @@
import Config from "../config";
import { SponsorTime } from "../types";
import { getSkippingText } from "../utils/categoryUtils";
import { keybindToString } from "../utils/configUtils";
import { AnimationUtils } from "../utils/animationUtils";
import { keybindToString } from "@ajayyy/maze-utils/lib/config";
export interface SkipButtonControlBarProps {
skip: (segment: SponsorTime) => void;

View File

@@ -16,6 +16,7 @@ import { showDonationLink } from "./utils/configUtils";
import { localizeHtmlPage } from "./utils/pageUtils";
import { StorageChangesObject } from "@ajayyy/maze-utils/lib/config";
import { getHash } from "@ajayyy/maze-utils/lib/hash";
import { isFirefoxOrSafari } from "@ajayyy/maze-utils";
const utils = new Utils();
let embed = false;
@@ -186,7 +187,7 @@ async function init() {
}
// Permission needed on Firefox
if (utils.isFirefox()) {
if (isFirefoxOrSafari()) {
const permissionSuccess = await new Promise((resolve) => {
chrome.permissions.request({
origins: [textChangeInput.value + "/"],

View File

@@ -67,7 +67,7 @@ export class Tooltip {
</img>
: null}
{this.text ?
<span className="sponsorSkipObject">
<span className={`sponsorSkipObject${!props.showLogo ? ` sponsorSkipObjectFirst` : ``}`}>
{this.text + (props.link ? ". " : "")}
{props.link ?
<a style={{textDecoration: "underline"}}

View File

@@ -31,6 +31,7 @@ export interface VideoDurationResponse {
}
export enum CategorySkipOption {
Disabled = -1,
ShowOverlay,
ManualSkip,
AutoSkip
@@ -221,14 +222,6 @@ export enum NoticeVisbilityMode {
FadedForAll = 4
}
export type Keybind = {
key: string;
code?: string;
ctrl?: boolean;
alt?: boolean;
shift?: boolean;
}
export interface ButtonListener {
name: string;
listener: (e?: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void;

View File

@@ -1,12 +1,12 @@
import Config, { VideoDownvotes } from "./config";
import { CategorySelection, SponsorTime, BackgroundScriptContainer, Registration, VideoID, SponsorHideType } from "./types";
import { CategorySelection, SponsorTime, BackgroundScriptContainer, Registration, VideoID, SponsorHideType, CategorySkipOption } from "./types";
import { getHash, HashedValue } from "@ajayyy/maze-utils/lib/hash";
import * as CompileConfig from "../config.json";
import { waitFor } from "@ajayyy/maze-utils";
import { isSafari } from "./utils/configUtils";
import { isFirefoxOrSafari, waitFor } from "@ajayyy/maze-utils";
import { findValidElementFromSelector } from "@ajayyy/maze-utils/lib/dom";
import { FetchResponse, sendRequestToCustomServer } from "@ajayyy/maze-utils/lib/background-request-proxy"
import { isSafari } from "@ajayyy/maze-utils/lib/config";
export default class Utils {
@@ -49,7 +49,7 @@ export default class Utils {
setupExtraSitePermissions(callback: (granted: boolean) => void): void {
let permissions = ["webNavigation"];
if (!isSafari()) permissions.push("declarativeContent");
if (this.isFirefox() && !isSafari()) permissions = [];
if (isFirefoxOrSafari() && !isSafari()) permissions = [];
chrome.permissions.request({
origins: this.getPermissionRegex(),
@@ -113,7 +113,7 @@ export default class Utils {
});
}
if (!this.isFirefox() && chrome.declarativeContent) {
if (!isFirefoxOrSafari() && chrome.declarativeContent) {
// Only if we have permission
chrome.declarativeContent.onPageChanged.removeRules(["invidious"]);
}
@@ -143,7 +143,7 @@ export default class Utils {
containsInvidiousPermission(): Promise<boolean> {
return new Promise((resolve) => {
let permissions = ["declarativeContent"];
if (this.isFirefox()) permissions = [];
if (isFirefoxOrSafari()) permissions = [];
chrome.permissions.contains({
origins: this.getPermissionRegex(),
@@ -225,7 +225,7 @@ export default class Utils {
return selection;
}
}
return { name: "None", option: 0} as CategorySelection;
return { name: category, option: CategorySkipOption.Disabled} as CategorySelection;
}
/**
@@ -293,6 +293,7 @@ export default class Utils {
const selectors = [
"#player-container-id", // Mobile YouTube
"#movie_player",
".html5-video-player", // May 2023 Card-Based YouTube Layout
"#c4-player", // Channel Trailer
"#player-container", // Preview on hover
"#main-panel.ytmusic-player-page", // YouTube music
@@ -329,13 +330,6 @@ export default class Utils {
return Boolean(num.match(/^[0-9a-f]+$/i));
}
/**
* Is this Firefox (web-extensions)
*/
isFirefox(): boolean {
return typeof(browser) !== "undefined";
}
async addHiddenSegment(videoID: VideoID, segmentUUID: string, hidden: SponsorHideType) {
if (chrome.extension.inIncognitoContext || !Config.config.trackDownvotes) return;

View File

@@ -1,48 +1,5 @@
import Config from "../config";
import { Keybind } from "../types";
export function showDonationLink(): boolean {
return navigator.vendor !== "Apple Computer, Inc." && Config.config.showDonationLink;
}
export function isSafari(): boolean {
return typeof(navigator) !== "undefined" && navigator.vendor === "Apple Computer, Inc.";
}
export function keybindEquals(first: Keybind, second: Keybind): boolean {
if (first == null || second == null ||
Boolean(first.alt) != Boolean(second.alt) || Boolean(first.ctrl) != Boolean(second.ctrl) || Boolean(first.shift) != Boolean(second.shift) ||
first.key == null && first.code == null || second.key == null && second.code == null)
return false;
if (first.code != null && second.code != null)
return first.code === second.code;
if (first.key != null && second.key != null)
return first.key.toUpperCase() === second.key.toUpperCase();
return false;
}
export function formatKey(key: string): string {
if (key == null)
return "";
else if (key == " ")
return "Space";
else if (key.length == 1)
return key.toUpperCase();
else
return key;
}
export function keybindToString(keybind: Keybind): string {
if (keybind == null || keybind.key == null)
return "";
let ret = "";
if (keybind.ctrl)
ret += "Ctrl+";
if (keybind.alt)
ret += "Alt+";
if (keybind.shift)
ret += "Shift+";
return ret += formatKey(keybind.key);
}

View File

@@ -1,4 +1,4 @@
import { Category, VideoID } from "../types";
import { Category, CategorySkipOption, VideoID } from "../types";
import { getHash } from "@ajayyy/maze-utils/lib/hash";
import Utils from "../utils";
import { logWarn } from "./logger";
@@ -58,7 +58,12 @@ export async function getVideoLabel(videoID: VideoID): Promise<Category | null>
const result = await getLabelHashBlock(prefix);
if (result) {
return result.videos[videoID] ?? null;
const category = result.videos[videoID];
if (category && utils.getCategorySelection(category).option !== CategorySkipOption.Disabled) {
return category;
} else {
return null;
}
}
return null;