index.tsx raw
1 import Relay from '@/components/Relay'
2 import RelayIcon from '@/components/RelayIcon'
3 import PrimaryPageLayout from '@/layouts/PrimaryPageLayout'
4 import { normalizeUrl, simplifyUrl } from '@/lib/url'
5 import { usePrimaryPage } from '@/PageManager'
6 import { useFavoriteRelays } from '@/providers/FavoriteRelaysProvider'
7 import { useRelayAdmin } from '@/providers/RelayAdminProvider'
8 import { TPageRef } from '@/types'
9 import { Server, Shield } from 'lucide-react'
10 import { forwardRef, lazy, Suspense, useMemo } from 'react'
11
12 const RelayAdminPanel = lazy(() => import('./admin'))
13
14 const RelayPage = forwardRef<TPageRef>(({ url }: { url?: string }, ref) => {
15 const normalizedUrl = useMemo(() => (url ? normalizeUrl(url) : undefined), [url])
16 const { isEmbedded, isAdmin, isLoading } = useRelayAdmin()
17
18 const showAdmin = isEmbedded && isAdmin && !normalizedUrl
19
20 return (
21 <PrimaryPageLayout
22 pageName="relay"
23 titlebar={<RelayPageTitlebar url={normalizedUrl} showAdmin={showAdmin} />}
24 displayScrollToTopButton
25 ref={ref}
26 >
27 {normalizedUrl ? (
28 <Relay url={normalizedUrl} />
29 ) : showAdmin ? (
30 <Suspense
31 fallback={
32 <div className="flex items-center justify-center py-12 text-muted-foreground">
33 Loading admin...
34 </div>
35 }
36 >
37 <RelayAdminPanel />
38 </Suspense>
39 ) : isEmbedded && !isLoading ? (
40 <div className="flex items-center justify-center py-12 text-muted-foreground">
41 Log in as admin to access relay management.
42 </div>
43 ) : (
44 <RelayList />
45 )}
46 </PrimaryPageLayout>
47 )
48 })
49 RelayPage.displayName = 'RelayPage'
50 export default RelayPage
51
52 function RelayList() {
53 const { favoriteRelays } = useFavoriteRelays()
54 const { navigate } = usePrimaryPage()
55
56 if (favoriteRelays.length === 0) {
57 return (
58 <div className="flex items-center justify-center py-12 text-muted-foreground">
59 No relays configured.
60 </div>
61 )
62 }
63
64 return (
65 <div className="p-3 space-y-1">
66 {favoriteRelays.map((relay) => (
67 <button
68 key={relay}
69 className="w-full flex items-center gap-3 p-3 rounded-lg clickable hover:bg-muted/50 transition-colors text-left"
70 onClick={() => navigate('relay', { url: relay })}
71 >
72 <RelayIcon url={relay} />
73 <div className="flex-1 truncate font-medium">{simplifyUrl(relay)}</div>
74 </button>
75 ))}
76 </div>
77 )
78 }
79
80 function RelayPageTitlebar({ url, showAdmin }: { url?: string; showAdmin?: boolean }) {
81 return (
82 <div className="flex items-center gap-2 px-3 h-full">
83 {showAdmin ? <Shield /> : <Server />}
84 <div className="text-lg font-semibold truncate">
85 {showAdmin ? 'Relay Admin' : url ? simplifyUrl(url) : 'Relays'}
86 </div>
87 </div>
88 )
89 }
90