diff --git a/src/components/ParentNotePreview/index.tsx b/src/components/ParentNotePreview/index.tsx
index 4fa6e76a..d9694f9a 100644
--- a/src/components/ParentNotePreview/index.tsx
+++ b/src/components/ParentNotePreview/index.tsx
@@ -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 && }
{isMuted ? (
[{t('This user has been muted')}]
+ ) : !isSupportedKind(event.kind) ? (
+ [{t('Cannot handle event of kind k', { k: event.kind })}]
) : (
)}
diff --git a/src/components/PostEditor/Uploader.tsx b/src/components/PostEditor/Uploader.tsx
index be42bd09..4a731306 100644
--- a/src/components/PostEditor/Uploader.tsx
+++ b/src/components/PostEditor/Uploader.tsx
@@ -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) {
diff --git a/src/components/ReplyNoteList/index.tsx b/src/components/ReplyNoteList/index.tsx
index 570eb349..88ebd5e1 100644
--- a/src/components/ReplyNoteList/index.tsx
+++ b/src/components/ReplyNoteList/index.tsx
@@ -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()
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 & {
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],
diff --git a/src/lib/draft-event.ts b/src/lib/draft-event.ts
index c90bf3c2..95ecefe9 100644
--- a/src/lib/draft-event.ts
+++ b/src/lib/draft-event.ts
@@ -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]
]
diff --git a/src/lib/event.ts b/src/lib/event.ts
index 02c21508..cc67c188 100644
--- a/src/lib/event.ts
+++ b/src/lib/event.ts
@@ -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
}
diff --git a/src/pages/secondary/NotePage/index.tsx b/src/pages/secondary/NotePage/index.tsx
index ded17040..ccf72ab9 100644
--- a/src/pages/secondary/NotePage/index.tsx
+++ b/src/pages/secondary/NotePage/index.tsx
@@ -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 (
+
+
push(toNote(eventId))}
+ >
+
+ [{t('Cannot handle event of kind k', { k: event.kind })}]
+
+
+
+ )
+ }
+
return (