fix: scope polling to widgets, fix retry, guard dates, throttle umami

- Remove global refetchInterval; scope to widget queries via setQueryDefaults
- Fix error boundary retry: correct queryKey to [["widget"]], move invalidation to onReset
- Add toValidDate() helper in @homarr/common for cache hydration safety
- Guard date formatting in media-releases and media-requests against non-Date values
- Set umami refetchInterval to 60s via shared umamiQueryOptions constant
- Simplify dns-hole mutations to invalidate() instead of manual optimistic setData
This commit is contained in:
Thomas Camlong committed 2026-06-25 17:38:13 +02:00
1 parent 210a62b35a
commit c848dbfc1f
11 files changed
+84 -114

No files matched your search

@@ -61,35 +61,35 @@ const wsClient = createWSClient({
export function TRPCReactProvider(props: PropsWithChildren) {
const [persister] = useState(() => createWidgetQueryPersister());
const [queryClient] = useState(
() =>
new QueryClient({
defaultOptions: {
queries: {
staleTime: queryCacheDefaultStaleTimeMs,
refetchInterval: queryCacheDefaultRefetchIntervalMs,
gcTime: queryCacheDefaultGcTimeMs,
refetchOnWindowFocus: false,
refetchOnReconnect: false,
retry: 3,
},
mutations: {
onError(error) {
if (
error instanceof TRPCClientError &&
error.data?.code === "FORBIDDEN" &&
error.message === "Mutations are disabled in demo mode"
) {
showWarningNotification({
title: "Demo mode",
message: "This action is disabled in demo mode.",
});
}
},
const [queryClient] = useState(() => {
const client = new QueryClient({
defaultOptions: {
queries: {
staleTime: queryCacheDefaultStaleTimeMs,
gcTime: queryCacheDefaultGcTimeMs,
refetchOnWindowFocus: false,
refetchOnReconnect: false,
retry: 3,
},
mutations: {
onError(error) {
if (
error instanceof TRPCClientError &&
error.data?.code === "FORBIDDEN" &&
error.message === "Mutations are disabled in demo mode"
) {
showWarningNotification({
title: "Demo mode",
message: "This action is disabled in demo mode.",
});
}
},
},
}),
);
},
});
client.setQueryDefaults([["widget"]], { refetchInterval: queryCacheDefaultRefetchIntervalMs });
return client;
});
const [trpcClient] = useState(() => {
return clientApi.createClient({
@@ -1,6 +1,6 @@
import { Badge, Card } from "@mantine/core";
import { useElementSize } from "@mantine/hooks";
import { QueryErrorResetBoundary } from "@tanstack/react-query";
import { QueryErrorResetBoundary, useQueryClient } from "@tanstack/react-query";
import combineClasses from "clsx";
import { NoIntegrationSelectedError } from "@homarr/widgets/errors/classes";
import { ErrorBoundary } from "react-error-boundary";
@@ -98,12 +98,16 @@ const InnerContent = ({ item, ...dimensions }: InnerContentProps) => {
updateItemOptions({ itemId: item.id, newOptions });
const widgetSupportsIntegrations =
"supportedIntegrations" in definition && definition.supportedIntegrations.length >= 1;
const queryClient = useQueryClient();
return (
<QueryErrorResetBoundary>
{({ reset }) => (
<ErrorBoundary
onReset={reset}
onReset={() => {
void queryClient.invalidateQueries({ queryKey: [["widget"]] });
reset();
}}
fallbackRender={({ resetErrorBoundary, error }) => (
<>
<BoardItemMenu offset={4} item={newItem} resetErrorBoundary={resetErrorBoundary} />