From e8eb9fab9f61cb67d2a8a15aed41e8c1f8c0d353 Mon Sep 17 00:00:00 2001 From: GooseOb Date: Sun, 1 Dec 2024 04:05:02 +0100 Subject: [PATCH] move settings applying and setting plr elements out of `onPageChange` --- index.ts | 199 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 105 insertions(+), 94 deletions(-) diff --git a/index.ts b/index.ts index 8ecddc9..490a4a9 100644 --- a/index.ts +++ b/index.ts @@ -206,11 +206,6 @@ const untilAppear = (getItem: () => T, msToWait?: number) => until(getItem, Boolean, msToWait); let channelConfig = null as Partial; -let video: HTMLVideoElement, - subtitlesBtn: HTMLButtonElement, - muteBtn: HTMLButtonElement, - speedNormal: string, - isSpeedApplied = false; type Focusable = { focus(): void }; @@ -290,50 +285,82 @@ const findInNodeList = ( return null; }; -const ytMenu = { - async setPlayer(plr: Readonly) { - this.element = plr.querySelector('.ytp-settings-menu'); - this._btn = plr.querySelector('.ytp-settings-button'); - const clickBtn = this._btn.click.bind(this._btn); +const plr = { + async set(el: HTMLElement) { + this.isSpeedApplied = false; + await delay(1_000); + const getAd = () => el.querySelector('.ytp-ad-player-overlay'); + await until(getAd, (ad) => !ad, 200_000); + this.video ||= el.querySelector('.html5-main-video'); + this.subtitlesBtn ||= el.querySelector('.ytp-subtitles-button'); + this.muteBtn ||= el.querySelector('.ytp-mute-button'); + + this.menu.element ||= el.querySelector('.ytp-settings-menu'); + this.menu._btn ||= el.querySelector('.ytp-settings-button'); + const clickBtn = () => { + this.menu._btn.click(); + }; + restoreFocusAfter(clickBtn); await delay(50); restoreFocusAfter(clickBtn); + + const getMenuItems = () => + plr.menu.element.querySelectorAll( + '.ytp-menuitem[role="menuitem"]' + ); + plr.menu.setSettingItems(await until(getMenuItems, (arr) => !!arr.length)); + if (!this.speedNormal) + restoreFocusAfter(() => { + this.speedNormal = plr.menu.findInItem( + SPEED, + (btn) => !+btn.textContent + ).textContent; + }); }, + isSpeedApplied: false, + speedNormal: '', element: null as HTMLElement, - _btn: null as HTMLElement, - isOpen() { - return this.element.style.display !== 'none'; - }, - setOpen(bool: boolean) { - if (bool !== this.isOpen()) this._btn.click(); - }, - openItem(item: Readonly) { - this.setOpen(true); - item.click(); - return this.element.querySelectorAll( - '.ytp-panel-animate-forward .ytp-menuitem-label' - ); - }, - settingItems: { - [SPEED]: null, - [QUALITY]: null, - } as Record, - setSettingItems(items: DeepReadonly>) { - const findIcon = (d: string) => - findInNodeList(items, (el) => !!el.querySelector(`path[d="${d}"]`)); - - this.settingItems[SPEED] = findIcon( - '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' - ); - this.settingItems[QUALITY] = findIcon( - 'M15,17h6v1h-6V17z M11,17H3v1h8v2h1v-2v-1v-2h-1V17z M14,8h1V6V5V3h-1v2H3v1h11V8z M18,5v1h3V5H18z M6,14h1v-2v-1V9H6v2H3v1 h3V14z M10,12h11v-1H10V12z' - ); - }, - findInItem( - name: YtSettingName, - finder: (item: Readonly) => boolean - ) { - return findInNodeList(this.openItem(this.settingItems[name]), finder); + video: null as HTMLVideoElement, + subtitlesBtn: null as HTMLButtonElement, + muteBtn: null as HTMLButtonElement, + menu: { + element: null as HTMLElement, + _btn: null as HTMLElement, + isOpen() { + return this.element.style.display !== 'none'; + }, + setOpen(bool: boolean) { + if (bool !== this.isOpen()) this._btn.click(); + }, + openItem(item: Readonly) { + this.setOpen(true); + item.click(); + return this.element.querySelectorAll( + '.ytp-panel-animate-forward .ytp-menuitem-label' + ); + }, + settingItems: { + [SPEED]: null, + [QUALITY]: null, + } as Record, + setSettingItems(items: DeepReadonly>) { + const findIcon = (d: string) => + findInNodeList(items, (el) => !!el.querySelector(`path[d="${d}"]`)); + + this.settingItems[SPEED] = findIcon( + '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' + ); + this.settingItems[QUALITY] = findIcon( + 'M15,17h6v1h-6V17z M11,17H3v1h8v2h1v-2v-1v-2h-1V17z M14,8h1V6V5V3h-1v2H3v1h11V8z M18,5v1h3V5H18z M6,14h1v-2v-1V9H6v2H3v1 h3V14z M10,12h11v-1H10V12z' + ); + }, + findInItem( + name: YtSettingName, + finder: (item: Readonly) => boolean + ) { + return findInNodeList(this.openItem(this.settingItems[name]), finder); + }, }, }; @@ -381,42 +408,42 @@ type ValueSetters = { [P in Setting]: (value: Cfg[P]) => void }; const valueSetters: ValueSetters & ValueSetterHelpers = { _ytSettingItem(settingName, value) { - const isOpen = ytMenu.isOpen(); + const isOpen = plr.menu.isOpen(); const compare = comparators[settingName]; - const btn = ytMenu.findInItem(settingName, (btn) => + const btn = plr.menu.findInItem(settingName, (btn) => compare(value, btn.textContent) ); if (btn) { btn.click(); - ytMenu.setOpen(isOpen); + plr.menu.setOpen(isOpen); } }, speed(value) { - this._ytSettingItem(SPEED, isSpeedApplied ? speedNormal : value); - isSpeedApplied = !isSpeedApplied; + this._ytSettingItem(SPEED, plr.isSpeedApplied ? plr.speedNormal : value); + plr.isSpeedApplied = !plr.isSpeedApplied; }, customSpeed(value) { try { - video.playbackRate = isSpeedApplied ? 1 : +value; + plr.video.playbackRate = plr.isSpeedApplied ? 1 : +value; } catch { logger.outOfRange('Custom speed'); return; } - isSpeedApplied = !isSpeedApplied; + plr.isSpeedApplied = !plr.isSpeedApplied; }, subtitles(value) { - if (subtitlesBtn.ariaPressed !== value.toString()) subtitlesBtn.click(); + if (plr.subtitlesBtn.ariaPressed !== value.toString()) + plr.subtitlesBtn.click(); }, volume(value) { const num = +value; - muteBtn ||= document.querySelector('.ytp-mute-button'); - const isMuted = muteBtn.dataset.titleNoTooltip !== 'Mute'; + const isMuted = plr.muteBtn.dataset.titleNoTooltip !== 'Mute'; if (num === 0) { - if (!isMuted) muteBtn.click(); + if (!isMuted) plr.muteBtn.click(); } else { - if (isMuted) muteBtn.click(); + if (isMuted) plr.muteBtn.click(); try { - video.volume = num / 100; + plr.video.volume = num / 100; } catch { logger.outOfRange('Volume'); } @@ -486,7 +513,7 @@ const computeSettings = (doNotChangeSpeed: boolean) => { const isChannelSpeed = 'speed' in channelConfig; const isChannelCustomSpeed = 'customSpeed' in channelConfig; if (doNotChangeSpeed) { - settings.speed = speedNormal; + settings.speed = plr.speedNormal; delete settings.customSpeed; } else if (isChannelCustomSpeed) { delete settings.speed; @@ -496,6 +523,20 @@ const computeSettings = (doNotChangeSpeed: boolean) => { return settings; }; +const applySettings = (settings: Cfg) => { + restoreFocusAfter(() => { + if (!isNaN(+settings.customSpeed)) { + valueSetters.customSpeed(settings.customSpeed); + } + + delete settings.customSpeed; + + for (const setting in settings) + valueSetters[setting as Setting](settings[setting as never]); + plr.menu.setOpen(false); + }); +}; + const delay = (ms: number) => new Promise((res) => setTimeout(res, ms)); const onPageChange = async () => { if (location.pathname !== '/watch') return; @@ -507,43 +548,13 @@ const onPageChange = async () => { channelConfig = cfg.channels[channelUsername] ||= {}; - const plr = await untilAppear(getPlr); - await delay(1_000); - const getAd = () => plr.querySelector('.ytp-ad-player-overlay'); - await until(getAd, (ad) => !ad, 200_000); - await ytMenu.setPlayer(plr); - const getMenuItems = () => - ytMenu.element.querySelectorAll( - '.ytp-menuitem[role="menuitem"]' - ); - ytMenu.setSettingItems(await until(getMenuItems, (arr) => !!arr.length)); - if (!speedNormal) - restoreFocusAfter(() => { - speedNormal = ytMenu.findInItem( - SPEED, - (btn) => !+btn.textContent - ).textContent; - }); + await plr.set(await untilAppear(getPlr)); - isSpeedApplied = false; - video ||= plr.querySelector('.html5-main-video'); - subtitlesBtn ||= plr.querySelector('.ytp-subtitles-button'); - restoreFocusAfter(() => { - const settings = computeSettings( + applySettings( + computeSettings( cfg.flags.standardMusicSpeed && isMusicChannel(aboveTheFold) - ); - - if (!isNaN(+settings.customSpeed)) { - isSpeedApplied = false; - valueSetters.customSpeed(settings.customSpeed); - } - - delete settings.customSpeed; - - for (const setting in settings) - valueSetters[setting as Setting](settings[setting as never]); - ytMenu.setOpen(false); - }); + ) + ); /* ---------------------- settings menu ---------------------- */ @@ -586,7 +597,7 @@ const onPageChange = async () => { '1.75', '1.5', '1.25', - speedNormal, + plr.speedNormal, '0.75', '0.5', '0.25',