From 7b033b5cafee580055200a7644423f1b2b3d4b8f Mon Sep 17 00:00:00 2001 From: JellyBrick Date: Wed, 31 Jul 2024 22:08:45 +0900 Subject: [PATCH] fix(ambient-mode): fix ambient-mode not working for videos after restart (#2294) * Fix Ambient Mode not working for videos after restart (#2255) This should fix https://github.com/th-ch/youtube-music/issues/1641 * fix: fix waitForElement --------- Co-authored-by: craftgeil <80261988+craftgeil@users.noreply.github.com> --- src/plugins/album-actions/index.ts | 15 ++------------- src/plugins/ambient-mode/index.ts | 16 +++++++++------- src/plugins/skip-disliked-songs/index.ts | 15 ++------------- src/utils/wait-for-element.ts | 11 +++++++++++ 4 files changed, 24 insertions(+), 33 deletions(-) create mode 100644 src/utils/wait-for-element.ts diff --git a/src/plugins/album-actions/index.ts b/src/plugins/album-actions/index.ts index c9bf1864..bc27c9e3 100644 --- a/src/plugins/album-actions/index.ts +++ b/src/plugins/album-actions/index.ts @@ -1,6 +1,7 @@ import { t } from '@/i18n'; import { createPlugin } from '@/utils'; import { ElementFromHtml } from '@/plugins/utils/renderer'; +import { waitForElement } from '@/utils/wait-for-element'; import undislikeHTML from './templates/undislike.html?raw'; import dislikeHTML from './templates/dislike.html?raw'; @@ -16,7 +17,6 @@ export default createPlugin< changeObserver?: MutationObserver; waiting: boolean; onPageChange(): void; - waitForElem(selector: string): Promise; loadFullList: (event: MouseEvent) => void; applyToList(id: string, loader: HTMLElement): void; start(): void; @@ -50,7 +50,7 @@ export default createPlugin< } else { this.waiting = true; } - const continuations = await this.waitForElem('#continuations'); + const continuations = await waitForElement('#continuations'); this.waiting = false; //Gets the for buttons const buttons: Array = [ @@ -183,16 +183,5 @@ export default createPlugin< button.remove(); } }, - waitForElem(selector: string) { - return new Promise((resolve) => { - const interval = setInterval(() => { - const elem = document.querySelector(selector); - if (!elem) return; - - clearInterval(interval); - resolve(elem); - }); - }); - }, }, }); diff --git a/src/plugins/ambient-mode/index.ts b/src/plugins/ambient-mode/index.ts index 33d90dba..5dfd2023 100644 --- a/src/plugins/ambient-mode/index.ts +++ b/src/plugins/ambient-mode/index.ts @@ -4,6 +4,7 @@ import { t } from '@/i18n'; import { createPlugin } from '@/utils'; import { menu } from './menu'; import { AmbientModePluginConfig } from './types'; +import { waitForElement } from '@/utils/wait-for-element'; const defaultConfig: AmbientModePluginConfig = { enabled: false, @@ -36,7 +37,7 @@ export default createPlugin({ unregister: null as (() => void) | null, update: null as (() => void) | null, interval: null as NodeJS.Timeout | null, - lastMediaType: null as "video" | "image" | null, + lastMediaType: null as 'video' | 'image' | null, lastVideoSource: null as string | null, lastImageSource: null as string | null, @@ -53,7 +54,8 @@ export default createPlugin({ const songImage = document.querySelector('#song-image'); const songVideo = document.querySelector('#song-video'); const image = songImage?.querySelector('yt-img-shadow > img'); - const video = songVideo?.querySelector('.html5-video-container > video'); + const video = await waitForElement('.html5-video-container > video'); + const videoWrapper = document.querySelector('#song-video > .player-wrapper'); const injectBlurImage = () => { @@ -179,12 +181,12 @@ export default createPlugin({ const isVideoMode = () => { const songVideo = document.querySelector('#song-video'); if (!songVideo) { - this.lastMediaType = "image"; + this.lastMediaType = 'image'; return false; } const isVideo = getComputedStyle(songVideo).display !== 'none'; - this.lastMediaType = isVideo ? "video" : "image"; + this.lastMediaType = isVideo ? 'video' : 'image'; return isVideo; }; @@ -196,8 +198,8 @@ export default createPlugin({ if (isPageOpen) { const isVideo = isVideoMode(); if (!force) { - if (this.lastMediaType === "video" && this.lastVideoSource === video?.src) return false; - if (this.lastMediaType === "image" && this.lastImageSource === image?.src) return false; + if (this.lastMediaType === 'video' && this.lastVideoSource === video?.src) return false; + if (this.lastMediaType === 'image' && this.lastImageSource === image?.src) return false; } this.unregister?.(); this.unregister = (isVideo ? injectBlurVideo() : injectBlurImage()) ?? null; @@ -205,7 +207,7 @@ export default createPlugin({ this.unregister?.(); this.unregister = null; } - } + }; /* needed for switching between different views (e.g. miniplayer) */ const observer = new MutationObserver((mutationsList) => { diff --git a/src/plugins/skip-disliked-songs/index.ts b/src/plugins/skip-disliked-songs/index.ts index 8d8a3726..c3cd47e0 100644 --- a/src/plugins/skip-disliked-songs/index.ts +++ b/src/plugins/skip-disliked-songs/index.ts @@ -1,12 +1,12 @@ import { t } from '@/i18n'; import { createPlugin } from '@/utils'; +import { waitForElement } from '@/utils/wait-for-element'; export default createPlugin< unknown, unknown, { observer?: MutationObserver; - waitForElem(selector: string): Promise; start(): void; stop(): void; } @@ -15,19 +15,8 @@ export default createPlugin< description: () => t('plugins.skip-disliked-songs.description'), restartNeeded: false, renderer: { - waitForElem(selector: string) { - return new Promise((resolve) => { - const interval = setInterval(() => { - const elem = document.querySelector(selector); - if (!elem) return; - - clearInterval(interval); - resolve(elem); - }); - }); - }, start() { - this.waitForElem('#dislike-button-renderer').then((dislikeBtn) => { + waitForElement('#dislike-button-renderer').then((dislikeBtn) => { this.observer = new MutationObserver(() => { if (dislikeBtn?.getAttribute('like-status') == 'DISLIKE') { document diff --git a/src/utils/wait-for-element.ts b/src/utils/wait-for-element.ts new file mode 100644 index 00000000..1b43f492 --- /dev/null +++ b/src/utils/wait-for-element.ts @@ -0,0 +1,11 @@ +export const waitForElement = (selector: string): Promise => { + return new Promise((resolve) => { + const interval = setInterval(() => { + const elem = document.querySelector(selector); + if (!elem) return; + + clearInterval(interval); + resolve(elem); + }); + }); +};