103 lines
2.8 KiB
TypeScript
103 lines
2.8 KiB
TypeScript
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<Article[]>([])
|
|
const [loading, setLoading] = useState(true)
|
|
const [error, setError] = useState<string | null>(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,
|
|
}
|
|
}
|