feat: relay reviews tab
This commit is contained in:
@@ -1,15 +1,34 @@
|
|||||||
|
import { getReplaceableEventIdentifier } from '@/lib/event'
|
||||||
import { getStarsFromRelayReviewEvent } from '@/lib/event-metadata'
|
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 { Event } from 'nostr-tools'
|
||||||
import { useMemo } from 'react'
|
import { useMemo } from 'react'
|
||||||
import Content from '../Content'
|
import Content from '../Content'
|
||||||
import Stars from '../Stars'
|
import Stars from '../Stars'
|
||||||
|
|
||||||
export default function RelayReview({ event, className }: { event: Event; className?: string }) {
|
export default function RelayReview({ event, className }: { event: Event; className?: string }) {
|
||||||
|
const { push } = useSecondaryPage()
|
||||||
const stars = useMemo(() => getStarsFromRelayReviewEvent(event), [event])
|
const stars = useMemo(() => getStarsFromRelayReviewEvent(event), [event])
|
||||||
|
const url = useMemo(() => getReplaceableEventIdentifier(event), [event])
|
||||||
|
const simplifiedUrl = useMemo(() => simplifyUrl(url), [url])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={className}>
|
<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" />
|
<Content event={event} className="mt-2" />
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -68,9 +68,9 @@ export const ApplicationDataKey = {
|
|||||||
|
|
||||||
export const BIG_RELAY_URLS = [
|
export const BIG_RELAY_URLS = [
|
||||||
'wss://relay.damus.io/',
|
'wss://relay.damus.io/',
|
||||||
'wss://nos.lol/',
|
|
||||||
'wss://relay.nostr.band/',
|
'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/']
|
export const SEARCHABLE_RELAY_URLS = ['wss://relay.nostr.band/', 'wss://search.nos.today/']
|
||||||
|
|||||||
@@ -479,6 +479,7 @@ export default {
|
|||||||
'Primary color': 'اللون الأساسي',
|
'Primary color': 'اللون الأساسي',
|
||||||
Layout: 'التخطيط',
|
Layout: 'التخطيط',
|
||||||
'Two-column': 'عمودين',
|
'Two-column': 'عمودين',
|
||||||
'Single-column': 'عمود واحد'
|
'Single-column': 'عمود واحد',
|
||||||
|
Reviews: 'المراجعات'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -493,6 +493,7 @@ export default {
|
|||||||
'Primary color': 'Primärfarbe',
|
'Primary color': 'Primärfarbe',
|
||||||
Layout: 'Layout',
|
Layout: 'Layout',
|
||||||
'Two-column': 'Zweispaltig',
|
'Two-column': 'Zweispaltig',
|
||||||
'Single-column': 'Einspaltig'
|
'Single-column': 'Einspaltig',
|
||||||
|
Reviews: 'Bewertungen'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -478,6 +478,7 @@ export default {
|
|||||||
'Primary color': 'Primary color',
|
'Primary color': 'Primary color',
|
||||||
Layout: 'Layout',
|
Layout: 'Layout',
|
||||||
'Two-column': 'Two-column',
|
'Two-column': 'Two-column',
|
||||||
'Single-column': 'Single-column'
|
'Single-column': 'Single-column',
|
||||||
|
Reviews: 'Reviews'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -487,6 +487,7 @@ export default {
|
|||||||
'Primary color': 'Color primario',
|
'Primary color': 'Color primario',
|
||||||
Layout: 'Diseño',
|
Layout: 'Diseño',
|
||||||
'Two-column': 'Doble columna',
|
'Two-column': 'Doble columna',
|
||||||
'Single-column': 'Columna única'
|
'Single-column': 'Columna única',
|
||||||
|
Reviews: 'Reseñas'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -482,6 +482,7 @@ export default {
|
|||||||
'Primary color': 'رنگ اصلی',
|
'Primary color': 'رنگ اصلی',
|
||||||
Layout: 'چیدمان',
|
Layout: 'چیدمان',
|
||||||
'Two-column': 'دو ستونی',
|
'Two-column': 'دو ستونی',
|
||||||
'Single-column': 'تک ستونی'
|
'Single-column': 'تک ستونی',
|
||||||
|
Reviews: 'نقدها'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -492,6 +492,7 @@ export default {
|
|||||||
'Primary color': 'Couleur principale',
|
'Primary color': 'Couleur principale',
|
||||||
Layout: 'Disposition',
|
Layout: 'Disposition',
|
||||||
'Two-column': 'Deux colonnes',
|
'Two-column': 'Deux colonnes',
|
||||||
'Single-column': 'Une seule colonne'
|
'Single-column': 'Une seule colonne',
|
||||||
|
Reviews: 'Avis'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -484,6 +484,7 @@ export default {
|
|||||||
'Primary color': 'प्राथमिक रंग',
|
'Primary color': 'प्राथमिक रंग',
|
||||||
Layout: 'लेआउट',
|
Layout: 'लेआउट',
|
||||||
'Two-column': 'दोहरा स्तंभ',
|
'Two-column': 'दोहरा स्तंभ',
|
||||||
'Single-column': 'एकल स्तंभ'
|
'Single-column': 'एकल स्तंभ',
|
||||||
|
Reviews: 'समीक्षाएं'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -487,6 +487,7 @@ export default {
|
|||||||
'Primary color': 'Colore primario',
|
'Primary color': 'Colore primario',
|
||||||
Layout: 'Layout',
|
Layout: 'Layout',
|
||||||
'Two-column': 'Doppia colonna',
|
'Two-column': 'Doppia colonna',
|
||||||
'Single-column': 'Colonna singola'
|
'Single-column': 'Colonna singola',
|
||||||
|
Reviews: 'Recensioni'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -483,6 +483,7 @@ export default {
|
|||||||
'Primary color': '主要な色',
|
'Primary color': '主要な色',
|
||||||
Layout: 'レイアウト',
|
Layout: 'レイアウト',
|
||||||
'Two-column': '2列',
|
'Two-column': '2列',
|
||||||
'Single-column': '1列'
|
'Single-column': '1列',
|
||||||
|
Reviews: 'レビュー'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -483,6 +483,7 @@ export default {
|
|||||||
'Primary color': '기본 색상',
|
'Primary color': '기본 색상',
|
||||||
Layout: '레이아웃',
|
Layout: '레이아웃',
|
||||||
'Two-column': '두 열',
|
'Two-column': '두 열',
|
||||||
'Single-column': '한 열'
|
'Single-column': '한 열',
|
||||||
|
Reviews: '리뷰'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -487,6 +487,7 @@ export default {
|
|||||||
'Primary color': 'Kolor podstawowy',
|
'Primary color': 'Kolor podstawowy',
|
||||||
Layout: 'Układ',
|
Layout: 'Układ',
|
||||||
'Two-column': 'Dwie kolumny',
|
'Two-column': 'Dwie kolumny',
|
||||||
'Single-column': 'Jedna kolumna'
|
'Single-column': 'Jedna kolumna',
|
||||||
|
Reviews: 'Opinie'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -484,6 +484,7 @@ export default {
|
|||||||
'Primary color': 'Cor primária',
|
'Primary color': 'Cor primária',
|
||||||
Layout: 'Layout',
|
Layout: 'Layout',
|
||||||
'Two-column': 'Coluna dupla',
|
'Two-column': 'Coluna dupla',
|
||||||
'Single-column': 'Coluna única'
|
'Single-column': 'Coluna única',
|
||||||
|
Reviews: 'Avaliações'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -487,6 +487,7 @@ export default {
|
|||||||
'Primary color': 'Cor primária',
|
'Primary color': 'Cor primária',
|
||||||
Layout: 'Layout',
|
Layout: 'Layout',
|
||||||
'Two-column': 'Coluna dupla',
|
'Two-column': 'Coluna dupla',
|
||||||
'Single-column': 'Coluna única'
|
'Single-column': 'Coluna única',
|
||||||
|
Reviews: 'Avaliações'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -489,6 +489,7 @@ export default {
|
|||||||
'Primary color': 'Основной цвет',
|
'Primary color': 'Основной цвет',
|
||||||
Layout: 'Макет',
|
Layout: 'Макет',
|
||||||
'Two-column': 'Две колонки',
|
'Two-column': 'Две колонки',
|
||||||
'Single-column': 'Одна колонка'
|
'Single-column': 'Одна колонка',
|
||||||
|
Reviews: 'Отзывы'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -477,6 +477,7 @@ export default {
|
|||||||
'Primary color': 'สีหลัก',
|
'Primary color': 'สีหลัก',
|
||||||
Layout: 'เค้าโครง',
|
Layout: 'เค้าโครง',
|
||||||
'Two-column': 'สองคอลัมน์',
|
'Two-column': 'สองคอลัมน์',
|
||||||
'Single-column': 'คอลัมน์เดียว'
|
'Single-column': 'คอลัมน์เดียว',
|
||||||
|
Reviews: 'รีวิว'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -475,6 +475,7 @@ export default {
|
|||||||
'Primary color': '主色调',
|
'Primary color': '主色调',
|
||||||
Layout: '布局',
|
Layout: '布局',
|
||||||
'Two-column': '双栏',
|
'Two-column': '双栏',
|
||||||
'Single-column': '单栏'
|
'Single-column': '单栏',
|
||||||
|
Reviews: '评价'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,8 @@ export function generateBech32IdFromETag(tag: string[]) {
|
|||||||
export function generateBech32IdFromATag(tag: string[]) {
|
export function generateBech32IdFromATag(tag: string[]) {
|
||||||
try {
|
try {
|
||||||
const [, coordinate, relay] = tag
|
const [, coordinate, relay] = tag
|
||||||
const [kind, pubkey, identifier] = coordinate.split(':')
|
const [kind, pubkey, ...items] = coordinate.split(':')
|
||||||
|
const identifier = items.join(':')
|
||||||
return nip19.naddrEncode({
|
return nip19.naddrEncode({
|
||||||
kind: Number(kind),
|
kind: Number(kind),
|
||||||
pubkey,
|
pubkey,
|
||||||
|
|||||||
@@ -1,15 +1,19 @@
|
|||||||
import Explore from '@/components/Explore'
|
import Explore from '@/components/Explore'
|
||||||
import FollowingFavoriteRelayList from '@/components/FollowingFavoriteRelayList'
|
import FollowingFavoriteRelayList from '@/components/FollowingFavoriteRelayList'
|
||||||
|
import NoteList from '@/components/NoteList'
|
||||||
import Tabs from '@/components/Tabs'
|
import Tabs from '@/components/Tabs'
|
||||||
import { Button } from '@/components/ui/button'
|
import { Button } from '@/components/ui/button'
|
||||||
|
import { BIG_RELAY_URLS, ExtendedKind } from '@/constants'
|
||||||
import PrimaryPageLayout from '@/layouts/PrimaryPageLayout'
|
import PrimaryPageLayout from '@/layouts/PrimaryPageLayout'
|
||||||
|
import { useUserTrust } from '@/providers/UserTrustProvider'
|
||||||
import { Compass, Plus } from 'lucide-react'
|
import { Compass, Plus } from 'lucide-react'
|
||||||
import { forwardRef, useState } from 'react'
|
import { forwardRef, useState } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
type TExploreTabs = 'following' | 'explore'
|
type TExploreTabs = 'following' | 'explore' | 'reviews'
|
||||||
|
|
||||||
const ExplorePage = forwardRef((_, ref) => {
|
const ExplorePage = forwardRef((_, ref) => {
|
||||||
|
const { hideUntrustedNotes } = useUserTrust()
|
||||||
const [tab, setTab] = useState<TExploreTabs>('explore')
|
const [tab, setTab] = useState<TExploreTabs>('explore')
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -23,11 +27,23 @@ const ExplorePage = forwardRef((_, ref) => {
|
|||||||
value={tab}
|
value={tab}
|
||||||
tabs={[
|
tabs={[
|
||||||
{ value: 'explore', label: 'Explore' },
|
{ value: 'explore', label: 'Explore' },
|
||||||
|
{ value: 'reviews', label: 'Reviews' },
|
||||||
{ value: 'following', label: "Following's Favorites" }
|
{ value: 'following', label: "Following's Favorites" }
|
||||||
]}
|
]}
|
||||||
onTabChange={(tab) => setTab(tab as TExploreTabs)}
|
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>
|
</PrimaryPageLayout>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user