mirror of
https://github.com/vector-im/element-call.git
synced 2026-09-10 21:55:19 +00:00
ErrorView needed a widget only to decide whether to offer a close button or a link home. That prop was threaded down through ErrorPage, RichError and GroupCallErrorBoundary from seven call sites, to answer the single question of whether the host can dismiss Element Call — which the host bridge now answers directly through the presence of close(). Read the bridge from context in ErrorView and remove the prop, along with the plumbing that carried it. No functional change: the rendered output is unchanged, as the existing snapshot confirms. Move GroupCallView onto the host bridge GroupCallView asked the widget API to keep it on screen, to close it, and to tell it when a preloaded call should join. Route all three through the host bridge and drop the widget prop.
113 lines
2.9 KiB
TypeScript
113 lines
2.9 KiB
TypeScript
/*
|
|
Copyright 2025 New Vector Ltd.
|
|
|
|
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
|
Please see LICENSE in the repository root for full details.
|
|
*/
|
|
|
|
import { BigIcon, Button, Heading } from "@vector-im/compound-web";
|
|
import {
|
|
useCallback,
|
|
type ComponentType,
|
|
type FC,
|
|
type ReactNode,
|
|
type SVGAttributes,
|
|
type ReactElement,
|
|
} from "react";
|
|
import { useTranslation } from "react-i18next";
|
|
import { logger } from "matrix-js-sdk/lib/logger";
|
|
|
|
import { RageshakeButton } from "./settings/RageshakeButton";
|
|
import styles from "./ErrorView.module.css";
|
|
import { useUrlParams } from "./UrlParams";
|
|
import { LinkButton } from "./button";
|
|
import { useHostBridge } from "./HostBridge.ts";
|
|
|
|
interface Props {
|
|
Icon: ComponentType<SVGAttributes<SVGElement>>;
|
|
title: string;
|
|
/**
|
|
* Show an option to submit a rageshake.
|
|
* @default false
|
|
*/
|
|
rageshake?: boolean;
|
|
/**
|
|
* Whether the error is considered fatal, i.e. non-recoverable. Causes the app
|
|
* to fully reload when clicking 'return to home'.
|
|
* @default false
|
|
*/
|
|
fatal?: boolean;
|
|
children: ReactNode;
|
|
}
|
|
|
|
export const ErrorView: FC<Props> = ({
|
|
Icon,
|
|
title,
|
|
rageshake,
|
|
fatal,
|
|
children,
|
|
}) => {
|
|
const { t } = useTranslation();
|
|
const { confineToRoom } = useUrlParams();
|
|
const hostBridge = useHostBridge();
|
|
|
|
const onReload = useCallback(() => {
|
|
window.location.href = "/";
|
|
}, []);
|
|
|
|
const CloseButton: FC<{ close: () => Promise<void> }> = ({
|
|
close,
|
|
}): ReactElement => {
|
|
// When the host can dismiss us, offer that instead of a link home
|
|
const onClose = (): void => {
|
|
close().catch((e) => {
|
|
// What to do here?
|
|
logger.error("Failed to ask the host to close Element Call", e);
|
|
});
|
|
};
|
|
return (
|
|
<Button kind="primary" onClick={onClose}>
|
|
{t("action.close")}
|
|
</Button>
|
|
);
|
|
};
|
|
|
|
// Whether the error is considered fatal or pathname is `/` then reload the all app.
|
|
// If not then navigate to home page.
|
|
const ReturnToHomeButton = (): ReactElement => {
|
|
if (fatal || location.pathname === "/") {
|
|
return (
|
|
<Button kind="tertiary" className={styles.homeLink} onClick={onReload}>
|
|
{t("return_home_button")}
|
|
</Button>
|
|
);
|
|
} else {
|
|
return (
|
|
<LinkButton kind="tertiary" className={styles.homeLink} to="/">
|
|
{t("return_home_button")}
|
|
</LinkButton>
|
|
);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div className={styles.error}>
|
|
<BigIcon className={styles.icon}>
|
|
<Icon aria-hidden />
|
|
</BigIcon>
|
|
<Heading as="h1" weight="semibold" size="md">
|
|
{title}
|
|
</Heading>
|
|
{children}
|
|
{rageshake && (
|
|
<RageshakeButton description={`***Error View***: ${title}`} />
|
|
)}
|
|
{hostBridge.close ? (
|
|
<CloseButton close={hostBridge.close} />
|
|
) : (
|
|
!confineToRoom && <ReturnToHomeButton />
|
|
)}
|
|
</div>
|
|
);
|
|
};
|