Skip to content

Commit

Permalink
fix: restore player speed relying on English
Browse files Browse the repository at this point in the history
Restoring custom speed now supported
  • Loading branch information
VampireChicken12 committed Nov 20, 2023
1 parent ef7a51a commit 25b5574
Showing 1 changed file with 61 additions and 28 deletions.
89 changes: 61 additions & 28 deletions src/features/playerSpeed/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,42 +86,75 @@ export function restorePlayerSpeed() {
video.playbackRate = Number(playerSpeed);
}
export function setupPlaybackSpeedChangeListener() {
const settingsMenu = document.querySelector("div.ytp-settings-menu:not(#yte-feature-menu)");

// Function to handle the playback speed click event
function handlePlaybackSpeedClick(node: HTMLDivElement): void {
// Extract the playback speed value
const speedValue = node.textContent?.trim();
const settingsPanelMenu = document.querySelector("div.ytp-settings-menu:not(#yte-feature-menu)");
const speedMenuItemClickListener = (event: Event) => {
const { target: speedMenuItem } = event as Event & { target: HTMLDivElement };
if (!speedMenuItem) return;
const { textContent: speedValue } = speedMenuItem;
// If the playback speed is not available, return
if (!speedValue) return;
const playerSpeed = speedValue === "Normal" ? 1 : Number(speedValue);
const speedValueRegex = /(?<!\d\.)([0-1](\.\d+)?|2)(?![\d.])/;
let playerSpeed: number = 1;
if (speedValueRegex.test(speedValue)) {
const speedValueMatch = speedValue.match(speedValueRegex);
if (speedValueMatch) {
playerSpeed = Number(speedValueMatch[1]);
}
}
window.localStorage.setItem("playerSpeed", String(playerSpeed));
}
};

// Create an observer instance
const observer = new MutationObserver((mutationsList) => {
for (const mutation of mutationsList) {
if (mutation.type === "childList") {
const titleElement: HTMLSpanElement | null = document.querySelector("div.ytp-panel > div.ytp-panel-header > span.ytp-panel-title");
// TODO: fix this it relies on the language being English
if (titleElement && titleElement.textContent && titleElement.textContent.includes("Playback speed")) {
const menuItems: NodeListOf<HTMLDivElement> = document.querySelectorAll("div.ytp-panel-menu div.ytp-menuitem");
menuItems.forEach((node: HTMLDivElement) => {
eventManager.addEventListener(node, "click", () => handlePlaybackSpeedClick(node), "playerSpeed");
});
} else {
const menuItems: NodeListOf<HTMLDivElement> = document.querySelectorAll("div.ytp-panel-menu div.ytp-menuitem");
menuItems.forEach((node: HTMLDivElement) => {
eventManager.removeEventListener(node, "click", "playerSpeed");
});
}
const playerSpeedMenuObserver = new MutationObserver((mutationsList: MutationRecord[]) => {
mutationsList.forEach((mutation) => {
const { target: targetElement } = mutation as MutationRecord & { target: HTMLDivElement };

// Check if the target element has the desired structure
const panelHeader: HTMLDivElement | null = targetElement.querySelector("div.ytp-panel > div.ytp-panel-header");
const panelMenu: HTMLDivElement | null = targetElement.querySelector("div.ytp-panel > div.ytp-panel-menu");
const menuItems = panelMenu?.querySelectorAll("div.ytp-menuitem");
if (panelHeader && panelMenu && menuItems && menuItems.length === 8) {
menuItems.forEach((menuItem) => {
eventManager.addEventListener(menuItem as HTMLDivElement, "click", speedMenuItemClickListener, "playerSpeed");
});
}
}
});
});
const customSpeedSliderObserver = new MutationObserver((mutationsList: MutationRecord[]) => {
mutationsList.forEach((mutation) => {
const { target: targetElement } = mutation as MutationRecord & { target: HTMLDivElement };
const speedValue = targetElement.getAttribute("aria-valuenow");
// If the playback speed is not available, return
if (!speedValue) return;
const playerSpeed = parseFloat(speedValue);
window.localStorage.setItem("playerSpeed", String(playerSpeed));
});
});

const config: MutationObserverInit = { childList: true, subtree: true };

if (settingsMenu) {
observer.observe(settingsMenu, config);
if (settingsPanelMenu) {
playerSpeedMenuObserver.observe(settingsPanelMenu, config);
customSpeedSliderObserver.observe(settingsPanelMenu, {
attributeFilter: ["aria-valuenow"],
attributes: true,
childList: true,
subtree: true
});
const menuItems = [...document.querySelectorAll('div.ytp-settings-menu:not(#yte-feature-menu) > .ytp-panel > .ytp-panel-menu [role="menuitem"]')];
const speedMenuItem = menuItems.find(
(el) =>
el.children[0].innerHTML ===
`<svg height="24" viewBox="0 0 24 24" width="24"><path d="M10,8v8l6-4L10,8L10,8z M6.3,5L5.7,4.2C7.2,3,9,2.2,11,2l0.1,1C9.3,3.2,7.7,3.9,6.3,5z M5,6.3L4.2,5.7C3,7.2,2.2,9,2,11 l1,.1C3.2,9.3,3.9,7.7,5,6.3z M5,17.7c-1.1-1.4-1.8-3.1-2-4.8L2,13c0.2,2,1,3.8,2.2,5.4L5,17.7z M11.1,21c-1.8-0.2-3.4-0.9-4.8-2 l-0.6,.8C7.2,21,9,21.8,11,22L11.1,21z M22,12c0-5.2-3.9-9.4-9-10l-0.1,1c4.6,.5,8.1,4.3,8.1,9s-3.5,8.5-8.1,9l0.1,1 C18.2,21.5,22,17.2,22,12z" fill="white"></path></svg>`
) as HTMLDivElement | undefined;
if (!speedMenuItem) return;
const {
children: [, , speedMenuItemContent]
} = speedMenuItem;
if (!speedMenuItemContent) return;
const { textContent: speedValue } = speedMenuItem;
// If the playback speed is not available, return
if (!speedValue) return;
const playerSpeed = isNaN(Number(speedValue)) ? 1 : Number(speedValue);
window.localStorage.setItem("playerSpeed", String(playerSpeed));
}
}

0 comments on commit 25b5574

Please sign in to comment.