init
This commit is contained in:
commit
6e9e14a817
3 changed files with 149 additions and 0 deletions
11
background.js
Normal file
11
background.js
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
// Strip CSP headers from Yandex Music responses so our video can load
|
||||||
|
browser.webRequest.onHeadersReceived.addListener(
|
||||||
|
(details) => {
|
||||||
|
const headers = details.responseHeaders.filter(
|
||||||
|
(h) => !["content-security-policy", "x-content-security-policy"].includes(h.name.toLowerCase())
|
||||||
|
);
|
||||||
|
return { responseHeaders: headers };
|
||||||
|
},
|
||||||
|
{ urls: ["*://music.yandex.ru/*", "*://music.yandex.com/*"] },
|
||||||
|
["blocking", "responseHeaders"]
|
||||||
|
);
|
||||||
111
content.js
Normal file
111
content.js
Normal file
|
|
@ -0,0 +1,111 @@
|
||||||
|
const VIDEOS = [
|
||||||
|
"https://cdn.computernetthings.ru/nikit0s.mp4",
|
||||||
|
// "https://cdn.computernetthings.ru/video2.mp4",
|
||||||
|
];
|
||||||
|
|
||||||
|
const PHOTOS = [
|
||||||
|
"https://cdn.computernetthings.ru/ph1.jpg",
|
||||||
|
// "https://cdn.computernetthings.ru/photo2.jpg",
|
||||||
|
];
|
||||||
|
|
||||||
|
const CANVAS_SELECTOR = ".VibeWidgetAnimation_root__7fpeP > canvas:nth-child(1)";
|
||||||
|
const ROOT_SELECTOR = ".VibeWidgetAnimation_root__7fpeP";
|
||||||
|
const PLAY_INDICATOR_SELECTOR = ".VibeResetButton_root__ju8pE";
|
||||||
|
|
||||||
|
let container = null;
|
||||||
|
let currentEl = null;
|
||||||
|
|
||||||
|
function random(arr) {
|
||||||
|
return arr[Math.floor(Math.random() * arr.length)];
|
||||||
|
}
|
||||||
|
|
||||||
|
function elStyle(width, height) {
|
||||||
|
return `display:block;width:${width}px;height:${height}px;object-fit:cover;pointer-events:none;`;
|
||||||
|
// return `display:block;width:100%;height:100%;object-fit:cover;pointer-events:none;`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function showPhoto(width, height) {
|
||||||
|
const img = document.createElement("img");
|
||||||
|
img.src = random(PHOTOS);
|
||||||
|
img.style.cssText = elStyle(width, height);
|
||||||
|
currentEl?.remove();
|
||||||
|
currentEl = img;
|
||||||
|
container.appendChild(img);
|
||||||
|
}
|
||||||
|
|
||||||
|
function showVideo(width, height) {
|
||||||
|
const video = document.createElement("video");
|
||||||
|
video.src = random(VIDEOS);
|
||||||
|
video.setAttribute("autoplay", "");
|
||||||
|
video.setAttribute("loop", "");
|
||||||
|
video.setAttribute("muted", "");
|
||||||
|
video.setAttribute("playsinline", "");
|
||||||
|
video.muted = true;
|
||||||
|
video.style.cssText = elStyle(width, height);
|
||||||
|
currentEl?.remove();
|
||||||
|
currentEl = video;
|
||||||
|
container.appendChild(video);
|
||||||
|
video.play().catch(() => {});
|
||||||
|
}
|
||||||
|
|
||||||
|
function syncFromIndicator(indicator, width, height) {
|
||||||
|
if (indicator.getAttribute("aria-hidden") === "true") {
|
||||||
|
if (PHOTOS.length > 0) {
|
||||||
|
showPhoto(width, height);
|
||||||
|
} else {
|
||||||
|
currentEl?.pause?.();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
showVideo(width, height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function watchForPlayIndicator(width, height) {
|
||||||
|
const bind = (indicator) => {
|
||||||
|
syncFromIndicator(indicator, width, height);
|
||||||
|
new MutationObserver(() => syncFromIndicator(indicator, width, height)).observe(indicator, {
|
||||||
|
attributes: true,
|
||||||
|
attributeFilter: ["aria-hidden"],
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const indicator = document.querySelector(PLAY_INDICATOR_SELECTOR);
|
||||||
|
if (indicator) {
|
||||||
|
bind(indicator);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const waitObserver = new MutationObserver(() => {
|
||||||
|
const indicator = document.querySelector(PLAY_INDICATOR_SELECTOR);
|
||||||
|
if (indicator) {
|
||||||
|
waitObserver.disconnect();
|
||||||
|
bind(indicator);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
waitObserver.observe(document.body, { childList: true, subtree: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
function replaceAnimation(canvas) {
|
||||||
|
if (canvas.dataset.customReplaced) return;
|
||||||
|
canvas.dataset.customReplaced = "true";
|
||||||
|
canvas.style.display = "none";
|
||||||
|
|
||||||
|
const { width, height } = canvas.getBoundingClientRect();
|
||||||
|
const w = width || canvas.width;
|
||||||
|
const h = height || canvas.height;
|
||||||
|
|
||||||
|
container = canvas.closest(ROOT_SELECTOR) ?? canvas.parentElement;
|
||||||
|
|
||||||
|
showVideo(w, h);
|
||||||
|
watchForPlayIndicator(w, h);
|
||||||
|
}
|
||||||
|
|
||||||
|
const observer = new MutationObserver(() => {
|
||||||
|
const canvas = document.querySelector(CANVAS_SELECTOR);
|
||||||
|
if (canvas) replaceAnimation(canvas);
|
||||||
|
});
|
||||||
|
|
||||||
|
observer.observe(document.body, { childList: true, subtree: true });
|
||||||
|
|
||||||
|
const initial = document.querySelector(CANVAS_SELECTOR);
|
||||||
|
if (initial) replaceAnimation(initial);
|
||||||
27
manifest.json
Normal file
27
manifest.json
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
{
|
||||||
|
"manifest_version": 2,
|
||||||
|
"name": "Yandex Music Custom Animation",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "Replaces Yandex Music animation with a custom video",
|
||||||
|
"permissions": [
|
||||||
|
"activeTab",
|
||||||
|
"webRequest",
|
||||||
|
"webRequestBlocking",
|
||||||
|
"*://music.yandex.ru/*",
|
||||||
|
"*://music.yandex.com/*"
|
||||||
|
],
|
||||||
|
"background": {
|
||||||
|
"scripts": ["background.js"]
|
||||||
|
},
|
||||||
|
"content_scripts": [
|
||||||
|
{
|
||||||
|
"matches": ["*://music.yandex.ru/*", "*://music.yandex.com/*"],
|
||||||
|
"js": ["content.js"],
|
||||||
|
"run_at": "document_idle"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"icons": {
|
||||||
|
"48": "icon.png",
|
||||||
|
"96": "icon.png"
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue