template_0205

This commit is contained in:
Sofio
2026-02-05 13:16:05 +08:00
commit d93e4d9c9f
197 changed files with 52810 additions and 0 deletions

View File

@@ -0,0 +1,71 @@
import { StyleProp, TextStyle, View, ViewStyle } from "react-native"
import { Image, ImageStyle } from "expo-image"
import { useAppTheme } from "@/theme/context"
import type { ThemedStyle } from "@/theme/types"
import { s } from "@/utils/responsive"
import { Text } from "./Text"
export interface AvatarProps {
/**
* The image URI to display
*/
uri?: string | null
/**
* Fallback text to display when no image (usually first letter of name)
*/
fallback?: string
/**
* Size of the avatar (width and height)
* @default 80
*/
size?: number
/**
* Optional style override for the container
*/
style?: StyleProp<ViewStyle>
}
/**
* A reusable Avatar component with expo-image for efficient caching.
* Displays an image or a fallback letter when no image is available.
*/
export function Avatar(props: AvatarProps) {
const { uri, fallback = "U", size = s(80), style } = props
const { themed, theme } = useAppTheme()
const borderRadius = size / 2
const fontSize = size * 0.4
if (uri) {
return (
<Image
source={{ uri }}
style={[$image, { width: size, height: size, borderRadius }, style as ImageStyle]}
contentFit="cover"
cachePolicy="memory-disk"
transition={200}
placeholder={{ blurhash: "L6PZfSi_.AyE_3t7t7R**0o#DgR4" }}
/>
)
}
return (
<View style={[themed($placeholder), { width: size, height: size, borderRadius }, style]}>
<Text style={{ color: theme.colors.palette.neutral100, fontSize, fontWeight: "bold" }}>
{fallback.charAt(0).toUpperCase()}
</Text>
</View>
)
}
const $image: ImageStyle = {
backgroundColor: "#e1e1e1",
}
const $placeholder: ThemedStyle<ViewStyle> = ({ colors }) => ({
backgroundColor: colors.tint,
justifyContent: "center",
alignItems: "center",
})