Skip to content
Snippets Groups Projects
Verified Commit cc2d9b96 authored by Adrian Paschkowski's avatar Adrian Paschkowski :thinking:
Browse files

"Handle" errors in language loading

aka just throw them because the app is useless without language files
parent ef1ce03e
No related branches found
No related tags found
No related merge requests found
......@@ -22,10 +22,11 @@ const onError = (error: Error, { componentStack }: ErrorInfo) => {
function Fallback({ error }: FallbackProps) {
return (
<div className={`min-h-screen flex flex-col items-center justify-center gap-8 pt-16 pb-8 mx-4 ${STYLES.TEXT_COLOR}`}>
<div
className={`min-h-screen flex flex-col items-center justify-center gap-8 pt-16 pb-8 mx-4 ${STYLES.TEXT_COLOR}`}>
<Icon className="w-12 h-12 animate-spin fill-current" />
<h2 className="font-bold text-2xl">Unknown Error</h2>
<p className="max-w-xl">
<h2 className="font-bold text-2xl">Unexpected Error</h2>
<p className="max-w-xl text-center">
<a href="https://cdn.ai-rub.de/public/oopsie.mp4" className={`${STYLES.LINK_COLOR} underline`}>
OOPSIE WOOPSIE!!
</a>{" "}
......@@ -42,11 +43,15 @@ function Fallback({ error }: FallbackProps) {
function ErrorDetails({ error }: { error: Error }) {
const errorMessage = error.message || "Unknown Error";
return (
<div className="w-full overflow-x-auto">
<details className="text-sm mt-4">
<summary className="cursor-pointer">{errorMessage}</summary>
<pre className={`w-fit p-4 bg-slate-100 dark:bg-slate-900 border ${STYLES.BORDER_COLOR} rounded-md`}>{error.stack}</pre>
</details>
<div className="grid place-items-center">
<div className="max-w-full overflow-x-auto">
<details className="text-sm mt-4">
<summary className="cursor-pointer mb-2">{errorMessage}</summary>
<pre className={`w-fit p-4 bg-slate-100 dark:bg-slate-900 border ${STYLES.BORDER_COLOR} rounded-md`}>
{error.stack}
</pre>
</details>
</div>
</div>
);
}
import { useEffect, useState } from "react";
import { IntlProvider } from "react-intl";
import type { WithChildren } from "../../utils/types";
import type { WithChildren, WithClassName } from "../../utils/types";
import Logger from "../../Logger";
import { useLanguageStore } from "../../data/state/language";
import LoadingIndicator from "../widgets/LoadingIndicator";
......@@ -8,6 +8,7 @@ import Events from "../../data/events/Events";
import { EventTypes } from "../../data/events/eventTypes";
import useEvents from "../../data/events/useEvents";
import Overlay from "../widgets/Overlay";
import classNames from "classnames";
const TAG = "AppIntlProvider";
......@@ -17,9 +18,16 @@ export default function AppIntlProvider({ children }: WithChildren) {
const language = useLanguageStore(s => s.language);
const [messages, setMessages] = useState<IntlMessageMap | null>(null);
const [isLoading, setLoading] = useState<boolean>(false);
const [error, setError] = useState<Error | null>(null);
useEvents(data => {
switch (data.type) {
case EventTypes.LANGUAGE_LOAD_FAIL:
// Can't really work without strings, so hard-crash here to give
// the user a semi-good error message using the error boundary.
data.error.message = `Failed to load app language file: ${data.error.message}`;
setError(data.error);
break;
case EventTypes.LANGUAGE_LOAD_SUCCESS:
setMessages(data.language);
setLoading(false);
......@@ -32,15 +40,19 @@ export default function AppIntlProvider({ children }: WithChildren) {
setLoading(true);
}, [language]);
if (error) {
throw error;
}
if (!messages) {
return <LoadingIndicator className="font-bold text-2xl mt-16">Loading…</LoadingIndicator>;
return <Loading className="mt-16" />;
}
return (
<IntlProvider locale={language} messages={messages}>
{children}
<Overlay isVisible={isLoading}>
<LoadingIndicator className="font-bold text-2xl">Loading Language…</LoadingIndicator>
<Loading />
</Overlay>
</IntlProvider>
);
......@@ -50,10 +62,17 @@ export function preloadActiveLanguage() {
void loadLanguageFile(useLanguageStore.getState().language);
}
function Loading({ className }: WithClassName) {
return <LoadingIndicator className={classNames("font-bold text-2xl", className)}>Loading App…</LoadingIndicator>;
}
function loadLanguage(lang: string) {
loadLanguageFile(lang)
// TODO debug
// .then(l => new Promise<IntlMessageMap>(r => setTimeout(() => r(l), 2000)))
.then(lang => {
throw new Error("Failed to load shit");
})
.then(language => Events.emit(EventTypes.LANGUAGE_LOAD_SUCCESS, { language }))
.catch(error => {
Events.emit(EventTypes.LANGUAGE_LOAD_FAIL, { error: error as Error });
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment