fix: some 🐛
This commit is contained in:
@@ -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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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" />
|
||||||
|
|||||||
Reference in New Issue
Block a user