diff --git a/src/pages/Index.tsx b/src/pages/Index.tsx index c1b28408..3e2a6923 100644 --- a/src/pages/Index.tsx +++ b/src/pages/Index.tsx @@ -6,7 +6,7 @@ */ import { useCallback, useEffect, useMemo, useRef } from "react"; -import { useLocation } from "react-router"; +import { Navigate, useLocation } from "react-router"; import { AppHeader } from "../components/layout/AppHeader.tsx"; import { PresenceRow } from "../components/feed/PresenceRow.tsx"; @@ -36,6 +36,7 @@ import { DumpFeed, type MainFeedProps } from "../components/feed/DumpFeed.tsx"; import { JournalFeed } from "../components/feed/JournalFeed.tsx"; import { FollowedFeed } from "../components/feed/FollowedFeed.tsx"; import { NotFound } from "./NotFound.tsx"; +import { loginPath } from "../utils/auth/next.ts"; /** Passed to {@link Index} by the router, from the path. */ export interface IndexProps { @@ -76,11 +77,7 @@ export function Index( ); const defaultTab = useViewerDefaultFeedTab(); - // A guest on "follow", from a shared link or after signing out, gets the - // default tab rather than an empty page. - const tab: FeedTab = feedTab && (feedTab !== "follow" || !!user) - ? feedTab - : defaultTab; + const tab: FeedTab = feedTab ?? defaultTab; const feedUrl = categorySlug ? `${API_URL}/api/dumps?category=${encodeURIComponent(categorySlug)}` @@ -181,6 +178,13 @@ export function Index( }; if (categoryNotFound) return ; + // The default tab is never "follow" for a guest, so only a link leads one + // here: a digest's, or the page they signed out on. + if (tab === "follow" && !user) { + return ( + + ); + } return (
diff --git a/src/pages/RestrictedLoggedIn.tsx b/src/pages/RestrictedLoggedIn.tsx index 682570eb..ae29d26c 100644 --- a/src/pages/RestrictedLoggedIn.tsx +++ b/src/pages/RestrictedLoggedIn.tsx @@ -1,13 +1,15 @@ /** - * Guards `App`'s routes that need a session, the dump editor and - * `/notifications`. + * Guards `App`'s routes that need a session: the dump editor, + * `/notifications`, `/community`, `/settings` and `/manage`. `Index` sends a + * guest on the "follow" tab to sign in the same way. * * @module */ -import { Navigate } from "react-router"; +import { Navigate, useLocation } from "react-router"; import { useAuth } from "../hooks/auth/useAuth.ts"; +import { loginPath } from "../utils/auth/next.ts"; /** Passed to {@link RestrictedLoggedIn} by `App`, around a route's page. */ export interface RestrictedLoggedInProps { @@ -15,14 +17,17 @@ export interface RestrictedLoggedInProps { } /** - * Renders `children` when someone is signed in, and redirects to `/login` - * otherwise. The page it came from is not remembered, so signing in lands on - * `/`. + * Renders `children` when someone is signed in, and otherwise replaces the + * page with `/login`, which comes back to it once signed in: a digest's link + * to `/notifications` opened signed out lands there after all. */ export function RestrictedLoggedIn( { children }: RestrictedLoggedInProps, ): React.JSX.Element { const { user } = useAuth(); + const location = useLocation(); - return user ? <>{children} : ; + return user + ? <>{children} + : ; } diff --git a/src/test/pages/Index.test.tsx b/src/test/pages/Index.test.tsx index c66513b1..912530a0 100644 --- a/src/test/pages/Index.test.tsx +++ b/src/test/pages/Index.test.tsx @@ -249,10 +249,10 @@ describe("Index feeds", () => { .toBeInTheDocument(); }); - test("a guest on the follow tab gets the default feed, not a blank page", async () => { + test("a guest on the follow tab is sent to sign in, and back", () => { route("GET /api/dumps", () => page([older])); - setup("/follow"); - await screen.findByText("Old but loved"); + setup("/music/follow"); + expect(currentPath()).toBe("/login?next=%2Fmusic%2Ffollow"); }); test("the Android share sheet opens the new-dump form with the link", async () => { diff --git a/src/test/pages/RestrictedLoggedIn.test.tsx b/src/test/pages/RestrictedLoggedIn.test.tsx index 61bc7e70..a00b71ab 100644 --- a/src/test/pages/RestrictedLoggedIn.test.tsx +++ b/src/test/pages/RestrictedLoggedIn.test.tsx @@ -3,21 +3,22 @@ import { screen } from "@testing-library/react"; import { Route } from "react-router"; import { RestrictedLoggedIn } from "../../pages/RestrictedLoggedIn.tsx"; import { makeSession } from "../fixtures.ts"; -import { renderWithContexts } from "../render.tsx"; +import { currentPath, renderWithContexts } from "../render.tsx"; describe("RestrictedLoggedIn", () => { - test("sends guests to login", () => { + test("sends guests to login, which comes back to the page", () => { renderWithContexts(

secret

, { - route: "/notifications", - path: "/notifications", + route: "/community/monthly?x=1", + path: "/community/monthly", extraRoutes: login page

} />, }, ); expect(screen.getByText("login page")).toBeInTheDocument(); + expect(currentPath()).toBe("/login?next=%2Fcommunity%2Fmonthly%3Fx%3D1"); }); test("lets members through", () => {