fix: bug
This commit is contained in:
132
components/user/balance-card.tsx
Normal file
132
components/user/balance-card.tsx
Normal file
@@ -0,0 +1,132 @@
|
||||
import React from 'react';
|
||||
import { StyleSheet, TouchableOpacity, View } from 'react-native';
|
||||
|
||||
import { ThemedView } from '@/components/themed-view';
|
||||
import { ThemedText } from '@/components/themed-text';
|
||||
import { useThemeColor } from '@/hooks/use-theme-color';
|
||||
import { IconSymbol } from '@/components/ui/icon-symbol';
|
||||
|
||||
interface BalanceCardProps {
|
||||
balance: number;
|
||||
onRecharge: () => void;
|
||||
onHistory?: () => void;
|
||||
}
|
||||
|
||||
export function BalanceCard({ balance, onRecharge, onHistory }: BalanceCardProps) {
|
||||
const tintColor = useThemeColor({}, 'tint');
|
||||
const cardColor = useThemeColor({}, 'card');
|
||||
const borderColor = useThemeColor({}, 'cardBorder');
|
||||
|
||||
return (
|
||||
<ThemedView style={styles.container}>
|
||||
<View style={styles.header}>
|
||||
<View style={styles.titleContainer}>
|
||||
<IconSymbol name="dollarsign.circle" size={24} color={tintColor} />
|
||||
<ThemedText style={styles.title}>账户余额</ThemedText>
|
||||
</View>
|
||||
{onHistory && (
|
||||
<TouchableOpacity onPress={onHistory} style={styles.historyButton}>
|
||||
<ThemedText style={[styles.historyText, { color: tintColor }]}>
|
||||
消费记录
|
||||
</ThemedText>
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
</View>
|
||||
|
||||
<View style={styles.balanceContainer}>
|
||||
<ThemedText style={styles.currency}>¥</ThemedText>
|
||||
<ThemedText style={styles.balance}>{balance.toFixed(2)}</ThemedText>
|
||||
</View>
|
||||
|
||||
<TouchableOpacity
|
||||
style={[styles.rechargeButton, { backgroundColor: tintColor }]}
|
||||
onPress={onRecharge}
|
||||
activeOpacity={0.8}
|
||||
>
|
||||
<IconSymbol name="plus.circle.fill" size={20} color="white" />
|
||||
<ThemedText style={styles.rechargeText}>充值</ThemedText>
|
||||
</TouchableOpacity>
|
||||
|
||||
<View style={styles.tips}>
|
||||
<IconSymbol name="info.circle" size={14} color="#999" />
|
||||
<ThemedText style={styles.tipsText}>
|
||||
余额用于支付生成内容的消费
|
||||
</ThemedText>
|
||||
</View>
|
||||
</ThemedView>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
padding: 20,
|
||||
},
|
||||
header: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
marginBottom: 16,
|
||||
},
|
||||
titleContainer: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
gap: 8,
|
||||
},
|
||||
title: {
|
||||
fontSize: 16,
|
||||
fontWeight: '600',
|
||||
},
|
||||
historyButton: {
|
||||
paddingHorizontal: 12,
|
||||
paddingVertical: 6,
|
||||
},
|
||||
historyText: {
|
||||
fontSize: 14,
|
||||
fontWeight: '500',
|
||||
},
|
||||
balanceContainer: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'flex-end',
|
||||
justifyContent: 'center',
|
||||
marginVertical: 24,
|
||||
},
|
||||
currency: {
|
||||
fontSize: 24,
|
||||
fontWeight: '600',
|
||||
marginBottom: 4,
|
||||
},
|
||||
balance: {
|
||||
fontSize: 48,
|
||||
fontWeight: 'bold',
|
||||
lineHeight: 48,
|
||||
},
|
||||
rechargeButton: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
paddingVertical: 12,
|
||||
paddingHorizontal: 24,
|
||||
borderRadius: 24,
|
||||
gap: 8,
|
||||
alignSelf: 'center',
|
||||
},
|
||||
rechargeText: {
|
||||
color: 'white',
|
||||
fontSize: 16,
|
||||
fontWeight: '600',
|
||||
},
|
||||
tips: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
gap: 6,
|
||||
marginTop: 16,
|
||||
paddingTop: 16,
|
||||
borderTopWidth: 1,
|
||||
borderTopColor: '#f0f0f0',
|
||||
},
|
||||
tipsText: {
|
||||
fontSize: 12,
|
||||
color: '#666',
|
||||
flex: 1,
|
||||
},
|
||||
});
|
||||
319
components/user/generation-records.tsx
Normal file
319
components/user/generation-records.tsx
Normal file
@@ -0,0 +1,319 @@
|
||||
import React, { useState } from 'react';
|
||||
import { StyleSheet, ScrollView, TouchableOpacity, RefreshControl, Alert, ActivityIndicator } from 'react-native';
|
||||
import { router } from 'expo-router';
|
||||
|
||||
import { ThemedView } from '@/components/themed-view';
|
||||
import { ThemedText } from '@/components/themed-text';
|
||||
import { useThemeColor } from '@/hooks/use-theme-color';
|
||||
import { IconSymbol } from '@/components/ui/icon-symbol';
|
||||
import { GenerationRecord } from '@/lib/auth/types';
|
||||
|
||||
interface GenerationRecordsProps {
|
||||
userId?: string;
|
||||
}
|
||||
|
||||
const mockRecords: GenerationRecord[] = [
|
||||
{
|
||||
id: '1',
|
||||
userId: 'user1',
|
||||
type: 'image',
|
||||
title: '夏日风景插画',
|
||||
description: '生成了一张充满夏日气息的风景插画',
|
||||
thumbnail: undefined,
|
||||
mediaUrl: undefined,
|
||||
status: 'completed',
|
||||
cost: 0.5,
|
||||
createdAt: new Date('2024-01-15T10:30:00'),
|
||||
updatedAt: new Date('2024-01-15T10:35:00'),
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
userId: 'user1',
|
||||
type: 'video',
|
||||
title: '产品介绍视频',
|
||||
description: '为新产品制作了一个介绍视频',
|
||||
thumbnail: undefined,
|
||||
mediaUrl: undefined,
|
||||
status: 'pending',
|
||||
cost: 2.0,
|
||||
createdAt: new Date('2024-01-14T15:20:00'),
|
||||
updatedAt: new Date('2024-01-14T15:20:00'),
|
||||
},
|
||||
];
|
||||
|
||||
export function GenerationRecords({ userId }: GenerationRecordsProps) {
|
||||
const [records, setRecords] = useState<GenerationRecord[]>(mockRecords);
|
||||
const [refreshing, setRefreshing] = useState(false);
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
const tintColor = useThemeColor({}, 'tint');
|
||||
const textColor = useThemeColor({}, 'text');
|
||||
|
||||
const getTypeIcon = (type: string) => {
|
||||
switch (type) {
|
||||
case 'image':
|
||||
return 'photo';
|
||||
case 'video':
|
||||
return 'video';
|
||||
case 'text':
|
||||
return 'doc.text';
|
||||
default:
|
||||
return 'doc';
|
||||
}
|
||||
};
|
||||
|
||||
const getStatusColor = (status: string) => {
|
||||
switch (status) {
|
||||
case 'completed':
|
||||
return '#34C759';
|
||||
case 'pending':
|
||||
return '#FF9500';
|
||||
case 'failed':
|
||||
return '#FF3B30';
|
||||
default:
|
||||
return '#999';
|
||||
}
|
||||
};
|
||||
|
||||
const getStatusText = (status: string) => {
|
||||
switch (status) {
|
||||
case 'completed':
|
||||
return '已完成';
|
||||
case 'pending':
|
||||
return '生成中';
|
||||
case 'failed':
|
||||
return '失败';
|
||||
default:
|
||||
return '未知';
|
||||
}
|
||||
};
|
||||
|
||||
const handleRefresh = async () => {
|
||||
setRefreshing(true);
|
||||
try {
|
||||
// TODO: 实现刷新逻辑
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
} catch (error) {
|
||||
console.error('刷新失败:', error);
|
||||
} finally {
|
||||
setRefreshing(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleDelete = (recordId: string) => {
|
||||
Alert.alert(
|
||||
'删除记录',
|
||||
'确定要删除这条生成记录吗?此操作无法撤销。',
|
||||
[
|
||||
{ text: '取消', style: 'cancel' },
|
||||
{
|
||||
text: '删除',
|
||||
style: 'destructive',
|
||||
onPress: () => {
|
||||
setRecords(prev => prev.filter(record => record.id !== recordId));
|
||||
}
|
||||
}
|
||||
]
|
||||
);
|
||||
};
|
||||
|
||||
const handlePress = (record: GenerationRecord) => {
|
||||
if (record.status === 'completed') {
|
||||
// TODO: 跳转到详情页面
|
||||
console.log('查看记录详情:', record.id);
|
||||
}
|
||||
};
|
||||
|
||||
if (records.length === 0 && !loading) {
|
||||
return (
|
||||
<ThemedView style={styles.container}>
|
||||
<ThemedView style={styles.header}>
|
||||
<IconSymbol name="clock" size={20} color={tintColor} />
|
||||
<ThemedText style={styles.title}>生成记录</ThemedText>
|
||||
</ThemedView>
|
||||
<ThemedView style={styles.emptyContainer}>
|
||||
<IconSymbol name="doc.text" size={48} color="#ccc" />
|
||||
<ThemedText style={styles.emptyText}>暂无生成记录</ThemedText>
|
||||
<ThemedText style={styles.emptySubText}>开始创建你的第一个作品吧</ThemedText>
|
||||
</ThemedView>
|
||||
</ThemedView>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<ThemedView style={styles.container}>
|
||||
<ThemedView style={styles.header}>
|
||||
<IconSymbol name="clock" size={20} color={tintColor} />
|
||||
<ThemedText style={styles.title}>生成记录</ThemedText>
|
||||
<ThemedText style={styles.count}>({records.length})</ThemedText>
|
||||
</ThemedView>
|
||||
|
||||
<ScrollView
|
||||
style={styles.scrollView}
|
||||
refreshControl={
|
||||
<RefreshControl refreshing={refreshing} onRefresh={handleRefresh} />
|
||||
}
|
||||
>
|
||||
{records.map((record) => (
|
||||
<TouchableOpacity
|
||||
key={record.id}
|
||||
style={styles.recordItem}
|
||||
onPress={() => handlePress(record)}
|
||||
activeOpacity={0.7}
|
||||
>
|
||||
<ThemedView style={styles.recordLeft}>
|
||||
<ThemedView style={styles.typeIcon}>
|
||||
<IconSymbol
|
||||
name={getTypeIcon(record.type)}
|
||||
size={20}
|
||||
color={tintColor}
|
||||
/>
|
||||
</ThemedView>
|
||||
<ThemedView style={styles.recordContent}>
|
||||
<ThemedText style={styles.recordTitle}>{record.title}</ThemedText>
|
||||
{record.description && (
|
||||
<ThemedText style={styles.recordDescription} numberOfLines={2}>
|
||||
{record.description}
|
||||
</ThemedText>
|
||||
)}
|
||||
<ThemedView style={styles.recordMeta}>
|
||||
<ThemedText style={styles.recordTime}>
|
||||
{new Date(record.createdAt).toLocaleDateString()}
|
||||
</ThemedText>
|
||||
<ThemedText style={styles.recordCost}>¥{record.cost}</ThemedText>
|
||||
</ThemedView>
|
||||
</ThemedView>
|
||||
</ThemedView>
|
||||
|
||||
<ThemedView style={styles.recordRight}>
|
||||
<ThemedView
|
||||
style={[
|
||||
styles.statusBadge,
|
||||
{ backgroundColor: getStatusColor(record.status) + '20' }
|
||||
]}
|
||||
>
|
||||
<ThemedText
|
||||
style={[
|
||||
styles.statusText,
|
||||
{ color: getStatusColor(record.status) }
|
||||
]}
|
||||
>
|
||||
{getStatusText(record.status)}
|
||||
</ThemedText>
|
||||
</ThemedView>
|
||||
<TouchableOpacity
|
||||
style={styles.deleteButton}
|
||||
onPress={() => handleDelete(record.id)}
|
||||
>
|
||||
<IconSymbol name="trash" size={16} color="#FF3B30" />
|
||||
</TouchableOpacity>
|
||||
</ThemedView>
|
||||
</TouchableOpacity>
|
||||
))}
|
||||
</ScrollView>
|
||||
</ThemedView>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
},
|
||||
header: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
gap: 8,
|
||||
marginBottom: 16,
|
||||
},
|
||||
title: {
|
||||
fontSize: 18,
|
||||
fontWeight: '600',
|
||||
},
|
||||
count: {
|
||||
fontSize: 14,
|
||||
color: '#666',
|
||||
},
|
||||
scrollView: {
|
||||
flex: 1,
|
||||
},
|
||||
recordItem: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
paddingVertical: 12,
|
||||
borderBottomWidth: 1,
|
||||
borderBottomColor: '#f0f0f0',
|
||||
},
|
||||
recordLeft: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
flex: 1,
|
||||
gap: 12,
|
||||
},
|
||||
typeIcon: {
|
||||
width: 40,
|
||||
height: 40,
|
||||
borderRadius: 8,
|
||||
backgroundColor: '#f0f0f0',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
recordContent: {
|
||||
flex: 1,
|
||||
},
|
||||
recordTitle: {
|
||||
fontSize: 16,
|
||||
fontWeight: '600',
|
||||
marginBottom: 4,
|
||||
},
|
||||
recordDescription: {
|
||||
fontSize: 14,
|
||||
color: '#666',
|
||||
marginBottom: 4,
|
||||
},
|
||||
recordMeta: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
},
|
||||
recordTime: {
|
||||
fontSize: 12,
|
||||
color: '#999',
|
||||
},
|
||||
recordCost: {
|
||||
fontSize: 12,
|
||||
color: '#666',
|
||||
fontWeight: '500',
|
||||
},
|
||||
recordRight: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
gap: 8,
|
||||
},
|
||||
statusBadge: {
|
||||
paddingHorizontal: 8,
|
||||
paddingVertical: 4,
|
||||
borderRadius: 12,
|
||||
},
|
||||
statusText: {
|
||||
fontSize: 12,
|
||||
fontWeight: '500',
|
||||
},
|
||||
deleteButton: {
|
||||
padding: 8,
|
||||
},
|
||||
emptyContainer: {
|
||||
alignItems: 'center',
|
||||
paddingVertical: 40,
|
||||
},
|
||||
emptyText: {
|
||||
fontSize: 16,
|
||||
fontWeight: '600',
|
||||
marginTop: 16,
|
||||
marginBottom: 8,
|
||||
},
|
||||
emptySubText: {
|
||||
fontSize: 14,
|
||||
color: '#666',
|
||||
},
|
||||
});
|
||||
165
components/user/settings-list.tsx
Normal file
165
components/user/settings-list.tsx
Normal file
@@ -0,0 +1,165 @@
|
||||
import React from 'react';
|
||||
import { StyleSheet, TouchableOpacity, Alert } from 'react-native';
|
||||
import { router } from 'expo-router';
|
||||
|
||||
import { ThemedView } from '@/components/themed-view';
|
||||
import { ThemedText } from '@/components/themed-text';
|
||||
import { useThemeColor } from '@/hooks/use-theme-color';
|
||||
import { IconSymbol } from '@/components/ui/icon-symbol';
|
||||
|
||||
interface SettingsListProps {
|
||||
onLogout: () => void;
|
||||
}
|
||||
|
||||
interface SettingItem {
|
||||
id: string;
|
||||
title: string;
|
||||
icon: string;
|
||||
onPress?: () => void;
|
||||
destructive?: boolean;
|
||||
}
|
||||
|
||||
export function SettingsList({ onLogout }: SettingsListProps) {
|
||||
const tintColor = useThemeColor({}, 'tint');
|
||||
const textColor = useThemeColor({}, 'text');
|
||||
const destructiveColor = '#FF3B30';
|
||||
|
||||
const settings: SettingItem[] = [
|
||||
{
|
||||
id: 'account',
|
||||
title: '账户设置',
|
||||
icon: 'person.circle',
|
||||
onPress: () => router.push('/settings/account'),
|
||||
},
|
||||
{
|
||||
id: 'notification',
|
||||
title: '通知设置',
|
||||
icon: 'bell',
|
||||
onPress: () => router.push('/settings/notification'),
|
||||
},
|
||||
{
|
||||
id: 'privacy',
|
||||
title: '隐私设置',
|
||||
icon: 'lock',
|
||||
onPress: () => router.push('/settings/privacy'),
|
||||
},
|
||||
{
|
||||
id: 'about',
|
||||
title: '关于我们',
|
||||
icon: 'info.circle',
|
||||
onPress: () => router.push('/settings/about'),
|
||||
},
|
||||
{
|
||||
id: 'feedback',
|
||||
title: '意见反馈',
|
||||
icon: 'exclamationmark.bubble',
|
||||
onPress: () => router.push('/settings/feedback'),
|
||||
},
|
||||
{
|
||||
id: 'logout',
|
||||
title: '退出登录',
|
||||
icon: 'arrow.right.square',
|
||||
onPress: onLogout,
|
||||
destructive: true,
|
||||
},
|
||||
];
|
||||
|
||||
const handleSettingPress = (item: SettingItem) => {
|
||||
if (item.onPress) {
|
||||
if (item.destructive) {
|
||||
Alert.alert(
|
||||
'退出登录',
|
||||
'确定要退出登录吗?',
|
||||
[
|
||||
{ text: '取消', style: 'cancel' },
|
||||
{
|
||||
text: '确定',
|
||||
style: 'destructive',
|
||||
onPress: item.onPress,
|
||||
}
|
||||
]
|
||||
);
|
||||
} else {
|
||||
item.onPress();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<ThemedView style={styles.container}>
|
||||
<ThemedView style={styles.header}>
|
||||
<IconSymbol name="gearshape" size={20} color={tintColor} />
|
||||
<ThemedText style={styles.title}>设置</ThemedText>
|
||||
</ThemedView>
|
||||
|
||||
<ThemedView style={styles.settingsList}>
|
||||
{settings.map((item) => (
|
||||
<TouchableOpacity
|
||||
key={item.id}
|
||||
style={styles.settingItem}
|
||||
onPress={() => handleSettingPress(item)}
|
||||
activeOpacity={0.7}
|
||||
>
|
||||
<ThemedView style={styles.settingLeft}>
|
||||
<IconSymbol
|
||||
name={item.icon}
|
||||
size={20}
|
||||
color={item.destructive ? destructiveColor : tintColor}
|
||||
/>
|
||||
<ThemedText
|
||||
style={[
|
||||
styles.settingTitle,
|
||||
{ color: item.destructive ? destructiveColor : textColor }
|
||||
]}
|
||||
>
|
||||
{item.title}
|
||||
</ThemedText>
|
||||
</ThemedView>
|
||||
<IconSymbol
|
||||
name="chevron.right"
|
||||
size={16}
|
||||
color="#ccc"
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
))}
|
||||
</ThemedView>
|
||||
</ThemedView>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
},
|
||||
header: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
gap: 8,
|
||||
marginBottom: 16,
|
||||
},
|
||||
title: {
|
||||
fontSize: 18,
|
||||
fontWeight: '600',
|
||||
},
|
||||
settingsList: {
|
||||
borderRadius: 8,
|
||||
overflow: 'hidden',
|
||||
},
|
||||
settingItem: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
paddingVertical: 16,
|
||||
paddingHorizontal: 4,
|
||||
borderBottomWidth: 1,
|
||||
borderBottomColor: '#f0f0f0',
|
||||
},
|
||||
settingLeft: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
gap: 12,
|
||||
},
|
||||
settingTitle: {
|
||||
fontSize: 16,
|
||||
},
|
||||
});
|
||||
110
components/user/user-avatar.tsx
Normal file
110
components/user/user-avatar.tsx
Normal file
@@ -0,0 +1,110 @@
|
||||
import React from 'react';
|
||||
import { Image, StyleSheet, View } from 'react-native';
|
||||
|
||||
import { ThemedView } from '@/components/themed-view';
|
||||
import { ThemedText } from '@/components/themed-text';
|
||||
import { useThemeColor } from '@/hooks/use-theme-color';
|
||||
|
||||
interface UserAvatarProps {
|
||||
image?: string;
|
||||
name: string;
|
||||
size?: number;
|
||||
showBorder?: boolean;
|
||||
}
|
||||
|
||||
export function UserAvatar({
|
||||
image,
|
||||
name,
|
||||
size = 40,
|
||||
showBorder = true
|
||||
}: UserAvatarProps) {
|
||||
const borderColor = useThemeColor({}, 'cardBorder');
|
||||
const placeholderColor = useThemeColor({}, 'imagePlaceholder');
|
||||
const textColor = useThemeColor({}, 'text');
|
||||
|
||||
const avatarSize = size;
|
||||
const borderRadius = avatarSize / 2;
|
||||
const fontSize = avatarSize / 3;
|
||||
|
||||
const getInitials = (name: string) => {
|
||||
return name
|
||||
.split(' ')
|
||||
.map(word => word[0])
|
||||
.join('')
|
||||
.toUpperCase()
|
||||
.slice(0, 2);
|
||||
};
|
||||
|
||||
return (
|
||||
<View
|
||||
style={[
|
||||
styles.container,
|
||||
{
|
||||
width: avatarSize,
|
||||
height: avatarSize,
|
||||
borderRadius,
|
||||
borderColor: showBorder ? borderColor : 'transparent',
|
||||
}
|
||||
]}
|
||||
>
|
||||
{image ? (
|
||||
<Image
|
||||
source={{ uri: image }}
|
||||
style={[
|
||||
styles.image,
|
||||
{
|
||||
width: avatarSize - 4,
|
||||
height: avatarSize - 4,
|
||||
borderRadius: (avatarSize - 4) / 2,
|
||||
}
|
||||
]}
|
||||
resizeMode="cover"
|
||||
/>
|
||||
) : (
|
||||
<ThemedView
|
||||
style={[
|
||||
styles.placeholder,
|
||||
{
|
||||
width: avatarSize - 4,
|
||||
height: avatarSize - 4,
|
||||
borderRadius: (avatarSize - 4) / 2,
|
||||
backgroundColor: placeholderColor,
|
||||
}
|
||||
]}
|
||||
>
|
||||
<ThemedText
|
||||
style={[
|
||||
styles.initials,
|
||||
{
|
||||
fontSize,
|
||||
color: textColor,
|
||||
}
|
||||
]}
|
||||
>
|
||||
{getInitials(name)}
|
||||
</ThemedText>
|
||||
</ThemedView>
|
||||
)}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
borderWidth: 2,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
overflow: 'hidden',
|
||||
},
|
||||
image: {
|
||||
backgroundColor: 'transparent',
|
||||
},
|
||||
placeholder: {
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
initials: {
|
||||
fontWeight: '600',
|
||||
textAlign: 'center',
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user