Enhance FeedService filtering logic

- Added a watch function in useFeed to log updates to filtered posts,
aiding in debugging.
- Updated content filters to include text notes in announcements and
marketplace presets, ensuring broader content visibility.
- Enhanced FeedService to log detailed information during custom
filtering, improving traceability of filtering logic.
- Modified Home.vue to always use custom filters for better consistency
in feed display.

These changes improve the reactivity, flexibility, and clarity of the
feed system, enhancing the overall user experience.
This commit is contained in:
padreug 2025-09-16 22:03:37 +02:00
parent 7025ea81c6
commit f05398fa9e
4 changed files with 55 additions and 19 deletions

View file

@ -1,4 +1,4 @@
import { computed, ref, onMounted, onUnmounted } from 'vue' import { computed, ref, onMounted, onUnmounted, watch } from 'vue'
import { injectService, SERVICE_TOKENS } from '@/core/di-container' import { injectService, SERVICE_TOKENS } from '@/core/di-container'
import type { FeedService, FeedConfig, ContentFilter } from '../services/FeedService' import type { FeedService, FeedConfig, ContentFilter } from '../services/FeedService'
@ -78,6 +78,11 @@ export function useFeed(config: UseFeedConfig) {
stopAutoRefresh() stopAutoRefresh()
}) })
// Debug posts reactivity
watch(filteredPosts, (newPosts) => {
console.log('useFeed: Posts updated, count:', newPosts.length)
}, { immediate: true })
return { return {
posts: filteredPosts, posts: filteredPosts,
isLoading: feedService?.isLoading ?? ref(false), isLoading: feedService?.isLoading ?? ref(false),

View file

@ -117,7 +117,8 @@ export const FILTER_PRESETS: Record<string, ContentFilter[]> = {
], ],
announcements: [ announcements: [
CONTENT_FILTERS.adminAnnouncements CONTENT_FILTERS.adminAnnouncements,
CONTENT_FILTERS.textNotes // Include all text posts as fallback
], ],
community: [ community: [
@ -129,7 +130,8 @@ export const FILTER_PRESETS: Record<string, ContentFilter[]> = {
marketplace: [ marketplace: [
CONTENT_FILTERS.marketStalls, CONTENT_FILTERS.marketStalls,
CONTENT_FILTERS.marketProducts, CONTENT_FILTERS.marketProducts,
CONTENT_FILTERS.marketGeneral CONTENT_FILTERS.marketGeneral,
CONTENT_FILTERS.textNotes // Include text posts that may contain marketplace content
], ],
social: [ social: [

View file

@ -9,6 +9,7 @@ export interface FeedPost {
pubkey: string pubkey: string
content: string content: string
created_at: number created_at: number
kind: number
tags: string[][] tags: string[][]
mentions: string[] mentions: string[]
isReply: boolean isReply: boolean
@ -124,6 +125,7 @@ export class FeedService extends BaseService {
if (config.feedType === 'custom' && config.contentFilters) { if (config.feedType === 'custom' && config.contentFilters) {
// Use custom content filters // Use custom content filters
// Using custom content filters
for (const contentFilter of config.contentFilters) { for (const contentFilter of config.contentFilters) {
const filter: Filter = { const filter: Filter = {
kinds: contentFilter.kinds, kinds: contentFilter.kinds,
@ -131,11 +133,18 @@ export class FeedService extends BaseService {
} }
// Apply author filtering if specified // Apply author filtering if specified
if (contentFilter.filterByAuthor === 'admin' && config.adminPubkeys?.length) { if (contentFilter.filterByAuthor === 'admin') {
filter.authors = config.adminPubkeys if (config.adminPubkeys?.length) {
filter.authors = config.adminPubkeys
// Using admin authors for filtering
} else {
// No admin pubkeys configured - include all authors for admin filters
// No admin pubkeys configured - include all authors
}
} else if (contentFilter.filterByAuthor === 'exclude-admin' && config.adminPubkeys?.length) { } else if (contentFilter.filterByAuthor === 'exclude-admin' && config.adminPubkeys?.length) {
// Note: Nostr doesn't support negative filters natively, // Note: Nostr doesn't support negative filters natively,
// we'll filter these out in post-processing // we'll filter these out in post-processing
// Will exclude admin in post-processing
} }
filters.push(filter) filters.push(filter)
@ -152,10 +161,9 @@ export class FeedService extends BaseService {
if (config.adminPubkeys && config.adminPubkeys.length > 0) { if (config.adminPubkeys && config.adminPubkeys.length > 0) {
filter.authors = config.adminPubkeys filter.authors = config.adminPubkeys
} else { } else {
// No admin pubkeys configured for announcements - don't subscribe // No admin pubkeys configured - fall back to all text posts
console.log('No admin pubkeys configured for announcements feed') console.log('No admin pubkeys configured for announcements feed, showing all posts')
this._isLoading.value = false // filter.authors remains undefined, so all authors are included
return
} }
} }
@ -225,6 +233,7 @@ export class FeedService extends BaseService {
pubkey: event.pubkey, pubkey: event.pubkey,
content: event.content, content: event.content,
created_at: event.created_at, created_at: event.created_at,
kind: event.kind,
tags: event.tags || [], tags: event.tags || [],
mentions: event.tags?.filter((tag: string[]) => tag[0] === 'p').map((tag: string[]) => tag[1]) || [], mentions: event.tags?.filter((tag: string[]) => tag[0] === 'p').map((tag: string[]) => tag[1]) || [],
isReply: event.tags?.some((tag: string[]) => tag[0] === 'e' && tag[3] === 'reply') || false, isReply: event.tags?.some((tag: string[]) => tag[0] === 'e' && tag[3] === 'reply') || false,
@ -261,21 +270,30 @@ export class FeedService extends BaseService {
// For custom content filters, check if event matches any active filter // For custom content filters, check if event matches any active filter
if (config.feedType === 'custom' && config.contentFilters) { if (config.feedType === 'custom' && config.contentFilters) {
return config.contentFilters.some(filter => { console.log('FeedService: Using custom filters, count:', config.contentFilters.length)
const result = config.contentFilters.some(filter => {
console.log('FeedService: Checking filter:', filter.id, 'kinds:', filter.kinds, 'filterByAuthor:', filter.filterByAuthor)
// Check if event kind matches // Check if event kind matches
if (!filter.kinds.includes(event.kind)) { if (!filter.kinds.includes(event.kind)) {
console.log('FeedService: Kind mismatch, event kind:', event.kind, 'filter kinds:', filter.kinds)
return false return false
} }
// Apply author filtering // Apply author filtering
if (filter.filterByAuthor === 'admin') { if (filter.filterByAuthor === 'admin') {
console.log('FeedService: Admin filter, isAdminPost:', isAdminPost)
return isAdminPost return isAdminPost
} else if (filter.filterByAuthor === 'exclude-admin') { } else if (filter.filterByAuthor === 'exclude-admin') {
console.log('FeedService: Exclude admin filter, isAdminPost:', isAdminPost)
return !isAdminPost return !isAdminPost
} }
console.log('FeedService: Filter passed all checks')
return true return true
}) })
console.log('FeedService: Custom filter result:', result)
return result
} }
// Legacy feed type handling // Legacy feed type handling
@ -326,16 +344,27 @@ export class FeedService extends BaseService {
* Get filtered posts for specific feed type * Get filtered posts for specific feed type
*/ */
getFilteredPosts(config: FeedConfig): FeedPost[] { getFilteredPosts(config: FeedConfig): FeedPost[] {
return this._posts.value console.log('FeedService: getFilteredPosts called, total posts:', this._posts.value.length, 'config:', config.feedType)
.filter(post => this.shouldIncludeEvent({ const filtered = this._posts.value
id: post.id, .filter(post => {
pubkey: post.pubkey, const shouldInclude = this.shouldIncludeEvent({
content: post.content, id: post.id,
created_at: post.created_at, pubkey: post.pubkey,
tags: post.tags content: post.content,
} as NostrEvent, config)) created_at: post.created_at,
kind: post.kind,
tags: post.tags
} as NostrEvent, config)
if (!shouldInclude) {
console.log('FeedService: Post filtered out in getFilteredPosts:', post.id)
}
return shouldInclude
})
.sort((a, b) => b.created_at - a.created_at) .sort((a, b) => b.created_at - a.created_at)
.slice(0, config.maxPosts || 100) .slice(0, config.maxPosts || 100)
console.log('FeedService: getFilteredPosts returning', filtered.length, 'posts')
return filtered
} }
/** /**

View file

@ -59,7 +59,7 @@ const feedType = computed(() => {
for (const [presetName, presetFilters] of Object.entries(FILTER_PRESETS)) { for (const [presetName, presetFilters] of Object.entries(FILTER_PRESETS)) {
if (presetFilters.length === selectedFilters.value.length && if (presetFilters.length === selectedFilters.value.length &&
presetFilters.every(pf => selectedFilters.value.some(sf => sf.id === pf.id))) { presetFilters.every(pf => selectedFilters.value.some(sf => sf.id === pf.id))) {
return presetName === 'all' ? 'all' : 'custom' return 'custom' // Always use custom for proper filtering
} }
} }