mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-03-11 17:45:38 +00:00
Improved Localization in Account Manage Screen
This commit is contained in:
parent
18c40ced29
commit
821a6b864f
3 changed files with 1973 additions and 1820 deletions
File diff suppressed because it is too large
Load diff
|
|
@ -1535,5 +1535,12 @@
|
|||
"provider_logs": "Log Provider",
|
||||
"no_logs_captured": "Nessun log catturato."
|
||||
}
|
||||
}
|
||||
},
|
||||
"account_manager":{
|
||||
"sign_out":"Esci",
|
||||
"sign_out_desc":"",
|
||||
"user_id":"ID Utente",
|
||||
"display_name":"Nickname",
|
||||
"display_name_placeholder":"Aggiungi un nickname"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,16 @@
|
|||
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { View, Text, StyleSheet, TouchableOpacity, StatusBar, Platform, Animated, Easing, TextInput, ActivityIndicator } from 'react-native';
|
||||
import {
|
||||
View,
|
||||
Text,
|
||||
StyleSheet,
|
||||
TouchableOpacity,
|
||||
StatusBar,
|
||||
Platform,
|
||||
Animated,
|
||||
Easing,
|
||||
TextInput,
|
||||
ActivityIndicator,
|
||||
} from 'react-native';
|
||||
import FastImage from '@d11/react-native-fast-image';
|
||||
import { useNavigation } from '@react-navigation/native';
|
||||
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
||||
|
|
@ -7,331 +18,458 @@ import { MaterialIcons } from '@expo/vector-icons';
|
|||
import { useAccount } from '../contexts/AccountContext';
|
||||
import { useTheme } from '../contexts/ThemeContext';
|
||||
import { LinearGradient } from 'expo-linear-gradient';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import * as Haptics from 'expo-haptics';
|
||||
import CustomAlert from '../components/CustomAlert';
|
||||
|
||||
const AccountManageScreen: React.FC = () => {
|
||||
const navigation = useNavigation();
|
||||
const insets = useSafeAreaInsets();
|
||||
const { user, signOut, updateProfile } = useAccount();
|
||||
const { currentTheme } = useTheme();
|
||||
const navigation = useNavigation();
|
||||
const insets = useSafeAreaInsets();
|
||||
const { user, signOut, updateProfile } = useAccount();
|
||||
const { currentTheme } = useTheme();
|
||||
const { t } = useTranslation();
|
||||
const headerOpacity = useRef(new Animated.Value(0)).current;
|
||||
const headerTranslateY = useRef(new Animated.Value(8)).current;
|
||||
const contentOpacity = useRef(new Animated.Value(0)).current;
|
||||
const contentTranslateY = useRef(new Animated.Value(8)).current;
|
||||
|
||||
const headerOpacity = useRef(new Animated.Value(0)).current;
|
||||
const headerTranslateY = useRef(new Animated.Value(8)).current;
|
||||
const contentOpacity = useRef(new Animated.Value(0)).current;
|
||||
const contentTranslateY = useRef(new Animated.Value(8)).current;
|
||||
useEffect(() => {
|
||||
Animated.parallel([
|
||||
Animated.timing(headerOpacity, {
|
||||
toValue: 1,
|
||||
duration: 260,
|
||||
easing: Easing.out(Easing.cubic),
|
||||
useNativeDriver: true,
|
||||
}),
|
||||
Animated.timing(headerTranslateY, {
|
||||
toValue: 0,
|
||||
duration: 260,
|
||||
easing: Easing.out(Easing.cubic),
|
||||
useNativeDriver: true,
|
||||
}),
|
||||
Animated.timing(contentOpacity, {
|
||||
toValue: 1,
|
||||
duration: 320,
|
||||
delay: 80,
|
||||
easing: Easing.out(Easing.cubic),
|
||||
useNativeDriver: true,
|
||||
}),
|
||||
Animated.timing(contentTranslateY, {
|
||||
toValue: 0,
|
||||
duration: 320,
|
||||
delay: 80,
|
||||
easing: Easing.out(Easing.cubic),
|
||||
useNativeDriver: true,
|
||||
}),
|
||||
]).start();
|
||||
}, [headerOpacity, headerTranslateY, contentOpacity, contentTranslateY]);
|
||||
|
||||
useEffect(() => {
|
||||
Animated.parallel([
|
||||
Animated.timing(headerOpacity, { toValue: 1, duration: 260, easing: Easing.out(Easing.cubic), useNativeDriver: true }),
|
||||
Animated.timing(headerTranslateY, { toValue: 0, duration: 260, easing: Easing.out(Easing.cubic), useNativeDriver: true }),
|
||||
Animated.timing(contentOpacity, { toValue: 1, duration: 320, delay: 80, easing: Easing.out(Easing.cubic), useNativeDriver: true }),
|
||||
Animated.timing(contentTranslateY, { toValue: 0, duration: 320, delay: 80, easing: Easing.out(Easing.cubic), useNativeDriver: true }),
|
||||
]).start();
|
||||
}, [headerOpacity, headerTranslateY, contentOpacity, contentTranslateY]);
|
||||
const initial = useMemo(
|
||||
() => user?.email?.[0]?.toUpperCase() || 'U',
|
||||
[user?.email],
|
||||
);
|
||||
const [displayName, setDisplayName] = useState(user?.displayName || '');
|
||||
const [avatarUrl, setAvatarUrl] = useState(user?.avatarUrl || '');
|
||||
const [saving, setSaving] = useState(false);
|
||||
const [avatarError, setAvatarError] = useState(false);
|
||||
const [alertVisible, setAlertVisible] = useState(false);
|
||||
const [alertTitle, setAlertTitle] = useState('');
|
||||
const [alertMessage, setAlertMessage] = useState('');
|
||||
const [alertActions, setAlertActions] = useState<any[]>([]);
|
||||
useEffect(() => {
|
||||
// Reset image error state when URL changes
|
||||
setAvatarError(false);
|
||||
}, [avatarUrl]);
|
||||
|
||||
const initial = useMemo(() => (user?.email?.[0]?.toUpperCase() || 'U'), [user?.email]);
|
||||
const [displayName, setDisplayName] = useState(user?.displayName || '');
|
||||
const [avatarUrl, setAvatarUrl] = useState(user?.avatarUrl || '');
|
||||
const [saving, setSaving] = useState(false);
|
||||
const [avatarError, setAvatarError] = useState(false);
|
||||
const [alertVisible, setAlertVisible] = useState(false);
|
||||
const [alertTitle, setAlertTitle] = useState('');
|
||||
const [alertMessage, setAlertMessage] = useState('');
|
||||
const [alertActions, setAlertActions] = useState<any[]>([]);
|
||||
const handleSave = async () => {
|
||||
if (saving) return;
|
||||
setSaving(true);
|
||||
const err = await updateProfile({
|
||||
displayName: displayName.trim() || undefined,
|
||||
avatarUrl: avatarUrl.trim() || undefined,
|
||||
});
|
||||
if (err) {
|
||||
setAlertTitle(t('common.error'));
|
||||
setAlertMessage(err);
|
||||
setAlertActions([{ label: 'OK', onPress: () => {} }]);
|
||||
setAlertVisible(true);
|
||||
}
|
||||
setSaving(false);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
// Reset image error state when URL changes
|
||||
setAvatarError(false);
|
||||
}, [avatarUrl]);
|
||||
const handleSignOut = () => {
|
||||
setAlertTitle(t('account_manager.sign_out'));
|
||||
setAlertMessage(t('account_manager.sign_out_desc'));
|
||||
setAlertActions([
|
||||
{ label: t('common.cancel'), onPress: () => {} },
|
||||
{
|
||||
label: t('account_manager.sign_out'),
|
||||
onPress: async () => {
|
||||
try {
|
||||
await signOut();
|
||||
// @ts-ignore
|
||||
navigation.goBack();
|
||||
} catch (_) {}
|
||||
},
|
||||
style: { opacity: 1 },
|
||||
},
|
||||
]);
|
||||
setAlertVisible(true);
|
||||
};
|
||||
|
||||
const handleSave = async () => {
|
||||
if (saving) return;
|
||||
setSaving(true);
|
||||
const err = await updateProfile({ displayName: displayName.trim() || undefined, avatarUrl: avatarUrl.trim() || undefined });
|
||||
if (err) {
|
||||
setAlertTitle('Error');
|
||||
setAlertMessage(err);
|
||||
setAlertActions([{ label: 'OK', onPress: () => {} }]);
|
||||
setAlertVisible(true);
|
||||
}
|
||||
setSaving(false);
|
||||
};
|
||||
return (
|
||||
<View
|
||||
style={[
|
||||
styles.container,
|
||||
{ backgroundColor: currentTheme.colors.darkBackground },
|
||||
]}
|
||||
>
|
||||
<StatusBar
|
||||
translucent
|
||||
barStyle="light-content"
|
||||
backgroundColor="transparent"
|
||||
/>
|
||||
|
||||
const handleSignOut = () => {
|
||||
setAlertTitle('Sign out');
|
||||
setAlertMessage('Are you sure you want to sign out?');
|
||||
setAlertActions([
|
||||
{ label: 'Cancel', onPress: () => {} },
|
||||
{
|
||||
label: 'Sign out',
|
||||
onPress: async () => {
|
||||
try {
|
||||
await signOut();
|
||||
// @ts-ignore
|
||||
navigation.goBack();
|
||||
} catch (_) {}
|
||||
},
|
||||
style: { opacity: 1 },
|
||||
},
|
||||
]);
|
||||
setAlertVisible(true);
|
||||
};
|
||||
{/* Header */}
|
||||
<Animated.View
|
||||
style={[
|
||||
styles.header,
|
||||
{
|
||||
paddingTop:
|
||||
(Platform.OS === 'android' ? StatusBar.currentHeight || 0 : insets.top) +
|
||||
12,
|
||||
opacity: headerOpacity,
|
||||
transform: [{ translateY: headerTranslateY }],
|
||||
},
|
||||
]}
|
||||
>
|
||||
<LinearGradient
|
||||
colors={[currentTheme.colors.darkBackground, '#111318']}
|
||||
style={StyleSheet.absoluteFill}
|
||||
/>
|
||||
<TouchableOpacity
|
||||
onPress={() => navigation.goBack()}
|
||||
style={styles.headerBack}
|
||||
hitSlop={{ top: 8, bottom: 8, left: 8, right: 8 }}
|
||||
>
|
||||
<MaterialIcons
|
||||
name="arrow-back"
|
||||
size={22}
|
||||
color={currentTheme.colors.white}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
<Text style={[styles.headerTitle, { color: currentTheme.colors.white }]}>
|
||||
Account
|
||||
</Text>
|
||||
<View style={{ width: 22, height: 22 }} />
|
||||
</Animated.View>
|
||||
|
||||
return (
|
||||
<View style={[styles.container, { backgroundColor: currentTheme.colors.darkBackground }]}>
|
||||
<StatusBar translucent barStyle="light-content" backgroundColor="transparent" />
|
||||
{/* Content */}
|
||||
<Animated.View
|
||||
style={[
|
||||
styles.content,
|
||||
{
|
||||
opacity: contentOpacity,
|
||||
transform: [{ translateY: contentTranslateY }],
|
||||
},
|
||||
]}
|
||||
>
|
||||
{/* Profile Badge */}
|
||||
<View style={styles.profileContainer}>
|
||||
{avatarUrl && !avatarError ? (
|
||||
<View style={[styles.avatar, { overflow: 'hidden' }]}>
|
||||
<FastImage
|
||||
source={{ uri: avatarUrl }}
|
||||
style={styles.avatarImage}
|
||||
resizeMode={FastImage.resizeMode.cover}
|
||||
onError={() => setAvatarError(true)}
|
||||
/>
|
||||
</View>
|
||||
) : (
|
||||
<View
|
||||
style={[
|
||||
styles.avatar,
|
||||
{ backgroundColor: currentTheme.colors.elevation2 },
|
||||
]}
|
||||
>
|
||||
<Text style={styles.avatarText}>{displayName?.[0] || initial}</Text>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
|
||||
{/* Header */}
|
||||
<Animated.View
|
||||
style={[
|
||||
styles.header,
|
||||
{
|
||||
paddingTop: (Platform.OS === 'android' ? (StatusBar.currentHeight || 0) : insets.top) + 12,
|
||||
opacity: headerOpacity,
|
||||
transform: [{ translateY: headerTranslateY }],
|
||||
},
|
||||
]}
|
||||
>
|
||||
<LinearGradient
|
||||
colors={[currentTheme.colors.darkBackground, '#111318']}
|
||||
style={StyleSheet.absoluteFill}
|
||||
/>
|
||||
<TouchableOpacity onPress={() => navigation.goBack()} style={styles.headerBack} hitSlop={{ top: 8, bottom: 8, left: 8, right: 8 }}>
|
||||
<MaterialIcons name="arrow-back" size={22} color={currentTheme.colors.white} />
|
||||
</TouchableOpacity>
|
||||
<Text style={[styles.headerTitle, { color: currentTheme.colors.white }]}>Account</Text>
|
||||
<View style={{ width: 22, height: 22 }} />
|
||||
</Animated.View>
|
||||
{/* Account details card */}
|
||||
<View
|
||||
style={[
|
||||
styles.card,
|
||||
{
|
||||
backgroundColor: currentTheme.colors.elevation1,
|
||||
borderColor: currentTheme.colors.elevation2,
|
||||
},
|
||||
]}
|
||||
>
|
||||
<View style={styles.itemRow}>
|
||||
<View style={styles.itemLeft}>
|
||||
<MaterialIcons
|
||||
name="badge"
|
||||
size={20}
|
||||
color={currentTheme.colors.primary}
|
||||
/>
|
||||
<Text
|
||||
style={[styles.itemTitle, { color: currentTheme.colors.highEmphasis }]}
|
||||
>
|
||||
{t('account_manager.display_name')}
|
||||
</Text>
|
||||
</View>
|
||||
<TextInput
|
||||
placeholder={t('account_manager.display_name_placeholder')}
|
||||
placeholderTextColor={currentTheme.colors.mediumEmphasis}
|
||||
style={[styles.input, { color: currentTheme.colors.white }]}
|
||||
value={displayName}
|
||||
onChangeText={setDisplayName}
|
||||
numberOfLines={1}
|
||||
/>
|
||||
</View>
|
||||
|
||||
{/* Content */}
|
||||
<Animated.View style={[styles.content, { opacity: contentOpacity, transform: [{ translateY: contentTranslateY }] }]}>
|
||||
{/* Profile Badge */}
|
||||
<View style={styles.profileContainer}>
|
||||
{avatarUrl && !avatarError ? (
|
||||
<View style={[styles.avatar, { overflow: 'hidden' }]}>
|
||||
<FastImage
|
||||
source={{ uri: avatarUrl }}
|
||||
style={styles.avatarImage}
|
||||
resizeMode={FastImage.resizeMode.cover}
|
||||
onError={() => setAvatarError(true)}
|
||||
/>
|
||||
</View>
|
||||
) : (
|
||||
<View style={[styles.avatar, { backgroundColor: currentTheme.colors.elevation2 }]}>
|
||||
<Text style={styles.avatarText}>{(displayName?.[0] || initial)}</Text>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
<View style={styles.divider} />
|
||||
|
||||
{/* Account details card */}
|
||||
<View style={[styles.card, { backgroundColor: currentTheme.colors.elevation1, borderColor: currentTheme.colors.elevation2 }]}>
|
||||
<View style={styles.itemRow}>
|
||||
<View style={styles.itemLeft}>
|
||||
<MaterialIcons name="badge" size={20} color={currentTheme.colors.primary} />
|
||||
<Text style={[styles.itemTitle, { color: currentTheme.colors.highEmphasis }]}>Display name</Text>
|
||||
</View>
|
||||
<TextInput
|
||||
placeholder="Add a display name"
|
||||
placeholderTextColor={currentTheme.colors.mediumEmphasis}
|
||||
style={[styles.input, { color: currentTheme.colors.white }]}
|
||||
value={displayName}
|
||||
onChangeText={setDisplayName}
|
||||
numberOfLines={1}
|
||||
/>
|
||||
</View>
|
||||
<View
|
||||
style={[
|
||||
styles.itemRow,
|
||||
Platform.OS === 'android' && styles.itemRowCompact,
|
||||
]}
|
||||
>
|
||||
<View style={styles.itemLeft}>
|
||||
<MaterialIcons
|
||||
name="image"
|
||||
size={20}
|
||||
color={currentTheme.colors.primary}
|
||||
/>
|
||||
<Text
|
||||
style={[styles.itemTitle, { color: currentTheme.colors.highEmphasis }]}
|
||||
>
|
||||
Avatar URL
|
||||
</Text>
|
||||
</View>
|
||||
<TextInput
|
||||
placeholder="https://..."
|
||||
placeholderTextColor={currentTheme.colors.mediumEmphasis}
|
||||
style={[styles.input, { color: currentTheme.colors.white }]}
|
||||
value={avatarUrl}
|
||||
onChangeText={setAvatarUrl}
|
||||
autoCapitalize="none"
|
||||
numberOfLines={1}
|
||||
/>
|
||||
</View>
|
||||
|
||||
<View style={styles.divider} />
|
||||
<View style={styles.divider} />
|
||||
|
||||
<View style={[styles.itemRow, Platform.OS === 'android' && styles.itemRowCompact]}>
|
||||
<View style={styles.itemLeft}>
|
||||
<MaterialIcons name="image" size={20} color={currentTheme.colors.primary} />
|
||||
<Text style={[styles.itemTitle, { color: currentTheme.colors.highEmphasis }]}>Avatar URL</Text>
|
||||
</View>
|
||||
<TextInput
|
||||
placeholder="https://..."
|
||||
placeholderTextColor={currentTheme.colors.mediumEmphasis}
|
||||
style={[styles.input, { color: currentTheme.colors.white }]}
|
||||
value={avatarUrl}
|
||||
onChangeText={setAvatarUrl}
|
||||
autoCapitalize="none"
|
||||
numberOfLines={1}
|
||||
/>
|
||||
</View>
|
||||
<View style={styles.itemRow}>
|
||||
<View style={styles.itemLeft}>
|
||||
<MaterialIcons
|
||||
name="account-circle"
|
||||
size={20}
|
||||
color={currentTheme.colors.primary}
|
||||
/>
|
||||
<Text
|
||||
style={[styles.itemTitle, { color: currentTheme.colors.highEmphasis }]}
|
||||
>
|
||||
{t('common.email')}
|
||||
</Text>
|
||||
</View>
|
||||
<Text
|
||||
style={[styles.itemValue, { color: currentTheme.colors.mediumEmphasis }]}
|
||||
numberOfLines={1}
|
||||
>
|
||||
{user?.email || '—'}
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
<View style={styles.divider} />
|
||||
<View style={styles.divider} />
|
||||
|
||||
<View style={styles.itemRow}>
|
||||
<View style={styles.itemLeft}>
|
||||
<MaterialIcons name="account-circle" size={20} color={currentTheme.colors.primary} />
|
||||
<Text style={[styles.itemTitle, { color: currentTheme.colors.highEmphasis }]}>Email</Text>
|
||||
</View>
|
||||
<Text style={[styles.itemValue, { color: currentTheme.colors.mediumEmphasis }]} numberOfLines={1}>
|
||||
{user?.email || '—'}
|
||||
</Text>
|
||||
</View>
|
||||
<View style={styles.itemRow}>
|
||||
<View style={styles.itemLeft}>
|
||||
<MaterialIcons
|
||||
name="fingerprint"
|
||||
size={20}
|
||||
color={currentTheme.colors.primary}
|
||||
/>
|
||||
<Text
|
||||
style={[styles.itemTitle, { color: currentTheme.colors.highEmphasis }]}
|
||||
>
|
||||
{t('account_manager.user_id')}
|
||||
</Text>
|
||||
</View>
|
||||
<Text
|
||||
style={[styles.itemValue, { color: currentTheme.colors.mediumEmphasis }]}
|
||||
numberOfLines={1}
|
||||
>
|
||||
{user?.id}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<View style={styles.divider} />
|
||||
{/* Save and Sign out */}
|
||||
<TouchableOpacity
|
||||
activeOpacity={0.85}
|
||||
style={[
|
||||
styles.saveButton,
|
||||
{
|
||||
backgroundColor: currentTheme.colors.elevation2,
|
||||
borderColor: currentTheme.colors.elevation2,
|
||||
},
|
||||
]}
|
||||
onPress={handleSave}
|
||||
disabled={saving}
|
||||
>
|
||||
{saving ? (
|
||||
<ActivityIndicator color={currentTheme.colors.white} />
|
||||
) : (
|
||||
<>
|
||||
<MaterialIcons
|
||||
name="save-alt"
|
||||
size={18}
|
||||
color={currentTheme.colors.white}
|
||||
style={{ marginRight: 8 }}
|
||||
/>
|
||||
<Text style={styles.saveText}>{t('common.save')}</Text>
|
||||
</>
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
|
||||
<View style={styles.itemRow}>
|
||||
<View style={styles.itemLeft}>
|
||||
<MaterialIcons name="fingerprint" size={20} color={currentTheme.colors.primary} />
|
||||
<Text style={[styles.itemTitle, { color: currentTheme.colors.highEmphasis }]}>User ID</Text>
|
||||
</View>
|
||||
<Text style={[styles.itemValue, { color: currentTheme.colors.mediumEmphasis }]} numberOfLines={1}>
|
||||
{user?.id}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{/* Save and Sign out */}
|
||||
<TouchableOpacity
|
||||
activeOpacity={0.85}
|
||||
style={[styles.saveButton, { backgroundColor: currentTheme.colors.elevation2, borderColor: currentTheme.colors.elevation2 }]}
|
||||
onPress={handleSave}
|
||||
disabled={saving}
|
||||
>
|
||||
{saving ? (
|
||||
<ActivityIndicator color={currentTheme.colors.white} />
|
||||
) : (
|
||||
<>
|
||||
<MaterialIcons name="save-alt" size={18} color={currentTheme.colors.white} style={{ marginRight: 8 }} />
|
||||
<Text style={styles.saveText}>Save changes</Text>
|
||||
</>
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
|
||||
<TouchableOpacity
|
||||
activeOpacity={0.85}
|
||||
style={[
|
||||
styles.signOutButton,
|
||||
{ backgroundColor: currentTheme.colors.primary },
|
||||
]}
|
||||
onPress={handleSignOut}
|
||||
>
|
||||
<MaterialIcons name="logout" size={18} color="#fff" style={{ marginRight: 8 }} />
|
||||
<Text style={styles.signOutText}>Sign out</Text>
|
||||
</TouchableOpacity>
|
||||
</Animated.View>
|
||||
<CustomAlert
|
||||
visible={alertVisible}
|
||||
title={alertTitle}
|
||||
message={alertMessage}
|
||||
actions={alertActions}
|
||||
onClose={() => setAlertVisible(false)}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
<TouchableOpacity
|
||||
activeOpacity={0.85}
|
||||
style={[
|
||||
styles.signOutButton,
|
||||
{ backgroundColor: currentTheme.colors.primary },
|
||||
]}
|
||||
onPress={handleSignOut}
|
||||
>
|
||||
<MaterialIcons
|
||||
name="logout"
|
||||
size={18}
|
||||
color="#fff"
|
||||
style={{ marginRight: 8 }}
|
||||
/>
|
||||
<Text style={styles.signOutText}>{t('account_manager.sign_out')}</Text>
|
||||
</TouchableOpacity>
|
||||
</Animated.View>
|
||||
<CustomAlert
|
||||
visible={alertVisible}
|
||||
title={alertTitle}
|
||||
message={alertMessage}
|
||||
actions={alertActions}
|
||||
onClose={() => setAlertVisible(false)}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
},
|
||||
header: {
|
||||
paddingHorizontal: 16,
|
||||
paddingBottom: 14,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
},
|
||||
headerBack: {
|
||||
padding: 4,
|
||||
},
|
||||
headerTitle: {
|
||||
fontSize: 18,
|
||||
fontWeight: '800',
|
||||
},
|
||||
content: {
|
||||
flex: 1,
|
||||
paddingHorizontal: 16,
|
||||
paddingTop: 10,
|
||||
},
|
||||
profileContainer: {
|
||||
alignItems: 'center',
|
||||
marginBottom: 12,
|
||||
},
|
||||
avatar: {
|
||||
width: 72,
|
||||
height: 72,
|
||||
borderRadius: 36,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
avatarImage: {
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
},
|
||||
avatarText: {
|
||||
color: '#fff',
|
||||
fontWeight: '800',
|
||||
fontSize: 24,
|
||||
},
|
||||
card: {
|
||||
borderRadius: 14,
|
||||
borderWidth: StyleSheet.hairlineWidth,
|
||||
paddingHorizontal: 14,
|
||||
paddingVertical: 10,
|
||||
},
|
||||
itemRow: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
paddingVertical: 10,
|
||||
},
|
||||
itemRowCompact: {
|
||||
paddingVertical: 6,
|
||||
},
|
||||
input: {
|
||||
flex: 1,
|
||||
textAlign: 'right',
|
||||
paddingVertical: 6,
|
||||
marginLeft: 12,
|
||||
},
|
||||
itemLeft: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
gap: 8,
|
||||
},
|
||||
itemTitle: {
|
||||
fontSize: 14,
|
||||
fontWeight: '600',
|
||||
},
|
||||
itemValue: {
|
||||
fontSize: 14,
|
||||
maxWidth: '65%',
|
||||
},
|
||||
divider: {
|
||||
height: StyleSheet.hairlineWidth,
|
||||
backgroundColor: 'rgba(255,255,255,0.08)',
|
||||
},
|
||||
signOutButton: {
|
||||
marginTop: 16,
|
||||
height: 48,
|
||||
borderRadius: 12,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
flexDirection: 'row',
|
||||
},
|
||||
signOutText: {
|
||||
color: '#fff',
|
||||
fontWeight: '700',
|
||||
},
|
||||
saveButton: {
|
||||
marginTop: 12,
|
||||
height: 46,
|
||||
borderRadius: 12,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
flexDirection: 'row',
|
||||
borderWidth: StyleSheet.hairlineWidth,
|
||||
},
|
||||
saveText: {
|
||||
color: '#fff',
|
||||
fontWeight: '700',
|
||||
},
|
||||
container: {
|
||||
flex: 1,
|
||||
},
|
||||
header: {
|
||||
paddingHorizontal: 16,
|
||||
paddingBottom: 14,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
},
|
||||
headerBack: {
|
||||
padding: 4,
|
||||
},
|
||||
headerTitle: {
|
||||
fontSize: 18,
|
||||
fontWeight: '800',
|
||||
},
|
||||
content: {
|
||||
flex: 1,
|
||||
paddingHorizontal: 16,
|
||||
paddingTop: 10,
|
||||
},
|
||||
profileContainer: {
|
||||
alignItems: 'center',
|
||||
marginBottom: 12,
|
||||
},
|
||||
avatar: {
|
||||
width: 72,
|
||||
height: 72,
|
||||
borderRadius: 36,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
avatarImage: {
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
},
|
||||
avatarText: {
|
||||
color: '#fff',
|
||||
fontWeight: '800',
|
||||
fontSize: 24,
|
||||
},
|
||||
card: {
|
||||
borderRadius: 14,
|
||||
borderWidth: StyleSheet.hairlineWidth,
|
||||
paddingHorizontal: 14,
|
||||
paddingVertical: 10,
|
||||
},
|
||||
itemRow: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
paddingVertical: 10,
|
||||
},
|
||||
itemRowCompact: {
|
||||
paddingVertical: 6,
|
||||
},
|
||||
input: {
|
||||
flex: 1,
|
||||
textAlign: 'right',
|
||||
paddingVertical: 6,
|
||||
marginLeft: 12,
|
||||
},
|
||||
itemLeft: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
gap: 8,
|
||||
},
|
||||
itemTitle: {
|
||||
fontSize: 14,
|
||||
fontWeight: '600',
|
||||
},
|
||||
itemValue: {
|
||||
fontSize: 14,
|
||||
maxWidth: '65%',
|
||||
},
|
||||
divider: {
|
||||
height: StyleSheet.hairlineWidth,
|
||||
backgroundColor: 'rgba(255,255,255,0.08)',
|
||||
},
|
||||
signOutButton: {
|
||||
marginTop: 16,
|
||||
height: 48,
|
||||
borderRadius: 12,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
flexDirection: 'row',
|
||||
},
|
||||
signOutText: {
|
||||
color: '#fff',
|
||||
fontWeight: '700',
|
||||
},
|
||||
saveButton: {
|
||||
marginTop: 12,
|
||||
height: 46,
|
||||
borderRadius: 12,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
flexDirection: 'row',
|
||||
borderWidth: StyleSheet.hairlineWidth,
|
||||
},
|
||||
saveText: {
|
||||
color: '#fff',
|
||||
fontWeight: '700',
|
||||
},
|
||||
});
|
||||
|
||||
export default AccountManageScreen;
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue