Compare commits

...

10 Commits
4.6 ... 4.6.1

Author SHA1 Message Date
Ajay Ramachandran
cc7d7c0a0c New Crowdin updates (#1368) 2022-06-30 19:54:08 -04:00
Ajay Ramachandran
61b39a99db bump version 2022-06-30 19:53:26 -04:00
Ajay Ramachandran
98f776fa3a Merge pull request #1387 from mchangrh/await-embed
fix embeds not being detected correctly
2022-06-30 17:39:34 -04:00
Michael C
75f426f456 fix embeds not being detected correctly
- add awaiter for key element
- refresh ID with segments if videoID is invalid
2022-06-30 16:38:11 -04:00
Ajay Ramachandran
67b510e628 Merge pull request #1370 from mchangrh/popup-connection-error
Show connectionError string if status is not 404
2022-06-24 17:22:33 -04:00
Michael C
7cc0847db1 store response status 200 2022-06-24 10:49:57 -04:00
Michael C
b92132bf47 implement #1364
show connectionError string if status is not 404
2022-06-24 01:21:19 -04:00
Ajay
6b4da25847 Create source maps in dev 2022-06-22 13:21:15 -04:00
Ajay
529db4d6ca Merge branch 'master' of https://github.com/ajayyy/SponsorBlock 2022-06-22 13:18:49 -04:00
Ajay
d132342ffe Fix popup being out of date and auto closing
Fixes #1359
2022-06-22 13:18:48 -04:00
11 changed files with 198 additions and 43 deletions

View File

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

View File

@@ -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": "التعديل"
},

View File

@@ -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"
},

View File

@@ -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\""

View File

@@ -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"
}
}

View File

@@ -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;
@@ -100,7 +100,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 +120,9 @@ let submissionNotice: SubmissionNotice = null;
// If there is an advert playing (or about to be played), this is true
let isAdPlaying = false;
// last response status
let lastResponseStatus: number;
// Contains all of the functions and variables needed by the skip notice
const skipNoticeContentContainer: ContentContainer = () => ({
vote,
@@ -163,6 +169,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 +209,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
}));
@@ -828,7 +839,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,6 +847,9 @@ 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)
@@ -904,8 +917,10 @@ async function sponsorsLookup(keepOldSubmissions = true) {
//otherwise the listener can handle it
updatePreviewBar();
}
} else if (response?.status === 404) {
retryFetch();
} else {
if (lastResponseStatus === 404) {
retryFetch();
}
}
if (Config.config.isVip) {
@@ -1519,9 +1534,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 +1757,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;

View File

@@ -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 {

View File

@@ -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();

18
tsconfig-production.json Normal file
View 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"
]
}
}

View File

@@ -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"
]

View File

@@ -53,7 +53,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"
}
}
]