@ -5,11 +5,21 @@ import { useKindFilterOrDefaults } from '@/providers/KindFilterProvider'
import { useUserTrust } from '@/contexts/user-trust-context'
import { useUserTrust } from '@/contexts/user-trust-context'
import storage from '@/services/local-storage.service'
import storage from '@/services/local-storage.service'
import { PROFILE_MEDIA_TAB_KINDS } from '@/constants'
import { PROFILE_MEDIA_TAB_KINDS } from '@/constants'
import { isWispTrendingNotesRelayUrl } from '@/lib/wisp-trending-relay'
import type { TPrimaryPageName } from '@/PageManager'
import type { TPrimaryPageName } from '@/PageManager'
import { TFeedSubRequest , TNoteListMode } from '@/types'
import { TFeedSubRequest , TNoteListMode } from '@/types'
import { cn } from '@/lib/utils'
import { cn } from '@/lib/utils'
import type { Event } from 'nostr-tools'
import type { Event } from 'nostr-tools'
import { forwardRef , useCallback , useLayoutEffect , useMemo , useRef , useState , type ReactNode } from 'react'
import {
forwardRef ,
useCallback ,
useEffect ,
useLayoutEffect ,
useMemo ,
useRef ,
useState ,
type ReactNode
} from 'react'
import KindFilter from '../KindFilter'
import KindFilter from '../KindFilter'
const NormalFeed = forwardRef < TNoteListRef , {
const NormalFeed = forwardRef < TNoteListRef , {
@ -122,18 +132,33 @@ const NormalFeed = forwardRef<TNoteListRef, {
const MEDIA_KINDS = useMemo ( ( ) = > [ . . . PROFILE_MEDIA_TAB_KINDS ] , [ ] )
const MEDIA_KINDS = useMemo ( ( ) = > [ . . . PROFILE_MEDIA_TAB_KINDS ] , [ ] )
const tabs = useMemo (
/** Every shard URL is a nostrarchives Wisp “trending notes” stream — replies/gallery tabs are not applicable. */
( ) : TabDefinition [ ] = > {
const isWispTrendingOnlyFeed = useMemo (
const base : TabDefinition [ ] = [
( ) = >
{ value : 'posts' , label : 'Notes' } ,
subRequests . length > 0 &&
{ value : 'postsAndReplies' , label : 'Replies' }
subRequests . every (
]
( req ) = > req . urls . length > 0 && req . urls . every ( ( u ) = > isWispTrendingNotesRelayUrl ( u ) )
if ( isMainFeed ) base . push ( { value : 'media' , label : 'Gallery' } )
) ,
return base
[ subRequests ]
} ,
[ isMainFeed ]
)
)
useEffect ( ( ) = > {
if ( ! isWispTrendingOnlyFeed ) return
setListMode ( ( m ) = > ( m === 'posts' ? m : 'posts' ) )
} , [ isWispTrendingOnlyFeed ] )
const tabs = useMemo ( ( ) : TabDefinition [ ] = > {
if ( isMainFeed && isWispTrendingOnlyFeed ) {
return [ { value : 'posts' , label : 'Notes' } ]
}
const base : TabDefinition [ ] = [
{ value : 'posts' , label : 'Notes' } ,
{ value : 'postsAndReplies' , label : 'Replies' }
]
if ( isMainFeed ) base . push ( { value : 'media' , label : 'Gallery' } )
return base
} , [ isMainFeed , isWispTrendingOnlyFeed ] )
/** When in media mode, replace each shard's kinds with the media set. */
/** When in media mode, replace each shard's kinds with the media set. */
const effectiveSubRequests = useMemo ( ( ) = > {
const effectiveSubRequests = useMemo ( ( ) = > {
if ( listMode !== 'media' ) return subRequests
if ( listMode !== 'media' ) return subRequests
@ -183,29 +208,37 @@ const NormalFeed = forwardRef<TNoteListRef, {
/** Include kind picker deps for single-relay chips (kindless REQ + client-side kinds). */
/** Include kind picker deps for single-relay chips (kindless REQ + client-side kinds). */
const subHeaderFilterDepsKey = ` ${ allowKindlessRelayExplore ? 'kle' : 'std' } | ${ showKindsKey } | ${ feedKindFilterBypass } | ${ showAllKindsProp ? 'allProp' : 'k' } `
const subHeaderFilterDepsKey = ` ${ allowKindlessRelayExplore ? 'kle' : 'std' } | ${ showKindsKey } | ${ feedKindFilterBypass } | ${ showAllKindsProp ? 'allProp' : 'k' } `
const tabsElement = useMemo (
/** Notes / Replies / Gallery switch, plus refresh + kind filter — on Wisp trending only the tool row (no mode tabs). */
( ) = > (
const tabsElement = useMemo ( ( ) = > {
const kindRowOptions = (
< div className = "flex items-center gap-1" >
{ onSubHeaderRefresh != null && < RefreshButton onClick = { onSubHeaderRefresh } / > }
< KindFilter showKinds = { showKinds } onShowKindsChange = { handleShowKindsChange } / >
< / div >
)
if ( isMainFeed && isWispTrendingOnlyFeed ) {
return (
< div className = "flex w-full min-w-0 items-center justify-end gap-1 py-1" > { kindRowOptions } < / div >
)
}
return (
< Tabs
< Tabs
value = { listMode }
value = { listMode }
tabs = { tabs }
tabs = { tabs }
onTabChange = { handleListModeChange }
onTabChange = { handleListModeChange }
options = {
options = { kindRowOptions }
< div className = "flex items-center gap-1" >
{ onSubHeaderRefresh != null && < RefreshButton onClick = { onSubHeaderRefresh } / > }
< KindFilter showKinds = { showKinds } onShowKindsChange = { handleShowKindsChange } / >
< / div >
}
/ >
/ >
) ,
)
[
} , [
listMode ,
isMainFeed ,
tabs ,
isWispTrendingOnlyFeed ,
handleListModeChange ,
listMode ,
showKinds ,
tabs ,
onSubHeaderRefresh ,
handleListModeChange ,
handleShowKindsChange
showKinds ,
]
onSubHeaderRefresh ,
)
handleShowKindsChange
] )
const renderTabsInFeed = ! ( isMainFeed && setSubHeader ) && ! allowKindlessRelayExplore
const renderTabsInFeed = ! ( isMainFeed && setSubHeader ) && ! allowKindlessRelayExplore
@ -236,6 +269,7 @@ const NormalFeed = forwardRef<TNoteListRef, {
isMainFeed ,
isMainFeed ,
setSubHeader ,
setSubHeader ,
listMode ,
listMode ,
isWispTrendingOnlyFeed ,
subHeaderFilterDepsKey ,
subHeaderFilterDepsKey ,
onSubHeaderRefresh ,
onSubHeaderRefresh ,
allowKindlessRelayExplore ,
allowKindlessRelayExplore ,