From ebee3fafd40e09d6f085c538836a1c9fd4d4a52e Mon Sep 17 00:00:00 2001 From: InstaZDLL Date: Mon, 18 May 2026 03:49:09 +0200 Subject: [PATCH 1/3] fix(lyrics): surface result of library lyrics prefetch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Same silent-success bug as the missing-covers batch action: when every track already has cached lyrics (or the user is in offline mode), the backend returned silently and the UI never moved — the button looked dead. - backend: emit an initial `lyrics:prefetch-progress` event with total=N (including N=0) so the UI can show "nothing to do" instead of staying frozen on the subtitle. - frontend: capture the returned summary and show a short result message in the row subtitle for 5s ("X synced, Y not found, Z failed") or an explicit "Offline mode is enabled" / "Prefetch failed" message on error. - i18n: new `settings.lyricsPrefetch.result` / `.offline` / `.failed` keys propagated to all 17 locales. --- src-tauri/src/commands/lyrics.rs | 15 ++++++++++++++ src/components/views/SettingsView.tsx | 28 +++++++++++++++++++++++++-- src/i18n/locales/ar.json | 3 +++ src/i18n/locales/de.json | 3 +++ src/i18n/locales/en.json | 3 +++ src/i18n/locales/es.json | 3 +++ src/i18n/locales/fr.json | 3 +++ src/i18n/locales/hi.json | 3 +++ src/i18n/locales/id.json | 3 +++ src/i18n/locales/it.json | 3 +++ src/i18n/locales/ja.json | 3 +++ src/i18n/locales/kr.json | 3 +++ src/i18n/locales/nl.json | 3 +++ src/i18n/locales/pt-BR.json | 3 +++ src/i18n/locales/pt.json | 3 +++ src/i18n/locales/ru.json | 3 +++ src/i18n/locales/tr.json | 3 +++ src/i18n/locales/zh-CN.json | 3 +++ src/i18n/locales/zh-TW.json | 3 +++ 19 files changed, 92 insertions(+), 2 deletions(-) diff --git a/src-tauri/src/commands/lyrics.rs b/src-tauri/src/commands/lyrics.rs index 6746273..03e33eb 100644 --- a/src-tauri/src/commands/lyrics.rs +++ b/src-tauri/src/commands/lyrics.rs @@ -696,6 +696,21 @@ async fn run_prefetch( let mut misses = 0u32; let mut failed = 0u32; + // Emit an initial frame so the UI can show the total — and explicitly + // surface the "nothing to do" case (total == 0) which otherwise looks + // like the button does nothing. + let _ = app.emit( + "lyrics:prefetch-progress", + LyricsPrefetchProgress { + processed: 0, + total, + hits: 0, + misses: 0, + failed: 0, + current_title: None, + }, + ); + let client = LrclibClient::new(); let mut cancelled = false; diff --git a/src/components/views/SettingsView.tsx b/src/components/views/SettingsView.tsx index cf1796e..ca519bc 100644 --- a/src/components/views/SettingsView.tsx +++ b/src/components/views/SettingsView.tsx @@ -708,6 +708,7 @@ export function SettingsView({ onNavigate }: SettingsViewProps) { failed: number; currentTitle: string | null; } | null>(null); + const [lyricsResultMsg, setLyricsResultMsg] = useState(null); useEffect(() => { let unlisten: (() => void) | null = null; @@ -741,14 +742,33 @@ export function SettingsView({ onNavigate }: SettingsViewProps) { if (isPrefetchingLyrics) return; setIsPrefetchingLyrics(true); setLyricsPrefetchProgress(null); + setLyricsResultMsg(null); try { const { prefetchLibraryLyrics } = await import("../../lib/tauri/lyrics"); - await prefetchLibraryLyrics(); + const summary = await prefetchLibraryLyrics(); + setLyricsResultMsg( + t("settings.lyricsPrefetch.result", { + hits: summary.hits, + misses: summary.misses, + failed: summary.failed, + }), + ); } catch (err) { console.error("[SettingsView] prefetch lyrics failed", err); + // Distinguish offline mode (the user can act on it) from a real + // failure so the message is not just a generic "something broke". + const msg = String(err); + setLyricsResultMsg( + msg.includes("offline") + ? t("settings.lyricsPrefetch.offline") + : t("settings.lyricsPrefetch.failed"), + ); } finally { setIsPrefetchingLyrics(false); - window.setTimeout(() => setLyricsPrefetchProgress(null), 3000); + window.setTimeout(() => { + setLyricsPrefetchProgress(null); + setLyricsResultMsg(null); + }, 5000); } }; @@ -2464,6 +2484,10 @@ export function SettingsView({ onNavigate }: SettingsViewProps) { ? ` — ${lyricsPrefetchProgress.currentTitle}` : ""} + ) : lyricsResultMsg ? ( +
+ {lyricsResultMsg} +
) : (
{t("settings.lyricsPrefetch.subtitle")} diff --git a/src/i18n/locales/ar.json b/src/i18n/locales/ar.json index 340ee0c..1b7619b 100644 --- a/src/i18n/locales/ar.json +++ b/src/i18n/locales/ar.json @@ -1244,6 +1244,9 @@ "lyricsPrefetch": { "title": "تحميل كلمات الأغاني مسبقًا", "subtitle": "تنزيل كلمات الأغاني للمكتبة بأكملها للاستخدام دون اتصال", + "result": "تم تزامن {{hits}}، لم يتم العثور على {{misses}}، فشل {{failed}}", + "offline": "وضع عدم الاتصال مفعّل", + "failed": "فشل التحميل المسبق", "action": "تحميل مسبق", "progress": "تم معالجة {{current}}/{{total}} · {{hits}} عُثر عليها" }, diff --git a/src/i18n/locales/de.json b/src/i18n/locales/de.json index 9d35bc9..af42e69 100644 --- a/src/i18n/locales/de.json +++ b/src/i18n/locales/de.json @@ -1240,6 +1240,9 @@ "lyricsPrefetch": { "title": "Songtexte vorab laden", "subtitle": "Songtexte der gesamten Bibliothek für Offline-Nutzung herunterladen", + "result": "{{hits}} synchronisiert, {{misses}} nicht gefunden, {{failed}} fehlgeschlagen", + "offline": "Offlinemodus aktiviert", + "failed": "Vorabladen fehlgeschlagen", "action": "Vorab laden", "progress": "{{current}}/{{total}} verarbeitet · {{hits}} gefunden" }, diff --git a/src/i18n/locales/en.json b/src/i18n/locales/en.json index 4e83972..b22305a 100644 --- a/src/i18n/locales/en.json +++ b/src/i18n/locales/en.json @@ -1294,6 +1294,9 @@ "lyricsPrefetch": { "title": "Prefetch lyrics", "subtitle": "Download lyrics for the entire library for offline use", + "result": "{{hits}} synced, {{misses}} not found, {{failed}} failed", + "offline": "Offline mode is enabled", + "failed": "Prefetch failed", "action": "Prefetch", "progress": "{{current}}/{{total}} processed · {{hits}} found" }, diff --git a/src/i18n/locales/es.json b/src/i18n/locales/es.json index a5efd93..8b79a58 100644 --- a/src/i18n/locales/es.json +++ b/src/i18n/locales/es.json @@ -1240,6 +1240,9 @@ "lyricsPrefetch": { "title": "Precargar letras", "subtitle": "Descargar las letras de toda la biblioteca para uso sin conexión", + "result": "{{hits}} sincronizadas, {{misses}} no encontradas, {{failed}} fallidas", + "offline": "Modo sin conexión activado", + "failed": "Error al precargar", "action": "Precargar", "progress": "{{current}}/{{total}} procesadas · {{hits}} encontradas" }, diff --git a/src/i18n/locales/fr.json b/src/i18n/locales/fr.json index f3809fb..9704fa2 100644 --- a/src/i18n/locales/fr.json +++ b/src/i18n/locales/fr.json @@ -1318,6 +1318,9 @@ "lyricsPrefetch": { "title": "Préchargement des paroles", "subtitle": "Télécharger les paroles de toute la bibliothèque pour usage hors-ligne", + "result": "{{hits}} synchronisées, {{misses}} introuvables, {{failed}} échecs", + "offline": "Mode hors-ligne activé", + "failed": "Échec du préchargement", "action": "Précharger", "progress": "{{current}}/{{total}} traités · {{hits}} trouvés" }, diff --git a/src/i18n/locales/hi.json b/src/i18n/locales/hi.json index 8631aa1..37d8136 100644 --- a/src/i18n/locales/hi.json +++ b/src/i18n/locales/hi.json @@ -1240,6 +1240,9 @@ "lyricsPrefetch": { "title": "बोल पहले से लोड करें", "subtitle": "ऑफ़लाइन उपयोग के लिए पूरी लाइब्रेरी के बोल डाउनलोड करें", + "result": "{{hits}} सिंक्ड, {{misses}} नहीं मिलीं, {{failed}} विफल", + "offline": "ऑफ़लाइन मोड सक्षम है", + "failed": "प्रीफ़ेच विफल", "action": "पहले से लोड करें", "progress": "{{current}}/{{total}} संसाधित · {{hits}} मिले" }, diff --git a/src/i18n/locales/id.json b/src/i18n/locales/id.json index c5599f0..29316ad 100644 --- a/src/i18n/locales/id.json +++ b/src/i18n/locales/id.json @@ -1239,6 +1239,9 @@ "lyricsPrefetch": { "title": "Pramuat lirik", "subtitle": "Unduh lirik untuk seluruh pustaka untuk penggunaan offline", + "result": "{{hits}} disinkronkan, {{misses}} tidak ditemukan, {{failed}} gagal", + "offline": "Mode luring diaktifkan", + "failed": "Pra-pemuatan gagal", "action": "Pramuat", "progress": "{{current}}/{{total}} diproses · {{hits}} ditemukan" }, diff --git a/src/i18n/locales/it.json b/src/i18n/locales/it.json index db37f8c..22ffb6f 100644 --- a/src/i18n/locales/it.json +++ b/src/i18n/locales/it.json @@ -1240,6 +1240,9 @@ "lyricsPrefetch": { "title": "Precarica i testi", "subtitle": "Scarica i testi dell’intera libreria per l’uso offline", + "result": "{{hits}} sincronizzati, {{misses}} non trovati, {{failed}} falliti", + "offline": "Modalità offline attiva", + "failed": "Precaricamento non riuscito", "action": "Precarica", "progress": "{{current}}/{{total}} elaborati · {{hits}} trovati" }, diff --git a/src/i18n/locales/ja.json b/src/i18n/locales/ja.json index 11b5d87..dc2494b 100644 --- a/src/i18n/locales/ja.json +++ b/src/i18n/locales/ja.json @@ -1239,6 +1239,9 @@ "lyricsPrefetch": { "title": "歌詞を事前取得", "subtitle": "オフライン利用のためライブラリ全体の歌詞をダウンロードします", + "result": "{{hits}} 件同期、{{misses}} 件見つからず、{{failed}} 件失敗", + "offline": "オフラインモードが有効です", + "failed": "プリフェッチに失敗しました", "action": "事前取得", "progress": "{{current}}/{{total}} 処理済み · {{hits}} 件取得" }, diff --git a/src/i18n/locales/kr.json b/src/i18n/locales/kr.json index 63dfc36..9366696 100644 --- a/src/i18n/locales/kr.json +++ b/src/i18n/locales/kr.json @@ -1239,6 +1239,9 @@ "lyricsPrefetch": { "title": "가사 미리 가져오기", "subtitle": "오프라인 사용을 위해 전체 라이브러리의 가사를 다운로드합니다", + "result": "{{hits}}개 동기화, {{misses}}개 없음, {{failed}}개 실패", + "offline": "오프라인 모드가 활성화됨", + "failed": "미리 가져오기 실패", "action": "미리 가져오기", "progress": "{{current}}/{{total}} 처리됨 · {{hits}}곡 찾음" }, diff --git a/src/i18n/locales/nl.json b/src/i18n/locales/nl.json index 0d6aa4f..d695f80 100644 --- a/src/i18n/locales/nl.json +++ b/src/i18n/locales/nl.json @@ -1240,6 +1240,9 @@ "lyricsPrefetch": { "title": "Songteksten vooraf ophalen", "subtitle": "Songteksten van de hele bibliotheek downloaden voor offline gebruik", + "result": "{{hits}} gesynchroniseerd, {{misses}} niet gevonden, {{failed}} mislukt", + "offline": "Offlinemodus is ingeschakeld", + "failed": "Vooraf laden mislukt", "action": "Vooraf ophalen", "progress": "{{current}}/{{total}} verwerkt · {{hits}} gevonden" }, diff --git a/src/i18n/locales/pt-BR.json b/src/i18n/locales/pt-BR.json index d518a0e..5457c3e 100644 --- a/src/i18n/locales/pt-BR.json +++ b/src/i18n/locales/pt-BR.json @@ -1240,6 +1240,9 @@ "lyricsPrefetch": { "title": "Pré-carregar letras", "subtitle": "Baixar as letras de toda a biblioteca para uso offline", + "result": "{{hits}} sincronizadas, {{misses}} não encontradas, {{failed}} falharam", + "offline": "Modo offline ativado", + "failed": "Pré-carregamento falhou", "action": "Pré-carregar", "progress": "{{current}}/{{total}} processadas · {{hits}} encontradas" }, diff --git a/src/i18n/locales/pt.json b/src/i18n/locales/pt.json index 3d5c929..433b160 100644 --- a/src/i18n/locales/pt.json +++ b/src/i18n/locales/pt.json @@ -1240,6 +1240,9 @@ "lyricsPrefetch": { "title": "Pré-carregar letras", "subtitle": "Baixar as letras de toda a biblioteca para uso offline", + "result": "{{hits}} sincronizadas, {{misses}} não encontradas, {{failed}} falhadas", + "offline": "Modo offline ativado", + "failed": "Pré-carregamento falhou", "action": "Pré-carregar", "progress": "{{current}}/{{total}} processadas · {{hits}} encontradas" }, diff --git a/src/i18n/locales/ru.json b/src/i18n/locales/ru.json index 57b2fa4..24f7727 100644 --- a/src/i18n/locales/ru.json +++ b/src/i18n/locales/ru.json @@ -1242,6 +1242,9 @@ "lyricsPrefetch": { "title": "Предзагрузка текстов", "subtitle": "Скачать тексты для всей библиотеки для офлайн-использования", + "result": "Синхронизировано: {{hits}}, не найдено: {{misses}}, ошибок: {{failed}}", + "offline": "Включен офлайн-режим", + "failed": "Не удалось предзагрузить", "action": "Предзагрузить", "progress": "{{current}}/{{total}} обработано · {{hits}} найдено" }, diff --git a/src/i18n/locales/tr.json b/src/i18n/locales/tr.json index 4207dc3..d17db9b 100644 --- a/src/i18n/locales/tr.json +++ b/src/i18n/locales/tr.json @@ -1239,6 +1239,9 @@ "lyricsPrefetch": { "title": "Şarkı sözlerini önceden yükle", "subtitle": "Çevrimdışı kullanım için tüm kütüphanenin şarkı sözlerini indir", + "result": "{{hits}} eşitlendi, {{misses}} bulunamadı, {{failed}} başarısız", + "offline": "Çevrimdışı modu etkin", + "failed": "Önbelleğe alma başarısız", "action": "Önceden yükle", "progress": "{{current}}/{{total}} işlendi · {{hits}} bulundu" }, diff --git a/src/i18n/locales/zh-CN.json b/src/i18n/locales/zh-CN.json index 08b2620..bf1fd06 100644 --- a/src/i18n/locales/zh-CN.json +++ b/src/i18n/locales/zh-CN.json @@ -1239,6 +1239,9 @@ "lyricsPrefetch": { "title": "预取歌词", "subtitle": "为整个曲库下载歌词以供离线使用", + "result": "已同步 {{hits}},未找到 {{misses}},失败 {{failed}}", + "offline": "已启用离线模式", + "failed": "预加载失败", "action": "预取", "progress": "已处理 {{current}}/{{total}} · 找到 {{hits}}" }, diff --git a/src/i18n/locales/zh-TW.json b/src/i18n/locales/zh-TW.json index efd219e..1149b17 100644 --- a/src/i18n/locales/zh-TW.json +++ b/src/i18n/locales/zh-TW.json @@ -1239,6 +1239,9 @@ "lyricsPrefetch": { "title": "預先擷取歌詞", "subtitle": "為整個曲庫下載歌詞以供離線使用", + "result": "已同步 {{hits}},找不到 {{misses}},失敗 {{failed}}", + "offline": "已啟用離線模式", + "failed": "預先載入失敗", "action": "預先擷取", "progress": "已處理 {{current}}/{{total}} · 找到 {{hits}}" }, From e5da5afa595db972eb01bb5d922c4770eb1addf8 Mon Sep 17 00:00:00 2001 From: InstaZDLL Date: Mon, 18 May 2026 03:50:13 +0200 Subject: [PATCH 2/3] fix(about): correct Vite and TypeScript versions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Frontend section was showing stale major versions that hadn't been bumped when the underlying deps were upgraded: - Vite: 6.x → 8.x (actual: ^8.0.13 in package.json) - TypeScript: 5.x → 6.x (actual: ~6.0.3 in package.json) --- src/components/views/AboutView.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/AboutView.tsx b/src/components/views/AboutView.tsx index 3a53253..161b6a7 100644 --- a/src/components/views/AboutView.tsx +++ b/src/components/views/AboutView.tsx @@ -313,7 +313,7 @@ export function AboutView({ onNavigate }: AboutViewProps) {
- +
From 535e41cbd7a4bbf06ef3e4ecc7352b290f33ff3b Mon Sep 17 00:00:00 2001 From: InstaZDLL Date: Mon, 18 May 2026 03:52:08 +0200 Subject: [PATCH 3/3] fix(library): drop dead "Import files" button from empty state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The "Import files" button rendered next to "Import folder" in the empty library state had no onClick handler — clicking it did nothing. The whole library architecture (`library_folder` table, filesystem watcher, periodic rescans) is folder-based, so importing isolated files would create orphan rows the scanner can't manage. Drop the button entirely and keep the working "Import folder" one, promoted to the primary emerald style since it's now the only call to action. Remove the now-unused UploadIcon import. The matching `library.actions.importFiles` i18n keys are kept in the locale files for now (cheap, and a future per-file import flow would reuse them). --- src/components/views/LibraryView.tsx | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/components/views/LibraryView.tsx b/src/components/views/LibraryView.tsx index 53cd718..73a83ec 100644 --- a/src/components/views/LibraryView.tsx +++ b/src/components/views/LibraryView.tsx @@ -31,7 +31,6 @@ import { useTranslation } from "react-i18next"; import type { LibraryTab } from "../../types"; import { Tab } from "../common/Tab"; import { EmptyState } from "../common/EmptyState"; -import { UploadIcon } from "../common/Icons"; import { Artwork } from "../common/Artwork"; import { AlbumLink } from "../common/AlbumLink"; import { ArtistLink } from "../common/ArtistLink"; @@ -717,15 +716,11 @@ export function LibraryView({ className="py-20" >
-