Skip to content

fix: post-release UX cleanup (lyrics feedback, version labels, dead button)#44

Merged
InstaZDLL merged 3 commits into
mainfrom
fix/post-release-bugs-1.1.x
May 18, 2026
Merged

fix: post-release UX cleanup (lyrics feedback, version labels, dead button)#44
InstaZDLL merged 3 commits into
mainfrom
fix/post-release-bugs-1.1.x

Conversation

@InstaZDLL
Copy link
Copy Markdown
Owner

@InstaZDLL InstaZDLL commented May 18, 2026

Summary

Three small UX fixes reported after the v1.1.1 release:

  1. Lyrics prefetch (commit ef60b04) — clicking "Précharger les paroles" looked dead when every track already had cached lyrics (or offline mode). Backend now emits an initial progress frame with the total (including 0) and the frontend shows a 5s toast-style result message ("X synced, Y not found, Z failed", "Offline mode enabled", or "Prefetch failed"). New i18n keys propagated to all 17 locales.
  2. About versions (commit 7dc4f90) — Vite shown as 6.x but actually 8.x; TypeScript shown as 5.x but actually 6.x. Bumped to match package.json.
  3. Dead "Import files" button (commit a26dca1) — the empty-state button next to "Import folder" had no handler and no backend; the whole library is folder-based so it never made sense. Removed entirely, "Import folder" promoted to the only (emerald) CTA.

Known follow-ups (parked, not in this PR)

User also reported during the same session — both need real-machine reproduction logs since the code paths look correct on inspection:

  • Playlist sort choice not persisted across app restarts (useSortMemory read/write are symmetric, hook gates UI on isLoaded to avoid flash). Possible cause: WAL not synced at hard shutdown; needs tracing instrumentation on set_profile_setting to confirm.
  • Last.fm "Connected as X" not shown after restart even though login succeeded. lastfm_get_status reads auth_credential.username; lastfm_login writes session.username (always a String, never NULL). Needs DB inspection (SELECT * FROM auth_credential WHERE provider='lastfm') on the user's profile to see whether the row is present and what the username column looks like.

Will spin those up as separate issues / PRs once we have repro data.

Test plan

  • bun run typecheck clean
  • bun run lint clean
  • Click "Précharger les paroles" with no missing lyrics → "X synced…" toast appears
  • Open About → Vite reads "8.x", TypeScript reads "6.x"
  • Open Library → empty state → only "Import folder" button visible, clicking opens picker

Summary by CodeRabbit

Notes de version

  • New Features

    • Affichage immédiat d'un état initial lors du préchargement des paroles.
    • Message de résultat détaillé affichant le nombre de paroles synchronisées, manquantes et échouées.
    • Gestion distincte des erreurs hors-ligne lors du préchargement.
  • Improvements

    • Mise à jour des versions affichées dans les informations techniques (Vite 8.x, TypeScript 6.x).
    • Suppression du bouton d'importation de fichiers individuels depuis la bibliothèque vide.
  • Localization

    • Nouveaux messages de résultat et d'erreur traduits dans tous les langages supportés.

Review Change Stack

@github-actions github-actions Bot added scope: frontend React/Vite frontend (src/) scope: backend Rust/Tauri backend (src-tauri/) scope: i18n Translations (src/i18n/) labels May 18, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 18, 2026

Warning

Rate limit exceeded

@InstaZDLL has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 28 minutes and 16 seconds before requesting another review.

To continue reviewing without waiting, purchase usage credits in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 173b9fd9-f3ab-48a5-9364-29896597c9bf

📥 Commits

Reviewing files that changed from the base of the PR and between a26dca1 and 535e41c.

📒 Files selected for processing (21)
  • src-tauri/src/commands/lyrics.rs
  • src/components/views/AboutView.tsx
  • src/components/views/LibraryView.tsx
  • src/components/views/SettingsView.tsx
  • src/i18n/locales/ar.json
  • src/i18n/locales/de.json
  • src/i18n/locales/en.json
  • src/i18n/locales/es.json
  • src/i18n/locales/fr.json
  • src/i18n/locales/hi.json
  • src/i18n/locales/id.json
  • src/i18n/locales/it.json
  • src/i18n/locales/ja.json
  • src/i18n/locales/kr.json
  • src/i18n/locales/nl.json
  • src/i18n/locales/pt-BR.json
  • src/i18n/locales/pt.json
  • src/i18n/locales/ru.json
  • src/i18n/locales/tr.json
  • src/i18n/locales/zh-CN.json
  • src/i18n/locales/zh-TW.json
📝 Walkthrough

Walkthrough

Ce PR améliore l'expérience utilisateur du préchargement des paroles en envoyant un événement de progression initial côté backend, affichant des résultats détaillés en frontend avec traductions multilingues. Il inclut aussi une simplification du flux d'import en bibliothèque et une mise à jour des versions de dépendances dans la page À propos.

Changes

Préchargement des paroles et mises à jour connexes

Couche / Fichier(s) Résumé
Événement initial de progression backend
src-tauri/src/commands/lyrics.rs
Le backend envoie un premier événement lyrics:prefetch-progress avec compteurs initialisés (processed/hits/misses/failed = 0) et le total calculé avant de traiter les pistes, garantissant que l'UI reçoit immédiatement un état cohérent.
Affichage et gestion d'état des résultats
src/components/views/SettingsView.tsx
Ajout de l'état lyricsResultMsg pour afficher les résultats distincts. Amélioration de handlePrefetchLyrics : récupération du summary renvoyé par le backend, construction d'un message i18n détaillé (hits/misses/failed), différenciation des erreurs hors-ligne ("offline") des autres échecs ("failed"), et délai d'effacement allongé à 5s. Rendu conditionnel du message en style émeraude dans la carte lyrics prefetch.
Traductions multilingues pour les résultats
src/i18n/locales/{ar,de,en,es,fr,hi,id,it,ja,kr,nl,pt-BR,pt,ru,tr,zh-CN,zh-TW}.json
Ajout de trois clés par locale sous settings.lyricsPrefetch : result (résumé hits/misses/failed), offline (activation du mode hors-ligne), failed (échec du préchargement), supportant le message de résultat détaillé en 16 langues.
Simplification du flux import en bibliothèque
src/components/views/LibraryView.tsx
Suppression de l'import UploadIcon et du bouton "import files" de l'EmptyState. Conservation uniquement de l'action "importFolder" avec style primary (émeraude), supprimant l'option d'import de fichiers individuels.
Mises à jour des versions tech stack
src/components/views/AboutView.tsx
Mise à jour des versions affichées : Vite passe à 8.x (précédemment 6.x) et TypeScript à 6.x (précédemment 5.x).

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Suggested labels

type: fix, size: s, scope: frontend, scope: backend, scope: i18n

Poem

📬 Le préchargement murmure ses débuts,
État initial envoyé sans attendre,
Résultats comptés dans seize langues tendres,
La bibliothèque ne prend que les dossiers,
Et les versions dansent vers l'avant ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed Le titre suit les conventions Conventional Commits avec portée en kebab-case et résume fidèlement les trois corrections UX principales (feedback lyrics, version labels, dead button).
Description check ✅ Passed La description couvre les trois corrections (Lyrics prefetch, About versions, dead button), explique le contexte et les raisons, liste les étapes de test, et référence les commits. Suit la structure du template.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/post-release-bugs-1.1.x

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions Bot added type: fix Bug fix size: m 50-200 lines labels May 18, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/components/views/SettingsView.tsx (2)

741-746: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Éviter qu’un ancien timeout efface une exécution en cours

Si l’utilisateur relance vite, le timeout précédent peut réinitialiser l’état pendant la nouvelle exécution. Annule le timer actif avant d’en créer un nouveau.

💡 Correctif proposé
+  const lyricsResultTimerRef = useRef<number | null>(null);

   const handlePrefetchLyrics = async () => {
     if (isPrefetchingLyrics) return;
+    if (lyricsResultTimerRef.current != null) {
+      window.clearTimeout(lyricsResultTimerRef.current);
+      lyricsResultTimerRef.current = null;
+    }
     setIsPrefetchingLyrics(true);
     setLyricsPrefetchProgress(null);
     setLyricsResultMsg(null);
@@
     } finally {
       setIsPrefetchingLyrics(false);
-      window.setTimeout(() => {
+      lyricsResultTimerRef.current = window.setTimeout(() => {
         setLyricsPrefetchProgress(null);
         setLyricsResultMsg(null);
+        lyricsResultTimerRef.current = null;
       }, 5000);
     }
   };
+
+  useEffect(() => {
+    return () => {
+      if (lyricsResultTimerRef.current != null) {
+        window.clearTimeout(lyricsResultTimerRef.current);
+      }
+    };
+  }, []);

Also applies to: 768-771

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/views/SettingsView.tsx` around lines 741 - 746, The prefetch
handlers (e.g., handlePrefetchLyrics) can have an earlier setTimeout clear the
state of a new run; introduce and use a persistent timer holder (a ref or
module-scope variable) to clear the previous timeout before creating a new one:
call clearTimeout(existingTimer) and replace it with the new setTimeout id, and
ensure you clear it when the operation completes or on unmount; apply the same
pattern to the other handler referenced (lines 768-771) so any in-flight timeout
is cancelled before starting a new prefetch.

711-765: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Ne pas afficher les erreurs “offline/failed” avec un style succès

Le rendu est toujours en vert dès que lyricsResultMsg existe, y compris pour les erreurs. Distingue succès/erreur dans l’état pour éviter un feedback trompeur.

💡 Correctif proposé
-  const [lyricsResultMsg, setLyricsResultMsg] = useState<string | null>(null);
+  const [lyricsResult, setLyricsResult] = useState<{
+    kind: "success" | "error";
+    message: string;
+  } | null>(null);
@@
-    setLyricsResultMsg(null);
+    setLyricsResult(null);
@@
-      setLyricsResultMsg(
-        t("settings.lyricsPrefetch.result", {
+      setLyricsResult({
+        kind: "success",
+        message: t("settings.lyricsPrefetch.result", {
           hits: summary.hits,
           misses: summary.misses,
           failed: summary.failed,
         }),
-      );
+      });
@@
-      setLyricsResultMsg(
-        msg.includes("offline")
-          ? t("settings.lyricsPrefetch.offline")
-          : t("settings.lyricsPrefetch.failed"),
-      );
+      setLyricsResult({
+        kind: "error",
+        message: msg.includes("offline")
+          ? t("settings.lyricsPrefetch.offline")
+          : t("settings.lyricsPrefetch.failed"),
+      });
@@
-        setLyricsResultMsg(null);
+        setLyricsResult(null);
@@
-                ) : lyricsResultMsg ? (
-                  <div className="text-xs text-emerald-600 dark:text-emerald-400 mt-1 truncate">
-                    {lyricsResultMsg}
+                ) : lyricsResult ? (
+                  <div
+                    className={`text-xs mt-1 truncate ${
+                      lyricsResult.kind === "success"
+                        ? "text-emerald-600 dark:text-emerald-400"
+                        : "text-rose-600 dark:text-rose-400"
+                    }`}
+                  >
+                    {lyricsResult.message}
                   </div>

Also applies to: 2487-2490

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/views/SettingsView.tsx` around lines 711 - 765, The UI
currently treats any non-null lyricsResultMsg as a success (green) even for
errors; add a separate status flag (e.g., lyricsResultStatus or
isLyricsPrefetchError) alongside lyricsResultMsg to represent success vs error,
set it to success when prefetchLibraryLyrics() returns (before calling
setLyricsResultMsg) and set it to error in the catch block (alongside setting
the error message), and update the render code that styles the message to use
this new flag instead of merely checking lyricsResultMsg; apply the same change
for the other occurrence that sets lyrics result messages (the block around the
other setLyricsResultMsg usage referenced in the review).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/components/views/SettingsView.tsx`:
- Around line 741-746: The prefetch handlers (e.g., handlePrefetchLyrics) can
have an earlier setTimeout clear the state of a new run; introduce and use a
persistent timer holder (a ref or module-scope variable) to clear the previous
timeout before creating a new one: call clearTimeout(existingTimer) and replace
it with the new setTimeout id, and ensure you clear it when the operation
completes or on unmount; apply the same pattern to the other handler referenced
(lines 768-771) so any in-flight timeout is cancelled before starting a new
prefetch.
- Around line 711-765: The UI currently treats any non-null lyricsResultMsg as a
success (green) even for errors; add a separate status flag (e.g.,
lyricsResultStatus or isLyricsPrefetchError) alongside lyricsResultMsg to
represent success vs error, set it to success when prefetchLibraryLyrics()
returns (before calling setLyricsResultMsg) and set it to error in the catch
block (alongside setting the error message), and update the render code that
styles the message to use this new flag instead of merely checking
lyricsResultMsg; apply the same change for the other occurrence that sets lyrics
result messages (the block around the other setLyricsResultMsg usage referenced
in the review).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 20535902-00b2-4ba9-9fc3-fa2ceabae570

📥 Commits

Reviewing files that changed from the base of the PR and between ad90b5b and a26dca1.

📒 Files selected for processing (21)
  • src-tauri/src/commands/lyrics.rs
  • src/components/views/AboutView.tsx
  • src/components/views/LibraryView.tsx
  • src/components/views/SettingsView.tsx
  • src/i18n/locales/ar.json
  • src/i18n/locales/de.json
  • src/i18n/locales/en.json
  • src/i18n/locales/es.json
  • src/i18n/locales/fr.json
  • src/i18n/locales/hi.json
  • src/i18n/locales/id.json
  • src/i18n/locales/it.json
  • src/i18n/locales/ja.json
  • src/i18n/locales/kr.json
  • src/i18n/locales/nl.json
  • src/i18n/locales/pt-BR.json
  • src/i18n/locales/pt.json
  • src/i18n/locales/ru.json
  • src/i18n/locales/tr.json
  • src/i18n/locales/zh-CN.json
  • src/i18n/locales/zh-TW.json

@InstaZDLL InstaZDLL self-assigned this May 18, 2026
InstaZDLL added 3 commits May 18, 2026 19:36
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.
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)
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).
@InstaZDLL InstaZDLL force-pushed the fix/post-release-bugs-1.1.x branch from a26dca1 to 535e41c Compare May 18, 2026 17:38
@InstaZDLL InstaZDLL merged commit d548516 into main May 18, 2026
13 checks passed
@InstaZDLL InstaZDLL deleted the fix/post-release-bugs-1.1.x branch May 18, 2026 17:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

scope: backend Rust/Tauri backend (src-tauri/) scope: frontend React/Vite frontend (src/) scope: i18n Translations (src/i18n/) size: m 50-200 lines type: fix Bug fix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant