FollowingFeed.tsx raw
1 import NormalFeed from '@/components/NormalFeed'
2 import { Button } from '@/components/ui/button'
3 import { usePrimaryPage } from '@/PageManager'
4 import { useFeed } from '@/providers/FeedProvider'
5 import { useFollowList } from '@/providers/FollowListProvider'
6 import { useNostr } from '@/providers/NostrProvider'
7 import client from '@/services/client.service'
8 import { TFeedSubRequest } from '@/types'
9 import { Compass, Search, UserPlus } from 'lucide-react'
10 import { useEffect, useRef, useState } from 'react'
11 import { useTranslation } from 'react-i18next'
12
13 export default function FollowingFeed() {
14 const { t } = useTranslation()
15 const { pubkey } = useNostr()
16 const { followingSet } = useFollowList()
17 const { navigate } = usePrimaryPage()
18 const { markFeedLoaded } = useFeed()
19 const [subRequests, setSubRequests] = useState<TFeedSubRequest[]>([])
20 const [hasFollowings, setHasFollowings] = useState<boolean | null>(null)
21 const [refreshCount, setRefreshCount] = useState(0)
22 const initializedRef = useRef(false)
23
24 useEffect(() => {
25 if (initializedRef.current) return
26
27 async function init() {
28 if (!pubkey) {
29 setSubRequests([])
30 setHasFollowings(null)
31 return
32 }
33
34 const followings = await client.fetchFollowings(pubkey)
35 setHasFollowings(followings.length > 0)
36 setSubRequests(await client.generateSubRequestsForPubkeys([pubkey, ...followings], pubkey))
37
38 if (followings.length) {
39 initializedRef.current = true
40 }
41 }
42
43 init()
44 }, [pubkey, followingSet, refreshCount])
45
46 // Show empty state when user has no followings
47 useEffect(() => {
48 if (hasFollowings === false) markFeedLoaded()
49 }, [hasFollowings, markFeedLoaded])
50
51 if (hasFollowings === false && subRequests.length > 0) {
52 return (
53 <div className="flex flex-col items-center justify-center min-h-[60vh] px-6 text-center">
54 <UserPlus size={64} className="text-muted-foreground mb-4" strokeWidth={1.5} />
55 <h2 className="text-2xl font-semibold mb-2">{t('Welcome to Smesh!')}</h2>
56 <p className="text-muted-foreground mb-6 max-w-md">
57 {t(
58 'Your feed is empty because you are not following anyone yet. Start by exploring interesting content and following users you like!'
59 )}
60 </p>
61 <div className="flex flex-col sm:flex-row gap-3 w-full max-w-md">
62 <Button size="lg" onClick={() => navigate('explore')} className="w-full">
63 <Compass className="size-5" />
64 {t('Explore')}
65 </Button>
66 <Button size="lg" variant="outline" onClick={() => navigate('search')} className="w-full">
67 <Search className="size-5" />
68 {t('Search Users')}
69 </Button>
70 </div>
71 </div>
72 )
73 }
74
75 return (
76 <NormalFeed
77 subRequests={subRequests}
78 onRefresh={() => {
79 initializedRef.current = false
80 setRefreshCount((count) => count + 1)
81 }}
82 onInitialLoad={markFeedLoaded}
83 isMainFeed
84 />
85 )
86 }
87