fix: 🐛
This commit is contained in:
@@ -15,7 +15,7 @@ import { cn } from '@/lib/utils'
|
|||||||
import mediaUpload from '@/services/media-upload.service'
|
import mediaUpload from '@/services/media-upload.service'
|
||||||
import { TImetaInfo } from '@/types'
|
import { TImetaInfo } from '@/types'
|
||||||
import { Event } from 'nostr-tools'
|
import { Event } from 'nostr-tools'
|
||||||
import { memo } from 'react'
|
import { useMemo } from 'react'
|
||||||
import {
|
import {
|
||||||
EmbeddedHashtag,
|
EmbeddedHashtag,
|
||||||
EmbeddedLNInvoice,
|
EmbeddedLNInvoice,
|
||||||
@@ -30,21 +30,21 @@ import MediaPlayer from '../MediaPlayer'
|
|||||||
import WebPreview from '../WebPreview'
|
import WebPreview from '../WebPreview'
|
||||||
import YoutubeEmbeddedPlayer from '../YoutubeEmbeddedPlayer'
|
import YoutubeEmbeddedPlayer from '../YoutubeEmbeddedPlayer'
|
||||||
|
|
||||||
const Content = memo(
|
export default function Content({
|
||||||
({
|
event,
|
||||||
event,
|
content,
|
||||||
content,
|
className,
|
||||||
className,
|
mustLoadMedia
|
||||||
mustLoadMedia
|
}: {
|
||||||
}: {
|
event?: Event
|
||||||
event?: Event
|
content?: string
|
||||||
content?: string
|
className?: string
|
||||||
className?: string
|
mustLoadMedia?: boolean
|
||||||
mustLoadMedia?: boolean
|
}) {
|
||||||
}) => {
|
const translatedEvent = useTranslatedEvent(event?.id)
|
||||||
const translatedEvent = useTranslatedEvent(event?.id)
|
const { nodes, allImages, lastNormalUrl, emojiInfos } = useMemo(() => {
|
||||||
const _content = translatedEvent?.content ?? event?.content ?? content
|
const _content = translatedEvent?.content ?? event?.content ?? content
|
||||||
if (!_content) return null
|
if (!_content) return {}
|
||||||
|
|
||||||
const nodes = parseContent(_content, [
|
const nodes = parseContent(_content, [
|
||||||
EmbeddedUrlParser,
|
EmbeddedUrlParser,
|
||||||
@@ -80,7 +80,6 @@ const Content = memo(
|
|||||||
})
|
})
|
||||||
.filter(Boolean)
|
.filter(Boolean)
|
||||||
.flat() as TImetaInfo[]
|
.flat() as TImetaInfo[]
|
||||||
let imageIndex = 0
|
|
||||||
|
|
||||||
const emojiInfos = getEmojiInfosFromEmojiTags(event?.tags)
|
const emojiInfos = getEmojiInfosFromEmojiTags(event?.tags)
|
||||||
|
|
||||||
@@ -88,73 +87,78 @@ const Content = memo(
|
|||||||
const lastNormalUrl =
|
const lastNormalUrl =
|
||||||
typeof lastNormalUrlNode?.data === 'string' ? lastNormalUrlNode.data : undefined
|
typeof lastNormalUrlNode?.data === 'string' ? lastNormalUrlNode.data : undefined
|
||||||
|
|
||||||
return (
|
return { nodes, allImages, emojiInfos, lastNormalUrl }
|
||||||
<div className={cn('text-wrap break-words whitespace-pre-wrap', className)}>
|
}, [event])
|
||||||
{nodes.map((node, index) => {
|
|
||||||
if (node.type === 'text') {
|
if (!nodes || nodes.length === 0) {
|
||||||
return node.data
|
return null
|
||||||
}
|
|
||||||
if (node.type === 'image' || node.type === 'images') {
|
|
||||||
const start = imageIndex
|
|
||||||
const end = imageIndex + (Array.isArray(node.data) ? node.data.length : 1)
|
|
||||||
imageIndex = end
|
|
||||||
return (
|
|
||||||
<ImageGallery
|
|
||||||
className="mt-2"
|
|
||||||
key={index}
|
|
||||||
images={allImages}
|
|
||||||
start={start}
|
|
||||||
end={end}
|
|
||||||
mustLoad={mustLoadMedia}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
if (node.type === 'media') {
|
|
||||||
return (
|
|
||||||
<MediaPlayer className="mt-2" key={index} src={node.data} mustLoad={mustLoadMedia} />
|
|
||||||
)
|
|
||||||
}
|
|
||||||
if (node.type === 'url') {
|
|
||||||
return <EmbeddedNormalUrl url={node.data} key={index} />
|
|
||||||
}
|
|
||||||
if (node.type === 'invoice') {
|
|
||||||
return <EmbeddedLNInvoice invoice={node.data} key={index} className="mt-2" />
|
|
||||||
}
|
|
||||||
if (node.type === 'websocket-url') {
|
|
||||||
return <EmbeddedWebsocketUrl url={node.data} key={index} />
|
|
||||||
}
|
|
||||||
if (node.type === 'event') {
|
|
||||||
const id = node.data.split(':')[1]
|
|
||||||
return <EmbeddedNote key={index} noteId={id} className="mt-2" />
|
|
||||||
}
|
|
||||||
if (node.type === 'mention') {
|
|
||||||
return <EmbeddedMention key={index} userId={node.data.split(':')[1]} />
|
|
||||||
}
|
|
||||||
if (node.type === 'hashtag') {
|
|
||||||
return <EmbeddedHashtag hashtag={node.data} key={index} />
|
|
||||||
}
|
|
||||||
if (node.type === 'emoji') {
|
|
||||||
const shortcode = node.data.split(':')[1]
|
|
||||||
const emoji = emojiInfos.find((e) => e.shortcode === shortcode)
|
|
||||||
if (!emoji) return node.data
|
|
||||||
return <Emoji classNames={{ img: 'mb-1' }} emoji={emoji} key={index} />
|
|
||||||
}
|
|
||||||
if (node.type === 'youtube') {
|
|
||||||
return (
|
|
||||||
<YoutubeEmbeddedPlayer
|
|
||||||
key={index}
|
|
||||||
url={node.data}
|
|
||||||
className="mt-2"
|
|
||||||
mustLoad={mustLoadMedia}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
})}
|
|
||||||
{lastNormalUrl && <WebPreview className="mt-2" url={lastNormalUrl} />}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
)
|
|
||||||
Content.displayName = 'Content'
|
let imageIndex = 0
|
||||||
export default Content
|
return (
|
||||||
|
<div className={cn('text-wrap break-words whitespace-pre-wrap', className)}>
|
||||||
|
{nodes.map((node, index) => {
|
||||||
|
if (node.type === 'text') {
|
||||||
|
return node.data
|
||||||
|
}
|
||||||
|
if (node.type === 'image' || node.type === 'images') {
|
||||||
|
const start = imageIndex
|
||||||
|
const end = imageIndex + (Array.isArray(node.data) ? node.data.length : 1)
|
||||||
|
imageIndex = end
|
||||||
|
return (
|
||||||
|
<ImageGallery
|
||||||
|
className="mt-2"
|
||||||
|
key={index}
|
||||||
|
images={allImages}
|
||||||
|
start={start}
|
||||||
|
end={end}
|
||||||
|
mustLoad={mustLoadMedia}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (node.type === 'media') {
|
||||||
|
return (
|
||||||
|
<MediaPlayer className="mt-2" key={index} src={node.data} mustLoad={mustLoadMedia} />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (node.type === 'url') {
|
||||||
|
return <EmbeddedNormalUrl url={node.data} key={index} />
|
||||||
|
}
|
||||||
|
if (node.type === 'invoice') {
|
||||||
|
return <EmbeddedLNInvoice invoice={node.data} key={index} className="mt-2" />
|
||||||
|
}
|
||||||
|
if (node.type === 'websocket-url') {
|
||||||
|
return <EmbeddedWebsocketUrl url={node.data} key={index} />
|
||||||
|
}
|
||||||
|
if (node.type === 'event') {
|
||||||
|
const id = node.data.split(':')[1]
|
||||||
|
return <EmbeddedNote key={index} noteId={id} className="mt-2" />
|
||||||
|
}
|
||||||
|
if (node.type === 'mention') {
|
||||||
|
return <EmbeddedMention key={index} userId={node.data.split(':')[1]} />
|
||||||
|
}
|
||||||
|
if (node.type === 'hashtag') {
|
||||||
|
return <EmbeddedHashtag hashtag={node.data} key={index} />
|
||||||
|
}
|
||||||
|
if (node.type === 'emoji') {
|
||||||
|
const shortcode = node.data.split(':')[1]
|
||||||
|
const emoji = emojiInfos.find((e) => e.shortcode === shortcode)
|
||||||
|
if (!emoji) return node.data
|
||||||
|
return <Emoji classNames={{ img: 'mb-1' }} emoji={emoji} key={index} />
|
||||||
|
}
|
||||||
|
if (node.type === 'youtube') {
|
||||||
|
return (
|
||||||
|
<YoutubeEmbeddedPlayer
|
||||||
|
key={index}
|
||||||
|
url={node.data}
|
||||||
|
className="mt-2"
|
||||||
|
mustLoad={mustLoadMedia}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
})}
|
||||||
|
{lastNormalUrl && <WebPreview className="mt-2" url={lastNormalUrl} />}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ export default function YoutubeEmbeddedPlayer({
|
|||||||
})
|
})
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to initialize YouTube player:', error)
|
console.error('Failed to initialize YouTube player:', error)
|
||||||
|
setError(true)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -101,18 +102,8 @@ export default function YoutubeEmbeddedPlayer({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!videoId && !initSuccess) {
|
if (!videoId && !initSuccess) {
|
||||||
return (
|
return <ExternalLink url={url} />
|
||||||
<a
|
|
||||||
href={url}
|
|
||||||
className="text-primary hover:underline"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
>
|
|
||||||
{url}
|
|
||||||
</a>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ export const EmbeddedUrlParser: TContentParser = (content: string) => {
|
|||||||
type = 'image'
|
type = 'image'
|
||||||
} else if (isMedia(url)) {
|
} else if (isMedia(url)) {
|
||||||
type = 'media'
|
type = 'media'
|
||||||
} else if (YOUTUBE_URL_REGEX.test(url)) {
|
} else if (url.match(YOUTUBE_URL_REGEX)) {
|
||||||
type = 'youtube'
|
type = 'youtube'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user