refactor(widgets): migrate all widgets from useSuspenseQuery to useQuery

Non-blocking data fetching for all 38 widget components. Widgets now
render immediately and show data when available, with loading state
delegated to the global refresh indicator in the board header.
This commit is contained in:
Thomas Camlong committed 2026-05-28 18:07:03 +02:00
1 parent cb5ae65f8a
commit 394debbea1
38 files changed
+96 -67

No files matched your search

+5 -4
View File
@@ -22,7 +22,7 @@ export default function AppWidget({ options, isEditMode, height, width }: Widget
const t = useI18n();
const settings = useSettings();
const board = useRequiredBoard();
const [app] = clientApi.app.byId.useSuspenseQuery(
const { data: app } = clientApi.app.byId.useQuery(
{
id: options.appId,
},
@@ -34,8 +34,8 @@ export default function AppWidget({ options, isEditMode, height, width }: Widget
},
);
useRegisterSpotlightContextResults(
`app-${app.id}`,
app.href
`app-${app?.id ?? options.appId}`,
app?.href
? [
{
id: app.id,
@@ -44,7 +44,6 @@ export default function AppWidget({ options, isEditMode, height, width }: Widget
interaction() {
return {
type: "link",
// We checked above that app.href is defined
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
href: app.href!,
newTab: options.openInNewTab,
@@ -56,6 +55,8 @@ export default function AppWidget({ options, isEditMode, height, width }: Widget
[app, options.openInNewTab],
);
if (!app) return null;
const isTiny = height < 100 || width < 100;
const isColumnLayout = options.layout.startsWith("column");
@@ -11,7 +11,7 @@ interface PingIndicatorProps {
}
export const PingIndicator = ({ appId }: PingIndicatorProps) => {
const [ping] = clientApi.widget.app.ping.useSuspenseQuery(
const { data: ping } = clientApi.widget.app.ping.useQuery(
{
id: appId,
},
@@ -21,7 +21,7 @@ export const PingIndicator = ({ appId }: PingIndicatorProps) => {
},
);
const [pingResult, setPingResult] = useState<RouterOutputs["widget"]["app"]["ping"]>(ping);
const [pingResult, setPingResult] = useState<RouterOutputs["widget"]["app"]["ping"] | undefined>(ping);
clientApi.widget.app.updatedPing.useSubscription(
{ id: appId },
@@ -32,16 +32,19 @@ export const PingIndicator = ({ appId }: PingIndicatorProps) => {
},
);
const isError = "error" in pingResult || pingResult.statusCode >= 500;
const current = pingResult ?? ping;
if (!current) return null;
const isError = "error" in current || current.statusCode >= 500;
return (
<PingDot
icon={isError ? IconX : IconCheck}
color={isError ? "red" : "green"}
tooltip={
"statusCode" in pingResult
? `${pingResult.statusCode} - ${pingResult.durationMs.toFixed(0)}ms`
: pingResult.error
"statusCode" in current
? `${current.statusCode} - ${current.durationMs.toFixed(0)}ms`
: current.error
}
/>
);