import React, { useEffect, useState, useCallback, useContext, useRef, Fragment, memo } from 'react'; import { Platform, useWindowDimensions, ScrollView } from 'react-native'; import { Icon, MD3Colors, Button, Text, TextInput, TouchableRipple, ActivityIndicator, Menu, Divider, PaperProvider, Portal } from 'react-native-paper'; import { View, AnimatePresence } from 'moti'; import Toast from 'react-native-toast-message'; import * as FileSystem from 'expo-file-system'; import axios from 'axios'; import Theme from '@/constants/theme'; import Dropdown from '@/components/dropdown'; import { CONTEXT } from '@/constants/module/context'; import Storage from '@/constants/module/storages/storage'; import ComicStorage from '@/constants/module/storages/comic_storage'; import ImageCacheStorage from '@/constants/module/storages/image_cache_storage'; import ChapterStorage from '@/constants/module/storages/chapter_storage'; import ChapterDataStorage from '@/constants/module/storages/chapter_data_storage'; interface BookmarkWidgetProps { setIsLoading: any; onRefresh: any; } const BookmarkWidget: React.FC = ({ setIsLoading, onRefresh, }) => { const Dimensions = useWindowDimensions(); const {themeTypeContext, setThemeTypeContext}:any = useContext(CONTEXT) const {widgetContext, setWidgetContext}:any = useContext(CONTEXT) const {showCloudflareTurnstileContext, setShowCloudflareTurnstileContext}:any = useContext(CONTEXT) const {apiBaseContext, setApiBaseContext}:any = useContext(CONTEXT) const [BOOKMARK_DATA, SET_BOOKMARK_DATA]: any = useState([]) const [MIGRATE_BOOKMARK_DATA, SET_MIGRATE_BOOKMARK_DATA]:any = useState([]) const [showMenuOption, setShowMenuOption]:any = useState({state:false,positions:[0,0,0,0],id:""}) const [searchTag, setSearchTag]:any = useState("") const [migrateTag,setMigrateTag]:any = useState("") const [manageBookmark, setManageBookmark]:any = useState({edit:"",delete:""}) const [createTag, setCreateTag]:any = useState({state:false,title:""}) const [removeTag, setRemoveTag]:any = useState({state:false, removing: false}) const controller = new AbortController(); const signal = controller.signal; const RenderTag = useCallback(({item}:any) =>{ const [editTag, setEditTag]:any = useState(item.value) useEffect(()=>{ },[manageBookmark]) return (<> {item.value.includes(searchTag) && ( <>{manageBookmark.edit !== item.value && manageBookmark.delete !== item.value && ( {item.label} { if (manageBookmark.edit){ setManageBookmark({...manageBookmark,edit:""}) setEditTag("") } const x = event.nativeEvent.pageX const y = event.nativeEvent.pageY setShowMenuOption({ ...showMenuOption, state: showMenuOption.id === item.value ? false : true, positions:[y+((Dimensions.width+Dimensions.height)/2)*0.0225,0,x-((Dimensions.width+Dimensions.height)/2)*0.18,0], id:showMenuOption.id === item.value ? "" : item.value, }) }} > ) } <>{manageBookmark.edit === item.value && ( } style={{ backgroundColor:Theme[themeTypeContext].background_color, borderColor:Theme[themeTypeContext].border_color, }} outlineColor={Theme[themeTypeContext].text_input_border_color} value={editTag} onChangeText={(text)=>{ setEditTag(text) }} /> { setManageBookmark({...manageBookmark,edit:""}) setEditTag("") setShowMenuOption({...showMenuOption,state:false,id:""}) }} > { const stored_bookmark = await Storage.get("bookmark"); const index = stored_bookmark.findIndex((item:string) => item === manageBookmark.edit); if (index !== -1){ stored_bookmark[index] = editTag; await Storage.store("bookmark", stored_bookmark) const stored_comics:any = await ComicStorage.getByTag(manageBookmark.edit) for (const item of stored_comics){ await ComicStorage.replaceTag(item.source, item.id, editTag) } const index_2 = BOOKMARK_DATA.findIndex((item:any) => item.value === manageBookmark.edit); if (index_2 !== -1){ BOOKMARK_DATA[index_2].label = editTag BOOKMARK_DATA[index_2].value = editTag } SET_BOOKMARK_DATA(BOOKMARK_DATA) setManageBookmark({...manageBookmark,edit:""}) setEditTag("") onRefresh(); } setShowMenuOption({...showMenuOption,state:false,id:""}) }} > ) } ) } ) } ,[Theme,themeTypeContext,manageBookmark,searchTag,removeTag,createTag,showMenuOption,MIGRATE_BOOKMARK_DATA,BOOKMARK_DATA]) const load_bookmark = async ()=>{ const stored_bookmark_data = await Storage.get("bookmark") || [] if (stored_bookmark_data.length) { const bookmark_data:Array = [] for (const item of stored_bookmark_data) { bookmark_data.push({ label:item, value:item, }) } SET_BOOKMARK_DATA(bookmark_data.sort()) }else SET_BOOKMARK_DATA([]) } useEffect(()=>{ SET_MIGRATE_BOOKMARK_DATA([{label:"None",value:""},...BOOKMARK_DATA]) },[BOOKMARK_DATA]) useEffect(()=>{ load_bookmark() return () => controller.abort(); },[]) return (<>{BOOKMARK_DATA !== null && <> <>{!createTag.state && !removeTag.state && <> <>{BOOKMARK_DATA.length ? <> { setSearchTag(event.nativeEvent.text) }} /> <>{BOOKMARK_DATA.map((item:any) => ( ) )} : <> No tag found } } <>{createTag.state && <> } style={{ backgroundColor:Theme[themeTypeContext].background_color, borderColor:Theme[themeTypeContext].border_color, }} outlineColor={Theme[themeTypeContext].text_input_border_color} value={createTag.title} onChange={(event)=>{ setCreateTag({...createTag,title:event.nativeEvent.text}) }} /> } <>{showMenuOption.state && { setManageBookmark({...manageBookmark,edit:showMenuOption.id}) setShowMenuOption({...showMenuOption,state:false}) }} > Edit { setManageBookmark({...manageBookmark,edit:"",delete:showMenuOption.id}) setShowMenuOption({...showMenuOption,state:false}) }} > Delete } <>{manageBookmark.delete && ( Delete Tag: "{manageBookmark.delete}" item.value !== manageBookmark.delete)} value={migrateTag} onChange={(async (item:any) => { setMigrateTag(item.value) })} /> <>{!migrateTag && ( Setting migration to None will remove all comics and chapters for this bookmark tag. )} <>{migrateTag ? { const stored_bookmark = await Storage.get("bookmark") const index = stored_bookmark.findIndex((item:any) => item === manageBookmark.delete) if (index === -1) return const stored_comics = await ComicStorage.getByTag(manageBookmark.delete) for (const comic of stored_comics) { const source = comic.source; const comic_id = comic.id await ComicStorage.replaceTag(source,comic_id,migrateTag) } stored_bookmark.splice(index, 1); await Storage.store("bookmark",stored_bookmark); const index_2 = BOOKMARK_DATA.findIndex((item:any) => item.value === manageBookmark.delete); if (index_2 !== -1){ BOOKMARK_DATA.splice(index_2, 1); } SET_BOOKMARK_DATA(BOOKMARK_DATA) setManageBookmark({...manageBookmark,edit:"",delete:""}) setShowMenuOption({...showMenuOption,state:false,id:""}) setMigrateTag("") onRefresh(); }} > Migrate : { const stored_bookmark = await Storage.get("bookmark"); const index = stored_bookmark.findIndex((item:any) => item === manageBookmark.delete) if (index === -1) return await ComicStorage.removeByTag(manageBookmark.delete); stored_bookmark.splice(index, 1); await Storage.store("bookmark",stored_bookmark); const index_2 = BOOKMARK_DATA.findIndex((item:any) => item.value === manageBookmark.delete); if (index_2 !== -1){ BOOKMARK_DATA.splice(index_2, 1); } SET_BOOKMARK_DATA(BOOKMARK_DATA) setManageBookmark({...manageBookmark,edit:"",delete:""}) setShowMenuOption({...showMenuOption,state:false,id:""}) setMigrateTag("") onRefresh() }} > Delete } { setShowMenuOption({...showMenuOption,state:false,id:""}) setManageBookmark({...manageBookmark,edit:"",delete:""}) }} > Cancel )} }) } export default BookmarkWidget;