From c44d5ea1111211aaeea699f33f0a9a2c591932fc Mon Sep 17 00:00:00 2001 From: JellyBrick Date: Fri, 11 Jul 2025 23:00:38 +0900 Subject: [PATCH] fix: improve menu detector --- src/plugins/downloader/renderer.tsx | 9 +--- src/plugins/picture-in-picture/renderer.tsx | 12 ++++- src/plugins/playback-speed/renderer.tsx | 12 ++++- src/plugins/utils/renderer/check.ts | 51 ++++++++++++++------- 4 files changed, 57 insertions(+), 27 deletions(-) diff --git a/src/plugins/downloader/renderer.tsx b/src/plugins/downloader/renderer.tsx index 8ec9712d..8b4d5817 100644 --- a/src/plugins/downloader/renderer.tsx +++ b/src/plugins/downloader/renderer.tsx @@ -13,7 +13,6 @@ import { DownloadButton } from './templates/download'; import type { RendererContext } from '@/types/contexts'; import type { DownloaderPluginConfig } from './index'; -let menu: HTMLElement | null = null; let download: () => void; const [downloadButtonText, setDownloadButtonText] = createSignal(''); @@ -21,14 +20,10 @@ const [downloadButtonText, setDownloadButtonText] = createSignal(''); let buttonContainer: HTMLDivElement | null = null; const menuObserver = new MutationObserver(() => { - if (!menu) { - menu = getSongMenu(); - if (!menu) { - return; - } - } + const menu = getSongMenu(); if ( + !menu || menu.contains(buttonContainer) || !isMusicOrVideoTrack() || !buttonContainer diff --git a/src/plugins/picture-in-picture/renderer.tsx b/src/plugins/picture-in-picture/renderer.tsx index 3387c3bd..5c5c7657 100644 --- a/src/plugins/picture-in-picture/renderer.tsx +++ b/src/plugins/picture-in-picture/renderer.tsx @@ -3,7 +3,10 @@ import keyEventAreEqual from 'keyboardevents-areequal'; import { render } from 'solid-js/web'; import { getSongMenu } from '@/providers/dom-elements'; -import { isMusicOrVideoTrack } from '@/plugins/utils/renderer/check'; +import { + isMusicOrVideoTrack, + isPlayerMenu, +} from '@/plugins/utils/renderer/check'; import { t } from '@/i18n'; @@ -152,7 +155,12 @@ export const onPlayerApiReady = async ( const observer = new MutationObserver(() => { const menu = getSongMenu(); - if (menu?.contains(pipButtonContainer) || !isMusicOrVideoTrack()) { + console.log(isPlayerMenu(menu)); + if ( + menu?.contains(pipButtonContainer) || + !isMusicOrVideoTrack() || + !isPlayerMenu(menu) + ) { return; } diff --git a/src/plugins/playback-speed/renderer.tsx b/src/plugins/playback-speed/renderer.tsx index 2e1c7228..04069584 100644 --- a/src/plugins/playback-speed/renderer.tsx +++ b/src/plugins/playback-speed/renderer.tsx @@ -7,7 +7,10 @@ import { getSongMenu } from '@/providers/dom-elements'; import { PlaybackSpeedSlider } from './components/slider'; import { t } from '@/i18n'; -import { isMusicOrVideoTrack } from '@/plugins/utils/renderer/check'; +import { + isMusicOrVideoTrack, + isPlayerMenu, +} from '@/plugins/utils/renderer/check'; const MIN_PLAYBACK_SPEED = 0.07; const MAX_PLAYBACK_SPEED = 16; @@ -83,7 +86,12 @@ export const onPlayerApiReady = () => { const observer = new MutationObserver(() => { const menu = getSongMenu(); - if (menu && !menu.contains(sliderContainer) && isMusicOrVideoTrack()) { + if ( + menu && + !menu.contains(sliderContainer) && + isMusicOrVideoTrack() && + isPlayerMenu(menu) + ) { menu.prepend(sliderContainer); } }); diff --git a/src/plugins/utils/renderer/check.ts b/src/plugins/utils/renderer/check.ts index 85b2f8f7..99f08f46 100644 --- a/src/plugins/utils/renderer/check.ts +++ b/src/plugins/utils/renderer/check.ts @@ -1,20 +1,39 @@ export const isMusicOrVideoTrack = () => { - let menuUrl = document.querySelector( - 'tp-yt-paper-listbox [tabindex="0"] #navigation-endpoint', - )?.href; - - if (!menuUrl?.includes('watch?')) { - menuUrl = undefined; - // check for podcast - for (const it of document.querySelectorAll( - 'tp-yt-paper-listbox [tabindex="-1"] #navigation-endpoint', - )) { - if (it.getAttribute('href')?.includes('podcast/')) { - menuUrl = it.getAttribute('href')!; - break; - } + for (const menuSelector of document.querySelectorAll< + HTMLAnchorElement & { + data: { + watchEndpoint: { + videoId: string; + }; + addToPlaylistEndpoint: { + videoId: string; + }; + clickTrackingParams: string; + }; + } + >('tp-yt-paper-listbox #navigation-endpoint')) { + if ( + menuSelector?.data?.addToPlaylistEndpoint?.videoId || + menuSelector?.data?.watchEndpoint?.videoId + ) { + return true; } } - - return !!menuUrl; + return false; +}; + +export const isPlayerMenu = (menu?: HTMLElement | null) => { + return ( + menu?.parentElement as + | (HTMLElement & { + ytEventForwardingBehavior: { + forwarder_: { + eventSink: HTMLElement; + }; + }; + }) + | null + )?.ytEventForwardingBehavior?.forwarder_?.eventSink?.matches( + 'ytmusic-menu-renderer.ytmusic-player-bar', + ); };