feat: 💨

This commit is contained in:
codytseng
2025-09-13 23:36:49 +08:00
parent f785d0d8a2
commit 206cbf7e19
5 changed files with 46 additions and 13 deletions

View File

@@ -31,7 +31,17 @@ import WebPreview from '../WebPreview'
import YoutubeEmbeddedPlayer from '../YoutubeEmbeddedPlayer' import YoutubeEmbeddedPlayer from '../YoutubeEmbeddedPlayer'
const Content = memo( const Content = memo(
({ event, content, className }: { event?: Event; content?: string; className?: string }) => { ({
event,
content,
className,
mustLoadMedia
}: {
event?: Event
content?: string
className?: string
mustLoadMedia?: boolean
}) => {
const translatedEvent = useTranslatedEvent(event?.id) const translatedEvent = useTranslatedEvent(event?.id)
const _content = translatedEvent?.content ?? event?.content ?? content const _content = translatedEvent?.content ?? event?.content ?? content
if (!_content) return null if (!_content) return null
@@ -95,11 +105,14 @@ const Content = memo(
images={allImages} images={allImages}
start={start} start={start}
end={end} end={end}
mustLoad={mustLoadMedia}
/> />
) )
} }
if (node.type === 'media') { if (node.type === 'media') {
return <MediaPlayer className="mt-2" key={index} src={node.data} /> return (
<MediaPlayer className="mt-2" key={index} src={node.data} mustLoad={mustLoadMedia} />
)
} }
if (node.type === 'url') { if (node.type === 'url') {
return <EmbeddedNormalUrl url={node.data} key={index} /> return <EmbeddedNormalUrl url={node.data} key={index} />
@@ -127,7 +140,14 @@ const Content = memo(
return <Emoji classNames={{ img: 'mb-1' }} emoji={emoji} key={index} /> return <Emoji classNames={{ img: 'mb-1' }} emoji={emoji} key={index} />
} }
if (node.type === 'youtube') { if (node.type === 'youtube') {
return <YoutubeEmbeddedPlayer key={index} url={node.data} className="mt-2" /> return (
<YoutubeEmbeddedPlayer
key={index}
url={node.data}
className="mt-2"
mustLoad={mustLoadMedia}
/>
)
} }
return null return null
})} })}

View File

@@ -14,12 +14,14 @@ export default function ImageGallery({
className, className,
images, images,
start = 0, start = 0,
end = images.length end = images.length,
mustLoad = false
}: { }: {
className?: string className?: string
images: TImetaInfo[] images: TImetaInfo[]
start?: number start?: number
end?: number end?: number
mustLoad?: boolean
}) { }) {
const id = useMemo(() => `image-gallery-${randomString()}`, []) const id = useMemo(() => `image-gallery-${randomString()}`, [])
const { autoLoadMedia } = useContentPolicy() const { autoLoadMedia } = useContentPolicy()
@@ -42,7 +44,7 @@ export default function ImageGallery({
const displayImages = images.slice(start, end) const displayImages = images.slice(start, end)
if (!autoLoadMedia) { if (!mustLoad && !autoLoadMedia) {
return displayImages.map((image, i) => ( return displayImages.map((image, i) => (
<ImageWithLightbox <ImageWithLightbox
key={i} key={i}

View File

@@ -4,7 +4,15 @@ import { useTranslation } from 'react-i18next'
import AudioPlayer from '../AudioPlayer' import AudioPlayer from '../AudioPlayer'
import VideoPlayer from '../VideoPlayer' import VideoPlayer from '../VideoPlayer'
export default function MediaPlayer({ src, className }: { src: string; className?: string }) { export default function MediaPlayer({
src,
className,
mustLoad = false
}: {
src: string
className?: string
mustLoad?: boolean
}) {
const { t } = useTranslation() const { t } = useTranslation()
const { autoLoadMedia } = useContentPolicy() const { autoLoadMedia } = useContentPolicy()
const [display, setDisplay] = useState(autoLoadMedia) const [display, setDisplay] = useState(autoLoadMedia)
@@ -19,7 +27,7 @@ export default function MediaPlayer({ src, className }: { src: string; className
}, [autoLoadMedia]) }, [autoLoadMedia])
useEffect(() => { useEffect(() => {
if (!display) { if (!mustLoad && !display) {
setMediaType(null) setMediaType(null)
return return
} }
@@ -52,9 +60,9 @@ export default function MediaPlayer({ src, className }: { src: string; className
return () => { return () => {
video.src = '' video.src = ''
} }
}, [src, display]) }, [src, display, mustLoad])
if (!display) { if (!mustLoad && !display) {
return ( return (
<div <div
className="text-primary hover:underline truncate w-fit cursor-pointer" className="text-primary hover:underline truncate w-fit cursor-pointer"

View File

@@ -15,6 +15,7 @@ export default function Preview({ content, className }: { content: string; class
<Content <Content
event={createFakeEvent({ content: processedContent, tags: emojiTags })} event={createFakeEvent({ content: processedContent, tags: emojiTags })}
className="pointer-events-none h-full" className="pointer-events-none h-full"
mustLoadMedia
/> />
</Card> </Card>
) )

View File

@@ -7,10 +7,12 @@ import { useTranslation } from 'react-i18next'
export default function YoutubeEmbeddedPlayer({ export default function YoutubeEmbeddedPlayer({
url, url,
className className,
mustLoad = false
}: { }: {
url: string url: string
className?: string className?: string
mustLoad?: boolean
}) { }) {
const { t } = useTranslation() const { t } = useTranslation()
const { autoLoadMedia } = useContentPolicy() const { autoLoadMedia } = useContentPolicy()
@@ -29,7 +31,7 @@ export default function YoutubeEmbeddedPlayer({
}, [autoLoadMedia]) }, [autoLoadMedia])
useEffect(() => { useEffect(() => {
if (!videoId || !containerRef.current || !display) return if (!videoId || !containerRef.current || (!mustLoad && !display)) return
if (!window.YT) { if (!window.YT) {
const script = document.createElement('script') const script = document.createElement('script')
@@ -75,9 +77,9 @@ export default function YoutubeEmbeddedPlayer({
playerRef.current.destroy() playerRef.current.destroy()
} }
} }
}, [videoId, display]) }, [videoId, display, mustLoad])
if (!display) { if (!mustLoad && !display) {
return ( return (
<div <div
className="text-primary hover:underline truncate w-fit cursor-pointer" className="text-primary hover:underline truncate w-fit cursor-pointer"