diff --git a/thoughts-frontend/app/remote-actor/page.tsx b/thoughts-frontend/app/remote-actor/page.tsx new file mode 100644 index 0000000..d8b9bce --- /dev/null +++ b/thoughts-frontend/app/remote-actor/page.tsx @@ -0,0 +1,35 @@ +import { notFound } from "next/navigation"; +import { cookies } from "next/headers"; +import { getMe, lookupRemoteActor, getRemoteActorPosts, Me } from "@/lib/api"; +import { RemoteUserProfile } from "@/components/remote-user-profile"; + +interface RemoteActorPageProps { + searchParams: Promise<{ handle?: string }>; +} + +export default async function RemoteActorPage({ + searchParams, +}: RemoteActorPageProps) { + const { handle } = await searchParams; + if (!handle) notFound(); + + const token = (await cookies()).get("auth_token")?.value ?? null; + + const [actorResult, postsResult, meResult] = await Promise.allSettled([ + lookupRemoteActor(handle, token), + getRemoteActorPosts(handle, 1, token), + token ? getMe(token) : Promise.resolve(null), + ]); + + if (actorResult.status === "rejected") { + notFound(); + } + + const actor = actorResult.value; + const posts = + postsResult.status === "fulfilled" ? postsResult.value.items : []; + const me = + meResult.status === "fulfilled" ? (meResult.value as Me | null) : null; + + return ; +} diff --git a/thoughts-frontend/app/users/[username]/page.tsx b/thoughts-frontend/app/users/[username]/page.tsx index f49e000..dec722c 100644 --- a/thoughts-frontend/app/users/[username]/page.tsx +++ b/thoughts-frontend/app/users/[username]/page.tsx @@ -5,11 +5,8 @@ import { getTopFriends, getUserProfile, getUserThoughts, - lookupRemoteActor, - getRemoteActorPosts, Me, } from "@/lib/api"; -import { RemoteUserProfile } from "@/components/remote-user-profile"; import { UserAvatar } from "@/components/user-avatar"; import { Calendar, Settings } from "lucide-react"; import { Card } from "@/components/ui/card"; @@ -30,28 +27,6 @@ export default async function ProfilePage({ params }: ProfilePageProps) { const { username } = await params; const token = (await cookies()).get("auth_token")?.value ?? null; - const HANDLE_RE = /^@[\w.-]+@[\w.-]+\.\w+$/; - - if (HANDLE_RE.test(username)) { - const [actorResult, postsResult, meResult] = await Promise.allSettled([ - lookupRemoteActor(username, token), - getRemoteActorPosts(username, 1, token), - token ? getMe(token) : Promise.resolve(null), - ]); - - if (actorResult.status === "rejected") { - notFound(); - } - - const actor = actorResult.value as Awaited>; - const posts = - postsResult.status === "fulfilled" ? postsResult.value.items : []; - const me = - meResult.status === "fulfilled" ? (meResult.value as Me | null) : null; - - return ; - } - const userProfilePromise = getUserProfile(username, token); const thoughtsPromise = getUserThoughts(username, token); const mePromise = token ? getMe(token) : Promise.resolve(null); diff --git a/thoughts-frontend/components/remote-user-card.tsx b/thoughts-frontend/components/remote-user-card.tsx index 1b199b0..a07f5e9 100644 --- a/thoughts-frontend/components/remote-user-card.tsx +++ b/thoughts-frontend/components/remote-user-card.tsx @@ -38,7 +38,7 @@ export function RemoteUserCard({ actor }: RemoteUserCardProps) { return (
diff --git a/thoughts-frontend/middleware.ts b/thoughts-frontend/middleware.ts new file mode 100644 index 0000000..c6d0186 --- /dev/null +++ b/thoughts-frontend/middleware.ts @@ -0,0 +1,23 @@ +import { NextResponse } from "next/server"; +import type { NextRequest } from "next/server"; + +export function middleware(request: NextRequest) { + const parts = request.nextUrl.pathname.split("/"); + + // /users/@user@instance or /users/%40user%40instance + if (parts.length === 3 && parts[1] === "users") { + const decoded = decodeURIComponent(parts[2]); + if (decoded.startsWith("@") && decoded.indexOf("@", 1) !== -1) { + const url = request.nextUrl.clone(); + url.pathname = "/remote-actor"; + url.searchParams.set("handle", decoded); + return NextResponse.rewrite(url); + } + } + + return NextResponse.next(); +} + +export const config = { + matcher: "/users/:path*", +};