Skip to content

Commit

Permalink
fix(player speed): Player speed is now restored to what it was.
Browse files Browse the repository at this point in the history
When disabling player speed option

The previous speed is restored
  • Loading branch information
VampireChicken12 committed Nov 7, 2023
1 parent 043b1cc commit b765a14
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 63 deletions.
157 changes: 104 additions & 53 deletions src/features/playerSpeed/index.ts
Original file line number Diff line number Diff line change
@@ -1,74 +1,125 @@
import type { YouTubePlayerDiv } from "@/src/types";
import eventManager from "@/src/utils/EventManager";
import { isWatchPage, isShortsPage, browserColorLog, waitForSpecificMessage } from "@/src/utils/utilities";

/**
* Sets the player speed based on the options received from a specific message.
* Sets the player speed based on the given speed.
*
* @param playerSpeed - The playback speed to set.
* @returns {Promise<void>} A promise that resolves once the player speed is set.
*/
export async function setPlayerSpeed(playerSpeed: number): Promise<void>;
/**
* Sets the player speed based on the options received
* It sets the playback speed if the option is enabled and a valid speed is specified.
*
* @param options - Options for setting the player speed.
* @returns {Promise<void>} A promise that resolves once the player speed is set.
*/
export default async function setPlayerSpeed(options?: { playerSpeed?: number; enableForcedPlaybackSpeed?: boolean }): Promise<void> {
if (options) {
const { enableForcedPlaybackSpeed, playerSpeed } = options;
if (!enableForcedPlaybackSpeed) return;
if (!playerSpeed) return;
// Get the player element
const playerContainer = isWatchPage()
? (document.querySelector("div#movie_player") as YouTubePlayerDiv | null)
: isShortsPage()
? (document.querySelector("div#shorts-player") as YouTubePlayerDiv | null)
: null;
const video = document.querySelector("video.html5-main-video") as HTMLVideoElement | null;
// If player element is not available, return
if (!playerContainer) return;

// If setPlaybackRate method is not available in the player, return
if (!playerContainer.setPlaybackRate) return;

// Log the message indicating the player speed being set
browserColorLog(`Setting player speed to ${playerSpeed}`, "FgMagenta");

// Set the playback speed
playerContainer.setPlaybackRate(playerSpeed);
// Set the video playback speed
if (video) video.playbackRate = playerSpeed;
} else {
export async function setPlayerSpeed(): Promise<void>;
export async function setPlayerSpeed(input?: number): Promise<void> {
let playerSpeed = 1;
let enablePlayerSpeed = true;
// If the input is a number, set the player speed to the given number
if (input === undefined) {
// Wait for the "options" message from the content script
const optionsData = await waitForSpecificMessage("options", "request_data", "content");
if (!optionsData) return;
const {
data: { options }
} = optionsData;
// Extract the necessary properties from the options object
const { player_speed, enable_forced_playback_speed } = options;
({ player_speed: playerSpeed, enable_forced_playback_speed: enablePlayerSpeed } = options);
} else if (typeof input === "number") {
playerSpeed = input;
}
// If the player speed is not specified, return
if (!playerSpeed) return;
// If forced playback speed option is disabled, return
if (!enablePlayerSpeed) return;
// Get the player element
const playerContainer = isWatchPage()
? (document.querySelector("div#movie_player") as YouTubePlayerDiv | null)
: isShortsPage()
? (document.querySelector("div#shorts-player") as YouTubePlayerDiv | null)
: null;
// If player element is not available, return
if (!playerContainer) return;
const video = document.querySelector("video.html5-main-video") as HTMLVideoElement | null;

// If setPlaybackRate method is not available in the player, return
if (!playerContainer.setPlaybackRate) return;
const playerVideoData = await playerContainer.getVideoData();
// If the video is live return
if (playerVideoData.isLive) return;
// Log the message indicating the player speed being set
browserColorLog(`Setting player speed to ${playerSpeed}`, "FgMagenta");

// If forced playback speed option is disabled, return
if (!enable_forced_playback_speed) return;
// Set the playback speed
playerContainer.setPlaybackRate(playerSpeed);
// Set the video playback speed
if (video) video.playbackRate = playerSpeed;
}
// Restore the player speed to the last saved player speed
export function restorePlayerSpeed() {
// Get the saved player speed from the local storage
const playerSpeed = window.localStorage.getItem("playerSpeed");
// If the player speed is not available, return
if (!playerSpeed) return;
// Get the player element
const playerContainer = isWatchPage()
? (document.querySelector("div#movie_player") as YouTubePlayerDiv | null)
: isShortsPage()
? (document.querySelector("div#shorts-player") as YouTubePlayerDiv | null)
: null;
const video = document.querySelector("video.html5-main-video") as HTMLVideoElement | null;
// If player element is not available, return
if (!playerContainer) return;
// If setPlaybackRate method is not available in the player, return
if (!playerContainer.setPlaybackRate) return;
if (!video) return;
// Log the message indicating the player speed being set
browserColorLog(`Restoring player speed to ${playerSpeed}`, "FgMagenta");
// Set the playback speed
playerContainer.setPlaybackRate(Number(playerSpeed));
// Set the video playback speed
video.playbackRate = Number(playerSpeed);
}
export function setupPlaybackSpeedChangeListener() {
const settingsMenu = document.querySelector("div.ytp-settings-menu:not(#yte-feature-menu)");

// If player speed is not specified, return
if (!player_speed) return;
// Function to handle the playback speed click event
function handlePlaybackSpeedClick(node: HTMLDivElement): void {
// Extract the playback speed value
const speedValue = node.textContent?.trim();
// If the playback speed is not available, return
if (!speedValue) return;
const playerSpeed = speedValue === "Normal" ? 1 : Number(speedValue);
window.localStorage.setItem("playerSpeed", String(playerSpeed));
}

// Get the player element
const playerContainer = isWatchPage()
? (document.querySelector("div#movie_player") as YouTubePlayerDiv | null)
: isShortsPage()
? (document.querySelector("div#shorts-player") as YouTubePlayerDiv | null)
: null;
// If player element is not available, return
if (!playerContainer) return;
const video = document.querySelector("video.html5-main-video") as HTMLVideoElement | null;
// 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");
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");
});
}
}
}
});

// If setPlaybackRate method is not available in the player, return
if (!playerContainer.setPlaybackRate) return;
const playerVideoData = await playerContainer.getVideoData();
// If the video is live return
if (playerVideoData.isLive) return;
// Log the message indicating the player speed being set
browserColorLog(`Setting player speed to ${player_speed}`, "FgMagenta");
const config: MutationObserverInit = { childList: true, subtree: true };

// Set the playback speed
playerContainer.setPlaybackRate(player_speed);
// Set the video playback speed
if (video) video.playbackRate = player_speed;
if (settingsMenu) {
observer.observe(settingsMenu, config);
}
}
15 changes: 5 additions & 10 deletions src/pages/content/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { addLoopButton, removeLoopButton } from "@/src/features/loopButton";
import { addMaximizePlayerButton, removeMaximizePlayerButton } from "@/src/features/maximizePlayerButton";
import { maximizePlayer } from "@/src/features/maximizePlayerButton/utils";
import setPlayerQuality from "@/src/features/playerQuality";
import setPlayerSpeed from "@/src/features/playerSpeed";
import { restorePlayerSpeed, setPlayerSpeed, setupPlaybackSpeedChangeListener } from "@/src/features/playerSpeed";
import { removeRemainingTimeDisplay, setupRemainingTime } from "@/src/features/remainingTime";
import enableRememberVolume from "@/src/features/rememberVolume";
import { addScreenshotButton, removeScreenshotButton } from "@/src/features/screenshotButton";
Expand Down Expand Up @@ -76,6 +76,7 @@ window.onload = function () {
addMaximizePlayerButton();
addScreenshotButton();
enableRememberVolume();
setupPlaybackSpeedChangeListener();
setPlayerQuality();
setPlayerSpeed();
volumeBoost();
Expand Down Expand Up @@ -128,15 +129,9 @@ window.onload = function () {
data: { playerSpeed, enableForcedPlaybackSpeed }
} = message;
if (enableForcedPlaybackSpeed && playerSpeed) {
setPlayerSpeed({
enableForcedPlaybackSpeed,
playerSpeed: Number(playerSpeed)
});
} else {
setPlayerSpeed({
enableForcedPlaybackSpeed: false,
playerSpeed: 1
});
setPlayerSpeed(Number(playerSpeed));
} else if (!enableForcedPlaybackSpeed) {
restorePlayerSpeed();
}
break;
}
Expand Down

0 comments on commit b765a14

Please sign in to comment.