mirror of
https://github.com/th-ch/youtube-music.git
synced 2026-01-13 03:11:46 +00:00
feat: migrate to new plugin api
Co-authored-by: Su-Yong <simssy2205@gmail.com>
This commit is contained in:
26
src/plugins/lyrics-genius/index.ts
Normal file
26
src/plugins/lyrics-genius/index.ts
Normal file
@ -0,0 +1,26 @@
|
||||
import style from './style.css?inline';
|
||||
|
||||
import { createPluginBuilder } from '../utils/builder';
|
||||
|
||||
export type LyricsGeniusPluginConfig = {
|
||||
enabled: boolean;
|
||||
romanizedLyrics: boolean;
|
||||
}
|
||||
|
||||
const builder = createPluginBuilder('lyrics-genius', {
|
||||
name: 'Lyrics Genius',
|
||||
restartNeeded: true,
|
||||
config: {
|
||||
enabled: false,
|
||||
romanizedLyrics: false,
|
||||
} as LyricsGeniusPluginConfig,
|
||||
styles: [style],
|
||||
});
|
||||
|
||||
export default builder;
|
||||
|
||||
declare global {
|
||||
interface PluginBuilderList {
|
||||
[builder.id]: typeof builder;
|
||||
}
|
||||
}
|
||||
@ -1,37 +1,35 @@
|
||||
import { BrowserWindow, ipcMain, net } from 'electron';
|
||||
import { net } from 'electron';
|
||||
import is from 'electron-is';
|
||||
import { convert } from 'html-to-text';
|
||||
|
||||
import style from './style.css';
|
||||
import { GetGeniusLyric } from './types';
|
||||
|
||||
import { cleanupName, SongInfo } from '../../providers/song-info';
|
||||
import builder from './index';
|
||||
|
||||
import { injectCSS } from '../utils/main';
|
||||
|
||||
import type { ConfigType } from '../../config/dynamic';
|
||||
import { cleanupName, type SongInfo } from '../../providers/song-info';
|
||||
|
||||
const eastAsianChars = /\p{Script=Katakana}|\p{Script=Hiragana}|\p{Script=Hangul}|\p{Script=Han}/u;
|
||||
let revRomanized = false;
|
||||
|
||||
export type LyricGeniusType = ConfigType<'lyrics-genius'>;
|
||||
export default builder.createMain(({ handle, getConfig }) =>{
|
||||
return {
|
||||
async onLoad() {
|
||||
const config = await getConfig();
|
||||
|
||||
export default (win: BrowserWindow, options: LyricGeniusType) => {
|
||||
if (options.romanizedLyrics) {
|
||||
revRomanized = true;
|
||||
}
|
||||
if (config.romanizedLyrics) {
|
||||
revRomanized = true;
|
||||
}
|
||||
|
||||
injectCSS(win.webContents, style);
|
||||
|
||||
ipcMain.handle('search-genius-lyrics', async (_, extractedSongInfo: SongInfo) => {
|
||||
const metadata = extractedSongInfo;
|
||||
return await fetchFromGenius(metadata);
|
||||
});
|
||||
};
|
||||
|
||||
export const toggleRomanized = () => {
|
||||
revRomanized = !revRomanized;
|
||||
};
|
||||
handle('search-genius-lyrics', async (_, extractedSongInfo: SongInfo) => {
|
||||
const metadata = extractedSongInfo;
|
||||
return await fetchFromGenius(metadata);
|
||||
});
|
||||
},
|
||||
onConfigChange(newConfig) {
|
||||
revRomanized = newConfig.romanizedLyrics;
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
export const fetchFromGenius = async (metadata: SongInfo) => {
|
||||
const songTitle = `${cleanupName(metadata.title)}`;
|
||||
|
||||
@ -1,19 +1,18 @@
|
||||
import { BrowserWindow, MenuItem } from 'electron';
|
||||
import builder from './index';
|
||||
|
||||
import { LyricGeniusType, toggleRomanized } from './main';
|
||||
export default builder.createMenu(async ({ getConfig, setConfig }) => {
|
||||
const config = await getConfig();
|
||||
|
||||
import { setOptions } from '../../config/plugins';
|
||||
import { MenuTemplate } from '../../menu';
|
||||
|
||||
export default (_: BrowserWindow, options: LyricGeniusType): MenuTemplate => [
|
||||
{
|
||||
label: 'Romanized Lyrics',
|
||||
type: 'checkbox',
|
||||
checked: options.romanizedLyrics,
|
||||
click(item: MenuItem) {
|
||||
options.romanizedLyrics = item.checked;
|
||||
setOptions('lyrics-genius', options);
|
||||
toggleRomanized();
|
||||
return [
|
||||
{
|
||||
label: 'Romanized Lyrics',
|
||||
type: 'checkbox',
|
||||
checked: config.romanizedLyrics,
|
||||
click(item) {
|
||||
setConfig({
|
||||
romanizedLyrics: item.checked,
|
||||
});
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
];
|
||||
});
|
||||
|
||||
@ -1,8 +1,11 @@
|
||||
import builder from './index';
|
||||
|
||||
import type { SongInfo } from '../../providers/song-info';
|
||||
|
||||
export default () => {
|
||||
const setLyrics = (lyricsContainer: Element, lyrics: string | null) => {
|
||||
lyricsContainer.innerHTML = `
|
||||
export default builder.createRenderer(({ on, invoke }) => ({
|
||||
onLoad() {
|
||||
const setLyrics = (lyricsContainer: Element, lyrics: string | null) => {
|
||||
lyricsContainer.innerHTML = `
|
||||
<div id="contents" class="style-scope ytmusic-section-list-renderer description ytmusic-description-shelf-renderer genius-lyrics">
|
||||
${lyrics?.replaceAll(/\r\n|\r|\n/g, '<br/>') ?? 'Could not retrieve lyrics from genius'}
|
||||
</div>
|
||||
@ -10,96 +13,97 @@ export default () => {
|
||||
</yt-formatted-string>
|
||||
`;
|
||||
|
||||
if (lyrics) {
|
||||
const footer = lyricsContainer.querySelector('.footer');
|
||||
if (lyrics) {
|
||||
const footer = lyricsContainer.querySelector('.footer');
|
||||
|
||||
if (footer) {
|
||||
footer.textContent = 'Source: Genius';
|
||||
if (footer) {
|
||||
footer.textContent = 'Source: Genius';
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
let unregister: (() => void) | null = null;
|
||||
let unregister: (() => void) | null = null;
|
||||
|
||||
window.ipcRenderer.on('update-song-info', (_, extractedSongInfo: SongInfo) => {
|
||||
unregister?.();
|
||||
on('update-song-info', (_, extractedSongInfo: SongInfo) => {
|
||||
unregister?.();
|
||||
|
||||
setTimeout(async () => {
|
||||
const tabList = document.querySelectorAll<HTMLElement>('tp-yt-paper-tab');
|
||||
const tabs = {
|
||||
upNext: tabList[0],
|
||||
lyrics: tabList[1],
|
||||
discover: tabList[2],
|
||||
};
|
||||
setTimeout(async () => {
|
||||
const tabList = document.querySelectorAll<HTMLElement>('tp-yt-paper-tab');
|
||||
const tabs = {
|
||||
upNext: tabList[0],
|
||||
lyrics: tabList[1],
|
||||
discover: tabList[2],
|
||||
};
|
||||
|
||||
// Check if disabled
|
||||
if (!tabs.lyrics?.hasAttribute('disabled')) return;
|
||||
// Check if disabled
|
||||
if (!tabs.lyrics?.hasAttribute('disabled')) return;
|
||||
|
||||
const lyrics = await window.ipcRenderer.invoke(
|
||||
'search-genius-lyrics',
|
||||
extractedSongInfo,
|
||||
) as string | null;
|
||||
|
||||
if (!lyrics) {
|
||||
// Delete previous lyrics if tab is open and couldn't get new lyrics
|
||||
tabs.upNext.click();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (window.electronIs.dev()) {
|
||||
console.log('Fetched lyrics from Genius');
|
||||
}
|
||||
|
||||
const tryToInjectLyric = (callback?: () => void) => {
|
||||
const lyricsContainer = document.querySelector(
|
||||
'[page-type="MUSIC_PAGE_TYPE_TRACK_LYRICS"] > ytmusic-message-renderer',
|
||||
const lyrics = await invoke<string | null>(
|
||||
'search-genius-lyrics',
|
||||
extractedSongInfo,
|
||||
);
|
||||
|
||||
if (lyricsContainer) {
|
||||
callback?.();
|
||||
if (!lyrics) {
|
||||
// Delete previous lyrics if tab is open and couldn't get new lyrics
|
||||
tabs.upNext.click();
|
||||
|
||||
setLyrics(lyricsContainer, lyrics);
|
||||
applyLyricsTabState();
|
||||
return;
|
||||
}
|
||||
};
|
||||
const applyLyricsTabState = () => {
|
||||
if (lyrics) {
|
||||
tabs.lyrics.removeAttribute('disabled');
|
||||
tabs.lyrics.removeAttribute('aria-disabled');
|
||||
} else {
|
||||
tabs.lyrics.setAttribute('disabled', '');
|
||||
tabs.lyrics.setAttribute('aria-disabled', '');
|
||||
|
||||
if (window.electronIs.dev()) {
|
||||
console.log('Fetched lyrics from Genius');
|
||||
}
|
||||
};
|
||||
const lyricsTabHandler = () => {
|
||||
const tabContainer = document.querySelector('ytmusic-tab-renderer');
|
||||
if (!tabContainer) return;
|
||||
|
||||
const observer = new MutationObserver((_, observer) => {
|
||||
tryToInjectLyric(() => observer.disconnect());
|
||||
});
|
||||
const tryToInjectLyric = (callback?: () => void) => {
|
||||
const lyricsContainer = document.querySelector(
|
||||
'[page-type="MUSIC_PAGE_TYPE_TRACK_LYRICS"] > ytmusic-message-renderer',
|
||||
);
|
||||
|
||||
observer.observe(tabContainer, {
|
||||
attributes: true,
|
||||
childList: true,
|
||||
subtree: true,
|
||||
});
|
||||
};
|
||||
if (lyricsContainer) {
|
||||
callback?.();
|
||||
|
||||
applyLyricsTabState();
|
||||
setLyrics(lyricsContainer, lyrics);
|
||||
applyLyricsTabState();
|
||||
}
|
||||
};
|
||||
const applyLyricsTabState = () => {
|
||||
if (lyrics) {
|
||||
tabs.lyrics.removeAttribute('disabled');
|
||||
tabs.lyrics.removeAttribute('aria-disabled');
|
||||
} else {
|
||||
tabs.lyrics.setAttribute('disabled', '');
|
||||
tabs.lyrics.setAttribute('aria-disabled', '');
|
||||
}
|
||||
};
|
||||
const lyricsTabHandler = () => {
|
||||
const tabContainer = document.querySelector('ytmusic-tab-renderer');
|
||||
if (!tabContainer) return;
|
||||
|
||||
tabs.discover.addEventListener('click', applyLyricsTabState);
|
||||
tabs.lyrics.addEventListener('click', lyricsTabHandler);
|
||||
tabs.upNext.addEventListener('click', applyLyricsTabState);
|
||||
const observer = new MutationObserver((_, observer) => {
|
||||
tryToInjectLyric(() => observer.disconnect());
|
||||
});
|
||||
|
||||
tryToInjectLyric();
|
||||
observer.observe(tabContainer, {
|
||||
attributes: true,
|
||||
childList: true,
|
||||
subtree: true,
|
||||
});
|
||||
};
|
||||
|
||||
unregister = () => {
|
||||
tabs.discover.removeEventListener('click', applyLyricsTabState);
|
||||
tabs.lyrics.removeEventListener('click', lyricsTabHandler);
|
||||
tabs.upNext.removeEventListener('click', applyLyricsTabState);
|
||||
};
|
||||
}, 500);
|
||||
});
|
||||
};
|
||||
applyLyricsTabState();
|
||||
|
||||
tabs.discover.addEventListener('click', applyLyricsTabState);
|
||||
tabs.lyrics.addEventListener('click', lyricsTabHandler);
|
||||
tabs.upNext.addEventListener('click', applyLyricsTabState);
|
||||
|
||||
tryToInjectLyric();
|
||||
|
||||
unregister = () => {
|
||||
tabs.discover.removeEventListener('click', applyLyricsTabState);
|
||||
tabs.lyrics.removeEventListener('click', lyricsTabHandler);
|
||||
tabs.upNext.removeEventListener('click', applyLyricsTabState);
|
||||
};
|
||||
}, 500);
|
||||
});
|
||||
}
|
||||
}));
|
||||
|
||||
Reference in New Issue
Block a user