UserTrustProvider.tsx raw
1 import client from '@/services/client.service'
2 import fayan from '@/services/fayan.service'
3 import storage, { dispatchSettingsChanged } from '@/services/local-storage.service'
4 import { createContext, useCallback, useContext, useEffect, useState } from 'react'
5 import { useNostr } from './NostrProvider'
6
7 type TUserTrustContext = {
8 hideUntrustedInteractions: boolean
9 hideUntrustedNotifications: boolean
10 hideUntrustedNotes: boolean
11 updateHideUntrustedInteractions: (hide: boolean) => void
12 updateHideUntrustedNotifications: (hide: boolean) => void
13 updateHideUntrustedNotes: (hide: boolean) => void
14 isUserTrusted: (pubkey: string) => boolean
15 isSpammer: (pubkey: string) => Promise<boolean>
16 }
17
18 const UserTrustContext = createContext<TUserTrustContext | undefined>(undefined)
19
20 export const useUserTrust = () => {
21 const context = useContext(UserTrustContext)
22 if (!context) {
23 throw new Error('useUserTrust must be used within a UserTrustProvider')
24 }
25 return context
26 }
27
28 const wotSet = new Set<string>()
29
30 export function UserTrustProvider({ children }: { children: React.ReactNode }) {
31 const { pubkey: currentPubkey } = useNostr()
32 const [hideUntrustedInteractions, setHideUntrustedInteractions] = useState(() =>
33 storage.getHideUntrustedInteractions()
34 )
35 const [hideUntrustedNotifications, setHideUntrustedNotifications] = useState(() =>
36 storage.getHideUntrustedNotifications()
37 )
38 const [hideUntrustedNotes, setHideUntrustedNotes] = useState(() =>
39 storage.getHideUntrustedNotes()
40 )
41
42 useEffect(() => {
43 if (!currentPubkey) return
44
45 const initWoT = async () => {
46 const followings = await client.fetchFollowings(currentPubkey, false)
47 followings.forEach((pubkey) => wotSet.add(pubkey))
48
49 const batchSize = 20
50 for (let i = 0; i < followings.length; i += batchSize) {
51 const batch = followings.slice(i, i + batchSize)
52 await Promise.allSettled(
53 batch.map(async (pubkey) => {
54 const _followings = await client.fetchFollowings(pubkey, false)
55 _followings.forEach((following) => {
56 wotSet.add(following)
57 })
58 })
59 )
60 await new Promise((resolve) => setTimeout(resolve, 200))
61 }
62 }
63 initWoT()
64 }, [currentPubkey])
65
66 const isUserTrusted = useCallback(
67 (pubkey: string) => {
68 if (!currentPubkey || pubkey === currentPubkey) return true
69 return wotSet.has(pubkey)
70 },
71 [currentPubkey]
72 )
73
74 const isSpammer = useCallback(
75 async (pubkey: string) => {
76 if (isUserTrusted(pubkey)) return false
77 const percentile = await fayan.fetchUserPercentile(pubkey)
78 if (percentile === null) return false
79 return percentile < 60
80 },
81 [isUserTrusted]
82 )
83
84 const updateHideUntrustedInteractions = (hide: boolean) => {
85 setHideUntrustedInteractions(hide)
86 storage.setHideUntrustedInteractions(hide)
87 dispatchSettingsChanged()
88 }
89
90 const updateHideUntrustedNotifications = (hide: boolean) => {
91 setHideUntrustedNotifications(hide)
92 storage.setHideUntrustedNotifications(hide)
93 dispatchSettingsChanged()
94 }
95
96 const updateHideUntrustedNotes = (hide: boolean) => {
97 setHideUntrustedNotes(hide)
98 storage.setHideUntrustedNotes(hide)
99 dispatchSettingsChanged()
100 }
101
102 return (
103 <UserTrustContext.Provider
104 value={{
105 hideUntrustedInteractions,
106 hideUntrustedNotifications,
107 hideUntrustedNotes,
108 updateHideUntrustedInteractions,
109 updateHideUntrustedNotifications,
110 updateHideUntrustedNotes,
111 isUserTrusted,
112 isSpammer
113 }}
114 >
115 {children}
116 </UserTrustContext.Provider>
117 )
118 }
119