From 340127a7f305992d7179e175bb8ca362490cb4b9 Mon Sep 17 00:00:00 2001 From: Ajay Date: Wed, 16 Mar 2022 12:30:35 -0400 Subject: [PATCH 01/23] Switch font back to arial --- public/popup.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/public/popup.css b/public/popup.css index 641d19c6..43320ce1 100644 --- a/public/popup.css +++ b/public/popup.css @@ -82,6 +82,10 @@ *
wrapper around each segment */ +.votingButtons { + font-family: Arial, Helvetica, sans-serif; +} + .votingButtons[open] { padding-bottom: 5px; } From 21d4f0487c1558d5d92b8719fb9db54b6db72575 Mon Sep 17 00:00:00 2001 From: Ajay Date: Wed, 16 Mar 2022 13:30:20 -0400 Subject: [PATCH 02/23] Fix skip notice behind controls on mobile youtube Fix #1229 --- src/utils.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/utils.ts b/src/utils.ts index 7ee3be4c..d89e1a3d 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -372,13 +372,15 @@ export default class Utils { findReferenceNode(): HTMLElement { const selectors = [ + "#player-container-id", // Mobile YouTube "#movie_player", "#c4-player", // Channel Trailer "#player-container", // Preview on hover "#main-panel.ytmusic-player-page", // YouTube music "#player-container .video-js", // Invidious ".main-video-section > .video-container" // Cloudtube - ] + ]; + let referenceNode = findValidElementFromSelector(selectors) if (referenceNode == null) { //for embeds From 1acda5fe0a21934c7a97fdf5cbda6a8d958dbc41 Mon Sep 17 00:00:00 2001 From: Ajay Date: Wed, 16 Mar 2022 16:17:44 -0400 Subject: [PATCH 03/23] Improve precision on chromium using predicted virtual time --- src/content.ts | 55 ++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 47 insertions(+), 8 deletions(-) diff --git a/src/content.ts b/src/content.ts index d826caea..776441bd 100644 --- a/src/content.ts +++ b/src/content.ts @@ -40,6 +40,11 @@ let videoInfo: VideoInfo = null; let channelIDInfo: ChannelIDInfo; // Locked Categories in this tab, like: ["sponsor","intro","outro"] let lockedCategories: Category[] = []; +// Used to calculate a more precise "virtual" video time +let lastKnownVideoTime: { videoTime: number, preciseTime: number } = { + videoTime: null, + preciseTime: null +}; // Skips are scheduled to ensure precision. // Skips are rescheduled every seeking event. @@ -450,7 +455,15 @@ function startSponsorSchedule(includeIntersectingSegments = false, currentTime?: } if (!video || video.paused) return; - if (currentTime === undefined || currentTime === null) currentTime = video.currentTime; + if (currentTime === undefined || currentTime === null) { + const virtualTime = lastKnownVideoTime.videoTime ? + (performance.now() - lastKnownVideoTime.preciseTime) / 1000 + lastKnownVideoTime.videoTime : null; + if (virtualTime && Math.abs(virtualTime - video.currentTime) < 0.6){ + currentTime = virtualTime; + } else { + currentTime = video.currentTime; + } + } if (videoMuted && !inMuteSegment(currentTime)) { video.muted = false; @@ -526,20 +539,26 @@ function startSponsorSchedule(includeIntersectingSegments = false, currentTime?: skippingFunction(); } else { const delayTime = timeUntilSponsor * 1000 * (1 / video.playbackRate); - if (delayTime < 300 && utils.isFirefox() && !isSafari()) { + if (delayTime < 300 && !isSafari()) { // For Firefox, use interval instead of timeout near the end to combat imprecise video time const startIntervalTime = performance.now(); - const startVideoTime = video.currentTime; + const startVideoTime = Math.max(currentTime, video.currentTime); currentSkipInterval = setInterval(() => { const intervalDuration = performance.now() - startIntervalTime; if (intervalDuration >= delayTime || video.currentTime >= skipTime[0]) { clearInterval(currentSkipInterval); - skippingFunction(Math.max(video.currentTime, startVideoTime + intervalDuration / 1000)); + if (!utils.isFirefox() && !video.muted) { + // Workaround for more accurate skipping on Chromium + video.muted = true; + video.muted = false; + } + + skippingFunction(Math.max(video.currentTime, startVideoTime + video.playbackRate * intervalDuration / 1000)); } - }, 5); + }, 1); } else { // Schedule for right before to be more precise than normal timeout - currentSkipSchedule = setTimeout(skippingFunction, Math.max(0, delayTime - 30)); + currentSkipSchedule = setTimeout(skippingFunction, Math.max(0, delayTime - 100)); } } } @@ -621,6 +640,8 @@ function setupVideoListeners() { if (!firstEvent && video.currentTime === 0) return; firstEvent = false; + updateVirtualTime(); + if (switchingVideos) { switchingVideos = false; // If already segments loaded before video, retry to skip starting segments @@ -641,6 +662,8 @@ function setupVideoListeners() { }); video.addEventListener('playing', () => { + updateVirtualTime(); + // Make sure it doesn't get double called with the play event if (Math.abs(lastCheckVideoTime - video.currentTime) > 0.3 || (lastCheckVideoTime !== video.currentTime && Date.now() - lastCheckTime > 2000)) { @@ -655,6 +678,8 @@ function setupVideoListeners() { // Reset lastCheckVideoTime lastCheckTime = Date.now(); lastCheckVideoTime = video.currentTime; + + updateVirtualTime(); startSponsorSchedule(); } @@ -662,18 +687,32 @@ function setupVideoListeners() { video.addEventListener('ratechange', () => startSponsorSchedule()); // Used by videospeed extension (https://github.com/igrigorik/videospeed/pull/740) video.addEventListener('videoSpeed_ratechange', () => startSponsorSchedule()); - video.addEventListener('pause', () => { + const paused = () => { // Reset lastCheckVideoTime lastCheckVideoTime = -1; lastCheckTime = 0; + + lastKnownVideoTime = { + videoTime: null, + preciseTime: null + } cancelSponsorSchedule(); - }); + }; + video.addEventListener('pause', paused); + video.addEventListener('waiting', paused); startSponsorSchedule(); } } +function updateVirtualTime() { + lastKnownVideoTime = { + videoTime: video.currentTime, + preciseTime: performance.now() + }; +} + function setupSkipButtonControlBar() { if (!skipButtonControlBar) { skipButtonControlBar = new SkipButtonControlBar({ From 5f4c4332bedf39d4d00513aaef93d0e83c14cb7e Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Wed, 16 Mar 2022 22:14:14 -0400 Subject: [PATCH 04/23] bump version --- manifest/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manifest/manifest.json b/manifest/manifest.json index a1357938..4eaae99d 100644 --- a/manifest/manifest.json +++ b/manifest/manifest.json @@ -1,7 +1,7 @@ { "name": "__MSG_fullName__", "short_name": "SponsorBlock", - "version": "4.1.6", + "version": "4.2", "default_locale": "en", "description": "__MSG_Description__", "homepage_url": "https://sponsor.ajay.app", From d9f1ee9bb8fabe011bccd685cf49342b3ca2b7f8 Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Wed, 16 Mar 2022 22:14:42 -0400 Subject: [PATCH 05/23] New Crowdin updates (#1225) --- public/_locales/cs/messages.json | 4 +- public/_locales/it/messages.json | 2 +- public/_locales/pt_PT/messages.json | 64 +++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+), 3 deletions(-) diff --git a/public/_locales/cs/messages.json b/public/_locales/cs/messages.json index e616cf6d..bb65ddc4 100644 --- a/public/_locales/cs/messages.json +++ b/public/_locales/cs/messages.json @@ -586,13 +586,13 @@ "message": "Titulky nebo když se objeví konečné karty YouTube. Není pro závěry s informacemi." }, "category_preview": { - "message": "Náhled/shrnutí" + "message": "Náhled / shrnutí" }, "category_preview_description": { "message": "Rychlé shrnutí předchozích epizod nebo náhled toho, co se objeví v aktuálním videu. Myšleno pro upravené sloučené klipy, ne pro mluvená shrnutí." }, "category_filler": { - "message": "Výplň/vtipy" + "message": "Výplň / vtipy" }, "category_filler_description": { "message": "Výplňové scény přidané jen jako přídavek nebo humor, které nejsou vyžadovány pro pochopení hlavního obsahu videa. Toto by nemělo zahrnovat segmenty poskytující kontext nebo podrobnosti na pozadí." diff --git a/public/_locales/it/messages.json b/public/_locales/it/messages.json index 8fa21d58..0e253383 100644 --- a/public/_locales/it/messages.json +++ b/public/_locales/it/messages.json @@ -562,7 +562,7 @@ "description": "Short description for this category" }, "category_interaction": { - "message": "Promemoria di Interazione (Sottoscrizione)" + "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." diff --git a/public/_locales/pt_PT/messages.json b/public/_locales/pt_PT/messages.json index 012946e8..ac1d4db3 100644 --- a/public/_locales/pt_PT/messages.json +++ b/public/_locales/pt_PT/messages.json @@ -118,6 +118,34 @@ "submitCheck": { "message": "Tem a certeza que pretende submeter?" }, + "whitelistChannel": { + "message": "Meter canal na Lista Branca" + }, + "removeFromWhitelist": { + "message": "Remover canal da Lista Branca" + }, + "voteOnTime": { + "message": "Votar em um segmento" + }, + "Submissions": { + "message": "Submissões" + }, + "savedPeopleFrom": { + "message": "Salvaste pessoas de " + }, + "viewLeaderboard": { + "message": "Tabela de Classificação" + }, + "recordTimesDescription": { + "message": "Enviar" + }, + "submissionEditHint": { + "message": "A edição da seção aparecerá depois que você clicar em enviar", + "description": "Appears in the popup to inform them that editing has been moved to the video player." + }, + "popupHint": { + "message": "Dica: Você pode configurar atalhos de teclado para enviar nas opções" + }, "clearTimesButton": { "message": "Limpar Intervalos" }, @@ -127,9 +155,15 @@ "publicStats": { "message": "Isto é usado na página pública de estatísticas que mostra o quanto já contríbuíu. Veje-a" }, + "Username": { + "message": "Nome de Utilizador" + }, "setUsername": { "message": "Criar nomde de utilizador" }, + "copyPublicID": { + "message": "Copiar UserID Publico" + }, "discordAdvert": { "message": "Junte-se ao discord oficial para sugerir dicas e sugestões!" }, @@ -148,18 +182,48 @@ "hideButtonsDescription": { "message": "Isto esconde os botões que aparecem no player do Youtube para submeter patrocínios. Entendemos que possa ser\n incómodo a algumas pessoas. Em vez de usar esses botões pode usar os do popup. Para esconder a mensagem que aparece, \n ususe o botão na mesma que diz \"Don't show this again\". Pode sempre reactivar estas definições novamente." }, + "showSkipButton": { + "message": "Mantenha o Botão Saltar para Destaque no Player" + }, "showInfoButton": { "message": "Mostrar botão de Informações no player do Youtube" }, "hideInfoButton": { "message": "Esconder botão de Informações no player do Youtube" }, + "autoHideInfoButton": { + "message": "Ocultar automaticamente o Botão de Informação" + }, "hideDeleteButton": { "message": "Esconder botão de Apagar no player do Youtube" }, "showDeleteButton": { "message": "Mostrar botão de Apagar no player do Youtube" }, + "enableViewTracking": { + "message": "Ativar Rastreamento de Contagem de Saltos" + }, + "whatViewTracking": { + "message": "Esse recurso rastreia quais segmentos você pulou para permitir que os usuários saibam o quanto seu envio ajudou outras pessoas e é usado como métrica junto com votos positivos para garantir que o spam não entre no banco de dados. A extensão envia uma mensagem ao servidor cada vez que você pular um segmento. Espero que a maioria das pessoas não altere essa configuração para que os números de visualização sejam precisos. :)" + }, + "enableViewTrackingInPrivate": { + "message": "Ativar o Rastreamento de Contagem de Saltos nas Guias Privadas/Anônimas" + }, + "enableTrackDownvotes": { + "message": "Guardar segmentos de votos negativos" + }, + "whatTrackDownvotes": { + "message": "Quaisquer segmentos que você votar negativo permanecerão ocultos mesmo após a atualização" + }, + "trackDownvotesWarning": { + "message": "Aviso: Ao desabilitar isso excluirá todos os votos negativos armazenados anteriormente" + }, + "enableQueryByHashPrefix": { + "message": "Consulta por Prefixo de Hash" + }, + "whatQueryByHashPrefix": { + "message": "Em vez de solicitar segmentos do servidor usando o ID do Vídeo, são enviados os primeiros 4 caracteres do hash do ID do Vídeo. Este servidor enviará de volta dados para todos os vídeos com hashes semelhantes." + }, "showNotice": { "message": "Mostrar notificação outra vez" }, From d4544a7c473d6592465d1abe690c2da1a4150d3f Mon Sep 17 00:00:00 2001 From: Ajay Date: Thu, 17 Mar 2022 00:27:36 -0400 Subject: [PATCH 06/23] Fixes for safari --- public/content.css | 4 ++++ src/content.ts | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/public/content.css b/public/content.css index 065cb759..790202d2 100644 --- a/public/content.css +++ b/public/content.css @@ -352,6 +352,10 @@ filter: brightness(80%); } +.segmentSummary { + outline: none; +} + .submitButton { background-color:#ec1c1c; -moz-border-radius:28px; diff --git a/src/content.ts b/src/content.ts index 776441bd..e133abe7 100644 --- a/src/content.ts +++ b/src/content.ts @@ -458,7 +458,7 @@ function startSponsorSchedule(includeIntersectingSegments = false, currentTime?: if (currentTime === undefined || currentTime === null) { const virtualTime = lastKnownVideoTime.videoTime ? (performance.now() - lastKnownVideoTime.preciseTime) / 1000 + lastKnownVideoTime.videoTime : null; - if (virtualTime && Math.abs(virtualTime - video.currentTime) < 0.6){ + if (!isSafari() && virtualTime && Math.abs(virtualTime - video.currentTime) < 0.6){ currentTime = virtualTime; } else { currentTime = video.currentTime; @@ -539,7 +539,7 @@ function startSponsorSchedule(includeIntersectingSegments = false, currentTime?: skippingFunction(); } else { const delayTime = timeUntilSponsor * 1000 * (1 / video.playbackRate); - if (delayTime < 300 && !isSafari()) { + if (delayTime < 300) { // For Firefox, use interval instead of timeout near the end to combat imprecise video time const startIntervalTime = performance.now(); const startVideoTime = Math.max(currentTime, video.currentTime); From 36f0fccd9c49dc8ac1d1c41806a568e910fc77f2 Mon Sep 17 00:00:00 2001 From: Ajay Date: Thu, 17 Mar 2022 00:29:33 -0400 Subject: [PATCH 07/23] Force css --- public/content.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/content.css b/public/content.css index 790202d2..095c59eb 100644 --- a/public/content.css +++ b/public/content.css @@ -353,7 +353,7 @@ } .segmentSummary { - outline: none; + outline: none !important; } .submitButton { From 15c73d79404efb9ecb7af921ed46adee3798405c Mon Sep 17 00:00:00 2001 From: Stopper Date: Thu, 17 Mar 2022 22:24:00 +0600 Subject: [PATCH 08/23] Fix guidelines link --- src/components/SubmissionNoticeComponent.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/SubmissionNoticeComponent.tsx b/src/components/SubmissionNoticeComponent.tsx index 82aa0cca..de9e9f7d 100644 --- a/src/components/SubmissionNoticeComponent.tsx +++ b/src/components/SubmissionNoticeComponent.tsx @@ -95,7 +95,7 @@ class SubmissionNoticeComponent extends React.Component window.open("https://wiki.sponsor.ajay.app/index.php/Guidelines")}> + onClick={() => window.open("https://wiki.sponsor.ajay.app/w/Guidelines")}> {chrome.i18n.getMessage(Config.config.submissionCountSinceCategories > 3 ? "guidelines" : "readTheGuidelines")} From 24fc5e4370a9ea579b46f977ef59bb84533ac0af Mon Sep 17 00:00:00 2001 From: Alec Rust Date: Sun, 13 Mar 2022 11:03:37 +0000 Subject: [PATCH 09/23] Fix popup width when rendered in-page --- public/popup.css | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/public/popup.css b/public/popup.css index 43320ce1..a3400503 100644 --- a/public/popup.css +++ b/public/popup.css @@ -33,6 +33,14 @@ text-align: center; } +/* + * Disable fixed popup width when displayed inline + */ + +#sponsorBlockPopupContainer #sponsorBlockPopupBody { + width: auto; +} + /* * Disable transition on all elements until the extension has loaded */ From f7510eea88f345f365d63eb6d763c6c037aa28b1 Mon Sep 17 00:00:00 2001 From: Alec Rust Date: Sun, 13 Mar 2022 11:42:16 +0000 Subject: [PATCH 10/23] Improve close popup button --- public/popup.css | 43 ++++++++--- src/content.ts | 196 ++++++++++++++++++++++++----------------------- 2 files changed, 132 insertions(+), 107 deletions(-) diff --git a/public/popup.css b/public/popup.css index a3400503..31b68092 100644 --- a/public/popup.css +++ b/public/popup.css @@ -7,14 +7,26 @@ } /* - * IDs on container element (when inserted in page), element, - * element and main container + * Container when popup displayed in-page */ #sponsorBlockPopupContainer { + position: relative; margin-bottom: 16px; } +/* + * Disable fixed popup width when displayed in-page + */ + +#sponsorBlockPopupContainer #sponsorBlockPopupBody { + width: auto; +} + +/* + * Main containers + */ + #sponsorBlockPopupHTML { color-scheme: dark; } @@ -33,14 +45,6 @@ text-align: center; } -/* - * Disable fixed popup width when displayed inline - */ - -#sponsorBlockPopupContainer #sponsorBlockPopupBody { - width: auto; -} - /* * Disable transition on all elements until the extension has loaded */ @@ -49,6 +53,25 @@ transition: none !important; } +/* + * Close popup button when displayed in-page + */ + +.sbCloseButton { + background: transparent; + border: 0; + padding: 8px; + cursor: pointer; + position: absolute; + top: 5px; + right: 5px; + opacity: 0.5; +} + +.sbCloseButton:hover { + opacity: 1; +} + /* * Header logo */ diff --git a/src/content.ts b/src/content.ts index e133abe7..5987050b 100644 --- a/src/content.ts +++ b/src/content.ts @@ -34,7 +34,7 @@ let sponsorVideoID: VideoID = null; const skipNotices: SkipNotice[] = []; let activeSkipKeybindElement: ToggleSkippable = null; -// JSON video info +// JSON video info let videoInfo: VideoInfo = null; // The channel this video is about let channelIDInfo: ChannelIDInfo; @@ -221,8 +221,8 @@ function messageListener(request: Message, sender: unknown, sendResponse: (respo /** * Called when the config is updated - * - * @param {String} changes + * + * @param {String} changes */ function contentConfigUpdateListener(changes: StorageChangesObject) { for (const key in changes) { @@ -301,7 +301,7 @@ async function videoIDChange(id) { // If enabled, it will check if this video is private or unlisted and double check with the user if the sponsors should be looked up if (Config.config.checkForUnlistedVideos) { - const shouldContinue = confirm("SponsorBlock: You have the setting 'Ignore Unlisted/Private Videos' enabled." + const shouldContinue = confirm("SponsorBlock: You have the setting 'Ignore Unlisted/Private Videos' enabled." + " Due to a change in how segment fetching works, this setting is not needed anymore as it cannot leak your video ID to the server." + " It instead sends just the first 4 characters of a longer hash of the videoID to the server, and filters through a subset of the database." + " More info about this implementation can be found here: https://github.com/ajayyy/SponsorBlockServer/issues/25" @@ -327,13 +327,13 @@ async function videoIDChange(id) { let controlsContainer = null; utils.wait(() => { - controlsContainer = document.getElementById("player-control-container") + controlsContainer = document.getElementById("player-control-container") return controlsContainer !== null }).then(() => { - observer.observe(document.getElementById("player-control-container"), { - attributes: true, - childList: true, - subtree: true + observer.observe(document.getElementById("player-control-container"), { + attributes: true, + childList: true, + subtree: true }); }).catch(); } else { @@ -456,7 +456,7 @@ function startSponsorSchedule(includeIntersectingSegments = false, currentTime?: if (!video || video.paused) return; if (currentTime === undefined || currentTime === null) { - const virtualTime = lastKnownVideoTime.videoTime ? + const virtualTime = lastKnownVideoTime.videoTime ? (performance.now() - lastKnownVideoTime.preciseTime) / 1000 + lastKnownVideoTime.videoTime : null; if (!isSafari() && virtualTime && Math.abs(virtualTime - video.currentTime) < 0.6){ currentTime = virtualTime; @@ -516,13 +516,13 @@ function startSponsorSchedule(includeIntersectingSegments = false, currentTime?: if (forceVideoTime >= skipTime[0] && forceVideoTime < skipTime[1]) { skipToTime({ - v: video, - skipTime, - skippingSegments, + v: video, + skipTime, + skippingSegments, openNotice: skipInfo.openNotice }); - if (utils.getCategorySelection(currentSkip.category)?.option === CategorySkipOption.ManualSkip + if (utils.getCategorySelection(currentSkip.category)?.option === CategorySkipOption.ManualSkip || currentSkip.actionType === ActionType.Mute) { forcedSkipTime = skipTime[0] + 0.001; } else { @@ -573,8 +573,8 @@ function inMuteSegment(currentTime: number): boolean { */ function incorrectVideoCheck(videoID?: string, sponsorTime?: SponsorTime): boolean { const currentVideoID = getYouTubeVideoID(document); - if (currentVideoID !== (videoID || sponsorVideoID) || (sponsorTime - && (!sponsorTimes || !sponsorTimes?.some((time) => time.segment === sponsorTime.segment)) + if (currentVideoID !== (videoID || sponsorVideoID) || (sponsorTime + && (!sponsorTimes || !sponsorTimes?.some((time) => time.segment === sponsorTime.segment)) && !sponsorTimesSubmitting.some((time) => time.segment === sponsorTime.segment))) { // Something has really gone wrong console.error("[SponsorBlock] The videoID recorded when trying to skip is different than what it should be."); @@ -592,13 +592,13 @@ function incorrectVideoCheck(videoID?: string, sponsorTime?: SponsorTime): boole function setupVideoMutationListener() { const videoContainer = document.querySelector(".html5-video-container"); if (!videoContainer || videoMutationObserver !== null || onInvidious) return; - + videoMutationObserver = new MutationObserver(refreshVideoAttachments); - videoMutationObserver.observe(videoContainer, { - attributes: true, - childList: true, - subtree: true + videoMutationObserver.observe(videoContainer, { + attributes: true, + childList: true, + subtree: true }); } @@ -647,19 +647,19 @@ function setupVideoListeners() { // If already segments loaded before video, retry to skip starting segments if (sponsorTimes) startSkipScheduleCheckingForStartSponsors(); } - + // Check if an ad is playing updateAdFlag(); - + // Make sure it doesn't get double called with the playing event if (Math.abs(lastCheckVideoTime - video.currentTime) > 0.3 || (lastCheckVideoTime !== video.currentTime && Date.now() - lastCheckTime > 2000)) { lastCheckTime = Date.now(); lastCheckVideoTime = video.currentTime; - + startSponsorSchedule(); } - + }); video.addEventListener('playing', () => { updateVirtualTime(); @@ -669,7 +669,7 @@ function setupVideoListeners() { || (lastCheckVideoTime !== video.currentTime && Date.now() - lastCheckTime > 2000)) { lastCheckTime = Date.now(); lastCheckVideoTime = video.currentTime; - + startSponsorSchedule(); } }); @@ -680,7 +680,7 @@ function setupVideoListeners() { lastCheckVideoTime = video.currentTime; updateVirtualTime(); - + startSponsorSchedule(); } }); @@ -696,12 +696,12 @@ function setupVideoListeners() { videoTime: null, preciseTime: null } - + cancelSponsorSchedule(); }; video.addEventListener('pause', paused); video.addEventListener('waiting', paused); - + startSponsorSchedule(); } } @@ -717,10 +717,10 @@ function setupSkipButtonControlBar() { if (!skipButtonControlBar) { skipButtonControlBar = new SkipButtonControlBar({ skip: (segment) => skipToTime({ - v: video, - skipTime: segment.segment, - skippingSegments: [segment], - openNotice: true, + v: video, + skipTime: segment.segment, + skippingSegments: [segment], + openNotice: true, forceAutoSkip: true }), onMobileYouTube @@ -759,7 +759,7 @@ async function sponsorsLookup(id: string, keepOldSubmissions = true) { const hashPrefix = (await utils.getHash(id, 1)).slice(0, 4) as VideoID & HashedValue; const response = await utils.asyncRequestToServer('GET', "/api/skipSegments/" + hashPrefix, { categories, - actionTypes: getEnabledActionTypes(), + actionTypes: getEnabledActionTypes(), userAgent: `${chrome.runtime.id}`, ...extraRequestData }); @@ -768,7 +768,7 @@ async function sponsorsLookup(id: string, keepOldSubmissions = true) { const recievedSegments: SponsorTime[] = JSON.parse(response.responseText) ?.filter((video) => video.videoID === id) ?.map((video) => video.segments)[0]; - if (!recievedSegments || !recievedSegments.length) { + if (!recievedSegments || !recievedSegments.length) { // return if no video found retryFetch(); return; @@ -834,7 +834,7 @@ async function sponsorsLookup(id: string, keepOldSubmissions = true) { } else if (response?.status === 404) { retryFetch(); } - + lookupVipInformation(id); } @@ -910,8 +910,8 @@ function retryFetch(): void { } /** - * Only should be used when it is okay to skip a sponsor when in the middle of it - * + * Only should be used when it is okay to skip a sponsor when in the middle of it + * * Ex. When segments are first loaded */ function startSkipScheduleCheckingForStartSponsors() { @@ -922,7 +922,7 @@ function startSkipScheduleCheckingForStartSponsors() { let found = false; let startingSegment: SponsorTime = null; for (const time of sponsorTimes) { - if (time.segment[0] <= video.currentTime && time.segment[0] > startingSegmentTime && time.segment[1] > video.currentTime + if (time.segment[0] <= video.currentTime && time.segment[0] > startingSegmentTime && time.segment[1] > video.currentTime && time.actionType !== ActionType.Poi) { startingSegmentTime = time.segment[0]; startingSegment = time; @@ -932,7 +932,7 @@ function startSkipScheduleCheckingForStartSponsors() { } if (!found) { for (const time of sponsorTimesSubmitting) { - if (time.segment[0] <= video.currentTime && time.segment[0] > startingSegmentTime && time.segment[1] > video.currentTime + if (time.segment[0] <= video.currentTime && time.segment[0] > startingSegmentTime && time.segment[1] > video.currentTime && time.actionType !== ActionType.Poi) { startingSegmentTime = time.segment[0]; startingSegment = time; @@ -951,8 +951,8 @@ function startSkipScheduleCheckingForStartSponsors() { if (skipOption !== CategorySkipOption.ShowOverlay) { skipToTime({ v: video, - skipTime: time.segment, - skippingSegments: [time], + skipTime: time.segment, + skippingSegments: [time], openNotice: true, unskipTime: video.currentTime }); @@ -975,7 +975,7 @@ function startSkipScheduleCheckingForStartSponsors() { /** * Get the video info for the current tab from YouTube - * + * * TODO: Replace */ async function getVideoInfo(): Promise { @@ -1023,9 +1023,9 @@ function getYouTubeVideoIDFromURL(url: string): string | boolean { //Attempt to parse url let urlObject: URL = null; - try { + try { urlObject = new URL(url); - } catch (e) { + } catch (e) { console.error("[SB] Unable to parse URL: " + url); return false; } @@ -1143,7 +1143,7 @@ async function whitelistCheck() { } //see if this is a whitelisted channel - if (whitelistedChannels != undefined && + if (whitelistedChannels != undefined && channelIDInfo.status === ChannelIDStatus.Found && whitelistedChannels.includes(channelIDInfo.id)) { channelWhitelisted = true; } @@ -1155,24 +1155,24 @@ async function whitelistCheck() { /** * Returns info about the next upcoming sponsor skip */ -function getNextSkipIndex(currentTime: number, includeIntersectingSegments: boolean, includeNonIntersectingSegments: boolean): +function getNextSkipIndex(currentTime: number, includeIntersectingSegments: boolean, includeNonIntersectingSegments: boolean): {array: ScheduledTime[], index: number, endIndex: number, openNotice: boolean} { - const { includedTimes: submittedArray, scheduledTimes: sponsorStartTimes } = + 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)); const endTimeIndex = getLatestEndTimeIndex(submittedArray, minSponsorTimeIndex); - const { includedTimes: unsubmittedArray, scheduledTimes: unsubmittedSponsorStartTimes } = + const { includedTimes: unsubmittedArray, scheduledTimes: unsubmittedSponsorStartTimes } = getStartTimes(sponsorTimesSubmitting, includeIntersectingSegments, includeNonIntersectingSegments); const { scheduledTimes: unsubmittedSponsorStartTimesAfterCurrentTime } = getStartTimes(sponsorTimesSubmitting, includeIntersectingSegments, includeNonIntersectingSegments, currentTime, false, false); const minUnsubmittedSponsorTimeIndex = unsubmittedSponsorStartTimes.indexOf(Math.min(...unsubmittedSponsorStartTimesAfterCurrentTime)); const previewEndTimeIndex = getLatestEndTimeIndex(unsubmittedArray, minUnsubmittedSponsorTimeIndex); - if ((minUnsubmittedSponsorTimeIndex === -1 && minSponsorTimeIndex !== -1) || + if ((minUnsubmittedSponsorTimeIndex === -1 && minSponsorTimeIndex !== -1) || sponsorStartTimes[minSponsorTimeIndex] < unsubmittedSponsorStartTimes[minUnsubmittedSponsorTimeIndex]) { return { array: submittedArray, @@ -1192,20 +1192,20 @@ function getNextSkipIndex(currentTime: number, includeIntersectingSegments: bool /** * This returns index if the skip option is not AutoSkip - * + * * Finds the last endTime that occurs in a segment that the given * segment skips into that is part of an AutoSkip category. - * - * Used to find where a segment should truely skip to if there are intersecting submissions due to + * + * Used to find where a segment should truely skip to if there are intersecting submissions due to * them having different categories. - * - * @param sponsorTimes + * + * @param sponsorTimes * @param index Index of the given sponsor - * @param hideHiddenSponsors + * @param hideHiddenSponsors */ function getLatestEndTimeIndex(sponsorTimes: SponsorTime[], index: number, hideHiddenSponsors = true): number { // Only combine segments for AutoSkip - if (index == -1 || + if (index == -1 || !shouldAutoSkip(sponsorTimes[index]) || sponsorTimes[index].actionType !== ActionType.Skip) { return index; @@ -1218,7 +1218,7 @@ function getLatestEndTimeIndex(sponsorTimes: SponsorTime[], index: number, hideH const currentSegment = sponsorTimes[i].segment; const latestEndTime = sponsorTimes[latestEndTimeIndex].segment[1]; - if (currentSegment[0] <= latestEndTime && currentSegment[1] > latestEndTime + if (currentSegment[0] <= latestEndTime && currentSegment[1] > latestEndTime && (!hideHiddenSponsors || sponsorTimes[i].hidden === SponsorHideType.Visible) && shouldAutoSkip(sponsorTimes[i]) && sponsorTimes[i].actionType === ActionType.Skip) { @@ -1238,11 +1238,11 @@ function getLatestEndTimeIndex(sponsorTimes: SponsorTime[], index: number, hideH /** * Gets just the start times from a sponsor times array. * Optionally specify a minimum - * - * @param sponsorTimes + * + * @param sponsorTimes * @param minimum * @param hideHiddenSponsors - * @param includeIntersectingSegments If true, it will include segments that start before + * @param includeIntersectingSegments If true, it will include segments that start before * the current time, but end after */ function getStartTimes(sponsorTimes: SponsorTime[], includeIntersectingSegments: boolean, includeNonIntersectingSegments: boolean, @@ -1271,14 +1271,14 @@ function getStartTimes(sponsorTimes: SponsorTime[], includeIntersectingSegments: for (let i = 0; i < possibleTimes.length; i++) { if ((minimum === undefined || ((includeNonIntersectingSegments && possibleTimes[i].scheduledTime >= minimum) - || (includeIntersectingSegments && possibleTimes[i].scheduledTime < minimum && possibleTimes[i].segment[1] > minimum))) + || (includeIntersectingSegments && possibleTimes[i].scheduledTime < minimum && possibleTimes[i].segment[1] > minimum))) && (!onlySkippableSponsors || shouldSkip(possibleTimes[i])) && (!hideHiddenSponsors || possibleTimes[i].hidden === SponsorHideType.Visible) && possibleTimes[i].actionType !== ActionType.Poi) { scheduledTimes.push(possibleTimes[i].scheduledTime); includedTimes.push(possibleTimes[i]); - } + } } return { includedTimes, scheduledTimes }; @@ -1286,8 +1286,8 @@ function getStartTimes(sponsorTimes: SponsorTime[], includeIntersectingSegments: /** * Skip to exact time in a video and autoskips - * - * @param time + * + * @param time */ function previewTime(time: number, unpause = true) { video.currentTime = time; @@ -1312,7 +1312,7 @@ function sendTelemetryAndCount(skippingSegments: SponsorTime[], secondsSkipped: Config.config.skipCount = Config.config.skipCount + 1; counted = true; } - + if (fullSkip) utils.asyncRequestToServer("POST", "/api/viewedVideoSponsorTime?UUID=" + segment.UUID); } } @@ -1325,7 +1325,7 @@ function skipToTime({v, skipTime, skippingSegments, openNotice, forceAutoSkip, u // There will only be one submission if it is manual skip const autoSkip: boolean = forceAutoSkip || shouldAutoSkip(skippingSegments[0]); - if ((autoSkip || sponsorTimesSubmitting.some((time) => time.segment === skippingSegments[0].segment)) + if ((autoSkip || sponsorTimesSubmitting.some((time) => time.segment === skippingSegments[0].segment)) && v.currentTime !== skipTime[1]) { switch(skippingSegments[0].actionType) { case ActionType.Poi: @@ -1366,8 +1366,8 @@ function skipToTime({v, skipTime, skippingSegments, openNotice, forceAutoSkip, u }) } - if (!autoSkip - && skippingSegments.length === 1 + if (!autoSkip + && skippingSegments.length === 1 && skippingSegments[0].actionType === ActionType.Poi) { skipButtonControlBar.enable(skippingSegments[0]); if (onMobileYouTube || Config.config.skipKeybind == null) skipButtonControlBar.setShowKeybindHint(false); @@ -1400,7 +1400,7 @@ function unskipSponsorTime(segment: SponsorTime, unskipTime: number = null) { //add a tiny bit of time to make sure it is not skipped again video.currentTime = unskipTime ?? segment.segment[0] + 0.001; } - + } function reskipSponsorTime(segment: SponsorTime) { @@ -1411,7 +1411,7 @@ function reskipSponsorTime(segment: SponsorTime) { const skippedTime = Math.max(segment.segment[1] - video.currentTime, 0); const segmentDuration = segment.segment[1] - segment.segment[0]; const fullSkip = skippedTime / segmentDuration > manualSkipPercentCount; - + video.currentTime = segment.segment[1]; sendTelemetryAndCount([segment], skippedTime, fullSkip); startSponsorSchedule(true, segment.segment[1], false); @@ -1463,8 +1463,8 @@ function shouldAutoSkip(segment: SponsorTime): boolean { } function shouldSkip(segment: SponsorTime): boolean { - return (segment.actionType !== ActionType.Full - && utils.getCategorySelection(segment.category)?.option !== CategorySkipOption.ShowOverlay) + return (segment.actionType !== ActionType.Full + && utils.getCategorySelection(segment.category)?.option !== CategorySkipOption.ShowOverlay) || (Config.config.autoSkipOnMusicVideos && sponsorTimes?.some((s) => s.category === "music_offtopic")); } @@ -1482,10 +1482,10 @@ async function createButtons(): Promise { createButton("info", "openPopup", openInfoMenu, "PlayerInfoIconSponsorBlocker.svg"); const controlsContainer = getControls(); - if (Config.config.autoHideInfoButton && !onInvidious && controlsContainer + if (Config.config.autoHideInfoButton && !onInvidious && controlsContainer && playerButtons["info"]?.button && !controlsWithEventListeners.includes(controlsContainer)) { controlsWithEventListeners.push(controlsContainer); - + AnimationUtils.setupAutoHideAnimation(playerButtons["info"].button, controlsContainer); } } @@ -1580,7 +1580,7 @@ function startOrEndTimingNewSegment() { const existingSegment = getIncompleteSegment(); const existingTime = existingSegment.segment[0]; const currentTime = roundedTime; - + // Swap timestamps if the user put the segment end before the start existingSegment.segment = [Math.min(existingTime, currentTime), Math.max(existingTime, currentTime)]; } @@ -1677,17 +1677,19 @@ function openInfoMenu() { popup.innerHTML = htmlData; //close button - const closeButton = document.createElement("div"); - closeButton.innerText = chrome.i18n.getMessage("closePopup"); - closeButton.classList.add("smallLink"); - closeButton.setAttribute("align", "center"); + const closeButton = document.createElement("button"); + const closeButtonIcon = document.createElement("img"); + closeButtonIcon.src = chrome.extension.getURL("icons/close.png"); + closeButtonIcon.width = 16; + closeButtonIcon.height = 16; + closeButton.appendChild(closeButtonIcon); + closeButton.setAttribute("title", chrome.i18n.getMessage("closePopup")); + closeButton.classList.add("sbCloseButton"); closeButton.addEventListener("click", closeInfoMenu); - // Theme based color - closeButton.style.color = "var(--yt-spec-text-primary)"; //add the close button popup.prepend(closeButton); - + const parentNodes = document.querySelectorAll("#secondary"); let parentNode = null; for (let i = 0; i < parentNodes.length; i++) { @@ -1798,7 +1800,7 @@ async function vote(type: number, UUID: SegmentUUID, category?: Category, skipNo } else { skipNotice.setNoticeInfoMessage.bind(skipNotice)(GenericUtils.getErrorMessage(response.statusCode, response.responseText)) } - + skipNotice.resetVoteButtonInfo.bind(skipNotice)(); } } @@ -1824,7 +1826,7 @@ async function voteAsync(type: number, UUID: SegmentUUID, category?: Category): // Count this as a skip Config.config.minutesSaved = Config.config.minutesSaved + factor * (sponsorTimes[sponsorIndex].segment[1] - sponsorTimes[sponsorIndex].segment[0]) / 60; - + Config.config.skipCount = Config.config.skipCount + factor; } @@ -1886,8 +1888,8 @@ function submitSponsorTimes() { submissionNotice.close(); submissionNotice = null; return; - } - + } + if (sponsorTimesSubmitting !== undefined && sponsorTimesSubmitting.length > 0) { submissionNotice = new SubmissionNotice(skipNoticeContentContainer, sendSubmitMessage); } @@ -1923,9 +1925,9 @@ async function sendSubmitMessage() { for (let i = 0; i < sponsorTimesSubmitting.length; i++) { const duration = sponsorTimesSubmitting[i].segment[1] - sponsorTimesSubmitting[i].segment[0]; if (duration > 0 && duration < Config.config.minDuration) { - const confirmShort = chrome.i18n.getMessage("shortCheck") + "\n\n" + + const confirmShort = chrome.i18n.getMessage("shortCheck") + "\n\n" + getSegmentsMessage(sponsorTimesSubmitting); - + if(!confirm(confirmShort)) return; } } @@ -2030,10 +2032,10 @@ function hotkeyListener(e: KeyboardEvent): void { || document.activeElement?.id?.toLowerCase()?.includes("editable")) return; const key: Keybind = { - key: e.key, - code: e.code, - alt: e.altKey, - ctrl: e.ctrlKey, + key: e.key, + code: e.code, + alt: e.altKey, + ctrl: e.ctrlKey, shift: e.shiftKey }; @@ -2094,7 +2096,7 @@ function sendRequestToCustomServer(type, fullAddress, callback) { xmlhttp.onreadystatechange = function () { callback(xmlhttp, false); }; - + xmlhttp.onerror = function() { callback(xmlhttp, true); }; @@ -2138,7 +2140,7 @@ function showTimeWithoutSkips(skippedDuration: number): void { display.appendChild(duration); } - + const durationAfterSkips = utils.getFormattedTime(video?.duration - skippedDuration) duration.innerText = (durationAfterSkips == null || skippedDuration <= 0) ? "" : " (" + durationAfterSkips + ")"; @@ -2146,7 +2148,7 @@ function showTimeWithoutSkips(skippedDuration: number): void { function checkForPreloadedSegment() { if (loadedPreloadedSegment) return; - + loadedPreloadedSegment = true; const hashParams = getHashParams(); @@ -2174,4 +2176,4 @@ function checkForPreloadedSegment() { Config.config.unsubmittedSegments[sponsorVideoID] = sponsorTimesSubmitting; Config.forceSyncUpdate("unsubmittedSegments"); } -} \ No newline at end of file +} From c0cfa3a6837dce07f46ca6fa2e1672895b0e1336 Mon Sep 17 00:00:00 2001 From: Alec Rust Date: Mon, 14 Mar 2022 13:17:59 +0000 Subject: [PATCH 11/23] Fix "You've saved" and "You've skipped" not being on separate lines Screenshot: https://i.imgur.com/VqeXMmS.png --- src/content.ts | 4 ++-- src/popup.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/content.ts b/src/content.ts index 5987050b..1bf28424 100644 --- a/src/content.ts +++ b/src/content.ts @@ -1680,8 +1680,8 @@ function openInfoMenu() { const closeButton = document.createElement("button"); const closeButtonIcon = document.createElement("img"); closeButtonIcon.src = chrome.extension.getURL("icons/close.png"); - closeButtonIcon.width = 16; - closeButtonIcon.height = 16; + closeButtonIcon.width = 15; + closeButtonIcon.height = 15; closeButton.appendChild(closeButtonIcon); closeButton.setAttribute("title", chrome.i18n.getMessage("closePopup")); closeButton.classList.add("sbCloseButton"); diff --git a/src/popup.ts b/src/popup.ts index df47d817..cbf92917 100644 --- a/src/popup.ts +++ b/src/popup.ts @@ -180,7 +180,7 @@ async function runThePopup(messageListener?: MessageListener): Promise { PageElements.sponsorTimesViewsDisplayEndWord.innerText = chrome.i18n.getMessage("Segment"); } PageElements.sponsorTimesViewsDisplay.innerText = viewCount.toLocaleString(); - PageElements.sponsorTimesViewsContainer.style.display = "unset"; + PageElements.sponsorTimesViewsContainer.style.display = "block"; } showDonateWidget(viewCount); @@ -212,7 +212,7 @@ async function runThePopup(messageListener?: MessageListener): Promise { } PageElements.sponsorTimesSkipsDoneDisplay.innerText = Config.config.skipCount.toLocaleString(); - PageElements.sponsorTimesSkipsDoneContainer.style.display = "unset"; + PageElements.sponsorTimesSkipsDoneContainer.style.display = "block"; } //get the amount of time this user has saved. From e30bccd2b7d6f0fa19170c5fa9621b5579a9c97a Mon Sep 17 00:00:00 2001 From: Ajay Date: Thu, 17 Mar 2022 22:19:21 -0400 Subject: [PATCH 12/23] Don't use virtual time on firefox --- src/content.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content.ts b/src/content.ts index e133abe7..250d6c4d 100644 --- a/src/content.ts +++ b/src/content.ts @@ -458,7 +458,7 @@ function startSponsorSchedule(includeIntersectingSegments = false, currentTime?: if (currentTime === undefined || currentTime === null) { const virtualTime = lastKnownVideoTime.videoTime ? (performance.now() - lastKnownVideoTime.preciseTime) / 1000 + lastKnownVideoTime.videoTime : null; - if (!isSafari() && virtualTime && Math.abs(virtualTime - video.currentTime) < 0.6){ + if (!utils.isFirefox() && !isSafari() && virtualTime && Math.abs(virtualTime - video.currentTime) < 0.6){ currentTime = virtualTime; } else { currentTime = video.currentTime; From 821bbc969bc4949b1359cff1c15ffe818cd11cf4 Mon Sep 17 00:00:00 2001 From: Ajay Date: Thu, 17 Mar 2022 22:19:33 -0400 Subject: [PATCH 13/23] bump version --- manifest/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manifest/manifest.json b/manifest/manifest.json index 4eaae99d..e2a79254 100644 --- a/manifest/manifest.json +++ b/manifest/manifest.json @@ -1,7 +1,7 @@ { "name": "__MSG_fullName__", "short_name": "SponsorBlock", - "version": "4.2", + "version": "4.2.1", "default_locale": "en", "description": "__MSG_Description__", "homepage_url": "https://sponsor.ajay.app", From ac7f2eb5b1454e5fc5be39c9bbb76ec7d1e1b5de Mon Sep 17 00:00:00 2001 From: Alec Rust Date: Sun, 20 Mar 2022 12:15:04 +0000 Subject: [PATCH 14/23] Refine "load in Firefox" docs --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9591f5eb..d1bd68bf 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@

Logo - +
Logo by @munadikieh

@@ -72,7 +72,7 @@ You must have [Node.js 16](https://nodejs.org/) and npm installed. - You can also run `npm run build` (for Chrome) or `npm run build:firefox` (for Firefox) to generate a production build. -4. The built extension is now in `dist/`. You can load it in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/#manifest) or in Firefox as a [temporary extension](https://developer.mozilla.org/en-US/docs/Tools/about:debugging#loading_a_temporary_extension). +4. The built extension is now in `dist/`. You can load this folder directly in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/#manifest), or for Firefox ZIP the contents of this folder then load it as a [temporary extension](https://developer.mozilla.org/en-US/docs/Tools/about:debugging#loading_a_temporary_extension). ### Developing with a clean profile and hot reloading From c66110a60fd2bb75cef9a6252561298ee986bd1e Mon Sep 17 00:00:00 2001 From: Ajay Date: Mon, 21 Mar 2022 22:42:47 -0400 Subject: [PATCH 15/23] Increase tooltip zindex --- public/content.css | 1 + 1 file changed, 1 insertion(+) diff --git a/public/content.css b/public/content.css index 095c59eb..f697300e 100644 --- a/public/content.css +++ b/public/content.css @@ -592,6 +592,7 @@ input::-webkit-inner-spin-button { line-height: 1.5em; color: white; font-size: 12px; + z-index: 1000; } .sponsorBlockTooltip a { From 940350504a5ff52a75a228e2921dd5ace887f756 Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Tue, 22 Mar 2022 22:09:57 -0400 Subject: [PATCH 16/23] different wording --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d1bd68bf..65cc8990 100644 --- a/README.md +++ b/README.md @@ -72,7 +72,7 @@ You must have [Node.js 16](https://nodejs.org/) and npm installed. - You can also run `npm run build` (for Chrome) or `npm run build:firefox` (for Firefox) to generate a production build. -4. The built extension is now in `dist/`. You can load this folder directly in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/#manifest), or for Firefox ZIP the contents of this folder then load it as a [temporary extension](https://developer.mozilla.org/en-US/docs/Tools/about:debugging#loading_a_temporary_extension). +4. The built extension is now in `dist/`. You can load this folder directly in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/#manifest), or convert it to a zip file to load it as a [temporary extension](https://developer.mozilla.org/en-US/docs/Tools/about:debugging#loading_a_temporary_extension) in Firefox. ### Developing with a clean profile and hot reloading From e8536fd4043cdefe50d0c6bf84b2fac199449ab7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 25 Mar 2022 23:39:45 +0000 Subject: [PATCH 17/23] Bump minimist from 1.2.5 to 1.2.6 Bumps [minimist](https://github.com/substack/minimist) from 1.2.5 to 1.2.6. - [Release notes](https://github.com/substack/minimist/releases) - [Commits](https://github.com/substack/minimist/compare/1.2.5...1.2.6) --- updated-dependencies: - dependency-name: minimist dependency-type: indirect ... Signed-off-by: dependabot[bot] --- package-lock.json | 38 ++++++-------------------------------- 1 file changed, 6 insertions(+), 32 deletions(-) diff --git a/package-lock.json b/package-lock.json index a6d80792..90a710ef 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4256,24 +4256,6 @@ "node": ">=0.10.0" } }, - "node_modules/copy-webpack-plugin/node_modules/schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, "node_modules/copy-webpack-plugin/node_modules/slash": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", @@ -9990,8 +9972,9 @@ } }, "node_modules/minimist": { - "version": "1.2.5", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", "dev": true }, "node_modules/mkdirp": { @@ -17279,16 +17262,6 @@ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true }, - "schema-utils": { - "version": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - } - }, "slash": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", @@ -21575,8 +21548,9 @@ } }, "minimist": { - "version": "1.2.5", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", "dev": true }, "mkdirp": { From 9f1f9f84d408d787b800f359dc0f0f8d6bf322af Mon Sep 17 00:00:00 2001 From: Zacchary Dempsey-Plante Date: Sat, 26 Mar 2022 23:09:24 -0400 Subject: [PATCH 18/23] Improve the channel ID lookup. --- src/content.ts | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/content.ts b/src/content.ts index a3352b3b..c9abca76 100644 --- a/src/content.ts +++ b/src/content.ts @@ -1120,11 +1120,12 @@ function updatePreviewBar(): void { async function whitelistCheck() { const whitelistedChannels = Config.config.whitelistedChannels; - const getChannelID = () => videoInfo?.videoDetails?.channelId - ?? document.querySelector(".ytd-channel-name a")?.getAttribute("href")?.replace(/\/.+\//, "") // YouTube - ?? document.querySelector(".ytp-title-channel-logo")?.getAttribute("href")?.replace(/https:\/.+\//, "") // YouTube Embed - ?? document.querySelector("a > .channel-profile")?.parentElement?.getAttribute("href")?.replace(/\/.+\//, "") // Invidious - ?? document.querySelector("a.slim-owner-icon-and-title")?.getAttribute("href")?.replace(/\/.+\//, ""); // Mobile YouTube + const getChannelID = () => + (document.querySelector("a.ytd-video-owner-renderer") // YouTube + ?? document.querySelector("a.ytp-title-channel-logo") // YouTube Embed + ?? document.querySelector(".channel-profile #channel-name")?.parentElement.parentElement // Invidious + ?? document.querySelector("a.slim-owner-icon-and-title")) // Mobile YouTube + ?.getAttribute("href")?.match(/\/channel\/(UC[a-zA-Z0-9_-]{22})/)[1]; try { await utils.wait(() => !!getChannelID(), 6000, 20); From b15a8db6516cfed7a99be5d0eff50470cf98ceab Mon Sep 17 00:00:00 2001 From: Ajay Date: Mon, 28 Mar 2022 15:33:15 -0400 Subject: [PATCH 19/23] Fix close skips not overlapping --- src/content.ts | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/content.ts b/src/content.ts index a3352b3b..d62b0be7 100644 --- a/src/content.ts +++ b/src/content.ts @@ -45,6 +45,8 @@ let lastKnownVideoTime: { videoTime: number, preciseTime: number } = { videoTime: null, preciseTime: null }; +// It resumes with a slightly later time on chromium +let lastTimeFromWaitingEvent = null; // Skips are scheduled to ensure precision. // Skips are rescheduled every seeking event. @@ -456,14 +458,16 @@ function startSponsorSchedule(includeIntersectingSegments = false, currentTime?: if (!video || video.paused) return; if (currentTime === undefined || currentTime === null) { - const virtualTime = lastKnownVideoTime.videoTime ? - (performance.now() - lastKnownVideoTime.preciseTime) / 1000 + lastKnownVideoTime.videoTime : null; - if (!utils.isFirefox() && !isSafari() && virtualTime && Math.abs(virtualTime - video.currentTime) < 0.6){ + const virtualTime = lastTimeFromWaitingEvent ?? (lastKnownVideoTime.videoTime ? + (performance.now() - lastKnownVideoTime.preciseTime) / 1000 + lastKnownVideoTime.videoTime : null); + if ((lastTimeFromWaitingEvent || !utils.isFirefox()) + && !isSafari() && virtualTime && Math.abs(virtualTime - video.currentTime) < 0.6){ currentTime = virtualTime; } else { currentTime = video.currentTime; } } + lastTimeFromWaitingEvent = null; if (videoMuted && !inMuteSegment(currentTime)) { video.muted = false; @@ -535,8 +539,8 @@ function startSponsorSchedule(includeIntersectingSegments = false, currentTime?: startSponsorSchedule(forcedIncludeIntersectingSegments, forcedSkipTime, forcedIncludeNonIntersectingSegments); }; - if (timeUntilSponsor <= 0) { - skippingFunction(); + if (timeUntilSponsor < 0.003) { + skippingFunction(currentTime); } else { const delayTime = timeUntilSponsor * 1000 * (1 / video.playbackRate); if (delayTime < 300) { @@ -680,6 +684,7 @@ function setupVideoListeners() { lastCheckVideoTime = video.currentTime; updateVirtualTime(); + lastTimeFromWaitingEvent = null; startSponsorSchedule(); } @@ -696,6 +701,7 @@ function setupVideoListeners() { videoTime: null, preciseTime: null } + lastTimeFromWaitingEvent = video.currentTime; cancelSponsorSchedule(); }; From bd6372d94429df80b5e43e3c6a31112cae56cdd3 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 1 Apr 2022 00:19:47 +0000 Subject: [PATCH 20/23] Update Invidious List --- ci/invidiouslist.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/invidiouslist.json b/ci/invidiouslist.json index 4638f7c3..6617abf6 100644 --- a/ci/invidiouslist.json +++ b/ci/invidiouslist.json @@ -1 +1 @@ -["yewtu.be","invidious.snopyta.org","vid.puffyan.us","invidious.kavin.rocks","invidio.xamh.de","inv.riverside.rocks","invidious-us.kavin.rocks","invidious.osi.kr","tube.cthd.icu","yt.artemislena.eu","youtube.076.ne.jp","invidious.namazso.eu"] \ No newline at end of file +["yewtu.be","vid.puffyan.us","invidious.snopyta.org","invidious.kavin.rocks","invidio.xamh.de","inv.riverside.rocks","invidious-us.kavin.rocks","invidious.osi.kr","tube.cthd.icu","invidious.flokinet.to","yt.artemislena.eu","youtube.076.ne.jp","invidious.namazso.eu"] \ No newline at end of file From 88f60c0e84394dbf8516f9fc7ca46542c698a532 Mon Sep 17 00:00:00 2001 From: Michael C Date: Fri, 8 Apr 2022 22:03:00 -0400 Subject: [PATCH 21/23] close #1265 --- src/content.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/content.ts b/src/content.ts index 2212945b..49c57372 100644 --- a/src/content.ts +++ b/src/content.ts @@ -1003,10 +1003,10 @@ function getYouTubeVideoID(document: Document): string | boolean { const url = document.URL; // clips should never skip, going from clip to full video has no indications. if (url.includes("youtube.com/clip/")) return false; + // skip to document and don't hide if on /embed/ + if (url.includes("/embed/") && url.includes("youtube.com")) return getYouTubeVideoIDFromDocument(document, false); // skip to URL if matches youtube watch or invidious or matches youtube pattern if ((!url.includes("youtube.com")) || url.includes("/watch") || url.includes("/shorts/") || url.includes("playlist")) return getYouTubeVideoIDFromURL(url); - // skip to document and don't hide if on /embed/ - if (url.includes("/embed/")) return getYouTubeVideoIDFromDocument(document, false); // skip to document if matches pattern if (url.includes("/channel/") || url.includes("/user/") || url.includes("/c/")) return getYouTubeVideoIDFromDocument(document); // not sure, try URL then document From 0d34e643c7a939d6326a4c49ce753b05b581abc1 Mon Sep 17 00:00:00 2001 From: Michael C Date: Fri, 8 Apr 2022 22:36:44 -0400 Subject: [PATCH 22/23] fix #1236 --- public/content.css | 6 ++++++ src/content.ts | 7 ++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/public/content.css b/public/content.css index f697300e..afcd4c3d 100644 --- a/public/content.css +++ b/public/content.css @@ -652,4 +652,10 @@ input::-webkit-inner-spin-button { .sponsorBlockCategoryPill:hover .categoryPillClose { display: inherit; +} + +/* tweak for mobile duration */ +#sponsorBlockDurationAfterSkips.ytm-time-display { + padding-left: 4px; + margin: 0px; } \ No newline at end of file diff --git a/src/content.ts b/src/content.ts index 49c57372..2ebfc38e 100644 --- a/src/content.ts +++ b/src/content.ts @@ -2126,14 +2126,15 @@ function updateAdFlag(): void { } function showTimeWithoutSkips(skippedDuration: number): void { - if (onMobileYouTube || onInvidious) return; + if (onInvidious) return; if (isNaN(skippedDuration) || skippedDuration < 0) { skippedDuration = 0; } // YouTube player time display - const display = document.querySelector(".ytp-time-display.notranslate"); + const displayClass = onMobileYouTube ? "ytm-time-display" : "ytp-time-display.notranslate" + const display = document.querySelector(`.${displayClass}`); if (!display) return; const durationID = "sponsorBlockDurationAfterSkips"; @@ -2143,7 +2144,7 @@ function showTimeWithoutSkips(skippedDuration: number): void { if (duration === null) { duration = document.createElement('span'); duration.id = durationID; - duration.classList.add("ytp-time-duration"); + duration.classList.add(displayClass); display.appendChild(duration); } From 6f5586d656d767a5f7a34f6e7a1f8043d665dad5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 9 Apr 2022 04:42:15 +0000 Subject: [PATCH 23/23] Bump moment from 2.29.1 to 2.29.2 Bumps [moment](https://github.com/moment/moment) from 2.29.1 to 2.29.2. - [Release notes](https://github.com/moment/moment/releases) - [Changelog](https://github.com/moment/moment/blob/develop/CHANGELOG.md) - [Commits](https://github.com/moment/moment/compare/2.29.1...2.29.2) --- updated-dependencies: - dependency-name: moment dependency-type: indirect ... Signed-off-by: dependabot[bot] --- package-lock.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index 90a710ef..419c2e2f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9990,9 +9990,9 @@ } }, "node_modules/moment": { - "version": "2.29.1", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", - "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==", + "version": "2.29.2", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.2.tgz", + "integrity": "sha512-UgzG4rvxYpN15jgCmVJwac49h9ly9NurikMWGPdVxm8GZD6XjkKPxDTjQQ43gtGgnV3X0cAyWDdP2Wexoquifg==", "dev": true, "optional": true, "engines": { @@ -21563,9 +21563,9 @@ } }, "moment": { - "version": "2.29.1", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", - "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==", + "version": "2.29.2", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.2.tgz", + "integrity": "sha512-UgzG4rvxYpN15jgCmVJwac49h9ly9NurikMWGPdVxm8GZD6XjkKPxDTjQQ43gtGgnV3X0cAyWDdP2Wexoquifg==", "dev": true, "optional": true },