diff --git a/src/pages/feed/FeedTabPosts.tsx b/src/pages/feed/FeedTabPosts.tsx index 74008a8..26c5d80 100644 --- a/src/pages/feed/FeedTabPosts.tsx +++ b/src/pages/feed/FeedTabPosts.tsx @@ -7,12 +7,14 @@ import { NDKEvent, NDKFilter, NDKKind, + NDKSubscription, NDKSubscriptionCacheUsage } from '@nostr-dev-kit/ndk' import { NoteSubmit } from 'components/Notes/NoteSubmit' import { Note } from 'components/Notes/Note' import { FeedPostsFilter, RepostFilter } from 'types' import { DEFAULT_FILTER_OPTIONS } from 'utils' +import { Dots } from 'components/Spinner' export const FeedTabPosts = () => { const SHOWING_STEP = 20 @@ -22,6 +24,7 @@ export const FeedTabPosts = () => { const { ndk } = useNDKContext() const [notes, setNotes] = useState([]) + const [discoveredNotes, setDiscoveredNotes] = useState([]) const [isFetching, setIsFetching] = useState(false) const [isLoadMoreVisible, setIsLoadMoreVisible] = useState(true) const [showing, setShowing] = useState(SHOWING_STEP) @@ -38,6 +41,8 @@ export const FeedTabPosts = () => { setIsFetching(true) setIsLoadMoreVisible(true) + let sub: NDKSubscription + const filter: NDKFilter = { authors: [...followList, userPubkey], kinds: [NDKKind.Text, NDKKind.Repost], @@ -50,12 +55,45 @@ export const FeedTabPosts = () => { cacheUsage: NDKSubscriptionCacheUsage.PARALLEL }) .then((ndkEventSet) => { - const ndkEvents = Array.from(ndkEventSet) + const ndkEvents = Array.from(ndkEventSet).sort( + (a, b) => (b.created_at ?? 0) - (a.created_at ?? 0) + ) setNotes(ndkEvents) + const firstNote = ndkEvents[0] + const filter: NDKFilter = { + authors: [...followList, userPubkey], + kinds: [NDKKind.Text, NDKKind.Repost], + since: firstNote.created_at + } + sub = ndk.subscribe(filter, { + closeOnEose: false, + cacheUsage: NDKSubscriptionCacheUsage.PARALLEL + }) + sub.on('event', (ndkEvent) => { + setDiscoveredNotes((prev) => { + // Skip existing + if ( + prev.find( + (e) => + e.id === ndkEvent.id || + ndkEvents.findIndex((n) => n.id === ndkEvent.id) === -1 + ) + ) { + return [...prev] + } + + return [...prev, ndkEvent] + }) + }) + sub.start() }) .finally(() => { setIsFetching(false) }) + + return () => { + if (sub) sub.stop() + } }, [followList, ndk, userPubkey]) const filteredNotes = useMemo(() => { @@ -96,15 +134,14 @@ export const FeedTabPosts = () => { const handleLoadMore = () => { const LOAD_MORE_STEP = SHOWING_STEP * 2 setShowing((prev) => prev + SHOWING_STEP) - const lastNote = filteredNotes[filteredNotes.length - 1] + const lastNote = notes[notes.length - 1] const filter: NDKFilter = { authors: [...followList, userPubkey], kinds: [NDKKind.Text, NDKKind.Repost], - limit: LOAD_MORE_STEP + limit: LOAD_MORE_STEP, + until: lastNote.created_at } - filter.until = lastNote.created_at - setIsFetching(true) ndk .fetchEvents(filter, { @@ -133,9 +170,42 @@ export const FeedTabPosts = () => { }) } + const discoveredCount = discoveredNotes.length + const handleDiscoveredClick = () => { + // Combine newly discovred with the notes + // Skip events already in notes + setNotes((prev) => { + return Array.from(new Set([...discoveredNotes, ...prev])) + }) + // Increase showing by the discovered count + setShowing((prev) => prev + discoveredNotes.length) + setDiscoveredNotes([]) + } + return ( <> +
+ +
{isFetching && } {filteredNotes.length === 0 && !isFetching && (
diff --git a/src/pages/profile/index.tsx b/src/pages/profile/index.tsx index 50f9acf..b1ff7e7 100644 --- a/src/pages/profile/index.tsx +++ b/src/pages/profile/index.tsx @@ -942,7 +942,7 @@ const ProfileTabPosts = () => { const handleLoadMore = () => { const LOAD_MORE_STEP = SHOWING_STEP * 2 setShowing((prev) => prev + SHOWING_STEP) - const lastNote = filteredNotes[filteredNotes.length - 1] + const lastNote = notes[notes.length - 1] const filter: NDKFilter = { authors: [profilePubkey], kinds: [NDKKind.Text, NDKKind.Repost],