feat(ui): R3 S2 — loading rows for blank-flash pages, error paths for forever-loading ones

- Blank-flash (showed an empty state on first load before data): DownloadCenter (queue + library
  tabs), AdminUsers (roles + invites), ChatThread, PlaylistsRail now show a loading indicator
  (and an error+retry) instead of a false-empty flash — guarded on `&& !data` so live data isn't
  disturbed on refetch.
- Forever-loading (`isLoading || !data` loops forever on a failed fetch): ConfigPanel, the three
  PlexBrowse subviews (playlist/show/season), and Stats' admin dashboard get an `isError && !data`
  error+retry path before the loading branch.
- Playlists' detail pane already had an error path (isError+retry); its list lives in PlaylistsRail
  (now covered), so no change needed there.
This commit is contained in:
2026-07-22 04:24:38 +02:00
parent a393fd2fb1
commit bf96318dea
7 changed files with 92 additions and 20 deletions
+8
View File
@@ -6,6 +6,7 @@ import { api, type ConfigItem, type PlexTestResult } from "../lib/api";
import { notify } from "../lib/notifications";
import Tooltip from "./Tooltip";
import Tabs, { usePersistedTab } from "./Tabs";
import { StateMessage } from "./QueryState";
import { PageToolbar } from "./PageShell";
import { Switch } from "./ui/form";
import { DraftSaveBar, type SaveState } from "./ui/DraftSaveBar";
@@ -148,6 +149,13 @@ export default function ConfigPanel() {
setDraft((d) => ({ ...d, plex_libraries: next.join(",") }));
};
if (q.isError && !data) {
return (
<StateMessage tone="error" onRetry={() => q.refetch()}>
{t("common.loadError")}
</StateMessage>
);
}
if (q.isLoading || !data) {
return <div className="p-4 max-w-3xl mx-auto text-muted">{t("config.loading")}</div>;
}