From 4166ecb8f552a4cdcb3ddd6653b2ae888d2cb674 Mon Sep 17 00:00:00 2001 From: Lucas Winther Date: Fri, 30 Oct 2026 22:16:06 +0100 Subject: [PATCH] fix(web): keep cached library rows when a refresh fails Co-Authored-By: Claude Opus 5.5 --- apps/web/src/components/LoadError.tsx | 22 ++++++++++++++++++++++ apps/web/src/routes/library.tsx | 10 ++++++++-- 2 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 apps/web/src/components/LoadError.tsx diff --git a/apps/web/src/components/LoadError.tsx b/apps/web/src/components/LoadError.tsx new file mode 100644 index 0000000..954c475 --- /dev/null +++ b/apps/web/src/components/LoadError.tsx @@ -0,0 +1,22 @@ +import { friendlyError } from "../format.ts"; + +/** + * A failed load. With cached data on screen (`stale`), a small inline banner sits above it so the user + * keeps what they had; with nothing cached, it is the whole state. + */ +export function LoadError({ error, retry, stale, className }: { error: unknown; retry: () => void; stale?: boolean; className?: string }) { + if (stale) { + return ( +
+

Can't refresh right now. {friendlyError(error)}

+ +
+ ); + } + return ( +
+

{friendlyError(error)}

+ +
+ ); +} diff --git a/apps/web/src/routes/library.tsx b/apps/web/src/routes/library.tsx index 120e8ea..05b6cc2 100644 --- a/apps/web/src/routes/library.tsx +++ b/apps/web/src/routes/library.tsx @@ -2,6 +2,7 @@ import { useInfiniteQuery, useMutation, useQueryClient } from "@tanstack/react-q import { useRef, useState, type FormEvent } from "react"; import { Link, useLocation } from "wouter"; import { api, type EntryView } from "../api.ts"; +import { LoadError } from "../components/LoadError.tsx"; import { Cover } from "../components/Cover.tsx"; import { EntryDetail } from "../components/EntryDetail.tsx"; import { Icon } from "../components/Icon.tsx"; @@ -165,12 +166,12 @@ function ListPane({ selectedId }: { selectedId: string | null }) { ))} - ) : entries.error ? ( + ) : entries.error && !entries.data ? (

{friendlyError(entries.error)}

- ) : items.length === 0 ? ( + ) : items.length === 0 && !entries.error ? (
{filtering ? ( <> @@ -186,6 +187,11 @@ function ListPane({ selectedId }: { selectedId: string | null }) {
) : (