ComicMTL / frontend /app /recent /components /comic_component.tsx
BloodyInside's picture
12-1-2024
cd23862
import React, { useEffect, useState, useCallback, useContext, useRef, useMemo } from 'react';
import { Link, router, useLocalSearchParams, useFocusEffect } from 'expo-router';
import { Image as RNImage, StyleSheet, useWindowDimensions, ScrollView, Pressable, RefreshControl, Platform, FlatList, TouchableOpacity } 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 { FlashList } from "@shopify/flash-list";
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 { Marquee } from '@animatereactnative/marquee';
import { Slider } from '@rneui/themed-edge';
import { __styles } from '../stylesheet/styles';
import Storage from '@/constants/module/storages/storage';
import ChapterStorage from '@/constants/module/storages/chapter_storage';
import CoverStorage from '@/constants/module/storages/cover_storage';
import Image from '@/components/Image';
import {CONTEXT} from '@/constants/module/context';
import {blobToBase64, base64ToBlob, getImageLayout} from "@/constants/module/file_manager";
import Theme from '@/constants/theme';
import ComicStorage from '@/constants/module/storages/comic_storage';
const ComicComponent = ({index, item, SELECTED_BOOKMARK, SET_SELECTED_BOOKMARK}:any) => {
const Dimensions = useWindowDimensions();
const controller = new AbortController();
const signal = controller.signal;
const {showMenuContext, setShowMenuContext}:any = useContext(CONTEXT)
const {themeTypeContext, setThemeTypeContext}:any = useContext(CONTEXT)
const {apiBaseContext, setApiBaseContext}:any = useContext(CONTEXT)
const {widgetContext, setWidgetContext}:any = useContext(CONTEXT)
const {showCloudflareTurnstileContext, setShowCloudflareTurnstileContext}:any = useContext(CONTEXT)
const [styles, setStyles]:any = useState(null)
const [isLoading, setIsLoading] = useState<boolean>(true)
const cover:any = useRef("")
useFocusEffect(useCallback(() => {
(async ()=>{
setIsLoading(true)
setStyles(__styles(themeTypeContext,Dimensions))
const stored_bookmark = await Storage.get("bookmark") || []
console.log(stored_bookmark)
cover.current = await CoverStorage.get(`${item.source}-${item.id}`) || ""
setIsLoading(false)
})()
return () => {
cover.current = ""
controller.abort();
};
},[]))
return (<>{styles && !isLoading && <>
<>{index === 0
? <View
style={{
width:"100%",
height:"auto",
paddingHorizontal:0,
paddingVertical:18,
borderBottomWidth:2,
borderColor:Theme[themeTypeContext].border_color,
display:"flex",
flexDirection:Dimensions.width >= 700 ? "row" : "column",
justifyContent:"space-around",
alignItems:"center",
gap:12,
}}
>
<TouchableRipple
rippleColor={Theme[themeTypeContext].ripple_color_outlined}
onPress={()=>{router.navigate(`/view/${item.source}/${item.id}/?mode=local`)}}
style={{...styles.item_box, marginHorizontal:12,}}
>
<>
<Image onError={(error:any)=>{console.log("load image error",error)}} source={cover.current}
style={styles.item_cover}
contentFit="cover" transition={1000}
onLoadEnd={()=>{cover.current = ""}}
/>
</>
</TouchableRipple>
<View
style={{
flex:1,
width:"auto",
height:Dimensions.width >= 700 ? "100%" : "auto",
paddingVertical:12,
alignItems:"center",
justifyContent:"space-around",
gap:12,
}}
>
<Text style={{
color:Theme[themeTypeContext].text_color,
fontSize:((Dimensions.width+Dimensions.height)/2)*0.035,
fontFamily:"roboto-bold",
textAlign:"center",
width:"100%",
}}>{item.info.title}</Text>
<TouchableRipple
rippleColor={Theme[themeTypeContext].ripple_color_outlined}
style={{
width:Dimensions.width*0.40,
display:"flex",
flexDirection:"column",
justifyContent:"center",
padding:8,
borderRadius:Dimensions.width*0.60/2,
backgroundColor:Theme[themeTypeContext].border_color,
shadowColor: Theme[themeTypeContext].shadow_color,
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.25,
shadowRadius: 3.84,
elevation: 5,
}}
onPress={()=>{
router.replace(`/read/${item.source}/${item.id}/${item.history.idx}/`)
}}
>
<View
style={{
display:"flex",
flexDirection:"column",
gap:12,
alignItems:"center",
}}
>
<Text selectable={false}
numberOfLines={1}
style={{
color:Theme[themeTypeContext].text_color,
fontSize:((Dimensions.width+Dimensions.height)/2)*0.0225,
fontFamily:"roboto-bold",
}}
>
Continue
</Text>
<Text selectable={false}
numberOfLines={1}
style={{
color:Theme[themeTypeContext].text_color,
fontSize:((Dimensions.width+Dimensions.height)/2)*0.02,
fontFamily:"roboto-bold",
}}
>
{item.history.title}
</Text>
</View>
</TouchableRipple>
</View>
</View>
: <TouchableRipple
rippleColor={Theme[themeTypeContext].ripple_color_outlined}
onPress={()=>{router.navigate(`/view/${item.source}/${item.id}/?mode=local`)}}
style={styles.item_box}
>
<>
<Image onError={(error:any)=>{console.log("load image error",error)}} source={cover.current}
style={styles.item_cover}
contentFit="cover" transition={1000}
onLoadEnd={()=>{cover.current = ""}}
/>
<Text style={styles.item_title}>{item.info.title}</Text>
</>
</TouchableRipple>
}</>
</>}</>)
}
export default ComicComponent;