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", () => {