"use client"; /** * /u/me shared layout — auth gate + Instagram-style profile shell. * * • Anonymous visitors trigger the global AuthModal and are bounced * home if they dismiss it (unchanged from before). * • Renders the ProfileHeader + ProfileTabs above every /u/me/* page. * Tabs: Posts / Collections / Bookmarks / Mentions. * * The old left ProfileSidebar is gone. The "Edit profile" affordance on * the header links out to the dedicated /settings/profile editor (which * lives outside this layout so it isn't framed by the header + tabs). */ import { useCallback, useEffect, useMemo, useState } from "react"; import { useRouter } from "next/navigation"; import { AtSign, Bookmark, EyeOff, FolderClosed, LayoutGrid, } from "lucide-react"; import { useAuth } from "@/components/auth/auth-provider"; import { useAuthGate } from "@/components/auth/auth-gate"; import { profile } from "@/lib/social"; import { ProfileHeader } from "@/components/profile/profile-header"; import { ProfileTabs, type ProfileTab } from "@/components/profile/profile-tabs"; import { HiddenCountProvider } from "@/components/profile/hidden-count-context"; export default function MeLayout({ children }: { children: React.ReactNode }) { const { user, loading } = useAuth(); const { requireAuth } = useAuthGate(); const router = useRouter(); useEffect(() => { if (loading || user) return; let cancelled = false; (async () => { const ok = await requireAuth(); if (!ok && !cancelled) router.replace("/"); })(); return () => { cancelled = true; }; }, [loading, user, requireAuth, router]); // Own profile counts (posts / followers / following) for the header // stat line. /auth/me doesn't carry these, so we read them from the // public profile endpoint (which returns no relationship for self). const [counts, setCounts] = useState<{ posts: number; followers: number; following: number; hidden: number; } | null>(null); const handle = user?.handle; useEffect(() => { if (!handle) return; let cancelled = false; profile .get(handle) .then((p) => { if (!cancelled) { setCounts({ posts: p.post_count, followers: p.follower_count, following: p.following_count, hidden: p.hidden_count ?? 0, }); } }) .catch(() => { /* counts are non-critical; leave the stat line minimal on error */ }); return () => { cancelled = true; }; }, [handle]); // Let a hide/unhide action anywhere in the subtree (the PostCardMenu) nudge // the hidden count so the "Hidden" tab toggles instantly. Clamped at 0. const adjustHiddenCount = useCallback((delta: number) => { setCounts((c) => c ? { ...c, hidden: Math.max(0, c.hidden + delta) } : c, ); }, []); const hiddenCtx = useMemo(() => ({ adjustHiddenCount }), [adjustHiddenCount]); if (loading || !user) { return (

{loading ? "Loading…" : "Sign in to view your library."}

); } const tabs: ProfileTab[] = [ { href: "/u/me", label: "Posts", icon: , activeFor: ["/u/me/posts"], }, { href: "/u/me/collections", label: "Collections", icon: , }, { href: "/u/me/bookmarks", label: "Bookmarks", icon: , }, { href: "/u/me/mentions", label: "Mentions", icon: , }, ]; // Surface the "Hidden" tab only when the user actually has hidden posts. if ((counts?.hidden ?? 0) > 0) { tabs.push({ href: "/u/me/hidden", label: "Hidden", icon: , }); } return (
{children}
); }