UserTrustProvider.tsx raw

   1  import client from '@/services/client.service'
   2  import fayan from '@/services/fayan.service'
   3  import { createContext, useCallback, useContext, useEffect } from 'react'
   4  import { useNostr } from './NostrProvider'
   5  
   6  type TUserTrustContext = {
   7    hideUntrustedInteractions: boolean
   8    hideUntrustedNotifications: boolean
   9    hideUntrustedNotes: boolean
  10    updateHideUntrustedInteractions: (hide: boolean) => void
  11    updateHideUntrustedNotifications: (hide: boolean) => void
  12    updateHideUntrustedNotes: (hide: boolean) => void
  13    isUserTrusted: (pubkey: string) => boolean
  14    isSpammer: (pubkey: string) => Promise<boolean>
  15  }
  16  
  17  const UserTrustContext = createContext<TUserTrustContext | undefined>(undefined)
  18  
  19  export const useUserTrust = () => {
  20    const context = useContext(UserTrustContext)
  21    if (!context) {
  22      throw new Error('useUserTrust must be used within a UserTrustProvider')
  23    }
  24    return context
  25  }
  26  
  27  const wotSet = new Set<string>()
  28  
  29  export function UserTrustProvider({ children }: { children: React.ReactNode }) {
  30    const { pubkey: currentPubkey } = useNostr()
  31    // All three hideUntrusted flags are permanently disabled.
  32    // Mute lists handle unwanted content. These flags break relay feeds
  33    // by turning them into de-facto follow feeds.
  34    const hideUntrustedInteractions = false
  35    const hideUntrustedNotes = false
  36    const hideUntrustedNotifications = false
  37  
  38    useEffect(() => {
  39      if (!currentPubkey) return
  40  
  41      const initWoT = async () => {
  42        const followings = await client.fetchFollowings(currentPubkey, false)
  43        followings.forEach((pubkey) => wotSet.add(pubkey))
  44  
  45        const batchSize = 20
  46        for (let i = 0; i < followings.length; i += batchSize) {
  47          const batch = followings.slice(i, i + batchSize)
  48          await Promise.allSettled(
  49            batch.map(async (pubkey) => {
  50              const _followings = await client.fetchFollowings(pubkey, false)
  51              _followings.forEach((following) => {
  52                wotSet.add(following)
  53              })
  54            })
  55          )
  56          await new Promise((resolve) => setTimeout(resolve, 200))
  57        }
  58      }
  59      initWoT()
  60    }, [currentPubkey])
  61  
  62    const isUserTrusted = useCallback(
  63      (pubkey: string) => {
  64        if (!currentPubkey || pubkey === currentPubkey) return true
  65        return wotSet.has(pubkey)
  66      },
  67      [currentPubkey]
  68    )
  69  
  70    const isSpammer = useCallback(
  71      async (pubkey: string) => {
  72        if (isUserTrusted(pubkey)) return false
  73        const percentile = await fayan.fetchUserPercentile(pubkey)
  74        if (percentile === null) return false
  75        return percentile < 60
  76      },
  77      [isUserTrusted]
  78    )
  79  
  80    // no-op updaters preserved for interface compatibility
  81    const updateHideUntrustedInteractions = (_hide: boolean) => {}
  82    const updateHideUntrustedNotifications = (_hide: boolean) => {}
  83    const updateHideUntrustedNotes = (_hide: boolean) => {}
  84  
  85    return (
  86      <UserTrustContext.Provider
  87        value={{
  88          hideUntrustedInteractions,
  89          hideUntrustedNotifications,
  90          hideUntrustedNotes,
  91          updateHideUntrustedInteractions,
  92          updateHideUntrustedNotifications,
  93          updateHideUntrustedNotes,
  94          isUserTrusted,
  95          isSpammer
  96        }}
  97      >
  98        {children}
  99      </UserTrustContext.Provider>
 100    )
 101  }
 102