fix: 🐛

This commit is contained in:
codytseng
2025-06-25 11:01:53 +08:00
parent cb32439896
commit 6c2cd0ff42
7 changed files with 131 additions and 19 deletions

View File

@@ -1,5 +1,6 @@
import { Skeleton } from '@/components/ui/skeleton'
import { useFetchEvent } from '@/hooks'
import { isSupportedKind } from '@/lib/event'
import { cn } from '@/lib/utils'
import { useMuteList } from '@/providers/MuteListProvider'
import { useMemo } from 'react'
@@ -68,6 +69,8 @@ export default function ParentNotePreview({
{event && <UserAvatar className="shrink-0" userId={event.pubkey} size="tiny" />}
{isMuted ? (
<div className="truncate">[{t('This user has been muted')}]</div>
) : !isSupportedKind(event.kind) ? (
<div className="truncate">[{t('Cannot handle event of kind k', { k: event.kind })}]</div>
) : (
<ContentPreview className="truncate" event={event} />
)}

View File

@@ -24,7 +24,6 @@ export default function Uploader({
try {
for (const file of event.target.files) {
const result = await mediaUpload.upload(file)
console.log('File uploaded successfully', result)
onUploadSuccess(result)
}
} catch (error) {

View File

@@ -1,8 +1,11 @@
import { BIG_RELAY_URLS, ExtendedKind } from '@/constants'
import {
getEventCoordinate,
getParentEventTag,
getRootAddressableEventTag,
getRootEventHexId,
getRootEventTag,
isReplaceable,
isReplyNoteEvent
} from '@/lib/event'
import { generateEventIdFromETag, tagNameEquals } from '@/lib/tag'
@@ -16,7 +19,10 @@ import { useTranslation } from 'react-i18next'
import { LoadingBar } from '../LoadingBar'
import ReplyNote, { ReplyNoteSkeleton } from '../ReplyNote'
type TRootInfo = { type: 'event'; id: string; pubkey: string } | { type: 'I'; id: string }
type TRootInfo =
| { type: 'E'; id: string; pubkey: string }
| { type: 'A'; id: string; eventId: string; pubkey: string; relay?: string }
| { type: 'I'; id: string }
const LIMIT = 100
const SHOW_COUNT = 10
@@ -30,7 +36,8 @@ export default function ReplyNoteList({ index, event }: { index?: number; event:
const replies = useMemo(() => {
const replyIdSet = new Set<string>()
const replyEvents: NEvent[] = []
let parentEventIds = [event.id]
const currentEventId = isReplaceable(event.kind) ? getEventCoordinate(event) : event.id
let parentEventIds = [currentEventId]
while (parentEventIds.length > 0) {
const events = parentEventIds.flatMap((id) => repliesMap.get(id)?.events || [])
events.forEach((evt) => {
@@ -52,22 +59,36 @@ export default function ReplyNoteList({ index, event }: { index?: number; event:
useEffect(() => {
const fetchRootEvent = async () => {
let root: TRootInfo = { type: 'event', id: event.id, pubkey: event.pubkey }
let root: TRootInfo = isReplaceable(event.kind)
? {
type: 'A',
id: getEventCoordinate(event),
eventId: event.id,
pubkey: event.pubkey,
relay: client.getEventHint(event.id)
}
: { type: 'E', id: event.id, pubkey: event.pubkey }
const rootEventTag = getRootEventTag(event)
if (rootEventTag) {
const [, rootEventHexId, , , rootEventPubkey] = rootEventTag
if (rootEventHexId && rootEventPubkey) {
root = { type: 'event', id: rootEventHexId, pubkey: rootEventPubkey }
root = { type: 'E', id: rootEventHexId, pubkey: rootEventPubkey }
} else {
const rootEventId = generateEventIdFromETag(rootEventTag)
if (rootEventId) {
const rootEvent = await client.fetchEvent(rootEventId)
if (rootEvent) {
root = { type: 'event', id: rootEvent.id, pubkey: rootEvent.pubkey }
root = { type: 'E', id: rootEvent.id, pubkey: rootEvent.pubkey }
}
}
}
} else if (event.kind === ExtendedKind.COMMENT) {
const rootATag = getRootAddressableEventTag(event)
if (rootATag) {
const [, coordinate, relay] = rootATag
const [, pubkey] = coordinate.split(':')
root = { type: 'A', id: coordinate, eventId: event.id, pubkey, relay }
}
const rootITag = event.tags.find(tagNameEquals('I'))
if (rootITag) {
root = { type: 'I', id: rootITag[1] }
@@ -110,13 +131,18 @@ export default function ReplyNoteList({ index, event }: { index?: number; event:
(rootInfo as { pubkey?: string }).pubkey ?? event.pubkey
)
const relayUrls = relayList.read.concat(BIG_RELAY_URLS)
const seenOn = client.getSeenEventRelayUrls(rootInfo.id)
const seenOn =
rootInfo.type === 'E'
? client.getSeenEventRelayUrls(rootInfo.id)
: rootInfo.type === 'A'
? client.getCurrentRelayUrls()
: []
relayUrls.unshift(...seenOn)
const filters: (Omit<Filter, 'since' | 'until'> & {
limit: number
})[] = []
if (rootInfo.type === 'event') {
if (rootInfo.type === 'E') {
filters.push({
'#e': [rootInfo.id],
kinds: [kinds.ShortTextNote],
@@ -129,6 +155,15 @@ export default function ReplyNoteList({ index, event }: { index?: number; event:
limit: LIMIT
})
}
} else if (rootInfo.type === 'A') {
filters.push({
'#A': [rootInfo.id],
kinds: [ExtendedKind.COMMENT],
limit: LIMIT
})
if (rootInfo.relay) {
relayUrls.push(rootInfo.relay)
}
} else {
filters.push({
'#I': [rootInfo.id],

View File

@@ -187,10 +187,12 @@ export async function createCommentDraftEvent(
const {
quoteEventIds,
rootEventId,
rootCoordinateTag,
rootKind,
rootPubkey,
rootUrl,
parentEventId,
parentCoordinate,
parentKind,
parentPubkey
} = await extractCommentMentions(content, parentEvent)
@@ -207,7 +209,9 @@ export async function createCommentDraftEvent(
tags.push(...mentions.filter((pubkey) => pubkey !== parentPubkey).map((pubkey) => ['p', pubkey]))
if (rootEventId) {
if (rootCoordinateTag) {
tags.push(rootCoordinateTag)
} else if (rootEventId) {
tags.push(
rootPubkey
? ['E', rootEventId, client.getEventHint(rootEventId), rootPubkey]
@@ -225,7 +229,9 @@ export async function createCommentDraftEvent(
}
tags.push(
...[
['e', parentEventId, client.getEventHint(parentEventId), parentPubkey],
parentCoordinate
? ['a', parentCoordinate, client.getEventHint(parentEventId)]
: ['e', parentEventId, client.getEventHint(parentEventId), parentPubkey],
['k', parentKind.toString()],
['p', parentPubkey]
]

View File

@@ -7,6 +7,7 @@ import { getAmountFromInvoice, getLightningAddressFromProfile } from './lightnin
import { formatPubkey, pubkeyToNpub } from './pubkey'
import {
extractImageInfoFromTag,
generateEventIdFromATag,
generateEventIdFromETag,
isReplyETag,
isRootETag,
@@ -27,7 +28,7 @@ export function isNsfwEvent(event: Event) {
export function isReplyNoteEvent(event: Event) {
if (event.kind === ExtendedKind.COMMENT) {
return !!getParentEventTag(event)
return !!getParentEventTag(event) || !!getParentAddressableEventTag(event)
}
if (event.kind !== kinds.ShortTextNote) return false
@@ -88,16 +89,27 @@ export function getParentEventTag(event?: Event) {
return tag
}
export function getParentAddressableEventTag(event?: Event) {
if (!event || event.kind !== ExtendedKind.COMMENT) return undefined
return event.tags.find(tagNameEquals('a')) ?? event.tags.find(tagNameEquals('A'))
}
export function getParentEventHexId(event?: Event) {
const tag = getParentEventTag(event)
return tag?.[1]
}
export function getParentEventId(event?: Event) {
const tag = getParentEventTag(event)
if (!tag) return undefined
const eTag = getParentEventTag(event)
if (!eTag) {
const aTag = getParentAddressableEventTag(event)
if (!aTag) return undefined
return generateEventIdFromETag(tag)
return generateEventIdFromATag(aTag)
}
return generateEventIdFromETag(eTag)
}
export function getRootEventTag(event?: Event) {
@@ -117,6 +129,12 @@ export function getRootEventTag(event?: Event) {
return tag
}
export function getRootAddressableEventTag(event?: Event) {
if (!event || event.kind !== ExtendedKind.COMMENT) return undefined
return event.tags.find(tagNameEquals('A'))
}
export function getRootEventHexId(event?: Event) {
const tag = getRootEventTag(event)
return tag?.[1]
@@ -124,7 +142,12 @@ export function getRootEventHexId(event?: Event) {
export function getRootEventId(event?: Event) {
const tag = getRootEventTag(event)
if (!tag) return undefined
if (!tag) {
const aTag = getRootAddressableEventTag(event)
if (!aTag) return undefined
return generateEventIdFromATag(aTag)
}
return generateEventIdFromETag(tag)
}
@@ -356,6 +379,13 @@ export async function extractRelatedEventIds(content: string, parentEvent?: Even
export async function extractCommentMentions(content: string, parentEvent: Event) {
const quoteEventIds: string[] = []
const parentEventIsReplaceable = isReplaceable(parentEvent.kind)
const rootCoordinateTag =
parentEvent.kind === ExtendedKind.COMMENT
? parentEvent.tags.find(tagNameEquals('A'))
: isReplaceable(parentEvent.kind)
? ['A', getEventCoordinate(parentEvent), client.getEventHint(parentEvent.id)]
: undefined
const rootEventId =
parentEvent.kind === ExtendedKind.COMMENT
? parentEvent.tags.find(tagNameEquals('E'))?.[1]
@@ -374,6 +404,7 @@ export async function extractCommentMentions(content: string, parentEvent: Event
: undefined
const parentEventId = parentEvent.id
const parentCoordinate = parentEventIsReplaceable ? getEventCoordinate(parentEvent) : undefined
const parentKind = parentEvent.kind
const parentPubkey = parentEvent.pubkey
@@ -399,10 +430,12 @@ export async function extractCommentMentions(content: string, parentEvent: Event
return {
quoteEventIds,
rootEventId,
rootCoordinateTag,
rootKind,
rootPubkey,
rootUrl,
parentEventId,
parentCoordinate,
parentKind,
parentPubkey
}

View File

@@ -11,7 +11,7 @@ import { Skeleton } from '@/components/ui/skeleton'
import { ExtendedKind } from '@/constants'
import { useFetchEvent } from '@/hooks'
import SecondaryPageLayout from '@/layouts/SecondaryPageLayout'
import { getParentEventId, getRootEventId, isPictureEvent } from '@/lib/event'
import { getParentEventId, getRootEventId, isPictureEvent, isSupportedKind } from '@/lib/event'
import { toNote, toNoteList } from '@/lib/link'
import { tagNameEquals } from '@/lib/tag'
import { useMuteList } from '@/providers/MuteListProvider'
@@ -158,6 +158,21 @@ function ParentNote({ eventId }: { eventId?: string }) {
)
}
if (!isSupportedKind(event.kind)) {
return (
<div>
<Card
className="flex space-x-1 p-1 items-center clickable text-sm text-muted-foreground hover:text-foreground"
onClick={() => push(toNote(eventId))}
>
<UserAvatar userId={event.pubkey} size="tiny" className="shrink-0" />
<div className="shrink-0">[{t('Cannot handle event of kind k', { k: event.kind })}]</div>
</Card>
<div className="ml-5 w-px h-2 bg-border" />
</div>
)
}
return (
<div>
<Card

View File

@@ -1,4 +1,9 @@
import { getParentEventTag, getRootEventTag } from '@/lib/event'
import {
getParentAddressableEventTag,
getParentEventTag,
getRootAddressableEventTag,
getRootEventTag
} from '@/lib/event'
import { Event } from 'nostr-tools'
import { createContext, useCallback, useContext, useState } from 'react'
@@ -29,15 +34,31 @@ export function ReplyProvider({ children }: { children: React.ReactNode }) {
if (newReplyIdSet.has(reply.id)) return
newReplyIdSet.add(reply.id)
let rootId: string | undefined
const rootETag = getRootEventTag(reply)
if (rootETag) {
const rootId = rootETag[1]
rootId = rootETag[1]
} else {
const rootATag = getRootAddressableEventTag(reply)
if (rootATag) {
rootId = rootATag[1]
}
}
if (rootId) {
newReplyEventMap.set(rootId, [...(newReplyEventMap.get(rootId) || []), reply])
}
let parentId: string | undefined
const parentETag = getParentEventTag(reply)
if (parentETag) {
const parentId = parentETag[1]
parentId = parentETag[1]
} else {
const parentATag = getParentAddressableEventTag(reply)
if (parentATag) {
parentId = parentATag[1]
}
}
if (parentId && parentId !== rootId) {
newReplyEventMap.set(parentId, [...(newReplyEventMap.get(parentId) || []), reply])
}
})