mirror of
https://github.com/lumina-rocks/lumina.git
synced 2026-04-18 11:26:53 +02:00
106 lines
3.7 KiB
TypeScript
106 lines
3.7 KiB
TypeScript
import { useRef, useState, useEffect } from "react";
|
|
import { useNostrEvents, dateToUnix } from "nostr-react";
|
|
import KIND20Card from "./KIND20Card";
|
|
import { getImageUrl } from "@/utils/utils";
|
|
import { Button } from "@/components/ui/button";
|
|
|
|
interface FollowerFeedProps {
|
|
pubkey: string;
|
|
}
|
|
|
|
const FollowerFeed: React.FC<FollowerFeedProps> = ({ pubkey }) => {
|
|
const now = useRef(new Date());
|
|
const [limit, setLimit] = useState(20);
|
|
const [retryCount, setRetryCount] = useState(0);
|
|
|
|
const { events: following, isLoading: followingLoading } = useNostrEvents({
|
|
filter: {
|
|
kinds: [3],
|
|
authors: [pubkey],
|
|
limit: 1,
|
|
},
|
|
});
|
|
|
|
// Add retry mechanism for following list loading
|
|
useEffect(() => {
|
|
// If following list is empty and we haven't exceeded max retries
|
|
if (following.length === 0 && !followingLoading && retryCount < 3) {
|
|
const timer = setTimeout(() => {
|
|
setRetryCount(prev => prev + 1);
|
|
}, 2000); // Retry after 2 seconds
|
|
|
|
return () => clearTimeout(timer);
|
|
}
|
|
}, [following, followingLoading, retryCount]);
|
|
|
|
let followingPubkeys = following.flatMap((event) =>
|
|
event.tags
|
|
.filter(tag => tag[0] === 'p')
|
|
.map(tag => tag[1])
|
|
);
|
|
|
|
const { events, isLoading } = useNostrEvents({
|
|
filter: {
|
|
limit: limit,
|
|
kinds: [20],
|
|
authors: followingPubkeys.length > 0 ? followingPubkeys : [pubkey], // fallback to user's own posts if following list is empty
|
|
},
|
|
enabled: followingPubkeys.length > 0 || retryCount >= 3, // only run query when we have pubkeys or after max retries
|
|
});
|
|
|
|
const loadMore = () => {
|
|
setLimit(prevLimit => prevLimit + 20);
|
|
};
|
|
|
|
return (
|
|
<>
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 px-2 md:px-4">
|
|
{isLoading && events.length === 0 ? (
|
|
// Show loading placeholder
|
|
Array(4).fill(0).map((_, index) => (
|
|
<div key={index} className="mb-4 md:mb-6">
|
|
<div className="animate-pulse my-4">
|
|
<div className="h-[300px] bg-gray-200 dark:bg-gray-700 rounded-lg"></div>
|
|
<div className="h-5 bg-gray-200 dark:bg-gray-700 rounded mt-4 w-3/4"></div>
|
|
<div className="h-4 bg-gray-200 dark:bg-gray-700 rounded mt-2 w-1/2"></div>
|
|
</div>
|
|
</div>
|
|
))
|
|
) : events.length > 0 ? (
|
|
// Show actual events
|
|
events.map((event) => (
|
|
<div key={event.id} className="mb-4 md:mb-6">
|
|
<KIND20Card
|
|
key={event.id}
|
|
pubkey={event.pubkey}
|
|
text={event.content}
|
|
image={getImageUrl(event.tags)}
|
|
eventId={event.id}
|
|
tags={event.tags}
|
|
event={event}
|
|
showViewNoteCardButton={true}
|
|
/>
|
|
</div>
|
|
))
|
|
) : followingPubkeys.length === 0 && retryCount >= 3 ? (
|
|
// If no following and max retries reached
|
|
<div className="col-span-full flex flex-col items-center justify-center py-10 text-gray-500">
|
|
<p className="text-lg">No follows found. Follow some users to see their posts here.</p>
|
|
</div>
|
|
) : (
|
|
// If following exists but no posts found
|
|
<div className="col-span-full flex flex-col items-center justify-center py-10 text-gray-500">
|
|
<p className="text-lg">No posts found from people you follow.</p>
|
|
</div>
|
|
)}
|
|
</div>
|
|
{!isLoading && events.length > 0 && (
|
|
<div className="flex justify-center p-4">
|
|
<Button className="w-full md:w-auto" onClick={loadMore}>Load More</Button>
|
|
</div>
|
|
)}
|
|
</>
|
|
);
|
|
}
|
|
|
|
export default FollowerFeed; |