import { createEffect, createMemo, createSignal, For, Index, Match, onCleanup, onMount, type Setter, Switch, } from 'solid-js'; import { currentLyrics, lyricsStore, type ProviderName, providerNames, type ProviderState, setLyricsStore, } from '../../providers'; import { _ytAPI } from '../index'; import type { YtIcons } from '@/types/icons'; export const providerIdx = createMemo(() => providerNames.indexOf(lyricsStore.provider), ); const shouldSwitchProvider = (providerData: ProviderState) => { if (providerData.state === 'error') return true; if (providerData.state === 'fetching') return true; return ( providerData.state === 'done' && !providerData.data?.lines && !providerData.data?.lyrics ); }; const providerBias = (p: ProviderName) => (lyricsStore.lyrics[p].state === 'done' ? 1 : -1) + (lyricsStore.lyrics[p].data?.lines?.length ? 2 : -1) + (lyricsStore.lyrics[p].data?.lines?.length && p === 'YTMusic' ? 1 : 0) + (lyricsStore.lyrics[p].data?.lyrics ? 1 : -1); const pickBestProvider = () => { const providers = Array.from(providerNames); providers.sort((a, b) => providerBias(b) - providerBias(a)); return providers[0]; }; const [hasManuallySwitchedProvider, setHasManuallySwitchedProvider] = createSignal(false); export const LyricsPicker = (props: { setStickRef: Setter; }) => { createEffect(() => { // fallback to the next source, if the current one has an error if (!hasManuallySwitchedProvider()) { const bestProvider = pickBestProvider(); const allProvidersFailed = providerNames.every((p) => shouldSwitchProvider(lyricsStore.lyrics[p]), ); if (allProvidersFailed) return; if (providerBias(lyricsStore.provider) < providerBias(bestProvider)) { setLyricsStore('provider', bestProvider); } } }); onMount(() => { const videoDataChangeHandler = (name: string) => { if (name !== 'dataloaded') return; setHasManuallySwitchedProvider(false); }; _ytAPI?.addEventListener('videodatachange', videoDataChangeHandler); onCleanup(() => _ytAPI?.removeEventListener('videodatachange', videoDataChangeHandler), ); }); const next = () => { setHasManuallySwitchedProvider(true); setLyricsStore('provider', (prevProvider) => { const idx = providerNames.indexOf(prevProvider); return providerNames[(idx + 1) % providerNames.length]; }); }; const previous = () => { setHasManuallySwitchedProvider(true); setLyricsStore('provider', (prevProvider) => { const idx = providerNames.indexOf(prevProvider); return providerNames[ (idx + providerNames.length - 1) % providerNames.length ]; }); }; const chevronLeft: YtIcons = 'yt-icons:chevron_left'; const chevronRight: YtIcons = 'yt-icons:chevron_right'; const successIcon: YtIcons = 'yt-icons:check-circle'; const errorIcon: YtIcons = 'yt-icons:error'; const notFoundIcon: YtIcons = 'yt-icons:warning'; return (
    {(_, idx) => (
  • setLyricsStore('provider', providerNames[idx()])} style={{ background: idx() === providerIdx() ? 'white' : 'black', }} /> )}
); };