Catch the component's errors inside the component

Only the call body sat inside an error boundary; anything thrown in the
lobby, the mute state or the providers propagated into the host's React
tree, where React unmounts everything up to the nearest boundary — the
host's, or the host's whole application. The standalone app has a
boundary at its top; the component now has the same, showing the error
page inside its container and asking the host to stop keeping it on
screen.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Timo K.
2026-09-08 15:38:59 +02:00
co-authored by Claude Fable 5.1
parent 779ee7a008
commit d18e82c546
+10
View File
@@ -45,11 +45,13 @@ import { logger } from "matrix-js-sdk/lib/logger";
import { MemoryRouter } from "react-router-dom"; import { MemoryRouter } from "react-router-dom";
import { I18nextProvider } from "react-i18next"; import { I18nextProvider } from "react-i18next";
import { TooltipProvider } from "@vector-im/compound-web"; import { TooltipProvider } from "@vector-im/compound-web";
import { ErrorBoundary } from "@sentry/react";
import { shouldPolyfill as shouldPolyfillSegmenter } from "@formatjs/intl-segmenter/should-polyfill"; import { shouldPolyfill as shouldPolyfillSegmenter } from "@formatjs/intl-segmenter/should-polyfill";
import { shouldPolyfill as shouldPolyfillDurationFormat } from "@formatjs/intl-durationformat/should-polyfill.js"; import { shouldPolyfill as shouldPolyfillDurationFormat } from "@formatjs/intl-durationformat/should-polyfill.js";
import EN from "../locales/en/app.json"; import EN from "../locales/en/app.json";
import { ElementCallView } from "../src/ElementCallView"; import { ElementCallView } from "../src/ElementCallView";
import { ErrorPage } from "../src/FullScreenView";
import { ClientProvider } from "../src/ClientContext"; import { ClientProvider } from "../src/ClientContext";
import { import {
type HostBridge, type HostBridge,
@@ -265,6 +267,13 @@ export const ElementCall: FC<ElementCallProps> = ({
rtcSession !== null && rtcSession !== null &&
mediaDevices !== null && ( mediaDevices !== null && (
<RootElementProvider value={container}> <RootElementProvider value={container}>
{/* Whatever goes wrong in here is shown in here. Left to
propagate, an error would unmount the host's own tree. */}
<ErrorBoundary
fallback={(error) => <ErrorPage error={error} />}
// A broken call should not hold the host on screen
onError={() => void hostBridge.setAlwaysOnScreen(false)}
>
<Decoration> <Decoration>
<TooltipProvider> <TooltipProvider>
<ClientProvider client={client}> <ClientProvider client={client}>
@@ -283,6 +292,7 @@ export const ElementCall: FC<ElementCallProps> = ({
</ClientProvider> </ClientProvider>
</TooltipProvider> </TooltipProvider>
</Decoration> </Decoration>
</ErrorBoundary>
</RootElementProvider> </RootElementProvider>
)} )}
</div> </div>