Add collapsible components and feed filter functionality
- Introduced Collapsible, CollapsibleContent, and CollapsibleTrigger components for improved UI interactions. - Added FeedFilters component to allow users to customize content visibility in the NostrFeed. - Updated NostrFeed and Home components to integrate new filtering capabilities, enhancing user experience with customizable content display. - Implemented content filter logic in FeedService to support dynamic filtering based on user selections. These changes enhance the modularity and interactivity of the feed system, providing users with greater control over the content they see.
This commit is contained in:
parent
a5e6c301e1
commit
e90c4992da
10 changed files with 574 additions and 24 deletions
|
|
@ -15,10 +15,20 @@ export interface FeedPost {
|
|||
replyTo?: string
|
||||
}
|
||||
|
||||
export interface ContentFilter {
|
||||
id: string
|
||||
label: string
|
||||
kinds: number[]
|
||||
description: string
|
||||
requiresAuth?: boolean
|
||||
filterByAuthor?: 'admin' | 'exclude-admin' | 'none'
|
||||
}
|
||||
|
||||
export interface FeedConfig {
|
||||
feedType: 'announcements' | 'general' | 'mentions' | 'events' | 'all'
|
||||
feedType: 'announcements' | 'general' | 'mentions' | 'events' | 'all' | 'custom'
|
||||
maxPosts?: number
|
||||
adminPubkeys?: string[]
|
||||
contentFilters?: ContentFilter[]
|
||||
}
|
||||
|
||||
export class FeedService extends BaseService {
|
||||
|
|
@ -109,29 +119,55 @@ export class FeedService extends BaseService {
|
|||
// Create subscription ID
|
||||
const subscriptionId = `feed-service-${config.feedType}-${Date.now()}`
|
||||
|
||||
// Create filter
|
||||
const filter: Filter = {
|
||||
kinds: [1], // Text notes
|
||||
limit: config.maxPosts || 50
|
||||
}
|
||||
// Create filters based on feed type and content filters
|
||||
const filters: Filter[] = []
|
||||
|
||||
if (config.feedType === 'announcements') {
|
||||
if (config.adminPubkeys && config.adminPubkeys.length > 0) {
|
||||
filter.authors = config.adminPubkeys
|
||||
} else {
|
||||
// No admin pubkeys configured for announcements - don't subscribe
|
||||
console.log('No admin pubkeys configured for announcements feed')
|
||||
this._isLoading.value = false
|
||||
return
|
||||
if (config.feedType === 'custom' && config.contentFilters) {
|
||||
// Use custom content filters
|
||||
for (const contentFilter of config.contentFilters) {
|
||||
const filter: Filter = {
|
||||
kinds: contentFilter.kinds,
|
||||
limit: Math.floor((config.maxPosts || 50) / config.contentFilters.length)
|
||||
}
|
||||
|
||||
// Apply author filtering if specified
|
||||
if (contentFilter.filterByAuthor === 'admin' && config.adminPubkeys?.length) {
|
||||
filter.authors = config.adminPubkeys
|
||||
} else if (contentFilter.filterByAuthor === 'exclude-admin' && config.adminPubkeys?.length) {
|
||||
// Note: Nostr doesn't support negative filters natively,
|
||||
// we'll filter these out in post-processing
|
||||
}
|
||||
|
||||
filters.push(filter)
|
||||
}
|
||||
} else {
|
||||
// Use legacy feed types
|
||||
const filter: Filter = {
|
||||
kinds: [1], // Text notes by default
|
||||
limit: config.maxPosts || 50
|
||||
}
|
||||
|
||||
// Handle legacy feed types
|
||||
if (config.feedType === 'announcements') {
|
||||
if (config.adminPubkeys && config.adminPubkeys.length > 0) {
|
||||
filter.authors = config.adminPubkeys
|
||||
} else {
|
||||
// No admin pubkeys configured for announcements - don't subscribe
|
||||
console.log('No admin pubkeys configured for announcements feed')
|
||||
this._isLoading.value = false
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
filters.push(filter)
|
||||
}
|
||||
|
||||
console.log(`Creating feed subscription for ${config.feedType} with filter:`, filter)
|
||||
console.log(`Creating feed subscription for ${config.feedType} with filters:`, filters)
|
||||
|
||||
// Subscribe to events with deduplication
|
||||
const unsubscribe = this.relayHub.subscribe({
|
||||
id: subscriptionId,
|
||||
filters: [filter],
|
||||
filters: filters,
|
||||
onEvent: (event: NostrEvent) => {
|
||||
this.handleNewEvent(event, config)
|
||||
},
|
||||
|
|
@ -223,6 +259,26 @@ export class FeedService extends BaseService {
|
|||
private shouldIncludeEvent(event: NostrEvent, config: FeedConfig): boolean {
|
||||
const isAdminPost = config.adminPubkeys?.includes(event.pubkey) || false
|
||||
|
||||
// For custom content filters, check if event matches any active filter
|
||||
if (config.feedType === 'custom' && config.contentFilters) {
|
||||
return config.contentFilters.some(filter => {
|
||||
// Check if event kind matches
|
||||
if (!filter.kinds.includes(event.kind)) {
|
||||
return false
|
||||
}
|
||||
|
||||
// Apply author filtering
|
||||
if (filter.filterByAuthor === 'admin') {
|
||||
return isAdminPost
|
||||
} else if (filter.filterByAuthor === 'exclude-admin') {
|
||||
return !isAdminPost
|
||||
}
|
||||
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
// Legacy feed type handling
|
||||
switch (config.feedType) {
|
||||
case 'announcements':
|
||||
return isAdminPost
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue