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>
This commit is contained in:
JellyBrick
2024-07-31 22:08:45 +09:00
committed by GitHub
parent 8924ec29d3
commit 7b033b5caf
4 changed files with 24 additions and 33 deletions

View File

@ -1,6 +1,7 @@
import { t } from '@/i18n'; import { t } from '@/i18n';
import { createPlugin } from '@/utils'; import { createPlugin } from '@/utils';
import { ElementFromHtml } from '@/plugins/utils/renderer'; import { ElementFromHtml } from '@/plugins/utils/renderer';
import { waitForElement } from '@/utils/wait-for-element';
import undislikeHTML from './templates/undislike.html?raw'; import undislikeHTML from './templates/undislike.html?raw';
import dislikeHTML from './templates/dislike.html?raw'; import dislikeHTML from './templates/dislike.html?raw';
@ -16,7 +17,6 @@ export default createPlugin<
changeObserver?: MutationObserver; changeObserver?: MutationObserver;
waiting: boolean; waiting: boolean;
onPageChange(): void; onPageChange(): void;
waitForElem(selector: string): Promise<HTMLElement>;
loadFullList: (event: MouseEvent) => void; loadFullList: (event: MouseEvent) => void;
applyToList(id: string, loader: HTMLElement): void; applyToList(id: string, loader: HTMLElement): void;
start(): void; start(): void;
@ -50,7 +50,7 @@ export default createPlugin<
} else { } else {
this.waiting = true; this.waiting = true;
} }
const continuations = await this.waitForElem('#continuations'); const continuations = await waitForElement<HTMLElement>('#continuations');
this.waiting = false; this.waiting = false;
//Gets the for buttons //Gets the for buttons
const buttons: Array<HTMLElement> = [ const buttons: Array<HTMLElement> = [
@ -183,16 +183,5 @@ export default createPlugin<
button.remove(); button.remove();
} }
}, },
waitForElem(selector: string) {
return new Promise((resolve) => {
const interval = setInterval(() => {
const elem = document.querySelector<HTMLElement>(selector);
if (!elem) return;
clearInterval(interval);
resolve(elem);
});
});
},
}, },
}); });

View File

@ -4,6 +4,7 @@ import { t } from '@/i18n';
import { createPlugin } from '@/utils'; import { createPlugin } from '@/utils';
import { menu } from './menu'; import { menu } from './menu';
import { AmbientModePluginConfig } from './types'; import { AmbientModePluginConfig } from './types';
import { waitForElement } from '@/utils/wait-for-element';
const defaultConfig: AmbientModePluginConfig = { const defaultConfig: AmbientModePluginConfig = {
enabled: false, enabled: false,
@ -36,7 +37,7 @@ export default createPlugin({
unregister: null as (() => void) | null, unregister: null as (() => void) | null,
update: null as (() => void) | null, update: null as (() => void) | null,
interval: null as NodeJS.Timeout | null, interval: null as NodeJS.Timeout | null,
lastMediaType: null as "video" | "image" | null, lastMediaType: null as 'video' | 'image' | null,
lastVideoSource: null as string | null, lastVideoSource: null as string | null,
lastImageSource: null as string | null, lastImageSource: null as string | null,
@ -53,7 +54,8 @@ export default createPlugin({
const songImage = document.querySelector<HTMLImageElement>('#song-image'); const songImage = document.querySelector<HTMLImageElement>('#song-image');
const songVideo = document.querySelector<HTMLDivElement>('#song-video'); const songVideo = document.querySelector<HTMLDivElement>('#song-video');
const image = songImage?.querySelector<HTMLImageElement>('yt-img-shadow > img'); const image = songImage?.querySelector<HTMLImageElement>('yt-img-shadow > img');
const video = songVideo?.querySelector<HTMLVideoElement>('.html5-video-container > video'); const video = await waitForElement<HTMLVideoElement>('.html5-video-container > video');
const videoWrapper = document.querySelector('#song-video > .player-wrapper'); const videoWrapper = document.querySelector('#song-video > .player-wrapper');
const injectBlurImage = () => { const injectBlurImage = () => {
@ -179,12 +181,12 @@ export default createPlugin({
const isVideoMode = () => { const isVideoMode = () => {
const songVideo = document.querySelector<HTMLDivElement>('#song-video'); const songVideo = document.querySelector<HTMLDivElement>('#song-video');
if (!songVideo) { if (!songVideo) {
this.lastMediaType = "image"; this.lastMediaType = 'image';
return false; return false;
} }
const isVideo = getComputedStyle(songVideo).display !== 'none'; const isVideo = getComputedStyle(songVideo).display !== 'none';
this.lastMediaType = isVideo ? "video" : "image"; this.lastMediaType = isVideo ? 'video' : 'image';
return isVideo; return isVideo;
}; };
@ -196,8 +198,8 @@ export default createPlugin({
if (isPageOpen) { if (isPageOpen) {
const isVideo = isVideoMode(); const isVideo = isVideoMode();
if (!force) { if (!force) {
if (this.lastMediaType === "video" && this.lastVideoSource === video?.src) return false; if (this.lastMediaType === 'video' && this.lastVideoSource === video?.src) return false;
if (this.lastMediaType === "image" && this.lastImageSource === image?.src) return false; if (this.lastMediaType === 'image' && this.lastImageSource === image?.src) return false;
} }
this.unregister?.(); this.unregister?.();
this.unregister = (isVideo ? injectBlurVideo() : injectBlurImage()) ?? null; this.unregister = (isVideo ? injectBlurVideo() : injectBlurImage()) ?? null;
@ -205,7 +207,7 @@ export default createPlugin({
this.unregister?.(); this.unregister?.();
this.unregister = null; this.unregister = null;
} }
} };
/* needed for switching between different views (e.g. miniplayer) */ /* needed for switching between different views (e.g. miniplayer) */
const observer = new MutationObserver((mutationsList) => { const observer = new MutationObserver((mutationsList) => {

View File

@ -1,12 +1,12 @@
import { t } from '@/i18n'; import { t } from '@/i18n';
import { createPlugin } from '@/utils'; import { createPlugin } from '@/utils';
import { waitForElement } from '@/utils/wait-for-element';
export default createPlugin< export default createPlugin<
unknown, unknown,
unknown, unknown,
{ {
observer?: MutationObserver; observer?: MutationObserver;
waitForElem(selector: string): Promise<HTMLElement>;
start(): void; start(): void;
stop(): void; stop(): void;
} }
@ -15,19 +15,8 @@ export default createPlugin<
description: () => t('plugins.skip-disliked-songs.description'), description: () => t('plugins.skip-disliked-songs.description'),
restartNeeded: false, restartNeeded: false,
renderer: { renderer: {
waitForElem(selector: string) {
return new Promise<HTMLElement>((resolve) => {
const interval = setInterval(() => {
const elem = document.querySelector<HTMLElement>(selector);
if (!elem) return;
clearInterval(interval);
resolve(elem);
});
});
},
start() { start() {
this.waitForElem('#dislike-button-renderer').then((dislikeBtn) => { waitForElement<HTMLElement>('#dislike-button-renderer').then((dislikeBtn) => {
this.observer = new MutationObserver(() => { this.observer = new MutationObserver(() => {
if (dislikeBtn?.getAttribute('like-status') == 'DISLIKE') { if (dislikeBtn?.getAttribute('like-status') == 'DISLIKE') {
document document

View File

@ -0,0 +1,11 @@
export const waitForElement = <T extends Element>(selector: string): Promise<T> => {
return new Promise<T>((resolve) => {
const interval = setInterval(() => {
const elem = document.querySelector<T>(selector);
if (!elem) return;
clearInterval(interval);
resolve(elem);
});
});
};