diff --git a/icons/UserAvatar.tsx b/icons/UserAvatar.tsx
new file mode 100644
index 0000000..ab39982
--- /dev/null
+++ b/icons/UserAvatar.tsx
@@ -0,0 +1,484 @@
+// https://raw.githubusercontent.com/bluesky-social/social-app/refs/heads/main/src/view/com/util/UserAvatar.tsx
+import React, {memo, useMemo} from 'react'
+import {Image, Pressable, StyleSheet, View} from 'react-native'
+import {Image as RNImage} from 'react-native-image-crop-picker'
+import Svg, {Circle, Path, Rect} from 'react-native-svg'
+import {AppBskyActorDefs, ModerationUI} from '@atproto/api'
+import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
+import {msg, Trans} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
+import {useQueryClient} from '@tanstack/react-query'
+
+import {usePalette} from '#/lib/hooks/usePalette'
+import {
+ useCameraPermission,
+ usePhotoLibraryPermission,
+} from '#/lib/hooks/usePermissions'
+import {makeProfileLink} from '#/lib/routes/links'
+import {colors} from '#/lib/styles'
+import {logger} from '#/logger'
+import {isAndroid, isNative, isWeb} from '#/platform/detection'
+import {precacheProfile} from '#/state/queries/profile'
+import {HighPriorityImage} from '#/view/com/util/images/Image'
+import {tokens, useTheme} from '#/alf'
+import {useSheetWrapper} from '#/components/Dialog/sheet-wrapper'
+import {
+ Camera_Filled_Stroke2_Corner0_Rounded as CameraFilled,
+ Camera_Stroke2_Corner0_Rounded as Camera,
+} from '#/components/icons/Camera'
+import {StreamingLive_Stroke2_Corner0_Rounded as Library} from '#/components/icons/StreamingLive'
+import {Trash_Stroke2_Corner0_Rounded as Trash} from '#/components/icons/Trash'
+import {Link} from '#/components/Link'
+import {MediaInsetBorder} from '#/components/MediaInsetBorder'
+import * as Menu from '#/components/Menu'
+import {ProfileHoverCard} from '#/components/ProfileHoverCard'
+import {openCamera, openCropper, openPicker} from '../../../lib/media/picker'
+
+export type UserAvatarType = 'user' | 'algo' | 'list' | 'labeler'
+
+interface BaseUserAvatarProps {
+ type?: UserAvatarType
+ shape?: 'circle' | 'square'
+ size: number
+ avatar?: string | null
+}
+
+interface UserAvatarProps extends BaseUserAvatarProps {
+ moderation?: ModerationUI
+ usePlainRNImage?: boolean
+ onLoad?: () => void
+}
+
+interface EditableUserAvatarProps extends BaseUserAvatarProps {
+ onSelectNewAvatar: (img: RNImage | null) => void
+}
+
+interface PreviewableUserAvatarProps extends BaseUserAvatarProps {
+ moderation?: ModerationUI
+ profile: AppBskyActorDefs.ProfileViewBasic
+ disableHoverCard?: boolean
+ onBeforePress?: () => void
+}
+
+const BLUR_AMOUNT = isWeb ? 5 : 100
+
+let DefaultAvatar = ({
+ type,
+ shape: overrideShape,
+ size,
+}: {
+ type: UserAvatarType
+ shape?: 'square' | 'circle'
+ size: number
+}): React.ReactNode => {
+ const finalShape = overrideShape ?? (type === 'user' ? 'circle' : 'square')
+ if (type === 'algo') {
+ // TODO: shape=circle
+ // Font Awesome Pro 6.4.0 by @fontawesome -https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc.
+ return (
+
+ )
+ }
+ if (type === 'list') {
+ // TODO: shape=circle
+ // Font Awesome Pro 6.4.0 by @fontawesome -https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc.
+ return (
+
+ )
+ }
+ if (type === 'labeler') {
+ return (
+
+ )
+ }
+ // TODO: shape=square
+ return (
+
+ )
+}
+DefaultAvatar = memo(DefaultAvatar)
+export {DefaultAvatar}
+
+let UserAvatar = ({
+ type = 'user',
+ shape: overrideShape,
+ size,
+ avatar,
+ moderation,
+ usePlainRNImage = false,
+ onLoad,
+}: UserAvatarProps): React.ReactNode => {
+ const pal = usePalette('default')
+ const backgroundColor = pal.colors.backgroundLight
+ const finalShape = overrideShape ?? (type === 'user' ? 'circle' : 'square')
+
+ const aviStyle = useMemo(() => {
+ if (finalShape === 'square') {
+ return {
+ width: size,
+ height: size,
+ borderRadius: size > 32 ? 8 : 3,
+ backgroundColor,
+ }
+ }
+ return {
+ width: size,
+ height: size,
+ borderRadius: Math.floor(size / 2),
+ backgroundColor,
+ }
+ }, [finalShape, size, backgroundColor])
+
+ const alert = useMemo(() => {
+ if (!moderation?.alert) {
+ return null
+ }
+ return (
+