)
}
-
-function RepostDescription({
- reposter,
- className
-}: {
- reposter?: string | null
- className?: string
-}) {
- const { t } = useTranslation()
- if (!reposter) return null
-
- return (
-
- )
-}
diff --git a/src/components/NoteCard/RepostDescription.tsx b/src/components/NoteCard/RepostDescription.tsx
new file mode 100644
index 00000000..c914492a
--- /dev/null
+++ b/src/components/NoteCard/RepostDescription.tsx
@@ -0,0 +1,23 @@
+import { cn } from '@/lib/utils'
+import { Repeat2 } from 'lucide-react'
+import { useTranslation } from 'react-i18next'
+import Username from '../Username'
+
+export default function RepostDescription({
+ reposter,
+ className
+}: {
+ reposter?: string | null
+ className?: string
+}) {
+ const { t } = useTranslation()
+ if (!reposter) return null
+
+ return (
+
+ )
+}
diff --git a/src/components/NoteCard/RepostNoteCard.tsx b/src/components/NoteCard/RepostNoteCard.tsx
index aee6fe28..ea194317 100644
--- a/src/components/NoteCard/RepostNoteCard.tsx
+++ b/src/components/NoteCard/RepostNoteCard.tsx
@@ -2,7 +2,7 @@ import { useMuteList } from '@/providers/MuteListProvider'
import client from '@/services/client.service'
import { Event, kinds, verifyEvent } from 'nostr-tools'
import { useMemo } from 'react'
-import NormalNoteCard from './NormalNoteCard'
+import GenericNoteCard from './GenericNoteCard'
export default function RepostNoteCard({
event,
@@ -17,7 +17,7 @@ export default function RepostNoteCard({
const targetEvent = useMemo(() => {
try {
const targetEvent = event.content ? (JSON.parse(event.content) as Event) : null
- if (!targetEvent || !verifyEvent(targetEvent) || targetEvent.kind !== kinds.ShortTextNote) {
+ if (!targetEvent || !verifyEvent(targetEvent) || targetEvent.kind === kinds.Repost) {
return null
}
client.addEventToCache(targetEvent)
@@ -38,5 +38,5 @@ export default function RepostNoteCard({
return null
}
- return
+ return
}
diff --git a/src/components/NoteCard/UnknownNoteCard.tsx b/src/components/NoteCard/UnknownNoteCard.tsx
new file mode 100644
index 00000000..c579f149
--- /dev/null
+++ b/src/components/NoteCard/UnknownNoteCard.tsx
@@ -0,0 +1,65 @@
+import { Button } from '@/components/ui/button'
+import { Separator } from '@/components/ui/separator'
+import { getSharableEventId } from '@/lib/event'
+import { cn } from '@/lib/utils'
+import { Check, Copy } from 'lucide-react'
+import { Event } from 'nostr-tools'
+import { useState } from 'react'
+import RepostDescription from './RepostDescription'
+import UserAvatar from '../UserAvatar'
+import Username from '../Username'
+import { FormattedTimestamp } from '../FormattedTimestamp'
+import { useTranslation } from 'react-i18next'
+
+export default function UnknownNoteCard({
+ event,
+ className,
+ embedded = false,
+ reposter
+}: {
+ event: Event
+ className?: string
+ embedded?: boolean
+ reposter?: string
+}) {
+ const { t } = useTranslation()
+ const [isCopied, setIsCopied] = useState(false)
+
+ return (
+
+
+
+
+
+
{t('Cannot handle event of kind k', { k: event.kind })}
+
+
+
+ {!embedded &&
}
+
+ )
+}
diff --git a/src/components/NoteCard/index.tsx b/src/components/NoteCard/index.tsx
index b6a8cafd..d20136a2 100644
--- a/src/components/NoteCard/index.tsx
+++ b/src/components/NoteCard/index.tsx
@@ -1,6 +1,6 @@
import { useMuteList } from '@/providers/MuteListProvider'
import { Event, kinds } from 'nostr-tools'
-import NormalNoteCard from './NormalNoteCard'
+import GenericNoteCard from './GenericNoteCard'
import RepostNoteCard from './RepostNoteCard'
export default function NoteCard({
@@ -22,5 +22,5 @@ export default function NoteCard({
)
}
- return
+ return
}
diff --git a/src/constants.ts b/src/constants.ts
index cf15a409..778db3ab 100644
--- a/src/constants.ts
+++ b/src/constants.ts
@@ -25,6 +25,7 @@ export const SEARCHABLE_RELAY_URLS = ['wss://relay.nostr.band/', 'wss://search.n
export const PICTURE_EVENT_KIND = 20
export const COMMENT_EVENT_KIND = 1111
+export const GROUP_METADATA_EVENT_KIND = 39000
export const URL_REGEX = /https?:\/\/[\w\p{L}\p{N}\p{M}&.-/?=#\-@%+_,:!~*]+/gu
export const EMAIL_REGEX = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/
diff --git a/src/i18n/en.ts b/src/i18n/en.ts
index 57d9d37d..6ea6a4ce 100644
--- a/src/i18n/en.ts
+++ b/src/i18n/en.ts
@@ -178,6 +178,9 @@ export default {
randomRelaysRefresh: 'Refresh',
'Explore more': 'Explore more',
'Payment page': 'Payment page',
- 'Supported NIPs': 'Supported NIPs'
+ 'Supported NIPs': 'Supported NIPs',
+ 'Open in a': 'Open in {{a}}',
+ 'Cannot handle event of kind k': 'Cannot handle event of kind {{k}}',
+ 'Sorry! The note cannot be found 😔': 'Sorry! The note cannot be found 😔'
}
}
diff --git a/src/i18n/zh.ts b/src/i18n/zh.ts
index d570c3c4..db545e44 100644
--- a/src/i18n/zh.ts
+++ b/src/i18n/zh.ts
@@ -179,6 +179,9 @@ export default {
randomRelaysRefresh: '换一批',
'Explore more': '探索更多',
'Payment page': '付款页面',
- 'Supported NIPs': '支持的 NIP'
+ 'Supported NIPs': '支持的 NIP',
+ 'Open in a': '在 {{a}} 中打开',
+ 'Cannot handle event of kind k': '无法处理类型为 {{k}} 的事件',
+ 'Sorry! The note cannot be found 😔': '抱歉!找不到该笔记 😔'
}
}
diff --git a/src/lib/event.ts b/src/lib/event.ts
index dd9d3ece..695e1bc4 100644
--- a/src/lib/event.ts
+++ b/src/lib/event.ts
@@ -45,6 +45,10 @@ export function isProtectedEvent(event: Event) {
return event.tags.some(([tagName]) => tagName === '-')
}
+export function isSupportedKind(kind: number) {
+ return [kinds.ShortTextNote, PICTURE_EVENT_KIND].includes(kind)
+}
+
export function getParentEventId(event?: Event) {
if (!event || !isReplyNoteEvent(event)) return undefined
const tag = event.tags.find(isReplyETag) ?? event.tags.find(tagNameEquals('e'))
@@ -81,7 +85,7 @@ export function getEventCoordinate(event: Event) {
}
export function getSharableEventId(event: Event) {
- const hints = client.getEventHints(event.id).slice(0, 3)
+ const hints = client.getEventHints(event.id).slice(0, 2)
if (isReplaceable(event.kind)) {
const identifier = event.tags.find(tagNameEquals('d'))?.[1] ?? ''
return nip19.naddrEncode({ pubkey: event.pubkey, kind: event.kind, identifier, relays: hints })
diff --git a/src/lib/link.ts b/src/lib/link.ts
index 398e6f04..dd9e80e3 100644
--- a/src/lib/link.ts
+++ b/src/lib/link.ts
@@ -1,9 +1,12 @@
+import client from '@/services/client.service'
import { Event, nip19 } from 'nostr-tools'
+import { getSharableEventId } from './event'
export const toHome = () => '/'
export const toNote = (eventOrId: Pick
| string) => {
if (typeof eventOrId === 'string') return `/notes/${eventOrId}`
- const nevent = nip19.neventEncode({ id: eventOrId.id, author: eventOrId.pubkey })
+ const relay = client.getEventHint(eventOrId.id)
+ const nevent = nip19.neventEncode({ id: eventOrId.id, author: eventOrId.pubkey, relays: [relay] })
return `/notes/${nevent}`
}
export const toNoteList = ({ hashtag, search }: { hashtag?: string; search?: string }) => {
@@ -40,7 +43,10 @@ export const toProfileEditor = () => '/profile-editor'
export const toRelay = (url: string) => `/relays/${encodeURIComponent(url)}`
export const toMuteList = () => '/mutes'
-export const toNoStrudelProfile = (id: string) => `https://nostrudel.ninja/#/u/${id}`
-export const toNoStrudelNote = (id: string) => `https://nostrudel.ninja/#/n/${id}`
-export const toNoStrudelArticle = (id: string) => `https://nostrudel.ninja/#/articles/${id}`
-export const toNoStrudelStream = (id: string) => `https://nostrudel.ninja/#/streams/${id}`
+export const toHablaLongFormArticle = (event: Event) => {
+ return `https://habla.news/a/${getSharableEventId(event)}`
+}
+export const toZapStreamLiveEvent = (event: Event) => {
+ return `https://zap.stream/${getSharableEventId(event)}`
+}
+export const toChachiChat = (relay: string, d: string) => `https://chachi.chat/${relay}/${d}`
diff --git a/src/pages/secondary/NotePage/index.tsx b/src/pages/secondary/NotePage/index.tsx
index 66cd2a9e..bd553950 100644
--- a/src/pages/secondary/NotePage/index.tsx
+++ b/src/pages/secondary/NotePage/index.tsx
@@ -12,6 +12,7 @@ import { useFetchEvent } from '@/hooks'
import SecondaryPageLayout from '@/layouts/SecondaryPageLayout'
import { getParentEventId, getRootEventId, isPictureEvent } from '@/lib/event'
import { toNote } from '@/lib/link'
+import { kinds } from 'nostr-tools'
import { forwardRef, useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import NotFoundPage from '../NotFoundPage'
@@ -57,15 +58,15 @@ const NotePage = forwardRef(({ id, index }: { id?: string; index?: number }, ref