Feed, VideoCard, Sidebar, PlayerModal, Channels, Stats, SettingsPanel, OnboardingWizard, NotificationCenter, Toaster, ErrorBoundary and the relativeTime helper are now fully translated in Hungarian, English and German, each with its own locale area file (auto-loaded). Key parity verified across all three languages.
49 lines
1.4 KiB
TypeScript
49 lines
1.4 KiB
TypeScript
import { Component, type ReactNode } from "react";
|
|
import i18n from "../i18n";
|
|
import { notify } from "../lib/notifications";
|
|
|
|
interface Props {
|
|
children: ReactNode;
|
|
}
|
|
interface State {
|
|
crashed: boolean;
|
|
}
|
|
|
|
// Catches render-time crashes anywhere in the tree, logs a fatal notification (kept
|
|
// in the center across the reload) and offers a recovery action.
|
|
export default class ErrorBoundary extends Component<Props, State> {
|
|
state: State = { crashed: false };
|
|
|
|
static getDerivedStateFromError(): State {
|
|
return { crashed: true };
|
|
}
|
|
|
|
componentDidCatch(error: Error) {
|
|
notify({
|
|
level: "fatal",
|
|
title: i18n.t("errors.boundary.notifTitle"),
|
|
message: error.message || i18n.t("errors.boundary.notifMessage"),
|
|
requiresInteraction: true,
|
|
});
|
|
}
|
|
|
|
render() {
|
|
if (this.state.crashed) {
|
|
return (
|
|
<div className="min-h-screen grid place-items-center text-muted p-6 text-center">
|
|
<div>
|
|
<div className="text-lg font-semibold text-fg mb-1">{i18n.t("errors.boundary.title")}</div>
|
|
<div className="text-sm mb-3">{i18n.t("errors.boundary.subtitle")}</div>
|
|
<button
|
|
onClick={() => location.reload()}
|
|
className="text-accent hover:underline text-sm font-semibold"
|
|
>
|
|
{i18n.t("errors.boundary.reload")}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
return this.props.children;
|
|
}
|
|
}
|