Add FeedService and integrate into NostrFeed module
- Introduced FeedService to manage feed functionality, including subscription and deduplication of posts. - Updated NostrFeed module to register FeedService in the DI container and initialize it during installation. - Refactored useFeed composable to utilize FeedService for managing feed state and loading posts. - Enhanced NostrFeed component to display posts and handle loading states more effectively. - Changed Home.vue to use the 'all' feed type for broader content display. These changes improve the modularity and functionality of the feed system, providing a more robust user experience.
This commit is contained in:
parent
2e12315a35
commit
6217e3b70a
6 changed files with 408 additions and 270 deletions
|
|
@ -1,97 +1,55 @@
|
|||
import { ref, computed, onMounted, onUnmounted } from 'vue'
|
||||
import { computed, ref, onMounted, onUnmounted } from 'vue'
|
||||
import { injectService, SERVICE_TOKENS } from '@/core/di-container'
|
||||
import { eventBus } from '@/core/event-bus'
|
||||
import type { Event as NostrEvent, Filter } from 'nostr-tools'
|
||||
import type { FeedService, FeedConfig } from '../services/FeedService'
|
||||
|
||||
export interface FeedConfig {
|
||||
feedType: 'announcements' | 'general' | 'mentions'
|
||||
export interface UseFeedConfig {
|
||||
feedType: 'announcements' | 'general' | 'mentions' | 'events' | 'all'
|
||||
maxPosts?: number
|
||||
refreshInterval?: number
|
||||
adminPubkeys?: string[]
|
||||
}
|
||||
|
||||
export function useFeed(config: FeedConfig) {
|
||||
const relayHub = injectService<any>(SERVICE_TOKENS.RELAY_HUB)
|
||||
const posts = ref<NostrEvent[]>([])
|
||||
const isLoading = ref(false)
|
||||
const error = ref<string | null>(null)
|
||||
|
||||
export function useFeed(config: UseFeedConfig) {
|
||||
const feedService = injectService<FeedService>(SERVICE_TOKENS.FEED_SERVICE)
|
||||
|
||||
console.log('useFeed: FeedService injected:', !!feedService)
|
||||
if (!feedService) {
|
||||
console.error('useFeed: FeedService not available from DI container')
|
||||
}
|
||||
|
||||
let refreshTimer: number | null = null
|
||||
let unsubscribe: (() => void) | null = null
|
||||
|
||||
// Convert to FeedService config
|
||||
const feedConfig: FeedConfig = {
|
||||
feedType: config.feedType,
|
||||
maxPosts: config.maxPosts,
|
||||
adminPubkeys: config.adminPubkeys
|
||||
}
|
||||
|
||||
const filteredPosts = computed(() => {
|
||||
let filtered = posts.value
|
||||
|
||||
// Filter by feed type
|
||||
if (config.feedType === 'announcements' && config.adminPubkeys) {
|
||||
filtered = filtered.filter(post => config.adminPubkeys!.includes(post.pubkey))
|
||||
}
|
||||
|
||||
// Sort by created timestamp (newest first)
|
||||
filtered = filtered.sort((a, b) => b.created_at - a.created_at)
|
||||
|
||||
// Limit posts
|
||||
if (config.maxPosts) {
|
||||
filtered = filtered.slice(0, config.maxPosts)
|
||||
}
|
||||
|
||||
return filtered
|
||||
if (!feedService) return []
|
||||
return feedService.getFilteredPosts(feedConfig)
|
||||
})
|
||||
|
||||
const loadFeed = async () => {
|
||||
if (!relayHub) {
|
||||
error.value = 'RelayHub not available'
|
||||
console.log('useFeed: loadFeed called, feedService available:', !!feedService)
|
||||
if (!feedService) {
|
||||
console.error('FeedService not available')
|
||||
return
|
||||
}
|
||||
|
||||
isLoading.value = true
|
||||
error.value = null
|
||||
|
||||
console.log('useFeed: calling feedService.subscribeFeed with config:', feedConfig)
|
||||
try {
|
||||
// Create filter based on feed type
|
||||
const filter: Filter = {
|
||||
kinds: [1], // Text notes
|
||||
limit: config.maxPosts || 50
|
||||
}
|
||||
|
||||
if (config.feedType === 'announcements' && config.adminPubkeys) {
|
||||
filter.authors = config.adminPubkeys
|
||||
}
|
||||
|
||||
// Subscribe to events
|
||||
await relayHub.subscribe('feed-subscription', [filter], {
|
||||
onEvent: (event: NostrEvent) => {
|
||||
// Add new event if not already present
|
||||
if (!posts.value.some(p => p.id === event.id)) {
|
||||
posts.value = [event, ...posts.value]
|
||||
|
||||
// Emit event for other modules
|
||||
eventBus.emit('nostr-feed:new-post', { event, feedType: config.feedType }, 'nostr-feed')
|
||||
}
|
||||
},
|
||||
onEose: () => {
|
||||
console.log('Feed subscription end of stored events')
|
||||
isLoading.value = false
|
||||
},
|
||||
onClose: () => {
|
||||
console.log('Feed subscription closed')
|
||||
}
|
||||
})
|
||||
|
||||
unsubscribe = () => {
|
||||
relayHub.unsubscribe('feed-subscription')
|
||||
}
|
||||
|
||||
await feedService.subscribeFeed(feedConfig)
|
||||
console.log('useFeed: subscribeFeed completed')
|
||||
} catch (err) {
|
||||
console.error('Failed to load feed:', err)
|
||||
error.value = err instanceof Error ? err.message : 'Failed to load feed'
|
||||
isLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const refreshFeed = () => {
|
||||
posts.value = []
|
||||
loadFeed()
|
||||
const refreshFeed = async () => {
|
||||
if (!feedService) return
|
||||
await feedService.refreshFeed()
|
||||
}
|
||||
|
||||
const startAutoRefresh = () => {
|
||||
|
|
@ -109,21 +67,19 @@ export function useFeed(config: FeedConfig) {
|
|||
|
||||
// Lifecycle
|
||||
onMounted(() => {
|
||||
console.log('useFeed: onMounted called')
|
||||
loadFeed()
|
||||
startAutoRefresh()
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
stopAutoRefresh()
|
||||
if (unsubscribe) {
|
||||
unsubscribe()
|
||||
}
|
||||
})
|
||||
|
||||
return {
|
||||
posts: filteredPosts,
|
||||
isLoading,
|
||||
error,
|
||||
isLoading: feedService?.isLoading ?? ref(false),
|
||||
error: feedService?.error ?? ref(null),
|
||||
refreshFeed,
|
||||
loadFeed
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue