Better error message when fetch fails (server temporarily unavailable)
Some checks are pending
E2E Tests / e2e (push) Waiting to run
Tests and checks on push / run-checks-and-tests (push) Waiting to run
Updates translation progress / update-translation-progress-issue (push) Waiting to run

Closes #2481
This commit is contained in:
Kalle
2025-11-22 12:17:46 +02:00
parent 7be3d255cb
commit 601d1d3fe3
2 changed files with 55 additions and 16 deletions

View File

@@ -3,6 +3,7 @@
- only rarely use comments, prefer descriptive variable and function names (leave existing comments as is)
- if you encounter an existing TODO comment assume it is there for a reason and do not remove it
- task is not considered completely until `npm run checks` passes
- normal file structure has constants at the top immediately followed by the main function body of the file. Helpers are used to structure the code and they are at the bottom of the file (then hoisted to the top)
## Commands

View File

@@ -4,7 +4,7 @@ import {
useRouteError,
} from "@remix-run/react";
import * as React from "react";
import { useCopyToClipboard, useLocation } from "react-use";
import { useLocation } from "react-use";
import { useUser } from "~/features/auth/core/user";
import {
ERROR_GIRL_IMAGE_PATH,
@@ -13,6 +13,7 @@ import {
} from "~/utils/urls";
import { SendouButton } from "./elements/Button";
import { Image } from "./Image";
import { RefreshArrowsIcon } from "./icons/RefreshArrows";
import { Main } from "./Main";
export function Catcher() {
@@ -20,7 +21,6 @@ export function Catcher() {
const user = useUser();
const { revalidate } = useRevalidator();
const location = useLocation();
const [, copyToClipboard] = useCopyToClipboard();
// refresh user data to make sure it's up to date (e.g. cookie might have been removed, let's show the prompt to log back in)
React.useEffect(() => {
@@ -29,6 +29,28 @@ export function Catcher() {
revalidate();
}, [revalidate, error]);
const isNetworkError =
error instanceof Error &&
(error.message.includes("Failed to fetch") ||
error.message.includes("NetworkError") ||
error.message.includes("Load failed"));
if (isNetworkError) {
return (
<Main>
<ErrorGirlImage />
<h2 className="text-center">Connection error</h2>
<p className="text-center">
The server was temporarily unavailable. This is usually a brief
network issue.
</p>
<div className="mt-4 stack sm items-center">
<RefreshPageButton />
</div>
</Main>
);
}
if (!isRouteErrorResponse(error)) {
const errorText = (() => {
if (!(error instanceof Error)) return;
@@ -38,26 +60,19 @@ export function Catcher() {
return (
<Main>
<Image
className="m-0-auto"
path={ERROR_GIRL_IMAGE_PATH}
width={292}
height={243.5}
alt=""
/>
<ErrorGirlImage />
<h2 className="text-center">Error happened</h2>
<p className="text-center">
It seems like you encountered a bug. Sorry about that! Please share
the diagnostics message below as well as other details (your browser?
what were you doing?) on{" "}
<a href={SENDOU_INK_DISCORD_URL}>our Discord</a> so it can be fixed.
There was an unexpected error. If this keeps happening, please report
it on <a href={SENDOU_INK_DISCORD_URL}>our Discord</a> so it can be
fixed. Include the error message below.
</p>
{errorText ? (
<div className="mt-4 stack sm items-center">
<textarea readOnly defaultValue={errorText} />
<SendouButton onPress={() => copyToClipboard(errorText)}>
Copy to clipboard
</SendouButton>
<div className="mt-2">
<RefreshPageButton />
</div>
</div>
) : null}
</Main>
@@ -128,3 +143,26 @@ function GetHelp() {
</p>
);
}
function ErrorGirlImage() {
return (
<Image
className="m-0-auto"
path={ERROR_GIRL_IMAGE_PATH}
width={292}
height={243.5}
alt=""
/>
);
}
function RefreshPageButton() {
return (
<SendouButton
onPress={() => window.location.reload()}
icon={<RefreshArrowsIcon />}
>
Refresh page
</SendouButton>
);
}