From b4cd8e17961623e92c5d0009eb9ee1e1186291dd Mon Sep 17 00:00:00 2001 From: Nicola Belluti Date: Wed, 7 Oct 2026 13:26:01 +0200 Subject: [PATCH] fix(oxibadge): show connection errors instead of failing silently MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit load_records/load_employees failures were only logged to the console and silently reset the UI to the month picker. Errors now flow through a shared store (src/lib/error.ts) into an ErrorBanner, reused by both Onboarding and ConfirmMonth, with the raw message passed straight through from Rust (no stable-code classification layer — these are mostly plain I/O errors, not worth categorizing). i18n stays grouped per screen as before, with error-related strings split into their own top-level "errors" group. Assisted-by: Claude Sonnet 5 --- oxibadge/src-tauri/src/lib.rs | 22 +++-------- .../src/lib/components/ConfirmMonth.svelte | 8 ++++ oxibadge/src/lib/components/Onboarding.svelte | 38 +++++++------------ oxibadge/src/lib/error.ts | 11 ++++++ oxibadge/src/lib/locales/en.json | 10 ++--- oxibadge/src/lib/locales/it.json | 10 ++--- oxibadge/src/routes/+page.svelte | 4 +- 7 files changed, 47 insertions(+), 56 deletions(-) create mode 100644 oxibadge/src/lib/error.ts diff --git a/oxibadge/src-tauri/src/lib.rs b/oxibadge/src-tauri/src/lib.rs index bda3d17..1daa1a4 100644 --- a/oxibadge/src-tauri/src/lib.rs +++ b/oxibadge/src-tauri/src/lib.rs @@ -22,27 +22,15 @@ async fn test_connection(host: String, port: u16) -> Result<(), String> { connect_with_retries(&host, port).await.map(|_| ()) } -/// Connects to the device, trying up to 3 times, returning a stable error -/// code (not a user-facing message) on failure so the frontend can -/// translate it. +/// Connects to the device, trying up to 3 times, returning the last error +/// message as-is on failure. async fn connect_with_retries(host: &str, port: u16) -> Result { let mut last_error = String::new(); for _ in 0..3 { - let err = match R701::connect((host, port)).await { + match R701::connect((host, port)).await { Ok(r701) => return Ok(r701), - Err(err) => err, - }; - last_error = match err.kind() { - std::io::ErrorKind::ConnectionRefused => "connection-refused".to_string(), - std::io::ErrorKind::TimedOut => "timed-out".to_string(), - _ if err - .to_string() - .contains("failed to lookup address information") => - { - "dns-failure".to_string() - } - _ => "unknown".to_string(), - }; + Err(err) => last_error = err.to_string(), + } } Err(last_error) } diff --git a/oxibadge/src/lib/components/ConfirmMonth.svelte b/oxibadge/src/lib/components/ConfirmMonth.svelte index f756b3f..9c023fa 100644 --- a/oxibadge/src/lib/components/ConfirmMonth.svelte +++ b/oxibadge/src/lib/components/ConfirmMonth.svelte @@ -2,9 +2,11 @@ import { tick } from 'svelte'; import { _, locale } from 'svelte-i18n'; import { monthName } from '$lib/month'; + import { error, clearError } from '$lib/error'; import Column from './Column.svelte'; import Intro from './Intro.svelte'; import Button from './Button.svelte'; + import ErrorBanner from './ErrorBanner.svelte'; let { onstart }: { onstart: (selection: { year: number; month: number }) => void } = $props(); @@ -46,12 +48,14 @@ if (isFuture(i)) return; month = i; open = null; + clearError(); } function pickYear(y: number) { year = y; if (y === currentYear && month > currentMonth) month = currentMonth; open = null; + clearError(); } function onYearScroll() { @@ -157,6 +161,10 @@