import { useState, useRef, useMemo, useCallback, useEffect } from 'react' import { View, Text, StyleSheet, Pressable, Dimensions, FlatList, Platform, } from 'react-native' import { Image } from 'expo-image' import { useTranslation } from 'react-i18next' import BottomSheet, { BottomSheetView, BottomSheetBackdrop } from '@gorhom/bottom-sheet' import { CloseIcon } from '@/components/icon' const { width: screenWidth } = Dimensions.get('window') type DrawerType = 'ai-record' | 'recent' interface AIGenerationRecordDrawerProps { visible: boolean onClose: () => void onSelectImage?: (imageUri: any) => void type?: DrawerType } // 模拟 AI 生成记录图片数据 const mockAIRecordImages = Array.from({ length: 12 }, (_, i) => ({ id: i + 1, uri: require('@/assets/images/android-icon-background.png'), })) // 模拟最近用过的图片数据 const mockRecentImages = Array.from({ length: 12 }, (_, i) => ({ id: i + 1, uri: require('@/assets/images/membership.png'), })) export default function AIGenerationRecordDrawer({ visible, onClose, onSelectImage, type = 'ai-record', }: AIGenerationRecordDrawerProps) { const { t } = useTranslation() const bottomSheetRef = useRef(null) const snapPoints = useMemo(() => ['98%'], []) useEffect(() => { if (visible) { bottomSheetRef.current?.expand() } else { bottomSheetRef.current?.close() } }, [visible]) const handleSheetChanges = useCallback((index: number) => { if (index === -1) { onClose() } }, [onClose]) const handleImageSelect = (imageSource: any) => { onSelectImage?.(imageSource) onClose() } const title = type === 'ai-record' ? t('aiGenerationRecord.title') : t('aiGenerationRecord.recentUsed') const images = type === 'ai-record' ? mockAIRecordImages : mockRecentImages const renderBackdrop = useCallback( (props: any) => ( ), [] ) const renderImageItem = ({ item, index }: { item: typeof mockAIRecordImages[0]; index: number }) => { const gap = 2 const itemWidth = (screenWidth - gap * 2) / 3 return ( handleImageSelect(item.uri)} android_ripple={{ color: 'rgba(255, 255, 255, 0.1)' }} > ) } return ( {/* 顶部标题栏 */} {title} {/* 图片网格 */} item.id.toString()} numColumns={3} contentContainerStyle={styles.imageGrid} showsVerticalScrollIndicator={false} removeClippedSubviews={Platform.OS === 'android'} maxToRenderPerBatch={Platform.OS === 'ios' ? 10 : 5} updateCellsBatchingPeriod={Platform.OS === 'ios' ? 50 : 100} initialNumToRender={Platform.OS === 'ios' ? 15 : 10} windowSize={Platform.OS === 'ios' ? 10 : 5} getItemLayout={(data, index) => { const gap = 2 const itemWidth = (screenWidth - gap * 2) / 3 const rowIndex = Math.floor(index / 3) return { length: itemWidth, offset: rowIndex * (itemWidth + gap), index, } }} /> ) } const styles = StyleSheet.create({ bottomSheetBackground: { backgroundColor: '#16181B', }, handleIndicator: { backgroundColor: '#666666', }, container: { flex: 1, backgroundColor: '#16181B', paddingTop: 12, }, header: { flexDirection: 'row', alignItems: 'center', justifyContent: 'center', paddingHorizontal: 16, paddingBottom: 12, position: 'relative', }, title: { color: '#F5F5F5', fontSize: 15, fontWeight: '600', }, closeButton: { position: 'absolute', right: 16, width: 24, height: 24, alignItems: 'center', justifyContent: 'center', zIndex: 10, }, imageGrid: { paddingHorizontal: 0, paddingBottom: Platform.OS === 'ios' ? 20 : 16, }, imageItem: { // aspectRatio = width / height // 1 : 1.3 (width : height) => 1 / 1.3 aspectRatio: 1 / 1.3, overflow: 'hidden', backgroundColor: '#262A31', }, image: { width: '100%', height: '100%', }, })