import { ChapterContent } from '@/components/memoir/ChapterContent'; import { ChapterItem } from '@/components/memoir/ChapterItem'; import { FullMemoirContent } from '@/components/memoir/FullMemoirContent'; import { AppColors } from '@/constants/theme'; import { Chapter, mockMemoir } from '@/data/mockData'; import { Ionicons } from '@expo/vector-icons'; import React, { useEffect, useState } from 'react'; import { Dimensions, Modal, Platform, Pressable, ScrollView, StyleSheet, Text, TouchableOpacity, View, } from 'react-native'; import Animated, { Easing, useAnimatedStyle, useSharedValue, withTiming, } from 'react-native-reanimated'; import { SafeAreaView } from 'react-native-safe-area-context'; const { width: SCREEN_WIDTH } = Dimensions.get('window'); type ViewType = 'toc' | 'chapter' | 'fullRead'; export default function MemoirScreen() { const [currentView, setCurrentView] = useState('toc'); const [selectedChapter, setSelectedChapter] = useState(null); const [showMoreMenu, setShowMoreMenu] = useState(false); // Animation values const tocTranslateX = useSharedValue(0); const readingTranslateX = useSharedValue(SCREEN_WIDTH); const isReading = currentView === 'chapter' || currentView === 'fullRead'; useEffect(() => { if (isReading) { // Slide reading view in from right tocTranslateX.value = withTiming(-SCREEN_WIDTH * 0.3, { duration: 300, easing: Easing.out(Easing.cubic), }); readingTranslateX.value = withTiming(0, { duration: 300, easing: Easing.out(Easing.cubic), }); } else { // Slide reading view out to right tocTranslateX.value = withTiming(0, { duration: 300, easing: Easing.out(Easing.cubic), }); readingTranslateX.value = withTiming(SCREEN_WIDTH, { duration: 300, easing: Easing.out(Easing.cubic), }); } }, [isReading]); const tocAnimatedStyle = useAnimatedStyle(() => ({ transform: [{ translateX: tocTranslateX.value }], })); const readingAnimatedStyle = useAnimatedStyle(() => ({ transform: [{ translateX: readingTranslateX.value }], })); const handleChapterPress = (chapter: Chapter) => { setSelectedChapter(chapter); setCurrentView('chapter'); }; const handleBackToToc = () => { setCurrentView('toc'); setTimeout(() => { setSelectedChapter(null); }, 300); }; const handleReadAll = () => { setCurrentView('fullRead'); setSelectedChapter(null); }; const handleExportPdf = () => { setShowMoreMenu(false); console.log('Export PDF pressed'); }; const handleShare = () => { setShowMoreMenu(false); console.log('Share pressed'); }; return ( {/* TOC View */} 回忆录 {/* Book Info */} {mockMemoir.title} {mockMemoir.subtitle} 更新于 {mockMemoir.updatedAt} {/* Chapter List */} {mockMemoir.chapters.map((chapter) => ( handleChapterPress(chapter)} /> ))} {/* Read All Button */} {mockMemoir.chapters.length > 0 && ( 阅读全文 )} {/* Reading View */} 返回目录 setShowMoreMenu(true)} activeOpacity={0.7} > {currentView === 'fullRead' ? ( ) : selectedChapter ? ( ) : null} {/* More Menu Modal */} setShowMoreMenu(false)} > setShowMoreMenu(false)} > 导出 PDF 分享 ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: AppColors.mediumPurple, }, contentWrapper: { flex: 1, position: 'relative', overflow: 'hidden', }, tocView: { position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, }, readingView: { position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, backgroundColor: AppColors.mediumPurple, }, purpleHeader: { height: 62, paddingHorizontal: 20, justifyContent: 'center', backgroundColor: AppColors.mediumPurple, }, purpleHeaderTitle: { fontSize: 32, fontWeight: '600', color: AppColors.white, }, readingHeader: { height: 62, flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', backgroundColor: AppColors.mediumPurple, paddingHorizontal: 16, }, backButton: { flexDirection: 'row', alignItems: 'center', }, backButtonText: { fontSize: 16, color: AppColors.white, marginLeft: 4, }, moreButton: { width: 40, height: 40, borderRadius: 20, alignItems: 'center', justifyContent: 'center', }, tocContainer: { flex: 1, backgroundColor: AppColors.cream, }, tocContent: { padding: 20, paddingBottom: 120, }, bookHeader: { alignItems: 'center', marginBottom: 24, paddingVertical: 20, backgroundColor: AppColors.white, borderRadius: 16, shadowColor: AppColors.deepPurple, shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.06, shadowRadius: 12, elevation: 2, }, bookTitle: { fontSize: 24, fontWeight: '600', color: AppColors.deepPurple, marginBottom: 6, }, bookSubtitle: { fontSize: 13, color: AppColors.slatePurple, }, bookUpdate: { fontSize: 12, color: AppColors.mediumPurple, marginTop: 6, }, readingContainer: { flex: 1, backgroundColor: AppColors.cream, }, floatingActions: { position: 'absolute', bottom: Platform.OS === 'ios' ? 100 : 80, left: 0, right: 0, alignItems: 'center', paddingHorizontal: 20, }, readAllButton: { flexDirection: 'row', alignItems: 'center', paddingVertical: 14, paddingHorizontal: 32, borderRadius: 25, backgroundColor: AppColors.mediumPurple, gap: 8, shadowColor: AppColors.deepPurple, shadowOffset: { width: 0, height: 4 }, shadowOpacity: 0.2, shadowRadius: 12, elevation: 4, }, readAllButtonText: { fontSize: 16, fontWeight: '600', color: AppColors.white, }, modalOverlay: { flex: 1, backgroundColor: 'rgba(0, 0, 0, 0.3)', justifyContent: 'flex-start', alignItems: 'flex-end', paddingTop: Platform.OS === 'ios' ? 110 : 90, paddingRight: 20, }, menuContainer: { backgroundColor: AppColors.white, borderRadius: 12, paddingVertical: 8, minWidth: 160, shadowColor: AppColors.deepPurple, shadowOffset: { width: 0, height: 4 }, shadowOpacity: 0.15, shadowRadius: 16, elevation: 8, }, menuItem: { flexDirection: 'row', alignItems: 'center', paddingVertical: 12, paddingHorizontal: 16, gap: 12, }, menuItemText: { fontSize: 15, color: AppColors.deepPurple, }, menuDivider: { height: 1, backgroundColor: 'rgba(32, 0, 40, 0.08)', marginHorizontal: 16, }, });