import { useState, useEffect, useMemo } from 'react' import { nostrService } from '@/lib/nostr' import type { Article } from '@/types/nostr' import { applyFiltersAndSort } from '@/lib/articleFiltering' import type { ArticleFilters } from '@/components/ArticleFilters' export function useArticles(searchQuery: string = '', filters: ArticleFilters | null = null) { const [articles, setArticles] = useState([]) const [loading, setLoading] = useState(true) const [error, setError] = useState(null) useEffect(() => { setLoading(true) setError(null) let unsubscribe: (() => void) | null = null nostrService.subscribeToArticles( (article) => { setArticles((prev) => { // Avoid duplicates if (prev.some((a) => a.id === article.id)) { return prev } return [article, ...prev].sort((a, b) => b.createdAt - a.createdAt) }) setLoading(false) }, 50 ).then((unsub) => { unsubscribe = unsub }).catch((e) => { console.error('Error subscribing to articles:', e) setError('Failed to load articles') setLoading(false) }) // Timeout after 10 seconds const timeout = setTimeout(() => { setLoading(false) if (articles.length === 0) { setError('No articles found') } }, 10000) return () => { if (unsubscribe) { unsubscribe() } clearTimeout(timeout) } }, []) const loadArticleContent = async (articleId: string, authorPubkey: string) => { try { const article = await nostrService.getArticleById(articleId) if (article) { // Try to load private content const privateContent = await nostrService.getPrivateContent(articleId, authorPubkey) if (privateContent) { setArticles((prev) => prev.map((a) => a.id === articleId ? { ...a, content: privateContent, paid: true } : a ) ) } return article } } catch (e) { console.error('Error loading article content:', e) setError(e instanceof Error ? e.message : 'Failed to load article') } return null } // Apply filters and sorting const filteredArticles = useMemo(() => { if (!filters) { // If no filters, just apply search if (!searchQuery.trim()) { return articles } return applyFiltersAndSort(articles, searchQuery, { authorPubkey: null, minPrice: null, maxPrice: null, sortBy: 'newest', }) } return applyFiltersAndSort(articles, searchQuery, filters) }, [articles, searchQuery, filters]) return { articles: filteredArticles, allArticles: articles, // Return all articles for filters component loading, error, loadArticleContent, } }