Fix skipping and preview bar on "add to queue", miniplayer and hover preview

Fixes #1486
This commit is contained in:
Ajay 2024-05-24 03:15:58 -04:00
parent e8a82eddca
commit a6695254b6
4 changed files with 150 additions and 82 deletions

@ -1 +1 @@
Subproject commit 036086403f675b8fea0e22065f26ba534e351562 Subproject commit 6212c29b9e86c9b06835f44882514fde454b357e

View file

@ -26,6 +26,11 @@
transition: transform .1s cubic-bezier(0,0,0.2,1); transition: transform .1s cubic-bezier(0,0,0.2,1);
} }
/* May 2024 hover preview */
.YtPlayerProgressBarProgressBar #previewbar {
transform: none;
}
.ytp-big-mode #previewbar { .ytp-big-mode #previewbar {
transform: scaleY(0.625) translateY(-30%) translateY(1.5px); transform: scaleY(0.625) translateY(-30%) translateY(1.5px);
} }

View file

@ -34,7 +34,7 @@ import { ChapterVote } from "./render/ChapterVote";
import { openWarningDialog } from "./utils/warnings"; import { openWarningDialog } from "./utils/warnings";
import { isFirefoxOrSafari, waitFor } from "../maze-utils/src"; import { isFirefoxOrSafari, waitFor } from "../maze-utils/src";
import { getErrorMessage, getFormattedTime } from "../maze-utils/src/formating"; import { getErrorMessage, getFormattedTime } from "../maze-utils/src/formating";
import { getChannelIDInfo, getVideo, getIsAdPlaying, getIsLivePremiere, setIsAdPlaying, checkVideoIDChange, getVideoID, getYouTubeVideoID, setupVideoModule, checkIfNewVideoID, isOnInvidious, isOnMobileYouTube } from "../maze-utils/src/video"; import { getChannelIDInfo, getVideo, getIsAdPlaying, getIsLivePremiere, setIsAdPlaying, checkVideoIDChange, getVideoID, getYouTubeVideoID, setupVideoModule, checkIfNewVideoID, isOnInvidious, isOnMobileYouTube, parseYouTubeVideoIDFromURL, getLastNonInlineVideoID, triggerVideoIDChange, triggerVideoElementChange, getIsInline } from "../maze-utils/src/video";
import { Keybind, StorageChangesObject, isSafari, keybindEquals, keybindToString } from "../maze-utils/src/config"; import { Keybind, StorageChangesObject, isSafari, keybindEquals, keybindToString } from "../maze-utils/src/config";
import { findValidElement } from "../maze-utils/src/dom" import { findValidElement } from "../maze-utils/src/dom"
import { getHash, HashedValue } from "../maze-utils/src/hash"; import { getHash, HashedValue } from "../maze-utils/src/hash";
@ -49,6 +49,7 @@ import { hideDeArrowPromotion, tryShowingDeArrowPromotion } from "./dearrowPromo
import { asyncRequestToServer } from "./utils/requests"; import { asyncRequestToServer } from "./utils/requests";
import { isMobileControlsOpen } from "./utils/mobileUtils"; import { isMobileControlsOpen } from "./utils/mobileUtils";
import { defaultPreviewTime } from "./utils/constants"; import { defaultPreviewTime } from "./utils/constants";
import { onVideoPage } from "../maze-utils/src/pageInfo";
cleanPage(); cleanPage();
@ -72,6 +73,8 @@ let sponsorDataFound = false;
let sponsorTimes: SponsorTime[] = []; let sponsorTimes: SponsorTime[] = [];
let existingChaptersImported = false; let existingChaptersImported = false;
let importingChaptersWaitingForFocus = false; let importingChaptersWaitingForFocus = false;
let importingChaptersWaiting = false;
let triedImportingChapters = false;
// List of open skip notices // List of open skip notices
const skipNotices: SkipNotice[] = []; const skipNotices: SkipNotice[] = [];
let activeSkipKeybindElement: ToggleSkippable = null; let activeSkipKeybindElement: ToggleSkippable = null;
@ -168,7 +171,6 @@ let submissionNotice: SubmissionNotice = null;
let lastResponseStatus: number; let lastResponseStatus: number;
let retryCount = 0; let retryCount = 0;
let lookupWaiting = false;
// Contains all of the functions and variables needed by the skip notice // Contains all of the functions and variables needed by the skip notice
const skipNoticeContentContainer: ContentContainer = () => ({ const skipNoticeContentContainer: ContentContainer = () => ({
@ -384,6 +386,7 @@ function resetValues() {
sponsorTimes = []; sponsorTimes = [];
existingChaptersImported = false; existingChaptersImported = false;
triedImportingChapters = false;
sponsorSkipped = []; sponsorSkipped = [];
lastResponseStatus = 0; lastResponseStatus = 0;
shownSegmentFailedToFetchWarning = false; shownSegmentFailedToFetchWarning = false;
@ -400,8 +403,9 @@ function resetValues() {
//reset sponsor data found check //reset sponsor data found check
sponsorDataFound = false; sponsorDataFound = false;
if (switchingVideos === null) {
// When first loading a video, it is not switching videos // When first loading a video, it is not switching videos
// Hover play also doesn't need this check
if (switchingVideos === null || !onVideoPage()) {
switchingVideos = false; switchingVideos = false;
} else { } else {
switchingVideos = true; switchingVideos = true;
@ -458,6 +462,17 @@ function videoIDChange(): void {
updateSponsorTimesSubmitting(); updateSponsorTimesSubmitting();
tryShowingDeArrowPromotion().catch(logWarn); tryShowingDeArrowPromotion().catch(logWarn);
checkPreviewbarState();
if (getIsInline()) {
// Hover preview progress bar can take some time to appear
// and if the miniplayer is also active then it would
// attach to the wrong one
setTimeout(checkPreviewbarState, 500);
setTimeout(checkPreviewbarState, 1000);
setTimeout(checkPreviewbarState, 3000);
}
} }
function handleMobileControlsMutations(): void { function handleMobileControlsMutations(): void {
@ -486,12 +501,7 @@ function handleMobileControlsMutations(): void {
createPreviewBar(); createPreviewBar();
} }
/** function getPreviewBarAttachElement(): HTMLElement | null {
* Creates a preview bar on the video
*/
function createPreviewBar(): void {
if (previewBar !== null) return;
const progressElementOptions = [{ const progressElementOptions = [{
// For new mobile YouTube (#1287) // For new mobile YouTube (#1287)
selector: ".progress-bar-line", selector: ".progress-bar-line",
@ -501,11 +511,18 @@ function createPreviewBar(): void {
selector: ".YtProgressBarProgressBarLine", selector: ".YtProgressBarProgressBarLine",
isVisibleCheck: true isVisibleCheck: true
}, { }, {
// For Desktop YouTube // For desktop YouTube hover play
// Priority is given to the hover play progress bar over the main progress bar
// for miniplayer + hover preview case
// Second is new hover play selector
selector: "#video-preview .ytp-progress-bar, #video-preview .YtProgressBarLineHost",
isVisibleCheck: true
}, {
// For desktop YouTube
selector: ".ytp-progress-bar", selector: ".ytp-progress-bar",
isVisibleCheck: true isVisibleCheck: true
}, { }, {
// For Desktop YouTube // For desktop YouTube
selector: ".no-model.cue-range-marker", selector: ".no-model.cue-range-marker",
isVisibleCheck: true isVisibleCheck: true
}, { }, {
@ -527,14 +544,27 @@ function createPreviewBar(): void {
const allElements = document.querySelectorAll(option.selector) as NodeListOf<HTMLElement>; const allElements = document.querySelectorAll(option.selector) as NodeListOf<HTMLElement>;
const el = option.isVisibleCheck ? findValidElement(allElements) : allElements[0]; const el = option.isVisibleCheck ? findValidElement(allElements) : allElements[0];
if (el) {
return el;
}
}
return null;
}
/**
* Creates a preview bar on the video
*/
function createPreviewBar(): void {
if (previewBar !== null) return;
const el = getPreviewBarAttachElement();
if (el) { if (el) {
const chapterVote = new ChapterVote(voteAsync); const chapterVote = new ChapterVote(voteAsync);
previewBar = new PreviewBar(el, isOnMobileYouTube(), isOnInvidious(), chapterVote, () => importExistingChapters(true)); previewBar = new PreviewBar(el, isOnMobileYouTube(), isOnInvidious(), chapterVote, () => importExistingChapters(true));
updatePreviewBar(); updatePreviewBar();
break;
}
} }
} }
@ -789,6 +819,8 @@ function inMuteSegment(currentTime: number, includeOverlap: boolean): boolean {
* This makes sure the videoID is still correct and if the sponsorTime is included * This makes sure the videoID is still correct and if the sponsorTime is included
*/ */
function incorrectVideoCheck(videoID?: string, sponsorTime?: SponsorTime): boolean { function incorrectVideoCheck(videoID?: string, sponsorTime?: SponsorTime): boolean {
if (!onVideoPage()) return false;
const currentVideoID = getYouTubeVideoID(); const currentVideoID = getYouTubeVideoID();
const recordedVideoID = videoID || getVideoID(); const recordedVideoID = videoID || getVideoID();
if (currentVideoID !== recordedVideoID || (sponsorTime if (currentVideoID !== recordedVideoID || (sponsorTime
@ -812,14 +844,16 @@ let playbackRateCheckInterval: NodeJS.Timeout | null = null;
let lastPlaybackSpeed = 1; let lastPlaybackSpeed = 1;
let setupVideoListenersFirstTime = true; let setupVideoListenersFirstTime = true;
function setupVideoListeners() { function setupVideoListeners() {
const video = getVideo();
//wait until it is loaded //wait until it is loaded
getVideo().addEventListener('loadstart', videoOnReadyListener) video.addEventListener('loadstart', videoOnReadyListener)
getVideo().addEventListener('durationchange', durationChangeListener); video.addEventListener('durationchange', durationChangeListener);
if (setupVideoListenersFirstTime) { if (setupVideoListenersFirstTime) {
addCleanupListener(() => { addCleanupListener(() => {
getVideo().removeEventListener('loadstart', videoOnReadyListener); video.removeEventListener('loadstart', videoOnReadyListener);
getVideo().removeEventListener('durationchange', durationChangeListener); video.removeEventListener('durationchange', durationChangeListener);
}); });
} }
@ -835,18 +869,20 @@ function setupVideoListeners() {
startSponsorSchedule(); startSponsorSchedule();
}; };
getVideo().addEventListener('ratechange', rateChangeListener); video.addEventListener('ratechange', rateChangeListener);
// Used by videospeed extension (https://github.com/igrigorik/videospeed/pull/740) // Used by videospeed extension (https://github.com/igrigorik/videospeed/pull/740)
getVideo().addEventListener('videoSpeed_ratechange', rateChangeListener); video.addEventListener('videoSpeed_ratechange', rateChangeListener);
const playListener = () => { const playListener = () => {
// If it is not the first event, then the only way to get to 0 is if there is a seek event // If it is not the first event, then the only way to get to 0 is if there is a seek event
// This check makes sure that changing the video resolution doesn't cause the extension to think it // This check makes sure that changing the video resolution doesn't cause the extension to think it
// gone back to the begining // gone back to the begining
if (getVideo().readyState <= HTMLMediaElement.HAVE_CURRENT_DATA if (video.readyState <= HTMLMediaElement.HAVE_CURRENT_DATA
&& getVideo().currentTime === 0) return; && video.currentTime === 0) return;
updateVirtualTime(); updateVirtualTime();
checkForMiniplayerPlaying();
if (switchingVideos || lastPausedAtZero) { if (switchingVideos || lastPausedAtZero) {
switchingVideos = false; switchingVideos = false;
@ -862,15 +898,15 @@ function setupVideoListeners() {
updateAdFlag(); updateAdFlag();
// Make sure it doesn't get double called with the playing event // Make sure it doesn't get double called with the playing event
if (Math.abs(lastCheckVideoTime - getVideo().currentTime) > 0.3 if (Math.abs(lastCheckVideoTime - video.currentTime) > 0.3
|| (lastCheckVideoTime !== getVideo().currentTime && Date.now() - lastCheckTime > 2000)) { || (lastCheckVideoTime !== video.currentTime && Date.now() - lastCheckTime > 2000)) {
lastCheckTime = Date.now(); lastCheckTime = Date.now();
lastCheckVideoTime = getVideo().currentTime; lastCheckVideoTime = video.currentTime;
startSponsorSchedule(); startSponsorSchedule();
} }
}; };
getVideo().addEventListener('play', playListener); video.addEventListener('play', playListener);
const playingListener = () => { const playingListener = () => {
updateVirtualTime(); updateVirtualTime();
@ -878,8 +914,8 @@ function setupVideoListeners() {
if (startedWaiting) { if (startedWaiting) {
startedWaiting = false; startedWaiting = false;
logDebug(`[SB] Playing event after buffering: ${Math.abs(lastCheckVideoTime - getVideo().currentTime) > 0.3 logDebug(`[SB] Playing event after buffering: ${Math.abs(lastCheckVideoTime - video.currentTime) > 0.3
|| (lastCheckVideoTime !== getVideo().currentTime && Date.now() - lastCheckTime > 2000)}`); || (lastCheckVideoTime !== video.currentTime && Date.now() - lastCheckTime > 2000)}`);
} }
if (switchingVideos) { if (switchingVideos) {
@ -891,63 +927,63 @@ function setupVideoListeners() {
} }
// Make sure it doesn't get double called with the play event // Make sure it doesn't get double called with the play event
if (Math.abs(lastCheckVideoTime - getVideo().currentTime) > 0.3 if (Math.abs(lastCheckVideoTime - video.currentTime) > 0.3
|| (lastCheckVideoTime !== getVideo().currentTime && Date.now() - lastCheckTime > 2000)) { || (lastCheckVideoTime !== video.currentTime && Date.now() - lastCheckTime > 2000)) {
lastCheckTime = Date.now(); lastCheckTime = Date.now();
lastCheckVideoTime = getVideo().currentTime; lastCheckVideoTime = video.currentTime;
startSponsorSchedule(); startSponsorSchedule();
} }
if (playbackRateCheckInterval) clearInterval(playbackRateCheckInterval); if (playbackRateCheckInterval) clearInterval(playbackRateCheckInterval);
lastPlaybackSpeed = getVideo().playbackRate; lastPlaybackSpeed = video.playbackRate;
// Video speed controller compatibility // Video speed controller compatibility
// That extension makes rate change events not propagate // That extension makes rate change events not propagate
if (document.body.classList.contains("vsc-initialized")) { if (document.body.classList.contains("vsc-initialized")) {
playbackRateCheckInterval = setInterval(() => { playbackRateCheckInterval = setInterval(() => {
if ((!getVideoID() || getVideo().paused) && playbackRateCheckInterval) { if ((!getVideoID() || video.paused) && playbackRateCheckInterval) {
// Video is gone, stop checking // Video is gone, stop checking
clearInterval(playbackRateCheckInterval); clearInterval(playbackRateCheckInterval);
return; return;
} }
if (getVideo().playbackRate !== lastPlaybackSpeed) { if (video.playbackRate !== lastPlaybackSpeed) {
lastPlaybackSpeed = getVideo().playbackRate; lastPlaybackSpeed = video.playbackRate;
rateChangeListener(); rateChangeListener();
} }
}, 2000); }, 2000);
} }
}; };
getVideo().addEventListener('playing', playingListener); video.addEventListener('playing', playingListener);
const seekingListener = () => { const seekingListener = () => {
lastKnownVideoTime.fromPause = false; lastKnownVideoTime.fromPause = false;
if (!getVideo().paused){ if (!video.paused){
// Reset lastCheckVideoTime // Reset lastCheckVideoTime
lastCheckTime = Date.now(); lastCheckTime = Date.now();
lastCheckVideoTime = getVideo().currentTime; lastCheckVideoTime = video.currentTime;
updateVirtualTime(); updateVirtualTime();
clearWaitingTime(); clearWaitingTime();
// Sometimes looped videos loop back to almost zero, but not quite // Sometimes looped videos loop back to almost zero, but not quite
if (getVideo().loop && getVideo().currentTime < 0.2) { if (video.loop && video.currentTime < 0.2) {
startSponsorSchedule(false, 0); startSponsorSchedule(false, 0);
} else { } else {
startSponsorSchedule(); startSponsorSchedule();
} }
} else { } else {
updateActiveSegment(getVideo().currentTime); updateActiveSegment(video.currentTime);
if (getVideo().currentTime === 0) { if (video.currentTime === 0) {
lastPausedAtZero = true; lastPausedAtZero = true;
} }
} }
}; };
getVideo().addEventListener('seeking', seekingListener); video.addEventListener('seeking', seekingListener);
const stoppedPlayback = () => { const stoppedPlayback = () => {
// Reset lastCheckVideoTime // Reset lastCheckVideoTime
@ -958,7 +994,7 @@ function setupVideoListeners() {
lastKnownVideoTime.videoTime = null; lastKnownVideoTime.videoTime = null;
lastKnownVideoTime.preciseTime = null; lastKnownVideoTime.preciseTime = null;
updateWaitingTime(); updateWaitingTime(video);
cancelSponsorSchedule(); cancelSponsorSchedule();
}; };
@ -967,26 +1003,26 @@ function setupVideoListeners() {
stoppedPlayback(); stoppedPlayback();
}; };
getVideo().addEventListener('pause', pauseListener); video.addEventListener('pause', pauseListener);
const waitingListener = () => { const waitingListener = () => {
logDebug("[SB] Not skipping due to buffering"); logDebug("[SB] Not skipping due to buffering");
startedWaiting = true; startedWaiting = true;
stoppedPlayback(); stoppedPlayback();
}; };
getVideo().addEventListener('waiting', waitingListener); video.addEventListener('waiting', waitingListener);
startSponsorSchedule(); startSponsorSchedule();
if (setupVideoListenersFirstTime) { if (setupVideoListenersFirstTime) {
addCleanupListener(() => { addCleanupListener(() => {
getVideo().removeEventListener('play', playListener); video.removeEventListener('play', playListener);
getVideo().removeEventListener('playing', playingListener); video.removeEventListener('playing', playingListener);
getVideo().removeEventListener('seeking', seekingListener); video.removeEventListener('seeking', seekingListener);
getVideo().removeEventListener('ratechange', rateChangeListener); video.removeEventListener('ratechange', rateChangeListener);
getVideo().removeEventListener('videoSpeed_ratechange', rateChangeListener); video.removeEventListener('videoSpeed_ratechange', rateChangeListener);
getVideo().removeEventListener('pause', pauseListener); video.removeEventListener('pause', pauseListener);
getVideo().removeEventListener('waiting', waitingListener); video.removeEventListener('waiting', waitingListener);
if (playbackRateCheckInterval) clearInterval(playbackRateCheckInterval); if (playbackRateCheckInterval) clearInterval(playbackRateCheckInterval);
}); });
@ -1037,8 +1073,8 @@ function updateVirtualTime() {
} }
} }
function updateWaitingTime(): void { function updateWaitingTime(video: HTMLVideoElement): void {
lastTimeFromWaitingEvent = getVideo().currentTime; lastTimeFromWaitingEvent = video.currentTime;
} }
function clearWaitingTime(): void { function clearWaitingTime(): void {
@ -1072,17 +1108,6 @@ function setupCategoryPill() {
} }
async function sponsorsLookup(keepOldSubmissions = true) { async function sponsorsLookup(keepOldSubmissions = true) {
if (lookupWaiting) return;
//there is still no video here
if (!getVideo()) {
lookupWaiting = true;
setTimeout(() => {
lookupWaiting = false;
sponsorsLookup()
}, 100);
return;
}
const categories: string[] = Config.config.categorySelections.map((category) => category.name); const categories: string[] = Config.config.categorySelections.map((category) => category.name);
const extraRequestData: Record<string, unknown> = {}; const extraRequestData: Record<string, unknown> = {};
@ -1159,13 +1184,14 @@ async function sponsorsLookup(keepOldSubmissions = true) {
} }
} }
if (!getVideo()) {
//there is still no video here
await waitFor(() => getVideo(), 5000, 10);
}
startSkipScheduleCheckingForStartSponsors(); startSkipScheduleCheckingForStartSponsors();
//update the preview bar if (!isNaN(getVideo().duration)) {
//leave the type blank for now until categories are added
if (lastPreviewBarUpdate == getVideoID() || (lastPreviewBarUpdate == null && !isNaN(getVideo().duration))) {
//set it now
//otherwise the listener can handle it
updatePreviewBar(); updatePreviewBar();
} }
} else { } else {
@ -1193,10 +1219,10 @@ async function sponsorsLookup(keepOldSubmissions = true) {
} }
function importExistingChapters(wait: boolean) { function importExistingChapters(wait: boolean) {
if (!existingChaptersImported) { if (!existingChaptersImported && !importingChaptersWaiting && !triedImportingChapters && onVideoPage() && !isOnMobileYouTube()) {
const waitCondition = () => getVideo()?.duration && getExistingChapters(getVideoID(), getVideo().duration); const waitCondition = () => getVideo()?.duration && getExistingChapters(getVideoID(), getVideo().duration);
if (!waitCondition() && wait && !document.hasFocus() && !importingChaptersWaitingForFocus) { if (wait && !document.hasFocus() && !importingChaptersWaitingForFocus && !waitCondition()) {
importingChaptersWaitingForFocus = true; importingChaptersWaitingForFocus = true;
const listener = () => { const listener = () => {
importExistingChapters(wait); importExistingChapters(wait);
@ -1204,14 +1230,17 @@ function importExistingChapters(wait: boolean) {
}; };
window.addEventListener("focus", listener); window.addEventListener("focus", listener);
} else { } else {
importingChaptersWaiting = true;
waitFor(waitCondition, waitFor(waitCondition,
wait ? 15000 : 0, 400, (c) => c?.length > 0).then((chapters) => { wait ? 15000 : 0, 400, (c) => c?.length > 0).then((chapters) => {
importingChaptersWaiting = false;
if (!existingChaptersImported && chapters?.length > 0) { if (!existingChaptersImported && chapters?.length > 0) {
sponsorTimes = (sponsorTimes ?? []).concat(...chapters).sort((a, b) => a.segment[0] - b.segment[0]); sponsorTimes = (sponsorTimes ?? []).concat(...chapters).sort((a, b) => a.segment[0] - b.segment[0]);
existingChaptersImported = true; existingChaptersImported = true;
updatePreviewBar(); updatePreviewBar();
} }
}).catch(() => {}); // eslint-disable-line @typescript-eslint/no-empty-function }).catch(() => { importingChaptersWaiting = false; triedImportingChapters = true; }); // eslint-disable-line @typescript-eslint/no-empty-function
} }
} }
} }
@ -1410,6 +1439,7 @@ function videoElementChange(newVideo: boolean): void {
setupCategoryPill(); setupCategoryPill();
} }
updatePreviewBar();
checkPreviewbarState(); checkPreviewbarState();
// Incase the page is still transitioning, check again in a few seconds // Incase the page is still transitioning, check again in a few seconds
@ -1419,8 +1449,19 @@ function videoElementChange(newVideo: boolean): void {
}) })
} }
let checkingPreviewbarAgain = false;
function checkPreviewbarState(): void { function checkPreviewbarState(): void {
if (previewBar && !utils.findReferenceNode()?.contains(previewBar.container)) { if (!getPreviewBarAttachElement() && !checkingPreviewbarAgain && getVideo() && getVideoID()) {
checkingPreviewbarAgain = true;
setTimeout(() => {
checkingPreviewbarAgain = false;
checkPreviewbarState();
}, 500);
return;
}
if (previewBar && !getPreviewBarAttachElement()?.contains(previewBar.container)) {
previewBar.remove(); previewBar.remove();
previewBar = null; previewBar = null;
} }
@ -2676,3 +2717,22 @@ function setCategoryColorCSSVariables() {
styleContainer.innerText = css; styleContainer.innerText = css;
} }
/**
* If mini player starts playing, then videoID change might have to be called
*/
function checkForMiniplayerPlaying() {
const miniPlayerUI = document.querySelector(".miniplayer") as HTMLElement;
if (!onVideoPage() && isVisible(miniPlayerUI)) {
const videoID = getLastNonInlineVideoID();
if (videoID) {
triggerVideoIDChange(videoID);
// treat as if video element has changed
const video = miniPlayerUI.querySelector("video") as HTMLVideoElement;
if (video && getVideo() !== video) {
triggerVideoElementChange(video);
}
}
}
}

View file

@ -13,6 +13,7 @@ import { DEFAULT_CATEGORY, shortCategoryName } from "../utils/categoryUtils";
import { normalizeChapterName } from "../utils/exporter"; import { normalizeChapterName } from "../utils/exporter";
import { findValidElement } from "../../maze-utils/src/dom"; import { findValidElement } from "../../maze-utils/src/dom";
import { addCleanupListener } from "../../maze-utils/src/cleanup"; import { addCleanupListener } from "../../maze-utils/src/cleanup";
import { isVisible } from "../utils/pageUtils";
const TOOLTIP_VISIBLE_CLASS = 'sponsorCategoryTooltipVisible'; const TOOLTIP_VISIBLE_CLASS = 'sponsorCategoryTooltipVisible';
const MIN_CHAPTER_SIZE = 0.003; const MIN_CHAPTER_SIZE = 0.003;
@ -225,10 +226,12 @@ class PreviewBar {
this.segments = segments ?? []; this.segments = segments ?? [];
this.videoDuration = videoDuration ?? 0; this.videoDuration = videoDuration ?? 0;
this.updatePageElements(); this.updatePageElements();
// Sometimes video duration is inaccurate, pull from accessibility info // Sometimes video duration is inaccurate, pull from accessibility info
const ariaDuration = parseInt(this.progressBar?.getAttribute('aria-valuemax')) ?? 0; const ariaDuration = parseInt(this.progressBar?.getAttribute('aria-valuemax')) ?? 0;
if (ariaDuration && Math.abs(ariaDuration - this.videoDuration) > 3) { const multipleActiveVideos = [...document.querySelectorAll("video")].filter((v) => isVisible(v)).length > 1;
if (!multipleActiveVideos && ariaDuration && Math.abs(ariaDuration - this.videoDuration) > 3) {
this.videoDuration = ariaDuration; this.videoDuration = ariaDuration;
} }
@ -236,7 +239,7 @@ class PreviewBar {
} }
private updatePageElements(): void { private updatePageElements(): void {
const allProgressBars = document.querySelectorAll('.ytp-progress-bar') as NodeListOf<HTMLElement>; const allProgressBars = document.querySelectorAll(".ytp-progress-bar") as NodeListOf<HTMLElement>;
this.progressBar = findValidElement(allProgressBars) ?? allProgressBars?.[0]; this.progressBar = findValidElement(allProgressBars) ?? allProgressBars?.[0];
if (this.progressBar) { if (this.progressBar) {