749 lines
22 KiB
TypeScript
749 lines
22 KiB
TypeScript
import React, { useState, useEffect } from 'react';
|
|
import {
|
|
View,
|
|
Text,
|
|
StyleSheet,
|
|
ScrollView,
|
|
TouchableOpacity,
|
|
Modal,
|
|
TextInput,
|
|
SafeAreaView,
|
|
Animated,
|
|
} from 'react-native';
|
|
import { LinearGradient } from 'expo-linear-gradient';
|
|
import { Ionicons, Feather, MaterialCommunityIcons, FontAwesome5 } from '@expo/vector-icons';
|
|
import { colors, typography, spacing, borderRadius, shadows } from '../theme/colors';
|
|
import { VaultAsset, VaultAssetType } from '../types';
|
|
import BiometricModal from '../components/common/BiometricModal';
|
|
|
|
// Asset type configuration with nautical theme
|
|
const assetTypeConfig: Record<VaultAssetType, { icon: string; iconType: 'ionicons' | 'feather' | 'material' | 'fontawesome5'; label: string }> = {
|
|
game_account: { icon: 'gamepad', iconType: 'fontawesome5', label: 'Digital Account' },
|
|
private_key: { icon: 'key', iconType: 'fontawesome5', label: 'Secret Key' },
|
|
document: { icon: 'scroll', iconType: 'fontawesome5', label: 'Document' },
|
|
photo: { icon: 'image', iconType: 'ionicons', label: 'Sealed Photo' },
|
|
will: { icon: 'file-signature', iconType: 'fontawesome5', label: 'Testament' },
|
|
custom: { icon: 'gem', iconType: 'fontawesome5', label: 'Treasure' },
|
|
};
|
|
|
|
// Mock data
|
|
const initialAssets: VaultAsset[] = [
|
|
{
|
|
id: '1',
|
|
type: 'private_key',
|
|
label: 'ETH Main Wallet Key',
|
|
createdAt: new Date('2024-01-10'),
|
|
updatedAt: new Date('2024-01-10'),
|
|
isEncrypted: true,
|
|
},
|
|
{
|
|
id: '2',
|
|
type: 'game_account',
|
|
label: 'Steam Account Credentials',
|
|
createdAt: new Date('2024-01-08'),
|
|
updatedAt: new Date('2024-01-08'),
|
|
isEncrypted: true,
|
|
},
|
|
{
|
|
id: '3',
|
|
type: 'document',
|
|
label: 'Insurance Policy Scan',
|
|
createdAt: new Date('2024-01-05'),
|
|
updatedAt: new Date('2024-01-05'),
|
|
isEncrypted: true,
|
|
},
|
|
{
|
|
id: '4',
|
|
type: 'will',
|
|
label: 'Testament Draft v2',
|
|
createdAt: new Date('2024-01-02'),
|
|
updatedAt: new Date('2024-01-15'),
|
|
isEncrypted: true,
|
|
},
|
|
];
|
|
|
|
const renderAssetTypeIcon = (config: typeof assetTypeConfig[VaultAssetType], size: number, color: string) => {
|
|
switch (config.iconType) {
|
|
case 'ionicons':
|
|
return <Ionicons name={config.icon as any} size={size} color={color} />;
|
|
case 'feather':
|
|
return <Feather name={config.icon as any} size={size} color={color} />;
|
|
case 'material':
|
|
return <MaterialCommunityIcons name={config.icon as any} size={size} color={color} />;
|
|
case 'fontawesome5':
|
|
return <FontAwesome5 name={config.icon as any} size={size} color={color} />;
|
|
}
|
|
};
|
|
|
|
export default function VaultScreen() {
|
|
const [isUnlocked, setIsUnlocked] = useState(false);
|
|
const [showBiometric, setShowBiometric] = useState(false);
|
|
const [assets, setAssets] = useState<VaultAsset[]>(initialAssets);
|
|
const [showAddModal, setShowAddModal] = useState(false);
|
|
const [selectedType, setSelectedType] = useState<VaultAssetType>('custom');
|
|
const [newLabel, setNewLabel] = useState('');
|
|
const [showUploadSuccess, setShowUploadSuccess] = useState(false);
|
|
const [fadeAnim] = useState(new Animated.Value(0));
|
|
const [pulseAnim] = useState(new Animated.Value(1));
|
|
|
|
useEffect(() => {
|
|
if (!isUnlocked) {
|
|
const timer = setTimeout(() => {
|
|
setShowBiometric(true);
|
|
}, 500);
|
|
return () => clearTimeout(timer);
|
|
}
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
if (isUnlocked) {
|
|
Animated.timing(fadeAnim, {
|
|
toValue: 1,
|
|
duration: 600,
|
|
useNativeDriver: true,
|
|
}).start();
|
|
}
|
|
}, [isUnlocked]);
|
|
|
|
useEffect(() => {
|
|
if (!isUnlocked) {
|
|
Animated.loop(
|
|
Animated.sequence([
|
|
Animated.timing(pulseAnim, {
|
|
toValue: 1.05,
|
|
duration: 1500,
|
|
useNativeDriver: true,
|
|
}),
|
|
Animated.timing(pulseAnim, {
|
|
toValue: 1,
|
|
duration: 1500,
|
|
useNativeDriver: true,
|
|
}),
|
|
])
|
|
).start();
|
|
}
|
|
}, [isUnlocked]);
|
|
|
|
const handleUnlock = () => {
|
|
setShowBiometric(false);
|
|
setIsUnlocked(true);
|
|
};
|
|
|
|
const handleAddAsset = () => {
|
|
if (!newLabel.trim()) return;
|
|
|
|
const newAsset: VaultAsset = {
|
|
id: Date.now().toString(),
|
|
type: selectedType,
|
|
label: newLabel,
|
|
createdAt: new Date(),
|
|
updatedAt: new Date(),
|
|
isEncrypted: true,
|
|
};
|
|
|
|
setAssets([newAsset, ...assets]);
|
|
setNewLabel('');
|
|
setSelectedType('custom');
|
|
setShowAddModal(false);
|
|
|
|
setShowUploadSuccess(true);
|
|
setTimeout(() => setShowUploadSuccess(false), 2500);
|
|
};
|
|
|
|
const formatDate = (date: Date) => {
|
|
return date.toLocaleDateString('en-US', {
|
|
year: 'numeric',
|
|
month: 'short',
|
|
day: 'numeric',
|
|
});
|
|
};
|
|
|
|
// Lock screen
|
|
if (!isUnlocked) {
|
|
return (
|
|
<View style={styles.lockContainer}>
|
|
<LinearGradient
|
|
colors={[colors.vault.backgroundGradientStart, colors.vault.backgroundGradientEnd]}
|
|
style={styles.lockGradient}
|
|
>
|
|
<SafeAreaView style={styles.lockSafeArea}>
|
|
<View style={styles.lockContent}>
|
|
<Animated.View style={[styles.lockIconContainer, { transform: [{ scale: pulseAnim }] }]}>
|
|
<LinearGradient
|
|
colors={[colors.nautical.teal, colors.nautical.deepTeal]}
|
|
style={styles.lockIconGradient}
|
|
>
|
|
<MaterialCommunityIcons name="treasure-chest" size={64} color={colors.vault.primary} />
|
|
</LinearGradient>
|
|
</Animated.View>
|
|
|
|
<Text style={styles.lockTitle}>THE DEEP VAULT</Text>
|
|
<Text style={styles.lockSubtitle}>Where treasures rest in silence</Text>
|
|
|
|
<View style={styles.waveContainer}>
|
|
<MaterialCommunityIcons name="waves" size={48} color={colors.vault.secondary} style={{ opacity: 0.3 }} />
|
|
</View>
|
|
|
|
<TouchableOpacity
|
|
style={styles.unlockButton}
|
|
onPress={() => setShowBiometric(true)}
|
|
activeOpacity={0.8}
|
|
>
|
|
<LinearGradient
|
|
colors={[colors.vault.primary, colors.vault.secondary]}
|
|
style={styles.unlockButtonGradient}
|
|
start={{ x: 0, y: 0 }}
|
|
end={{ x: 1, y: 0 }}
|
|
>
|
|
<Ionicons name="finger-print" size={20} color={colors.vault.background} />
|
|
<Text style={styles.unlockButtonText}>Captain's Verification</Text>
|
|
</LinearGradient>
|
|
</TouchableOpacity>
|
|
</View>
|
|
</SafeAreaView>
|
|
</LinearGradient>
|
|
|
|
<BiometricModal
|
|
visible={showBiometric}
|
|
onSuccess={handleUnlock}
|
|
onCancel={() => setShowBiometric(false)}
|
|
title="Enter the Vault"
|
|
message="Verify your identity to access your treasures"
|
|
isDark
|
|
/>
|
|
</View>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<View style={styles.container}>
|
|
<LinearGradient
|
|
colors={[colors.vault.backgroundGradientStart, colors.vault.backgroundGradientEnd]}
|
|
style={styles.gradient}
|
|
>
|
|
<SafeAreaView style={styles.safeArea}>
|
|
<Animated.View style={[styles.content, { opacity: fadeAnim }]}>
|
|
{/* Header */}
|
|
<View style={styles.header}>
|
|
<View style={styles.headerTop}>
|
|
<View style={styles.headerTitleRow}>
|
|
<MaterialCommunityIcons name="treasure-chest" size={26} color={colors.vault.primary} />
|
|
<Text style={styles.title}>THE VAULT</Text>
|
|
</View>
|
|
<View style={styles.securityBadge}>
|
|
<Ionicons name="shield-checkmark" size={14} color={colors.vault.success} />
|
|
<Text style={styles.securityText}>SEALED</Text>
|
|
</View>
|
|
</View>
|
|
<Text style={styles.subtitle}>
|
|
{assets.length} treasures · Encrypted at rest
|
|
</Text>
|
|
</View>
|
|
|
|
{/* Asset List */}
|
|
<ScrollView
|
|
style={styles.assetList}
|
|
showsVerticalScrollIndicator={false}
|
|
contentContainerStyle={styles.assetListContent}
|
|
>
|
|
{assets.map((asset) => {
|
|
const config = assetTypeConfig[asset.type];
|
|
return (
|
|
<TouchableOpacity
|
|
key={asset.id}
|
|
style={styles.assetCard}
|
|
activeOpacity={0.7}
|
|
>
|
|
<View style={styles.assetIconContainer}>
|
|
{renderAssetTypeIcon(config, 22, colors.vault.primary)}
|
|
</View>
|
|
<View style={styles.assetInfo}>
|
|
<Text style={styles.assetType}>{config.label}</Text>
|
|
<Text style={styles.assetLabel}>{asset.label}</Text>
|
|
<View style={styles.assetMetaRow}>
|
|
<Feather name="clock" size={10} color={colors.vault.textSecondary} />
|
|
<Text style={styles.assetMeta}>Sealed {formatDate(asset.createdAt)}</Text>
|
|
</View>
|
|
</View>
|
|
<View style={styles.encryptedBadge}>
|
|
<MaterialCommunityIcons name="lock" size={16} color="#fff" />
|
|
</View>
|
|
</TouchableOpacity>
|
|
);
|
|
})}
|
|
<View style={{ height: 100 }} />
|
|
</ScrollView>
|
|
|
|
{/* Add Button */}
|
|
<TouchableOpacity
|
|
style={styles.addButton}
|
|
onPress={() => setShowAddModal(true)}
|
|
activeOpacity={0.9}
|
|
>
|
|
<LinearGradient
|
|
colors={[colors.vault.primary, colors.vault.secondary]}
|
|
style={styles.addButtonGradient}
|
|
start={{ x: 0, y: 0 }}
|
|
end={{ x: 1, y: 0 }}
|
|
>
|
|
<FontAwesome5 name="plus" size={16} color={colors.vault.background} />
|
|
<Text style={styles.addButtonText}>Add Treasure</Text>
|
|
</LinearGradient>
|
|
</TouchableOpacity>
|
|
|
|
{/* Upload Success Toast */}
|
|
{showUploadSuccess && (
|
|
<Animated.View style={styles.successToast}>
|
|
<Ionicons name="checkmark-circle" size={20} color="#fff" />
|
|
<Text style={styles.successText}>Treasure sealed successfully</Text>
|
|
</Animated.View>
|
|
)}
|
|
</Animated.View>
|
|
</SafeAreaView>
|
|
</LinearGradient>
|
|
|
|
{/* Add Modal */}
|
|
<Modal
|
|
visible={showAddModal}
|
|
animationType="slide"
|
|
transparent
|
|
onRequestClose={() => setShowAddModal(false)}
|
|
>
|
|
<View style={styles.modalOverlay}>
|
|
<View style={styles.modalContent}>
|
|
<View style={styles.modalHandle} />
|
|
<View style={styles.modalHeader}>
|
|
<FontAwesome5 name="gem" size={22} color={colors.nautical.teal} />
|
|
<Text style={styles.modalTitle}>Add New Treasure</Text>
|
|
</View>
|
|
|
|
<Text style={styles.modalLabel}>TREASURE TYPE</Text>
|
|
<ScrollView
|
|
horizontal
|
|
showsHorizontalScrollIndicator={false}
|
|
style={styles.typeScroll}
|
|
contentContainerStyle={styles.typeScrollContent}
|
|
>
|
|
{(Object.keys(assetTypeConfig) as VaultAssetType[]).map((type) => {
|
|
const config = assetTypeConfig[type];
|
|
const isSelected = selectedType === type;
|
|
return (
|
|
<TouchableOpacity
|
|
key={type}
|
|
style={[styles.typeButton, isSelected && styles.typeButtonActive]}
|
|
onPress={() => setSelectedType(type)}
|
|
>
|
|
<View style={[styles.typeIconContainer, isSelected && styles.typeIconContainerActive]}>
|
|
{renderAssetTypeIcon(config, 22, isSelected ? colors.nautical.teal : colors.nautical.sage)}
|
|
</View>
|
|
<Text style={[styles.typeButtonLabel, isSelected && styles.typeButtonLabelActive]}>
|
|
{config.label}
|
|
</Text>
|
|
</TouchableOpacity>
|
|
);
|
|
})}
|
|
</ScrollView>
|
|
|
|
<Text style={styles.modalLabel}>TREASURE NAME</Text>
|
|
<TextInput
|
|
style={styles.input}
|
|
placeholder="e.g., Main wallet mnemonic"
|
|
placeholderTextColor={colors.nautical.sage}
|
|
value={newLabel}
|
|
onChangeText={setNewLabel}
|
|
/>
|
|
|
|
<View style={styles.encryptionNote}>
|
|
<MaterialCommunityIcons name="anchor" size={16} color={colors.nautical.teal} />
|
|
<Text style={styles.encryptionNoteText}>
|
|
Your treasure will be encrypted and sealed. Original data will be securely destroyed.
|
|
</Text>
|
|
</View>
|
|
|
|
<View style={styles.modalButtons}>
|
|
<TouchableOpacity
|
|
style={styles.cancelButton}
|
|
onPress={() => {
|
|
setShowAddModal(false);
|
|
setNewLabel('');
|
|
}}
|
|
>
|
|
<Text style={styles.cancelButtonText}>Cancel</Text>
|
|
</TouchableOpacity>
|
|
<TouchableOpacity
|
|
style={styles.confirmButton}
|
|
onPress={handleAddAsset}
|
|
>
|
|
<LinearGradient
|
|
colors={[colors.nautical.teal, colors.nautical.seafoam]}
|
|
style={styles.confirmButtonGradient}
|
|
start={{ x: 0, y: 0 }}
|
|
end={{ x: 1, y: 0 }}
|
|
>
|
|
<MaterialCommunityIcons name="lock" size={18} color="#fff" />
|
|
<Text style={styles.confirmButtonText}>Seal Treasure</Text>
|
|
</LinearGradient>
|
|
</TouchableOpacity>
|
|
</View>
|
|
</View>
|
|
</View>
|
|
</Modal>
|
|
</View>
|
|
);
|
|
}
|
|
|
|
const styles = StyleSheet.create({
|
|
container: {
|
|
flex: 1,
|
|
},
|
|
gradient: {
|
|
flex: 1,
|
|
},
|
|
safeArea: {
|
|
flex: 1,
|
|
},
|
|
content: {
|
|
flex: 1,
|
|
},
|
|
lockContainer: {
|
|
flex: 1,
|
|
},
|
|
lockGradient: {
|
|
flex: 1,
|
|
},
|
|
lockSafeArea: {
|
|
flex: 1,
|
|
},
|
|
lockContent: {
|
|
flex: 1,
|
|
justifyContent: 'center',
|
|
alignItems: 'center',
|
|
paddingHorizontal: spacing.xl,
|
|
},
|
|
lockIconContainer: {
|
|
marginBottom: spacing.lg,
|
|
},
|
|
lockIconGradient: {
|
|
width: 130,
|
|
height: 130,
|
|
borderRadius: 65,
|
|
justifyContent: 'center',
|
|
alignItems: 'center',
|
|
...shadows.glow,
|
|
},
|
|
lockTitle: {
|
|
fontSize: typography.fontSize.xxl,
|
|
fontWeight: '700',
|
|
color: colors.vault.text,
|
|
letterSpacing: typography.letterSpacing.widest,
|
|
marginBottom: spacing.sm,
|
|
fontFamily: typography.fontFamily.serif,
|
|
},
|
|
lockSubtitle: {
|
|
fontSize: typography.fontSize.base,
|
|
color: colors.vault.textSecondary,
|
|
marginBottom: spacing.xl,
|
|
textAlign: 'center',
|
|
fontStyle: 'italic',
|
|
},
|
|
waveContainer: {
|
|
marginBottom: spacing.xl,
|
|
},
|
|
unlockButton: {
|
|
borderRadius: borderRadius.lg,
|
|
overflow: 'hidden',
|
|
},
|
|
unlockButtonGradient: {
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
paddingVertical: spacing.md,
|
|
paddingHorizontal: spacing.xl,
|
|
gap: spacing.sm,
|
|
},
|
|
unlockButtonText: {
|
|
fontSize: typography.fontSize.base,
|
|
color: colors.vault.background,
|
|
fontWeight: '600',
|
|
},
|
|
header: {
|
|
paddingHorizontal: spacing.lg,
|
|
paddingTop: spacing.lg,
|
|
paddingBottom: spacing.md,
|
|
},
|
|
headerTop: {
|
|
flexDirection: 'row',
|
|
justifyContent: 'space-between',
|
|
alignItems: 'center',
|
|
marginBottom: spacing.xs,
|
|
},
|
|
headerTitleRow: {
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
gap: spacing.sm,
|
|
},
|
|
title: {
|
|
fontSize: typography.fontSize.xl,
|
|
fontWeight: '700',
|
|
color: colors.vault.text,
|
|
letterSpacing: typography.letterSpacing.wider,
|
|
fontFamily: typography.fontFamily.serif,
|
|
},
|
|
securityBadge: {
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
backgroundColor: `${colors.vault.success}20`,
|
|
paddingHorizontal: spacing.sm,
|
|
paddingVertical: spacing.xs,
|
|
borderRadius: borderRadius.full,
|
|
gap: spacing.xs,
|
|
},
|
|
securityText: {
|
|
fontSize: typography.fontSize.xs,
|
|
color: colors.vault.success,
|
|
fontWeight: '700',
|
|
letterSpacing: 1,
|
|
},
|
|
subtitle: {
|
|
fontSize: typography.fontSize.sm,
|
|
color: colors.vault.textSecondary,
|
|
},
|
|
assetList: {
|
|
flex: 1,
|
|
},
|
|
assetListContent: {
|
|
padding: spacing.lg,
|
|
paddingTop: spacing.sm,
|
|
},
|
|
assetCard: {
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
backgroundColor: colors.vault.cardBackground,
|
|
borderRadius: borderRadius.xl,
|
|
padding: spacing.base,
|
|
marginBottom: spacing.md,
|
|
borderWidth: 1,
|
|
borderColor: colors.vault.cardBorder,
|
|
},
|
|
assetIconContainer: {
|
|
width: 52,
|
|
height: 52,
|
|
borderRadius: 26,
|
|
backgroundColor: `${colors.vault.primary}15`,
|
|
justifyContent: 'center',
|
|
alignItems: 'center',
|
|
marginRight: spacing.base,
|
|
},
|
|
assetInfo: {
|
|
flex: 1,
|
|
},
|
|
assetType: {
|
|
fontSize: typography.fontSize.xs,
|
|
color: colors.vault.textSecondary,
|
|
textTransform: 'uppercase',
|
|
letterSpacing: 1,
|
|
marginBottom: 2,
|
|
fontWeight: '600',
|
|
},
|
|
assetLabel: {
|
|
fontSize: typography.fontSize.base,
|
|
color: colors.vault.text,
|
|
fontWeight: '600',
|
|
marginBottom: 4,
|
|
},
|
|
assetMetaRow: {
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
gap: spacing.xs,
|
|
},
|
|
assetMeta: {
|
|
fontSize: typography.fontSize.xs,
|
|
color: colors.vault.textSecondary,
|
|
},
|
|
encryptedBadge: {
|
|
width: 36,
|
|
height: 36,
|
|
borderRadius: 18,
|
|
backgroundColor: colors.vault.success,
|
|
justifyContent: 'center',
|
|
alignItems: 'center',
|
|
},
|
|
addButton: {
|
|
position: 'absolute',
|
|
bottom: 100,
|
|
left: spacing.lg,
|
|
right: spacing.lg,
|
|
borderRadius: borderRadius.lg,
|
|
overflow: 'hidden',
|
|
},
|
|
addButtonGradient: {
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
paddingVertical: spacing.md,
|
|
gap: spacing.sm,
|
|
},
|
|
addButtonText: {
|
|
fontSize: typography.fontSize.base,
|
|
color: colors.vault.background,
|
|
fontWeight: '700',
|
|
},
|
|
successToast: {
|
|
position: 'absolute',
|
|
bottom: 170,
|
|
left: spacing.lg,
|
|
right: spacing.lg,
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
backgroundColor: colors.vault.success,
|
|
paddingVertical: spacing.md,
|
|
borderRadius: borderRadius.lg,
|
|
gap: spacing.sm,
|
|
},
|
|
successText: {
|
|
fontSize: typography.fontSize.base,
|
|
color: '#fff',
|
|
fontWeight: '600',
|
|
},
|
|
modalOverlay: {
|
|
flex: 1,
|
|
backgroundColor: 'rgba(26, 58, 74, 0.8)',
|
|
justifyContent: 'flex-end',
|
|
},
|
|
modalContent: {
|
|
backgroundColor: colors.nautical.cream,
|
|
borderTopLeftRadius: borderRadius.xxl,
|
|
borderTopRightRadius: borderRadius.xxl,
|
|
padding: spacing.lg,
|
|
paddingBottom: spacing.xxl,
|
|
},
|
|
modalHandle: {
|
|
width: 40,
|
|
height: 4,
|
|
backgroundColor: colors.nautical.lightMint,
|
|
borderRadius: 2,
|
|
alignSelf: 'center',
|
|
marginBottom: spacing.lg,
|
|
},
|
|
modalHeader: {
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
gap: spacing.sm,
|
|
marginBottom: spacing.lg,
|
|
},
|
|
modalTitle: {
|
|
fontSize: typography.fontSize.lg,
|
|
fontWeight: '600',
|
|
color: colors.nautical.navy,
|
|
},
|
|
modalLabel: {
|
|
fontSize: typography.fontSize.xs,
|
|
color: colors.nautical.sage,
|
|
marginBottom: spacing.sm,
|
|
letterSpacing: typography.letterSpacing.wider,
|
|
fontWeight: '600',
|
|
},
|
|
typeScroll: {
|
|
marginBottom: spacing.lg,
|
|
},
|
|
typeScrollContent: {
|
|
gap: spacing.sm,
|
|
},
|
|
typeButton: {
|
|
alignItems: 'center',
|
|
paddingVertical: spacing.sm,
|
|
paddingHorizontal: spacing.base,
|
|
borderRadius: borderRadius.lg,
|
|
backgroundColor: colors.nautical.paleAqua,
|
|
borderWidth: 2,
|
|
borderColor: 'transparent',
|
|
minWidth: 100,
|
|
},
|
|
typeButtonActive: {
|
|
borderColor: colors.nautical.teal,
|
|
backgroundColor: colors.nautical.lightMint,
|
|
},
|
|
typeIconContainer: {
|
|
width: 44,
|
|
height: 44,
|
|
borderRadius: 22,
|
|
backgroundColor: colors.nautical.cream,
|
|
justifyContent: 'center',
|
|
alignItems: 'center',
|
|
marginBottom: spacing.xs,
|
|
},
|
|
typeIconContainerActive: {
|
|
backgroundColor: `${colors.nautical.teal}15`,
|
|
},
|
|
typeButtonLabel: {
|
|
fontSize: typography.fontSize.xs,
|
|
color: colors.nautical.sage,
|
|
textAlign: 'center',
|
|
fontWeight: '500',
|
|
},
|
|
typeButtonLabelActive: {
|
|
color: colors.nautical.teal,
|
|
fontWeight: '600',
|
|
},
|
|
input: {
|
|
backgroundColor: colors.nautical.paleAqua,
|
|
borderRadius: borderRadius.lg,
|
|
padding: spacing.base,
|
|
fontSize: typography.fontSize.base,
|
|
color: colors.nautical.navy,
|
|
marginBottom: spacing.md,
|
|
borderWidth: 1,
|
|
borderColor: colors.nautical.lightMint,
|
|
},
|
|
encryptionNote: {
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
backgroundColor: colors.nautical.lightMint,
|
|
borderRadius: borderRadius.lg,
|
|
padding: spacing.md,
|
|
marginBottom: spacing.lg,
|
|
gap: spacing.sm,
|
|
},
|
|
encryptionNoteText: {
|
|
flex: 1,
|
|
fontSize: typography.fontSize.sm,
|
|
color: colors.nautical.teal,
|
|
lineHeight: typography.fontSize.sm * 1.4,
|
|
},
|
|
modalButtons: {
|
|
flexDirection: 'row',
|
|
gap: spacing.md,
|
|
},
|
|
cancelButton: {
|
|
flex: 1,
|
|
paddingVertical: spacing.md,
|
|
borderRadius: borderRadius.lg,
|
|
backgroundColor: colors.nautical.paleAqua,
|
|
alignItems: 'center',
|
|
borderWidth: 1,
|
|
borderColor: colors.nautical.lightMint,
|
|
},
|
|
cancelButtonText: {
|
|
fontSize: typography.fontSize.base,
|
|
color: colors.nautical.sage,
|
|
fontWeight: '600',
|
|
},
|
|
confirmButton: {
|
|
flex: 1,
|
|
borderRadius: borderRadius.lg,
|
|
overflow: 'hidden',
|
|
},
|
|
confirmButtonGradient: {
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
paddingVertical: spacing.md,
|
|
gap: spacing.sm,
|
|
},
|
|
confirmButtonText: {
|
|
fontSize: typography.fontSize.base,
|
|
color: '#fff',
|
|
fontWeight: '600',
|
|
},
|
|
});
|