From 00577cd8861bab31814861d0d8d964f923f70538 Mon Sep 17 00:00:00 2001 From: Innei Date: Sat, 7 Oct 2023 11:32:43 +0800 Subject: [PATCH] fix: friend avatar image fallback --- src/app/friends/page.tsx | 4 ++- src/app/says/page.tsx | 9 ++++--- src/components/ui/avatar/Avatar.tsx | 42 ++++++++++++++++++++++------- src/components/ui/tag/Tag.tsx | 7 +++-- 4 files changed, 45 insertions(+), 17 deletions(-) diff --git a/src/app/friends/page.tsx b/src/app/friends/page.tsx index f9ec8cb1b8..d649875f91 100644 --- a/src/app/friends/page.tsx +++ b/src/app/friends/page.tsx @@ -160,12 +160,14 @@ const Card: FC<{ link: LinkModel }> = ({ link }) => { {enter && } {link.name} diff --git a/src/app/says/page.tsx b/src/app/says/page.tsx index a24572e339..5ee10d624f 100644 --- a/src/app/says/page.tsx +++ b/src/app/says/page.tsx @@ -1,7 +1,7 @@ 'use client' import { useInfiniteQuery } from '@tanstack/react-query' -import { memo, useRef } from 'react' +import { memo, useMemo } from 'react' import { m } from 'framer-motion' import Markdown from 'markdown-to-jsx' import type { SayModel } from '@mx-space/api-client' @@ -110,9 +110,10 @@ const Item = memo<{ const hasSource = !!say.source const hasAuthor = !!say.author // const color = colorsMap.get(say.id) - const { dark: darkColors, light: lightColors } = useRef( - getColorScheme(stringToHue(say.id)), - ).current + const { dark: darkColors, light: lightColors } = useMemo( + () => getColorScheme(stringToHue(say.id)), + [say.id], + ) const isDark = useIsDark() return ( diff --git a/src/components/ui/avatar/Avatar.tsx b/src/components/ui/avatar/Avatar.tsx index 98fde5d834..af56d57315 100644 --- a/src/components/ui/avatar/Avatar.tsx +++ b/src/components/ui/avatar/Avatar.tsx @@ -1,8 +1,10 @@ 'use client' -import React, { createElement, useRef, useState } from 'react' +import React, { createElement, useMemo, useRef, useState } from 'react' import type { DetailedHTMLProps, FC, ImgHTMLAttributes } from 'react' +import { useIsDark } from '~/hooks/common/use-is-dark' +import { getColorScheme, stringToHue } from '~/lib/color' import { clsxm } from '~/lib/helper' import { FlexText } from '../text' @@ -16,6 +18,8 @@ interface AvatarProps { shadow?: boolean text?: string + randomColor?: boolean + radius?: number lazy?: boolean } @@ -32,13 +36,25 @@ export const Avatar: FC< imageUrl, text, url, + randomColor, + radius, ...imageProps } = props const avatarRef = useRef(null) const [loaded, setLoaded] = useState(!lazy) + const [loadError, setLoadError] = useState(false) const { className, ...restProps } = wrapperProps + const colors = useMemo( + () => + (text || imageUrl) && + randomColor && + (getColorScheme(stringToHue(text || imageUrl!)) as any), + [text, imageUrl, randomColor], + ) + const isDark = useIsDark() + const bgColor = isDark ? colors?.dark.background : colors?.light.background return (
{createElement( @@ -68,30 +86,34 @@ export const Avatar: FC< } : {}), }, - imageUrl ? ( + imageUrl && !loadError ? (
setLoaded(true)} + onError={() => setLoadError(true)} loading={lazy ? 'lazy' : 'eager'} {...imageProps} className={clsxm( - 'aspect-square rounded-full', + 'aspect-square rounded-full duration-200', imageProps.className, )} />
) : text ? ( -
- +
+
) : null, )} diff --git a/src/components/ui/tag/Tag.tsx b/src/components/ui/tag/Tag.tsx index 7d9f444b06..50c499e5ec 100644 --- a/src/components/ui/tag/Tag.tsx +++ b/src/components/ui/tag/Tag.tsx @@ -1,4 +1,4 @@ -import { memo } from 'react' +import { memo, useMemo } from 'react' import { useIsDark } from '~/hooks/common/use-is-dark' import { addAlphaToHSL, getColorScheme, stringToHue } from '~/lib/color' @@ -12,7 +12,10 @@ export const Tag = memo(function Tag(props: { count?: number }) { const { text, count, passProps, onClick } = props - const { dark, light } = getColorScheme(stringToHue(text)) + const { dark, light } = useMemo( + () => getColorScheme(stringToHue(text)), + [text], + ) const isDark = useIsDark() const bgColor = isDark ? dark.background : light.background