Skip to content

Commit a203868

Browse files
committed
Show possible timeout messages for React panel
1 parent 0fa3c9a commit a203868

File tree

7 files changed

+99
-7
lines changed

7 files changed

+99
-7
lines changed
Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
1-
import { CSSProperties } from "react";
1+
import { CSSProperties, ReactNode } from "react";
22

33
import styles from "./Loader.module.css";
44

55
export default function Loader({
66
className = "",
7+
message = "Loading…",
78
style,
89
}: {
910
className?: string;
11+
message?: ReactNode;
1012
style?: CSSProperties;
1113
}) {
1214
return (
1315
<div className={`${className} ${styles.Loader}`} data-test-name="Loader" style={style}>
14-
Loading…
16+
{message}
1517
</div>
1618
);
1719
}

packages/replay-next/components/PanelLoader.module.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
.Loader {
1111
flex: 1 1 auto;
1212
display: flex;
13+
flex-direction: column;
1314
align-items: center;
1415
justify-content: center;
1516
}
Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,23 @@
1-
import { CSSProperties } from "react";
1+
import { CSSProperties, ReactNode } from "react";
22

33
import Loader from "replay-next/components/Loader";
44
import { LoadingProgressBar } from "replay-next/components/LoadingProgressBar";
55

66
import styles from "./PanelLoader.module.css";
77

8-
export function PanelLoader({ className, style }: { className?: string; style?: CSSProperties }) {
8+
export function PanelLoader({
9+
className,
10+
message,
11+
style,
12+
}: {
13+
className?: string;
14+
message?: ReactNode;
15+
style?: CSSProperties;
16+
}) {
917
return (
1018
<div className={`${styles.Wrapper} ${className}`} style={style}>
1119
<LoadingProgressBar />
12-
<Loader className={styles.Loader} />
20+
<Loader className={styles.Loader} message={message} />
1321
</div>
1422
);
1523
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { createStreamingCache } from "suspense";
2+
3+
export const TimeoutCache = createStreamingCache<
4+
[eventName: string, timeoutAfterMs: number],
5+
boolean
6+
>({
7+
debugLabel: "TimeoutCache",
8+
getKey: (eventName: string, timeoutAfterMs: number) => `${eventName}:${timeoutAfterMs}`,
9+
load: async (options, _, timeoutAfterMs: number) => {
10+
const { resolve, signal, update } = options;
11+
console.log("[TimeoutCache] -> streaming", _, timeoutAfterMs);
12+
13+
update(false);
14+
15+
const timeout = setTimeout(() => {
16+
console.log("[TimeoutCache] -> done", _, timeoutAfterMs);
17+
update(true);
18+
resolve();
19+
}, timeoutAfterMs);
20+
21+
signal.addEventListener("abort", () => {
22+
console.log("[TimeoutCache] -> aborted", _, timeoutAfterMs);
23+
clearTimeout(timeout);
24+
});
25+
},
26+
});
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
.Messages {
2+
display: flex;
3+
flex-direction: column;
4+
gap: 1rem;
5+
text-align: center;
6+
}
7+
8+
.Message {
9+
color: var(--color-dim);
10+
transition: height 0.3s;
11+
}
12+
13+
.DiscordLink {
14+
text-decoration: underline;
15+
cursor: pointer;
16+
}
Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,54 @@
1+
import { PropsWithChildren, ReactNode, Suspense } from "react";
2+
import { useStreamingValue } from "suspense";
3+
14
import { InlineErrorBoundary } from "replay-next/components/errors/InlineErrorBoundary";
5+
import ExternalLink from "replay-next/components/ExternalLink";
6+
import { PanelLoader } from "replay-next/components/PanelLoader";
27
import { useMostRecentLoadedPause } from "replay-next/src/hooks/useMostRecentLoadedPause";
8+
import { TimeoutCache } from "replay-next/src/suspense/TimingCache";
39

410
import { ReactDevToolsPanel } from "./react-devtools/components/ReactDevToolsPanel";
11+
import styles from "./ReactDevTools.module.css";
512

613
export default function ReactDevToolsWithErrorBoundary() {
714
const { point, pauseId } = useMostRecentLoadedPause() ?? {};
815

916
return (
1017
<InlineErrorBoundary name="ReactDevTools" resetKey={pauseId ?? ""}>
11-
<ReactDevToolsPanel executionPoint={point ?? null} pauseId={pauseId ?? null} />
18+
<SuspenseWithLoadingStalledMessage>
19+
<ReactDevToolsPanel executionPoint={point ?? null} pauseId={pauseId ?? null} />
20+
</SuspenseWithLoadingStalledMessage>
1221
</InlineErrorBoundary>
1322
);
1423
}
24+
25+
function SuspenseWithLoadingStalledMessage({ children }: PropsWithChildren) {
26+
let message: ReactNode | undefined = undefined;
27+
28+
const { value: showShortMessage } = useStreamingValue(
29+
TimeoutCache.stream("react:annotations-loading-stalled:short", 30_000)
30+
);
31+
const { value: showLongMessage } = useStreamingValue(
32+
TimeoutCache.stream("react:annotations-loading-stalled:long", 300_000)
33+
);
34+
35+
if (showLongMessage) {
36+
message = (
37+
<div className={styles.Messages}>
38+
<p className={styles.Message}>This is taking longer than we expected.</p>
39+
<p className={styles.Message}>Something may have gone wrong.</p>
40+
<p className={styles.Message}>
41+
Contact us{" "}
42+
<ExternalLink className={styles.DiscordLink} href="https://discord.gg/n2dTK6kcRX">
43+
on Discord
44+
</ExternalLink>{" "}
45+
if you need more assistance.
46+
</p>
47+
</div>
48+
);
49+
} else if (showShortMessage) {
50+
message = <p className={styles.Message}>This is taking longer than expected.</p>;
51+
}
52+
53+
return <Suspense fallback={<PanelLoader message={message} />}>{children}</Suspense>;
54+
}

src/ui/components/SecondaryToolbox/react-devtools/components/ReactDevToolsPanel.module.css

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,6 @@
8080
.DisabledDuringPlaybackMessage,
8181
.NotMountedYetMessage,
8282
.ProtocolFailedMessage {
83-
width: 100%;
8483
display: flex;
8584
flex-direction: column;
8685
color: var(--color-dim);

0 commit comments

Comments
 (0)