mirror of
https://github.com/lumina-rocks/lumina.git
synced 2026-06-06 18:51:16 +02:00
Feature: Load more (#28)
* load more button on global feed * load more button on follower feed * load more button on follower feed * load more button on profile feed * only show first 20 instead of 100 images in profile quick view feed * load more button on profile text feed
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
import { useRef } from "react";
|
||||
import { useRef, useState } from "react";
|
||||
import { useNostrEvents, dateToUnix } from "nostr-react";
|
||||
import NoteCard from './NoteCard';
|
||||
import KIND20Card from "./KIND20Card";
|
||||
import { getImageUrl } from "@/utils/utils";
|
||||
import { Button } from "@/components/ui/button";
|
||||
|
||||
interface FollowerFeedProps {
|
||||
pubkey: string;
|
||||
@@ -10,6 +10,7 @@ interface FollowerFeedProps {
|
||||
|
||||
const FollowerFeed: React.FC<FollowerFeedProps> = ({ pubkey }) => {
|
||||
const now = useRef(new Date());
|
||||
const [limit, setLimit] = useState(20);
|
||||
|
||||
const { events: following, isLoading: followingLoading } = useNostrEvents({
|
||||
filter: {
|
||||
@@ -21,31 +22,42 @@ const FollowerFeed: React.FC<FollowerFeedProps> = ({ pubkey }) => {
|
||||
|
||||
let followingPubkeys = following.flatMap((event) => event.tags.map(tag => tag[1])).slice(0, 500);
|
||||
|
||||
const { events } = useNostrEvents({
|
||||
const { events, isLoading } = useNostrEvents({
|
||||
filter: {
|
||||
limit: 20,
|
||||
limit: limit,
|
||||
kinds: [20],
|
||||
authors: followingPubkeys,
|
||||
},
|
||||
});
|
||||
|
||||
const loadMore = () => {
|
||||
setLimit(prevLimit => prevLimit + 20);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 px-2 md:px-4">
|
||||
{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 className="grid grid-cols-1 md:grid-cols-2 gap-4 px-2 md:px-4">
|
||||
{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>
|
||||
))}
|
||||
</div>
|
||||
{!isLoading && (
|
||||
<div className="flex justify-center p-4">
|
||||
<Button className="w-full md:w-auto" onClick={loadMore}>Load More</Button>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useRef } from "react";
|
||||
import { useRef, useState } from "react";
|
||||
import { useNostrEvents, dateToUnix } from "nostr-react";
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import QuickViewNoteCard from "./QuickViewNoteCard";
|
||||
import QuickViewKind20NoteCard from "./QuickViewKind20NoteCard";
|
||||
import { getImageUrl } from "@/utils/utils";
|
||||
@@ -11,6 +12,7 @@ interface FollowerQuickViewFeedProps {
|
||||
|
||||
const FollowerQuickViewFeed: React.FC<FollowerQuickViewFeedProps> = ({ pubkey }) => {
|
||||
const now = useRef(new Date()); // Make sure current time isn't re-rendered
|
||||
const [limit, setLimit] = useState(25);
|
||||
|
||||
const { events: following, isLoading: followingLoading } = useNostrEvents({
|
||||
filter: {
|
||||
@@ -19,51 +21,65 @@ const FollowerQuickViewFeed: React.FC<FollowerQuickViewFeedProps> = ({ pubkey })
|
||||
limit: 1,
|
||||
},
|
||||
});
|
||||
// let followingPubkeys = following.map((event) => event.tags[event.tags.length - 1][1]);
|
||||
// let followingPubkeys = following.flatMap((event) => event.tags.map(tag => tag[1])).slice(0, 50);
|
||||
|
||||
let followingPubkeys = following.flatMap((event) => event.tags.map(tag => tag[1])).slice(0, 500);
|
||||
|
||||
const { events } = useNostrEvents({
|
||||
const { events, isLoading } = useNostrEvents({
|
||||
filter: {
|
||||
// since: dateToUnix(now.current), // all new events from now
|
||||
// since: 0,
|
||||
limit: 25,
|
||||
limit: limit,
|
||||
kinds: [20],
|
||||
authors: followingPubkeys,
|
||||
},
|
||||
});
|
||||
|
||||
const loadMore = () => {
|
||||
setLimit(prevLimit => prevLimit + 25);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="grid grid-cols-3 gap-2">
|
||||
{events.length === 0 ? (
|
||||
{events.length === 0 && isLoading ? (
|
||||
<>
|
||||
<div>
|
||||
<Skeleton className="h-[125px] rounded-xl" />
|
||||
<div className="space-y-2 py-2">
|
||||
<Skeleton className="h-4 w-1/3" />
|
||||
<Skeleton className="h-4 w-1/3" />
|
||||
<div>
|
||||
<Skeleton className="h-[33vh] rounded-xl" />
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<Skeleton className="h-[125px] rounded-xl" />
|
||||
<div className="space-y-2 py-2">
|
||||
<Skeleton className="h-4 w-1/3" />
|
||||
<Skeleton className="h-4 w-1/3" />
|
||||
<div>
|
||||
<Skeleton className="h-[33vh] rounded-xl" />
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<Skeleton className="h-[125px] rounded-xl" />
|
||||
<div className="space-y-2 py-2">
|
||||
<Skeleton className="h-4 w-1/3" />
|
||||
<Skeleton className="h-4 w-1/3" />
|
||||
<div>
|
||||
<Skeleton className="h-[33vh] rounded-xl" />
|
||||
</div>
|
||||
<div>
|
||||
<Skeleton className="h-[33vh] rounded-xl" />
|
||||
</div>
|
||||
<div>
|
||||
<Skeleton className="h-[33vh] rounded-xl" />
|
||||
</div>
|
||||
<div>
|
||||
<Skeleton className="h-[33vh] rounded-xl" />
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
) : (events.map((event) => (
|
||||
<QuickViewKind20NoteCard key={event.id} pubkey={event.pubkey} text={event.content} image={getImageUrl(event.tags)} event={event} tags={event.tags} eventId={event.id} linkToNote={true} />
|
||||
)))}
|
||||
) : (
|
||||
events.map((event) => (
|
||||
<QuickViewKind20NoteCard
|
||||
key={event.id}
|
||||
pubkey={event.pubkey}
|
||||
text={event.content}
|
||||
image={getImageUrl(event.tags)}
|
||||
event={event}
|
||||
tags={event.tags}
|
||||
eventId={event.id}
|
||||
linkToNote={true}
|
||||
/>
|
||||
))
|
||||
)}
|
||||
</div>
|
||||
{!isLoading && (
|
||||
<div className="flex justify-center p-4">
|
||||
<Button className="w-full md:w-auto" onClick={loadMore}>Load More</Button>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,16 +1,24 @@
|
||||
import { useNostrEvents } from "nostr-react";
|
||||
import KIND20Card from "./KIND20Card";
|
||||
import { getImageUrl } from "@/utils/utils";
|
||||
import QuickViewKind20NoteCard from "./QuickViewKind20NoteCard";
|
||||
import { useState, useRef } from "react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
|
||||
const GlobalFeed: React.FC = () => {
|
||||
const { events } = useNostrEvents({
|
||||
const now = useRef(new Date());
|
||||
const [limit, setLimit] = useState(20);
|
||||
|
||||
const { events, isLoading } = useNostrEvents({
|
||||
filter: {
|
||||
limit: 20,
|
||||
limit: limit,
|
||||
kinds: [20],
|
||||
},
|
||||
});
|
||||
|
||||
const loadMore = () => {
|
||||
setLimit(prevLimit => prevLimit + 20);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<h2 className="text-2xl font-bold mb-4 px-2 md:px-4">Global Feed</h2>
|
||||
@@ -29,20 +37,15 @@ const GlobalFeed: React.FC = () => {
|
||||
event={event}
|
||||
showViewNoteCardButton={true}
|
||||
/>
|
||||
{/* <QuickViewKind20NoteCard
|
||||
key={event.id}
|
||||
pubkey={event.pubkey}
|
||||
text={event.content}
|
||||
image={imageUrl}
|
||||
eventId={event.id}
|
||||
tags={event.tags}
|
||||
event={event}
|
||||
linkToNote={true}
|
||||
/> */}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
{!isLoading && (
|
||||
<div className="flex justify-center p-4">
|
||||
<Button className="w-full md:w-auto" onClick={loadMore}>Load More</Button>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { useRef } from "react";
|
||||
import { useRef, useState } from "react";
|
||||
import { useNostrEvents, dateToUnix } from "nostr-react";
|
||||
import NoteCard from '@/components/NoteCard';
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import KIND20Card from "./KIND20Card";
|
||||
import { getImageUrl } from "@/utils/utils";
|
||||
|
||||
@@ -10,23 +11,24 @@ interface ProfileFeedProps {
|
||||
}
|
||||
|
||||
const ProfileFeed: React.FC<ProfileFeedProps> = ({ pubkey }) => {
|
||||
const now = useRef(new Date()); // Make sure current time isn't re-rendered
|
||||
const now = useRef(new Date());
|
||||
const [limit, setLimit] = useState(10);
|
||||
|
||||
const { events } = useNostrEvents({
|
||||
const { events, isLoading } = useNostrEvents({
|
||||
filter: {
|
||||
// since: dateToUnix(now.current), // all new events from now
|
||||
authors: [pubkey],
|
||||
// since: 0,
|
||||
// limit: 10,
|
||||
kinds: [20],
|
||||
limit: limit,
|
||||
},
|
||||
});
|
||||
|
||||
const loadMore = () => {
|
||||
setLimit(prevLimit => prevLimit + 10);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* <h2>Profile Feed</h2> */}
|
||||
|
||||
{events.length === 0 ? (
|
||||
{events.length === 0 && isLoading ? (
|
||||
<div className="flex flex-col space-y-3">
|
||||
<Skeleton className="h-[125px] rounded-xl" />
|
||||
<div className="space-y-2">
|
||||
@@ -34,13 +36,29 @@ const ProfileFeed: React.FC<ProfileFeedProps> = ({ pubkey }) => {
|
||||
<Skeleton className="h-4 w-[200px]" />
|
||||
</div>
|
||||
</div>
|
||||
) : (events.map((event) => (
|
||||
// <p key={event.id}>{event.pubkey} posted: {event.content}</p>
|
||||
// <ProfileNoteCard key={event.id} pubkey={event.pubkey} text={event.content} event={event} tags={event.tags} />
|
||||
<div key={event.id} className="py-6">
|
||||
<KIND20Card key={event.id} pubkey={event.pubkey} text={event.content} image={getImageUrl(event.tags)} event={event} tags={event.tags} eventId={event.id} showViewNoteCardButton={true}/>
|
||||
</div>
|
||||
)))}
|
||||
) : (
|
||||
<>
|
||||
{events.map((event) => (
|
||||
<div key={event.id} className="py-6">
|
||||
<KIND20Card
|
||||
key={event.id}
|
||||
pubkey={event.pubkey}
|
||||
text={event.content}
|
||||
image={getImageUrl(event.tags)}
|
||||
event={event}
|
||||
tags={event.tags}
|
||||
eventId={event.id}
|
||||
showViewNoteCardButton={true}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
{!isLoading && (
|
||||
<div className="flex justify-center p-4">
|
||||
<Button className="w-full md:w-auto" onClick={loadMore}>Load More</Button>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ interface ProfileQuickViewFeedProps {
|
||||
|
||||
const ProfileQuickViewFeed: React.FC<ProfileQuickViewFeedProps> = ({ pubkey }) => {
|
||||
const now = useRef(new Date()); // Make sure current time isn't re-rendered
|
||||
const [limit, setLimit] = useState(100);
|
||||
const [limit, setLimit] = useState(20);
|
||||
|
||||
const { isLoading, events } = useNostrEvents({
|
||||
filter: {
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
import { useRef } from "react";
|
||||
import { useRef, useState } from "react";
|
||||
import { useNostrEvents, dateToUnix } from "nostr-react";
|
||||
import NoteCard from '@/components/NoteCard';
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
import { Button } from "@/components/ui/button";
|
||||
|
||||
interface ProfileTextFeedProps {
|
||||
pubkey: string;
|
||||
}
|
||||
|
||||
const ProfileTextFeed: React.FC<ProfileTextFeedProps> = ({ pubkey }) => {
|
||||
const now = useRef(new Date()); // Make sure current time isn't re-rendered
|
||||
const now = useRef(new Date());
|
||||
const [limit, setLimit] = useState(10);
|
||||
|
||||
const { events, isLoading } = useNostrEvents({
|
||||
filter: {
|
||||
// since: dateToUnix(now.current), // all new events from now
|
||||
authors: [pubkey],
|
||||
// since: 0,
|
||||
// limit: 10,
|
||||
kinds: [1],
|
||||
limit: limit,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -25,10 +25,12 @@ const ProfileTextFeed: React.FC<ProfileTextFeedProps> = ({ pubkey }) => {
|
||||
// filter out all replies (tag[0] == e)
|
||||
filteredEvents = filteredEvents.filter((event) => !event.tags.some((tag) => { return tag[0] == 'e' }));
|
||||
|
||||
const loadMore = () => {
|
||||
setLimit(prevLimit => prevLimit + 10);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* <h2>Profile Feed</h2> */}
|
||||
|
||||
{filteredEvents.length === 0 && isLoading ? (
|
||||
<div className="flex flex-col space-y-3">
|
||||
<Skeleton className="h-[125px] rounded-xl" />
|
||||
@@ -37,13 +39,28 @@ const ProfileTextFeed: React.FC<ProfileTextFeedProps> = ({ pubkey }) => {
|
||||
<Skeleton className="h-4 w-[200px]" />
|
||||
</div>
|
||||
</div>
|
||||
) : (filteredEvents.map((event) => (
|
||||
// <p key={event.id}>{event.pubkey} posted: {event.content}</p>
|
||||
// <ProfileNoteCard key={event.id} pubkey={event.pubkey} text={event.content} event={event} tags={event.tags} />
|
||||
<div key={event.id} className="py-6">
|
||||
<NoteCard key={event.id} pubkey={event.pubkey} text={event.content} event={event} tags={event.tags} eventId={event.id} showViewNoteCardButton={true} />
|
||||
</div>
|
||||
)))}
|
||||
) : (
|
||||
<>
|
||||
{filteredEvents.map((event) => (
|
||||
<div key={event.id} className="py-6">
|
||||
<NoteCard
|
||||
key={event.id}
|
||||
pubkey={event.pubkey}
|
||||
text={event.content}
|
||||
event={event}
|
||||
tags={event.tags}
|
||||
eventId={event.id}
|
||||
showViewNoteCardButton={true}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
{!isLoading && filteredEvents.length > 0 && (
|
||||
<div className="flex justify-center p-4">
|
||||
<Button className="w-full md:w-auto" onClick={loadMore}>Load More</Button>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user