Files
frontend/VAULT_USAGE_EXAMPLE.tsx

470 lines
14 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* VaultScreen 重构使用示例
*
* 这个文件展示了如何使用新创建的组件和 hooks 来简化 VaultScreen
*
* 使用方法:
* 1. 将这些代码片段复制到 VaultScreen.tsx 中替换对应的部分
* 2. 确保导入了所有必要的组件
*/
// ============================================
// 1. 导入新组件和 Hooks
// ============================================
// 在文件顶部添加这些导入
import { VaultButton, LabeledInput, AssetCard } from '@/components/vault';
import { useAddFlow, useMnemonicFlow } from '@/hooks/vault';
// ============================================
// 2. 使用 Hooks 管理状态
// ============================================
export default function VaultScreen() {
// 原来的代码:
// const [addStep, setAddStep] = useState(1);
// const [addMethod, setAddMethod] = useState<'text' | 'file' | 'scan'>('text');
// const [addVerified, setAddVerified] = useState(false);
// const [rehearsalConfirmed, setRehearsalConfirmed] = useState(false);
// const [selectedType, setSelectedType] = useState<VaultAssetType>('custom');
// const [newLabel, setNewLabel] = useState('');
// const [treasureContent, setTreasureContent] = useState('');
// const [accountProvider, setAccountProvider] = useState<'bank' | 'steam' | 'facebook' | 'custom'>('bank');
// 新代码:使用 useAddFlow hook
const addFlow = useAddFlow();
// 原来的代码:
// const [mnemonicWords, setMnemonicWords] = useState<string[]>([]);
// const [mnemonicParts, setMnemonicParts] = useState<string[][]>([]);
// const [mnemonicStep, setMnemonicStep] = useState<1 | 2 | 3 | 4 | 5>(1);
// const [heirStep, setHeirStep] = useState<'decision' | 'asset' | 'heir' | 'summary'>('decision');
// const [replaceIndex, setReplaceIndex] = useState<number | null>(null);
// const [replaceQuery, setReplaceQuery] = useState('');
// const [progressIndex, setProgressIndex] = useState(0);
// const [isCapturing, setIsCapturing] = useState(false);
// 新代码:使用 useMnemonicFlow hook
const mnemonicFlow = useMnemonicFlow();
// ... 其他状态保持不变
// ============================================
// 3. 更新 resetAddFlow 函数
// ============================================
const resetAddFlow = () => {
// 原来的代码:需要手动重置每个状态
// setAddStep(1);
// setAddMethod('text');
// setAddVerified(false);
// setRehearsalConfirmed(false);
// setSelectedType('custom');
// setNewLabel('');
// setAccountProvider('bank');
// 新代码:一行搞定
addFlow.reset();
};
// ============================================
// 4. 使用 AssetCard 组件渲染资产列表
// ============================================
// 原来的代码(在 return 语句中的资产列表部分,第 1089-1159 行):
/*
<ScrollView
style={styles.assetList}
showsVerticalScrollIndicator={false}
contentContainerStyle={styles.assetListContent}
>
{assets.map((asset, index) => {
const config = assetTypeConfig[asset.type];
if (!assetAnimations.current.has(asset.id)) {
const anim = new Animated.Value(0);
assetAnimations.current.set(asset.id, anim);
Animated.spring(anim, {
toValue: 1,
useNativeDriver: true,
tension: 65,
friction: 10,
delay: index * 80,
}).start();
}
const animValue = assetAnimations.current.get(asset.id) || new Animated.Value(1);
return (
<Animated.View
key={asset.id}
style={{
opacity: animValue,
transform: [
{
translateY: animValue.interpolate({
inputRange: [0, 1],
outputRange: [30, 0],
}),
},
{
scale: animValue.interpolate({
inputRange: [0, 1],
outputRange: [0.92, 1],
}),
},
],
}}
>
<TouchableOpacity
style={styles.assetCard}
activeOpacity={0.7}
onPress={() => handleOpenDetail(asset)}
>
<View style={styles.assetIconContainer}>
{renderAssetTypeIcon(config, 24, 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={11} color={colors.vault.textSecondary} />
<Text style={styles.assetMeta}>Sealed {formatDate(asset.createdAt)}</Text>
</View>
</View>
<View style={styles.encryptedBadge}>
<MaterialCommunityIcons name="lock" size={18} color="#fff" />
</View>
</TouchableOpacity>
</Animated.View>
);
})}
<View style={{ height: 100 }} />
</ScrollView>
*/
// 新代码:简洁清晰
const renderAssetList = () => (
<ScrollView
style={styles.assetList}
showsVerticalScrollIndicator={false}
contentContainerStyle={styles.assetListContent}
>
{assets.map((asset, index) => (
<AssetCard
key={asset.id}
asset={asset}
index={index}
onPress={handleOpenDetail}
/>
))}
<View style={{ height: 100 }} />
</ScrollView>
);
// ============================================
// 5. 使用 VaultButton 组件替换按钮
// ============================================
// 原来的代码(解锁按钮,第 1026-1041 行):
/*
<TouchableOpacity
style={styles.unlockButton}
onPress={handleUnlock}
activeOpacity={0.9}
>
<LinearGradient
colors={[colors.vault.primary, colors.vault.secondary]}
style={styles.unlockButtonGradient}
start={{ x: 0, y: 0 }}
end={{ x: 1, y: 1 }}
>
<Ionicons
name="finger-print"
size={20}
color={colors.vault.background}
/>
<Text style={styles.unlockButtonText}>
{hasS0 ? 'Captain\'s Verification' : 'Enter Vault'}
</Text>
</LinearGradient>
</TouchableOpacity>
*/
// 新代码:
const renderUnlockButton = () => (
<VaultButton
variant="primary"
icon="finger-print"
onPress={handleUnlock}
style={styles.unlockButton}
>
{hasS0 ? "Captain's Verification" : "Enter Vault"}
</VaultButton>
);
// 原来的代码(添加按钮,第 1162-1180 行):
/*
<TouchableOpacity
style={styles.addButton}
onPress={() => {
resetAddFlow();
clearAddError();
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>
*/
// 新代码:
const renderAddButton = () => (
<VaultButton
variant="primary"
icon="plus"
onPress={() => {
resetAddFlow();
clearAddError();
setShowAddModal(true);
}}
style={styles.addButton}
>
Add Treasure
</VaultButton>
);
// ============================================
// 6. 使用 LabeledInput 组件替换输入框
// ============================================
// 在 Add Modal 中(第 1238-1245 行):
/*
<Text style={styles.modalLabel}>TREASURE TITLE</Text>
<TextInput
style={styles.input}
placeholder="e.g., Main wallet mnemonic"
placeholderTextColor={colors.nautical.sage}
value={newLabel}
onChangeText={setNewLabel}
/>
*/
// 新代码:
const renderTitleInput = () => (
<LabeledInput
label="TREASURE TITLE"
placeholder="e.g., Main wallet mnemonic"
value={addFlow.state.label}
onChangeText={addFlow.setLabel}
/>
);
// 在 Add Modal 内容步骤中(第 1305-1315 行):
/*
<Text style={styles.modalLabel}>CONTENT</Text>
<TextInput
style={[styles.input, styles.inputMultiline]}
placeholder="Enter content to seal (plaintext is encrypted locally before upload)"
placeholderTextColor={colors.nautical.sage}
value={treasureContent}
onChangeText={setTreasureContent}
multiline
numberOfLines={6}
textAlignVertical="top"
/>
*/
// 新代码:
const renderContentInput = () => (
<LabeledInput
label="CONTENT"
placeholder="Enter content to seal (plaintext is encrypted locally before upload)"
value={addFlow.state.content}
onChangeText={addFlow.setContent}
multiline
/>
);
// ============================================
// 7. 在 Modal 中使用 VaultButton
// ============================================
// 原来的模态框按钮代码(第 1428-1481 行):
/*
<View style={styles.modalButtons}>
<TouchableOpacity
style={styles.cancelButton}
onPress={() => {
if (addStep === 1) {
setShowAddModal(false);
setTreasureContent('');
clearAddError();
} else {
setAddStep(addStep - 1);
clearAddError();
}
}}
>
<Text style={styles.cancelButtonText}>
{addStep === 1 ? 'Cancel' : 'Back'}
</Text>
</TouchableOpacity>
{addStep < 3 ? (
<TouchableOpacity
style={styles.confirmButton}
onPress={() => setAddStep(addStep + 1)}
>
<LinearGradient
colors={[colors.nautical.teal, colors.nautical.seafoam]}
style={styles.confirmButtonGradient}
start={{ x: 0, y: 0 }}
end={{ x: 1, y: 0 }}
>
<Text style={styles.confirmButtonText}>Continue</Text>
</LinearGradient>
</TouchableOpacity>
) : (
<TouchableOpacity
style={styles.confirmButton}
onPress={handleAddAsset}
activeOpacity={canSeal ? 0.9 : 1}
disabled={!canSeal}
>
<LinearGradient
colors={[colors.nautical.teal, colors.nautical.seafoam]}
style={[
styles.confirmButtonGradient,
!canSeal && styles.confirmButtonGradientDisabled,
]}
start={{ x: 0, y: 0 }}
end={{ x: 1, y: 0 }}
>
<MaterialCommunityIcons name="lock" size={18} color="#fff" />
<Text style={styles.confirmButtonText}>{isSealing ? 'Sealing...' : 'Seal Treasure'}</Text>
</LinearGradient>
</TouchableOpacity>
)}
</View>
*/
// 新代码:
const renderModalButtons = () => {
const canSeal = addFlow.canProceed();
return (
<View style={styles.modalButtons}>
<VaultButton
variant="secondary"
onPress={() => {
if (addFlow.state.step === 1) {
setShowAddModal(false);
addFlow.reset();
clearAddError();
} else {
addFlow.setStep(addFlow.state.step - 1);
clearAddError();
}
}}
fullWidth
>
{addFlow.state.step === 1 ? 'Cancel' : 'Back'}
</VaultButton>
{addFlow.state.step < 3 ? (
<VaultButton
variant="primary"
onPress={() => addFlow.setStep(addFlow.state.step + 1)}
fullWidth
>
Continue
</VaultButton>
) : (
<VaultButton
variant="primary"
icon="lock"
loading={isSealing}
disabled={!canSeal}
onPress={handleAddAsset}
fullWidth
>
{isSealing ? 'Sealing...' : 'Seal Treasure'}
</VaultButton>
)}
</View>
);
};
// ============================================
// 8. 使用 Hook 访问状态的示例
// ============================================
// 原来访问状态的方式:
// if (addStep === 1) { ... }
// if (mnemonicStep === 3) { ... }
// setAddStep(2)
// setMnemonicWords(words)
// 新的访问方式:
// if (addFlow.state.step === 1) { ... }
// if (mnemonicFlow.state.step === 3) { ... }
// addFlow.setStep(2)
// mnemonicFlow.setWords(words)
return (
// ... 使用上面定义的渲染函数
);
}
// ============================================
// 9. 可以删除的代码
// ============================================
/*
重构后可以删除以下内容:
1. 大量的状态变量声明(第 111-167 行)
2. assetAnimations ref 和相关逻辑(第 171 行及使用处)
3. 资产卡片的动画代码(已移到 AssetCard 组件)
4. 所有重复的按钮样式定义
5. 所有重复的输入框样式定义
StyleSheet 中可以删除:
- unlockButton, unlockButtonGradient, unlockButtonText
- addButton, addButtonGradient, addButtonText
- assetCard, assetIconContainer, assetInfo, assetType, assetLabel, assetMetaRow, assetMeta, encryptedBadge
- 大部分 modal 相关的样式(已移到 modalStyles.ts
*/
// ============================================
// 10. 性能优化建议
// ============================================
/*
1. 使用 React.memo 包装 AssetCard 避免不必要的重渲染
2. 使用 useCallback 包装事件处理函数
3. 考虑使用 FlatList 替代 ScrollView如果资产列表很长
4. 延迟加载模态框组件React.lazy
示例:
const AssetList = React.memo(({ assets, onOpenDetail }) => (
assets.map((asset, index) => (
<AssetCard key={asset.id} asset={asset} index={index} onPress={onOpenDetail} />
))
));
const handleOpenDetail = useCallback((asset: VaultAsset) => {
setSelectedAsset(asset);
setShowDetail(true);
}, []);
*/