From 314c363e5ca69a50626650ade8968feec583e5ce Mon Sep 17 00:00:00 2001 From: Mohamed Bassem Date: Wed, 24 Dec 2025 12:18:08 +0200 Subject: feat: add support for user avatars (#2296) * feat: add support for user avatars * more fixes * more fixes * more fixes * more fixes --- apps/web/components/ui/user-avatar.tsx | 52 ++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 apps/web/components/ui/user-avatar.tsx (limited to 'apps/web/components/ui/user-avatar.tsx') diff --git a/apps/web/components/ui/user-avatar.tsx b/apps/web/components/ui/user-avatar.tsx new file mode 100644 index 00000000..4ebb6ec3 --- /dev/null +++ b/apps/web/components/ui/user-avatar.tsx @@ -0,0 +1,52 @@ +"use client"; + +import { useMemo } from "react"; +import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; +import { cn } from "@/lib/utils"; + +import { getAssetUrl } from "@karakeep/shared/utils/assetUtils"; + +interface UserAvatarProps { + image?: string | null; + name?: string | null; + className?: string; + imgClassName?: string; + fallbackClassName?: string; + fallback?: React.ReactNode; +} + +const isExternalUrl = (value: string) => + value.startsWith("http://") || value.startsWith("https://"); + +export function UserAvatar({ + image, + name, + className, + imgClassName, + fallbackClassName, + fallback, +}: UserAvatarProps) { + const avatarUrl = useMemo(() => { + if (!image) { + return null; + } + return isExternalUrl(image) ? image : getAssetUrl(image); + }, [image]); + + const fallbackContent = fallback ?? name?.charAt(0) ?? "U"; + + return ( + + {avatarUrl && ( + + )} + + {fallbackContent} + + + ); +} -- cgit v1.2.3-70-g09d2