feat(db): add tracks table and lyric scan caching

This commit is contained in:
2025-10-05 00:17:19 -04:00
parent 25ce2d676e
commit 8fb27b1acd
4 changed files with 185 additions and 2 deletions

View File

@@ -3,7 +3,8 @@
import { settings } from '$lib/stores/settings';
import { setSuccess, setWarning, setError, setInfo } from '$lib/stores/status';
import { checkApiStatus, fetchAndSaveLyrics } from '$lib/services/lrclib';
import { scanForTracksWithoutLyrics, type TrackWithoutLyrics } from '$lib/library/lyricScanner';
import { scanForTracksWithoutLyrics, loadCachedTracksWithoutLyrics, type TrackWithoutLyrics } from '$lib/library/lyricScanner';
import { getLyricsScanTimestamp, upsertTrack } from '$lib/library/database';
import ContextMenu, { type MenuItem } from '$lib/components/ContextMenu.svelte';
type ViewMode = 'tracks' | 'info';
@@ -16,11 +17,22 @@
let tracks = $state<TrackWithoutLyrics[]>([]);
let selectedTrackIndex = $state<number | null>(null);
let contextMenu = $state<{ x: number; y: number; trackIndex: number } | null>(null);
let lastScanned = $state<number | null>(null);
onMount(async () => {
await checkApi();
await loadCachedResults();
});
async function loadCachedResults() {
try {
tracks = await loadCachedTracksWithoutLyrics();
lastScanned = await getLyricsScanTimestamp();
} catch (error) {
console.error('[LRCLIB] Error loading cached results:', error);
}
}
async function checkApi() {
checkingApi = true;
apiAvailable = await checkApiStatus();
@@ -45,6 +57,7 @@
);
tracks = foundTracks;
lastScanned = await getLyricsScanTimestamp();
if (tracks.length === 0) {
setInfo('All tracks have lyrics!');
@@ -72,6 +85,17 @@
});
if (result.success) {
// Update database to mark track as having lyrics
await upsertTrack({
path: track.path,
title: track.title,
artist: track.artist,
album: track.album,
duration: Math.round(track.duration),
format: track.format,
has_lyrics: true
});
if (result.instrumental) {
setInfo(`Track marked as instrumental: ${track.title}`);
} else if (result.hasLyrics) {
@@ -194,7 +218,12 @@
{#if viewMode === 'tracks'}
<!-- Tracks View -->
<div class="tab-header">
<span>{tracks.length} track{tracks.length !== 1 ? 's' : ''} found</span>
<div class="header-left">
<span>{tracks.length} track{tracks.length !== 1 ? 's' : ''} found</span>
{#if lastScanned}
<span class="last-scanned">Last scanned: {new Date(lastScanned * 1000).toLocaleString()}</span>
{/if}
</div>
<div class="actions-row">
<button onclick={handleScan} disabled={scanning || !$settings.musicFolder}>
{scanning ? 'Scanning...' : 'Scan Library'}
@@ -337,6 +366,17 @@
flex-shrink: 0;
}
.header-left {
display: flex;
flex-direction: column;
gap: 4px;
}
.last-scanned {
font-size: 10px;
opacity: 0.6;
}
.status-row {
display: flex;
align-items: center;