import React, { useEffect, useState, useCallback, useContext, useRef } from 'react'; import { Link, router, useLocalSearchParams, useNavigation, useFocusEffect } from 'expo-router'; import { Image as RNImage, StyleSheet, useWindowDimensions, ScrollView, Pressable, RefreshControl, Platform } from 'react-native'; import { SafeAreaView } from 'react-native-safe-area-context'; import { Icon, MD3Colors, Button, Text, TextInput, TouchableRipple } from 'react-native-paper'; import CircularProgress from 'react-native-circular-progress-indicator'; import { ActivityIndicator } from 'react-native-paper'; import uuid from 'react-native-uuid'; import Toast from 'react-native-toast-message'; import { View, AnimatePresence } from 'moti'; import * as Clipboard from 'expo-clipboard'; import * as FileSystem from 'expo-file-system'; import NetInfo from "@react-native-community/netinfo"; import JSZip from 'jszip'; import ComicStorage from '@/constants/module/storages/comic_storage'; import ChapterStorage from '@/constants/module/storages/chapter_storage'; import ChapterDataStorage from '@/constants/module/storages/chapter_data_storage'; import Image from '@/components/Image'; import {CONTEXT} from '@/constants/module/context'; import {blobToBase64, base64ToBlob} from "@/constants/module/file_manager"; import Theme from '@/constants/theme'; import { get_chapter } from '../modules/get_chapter'; const ChapterImage = ({item, zoom, showOptions, setShowOptions, setIsLoading, SET_DATA}:any)=>{ const SOURCE = useLocalSearchParams().source; const COMIC_ID = useLocalSearchParams().comic_id; const CHAPTER_IDX = Number(useLocalSearchParams().chapter_idx as string); const Dimensions = useWindowDimensions(); const {showMenuContext, setShowMenuContext}:any = useContext(CONTEXT) const {themeTypeContext, setThemeTypeContext}:any = useContext(CONTEXT) const {showCloudflareTurnstileContext, setShowCloudflareTurnstileContext}:any = useContext(CONTEXT) const [isReady, setIsReady] = useState(false); const [isError, setIsError] = useState({state:false,text:""}); const [isNavigate, setIsNavigate] = useState(false); const image = useRef(null); const image_layout = useRef(null); useEffect(()=>{(async () => { if (item.type === "page"){ const store_chapter_image_data = await ChapterDataStorage.get(item.id) if (store_chapter_image_data){ image.current = {type:"blob",data:store_chapter_image_data.data} image_layout.current = store_chapter_image_data.layout setIsReady(true) }else{ setIsError({state:true,text:"Image not found!"}) } }else setIsReady(true) })()},[]) useFocusEffect(useCallback(() => { return () => { image.current = null }; },[])) return ( { setShowOptions({type:"general",state:!showOptions.state}) }} style={{ display:"flex", width:"100%", height:"auto", borderWidth:0, alignItems:"center", }} > <>{isReady ? (<> {item.type === "page" && ( 720 ? 0.8 * Dimensions.width * (1 - zoom / 100) : `${100 - zoom}%`, aspectRatio: image_layout.current.width / image_layout.current.height, }} onLoadEnd={()=>{ image.current = "" }} /> )} {item.type === "chapter-info-banner" && ( 720 ? 0.8 * Dimensions.width * (1 - zoom / 100) : `${100 - zoom}%`, height:"auto", backgroundColor:"black", padding:16, }} > End: {item.value.last} Next: {item.value.next} )} {item.type === "no-chapter-banner" && ( 720 ? 0.8 * Dimensions.width * (1 - zoom / 100) : `${100 - zoom}%`, height:"auto", backgroundColor:"black", padding:16, }} > No more chapters on local. You can go back and download more if available. )} {item.type === "chapter-navigate" && ( 720 ? 0.8 * Dimensions.width * (1 - zoom / 100) : `${100 - zoom}%`, paddingHorizontal: 12, paddingVertical: 18, }} > { setIsNavigate(true); const stored_chapter_info = await ChapterStorage.getByIdx(`${SOURCE}-${COMIC_ID}`,item.chapter_idx-1) if (stored_chapter_info?.data_state === "completed"){ setIsLoading(true); router.replace(`/read/${SOURCE}/${COMIC_ID}/${stored_chapter_info.idx}/`) }else{ Toast.show({ type: 'info', text1: 'Chapter not download yet.', text2: "You can go back and download more.", position: "bottom", visibilityTime: 4000, text1Style:{ fontFamily:"roboto-bold", fontSize:((Dimensions.width+Dimensions.height)/2)*0.025 }, text2Style:{ fontFamily:"roboto-medium", fontSize:((Dimensions.width+Dimensions.height)/2)*0.0185, }, }); } setIsNavigate(false); }} > Previous { setIsNavigate(true); const stored_chapter_info = await ChapterStorage.getByIdx(`${SOURCE}-${COMIC_ID}`,item.chapter_idx+1) if (stored_chapter_info?.data_state === "completed"){ setIsLoading(true) const stored_comic = await ComicStorage.getByID(SOURCE, COMIC_ID) if (stored_comic.history.idx && item.chapter_idx+1 > stored_comic.history.idx) { await ComicStorage.updateHistory(SOURCE, COMIC_ID, {idx:stored_chapter_info?.idx, id:stored_chapter_info?.id, title:stored_chapter_info?.title}) } router.replace(`/read/${SOURCE}/${COMIC_ID}/${stored_chapter_info.idx}/`) }else{ Toast.show({ type: 'info', text1: 'Chapter not download yet.', text2: "You can go back and download more.", position: "bottom", visibilityTime: 4000, text1Style:{ fontFamily:"roboto-bold", fontSize:((Dimensions.width+Dimensions.height)/2)*0.025 }, text2Style:{ fontFamily:"roboto-medium", fontSize:((Dimensions.width+Dimensions.height)/2)*0.0185, }, }); } setIsNavigate(false); }} > Next )} ) : ( 720 ? 0.8 * Dimensions.width * (1 - zoom / 100) : `${100 - zoom}%`, height: Dimensions.height * 0.75 }} > {isError.state ? ( {isError.text} ) : () } ) } ) } export default ChapterImage