story-research-zapwall/hooks/useUserArticles.ts
2026-01-07 01:51:26 +01:00

116 lines
3.4 KiB
TypeScript

import { useEffect, useMemo, useRef, useState } from 'react'
import { nostrService } from '@/lib/nostr'
import type { Article } from '@/types/nostr'
import { applyFiltersAndSort } from '@/lib/articleFiltering'
import type { ArticleFilters } from '@/components/ArticleFilters'
import { objectCache } from '@/lib/objectCache'
/**
* Hook to fetch articles published by a specific user
*/
export function useUserArticles(
userPubkey: string,
searchQuery: string = '',
filters: ArticleFilters | null = null
): {
articles: Article[]
allArticles: Article[]
loading: boolean
error: string | null
loadArticleContent: (articleId: string, authorPubkey: string) => Promise<Article | null>
} {
const [articles, setArticles] = useState<Article[]>([])
const [loading, setLoading] = useState(true)
const [error, setError] = useState<string | null>(null)
const hasArticlesRef = useRef(false)
useEffect(() => {
if (!userPubkey) {
setLoading(false)
return
}
setLoading(true)
setError(null)
// Read only from IndexedDB cache - no network subscription
void (async (): Promise<void> => {
try {
const allPublications = await objectCache.getAll('publication')
const allAuthors = await objectCache.getAll('author')
const allArticles = [...allPublications, ...allAuthors] as Article[]
// Filter by user pubkey
const userArticles = allArticles.filter((article) => article.pubkey === userPubkey)
// Sort by creation date descending
const sortedArticles = userArticles.sort((a, b) => b.createdAt - a.createdAt)
setArticles(sortedArticles)
hasArticlesRef.current = sortedArticles.length > 0
if (sortedArticles.length === 0) {
setError('Aucun contenu trouvé')
}
} catch (error) {
console.error('Error loading user articles from cache:', error)
setError('Erreur lors du chargement des articles')
} finally {
setLoading(false)
}
})()
return () => {
// No cleanup needed - no network subscription
}
}, [userPubkey])
// Apply filters and sorting
const filteredArticles = useMemo(() => {
const effectiveFilters =
filters ??
({
authorPubkey: null,
sortBy: 'newest',
category: 'all',
} as const)
if (!filters && !searchQuery.trim()) {
return articles
}
return applyFiltersAndSort(articles, searchQuery, effectiveFilters)
}, [articles, searchQuery, filters])
const loadArticleContent = async (articleId: string, authorPubkey: string): Promise<Article | null> => {
try {
const article = await nostrService.getArticleById(articleId)
if (article) {
// Try to decrypt article content using decryption key from private messages
const decryptedContent = await nostrService.getDecryptedArticleContent(articleId, authorPubkey)
if (decryptedContent) {
setArticles((prev) =>
prev.map((a) =>
(a.id === articleId
? { ...a, content: decryptedContent, 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
}
return {
articles: filteredArticles,
allArticles: articles,
loading,
error,
loadArticleContent,
}
}