Fix repost state drift and document workflow
This commit is contained in:
@@ -182,7 +182,8 @@ export async function GET(
|
||||
const viewerReposts = await db.query.posts.findMany({
|
||||
where: and(
|
||||
eq(posts.userId, viewer.id),
|
||||
inArray(posts.repostOfId, allPostIds)
|
||||
inArray(posts.repostOfId, allPostIds),
|
||||
eq(posts.isRemoved, false)
|
||||
),
|
||||
});
|
||||
const repostedPostIds = new Set(viewerReposts.map(r => r.repostOfId));
|
||||
|
||||
@@ -821,7 +821,8 @@ export async function GET(request: Request) {
|
||||
const viewerReposts = await db.query.posts.findMany({
|
||||
where: and(
|
||||
eq(posts.userId, viewer.id),
|
||||
inArray(posts.repostOfId, localPostIds)
|
||||
inArray(posts.repostOfId, localPostIds),
|
||||
eq(posts.isRemoved, false)
|
||||
),
|
||||
});
|
||||
viewerReposts.forEach(r => { if (r.repostOfId) repostedPostIds.add(r.repostOfId); });
|
||||
|
||||
@@ -201,7 +201,8 @@ export async function GET(request: Request) {
|
||||
const viewerReposts = await db.query.posts.findMany({
|
||||
where: and(
|
||||
eq(posts.userId, viewer.id),
|
||||
inArray(posts.repostOfId, postIds)
|
||||
inArray(posts.repostOfId, postIds),
|
||||
eq(posts.isRemoved, false)
|
||||
),
|
||||
});
|
||||
const repostedPostIds = new Set(viewerReposts.map(r => r.repostOfId));
|
||||
|
||||
@@ -67,7 +67,8 @@ export async function GET(request: Request, context: RouteContext) {
|
||||
const viewerReposts = await db.query.posts.findMany({
|
||||
where: and(
|
||||
eq(posts.userId, viewer.id),
|
||||
inArray(posts.repostOfId, postIds)
|
||||
inArray(posts.repostOfId, postIds),
|
||||
eq(posts.isRemoved, false)
|
||||
),
|
||||
});
|
||||
const repostedPostIds = new Set(viewerReposts.map(r => r.repostOfId));
|
||||
|
||||
@@ -177,7 +177,8 @@ export async function GET(request: Request, context: RouteContext) {
|
||||
const viewerReposts = await db.query.posts.findMany({
|
||||
where: and(
|
||||
eq(posts.userId, viewer.id),
|
||||
inArray(posts.repostOfId, postIds)
|
||||
inArray(posts.repostOfId, postIds),
|
||||
eq(posts.isRemoved, false)
|
||||
),
|
||||
});
|
||||
const repostedPostIds = new Set(viewerReposts.map(r => r.repostOfId));
|
||||
|
||||
@@ -274,7 +274,12 @@ export default function ExplorePage() {
|
||||
|
||||
const handleRepost = async (postId: string, currentReposted: boolean) => {
|
||||
const method = currentReposted ? 'DELETE' : 'POST';
|
||||
await fetch(`/api/posts/${postId}/repost`, { method });
|
||||
const res = await fetch(`/api/posts/${postId}/repost`, { method });
|
||||
|
||||
if (!res.ok) {
|
||||
const data = await res.json().catch(() => ({}));
|
||||
throw new Error(data.error || 'Failed to update repost');
|
||||
}
|
||||
};
|
||||
|
||||
const handleDelete = (postId: string) => {
|
||||
|
||||
+7
-4
@@ -173,10 +173,13 @@ export default function Home() {
|
||||
|
||||
const handleRepost = async (postId: string, currentReposted: boolean) => {
|
||||
if (!did || !handle) return;
|
||||
if (currentReposted) {
|
||||
await signedAPI.unrepostPost(postId, did, handle);
|
||||
} else {
|
||||
await signedAPI.repostPost(postId, did, handle);
|
||||
const res = currentReposted
|
||||
? await signedAPI.unrepostPost(postId, did, handle)
|
||||
: await signedAPI.repostPost(postId, did, handle);
|
||||
|
||||
if (!res.ok) {
|
||||
const data = await res.json().catch(() => ({}));
|
||||
throw new Error(data.error || 'Failed to update repost');
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -187,7 +187,12 @@ export default function SearchPage() {
|
||||
|
||||
const handleRepost = async (postId: string, currentReposted: boolean) => {
|
||||
const method = currentReposted ? 'DELETE' : 'POST';
|
||||
await fetch(`/api/posts/${postId}/repost`, { method });
|
||||
const res = await fetch(`/api/posts/${postId}/repost`, { method });
|
||||
|
||||
if (!res.ok) {
|
||||
const data = await res.json().catch(() => ({}));
|
||||
throw new Error(data.error || 'Failed to update repost');
|
||||
}
|
||||
};
|
||||
|
||||
const handleDelete = (postId: string) => {
|
||||
|
||||
@@ -213,7 +213,12 @@ export default function ProfilePage() {
|
||||
|
||||
const handleRepost = async (postId: string, currentReposted: boolean) => {
|
||||
const method = currentReposted ? 'DELETE' : 'POST';
|
||||
await fetch(`/api/posts/${postId}/repost`, { method });
|
||||
const res = await fetch(`/api/posts/${postId}/repost`, { method });
|
||||
|
||||
if (!res.ok) {
|
||||
const data = await res.json().catch(() => ({}));
|
||||
throw new Error(data.error || 'Failed to update repost');
|
||||
}
|
||||
};
|
||||
|
||||
const handleComment = (post: Post) => {
|
||||
|
||||
@@ -92,10 +92,13 @@ export default function PostDetailPage() {
|
||||
|
||||
const handleRepost = async (postId: string, currentReposted: boolean) => {
|
||||
if (!did || !userHandle) return;
|
||||
if (currentReposted) {
|
||||
await signedAPI.unrepostPost(postId, did, userHandle);
|
||||
} else {
|
||||
await signedAPI.repostPost(postId, did, userHandle);
|
||||
const res = currentReposted
|
||||
? await signedAPI.unrepostPost(postId, did, userHandle)
|
||||
: await signedAPI.repostPost(postId, did, userHandle);
|
||||
|
||||
if (!res.ok) {
|
||||
const data = await res.json().catch(() => ({}));
|
||||
throw new Error(data.error || 'Failed to update repost');
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ function LinkPreviewImage({ src, alt }: { src: string; alt: string }) {
|
||||
interface PostCardProps {
|
||||
post: Post;
|
||||
onLike?: (id: string, currentLiked: boolean) => void;
|
||||
onRepost?: (id: string, currentReposted: boolean) => void;
|
||||
onRepost?: (id: string, currentReposted: boolean) => Promise<void> | void;
|
||||
onComment?: (post: Post) => void;
|
||||
onDelete?: (id: string) => void;
|
||||
onHide?: (id: string) => void; // Called when post should be hidden (block/mute)
|
||||
@@ -50,6 +50,8 @@ export function PostCard({ post, onLike, onRepost, onComment, onDelete, onHide,
|
||||
const router = useRouter();
|
||||
const [liked, setLiked] = useState(post.isLiked || false);
|
||||
const [reposted, setReposted] = useState(post.isReposted || false);
|
||||
const [repostsCount, setRepostsCount] = useState(post.repostsCount || 0);
|
||||
const [repostPending, setRepostPending] = useState(false);
|
||||
const [reporting, setReporting] = useState(false);
|
||||
const [deleting, setDeleting] = useState(false);
|
||||
const [showMenu, setShowMenu] = useState(false);
|
||||
@@ -61,7 +63,8 @@ export function PostCard({ post, onLike, onRepost, onComment, onDelete, onHide,
|
||||
useEffect(() => {
|
||||
setLiked(post.isLiked || false);
|
||||
setReposted(post.isReposted || false);
|
||||
}, [post.isLiked, post.isReposted, post.id]);
|
||||
setRepostsCount(post.repostsCount || 0);
|
||||
}, [post.isLiked, post.isReposted, post.repostsCount, post.id]);
|
||||
|
||||
const formatTime = (dateStr: string | Date) => {
|
||||
const date = new Date(dateStr);
|
||||
@@ -104,18 +107,37 @@ export function PostCard({ post, onLike, onRepost, onComment, onDelete, onHide,
|
||||
onLike?.(post.id, currentLiked); // Pass current state before toggle
|
||||
};
|
||||
|
||||
const handleRepost = (e: React.MouseEvent) => {
|
||||
const handleRepost = async (e: React.MouseEvent) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
if (repostPending) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isIdentityUnlocked) {
|
||||
showToast('Please log in to repost', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
const currentReposted = reposted;
|
||||
setReposted(!currentReposted);
|
||||
onRepost?.(post.id, currentReposted); // Pass current state before toggle
|
||||
const currentRepostsCount = repostsCount;
|
||||
const nextReposted = !currentReposted;
|
||||
const nextRepostsCount = Math.max(0, currentRepostsCount + (currentReposted ? -1 : 1));
|
||||
|
||||
setReposted(nextReposted);
|
||||
setRepostsCount(nextRepostsCount);
|
||||
setRepostPending(true);
|
||||
|
||||
try {
|
||||
await onRepost?.(post.id, currentReposted);
|
||||
} catch (error) {
|
||||
setReposted(currentReposted);
|
||||
setRepostsCount(currentRepostsCount);
|
||||
showToast(error instanceof Error ? error.message : 'Failed to update repost', 'error');
|
||||
} finally {
|
||||
setRepostPending(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleComment = (e: React.MouseEvent) => {
|
||||
@@ -657,9 +679,9 @@ export function PostCard({ post, onLike, onRepost, onComment, onDelete, onHide,
|
||||
<MessageIcon />
|
||||
<span>{post.repliesCount || ''}</span>
|
||||
</button>
|
||||
<button className={`post-action ${reposted ? 'reposted' : ''}`} onClick={handleRepost}>
|
||||
<button className={`post-action ${reposted ? 'reposted' : ''}`} onClick={handleRepost} disabled={repostPending}>
|
||||
<RepeatIcon />
|
||||
<span>{(post.repostsCount - (post.isReposted ? 1 : 0)) + (reposted ? 1 : 0) || ''}</span>
|
||||
<span>{repostsCount || ''}</span>
|
||||
</button>
|
||||
<button className={`post-action ${liked ? 'liked' : ''}`} onClick={handleLike}>
|
||||
<HeartIcon filled={liked} />
|
||||
|
||||
Reference in New Issue
Block a user