diff options
author | Ajay <[email protected]> | 2024-01-21 20:35:00 -0500 |
---|---|---|
committer | Ajay <[email protected]> | 2024-01-21 20:35:00 -0500 |
commit | 1f96e3b1174b27cc75c7bdd79e5f1c9116e9b108 (patch) | |
tree | 7ee2a1573b23a430fdcaf04022a6bfc17eeeba53 /src | |
parent | b3b5d46e4eb34fd087f9bf4f674e7f83a4ba4061 (diff) | |
download | SponsorBlock-1f96e3b1174b27cc75c7bdd79e5f1c9116e9b108.tar.gz SponsorBlock-1f96e3b1174b27cc75c7bdd79e5f1c9116e9b108.zip |
Improve precision of hover preview
Also fixes issue with YouTube "most-replayed" messing it up
Diffstat (limited to 'src')
-rw-r--r-- | src/js-components/previewBar.ts | 72 |
1 files changed, 30 insertions, 42 deletions
diff --git a/src/js-components/previewBar.ts b/src/js-components/previewBar.ts index a2522f08..ff498a28 100644 --- a/src/js-components/previewBar.ts +++ b/src/js-components/previewBar.ts @@ -11,7 +11,6 @@ import { ActionType, Category, SegmentContainer, SponsorHideType, SponsorSourceT import { partition } from "../utils/arrayUtils"; import { DEFAULT_CATEGORY, shortCategoryName } from "../utils/categoryUtils"; import { normalizeChapterName } from "../utils/exporter"; -import { getFormattedTimeToSeconds } from "../../maze-utils/src/formating"; import { findValidElement } from "../../maze-utils/src/dom"; import { addCleanupListener } from "../../maze-utils/src/cleanup"; @@ -125,34 +124,11 @@ class PreviewBar { mouseOnSeekBar = false; }); - const observer = new MutationObserver((mutations) => { + seekBar.addEventListener("mousemove", (e: MouseEvent) => { if (!mouseOnSeekBar || !this.categoryTooltip || !this.categoryTooltipContainer) return; - // Only care about mutations to time tooltip - if (!mutations.some((mutation) => (mutation.target as HTMLElement).classList.contains("ytp-tooltip-text"))) { - return; - } - - const tooltipTextElements = tooltipTextWrapper.querySelectorAll(".ytp-tooltip-text"); - let timeInSeconds: number | null = null; - let noYoutubeChapters = false; - - for (const tooltipTextElement of tooltipTextElements) { - if (tooltipTextElement.classList.contains('ytp-tooltip-text-no-title')) noYoutubeChapters = true; - - const tooltipText = tooltipTextElement.textContent; - if (tooltipText === null || tooltipText.length === 0) continue; - - timeInSeconds = getFormattedTimeToSeconds(tooltipText); - - if (timeInSeconds !== null) break; - } - - if (timeInSeconds === null) { - originalTooltip.style.removeProperty("display"); - - return; - } + let noYoutubeChapters = !!tooltipTextWrapper.querySelector(".ytp-tooltip-text.ytp-tooltip-text-no-title"); + const timeInSeconds = this.decimalToTime((e.clientX - seekBar.getBoundingClientRect().x) / seekBar.clientWidth); // Find the segment at that location, using the shortest if multiple found const [normalSegments, chapterSegments] = @@ -198,15 +174,6 @@ class PreviewBar { this.chapterTooltip.style.textAlign = titleTooltip.style.textAlign; } }); - - observer.observe(tooltipTextWrapper, { - childList: true, - subtree: true, - }); - - addCleanupListener(() => { - observer.disconnect(); - }); } private setTooltipTitle(segment: PreviewBarSegment, tooltip: HTMLElement): void { @@ -920,6 +887,17 @@ class PreviewBar { } timeToDecimal(time: number): number { + return this.decimalTimeConverter(time, true); + } + + decimalToTime(decimal: number): number { + return this.decimalTimeConverter(decimal, false); + } + + /** + * Decimal to time or time to decimal + */ + decimalTimeConverter(value: number, isTime: boolean): number { if (this.originalChapterBarBlocks?.length > 1 && this.existingChapters.length === this.originalChapterBarBlocks?.length) { // Parent element to still work when display: none const totalPixels = this.originalChapterBar.parentElement.clientWidth; @@ -929,8 +907,9 @@ class PreviewBar { const chapterElement = this.originalChapterBarBlocks[i]; const widthPixels = parseFloat(chapterElement.style.width.replace("px", "")); - if (time >= this.existingChapters[i].segment[1]) { - const marginPixels = chapterElement.style.marginRight ? parseFloat(chapterElement.style.marginRight.replace("px", "")) : 0; + const marginPixels = chapterElement.style.marginRight ? parseFloat(chapterElement.style.marginRight.replace("px", "")) : 0; + if ((isTime && value >= this.existingChapters[i].segment[1]) + || (!isTime && value >= (pixelOffset + widthPixels + marginPixels) / totalPixels)) { pixelOffset += widthPixels + marginPixels; lastCheckedChapter = i; } else { @@ -944,13 +923,22 @@ class PreviewBar { const latestWidth = parseFloat(this.originalChapterBarBlocks[lastCheckedChapter + 1].style.width.replace("px", "")); const latestChapterDuration = latestChapter.segment[1] - latestChapter.segment[0]; - const percentageInCurrentChapter = (time - latestChapter.segment[0]) / latestChapterDuration; - const sizeOfCurrentChapter = latestWidth / totalPixels; - return Math.min(1, ((pixelOffset / totalPixels) + (percentageInCurrentChapter * sizeOfCurrentChapter))); + if (isTime) { + const percentageInCurrentChapter = (value - latestChapter.segment[0]) / latestChapterDuration; + const sizeOfCurrentChapter = latestWidth / totalPixels; + return Math.min(1, ((pixelOffset / totalPixels) + (percentageInCurrentChapter * sizeOfCurrentChapter))); + } else { + const percentageInCurrentChapter = (value * totalPixels - pixelOffset) / latestWidth; + return Math.max(0, latestChapter.segment[0] + (percentageInCurrentChapter * latestChapterDuration)); + } } } - return Math.min(1, time / this.videoDuration); + if (isTime) { + return Math.min(1, value / this.videoDuration); + } else { + return Math.max(0, value * this.videoDuration); + } } /* |