mirror of
https://github.com/ajayyy/SponsorBlock.git
synced 2025-12-08 12:37:05 +03:00
Added preview bar to mobile
This commit is contained in:
128
src/content.ts
128
src/content.ts
@@ -30,6 +30,7 @@ var sponsorSkipped = [];
|
|||||||
var video: HTMLVideoElement;
|
var video: HTMLVideoElement;
|
||||||
|
|
||||||
var onInvidious;
|
var onInvidious;
|
||||||
|
var onMobileYouTube;
|
||||||
|
|
||||||
//the video id of the last preview bar update
|
//the video id of the last preview bar update
|
||||||
var lastPreviewBarUpdate;
|
var lastPreviewBarUpdate;
|
||||||
@@ -47,7 +48,7 @@ var title;
|
|||||||
var channelWhitelisted = false;
|
var channelWhitelisted = false;
|
||||||
|
|
||||||
// create preview bar
|
// create preview bar
|
||||||
var previewBar = null;
|
var previewBar: PreviewBar = null;
|
||||||
|
|
||||||
// When not null, a sponsor is currently being previewed and auto skip should be enabled.
|
// When not null, a sponsor is currently being previewed and auto skip should be enabled.
|
||||||
// This is set to a timeout function when that happens that will reset it after 3 seconds.
|
// This is set to a timeout function when that happens that will reset it after 3 seconds.
|
||||||
@@ -278,26 +279,19 @@ async function videoIDChange(id) {
|
|||||||
channelIDPromise.then(() => channelIDPromise.isFulfilled = true).catch(() => channelIDPromise.isRejected = true);
|
channelIDPromise.then(() => channelIDPromise.isFulfilled = true).catch(() => channelIDPromise.isRejected = true);
|
||||||
|
|
||||||
//setup the preview bar
|
//setup the preview bar
|
||||||
if (previewBar == null) {
|
if (previewBar === null) {
|
||||||
//create it
|
if (onMobileYouTube) {
|
||||||
utils.wait(getControls).then(result => {
|
// Mobile YouTube workaround
|
||||||
const progressElementSelectors = [
|
const observer = new MutationObserver(handleMobileControlsMutations);
|
||||||
// For YouTube
|
|
||||||
"ytp-progress-bar-container",
|
|
||||||
"no-model cue-range-markers",
|
|
||||||
// For Invidious/VideoJS
|
|
||||||
"vjs-progress-holder"
|
|
||||||
];
|
|
||||||
|
|
||||||
for (const selector of progressElementSelectors) {
|
observer.observe(document.getElementById("player-control-container"), {
|
||||||
const el = document.getElementsByClassName(selector);
|
attributes: true,
|
||||||
|
childList: true,
|
||||||
if (el && el.length && el[0]) {
|
subtree: true
|
||||||
previewBar = new PreviewBar(el[0]);
|
});
|
||||||
break;
|
} else {
|
||||||
}
|
utils.wait(getControls).then(createPreviewBar);
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//warn them if they had unsubmitted times
|
//warn them if they had unsubmitted times
|
||||||
@@ -361,6 +355,56 @@ async function videoIDChange(id) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleMobileControlsMutations(): void {
|
||||||
|
let mobileYouTubeSelector = ".progress-bar-background";
|
||||||
|
|
||||||
|
if (previewBar !== null) {
|
||||||
|
if (document.body.contains(previewBar.container)) {
|
||||||
|
updatePreviewBarPositionMobile(document.getElementsByClassName(mobileYouTubeSelector)[0]);
|
||||||
|
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
// The container does not exist anymore, remove that old preview bar
|
||||||
|
previewBar.remove();
|
||||||
|
previewBar = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the preview bar if needed (the function hasn't returned yet)
|
||||||
|
createPreviewBar();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a preview bar on the video
|
||||||
|
*/
|
||||||
|
function createPreviewBar(): void {
|
||||||
|
if (previewBar !== null) return;
|
||||||
|
|
||||||
|
const progressElementSelectors = [
|
||||||
|
// For mobile YouTube
|
||||||
|
".progress-bar-background",
|
||||||
|
// For YouTube
|
||||||
|
".ytp-progress-bar-container",
|
||||||
|
".no-model.cue-range-markers",
|
||||||
|
// For Invidious/VideoJS
|
||||||
|
".vjs-progress-holder"
|
||||||
|
];
|
||||||
|
|
||||||
|
for (const selector of progressElementSelectors) {
|
||||||
|
const el = document.querySelectorAll(selector);
|
||||||
|
|
||||||
|
if (el && el.length && el[0]) {
|
||||||
|
console.log(selector)
|
||||||
|
|
||||||
|
previewBar = new PreviewBar(el[0], onMobileYouTube);
|
||||||
|
|
||||||
|
updatePreviewBar();
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function sponsorsLookup(id: string, channelIDPromise?) {
|
function sponsorsLookup(id: string, channelIDPromise?) {
|
||||||
|
|
||||||
video = document.querySelector('video') // Youtube video player
|
video = document.querySelector('video') // Youtube video player
|
||||||
@@ -499,6 +543,8 @@ function getYouTubeVideoID(url: string) {
|
|||||||
// Check if valid hostname
|
// Check if valid hostname
|
||||||
if (Config.config && Config.config.invidiousInstances.includes(urlObject.host)) {
|
if (Config.config && Config.config.invidiousInstances.includes(urlObject.host)) {
|
||||||
onInvidious = true;
|
onInvidious = true;
|
||||||
|
} else if (urlObject.host === "m.youtube.com") {
|
||||||
|
onMobileYouTube = true;
|
||||||
} else if (!["m.youtube.com", "www.youtube.com", "www.youtube-nocookie.com"].includes(urlObject.host)) {
|
} else if (!["m.youtube.com", "www.youtube.com", "www.youtube-nocookie.com"].includes(urlObject.host)) {
|
||||||
if (!Config.config) {
|
if (!Config.config) {
|
||||||
// Call this later, in case this is an Invidious tab
|
// Call this later, in case this is an Invidious tab
|
||||||
@@ -572,6 +618,15 @@ function getChannelID() {
|
|||||||
channelWhitelisted = false;
|
channelWhitelisted = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function is required on mobile YouTube and will keep getting called whenever the preview bar disapears
|
||||||
|
*/
|
||||||
|
async function updatePreviewBarPositionMobile(parent: Element) {
|
||||||
|
if (document.getElementById("previewbar") === null) {
|
||||||
|
previewBar.updatePosition(parent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function updatePreviewBar() {
|
function updatePreviewBar() {
|
||||||
let localSponsorTimes = sponsorTimes;
|
let localSponsorTimes = sponsorTimes;
|
||||||
if (localSponsorTimes == null) localSponsorTimes = [];
|
if (localSponsorTimes == null) localSponsorTimes = [];
|
||||||
@@ -750,16 +805,25 @@ function createButton(baseID, title, callback, imageName, isDraggable=false) {
|
|||||||
controls.prepend(newButton);
|
controls.prepend(newButton);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getControls() {
|
function getControls(): HTMLElement | boolean {
|
||||||
let controls = document.getElementsByClassName("ytp-right-controls");
|
let controlsSelectors = [
|
||||||
|
// YouTube
|
||||||
|
".ytp-right-controls",
|
||||||
|
// Mobile YouTube
|
||||||
|
"#player-control-overlay",
|
||||||
|
// Invidious/videojs video element's controls element
|
||||||
|
".vjs-control-bar"
|
||||||
|
]
|
||||||
|
|
||||||
if (!controls || controls.length === 0) {
|
for (const controlsSelector of controlsSelectors) {
|
||||||
// The invidious video element's controls element
|
let controls = document.querySelectorAll(controlsSelector);
|
||||||
controls = document.getElementsByClassName("vjs-control-bar");
|
|
||||||
return (!controls || controls.length === 0) ? false : controls[controls.length - 1];
|
if (controls && controls.length > 0) {
|
||||||
} else {
|
return <HTMLElement> controls[controls.length - 1];
|
||||||
return controls[controls.length - 1];
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
//adds all the player controls buttons
|
//adds all the player controls buttons
|
||||||
@@ -782,7 +846,7 @@ async function updateVisibilityOfPlayerControlsButton() {
|
|||||||
|
|
||||||
await createButtons();
|
await createButtons();
|
||||||
|
|
||||||
if (Config.config.hideVideoPlayerControls || onInvidious) {
|
if (Config.config.hideVideoPlayerControls || onInvidious || onMobileYouTube) {
|
||||||
document.getElementById("startSponsorButton").style.display = "none";
|
document.getElementById("startSponsorButton").style.display = "none";
|
||||||
document.getElementById("submitButton").style.display = "none";
|
document.getElementById("submitButton").style.display = "none";
|
||||||
} else {
|
} else {
|
||||||
@@ -790,13 +854,13 @@ async function updateVisibilityOfPlayerControlsButton() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//don't show the info button on embeds
|
//don't show the info button on embeds
|
||||||
if (Config.config.hideInfoButtonPlayerControls || document.URL.includes("/embed/") || onInvidious) {
|
if (Config.config.hideInfoButtonPlayerControls || document.URL.includes("/embed/") || onInvidious || onMobileYouTube) {
|
||||||
document.getElementById("infoButton").style.display = "none";
|
document.getElementById("infoButton").style.display = "none";
|
||||||
} else {
|
} else {
|
||||||
document.getElementById("infoButton").style.removeProperty("display");
|
document.getElementById("infoButton").style.removeProperty("display");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Config.config.hideDeleteButtonPlayerControls || onInvidious) {
|
if (Config.config.hideDeleteButtonPlayerControls || onInvidious || onMobileYouTube) {
|
||||||
document.getElementById("deleteButton").style.display = "none";
|
document.getElementById("deleteButton").style.display = "none";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -848,7 +912,7 @@ async function changeStartSponsorButton(showStartSponsor, uploadButtonVisible) {
|
|||||||
await utils.wait(isSubmitButtonLoaded);
|
await utils.wait(isSubmitButtonLoaded);
|
||||||
|
|
||||||
//if it isn't visible, there is no data
|
//if it isn't visible, there is no data
|
||||||
let shouldHide = (uploadButtonVisible && !(Config.config.hideDeleteButtonPlayerControls || onInvidious)) ? "unset" : "none"
|
let shouldHide = (uploadButtonVisible && !(Config.config.hideDeleteButtonPlayerControls || onInvidious || onMobileYouTube)) ? "unset" : "none"
|
||||||
document.getElementById("deleteButton").style.display = shouldHide;
|
document.getElementById("deleteButton").style.display = shouldHide;
|
||||||
|
|
||||||
if (showStartSponsor) {
|
if (showStartSponsor) {
|
||||||
|
|||||||
@@ -23,19 +23,29 @@ let barTypes = {
|
|||||||
class PreviewBar {
|
class PreviewBar {
|
||||||
container: HTMLUListElement;
|
container: HTMLUListElement;
|
||||||
parent: any;
|
parent: any;
|
||||||
|
onMobileYouTube: boolean;
|
||||||
|
|
||||||
constructor(parent) {
|
constructor(parent, onMobileYouTube) {
|
||||||
this.container = document.createElement('ul');
|
this.container = document.createElement('ul');
|
||||||
this.container.id = 'previewbar';
|
this.container.id = 'previewbar';
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
|
|
||||||
this.updatePosition();
|
this.onMobileYouTube = onMobileYouTube;
|
||||||
|
|
||||||
|
this.updatePosition(parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
updatePosition() {
|
updatePosition(parent) {
|
||||||
//below the seek bar
|
//below the seek bar
|
||||||
// this.parent.insertAdjacentElement("afterEnd", this.container);
|
// this.parent.insertAdjacentElement("afterEnd", this.container);
|
||||||
|
|
||||||
|
this.parent = parent;
|
||||||
|
|
||||||
|
if (this.onMobileYouTube) {
|
||||||
|
parent.style.backgroundColor = "rgba(255, 255, 255, 0.3)";
|
||||||
|
parent.style.opacity = "1";
|
||||||
|
}
|
||||||
|
|
||||||
//on the seek bar
|
//on the seek bar
|
||||||
this.parent.insertAdjacentElement("afterBegin", this.container);
|
this.parent.insertAdjacentElement("afterBegin", this.container);
|
||||||
}
|
}
|
||||||
@@ -70,7 +80,7 @@ class PreviewBar {
|
|||||||
bar.setAttribute('data-vs-segment-type', types[i]);
|
bar.setAttribute('data-vs-segment-type', types[i]);
|
||||||
|
|
||||||
bar.style.backgroundColor = barTypes[types[i]].color;
|
bar.style.backgroundColor = barTypes[types[i]].color;
|
||||||
bar.style.opacity = barTypes[types[i]].opacity;
|
if (!this.onMobileYouTube) bar.style.opacity = barTypes[types[i]].opacity;
|
||||||
bar.style.width = width + '%';
|
bar.style.width = width + '%';
|
||||||
bar.style.left = (timestamps[i][0] / duration * 100) + "%";
|
bar.style.left = (timestamps[i][0] / duration * 100) + "%";
|
||||||
bar.style.position = "absolute"
|
bar.style.position = "absolute"
|
||||||
|
|||||||
Reference in New Issue
Block a user