feat: add support for commenting and reacting on external content

This commit is contained in:
codytseng 2025-11-15 16:26:19 +08:00
parent 5ba5c26fcd
commit 0bb62dd3fb
76 changed files with 1635 additions and 639 deletions

View file

@ -1,36 +0,0 @@
import { ExtendedKind } from '@/constants'
import { tagNameEquals } from '@/lib/tag'
import { cn } from '@/lib/utils'
import { Event } from 'nostr-tools'
import { useMemo } from 'react'
import { useTranslation } from 'react-i18next'
export default function IValue({ event, className }: { event: Event; className?: string }) {
const { t } = useTranslation()
const iValue = useMemo(() => {
if (event.kind !== ExtendedKind.COMMENT) return undefined
const iTag = event.tags.find(tagNameEquals('i'))
return iTag ? iTag[1] : undefined
}, [event])
if (!iValue) return null
return (
<div className={cn('truncate text-muted-foreground', className)}>
{t('Comment on') + ' '}
{iValue.startsWith('http') ? (
<a
className="hover:text-foreground underline truncate"
href={iValue}
target="_blank"
rel="noopener noreferrer"
onClick={(e) => e.stopPropagation()}
>
{iValue}
</a>
) : (
<span>{iValue}</span>
)}
</div>
)
}

View file

@ -1,7 +1,7 @@
import { useSecondaryPage } from '@/PageManager'
import { ExtendedKind, SUPPORTED_KINDS } from '@/constants'
import { getParentBech32Id, isNsfwEvent } from '@/lib/event'
import { toNote } from '@/lib/link'
import { getParentStuff, isNsfwEvent } from '@/lib/event'
import { toExternalContent, toNote } from '@/lib/link'
import { useContentPolicy } from '@/providers/ContentPolicyProvider'
import { useMuteList } from '@/providers/MuteListProvider'
import { useScreenSize } from '@/providers/ScreenSizeProvider'
@ -22,7 +22,6 @@ import CommunityDefinition from './CommunityDefinition'
import EmojiPack from './EmojiPack'
import GroupMetadata from './GroupMetadata'
import Highlight from './Highlight'
import IValue from './IValue'
import LiveEvent from './LiveEvent'
import LongFormArticle from './LongFormArticle'
import LongFormArticlePreview from './LongFormArticlePreview'
@ -51,10 +50,9 @@ export default function Note({
}) {
const { push } = useSecondaryPage()
const { isSmallScreen } = useScreenSize()
const parentEventId = useMemo(
() => (hideParentNotePreview ? undefined : getParentBech32Id(event)),
[event, hideParentNotePreview]
)
const { parentEventId, parentExternalContent } = useMemo(() => {
return getParentStuff(event)
}, [event])
const { defaultShowNsfw } = useContentPolicy()
const [showNsfw, setShowNsfw] = useState(false)
const { mutePubkeySet } = useMuteList()
@ -141,17 +139,21 @@ export default function Note({
)}
</div>
</div>
{parentEventId && (
{!hideParentNotePreview && (
<ParentNotePreview
eventId={parentEventId}
externalContent={parentExternalContent}
className="mt-2"
onClick={(e) => {
e.stopPropagation()
push(toNote(parentEventId))
if (parentExternalContent) {
push(toExternalContent(parentExternalContent))
} else if (parentEventId) {
push(toNote(parentEventId))
}
}}
/>
)}
<IValue event={event} className="mt-2" />
{content}
</div>
)