From 6ee48ffb9d628a04c487b73b222be76241ff3ec4 Mon Sep 17 00:00:00 2001 From: Mohamed Bassem Date: Mon, 29 Dec 2025 10:23:36 +0200 Subject: feat(mobile): make the settings menu look more native (#2307) * feat(mobile): make the settings menu look more native * more fixes * review comments --- apps/mobile/components/ui/Avatar.tsx | 88 ++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 apps/mobile/components/ui/Avatar.tsx (limited to 'apps/mobile/components/ui/Avatar.tsx') diff --git a/apps/mobile/components/ui/Avatar.tsx b/apps/mobile/components/ui/Avatar.tsx new file mode 100644 index 00000000..923c634e --- /dev/null +++ b/apps/mobile/components/ui/Avatar.tsx @@ -0,0 +1,88 @@ +import * as React from "react"; +import { Image, View } from "react-native"; +import { Text } from "@/components/ui/Text"; +import { useAssetUrl } from "@/lib/hooks"; +import { cn } from "@/lib/utils"; + +interface AvatarProps { + image?: string | null; + name?: string | null; + size?: number; + className?: string; + imageClassName?: string; + fallbackClassName?: string; +} + +function isExternalUrl(url: string) { + return url.startsWith("http://") || url.startsWith("https://"); +} + +export function Avatar({ + image, + name, + size = 40, + className, + imageClassName, + fallbackClassName, +}: AvatarProps) { + const [imageError, setImageError] = React.useState(false); + const assetUrl = useAssetUrl(image ?? ""); + + const imageUrl = React.useMemo(() => { + if (!image) return null; + return isExternalUrl(image) + ? { + uri: image, + } + : assetUrl; + }, [image]); + + React.useEffect(() => { + setImageError(false); + }, [image]); + + const initials = React.useMemo(() => { + if (!name) return "U"; + return name.charAt(0).toUpperCase(); + }, [name]); + + const showFallback = !imageUrl || imageError; + + return ( + + {showFallback ? ( + + + {initials} + + + ) : ( + setImageError(true)} + /> + )} + + ); +} -- cgit v1.2.3-70-g09d2