From 355262e632d0491117112f8dce0b085729cdd6c6 Mon Sep 17 00:00:00 2001 From: MHSanaei Date: Sat, 13 Jun 2026 10:42:14 +0200 Subject: [PATCH] fix(clients): keep the client list live with a background poll (#5262) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The paged client list is sorted/paginated server-side but fetched with staleTime: Infinity, so the WS client_stats patch only refreshed traffic on already-visible rows — newly connected clients never appeared and the sort order went stale until a manual refresh. Add a 5s refetchInterval so the current page tracks reality, and drive the table overlay off isPlaceholderData so the background poll does not flash it. --- frontend/src/hooks/useClients.ts | 7 +++++++ frontend/src/pages/clients/ClientsPage.tsx | 6 +++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/frontend/src/hooks/useClients.ts b/frontend/src/hooks/useClients.ts index e266710dc..73203119d 100644 --- a/frontend/src/hooks/useClients.ts +++ b/frontend/src/hooks/useClients.ts @@ -183,6 +183,9 @@ export function useClients() { queryKey: keys.clients.list(query), queryFn: () => fetchClientPage(query), staleTime: Infinity, + // List is sorted/paged server-side, so the WS patch can't add new or + // re-sort rows; poll the current page to keep it live (pauses when hidden). + refetchInterval: 5000, placeholderData: keepPreviousData, }); @@ -216,6 +219,9 @@ export function useClients() { const fetched = listQuery.data !== undefined || listQuery.isError; const fetchError = listQuery.error ? (listQuery.error as Error).message : ''; const loading = listQuery.isFetching; + // Showing kept-previous data for a new key (filter/sort/page) — drives the + // table overlay so the 5s background poll doesn't flash it. + const transitioning = listQuery.isPlaceholderData; const inbounds = inboundOptionsQuery.data ?? []; const onlines = useMemo(() => onlinesQuery.data ?? [], [onlinesQuery.data]); @@ -528,6 +534,7 @@ export function useClients() { inbounds, onlines, loading, + transitioning, fetched, fetchError, subSettings, diff --git a/frontend/src/pages/clients/ClientsPage.tsx b/frontend/src/pages/clients/ClientsPage.tsx index 7e9efeab5..9db5acfcd 100644 --- a/frontend/src/pages/clients/ClientsPage.tsx +++ b/frontend/src/pages/clients/ClientsPage.tsx @@ -197,7 +197,7 @@ export default function ClientsPage() { summary: serverSummary, allGroups, setQuery, - inbounds, onlines, loading, fetched, fetchError, subSettings, + inbounds, onlines, loading, transitioning, fetched, fetchError, subSettings, tgBotEnable, expireDiff, trafficDiff, pageSize, create, update, remove, bulkDelete, bulkAdjust, bulkAddToGroup, bulkRemoveFromGroup, attach, bulkAttach, detach, bulkDetach, resetTraffic, resetAllTraffics, delDepleted, setEnable, @@ -1100,7 +1100,7 @@ export default function ClientsPage() { columns={columns} dataSource={sortedClients} - loading={loading} + loading={transitioning} rowKey="email" rowSelection={rowSelection} pagination={tablePagination} @@ -1117,7 +1117,7 @@ export default function ClientsPage() { }} /> ) : ( - +
{filteredClients.length > 0 && (