fix(web): keep cached library rows when a refresh fails

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
Lucas Winther
2026-10-30 22:16:06 +01:00
co-authored by Claude Opus 5.5
parent 5c837a6679
commit 4166ecb8f5
2 changed files with 30 additions and 2 deletions
+22
View File
@@ -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 (
<div className={`stale-banner${className ? ` ${className}` : ""}`} role="alert">
<p>Can't refresh right now. {friendlyError(error)}</p>
<button type="button" className="btn ghost small" onClick={retry}>Try again</button>
</div>
);
}
return (
<div className={`load-error${className ? ` ${className}` : ""}`} role="alert">
<p>{friendlyError(error)}</p>
<button type="button" className="btn small" onClick={retry}>Try again</button>
</div>
);
}
+8 -2
View File
@@ -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 }) {
</li>
))}
</ul>
) : entries.error ? (
) : entries.error && !entries.data ? (
<div className="list-note" role="alert">
<p>{friendlyError(entries.error)}</p>
<button className="btn small" onClick={() => void entries.refetch()}>Try again</button>
</div>
) : items.length === 0 ? (
) : items.length === 0 && !entries.error ? (
<div className="list-note">
{filtering ? (
<>
@@ -186,6 +187,11 @@ function ListPane({ selectedId }: { selectedId: string | null }) {
</div>
) : (
<ul className="list">
{entries.error && (
<li>
<LoadError error={entries.error} retry={() => void entries.refetch()} stale className="in-list" />
</li>
)}
{items.map((e) => (
<li key={e.id}>
<Row entry={e} selected={e.id === selectedId} flagged={flagged.has(e.id)} scale={scale} />