feat: show ellipsis if root and parent reply are not consecutive

This commit is contained in:
codytseng
2025-07-15 22:39:07 +08:00
parent 03deb9d375
commit a710e40747

View File

@@ -11,10 +11,12 @@ import { Skeleton } from '@/components/ui/skeleton'
import { ExtendedKind } from '@/constants' 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, getParentEventTag, getRootEventId, isPictureEvent } from '@/lib/event'
import { toNote, toNoteList } from '@/lib/link' import { toNote, toNoteList } from '@/lib/link'
import { tagNameEquals } from '@/lib/tag' import { tagNameEquals } from '@/lib/tag'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
import { Ellipsis } from 'lucide-react'
import { Event } from 'nostr-tools'
import { forwardRef, useMemo } from 'react' import { forwardRef, useMemo } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import NotFoundPage from '../NotFoundPage' import NotFoundPage from '../NotFoundPage'
@@ -28,6 +30,8 @@ const NotePage = forwardRef(({ id, index }: { id?: string; index?: number }, ref
() => (event?.kind === ExtendedKind.COMMENT ? event.tags.find(tagNameEquals('I')) : undefined), () => (event?.kind === ExtendedKind.COMMENT ? event.tags.find(tagNameEquals('I')) : undefined),
[event] [event]
) )
const { isFetching: isFetchingRootEvent, event: rootEvent } = useFetchEvent(rootEventId)
const { isFetching: isFetchingParentEvent, event: parentEvent } = useFetchEvent(parentEventId)
if (!event && isFetching) { if (!event && isFetching) {
return ( return (
@@ -73,9 +77,18 @@ const NotePage = forwardRef(({ id, index }: { id?: string; index?: number }, ref
<div className="px-4"> <div className="px-4">
{rootITag && <ExternalRoot value={rootITag[1]} />} {rootITag && <ExternalRoot value={rootITag[1]} />}
{rootEventId !== parentEventId && ( {rootEventId !== parentEventId && (
<ParentNote key={`root-note-${event.id}`} eventId={rootEventId} /> <ParentNote
key={`root-note-${event.id}`}
isFetching={isFetchingRootEvent}
event={rootEvent}
isConsecutive={isConsecutive(rootEvent, parentEvent)}
/>
)} )}
<ParentNote key={`parent-note-${event.id}`} eventId={parentEventId} /> <ParentNote
key={`parent-note-${event.id}`}
isFetching={isFetchingParentEvent}
event={parentEvent}
/>
<Note <Note
key={`note-${event.id}`} key={`note-${event.id}`}
event={event} event={event}
@@ -109,41 +122,59 @@ function ExternalRoot({ value }: { value: string }) {
) )
} }
function ParentNote({ eventId }: { eventId?: string }) { function ParentNote({
event,
isFetching,
isConsecutive = true
}: {
event?: Event
isFetching: boolean
isConsecutive?: boolean
}) {
const { push } = useSecondaryPage() const { push } = useSecondaryPage()
const { event, isFetching } = useFetchEvent(eventId)
if (!eventId) return null
if (isFetching) { if (isFetching) {
return ( return (
<div> <div>
<Card className="flex space-x-1 p-1 items-center clickable text-sm text-muted-foreground"> <Card className="flex space-x-1 px-2 py-1 items-center clickable text-sm text-muted-foreground">
<Skeleton className="shrink w-4 h-4 rounded-full" /> <Skeleton className="shrink w-4 h-4 rounded-full" />
<div className="py-1 flex-1"> <div className="py-1 flex-1">
<Skeleton className="h-3" /> <Skeleton className="h-3" />
</div> </div>
</Card> </Card>
<div className="ml-5 w-px h-2 bg-border" /> <div className="ml-5 w-px h-3 bg-border" />
</div> </div>
) )
} }
if (!event) return null
return ( return (
<div> <div>
<Card <Card
className={cn( className={cn(
'flex space-x-1 p-1 items-center clickable text-sm text-muted-foreground', 'flex space-x-1 px-1.5 py-1 items-center clickable text-sm text-muted-foreground',
event && 'hover:text-foreground' event && 'hover:text-foreground'
)} )}
onClick={() => { onClick={() => {
if (!event) return if (!event) return
push(toNote(eventId)) push(toNote(event))
}} }}
> >
{event && <UserAvatar userId={event.pubkey} size="tiny" className="shrink-0" />} {event && <UserAvatar userId={event.pubkey} size="tiny" className="shrink-0" />}
<ContentPreview className="truncate" event={event} /> <ContentPreview className="truncate" event={event} />
</Card> </Card>
<div className="ml-5 w-px h-2 bg-border" /> {isConsecutive ? (
<div className="ml-5 w-px h-3 bg-border" />
) : (
<Ellipsis className="ml-3.5 text-muted-foreground/60 size-3" />
)}
</div> </div>
) )
} }
function isConsecutive(rootEvent?: Event, parentEvent?: Event) {
const eTag = getParentEventTag(parentEvent)
if (!eTag) return false
return rootEvent?.id === eTag[1]
}