mirror of
https://github.com/th-ch/youtube-music.git
synced 2026-01-10 10:11:46 +00:00
fix: fix an issue with videodatachangefired timing
This commit is contained in:
@ -4,6 +4,8 @@ import style from './style.css?inline';
|
||||
|
||||
import { createPlugin } from '@/utils';
|
||||
|
||||
import type { VideoDataChanged } from '@/types/video-data-changed';
|
||||
|
||||
export default createPlugin({
|
||||
name: 'Album Color Theme',
|
||||
restartNeeded: true,
|
||||
@ -110,8 +112,8 @@ export default createPlugin({
|
||||
onPlayerApiReady(playerApi) {
|
||||
const fastAverageColor = new FastAverageColor();
|
||||
|
||||
playerApi.addEventListener('videodatachange', (name: string) => {
|
||||
if (name === 'dataloaded') {
|
||||
document.addEventListener('videodatachange', (event: CustomEvent<VideoDataChanged>) => {
|
||||
if (event.detail.name === 'dataloaded') {
|
||||
const playerResponse = playerApi.getPlayerResponse();
|
||||
const thumbnail = playerResponse?.videoDetails?.thumbnail?.thumbnails?.at(0);
|
||||
if (thumbnail) {
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { createPlugin } from '@/utils';
|
||||
|
||||
import type { VideoDataChanged } from '@/types/video-data-changed';
|
||||
import type { YoutubePlayer } from '@/types/youtube-player';
|
||||
|
||||
export type DisableAutoPlayPluginConfig = {
|
||||
@ -13,7 +14,7 @@ export default createPlugin<
|
||||
{
|
||||
config: DisableAutoPlayPluginConfig | null;
|
||||
api: YoutubePlayer | null;
|
||||
eventListener: (name: string) => void;
|
||||
eventListener: (event: CustomEvent<VideoDataChanged>) => void;
|
||||
timeUpdateListener: (e: Event) => void;
|
||||
},
|
||||
DisableAutoPlayPluginConfig
|
||||
@ -44,12 +45,12 @@ export default createPlugin<
|
||||
renderer: {
|
||||
config: null,
|
||||
api: null,
|
||||
eventListener(name: string) {
|
||||
eventListener(event: CustomEvent<VideoDataChanged>) {
|
||||
if (this.config?.applyOnce) {
|
||||
this.api?.removeEventListener('videodatachange', this.eventListener);
|
||||
document.removeEventListener('videodatachange', this.eventListener);
|
||||
}
|
||||
|
||||
if (name === 'dataloaded') {
|
||||
if (event.detail.name === 'dataloaded') {
|
||||
this.api?.pauseVideo();
|
||||
document.querySelector<HTMLVideoElement>('video')?.addEventListener('timeupdate', this.timeUpdateListener, { once: true });
|
||||
}
|
||||
@ -65,10 +66,10 @@ export default createPlugin<
|
||||
onPlayerApiReady(api) {
|
||||
this.api = api;
|
||||
|
||||
api.addEventListener('videodatachange', this.eventListener);
|
||||
document.addEventListener('videodatachange', this.eventListener);
|
||||
},
|
||||
stop() {
|
||||
this.api?.removeEventListener('videodatachange', this.eventListener);
|
||||
document.removeEventListener('videodatachange', this.eventListener);
|
||||
},
|
||||
onConfigChange(newConfig) {
|
||||
this.config = newConfig;
|
||||
|
||||
@ -13,28 +13,48 @@ import type { PluginConfig } from '@/types/plugins';
|
||||
import type { YoutubePlayer } from '@/types/youtube-player';
|
||||
|
||||
let api: (Element & YoutubePlayer) | null = null;
|
||||
let isPluginLoaded = false;
|
||||
let isApiLoaded = false;
|
||||
let firstDataLoaded = false;
|
||||
|
||||
async function listenForApiLoad() {
|
||||
api = document.querySelector('#movie_player');
|
||||
if (api) {
|
||||
await onApiLoaded();
|
||||
const observer = new MutationObserver(() => {
|
||||
const playerApi = document.querySelector<Element & YoutubePlayer>('#movie_player');
|
||||
if (playerApi) {
|
||||
observer.disconnect();
|
||||
|
||||
return;
|
||||
}
|
||||
// Inject song-info provider
|
||||
setupSongInfo(playerApi);
|
||||
const dataLoadedListener = (name: string) => {
|
||||
if (!firstDataLoaded && name === 'dataloaded') {
|
||||
firstDataLoaded = true;
|
||||
playerApi.removeEventListener('videodatachange', dataLoadedListener);
|
||||
}
|
||||
};
|
||||
playerApi.addEventListener('videodatachange', dataLoadedListener);
|
||||
|
||||
const observer = new MutationObserver(() => {
|
||||
api = document.querySelector('#movie_player');
|
||||
if (api) {
|
||||
observer.disconnect();
|
||||
if (isPluginLoaded && !isApiLoaded) {
|
||||
api = playerApi;
|
||||
isApiLoaded = true;
|
||||
|
||||
onApiLoaded();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
observer.observe(document.documentElement, {
|
||||
childList: true,
|
||||
subtree: true,
|
||||
});
|
||||
observer.observe(document.documentElement, {
|
||||
childList: true,
|
||||
subtree: true,
|
||||
});
|
||||
|
||||
async function listenForApiLoad() {
|
||||
if (!isApiLoaded) {
|
||||
api = document.querySelector('#movie_player');
|
||||
if (api) {
|
||||
await onApiLoaded();
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface YouTubeMusicAppElement extends HTMLElement {
|
||||
@ -45,9 +65,6 @@ async function onApiLoaded() {
|
||||
window.ipcRenderer.on('seekTo', (_, t: number) => api!.seekTo(t));
|
||||
window.ipcRenderer.on('seekBy', (_, t: number) => api!.seekBy(t));
|
||||
|
||||
// Inject song-info provider
|
||||
setupSongInfo(api!);
|
||||
|
||||
const video = document.querySelector('video')!;
|
||||
const audioContext = new AudioContext();
|
||||
const audioSource = audioContext.createMediaElementSource(video);
|
||||
@ -59,6 +76,10 @@ async function onApiLoaded() {
|
||||
}
|
||||
}
|
||||
|
||||
if (firstDataLoaded) {
|
||||
document.dispatchEvent(new CustomEvent('videodatachange', { detail: { name: 'dataloaded' } }));
|
||||
}
|
||||
|
||||
const audioCanPlayEventDispatcher = () => {
|
||||
document.dispatchEvent(
|
||||
new CustomEvent('audioCanPlay', {
|
||||
@ -128,6 +149,7 @@ async function onApiLoaded() {
|
||||
|
||||
(async () => {
|
||||
await loadAllRendererPlugins();
|
||||
isPluginLoaded = true;
|
||||
|
||||
window.ipcRenderer.on(
|
||||
'plugin:unload',
|
||||
|
||||
2
src/reset.d.ts
vendored
2
src/reset.d.ts
vendored
@ -4,6 +4,7 @@ import type { ipcRenderer as electronIpcRenderer } from 'electron';
|
||||
import type is from 'electron-is';
|
||||
|
||||
import type config from './config';
|
||||
import type { VideoDataChanged } from '@/types/video-data-changed';
|
||||
|
||||
declare global {
|
||||
interface Compressor {
|
||||
@ -13,6 +14,7 @@ declare global {
|
||||
|
||||
interface DocumentEventMap {
|
||||
'audioCanPlay': CustomEvent<Compressor>;
|
||||
'videodatachange': CustomEvent<VideoDataChanged>;
|
||||
}
|
||||
|
||||
interface Window {
|
||||
|
||||
6
src/types/video-data-changed.ts
Normal file
6
src/types/video-data-changed.ts
Normal file
@ -0,0 +1,6 @@
|
||||
import type { VideoDataChangeValue } from '@/types/player-api-events';
|
||||
|
||||
export interface VideoDataChanged {
|
||||
name: string;
|
||||
videoData?: VideoDataChangeValue;
|
||||
}
|
||||
Reference in New Issue
Block a user