fix: some 🐛

This commit is contained in:
codytseng
2025-01-08 21:30:29 +08:00
parent dacaa4a75d
commit fe815bcce5
2 changed files with 32 additions and 32 deletions

View File

@@ -2,10 +2,10 @@ import { Skeleton } from '@/components/ui/skeleton'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
import { TImageInfo } from '@/types' import { TImageInfo } from '@/types'
import { decode } from 'blurhash' import { decode } from 'blurhash'
import { HTMLAttributes, useEffect, useMemo, useState } from 'react' import { HTMLAttributes, useEffect, useState } from 'react'
export default function Image({ export default function Image({
image: { url, blurHash, dim }, image: { url, blurHash },
alt, alt,
className = '', className = '',
classNames = {}, classNames = {},
@@ -20,26 +20,19 @@ export default function Image({
const [isLoading, setIsLoading] = useState(true) const [isLoading, setIsLoading] = useState(true)
const [displayBlurHash, setDisplayBlurHash] = useState(true) const [displayBlurHash, setDisplayBlurHash] = useState(true)
const [blurDataUrl, setBlurDataUrl] = useState<string | null>(null) const [blurDataUrl, setBlurDataUrl] = useState<string | null>(null)
const { width, height } = useMemo<{ width?: number; height?: number }>(() => {
if (dim) {
return dim
}
if (blurHash) {
const { numX, numY } = decodeBlurHashSize(blurHash)
return { width: numX * 10, height: numY * 10 }
}
return {}
}, [dim])
useEffect(() => { useEffect(() => {
if (blurHash) { if (blurHash) {
const pixels = decode(blurHash, 32, 32) const { numX, numY } = decodeBlurHashSize(blurHash)
const width = numX * 5
const height = numY * 5
const pixels = decode(blurHash, width, height)
const canvas = document.createElement('canvas') const canvas = document.createElement('canvas')
canvas.width = 32 canvas.width = width
canvas.height = 32 canvas.height = height
const ctx = canvas.getContext('2d') const ctx = canvas.getContext('2d')
if (ctx) { if (ctx) {
const imageData = ctx.createImageData(32, 32) const imageData = ctx.createImageData(width, height)
imageData.data.set(pixels) imageData.data.set(pixels)
ctx.putImageData(imageData, 0, 0) ctx.putImageData(imageData, 0, 0)
setBlurDataUrl(canvas.toDataURL()) setBlurDataUrl(canvas.toDataURL())
@@ -54,22 +47,20 @@ export default function Image({
src={url} src={url}
alt={alt} alt={alt}
className={cn( className={cn(
'object-cover transition-opacity duration-700', 'object-cover transition-opacity duration-300',
isLoading ? 'opacity-0' : 'opacity-100', isLoading ? 'opacity-0' : 'opacity-100',
className className
)} )}
onLoad={() => { onLoad={() => {
setIsLoading(false) setIsLoading(false)
setTimeout(() => setDisplayBlurHash(false), 1000) setTimeout(() => setDisplayBlurHash(false), 500)
}} }}
/> />
{displayBlurHash && blurDataUrl && ( {displayBlurHash && blurDataUrl && (
<img <img
src={blurDataUrl} src={blurDataUrl}
className={cn('absolute inset-0 object-cover -z-10', className)} className={cn('absolute inset-0 object-cover w-full h-full -z-10', className)}
alt={alt} alt={alt}
width={width}
height={height}
/> />
)} )}
</div> </div>
@@ -78,15 +69,8 @@ export default function Image({
const DIGITS = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz#$%*+,-.:;=?@[]^_{|}~' const DIGITS = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz#$%*+,-.:;=?@[]^_{|}~'
function decodeBlurHashSize(blurHash: string) { function decodeBlurHashSize(blurHash: string) {
const sizeFlag = blurHash.charAt(0) const sizeValue = DIGITS.indexOf(blurHash[0])
const numY = (sizeValue / 9 + 1) | 0
const sizeValue = DIGITS.indexOf(sizeFlag)
const numY = Math.floor(sizeValue / 9) + 1
const numX = (sizeValue % 9) + 1 const numX = (sizeValue % 9) + 1
return { numX, numY }
return {
numX,
numY
}
} }

View File

@@ -6,6 +6,13 @@ import { Event } from 'nostr-tools'
import Image from '../Image' import Image from '../Image'
import UserAvatar from '../UserAvatar' import UserAvatar from '../UserAvatar'
import Username from '../Username' import Username from '../Username'
import { useMemo } from 'react'
import {
embedded,
embeddedHashtagRenderer,
embeddedNostrNpubRenderer,
embeddedNostrProfileRenderer
} from '../Embedded'
export default function PictureNoteCard({ export default function PictureNoteCard({
event, event,
@@ -16,12 +23,21 @@ export default function PictureNoteCard({
}) { }) {
const { push } = useSecondaryPage() const { push } = useSecondaryPage()
const firstImage = extractFirstPictureFromPictureEvent(event) const firstImage = extractFirstPictureFromPictureEvent(event)
const content = useMemo(
() =>
embedded(event.content, [
embeddedNostrNpubRenderer,
embeddedNostrProfileRenderer,
embeddedHashtagRenderer
]),
[event]
)
if (!firstImage) return null if (!firstImage) return null
return ( return (
<div className={cn('space-y-1 cursor-pointer', className)} onClick={() => push(toNote(event))}> <div className={cn('space-y-1 cursor-pointer', className)} onClick={() => push(toNote(event))}>
<Image className="rounded-lg w-full aspect-[6/8]" image={firstImage} /> <Image className="rounded-lg w-full aspect-[6/8]" image={firstImage} />
<div className="line-clamp-2 px-2">{event.content}</div> <div className="line-clamp-2 px-2">{content}</div>
<div className="flex items-center gap-2 px-2"> <div className="flex items-center gap-2 px-2">
<UserAvatar userId={event.pubkey} size="xSmall" /> <UserAvatar userId={event.pubkey} size="xSmall" />
<Username userId={event.pubkey} className="text-sm text-muted-foreground truncate" /> <Username userId={event.pubkey} className="text-sm text-muted-foreground truncate" />