mirror of
https://github.com/th-ch/youtube-music.git
synced 2026-01-14 20:01:47 +00:00
plugin: Synced Lyrics (#2207)
* Added Plugin File * Added Logic * Known issue * Finished Backend part * Before cleanup * Added Style Removed log * Fixed time and visibility issues * Changed lyrics style * Changed way lyrics are selected * Fix * Added style lyrics options * Cleanup * Fix lyrics styling Changed how lyrics status are changed * Moved code to make file more readable * Change Tab Size * Fixed issue with overlapping lyrics * Removed debug console.log * Added style adaptation for music videos * Changed file indent * Revered back to original pnpm file * Removed unnecessary option * Fix lyrics status bug Removed leftover logs * Started to implement fetching for genius lyrics * feat(synced-lyrics): add `addedVersion` field * Made changes according to feedbacks * fix: add a delay of 300ms to the current time - Since the transition takes 300ms, we need to add a delay of 300ms to the current time * Removed test about genius.com scraping * Removed 300ms delay * chore: cleaned up the code * Specified path and variable * chore: always enable lyrics tab * chore: use SolidJS to render the lyrics * chore: remove useless signal * chore: feature-parity with original PR (+some nice stuff) * recreate lock file * show json decode error * feat(synced-lyrics): improve ui - Change type assertion code - Replace span to `yt-formatted-string` - Add refetch button * chore: make the lyric styling a solidjs effect * feat: i18n * chore: apply suggestion --------- Co-authored-by: Su-Yong <simssy2205@gmail.com> Co-authored-by: JellyBrick <shlee1503@naver.com> Co-authored-by: Angelos Bouklis <53124886+ArjixWasTaken@users.noreply.github.com>
This commit is contained in:
90
src/plugins/synced-lyrics/renderer/index.ts
Normal file
90
src/plugins/synced-lyrics/renderer/index.ts
Normal file
@ -0,0 +1,90 @@
|
||||
/* eslint-disable prefer-const, @typescript-eslint/no-unused-vars */
|
||||
|
||||
import { createRenderer } from '@/utils';
|
||||
import { SongInfo } from '@/providers/song-info';
|
||||
import { YoutubePlayer } from '@/types/youtube-player';
|
||||
|
||||
import { makeLyricsRequest } from './lyrics';
|
||||
import { selectors, tabStates } from './utils';
|
||||
import { setConfig } from './renderer';
|
||||
import { setCurrentTime } from './components/LyricsContainer';
|
||||
|
||||
import type { SyncedLyricsPluginConfig } from '../types';
|
||||
|
||||
export let _ytAPI: YoutubePlayer | null = null;
|
||||
|
||||
export const renderer = createRenderer({
|
||||
onConfigChange(newConfig) {
|
||||
setConfig(newConfig as SyncedLyricsPluginConfig);
|
||||
},
|
||||
|
||||
observerCallback(mutations: MutationRecord[]) {
|
||||
for (const mutation of mutations) {
|
||||
const header = mutation.target as HTMLElement;
|
||||
|
||||
switch (mutation.attributeName) {
|
||||
case 'disabled':
|
||||
header.removeAttribute('disabled');
|
||||
break;
|
||||
case 'aria-selected':
|
||||
tabStates[header.ariaSelected as 'true' | 'false']?.(
|
||||
_ytAPI?.getVideoData(),
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
onPlayerApiReady(api) {
|
||||
_ytAPI = api;
|
||||
|
||||
// @ts-expect-error type is 'unknown', so TS complains
|
||||
api.addEventListener('videodatachange', this.videoDataChange);
|
||||
|
||||
// @ts-expect-error type is 'unknown', so TS complains
|
||||
this.videoDataChange();
|
||||
},
|
||||
|
||||
hasAddedEvents: false,
|
||||
observer: null as MutationObserver | null,
|
||||
videoDataChange() {
|
||||
if (!this.hasAddedEvents) {
|
||||
const video = document.querySelector('video');
|
||||
|
||||
// @ts-expect-error type is 'unknown', so TS complains
|
||||
video?.addEventListener('timeupdate', this.progressCallback);
|
||||
|
||||
if (video) this.hasAddedEvents = true;
|
||||
}
|
||||
|
||||
const header = document.querySelector<HTMLElement>(selectors.head);
|
||||
if (!header) return;
|
||||
|
||||
this.observer ??= new MutationObserver(
|
||||
this.observerCallback as MutationCallback,
|
||||
);
|
||||
|
||||
// Force the lyrics tab to be enabled at all times.
|
||||
this.observer.disconnect();
|
||||
this.observer.observe(header, { attributes: true });
|
||||
header.removeAttribute('disabled');
|
||||
},
|
||||
|
||||
progressCallback(evt: Event) {
|
||||
switch (evt.type) {
|
||||
case 'timeupdate': {
|
||||
const video = evt.target as HTMLVideoElement;
|
||||
setCurrentTime(video.currentTime * 1000);
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
async start({ getConfig, ipc: { on } }) {
|
||||
setConfig((await getConfig()) as SyncedLyricsPluginConfig);
|
||||
|
||||
on('ytmd:update-song-info', async (info: SongInfo) => {
|
||||
await makeLyricsRequest(info);
|
||||
});
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user