Let the shell say where home is, and drop the router from the call

The call reached for react-router in five places to send the user
"home": on leaving without a lobby, from the lobby's recents link, from
the post-call screen, from the error page's return button and from the
header logo. Home is the standalone app's home page; the call has no
idea where that is, and a component has no such place at all — its host
decides what follows a call. Yet the component had to mount a
MemoryRouter just so those hooks would not throw.

`useLeaveToHome` is the way home as the shell supplies it: the app
provides `navigate("/")` from inside its router, the component provides
nothing, and everything that used to link to "/" now either calls it or,
when there is none, offers no way out. The logo becomes a plain logo,
the recents and "not now" links disappear, the error page's button does
too. `ClientProvider`'s logout goes the same way. The component no
longer renders a router.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Timo K.
2026-09-08 15:39:00 +02:00
co-authored by Claude Fable 5.1
parent f5a94ce702
commit b7285064fd
15 changed files with 299 additions and 182 deletions
+11 -9
View File
@@ -9,8 +9,6 @@ import { type FC, type FormEventHandler, useCallback, useState } from "react";
import { type MatrixClient } from "matrix-js-sdk";
import { Trans, useTranslation } from "react-i18next";
import { Button, Heading, Text } from "@vector-im/compound-web";
import { useNavigate } from "react-router-dom";
import { logger } from "matrix-js-sdk/lib/logger";
import styles from "./CallEndedView.module.css";
import feedbackStyle from "../input/FeedbackInput.module.css";
@@ -19,8 +17,9 @@ import { Header, HeaderLogo, LeftNav, RightNav } from "../Header";
import { PosthogAnalytics } from "../analytics/PosthogAnalytics";
import { FieldRow, InputField } from "../input/Input";
import { StarRatingInput } from "../input/StarRatingInput";
import { Link } from "../button/Link";
import { LinkButton } from "../button";
import { LeaveToHomeLink } from "../button/LeaveToHomeLink";
import { useLeaveToHome } from "../LeaveToHomeContext";
interface Props {
client: MatrixClient;
@@ -38,7 +37,7 @@ export const CallEndedView: FC<Props> = ({
endedCallId,
}) => {
const { t } = useTranslation();
const navigate = useNavigate();
const leaveToHome = useLeaveToHome();
const { displayName } = useProfile(client);
const [surveySubmitted, setSurveySubmitted] = useState(false);
@@ -68,14 +67,12 @@ export const CallEndedView: FC<Props> = ({
setSurveySubmitted(true);
} else if (!confineToRoom) {
// if the user already has an account immediately go back to the home screen
navigate("/")?.catch((error) => {
logger.error("Failed to navigate to /", error);
});
leaveToHome?.();
}
}, 1000);
}, 1000);
},
[endedCallId, navigate, isPasswordlessUser, confineToRoom, starRating],
[endedCallId, leaveToHome, isPasswordlessUser, confineToRoom, starRating],
);
const createAccountDialog = isPasswordlessUser && (
@@ -87,6 +84,8 @@ export const CallEndedView: FC<Props> = ({
calls
</p>
</Trans>
{/* Only guests of the standalone app are ever passwordless, so this
route is always the standalone app's own. */}
<LinkButton className={styles.callEndedButton} to="/register">
{t("call_ended_view.create_account_button")}
</LinkButton>
@@ -157,7 +156,10 @@ export const CallEndedView: FC<Props> = ({
</main>
{!confineToRoom && (
<Text className={styles.footer}>
<Link to="/"> {t("call_ended_view.not_now_button")} </Link>
<LeaveToHomeLink>
{" "}
{t("call_ended_view.not_now_button")}{" "}
</LeaveToHomeLink>
</Text>
)}
</div>