91 lines
3.0 KiB
TypeScript
91 lines
3.0 KiB
TypeScript
"use client";
|
|
|
|
/**
|
|
* /u/me/hidden — the owner's hidden posts.
|
|
*
|
|
* Posts hidden from timelines + public collections live here (and in any
|
|
* private collections). Each card's overflow menu offers "Unhide from
|
|
* timeline"; on unhide we drop the post from this list since it's no longer
|
|
* hidden. The tab itself is only shown (by the /u/me layout) when the user
|
|
* has at least one hidden post.
|
|
*/
|
|
|
|
import { useEffect, useState } from "react";
|
|
import { useRouter } from "next/navigation";
|
|
import { useAuth } from "@/components/auth/auth-provider";
|
|
import { PostScrollCard } from "@/components/social/post/post-scroll-card";
|
|
import { posts, SocialError, type Post } from "@/lib/social";
|
|
|
|
export default function MyHiddenPostsPage() {
|
|
const { user } = useAuth();
|
|
const router = useRouter();
|
|
const [feed, setFeed] = useState<Post[]>([]);
|
|
const [loading, setLoading] = useState(true);
|
|
const [error, setError] = useState<string | null>(null);
|
|
|
|
useEffect(() => {
|
|
if (!user) return;
|
|
posts
|
|
.hidden()
|
|
.then((rows) => {
|
|
const list = rows ?? [];
|
|
setFeed(list);
|
|
// Nothing hidden → the "Hidden" tab isn't in the strip, so this page
|
|
// is a tab-less dead-end. Send the user to their Posts tab instead.
|
|
if (list.length === 0) router.replace("/u/me");
|
|
})
|
|
.catch((err) =>
|
|
setError(
|
|
err instanceof SocialError
|
|
? err.message
|
|
: "Could not load hidden posts.",
|
|
),
|
|
)
|
|
.finally(() => setLoading(false));
|
|
}, [user, router]);
|
|
|
|
function onPostUpdated(updated: Post) {
|
|
setFeed((rows) => rows.map((p) => (p.id === updated.id ? updated : p)));
|
|
}
|
|
|
|
// Unhiding a post means it's no longer hidden → drop it from this list.
|
|
// When that empties the list, the "Hidden" tab disappears (the layout's
|
|
// count hits 0), so move the user to their Posts tab rather than leaving
|
|
// them on an empty page with no active tab.
|
|
function onHiddenChange(id: string, hidden: boolean) {
|
|
if (hidden) return;
|
|
const remaining = feed.filter((p) => p.id !== id);
|
|
setFeed(remaining);
|
|
if (remaining.length === 0) router.replace("/u/me");
|
|
}
|
|
|
|
if (!user) return null;
|
|
|
|
return (
|
|
<div className="max-w-xl w-full mx-auto space-y-6">
|
|
<p className="text-sm text-muted-foreground">
|
|
Hidden posts don't appear on your timeline, in the feed, or in
|
|
public collections — but stay in your private collections. Use a card's
|
|
menu to unhide.
|
|
</p>
|
|
|
|
{error ? (
|
|
<p className="text-sm text-destructive">{error}</p>
|
|
) : loading ? (
|
|
<p className="text-sm text-muted-foreground">Loading…</p>
|
|
) : feed.length === 0 ? (
|
|
<p className="text-sm text-muted-foreground">No hidden posts.</p>
|
|
) : (
|
|
feed.map((p) => (
|
|
<PostScrollCard
|
|
key={p.id}
|
|
post={p}
|
|
onUpdated={onPostUpdated}
|
|
onHiddenChange={onHiddenChange}
|
|
/>
|
|
))
|
|
)}
|
|
</div>
|
|
);
|
|
}
|