feat(profile): avatar presets, upload, nickname editing
- FastAPI: preset assets 01–08, GET list/static, PUT /me/avatar/preset, safer uploaded-avatar path validation, preset_avatars + HTTP tests. - Expo: personal-info (library + presets), profile tab avatar, resolveApiMediaUrl, auth hooks cache sync, Web multipart helper, partial-save messaging + profile i18n. - Includes existing edits to conversation screen and voice use-player. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { router } from 'expo-router';
|
||||
import { Image } from 'expo-image';
|
||||
import React from 'react';
|
||||
import { Pressable, ScrollView, View } from 'react-native';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
@@ -21,6 +22,7 @@ import {
|
||||
import { Icon } from '@/components/ui/icon';
|
||||
import { Switch } from '@/components/ui/switch';
|
||||
import { Text } from '@/components/ui/text';
|
||||
import { resolveApiMediaUrl } from '@/core/api/media-url';
|
||||
import { useAppSettings } from '@/hooks/use-app-settings';
|
||||
import { useSession, useLogout } from '@/features/auth/hooks';
|
||||
import { useCurrentPlan } from '@/features/profile/hooks';
|
||||
@@ -181,6 +183,8 @@ export default function ProfileScreen() {
|
||||
themeOptions.find((o) => o.value === themeName)?.label ??
|
||||
tApp('theme.default');
|
||||
|
||||
const avatarUri = resolveApiMediaUrl(user?.avatar_url ?? null);
|
||||
|
||||
return (
|
||||
<ScrollView
|
||||
contentInsetAdjustmentBehavior="automatic"
|
||||
@@ -191,10 +195,19 @@ export default function ProfileScreen() {
|
||||
<View className="items-center gap-4 py-8">
|
||||
<View className="relative">
|
||||
<View
|
||||
className="h-24 w-24 items-center justify-center rounded-full bg-muted"
|
||||
className="h-24 w-24 items-center justify-center overflow-hidden rounded-full bg-muted"
|
||||
style={{ borderCurve: 'continuous' }}
|
||||
>
|
||||
<Icon as={User} className="text-muted-foreground" size={40} />
|
||||
{avatarUri ? (
|
||||
<Image
|
||||
source={{ uri: avatarUri }}
|
||||
style={{ width: '100%', height: '100%' }}
|
||||
contentFit="cover"
|
||||
accessibilityIgnoresInvertColors
|
||||
/>
|
||||
) : (
|
||||
<Icon as={User} className="text-muted-foreground" size={40} />
|
||||
)}
|
||||
</View>
|
||||
<Pressable
|
||||
className="absolute bottom-0 right-0 h-9 w-9 items-center justify-center rounded-full border-2 border-background bg-primary"
|
||||
|
||||
Reference in New Issue
Block a user