feat: support viewing notes related to external content
This commit is contained in:
@@ -8,11 +8,20 @@ export const toNote = (eventOrId: Pick<Event, 'id' | 'pubkey'> | string) => {
|
|||||||
const nevent = generateEventId(eventOrId)
|
const nevent = generateEventId(eventOrId)
|
||||||
return `/notes/${nevent}`
|
return `/notes/${nevent}`
|
||||||
}
|
}
|
||||||
export const toNoteList = ({ hashtag, search }: { hashtag?: string; search?: string }) => {
|
export const toNoteList = ({
|
||||||
|
hashtag,
|
||||||
|
search,
|
||||||
|
externalContentId
|
||||||
|
}: {
|
||||||
|
hashtag?: string
|
||||||
|
search?: string
|
||||||
|
externalContentId?: string
|
||||||
|
}) => {
|
||||||
const path = '/notes'
|
const path = '/notes'
|
||||||
const query = new URLSearchParams()
|
const query = new URLSearchParams()
|
||||||
if (hashtag) query.set('t', hashtag.toLowerCase())
|
if (hashtag) query.set('t', hashtag.toLowerCase())
|
||||||
if (search) query.set('s', search)
|
if (search) query.set('s', search)
|
||||||
|
if (externalContentId) query.set('i', externalContentId)
|
||||||
return `${path}?${query.toString()}`
|
return `${path}?${query.toString()}`
|
||||||
}
|
}
|
||||||
export const toProfile = (userId: string) => {
|
export const toProfile = (userId: string) => {
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
import NoteList from '@/components/NoteList'
|
import NoteList from '@/components/NoteList'
|
||||||
import { BIG_RELAY_URLS, SEARCHABLE_RELAY_URLS } from '@/constants'
|
import { BIG_RELAY_URLS, SEARCHABLE_RELAY_URLS } from '@/constants'
|
||||||
import SecondaryPageLayout from '@/layouts/SecondaryPageLayout'
|
import SecondaryPageLayout from '@/layouts/SecondaryPageLayout'
|
||||||
|
import { useNostr } from '@/providers/NostrProvider'
|
||||||
import { Filter } from 'nostr-tools'
|
import { Filter } from 'nostr-tools'
|
||||||
import { forwardRef, useMemo } from 'react'
|
import { forwardRef, useMemo } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
const NoteListPage = forwardRef(({ index }: { index?: number }, ref) => {
|
const NoteListPage = forwardRef(({ index }: { index?: number }, ref) => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
|
const { relayList } = useNostr()
|
||||||
const {
|
const {
|
||||||
title = '',
|
title = '',
|
||||||
filter,
|
filter,
|
||||||
@@ -22,8 +24,7 @@ const NoteListPage = forwardRef(({ index }: { index?: number }, ref) => {
|
|||||||
return {
|
return {
|
||||||
title: `# ${hashtag}`,
|
title: `# ${hashtag}`,
|
||||||
filter: { '#t': [hashtag] },
|
filter: { '#t': [hashtag] },
|
||||||
urls: BIG_RELAY_URLS,
|
urls: BIG_RELAY_URLS
|
||||||
type: 'hashtag'
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const search = searchParams.get('s')
|
const search = searchParams.get('s')
|
||||||
@@ -31,8 +32,15 @@ const NoteListPage = forwardRef(({ index }: { index?: number }, ref) => {
|
|||||||
return {
|
return {
|
||||||
title: `${t('Search')}: ${search}`,
|
title: `${t('Search')}: ${search}`,
|
||||||
filter: { search },
|
filter: { search },
|
||||||
urls: SEARCHABLE_RELAY_URLS,
|
urls: SEARCHABLE_RELAY_URLS
|
||||||
type: 'search'
|
}
|
||||||
|
}
|
||||||
|
const externalContentId = searchParams.get('i')
|
||||||
|
if (externalContentId) {
|
||||||
|
return {
|
||||||
|
title: externalContentId,
|
||||||
|
filter: { '#I': [externalContentId] },
|
||||||
|
urls: BIG_RELAY_URLS.concat(relayList?.write || [])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return { urls: BIG_RELAY_URLS }
|
return { urls: BIG_RELAY_URLS }
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import { ExtendedKind } from '@/constants'
|
|||||||
import { useFetchEvent } from '@/hooks'
|
import { useFetchEvent } from '@/hooks'
|
||||||
import SecondaryPageLayout from '@/layouts/SecondaryPageLayout'
|
import SecondaryPageLayout from '@/layouts/SecondaryPageLayout'
|
||||||
import { getParentEventId, getRootEventId, isPictureEvent } from '@/lib/event'
|
import { getParentEventId, getRootEventId, isPictureEvent } from '@/lib/event'
|
||||||
import { toNote } from '@/lib/link'
|
import { toNote, toNoteList } from '@/lib/link'
|
||||||
import { tagNameEquals } from '@/lib/tag'
|
import { tagNameEquals } from '@/lib/tag'
|
||||||
import { useMuteList } from '@/providers/MuteListProvider'
|
import { useMuteList } from '@/providers/MuteListProvider'
|
||||||
import { forwardRef, useMemo } from 'react'
|
import { forwardRef, useMemo } from 'react'
|
||||||
@@ -71,8 +71,8 @@ const NotePage = forwardRef(({ id, index }: { id?: string; index?: number }, ref
|
|||||||
return (
|
return (
|
||||||
<SecondaryPageLayout ref={ref} index={index} title={t('Note')} displayScrollToTopButton>
|
<SecondaryPageLayout ref={ref} index={index} title={t('Note')} displayScrollToTopButton>
|
||||||
<div className="px-4">
|
<div className="px-4">
|
||||||
{rootITag && <OtherRoot value={rootITag[1]} />}
|
{rootITag && <ExternalRoot value={rootITag[1]} />}
|
||||||
{!rootITag && rootEventId !== parentEventId && (
|
{rootEventId !== parentEventId && (
|
||||||
<ParentNote key={`root-note-${event.id}`} eventId={rootEventId} />
|
<ParentNote key={`root-note-${event.id}`} eventId={rootEventId} />
|
||||||
)}
|
)}
|
||||||
<ParentNote key={`parent-note-${event.id}`} eventId={parentEventId} />
|
<ParentNote key={`parent-note-${event.id}`} eventId={parentEventId} />
|
||||||
@@ -92,15 +92,14 @@ const NotePage = forwardRef(({ id, index }: { id?: string; index?: number }, ref
|
|||||||
NotePage.displayName = 'NotePage'
|
NotePage.displayName = 'NotePage'
|
||||||
export default NotePage
|
export default NotePage
|
||||||
|
|
||||||
function OtherRoot({ value }: { value: string }) {
|
function ExternalRoot({ value }: { value: string }) {
|
||||||
const type = useMemo(() => (value.startsWith('http') ? 'url' : 'other'), [value])
|
const { push } = useSecondaryPage()
|
||||||
|
|
||||||
if (type === 'url') {
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Card
|
<Card
|
||||||
className="flex space-x-1 p-1 pl-2 clickable text-sm text-muted-foreground hover:text-foreground"
|
className="flex space-x-1 p-1 items-center clickable text-sm text-muted-foreground hover:text-foreground"
|
||||||
onClick={() => window.open(value, '_blank')}
|
onClick={() => push(toNoteList({ externalContentId: value }))}
|
||||||
>
|
>
|
||||||
<div className="truncate">{value}</div>
|
<div className="truncate">{value}</div>
|
||||||
</Card>
|
</Card>
|
||||||
@@ -109,16 +108,6 @@ function OtherRoot({ value }: { value: string }) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<Card className="flex space-x-1 p-1 text-sm text-muted-foreground">
|
|
||||||
<div className="truncate">{value}</div>
|
|
||||||
</Card>
|
|
||||||
<div className="ml-5 w-px h-2 bg-border" />
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function ParentNote({ eventId }: { eventId?: string }) {
|
function ParentNote({ eventId }: { eventId?: string }) {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const { push } = useSecondaryPage()
|
const { push } = useSecondaryPage()
|
||||||
|
|||||||
Reference in New Issue
Block a user