import React, { useState, useEffect } from 'react'; import { ProgressSpinner } from 'primereact/progressspinner'; import { useDiscordQuery } from '@/hooks/communityQueries/useDiscordQuery'; import { useQuery } from '@tanstack/react-query'; import axios from 'axios'; import { useRouter } from 'next/router'; import { useCommunityNotes } from '@/hooks/nostr/useCommunityNotes'; import { useNDKContext } from '@/context/NDKContext'; import { findKind0Fields } from '@/utils/nostr'; import NostrIcon from '../../../public/images/nostr.png'; import Image from 'next/image'; import { useImageProxy } from '@/hooks/useImageProxy'; import { nip19 } from 'nostr-tools'; import CommunityMessage from '@/components/feeds/messages/CommunityMessage'; import useWindowWidth from '@/hooks/useWindowWidth'; const StackerNewsIconComponent = () => ( ); const fetchStackerNews = async () => { const response = await axios.get('/api/stackernews'); return response.data.data.items.items; }; const GlobalFeed = ({searchQuery}) => { const router = useRouter(); const { data: discordData, error: discordError, isLoading: discordLoading } = useDiscordQuery({page: router.query.page}); const { data: stackerNewsData, error: stackerNewsError, isLoading: stackerNewsLoading } = useQuery({queryKey: ['stackerNews'], queryFn: fetchStackerNews}); const { communityNotes: nostrData, error: nostrError, isLoading: nostrLoading } = useCommunityNotes(); const { ndk } = useNDKContext(); const { returnImageProxy } = useImageProxy(); const windowWidth = useWindowWidth(); const [authorData, setAuthorData] = useState({}); useEffect(() => { const fetchAuthors = async () => { const authorDataMap = {}; for (const message of nostrData) { const author = await fetchAuthor(message.pubkey); authorDataMap[message.pubkey] = author; } setAuthorData(authorDataMap); }; if (nostrData && nostrData.length > 0) { fetchAuthors(); } }, [nostrData]); const fetchAuthor = async (pubkey) => { try { await ndk.connect(); const filter = { kinds: [0], authors: [pubkey] } const author = await ndk.fetchEvent(filter); if (author) { try { const fields = await findKind0Fields(JSON.parse(author.content)); return fields; } catch (error) { console.error('Error fetching author:', error); } } else { return null; } } catch (error) { console.error('Error fetching author:', error); } } if (discordLoading || stackerNewsLoading || nostrLoading) { return (
); } if (discordError || stackerNewsError || nostrError) { return
Failed to load feed. Please try again later.
; } const combinedFeed = [ ...(discordData || []).map(item => ({ ...item, type: 'discord' })), ...(stackerNewsData || []).map(item => ({ ...item, type: 'stackernews' })), ...(nostrData || []).map(item => ({ ...item, type: 'nostr' })) ].sort((a, b) => { const dateA = a.type === 'nostr' ? a.created_at * 1000 : new Date(a.timestamp || a.createdAt); const dateB = b.type === 'nostr' ? b.created_at * 1000 : new Date(b.timestamp || b.createdAt); return dateB - dateA; }).filter(item => { const searchLower = searchQuery.toLowerCase(); if (item.type === 'discord' || item.type === 'nostr') { return item.content.toLowerCase().includes(searchLower); } else if (item.type === 'stackernews') { return item.title.toLowerCase().includes(searchLower); } return false; }); return (
{combinedFeed.length > 0 ? ( combinedFeed.map(item => ( : item.type === 'nostr' ? Nostr : null} platformLink={item.type === 'discord' ? `https://discord.com/channels/${item.channelId}/${item.id}` : item.type === 'stackernews' ? `https://stacker.news/items/${item.id}` : `https://nostr.band/${nip19.noteEncode(item.id)}`} additionalContent={item.type === 'stackernews' ? `Comments: ${item.comments.length} | Sats: ${item.sats}` : null} /> )) ) : (
{searchQuery ? "No matching items found." : "No items available."}
)}
); }; export default GlobalFeed;