mirror of
https://github.com/Psychotoxical/psysonic.git
synced 2026-07-22 07:15:47 +00:00
a78c0fe9ac
- fix(fonts): update CSS var declarations to @fontsource-variable naming
('Inter Variable', 'Outfit Variable', etc.) so dynamic font switching works
- fix(layout): 100vh → 100% on .app-shell to fix Windows WebView2 playerbar drift;
1fr → minmax(0,1fr) in all grid-template-rows + remove min-height: 720px to fix
Linux playerbar disappearing at high zoom or small window sizes
- fix(updater): replace shell open() with Rust open_folder command to bypass
shell:allow-open capability scope blocking local paths on Windows
- fix(lyrics): add get_embedded_lyrics Tauri command (id3 crate for MP3 SYLT/USLT,
lofty for FLAC SYNCEDLYRICS/LYRICS); fix parseLrc regex for LRC without fractional
seconds; fix SubsonicStructuredLyrics to accept both synced and issynced fields
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
50 lines
1.3 KiB
TypeScript
50 lines
1.3 KiB
TypeScript
export interface LrclibLyrics {
|
|
syncedLyrics: string | null;
|
|
plainLyrics: string | null;
|
|
}
|
|
|
|
export interface LrcLine {
|
|
time: number; // seconds
|
|
text: string;
|
|
}
|
|
|
|
export async function fetchLyrics(
|
|
artist: string,
|
|
title: string,
|
|
album: string,
|
|
duration: number,
|
|
): Promise<LrclibLyrics | null> {
|
|
const params = new URLSearchParams({
|
|
artist_name: artist,
|
|
track_name: title,
|
|
album_name: album,
|
|
duration: Math.round(duration).toString(),
|
|
});
|
|
try {
|
|
const res = await fetch(`https://lrclib.net/api/get?${params}`);
|
|
if (!res.ok) return null;
|
|
const data = await res.json();
|
|
return {
|
|
syncedLyrics: data.syncedLyrics ?? null,
|
|
plainLyrics: data.plainLyrics ?? null,
|
|
};
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
export function parseLrc(lrc: string): LrcLine[] {
|
|
const lines: LrcLine[] = [];
|
|
for (const line of lrc.split('\n')) {
|
|
// \d+(?:\.\d*)? — decimal part is optional so [mm:ss] (no fraction) also matches.
|
|
// parseFloat handles all forms: "15", "15.", "15.3", "15.32" correctly.
|
|
const match = line.match(/^\[(\d+):(\d+(?:\.\d*)?)\](.*)/);
|
|
if (!match) continue;
|
|
const mins = parseInt(match[1], 10);
|
|
const secs = parseFloat(match[2]);
|
|
const text = match[3].trim();
|
|
lines.push({ time: mins * 60 + secs, text });
|
|
}
|
|
return lines.sort((a, b) => a.time - b.time);
|
|
}
|