Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | 5x 5x 4x | import React from 'react';
import { Image, Modal } from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { Text, XStack, YStack } from 'tamagui';
import { Button } from '@/src/design-system/components';
import { IconSymbol } from '@/src/components/ui/IconSymbol';
interface PhotoPreviewProps {
/** 照片 URI */
photoUri: string | null;
/** 是否显示 */
visible: boolean;
/** 确认使用照片 */
onConfirm: () => void;
/** 重新拍照 */
onRetake: () => void;
/** 取消 */
onCancel: () => void;
}
/**
* 照片预览组件
*
* 功能:
* - 显示刚拍摄的照片预览
* - 提供确认使用、重拍、取消三个操作
* - 全屏显示,提供更好的查看体验
*
* 设计原则:
* - Modal 使用 React Native 原生组件
* - 布局使用 Tamagui 组件保持一致性
* - 提供清晰的操作按钮和视觉反馈
*
* @example
* ```tsx
* <PhotoPreview
* photoUri={photoUri}
* visible={showPreview}
* onConfirm={handleConfirm}
* onRetake={handleRetake}
* onCancel={handleCancel}
* />
* ```
*/
export function PhotoPreview({
photoUri,
visible,
onConfirm,
onRetake,
onCancel,
}: PhotoPreviewProps) {
const insets = useSafeAreaInsets();
if (!photoUri) return null;
return (
<Modal visible={visible} animationType="fade" statusBarTranslucent>
<YStack flex={1} backgroundColor="black">
{/* 顶部操作栏 */}
<XStack
paddingTop={insets.top + 10}
paddingHorizontal="$4"
paddingBottom="$3"
justifyContent="space-between"
alignItems="center"
backgroundColor="rgba(0, 0, 0, 0.7)"
>
<Button size="sm" variant="ghost" rounded onPress={onCancel}>
<IconSymbol name="xmark" size={24} color="white" />
</Button>
<Text fontSize="$6" fontWeight="600" color="white">
照片预览
</Text>
<YStack width={40} height={40} />
</XStack>
{/* 照片预览区域 */}
<YStack flex={1} justifyContent="center" alignItems="center" padding="$4">
<Image
source={{ uri: photoUri }}
style={{ width: '100%', height: '100%' }}
resizeMode="contain"
/>
</YStack>
{/* 底部操作按钮 */}
<YStack
paddingHorizontal="$4"
paddingBottom={insets.bottom + 20}
paddingTop="$4"
backgroundColor="rgba(0, 0, 0, 0.7)"
gap="$3"
>
{/* 提示文本 */}
<Text fontSize="$3" color="$gray10" textAlign="center">
请确认照片清晰可见,配料表信息完整
</Text>
{/* 操作按钮组 */}
<XStack gap="$3">
{/* 重拍按钮 */}
<Button
flex={1}
size="lg"
variant="secondary"
onPress={onRetake}
leftIcon={<IconSymbol name="camera.rotate" size={20} color="white" />}
>
重新拍照
</Button>
{/* 确认按钮 */}
<Button
flex={1}
size="lg"
variant="primary"
onPress={onConfirm}
leftIcon={<IconSymbol name="checkmark.circle.fill" size={20} color="white" />}
>
确认使用
</Button>
</XStack>
</YStack>
</YStack>
</Modal>
);
}
|