From 9e4939e2e38fbc8e9aed7341f671d4c4941b76fe Mon Sep 17 00:00:00 2001 From: Ajay Date: Tue, 14 Jan 2025 15:08:01 -0500 Subject: [PATCH 01/26] Fix options page layout issue --- public/options/options.css | 1 + 1 file changed, 1 insertion(+) diff --git a/public/options/options.css b/public/options/options.css index b36a802b..b68ce3dd 100644 --- a/public/options/options.css +++ b/public/options/options.css @@ -373,6 +373,7 @@ input[type='number'] { display: inline-block; width: 40px; height: 24px; + min-width: 40px; } .switch input { From 0f4c1c50cb39fce6d7f4f583de138c4eb7e12fdc Mon Sep 17 00:00:00 2001 From: Ajay Date: Fri, 17 Jan 2025 04:33:56 -0500 Subject: [PATCH 02/26] Add delay to fetch on hover to make it less easy to trigger --- src/utils/thumbnails.ts | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/src/utils/thumbnails.ts b/src/utils/thumbnails.ts index 68ad8169..f6f82a60 100644 --- a/src/utils/thumbnails.ts +++ b/src/utils/thumbnails.ts @@ -58,10 +58,27 @@ function thumbnailHoverListener(e: MouseEvent) { if (!thumbnail) return; // Pre-fetch data for this video - const videoID = extractVideoID(thumbnail); - if (videoID) { - void getSegmentsForVideo(videoID, false); - } + let fetched = false; + const preFetch = () => { + fetched = true; + const videoID = extractVideoID(thumbnail); + if (videoID) { + void getSegmentsForVideo(videoID, false); + } + }; + const timeout = setTimeout(preFetch, 200); + const onMouseDown = () => { + clearTimeout(timeout); + if (!fetched) { + preFetch(); + } + }; + + e.target.addEventListener("mousedown", onMouseDown, { once: true }); + e.target.addEventListener("mouseleave", () => { + clearTimeout(timeout); + e.target.removeEventListener("mousedown", onMouseDown); + }, { once: true }); } function getLink(thumbnail: HTMLImageElement): HTMLAnchorElement | null { From 0f75953ad152c9db54974143ea6fd1b51243977e Mon Sep 17 00:00:00 2001 From: Ajay Date: Fri, 17 Jan 2025 04:35:52 -0500 Subject: [PATCH 03/26] bump version --- manifest/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manifest/manifest.json b/manifest/manifest.json index 7e19a919..7c12cd25 100644 --- a/manifest/manifest.json +++ b/manifest/manifest.json @@ -1,7 +1,7 @@ { "name": "__MSG_fullName__", "short_name": "SponsorBlock", - "version": "5.11", + "version": "5.11.1", "default_locale": "en", "description": "__MSG_Description__", "homepage_url": "https://sponsor.ajay.app", From 236c95d2f66f98690727e3b6efece929d5dcd370 Mon Sep 17 00:00:00 2001 From: Ajay Date: Sat, 18 Jan 2025 00:25:33 -0500 Subject: [PATCH 04/26] Only do pre-fetch on hover if there are segments near the start of the video --- src/utils/thumbnails.ts | 8 ++++---- src/utils/videoLabels.ts | 29 ++++++++++++++++++++++++----- 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/src/utils/thumbnails.ts b/src/utils/thumbnails.ts index f6f82a60..5b98cc44 100644 --- a/src/utils/thumbnails.ts +++ b/src/utils/thumbnails.ts @@ -1,6 +1,6 @@ import { isOnInvidious, parseYouTubeVideoIDFromURL } from "../../maze-utils/src/video"; import Config from "../config"; -import { getVideoLabel } from "./videoLabels"; +import { getHasStartSegment, getVideoLabel } from "./videoLabels"; import { getThumbnailSelector, setThumbnailListener } from "../../maze-utils/src/thumbnailManagement"; import { VideoID } from "../types"; import { getSegmentsForVideo } from "./segmentData"; @@ -59,14 +59,14 @@ function thumbnailHoverListener(e: MouseEvent) { // Pre-fetch data for this video let fetched = false; - const preFetch = () => { + const preFetch = async () => { fetched = true; const videoID = extractVideoID(thumbnail); - if (videoID) { + if (videoID && await getHasStartSegment(videoID)) { void getSegmentsForVideo(videoID, false); } }; - const timeout = setTimeout(preFetch, 200); + const timeout = setTimeout(preFetch, 100); const onMouseDown = () => { clearTimeout(timeout); if (!fetched) { diff --git a/src/utils/videoLabels.ts b/src/utils/videoLabels.ts index 82af788c..4b9c71c4 100644 --- a/src/utils/videoLabels.ts +++ b/src/utils/videoLabels.ts @@ -6,9 +6,14 @@ import { asyncRequestToServer } from "./requests"; const utils = new Utils(); +interface VideoLabelsCacheData { + category: Category; + hasStartSegment: boolean; +} + export interface LabelCacheEntry { timestamp: number; - videos: Record; + videos: Record; } const labelCache: Record = {}; @@ -21,7 +26,7 @@ async function getLabelHashBlock(hashPrefix: string): Promise [video.videoID, video.segments[0].category])), + videos: Object.fromEntries(data.map(video => [video.videoID, { + category: video.segments[0]?.category, + hasStartSegment: video.hasStartSegment + }])), }; labelCache[hashPrefix] = newEntry; @@ -55,11 +63,11 @@ async function getLabelHashBlock(hashPrefix: string): Promise { - const prefix = (await getHash(videoID, 1)).slice(0, 3); + const prefix = (await getHash(videoID, 1)).slice(0, 4); const result = await getLabelHashBlock(prefix); if (result) { - const category = result.videos[videoID]; + const category = result.videos[videoID]?.category; if (category && utils.getCategorySelection(category).option !== CategorySkipOption.Disabled) { return category; } else { @@ -67,5 +75,16 @@ export async function getVideoLabel(videoID: VideoID): Promise } } + return null; +} + +export async function getHasStartSegment(videoID: VideoID): Promise { + const prefix = (await getHash(videoID, 1)).slice(0, 4); + const result = await getLabelHashBlock(prefix); + + if (result) { + return result?.videos[videoID]?.hasStartSegment ?? false; + } + return null; } \ No newline at end of file From b81de9627795528e43d2d0c381bf620dbddddb86 Mon Sep 17 00:00:00 2001 From: Ajay Date: Sat, 18 Jan 2025 03:10:14 -0500 Subject: [PATCH 05/26] Add support for partial segment IDs --- src/background.ts | 6 +++--- src/content.ts | 7 ++++--- src/utils.ts | 14 +++++++++++++- src/utils/segmentData.ts | 4 +++- 4 files changed, 23 insertions(+), 8 deletions(-) diff --git a/src/background.ts b/src/background.ts index a5a70219..6bb21d1b 100644 --- a/src/background.ts +++ b/src/background.ts @@ -43,7 +43,7 @@ chrome.runtime.onMessage.addListener(function (request, sender, callback) { chrome.tabs.create({url: chrome.runtime.getURL(request.url)}); return false; case "submitVote": - submitVote(request.type, request.UUID, request.category).then(callback); + submitVote(request.type, request.UUID, request.category, request.videoID).then(callback); //this allows the callback to be called later return true; @@ -214,7 +214,7 @@ async function unregisterFirefoxContentScript(id: string) { } } -async function submitVote(type: number, UUID: string, category: string) { +async function submitVote(type: number, UUID: string, category: string, videoID: string) { let userID = Config.config.userID; if (userID == undefined || userID === "undefined") { @@ -226,7 +226,7 @@ async function submitVote(type: number, UUID: string, category: string) { const typeSection = (type !== undefined) ? "&type=" + type : "&category=" + category; try { - const response = await asyncRequestToServer("POST", "/api/voteOnSponsorTime?UUID=" + UUID + "&userID=" + userID + typeSection); + const response = await asyncRequestToServer("POST", "/api/voteOnSponsorTime?UUID=" + UUID + "&videoID=" + videoID + "&userID=" + userID + typeSection); if (response.ok) { return { diff --git a/src/content.ts b/src/content.ts index 0b075450..0eb01389 100644 --- a/src/content.ts +++ b/src/content.ts @@ -1400,7 +1400,7 @@ function updatePreviewBar(): void { showLarger: segment.actionType === ActionType.Poi, description: segment.description, source: segment.source, - requiredSegment: requiredSegment && (segment.UUID === requiredSegment || segment.UUID?.startsWith(requiredSegment)), + requiredSegment: requiredSegment && (segment.UUID === requiredSegment || segment.UUID?.startsWith(requiredSegment) || requiredSegment.startsWith(segment.UUID)), selectedSegment: selectedSegment && segment.UUID === selectedSegment }); }); @@ -1678,7 +1678,7 @@ function sendTelemetryAndCount(skippingSegments: SponsorTime[], secondsSkipped: counted = true; } - if (fullSkip) asyncRequestToServer("POST", "/api/viewedVideoSponsorTime?UUID=" + segment.UUID); + if (fullSkip) asyncRequestToServer("POST", "/api/viewedVideoSponsorTime?UUID=" + segment.UUID + "&videoID=" + getVideoID()); } } } @@ -2268,7 +2268,8 @@ async function voteAsync(type: number, UUID: SegmentUUID, category?: Category): message: "submitVote", type: type, UUID: UUID, - category: category + category: category, + videoID: getVideoID() }, (response) => { if (response.successType === 1) { // Change the sponsor locally diff --git a/src/utils.ts b/src/utils.ts index c1887119..6c646a7b 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -5,6 +5,7 @@ import { getHash, HashedValue } from "../maze-utils/src/hash"; import { waitFor } from "../maze-utils/src"; import { findValidElementFromSelector } from "../maze-utils/src/dom"; import { isSafari } from "../maze-utils/src/config"; +import { asyncRequestToServer } from "./utils/requests"; export default class Utils { @@ -198,7 +199,7 @@ export default class Utils { getSponsorIndexFromUUID(sponsorTimes: SponsorTime[], UUID: string): number { for (let i = 0; i < sponsorTimes.length; i++) { - if (sponsorTimes[i].UUID === UUID) { + if (sponsorTimes[i].UUID.startsWith(UUID) || UUID.startsWith(sponsorTimes[i].UUID)) { return i; } } @@ -282,6 +283,17 @@ export default class Utils { if ((chrome.extension.inIncognitoContext && !Config.config.trackDownvotesInPrivate) || !Config.config.trackDownvotes) return; + if (segmentUUID.length < 60) { + const segmentIDData = await asyncRequestToServer("GET", "/api/segmentID", { + UUID: segmentUUID, + videoID + }); + + if (segmentIDData.ok && segmentIDData.responseText) { + segmentUUID = segmentIDData.responseText; + } + } + const hashedVideoID = (await getHash(videoID, 1)).slice(0, 4) as VideoID & HashedValue; const UUIDHash = await getHash(segmentUUID, 1); diff --git a/src/utils/segmentData.ts b/src/utils/segmentData.ts index 1c2e631a..5741730d 100644 --- a/src/utils/segmentData.ts +++ b/src/utils/segmentData.ts @@ -48,11 +48,13 @@ async function fetchSegmentsForVideo(videoID: VideoID): Promise const extraRequestData: Record = {}; const hashParams = getHashParams(); if (hashParams.requiredSegment) extraRequestData.requiredSegment = hashParams.requiredSegment; - + const hashPrefix = (await getHash(videoID, 1)).slice(0, 4) as VideoID & HashedValue; + const hasDownvotedSegments = !!Config.local.downvotedSegments[hashPrefix]; const response = await asyncRequestToServer('GET', "/api/skipSegments/" + hashPrefix, { categories: CompileConfig.categoryList, actionTypes: ActionTypes, + trimUUIDs: hasDownvotedSegments ? null : 5, ...extraRequestData }, { "X-CLIENT-NAME": `${chrome.runtime.id}/v${chrome.runtime.getManifest().version}` From 2cefb9822b6cecf63621fb91fc44de6d0c38df86 Mon Sep 17 00:00:00 2001 From: Ajay Date: Sat, 18 Jan 2025 03:13:40 -0500 Subject: [PATCH 06/26] Make copy button in popup use full segment ID --- src/popup.ts | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/popup.ts b/src/popup.ts index b20723a2..0776fd24 100644 --- a/src/popup.ts +++ b/src/popup.ts @@ -681,9 +681,22 @@ async function runThePopup(messageListener?: MessageListener): Promise { uuidButton.className = "voteButton"; uuidButton.src = chrome.runtime.getURL("icons/clipboard.svg"); uuidButton.title = chrome.i18n.getMessage("copySegmentID"); - uuidButton.addEventListener("click", () => { - copyToClipboard(UUID); + uuidButton.addEventListener("click", async () => { const stopAnimation = AnimationUtils.applyLoadingAnimation(uuidButton, 0.3); + + if (UUID.length > 60) { + copyToClipboard(UUID); + } else { + const segmentIDData = await asyncRequestToServer("GET", "/api/segmentID", { + UUID: UUID, + videoID: currentVideoID + }); + + if (segmentIDData.ok && segmentIDData.responseText) { + copyToClipboard(segmentIDData.responseText); + } + } + stopAnimation(); }); From ac52a1cb1de42ea0945893184a3fd8b29f45c10f Mon Sep 17 00:00:00 2001 From: Ajay Date: Mon, 20 Jan 2025 02:28:23 -0500 Subject: [PATCH 07/26] update translations --- public/_locales | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/_locales b/public/_locales index 1853c78f..a45cc387 160000 --- a/public/_locales +++ b/public/_locales @@ -1 +1 @@ -Subproject commit 1853c78fc2f7206d6041d65dee598b8c68191b48 +Subproject commit a45cc387cad0172de63bc1e25fb6f5c1c6ac2c69 From 617f0e25e8af225e3cb5cd1ea6ce60671886916f Mon Sep 17 00:00:00 2001 From: Ajay Date: Mon, 20 Jan 2025 02:28:35 -0500 Subject: [PATCH 08/26] bump version --- manifest/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manifest/manifest.json b/manifest/manifest.json index 7c12cd25..a9e71531 100644 --- a/manifest/manifest.json +++ b/manifest/manifest.json @@ -1,7 +1,7 @@ { "name": "__MSG_fullName__", "short_name": "SponsorBlock", - "version": "5.11.1", + "version": "5.11.2", "default_locale": "en", "description": "__MSG_Description__", "homepage_url": "https://sponsor.ajay.app", From 945ac5aad3660683f98de2563c05f5d9a16b6e35 Mon Sep 17 00:00:00 2001 From: Ajay Date: Tue, 21 Jan 2025 23:42:58 -0500 Subject: [PATCH 09/26] Fix local storage error appearing unnecessarily Also adds more details to the log message --- maze-utils | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/maze-utils b/maze-utils index dc162b4e..a1e6ea7c 160000 --- a/maze-utils +++ b/maze-utils @@ -1 +1 @@ -Subproject commit dc162b4e7d26b33c31392ba8ba830976a2d97062 +Subproject commit a1e6ea7c60dfb2fde7b06be210df51f1dd836e85 From 7a1fa601da3c55c25cd0441f3f0e6254a420ad56 Mon Sep 17 00:00:00 2001 From: Ajay Date: Tue, 21 Jan 2025 23:43:11 -0500 Subject: [PATCH 10/26] bump version --- manifest/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manifest/manifest.json b/manifest/manifest.json index a9e71531..73530f47 100644 --- a/manifest/manifest.json +++ b/manifest/manifest.json @@ -1,7 +1,7 @@ { "name": "__MSG_fullName__", "short_name": "SponsorBlock", - "version": "5.11.2", + "version": "5.11.3", "default_locale": "en", "description": "__MSG_Description__", "homepage_url": "https://sponsor.ajay.app", From eb61ad76c153fa8d5623bfc42c332a3cdd41c43f Mon Sep 17 00:00:00 2001 From: Ajay Date: Wed, 22 Jan 2025 14:17:04 -0500 Subject: [PATCH 11/26] Add extension name to storage error message --- maze-utils | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/maze-utils b/maze-utils index a1e6ea7c..67799eeb 160000 --- a/maze-utils +++ b/maze-utils @@ -1 +1 @@ -Subproject commit a1e6ea7c60dfb2fde7b06be210df51f1dd836e85 +Subproject commit 67799eebf03238a999e24de1ce9bddcb919b7c99 From 6965279d367907f58ce7d06e9f492bd2765ee31e Mon Sep 17 00:00:00 2001 From: Ajay Date: Wed, 22 Jan 2025 14:17:15 -0500 Subject: [PATCH 12/26] bump version --- manifest/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manifest/manifest.json b/manifest/manifest.json index 73530f47..9cc12249 100644 --- a/manifest/manifest.json +++ b/manifest/manifest.json @@ -1,7 +1,7 @@ { "name": "__MSG_fullName__", "short_name": "SponsorBlock", - "version": "5.11.3", + "version": "5.11.4", "default_locale": "en", "description": "__MSG_Description__", "homepage_url": "https://sponsor.ajay.app", From c3cbc44d2897221bcb41ff6f02c0bfb56d6a6640 Mon Sep 17 00:00:00 2001 From: Ajay Date: Thu, 23 Jan 2025 05:18:49 -0500 Subject: [PATCH 13/26] Fix hiding segments not working on videos with YouTube chapters Fixes #2194 --- src/utils.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/utils.ts b/src/utils.ts index 6c646a7b..1a20209c 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -199,7 +199,7 @@ export default class Utils { getSponsorIndexFromUUID(sponsorTimes: SponsorTime[], UUID: string): number { for (let i = 0; i < sponsorTimes.length; i++) { - if (sponsorTimes[i].UUID.startsWith(UUID) || UUID.startsWith(sponsorTimes[i].UUID)) { + if (sponsorTimes[i].UUID && (sponsorTimes[i].UUID.startsWith(UUID) || UUID.startsWith(sponsorTimes[i].UUID))) { return i; } } @@ -320,6 +320,7 @@ export default class Utils { allDownvotes[hashedVideoID] = currentVideoData; } + console.log(allDownvotes) const entries = Object.entries(allDownvotes); if (entries.length > 10000) { From 5c7e3b5cb3f5ed0aa65771d27b5b9c8721be2335 Mon Sep 17 00:00:00 2001 From: Ajay Date: Thu, 23 Jan 2025 05:19:10 -0500 Subject: [PATCH 14/26] bump version --- manifest/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manifest/manifest.json b/manifest/manifest.json index 9cc12249..aea11c66 100644 --- a/manifest/manifest.json +++ b/manifest/manifest.json @@ -1,7 +1,7 @@ { "name": "__MSG_fullName__", "short_name": "SponsorBlock", - "version": "5.11.4", + "version": "5.11.5", "default_locale": "en", "description": "__MSG_Description__", "homepage_url": "https://sponsor.ajay.app", From 19efcb5a98477e42347c0deac69bc957b0c8101a Mon Sep 17 00:00:00 2001 From: Ajay Date: Sun, 2 Feb 2025 22:17:51 -0500 Subject: [PATCH 15/26] Handle video being null in skip notice Resolves #2201 --- src/components/SkipNoticeComponent.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/SkipNoticeComponent.tsx b/src/components/SkipNoticeComponent.tsx index d30ae4d4..cb1217a7 100644 --- a/src/components/SkipNoticeComponent.tsx +++ b/src/components/SkipNoticeComponent.tsx @@ -697,7 +697,7 @@ class SkipNoticeComponent extends React.Component number { return () => { const sponsorTime = this.segments[index]; - const duration = Math.round((sponsorTime.segment[1] - getCurrentTime()) * (1 / getVideo().playbackRate)); + const duration = Math.round((sponsorTime.segment[1] - getCurrentTime()) * (1 / (getVideo()?.playbackRate ?? 1))); return Math.max(duration, Config.config.skipNoticeDuration); }; From c9c02e91ff00519134c2a1d5a5a6a014c13c2107 Mon Sep 17 00:00:00 2001 From: gosha305 Date: Mon, 10 Feb 2025 01:28:22 +0100 Subject: [PATCH 16/26] Added keybinds to vote on the last segment Added keybinds to vote on the last segment fixed Upvote/Downvote keybind message variable names to match others in that options section --- public/options/options.html | 10 ++++++++++ src/components/options/KeybindDialogComponent.tsx | 4 +++- src/config.ts | 4 ++++ src/content.ts | 10 ++++++++++ 4 files changed, 27 insertions(+), 1 deletion(-) diff --git a/public/options/options.html b/public/options/options.html index 9bb6b40c..43e73b60 100644 --- a/public/options/options.html +++ b/public/options/options.html @@ -472,6 +472,16 @@
+
+ +
+
+ +
+ +
+
+