feat: relay reviews tab

This commit is contained in:
codytseng
2025-10-23 23:38:44 +08:00
parent d93b3e865b
commit 36c9796ea1
20 changed files with 74 additions and 22 deletions

View File

@@ -1,15 +1,34 @@
import { getReplaceableEventIdentifier } from '@/lib/event'
import { getStarsFromRelayReviewEvent } from '@/lib/event-metadata'
import { toRelay } from '@/lib/link'
import { simplifyUrl } from '@/lib/url'
import { useSecondaryPage } from '@/PageManager'
import { Event } from 'nostr-tools'
import { useMemo } from 'react'
import Content from '../Content'
import Stars from '../Stars'
export default function RelayReview({ event, className }: { event: Event; className?: string }) {
const { push } = useSecondaryPage()
const stars = useMemo(() => getStarsFromRelayReviewEvent(event), [event])
const url = useMemo(() => getReplaceableEventIdentifier(event), [event])
const simplifiedUrl = useMemo(() => simplifyUrl(url), [url])
return (
<div className={className}>
<Stars stars={stars} className="mt-2" />
<div className="mt-2 flex items-center gap-2">
<Stars stars={stars} />
<span className="text-sm text-muted-foreground"></span>
<div
className="text-sm text-muted-foreground hover:text-foreground hover:underline cursor-pointer truncate"
onClick={(e) => {
e.stopPropagation()
push(toRelay(url))
}}
>
{simplifiedUrl}
</div>
</div>
<Content event={event} className="mt-2" />
</div>
)

View File

@@ -68,9 +68,9 @@ export const ApplicationDataKey = {
export const BIG_RELAY_URLS = [
'wss://relay.damus.io/',
'wss://nos.lol/',
'wss://relay.nostr.band/',
'wss://nostr.mom/'
'wss://relay.primal.net/',
'wss://nos.lol/'
]
export const SEARCHABLE_RELAY_URLS = ['wss://relay.nostr.band/', 'wss://search.nos.today/']

View File

@@ -479,6 +479,7 @@ export default {
'Primary color': 'اللون الأساسي',
Layout: 'التخطيط',
'Two-column': 'عمودين',
'Single-column': 'عمود واحد'
'Single-column': 'عمود واحد',
Reviews: 'المراجعات'
}
}

View File

@@ -493,6 +493,7 @@ export default {
'Primary color': 'Primärfarbe',
Layout: 'Layout',
'Two-column': 'Zweispaltig',
'Single-column': 'Einspaltig'
'Single-column': 'Einspaltig',
Reviews: 'Bewertungen'
}
}

View File

@@ -478,6 +478,7 @@ export default {
'Primary color': 'Primary color',
Layout: 'Layout',
'Two-column': 'Two-column',
'Single-column': 'Single-column'
'Single-column': 'Single-column',
Reviews: 'Reviews'
}
}

View File

@@ -487,6 +487,7 @@ export default {
'Primary color': 'Color primario',
Layout: 'Diseño',
'Two-column': 'Doble columna',
'Single-column': 'Columna única'
'Single-column': 'Columna única',
Reviews: 'Reseñas'
}
}

View File

@@ -482,6 +482,7 @@ export default {
'Primary color': 'رنگ اصلی',
Layout: 'چیدمان',
'Two-column': 'دو ستونی',
'Single-column': 'تک ستونی'
'Single-column': 'تک ستونی',
Reviews: 'نقدها'
}
}

View File

@@ -492,6 +492,7 @@ export default {
'Primary color': 'Couleur principale',
Layout: 'Disposition',
'Two-column': 'Deux colonnes',
'Single-column': 'Une seule colonne'
'Single-column': 'Une seule colonne',
Reviews: 'Avis'
}
}

View File

@@ -484,6 +484,7 @@ export default {
'Primary color': 'प्राथमिक रंग',
Layout: 'लेआउट',
'Two-column': 'दोहरा स्तंभ',
'Single-column': 'एकल स्तंभ'
'Single-column': 'एकल स्तंभ',
Reviews: 'समीक्षाएं'
}
}

View File

@@ -487,6 +487,7 @@ export default {
'Primary color': 'Colore primario',
Layout: 'Layout',
'Two-column': 'Doppia colonna',
'Single-column': 'Colonna singola'
'Single-column': 'Colonna singola',
Reviews: 'Recensioni'
}
}

View File

@@ -483,6 +483,7 @@ export default {
'Primary color': '主要な色',
Layout: 'レイアウト',
'Two-column': '2列',
'Single-column': '1列'
'Single-column': '1列',
Reviews: 'レビュー'
}
}

View File

@@ -483,6 +483,7 @@ export default {
'Primary color': '기본 색상',
Layout: '레이아웃',
'Two-column': '두 열',
'Single-column': '한 열'
'Single-column': '한 열',
Reviews: '리뷰'
}
}

View File

@@ -487,6 +487,7 @@ export default {
'Primary color': 'Kolor podstawowy',
Layout: 'Układ',
'Two-column': 'Dwie kolumny',
'Single-column': 'Jedna kolumna'
'Single-column': 'Jedna kolumna',
Reviews: 'Opinie'
}
}

View File

@@ -484,6 +484,7 @@ export default {
'Primary color': 'Cor primária',
Layout: 'Layout',
'Two-column': 'Coluna dupla',
'Single-column': 'Coluna única'
'Single-column': 'Coluna única',
Reviews: 'Avaliações'
}
}

View File

@@ -487,6 +487,7 @@ export default {
'Primary color': 'Cor primária',
Layout: 'Layout',
'Two-column': 'Coluna dupla',
'Single-column': 'Coluna única'
'Single-column': 'Coluna única',
Reviews: 'Avaliações'
}
}

View File

@@ -489,6 +489,7 @@ export default {
'Primary color': 'Основной цвет',
Layout: 'Макет',
'Two-column': 'Две колонки',
'Single-column': 'Одна колонка'
'Single-column': 'Одна колонка',
Reviews: 'Отзывы'
}
}

View File

@@ -477,6 +477,7 @@ export default {
'Primary color': 'สีหลัก',
Layout: 'เค้าโครง',
'Two-column': 'สองคอลัมน์',
'Single-column': 'คอลัมน์เดียว'
'Single-column': 'คอลัมน์เดียว',
Reviews: 'รีวิว'
}
}

View File

@@ -475,6 +475,7 @@ export default {
'Primary color': '主色调',
Layout: '布局',
'Two-column': '双栏',
'Single-column': '单栏'
'Single-column': '单栏',
Reviews: '评价'
}
}

View File

@@ -34,7 +34,8 @@ export function generateBech32IdFromETag(tag: string[]) {
export function generateBech32IdFromATag(tag: string[]) {
try {
const [, coordinate, relay] = tag
const [kind, pubkey, identifier] = coordinate.split(':')
const [kind, pubkey, ...items] = coordinate.split(':')
const identifier = items.join(':')
return nip19.naddrEncode({
kind: Number(kind),
pubkey,

View File

@@ -1,15 +1,19 @@
import Explore from '@/components/Explore'
import FollowingFavoriteRelayList from '@/components/FollowingFavoriteRelayList'
import NoteList from '@/components/NoteList'
import Tabs from '@/components/Tabs'
import { Button } from '@/components/ui/button'
import { BIG_RELAY_URLS, ExtendedKind } from '@/constants'
import PrimaryPageLayout from '@/layouts/PrimaryPageLayout'
import { useUserTrust } from '@/providers/UserTrustProvider'
import { Compass, Plus } from 'lucide-react'
import { forwardRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
type TExploreTabs = 'following' | 'explore'
type TExploreTabs = 'following' | 'explore' | 'reviews'
const ExplorePage = forwardRef((_, ref) => {
const { hideUntrustedNotes } = useUserTrust()
const [tab, setTab] = useState<TExploreTabs>('explore')
return (
@@ -23,11 +27,23 @@ const ExplorePage = forwardRef((_, ref) => {
value={tab}
tabs={[
{ value: 'explore', label: 'Explore' },
{ value: 'reviews', label: 'Reviews' },
{ value: 'following', label: "Following's Favorites" }
]}
onTabChange={(tab) => setTab(tab as TExploreTabs)}
/>
{tab === 'following' ? <FollowingFavoriteRelayList /> : <Explore />}
{tab === 'explore' ? (
<Explore />
) : tab === 'reviews' ? (
<NoteList
showKinds={[ExtendedKind.RELAY_REVIEW]}
subRequests={[{ urls: BIG_RELAY_URLS, filter: {} }]}
filterMutedNotes
hideUntrustedNotes={hideUntrustedNotes}
/>
) : (
<FollowingFavoriteRelayList />
)}
</PrimaryPageLayout>
)
})