fix: apply fix from eslint

This commit is contained in:
JellyBrick
2025-07-10 14:14:43 +09:00
parent 2cfc38757a
commit 1da83ff27c
29 changed files with 1654 additions and 168 deletions

View File

@ -1,12 +1,13 @@
import { createBackend } from '@/utils';
import { net } from 'electron';
import { createBackend } from '@/utils';
const handlers = {
// Note: This will only be used for Forbidden headers, e.g. User-Agent, Authority, Cookie, etc.
// See: https://developer.mozilla.org/en-US/docs/Glossary/Forbidden_request_header
async fetch(
url: string,
init: RequestInit
init: RequestInit,
): Promise<[number, string, Record<string, string>]> {
const res = await net.fetch(url, init);
return [
@ -19,7 +20,9 @@ const handlers = {
export const backend = createBackend({
start(ctx) {
ctx.ipc.handle('synced-lyrics:fetch', handlers.fetch);
ctx.ipc.handle('synced-lyrics:fetch', (url: string, init: RequestInit) =>
handlers.fetch(url, init),
);
},
stop(ctx) {
ctx.ipc.removeHandler('synced-lyrics:fetch');

View File

@ -17,7 +17,6 @@ export class LRCLib implements LyricProvider {
songDuration,
tags,
}: SearchSongInfo): Promise<LyricResult | null> {
let query = new URLSearchParams({
artist_name: artist,
track_name: title,
@ -59,7 +58,7 @@ export class LRCLib implements LyricProvider {
if (!Array.isArray(data)) {
throw new Error(`Expected an array, instead got ${typeof data}`);
}
// If still no results, try with the original title as fallback
if (data.length === 0 && alternativeTitle) {
query = new URLSearchParams({ q: title });
@ -98,15 +97,15 @@ export class LRCLib implements LyricProvider {
}
}
let ratio = Math.max(
...permutations.map(([x, y]) => jaroWinkler(x, y)),
);
let ratio = Math.max(...permutations.map(([x, y]) => jaroWinkler(x, y)));
// If direct artist match is below threshold and we have tags, try matching with tags
if (ratio <= 0.9 && tags && tags.length > 0) {
// Filter out the artist from tags to avoid duplicate comparisons
const filteredTags = tags.filter(tag => tag.toLowerCase() !== artist.toLowerCase());
const filteredTags = tags.filter(
(tag) => tag.toLowerCase() !== artist.toLowerCase(),
);
const tagPermutations = [];
// Compare each tag with each item artist
for (const tag of filteredTags) {
@ -114,19 +113,19 @@ export class LRCLib implements LyricProvider {
tagPermutations.push([tag.toLowerCase(), itemArtist.toLowerCase()]);
}
}
// Compare each item artist with each tag
for (const itemArtist of itemArtists) {
for (const tag of filteredTags) {
tagPermutations.push([itemArtist.toLowerCase(), tag.toLowerCase()]);
}
}
if (tagPermutations.length > 0) {
const tagRatio = Math.max(
...tagPermutations.map(([x, y]) => jaroWinkler(x, y)),
);
// Use the best match ratio between direct artist match and tag match
ratio = Math.max(ratio, tagRatio);
}

View File

@ -37,10 +37,13 @@ type LyricsStore = {
};
const initialData = () =>
providerNames.reduce((acc, name) => {
acc[name] = { state: 'fetching', data: null, error: null };
return acc;
}, {} as LyricsStore['lyrics']);
providerNames.reduce(
(acc, name) => {
acc[name] = { state: 'fetching', data: null, error: null };
return acc;
},
{} as LyricsStore['lyrics'],
);
export const [lyricsStore, setLyricsStore] = createStore<LyricsStore>({
provider: providerNames[0],

View File

@ -10,11 +10,13 @@ interface PlainLyricsProps {
export const PlainLyrics = (props: PlainLyricsProps) => {
const [romanization, setRomanization] = createSignal('');
createEffect(async () => {
createEffect(() => {
if (!config()?.romanization) return;
const input = canonicalize(props.line);
setRomanization(canonicalize(await romanize(input)));
romanize(input).then((result) => {
setRomanization(canonicalize(result));
});
});
return (

View File

@ -1,13 +1,14 @@
import { createEffect, createMemo, For, Show, createSignal } from 'solid-js';
import { VirtualizerHandle } from 'virtua/solid';
import { LineLyrics } from '@/plugins/synced-lyrics/types';
import { config } from '../renderer';
import { _ytAPI } from '..';
import { canonicalize, romanize, simplifyUnicode } from '../utils';
import { VirtualizerHandle } from 'virtua/solid';
import { LineLyrics } from '@/plugins/synced-lyrics/types';
interface SyncedLineProps {
scroller: VirtualizerHandle;
index: number;
@ -27,80 +28,57 @@ export const SyncedLine = (props: SyncedLineProps) => {
const [romanization, setRomanization] = createSignal('');
createEffect(async () => {
createEffect(() => {
if (!config()?.romanization) return;
const input = canonicalize(text());
setRomanization(canonicalize(await romanize(input)));
romanize(input).then((result) => {
setRomanization(canonicalize(result));
});
});
if (!text()) {
return (
<yt-formatted-string
text={{
runs: [{ text: '' }],
}}
/>
);
}
return (
<div
class={`synced-line ${props.status}`}
onClick={() => {
_ytAPI?.seekTo((props.line.timeInMs + 10) / 1000);
}}
>
<div dir="auto" class="description ytmusic-description-shelf-renderer">
<Show
when={text()}
fallback={
<yt-formatted-string
text={{
runs: [
{ text: config()?.showTimeCodes ? `[${props.line.time}] ` : '' },
],
runs: [{ text: '' }],
}}
/>
}
>
<div
class={`synced-line ${props.status}`}
onClick={() => {
_ytAPI?.seekTo((props.line.timeInMs + 10) / 1000);
}}
>
<div dir="auto" class="description ytmusic-description-shelf-renderer">
<yt-formatted-string
text={{
runs: [
{
text: config()?.showTimeCodes ? `[${props.line.time}] ` : '',
},
],
}}
/>
<div
class="text-lyrics"
ref={(div: HTMLDivElement) => {
// TODO: Investigate the animation, even though the duration is properly set, all lines have the same animation duration
div.style.setProperty(
'--lyrics-duration',
`${props.line.duration / 1000}s`,
'important',
);
}}
style={{ 'display': 'flex', 'flex-direction': 'column' }}
>
<span>
<For each={text().split(' ')}>
{(word, index) => {
return (
<span
style={{
'transition-delay': `${index() * 0.05}s`,
'animation-delay': `${index() * 0.05}s`,
}}
>
<yt-formatted-string
text={{
runs: [{ text: `${word} ` }],
}}
/>
</span>
);
}}
</For>
</span>
<Show
when={
config()?.romanization &&
simplifyUnicode(text()) !== simplifyUnicode(romanization())
}
<div
class="text-lyrics"
ref={(div: HTMLDivElement) => {
// TODO: Investigate the animation, even though the duration is properly set, all lines have the same animation duration
div.style.setProperty(
'--lyrics-duration',
`${props.line.duration / 1000}s`,
'important',
);
}}
style={{ 'display': 'flex', 'flex-direction': 'column' }}
>
<span class="romaji">
<For each={romanization().split(' ')}>
<span>
<For each={text().split(' ')}>
{(word, index) => {
return (
<span
@ -119,9 +97,37 @@ export const SyncedLine = (props: SyncedLineProps) => {
}}
</For>
</span>
</Show>
<Show
when={
config()?.romanization &&
simplifyUnicode(text()) !== simplifyUnicode(romanization())
}
>
<span class="romaji">
<For each={romanization().split(' ')}>
{(word, index) => {
return (
<span
style={{
'transition-delay': `${index() * 0.05}s`,
'animation-delay': `${index() * 0.05}s`,
}}
>
<yt-formatted-string
text={{
runs: [{ text: `${word} ` }],
}}
/>
</span>
);
}}
</For>
</span>
</Show>
</div>
</div>
</div>
</div>
</Show>
);
};

View File

@ -14,7 +14,7 @@ import type { SyncedLyricsPluginConfig } from '../types';
export let _ytAPI: YoutubePlayer | null = null;
export let netFetch: (
url: string,
init?: RequestInit
init?: RequestInit,
) => Promise<[number, string, Record<string, string>]>;
export const renderer = createRenderer<
@ -56,7 +56,7 @@ export const renderer = createRenderer<
if (!this.updateTimestampInterval) {
this.updateTimestampInterval = setInterval(
() => setCurrentTime((_ytAPI?.getCurrentTime() ?? 0) * 1000),
100
100,
);
}

View File

@ -10,11 +10,11 @@ import pinyin from 'tiny-pinyin';
import { lazy } from 'lazy-var';
import { detect } from 'tinyld';
import { waitForElement } from '@/utils/wait-for-element';
import { LyricsRenderer, setIsVisible } from './renderer';
import { detect } from 'tinyld';
export const selectors = {
head: '#tabsContent > .tab-header:nth-of-type(2)',
body: {