BloodyInside commited on
Commit
cffd4ca
β€’
1 Parent(s): cdc95a6
Files changed (29) hide show
  1. backend/module/web_scrap/ColaManga/__pycache__/get_chapter.cpython-312.pyc +0 -0
  2. backend/module/web_scrap/ColaManga/__pycache__/get_cover.cpython-312.pyc +0 -0
  3. backend/module/web_scrap/ColaManga/get_chapter.py +2 -6
  4. backend/module/web_scrap/ColaManga/get_cover.py +7 -13
  5. backend/module/web_scrap/__pycache__/utils.cpython-312.pyc +0 -0
  6. backend/module/web_scrap/utils.py +1 -1
  7. frontend/app/_layout.tsx +1 -1
  8. frontend/app/explore/components/widgets.tsx +4 -4
  9. frontend/app/explore/index.tsx +2 -2
  10. frontend/app/explore/module/content.tsx +1 -1
  11. frontend/app/index.tsx +1 -1
  12. frontend/app/read/[source]/[comic_id]/index.tsx +373 -277
  13. frontend/app/read/components/chapter_image.tsx +1 -1
  14. frontend/app/read/components/menu/components/menu_button.tsx +1 -1
  15. frontend/app/read/components/menu/menu.tsx +1 -1
  16. frontend/app/read/modules/get_chapter.tsx +2 -2
  17. frontend/app/view/[source]/[comic_id].tsx +5 -5
  18. frontend/app/view/componenets/chapter.tsx +4 -4
  19. frontend/app/view/componenets/widgets.tsx +4 -4
  20. frontend/app/view/modules/content.tsx +4 -4
  21. frontend/app/view/modules/socket.tsx +1 -1
  22. frontend/components/Image.tsx +1 -1
  23. frontend/components/cloudflare_turnstile.tsx +1 -1
  24. frontend/components/menu/components/menu_button.tsx +1 -1
  25. frontend/components/menu/menu.tsx +1 -1
  26. frontend/constants/module/{chapter_storage.tsx β†’ storages/chapter_storage.tsx} +1 -1
  27. frontend/constants/module/{comic_storage.tsx β†’ storages/comic_storage.tsx} +0 -0
  28. frontend/constants/module/{image_cache_storage.tsx β†’ storages/image_cache_storage.tsx} +1 -1
  29. frontend/constants/module/{storage.tsx β†’ storages/storage.tsx} +0 -0
backend/module/web_scrap/ColaManga/__pycache__/get_chapter.cpython-312.pyc CHANGED
Binary files a/backend/module/web_scrap/ColaManga/__pycache__/get_chapter.cpython-312.pyc and b/backend/module/web_scrap/ColaManga/__pycache__/get_chapter.cpython-312.pyc differ
 
backend/module/web_scrap/ColaManga/__pycache__/get_cover.cpython-312.pyc CHANGED
Binary files a/backend/module/web_scrap/ColaManga/__pycache__/get_cover.cpython-312.pyc and b/backend/module/web_scrap/ColaManga/__pycache__/get_cover.cpython-312.pyc differ
 
backend/module/web_scrap/ColaManga/get_chapter.py CHANGED
@@ -59,14 +59,10 @@ def scrap(comic_id:str="",chapter_id:str="",output_dir:str=""):
59
  child_list = parent_element.find_elements(By.CLASS_NAME, "mh_comicpic")
60
 
61
  blob_list = []
62
- is_no_more = False
63
  for child in child_list:
64
- if is_no_more: break
65
- timeout = date_utils.utc_time().add(10,'second').get()
66
  while True:
67
- if date_utils.utc_time().get() >= timeout:
68
- is_no_more = True
69
- break
70
  image_element = child.find_element(By.TAG_NAME, "img")
71
  driver.execute_script("arguments[0].scrollIntoView({ behavior: 'smooth', block: 'center' });", image_element)
72
 
 
59
  child_list = parent_element.find_elements(By.CLASS_NAME, "mh_comicpic")
60
 
61
  blob_list = []
 
62
  for child in child_list:
63
+ timeout = date_utils.utc_time().add(5,'second').get()
 
64
  while True:
65
+ if date_utils.utc_time().get() > timeout: break
 
 
66
  image_element = child.find_element(By.TAG_NAME, "img")
67
  driver.execute_script("arguments[0].scrollIntoView({ behavior: 'smooth', block: 'center' });", image_element)
68
 
backend/module/web_scrap/ColaManga/get_cover.py CHANGED
@@ -3,7 +3,7 @@
3
  from ..utils import SeleniumScraper
4
  from core.settings import BASE_DIR
5
  from selenium.webdriver.common.by import By
6
-
7
  import json, base64, os, sys, time, threading
8
 
9
 
@@ -27,23 +27,19 @@ def scrap(id:int=None,cover_id:int=None):
27
  driver = scraper.driver()
28
  driver.get(url)
29
 
30
- timeout = 0
31
  while True:
32
- if timeout >= MAX_TIMEOUT: raise Exception('#1 Timed out!')
33
  page_state = driver.execute_script('return document.readyState;')
34
  if page_state == 'complete': break
35
- timeout += 1
36
- time.sleep(1)
37
 
38
  image_src_url = f'https://res.colamanga.com/comic/{cover_id}/cover.jpg'
39
 
40
  # Find the image element by its src attribute
41
- timeout = 0
42
  while True:
43
- if timeout >= MAX_TIMEOUT: raise Exception('#2 Timed out!')
44
  if len(driver.find_elements(By.CLASS_NAME, "fed-list-pics")): break
45
- timeout += 1
46
- time.sleep(1)
47
 
48
  origin_image_element = driver.find_elements(By.CLASS_NAME, "fed-list-pics")[0]
49
 
@@ -52,16 +48,14 @@ def scrap(id:int=None,cover_id:int=None):
52
 
53
  image_element = driver.find_element(By.ID, "injected_image")
54
 
55
- timeout = 0
56
  while True:
57
- if timeout >= MAX_TIMEOUT: raise Exception('#3 Timed out!')
58
  is_image_loaded = driver.execute_script(
59
  "return arguments[0].complete",
60
  image_element
61
  )
62
  if is_image_loaded: break
63
- timeout += 1
64
- time.sleep(1)
65
 
66
  DATA = None
67
 
 
3
  from ..utils import SeleniumScraper
4
  from core.settings import BASE_DIR
5
  from selenium.webdriver.common.by import By
6
+ from backend.module.utils import date_utils
7
  import json, base64, os, sys, time, threading
8
 
9
 
 
27
  driver = scraper.driver()
28
  driver.get(url)
29
 
30
+ timeout = date_utils.utc_time().add(MAX_TIMEOUT,'second').get()
31
  while True:
32
+ if date_utils.utc_time().get() >= timeout: raise Exception('#1 Timed out!')
33
  page_state = driver.execute_script('return document.readyState;')
34
  if page_state == 'complete': break
 
 
35
 
36
  image_src_url = f'https://res.colamanga.com/comic/{cover_id}/cover.jpg'
37
 
38
  # Find the image element by its src attribute
39
+ timeout = date_utils.utc_time().add(MAX_TIMEOUT,'second').get()
40
  while True:
41
+ if date_utils.utc_time().get() >= timeout: raise Exception('#2 Timed out!')
42
  if len(driver.find_elements(By.CLASS_NAME, "fed-list-pics")): break
 
 
43
 
44
  origin_image_element = driver.find_elements(By.CLASS_NAME, "fed-list-pics")[0]
45
 
 
48
 
49
  image_element = driver.find_element(By.ID, "injected_image")
50
 
51
+ timeout = date_utils.utc_time().add(MAX_TIMEOUT,'second').get()
52
  while True:
53
+ if date_utils.utc_time().get() >= timeout: raise Exception('#3 Timed out!')
54
  is_image_loaded = driver.execute_script(
55
  "return arguments[0].complete",
56
  image_element
57
  )
58
  if is_image_loaded: break
 
 
59
 
60
  DATA = None
61
 
backend/module/web_scrap/__pycache__/utils.cpython-312.pyc CHANGED
Binary files a/backend/module/web_scrap/__pycache__/utils.cpython-312.pyc and b/backend/module/web_scrap/__pycache__/utils.cpython-312.pyc differ
 
backend/module/web_scrap/utils.py CHANGED
@@ -13,7 +13,7 @@ import time, threading
13
  class SeleniumScraper:
14
  def __init__(self):
15
  options = Options()
16
- # options.add_argument("--headless")
17
  options.add_argument('--no-sandbox')
18
  options.add_argument("--no-quit")
19
  options.add_argument('--disable-extensions')
 
13
  class SeleniumScraper:
14
  def __init__(self):
15
  options = Options()
16
+ options.add_argument("--headless")
17
  options.add_argument('--no-sandbox')
18
  options.add_argument("--no-quit")
19
  options.add_argument('--disable-extensions')
frontend/app/_layout.tsx CHANGED
@@ -7,7 +7,7 @@ import { useWindowDimensions, View, Text, Pressable } from 'react-native';
7
  import 'react-native-reanimated';
8
  import { SafeAreaView } from 'react-native-safe-area-context';
9
  import Menu from '@/components/menu/menu';
10
- import Storage from '@/constants/module/storage';
11
  import { useColorScheme } from '@/hooks/useColorScheme';
12
  import Toast, { SuccessToast } from 'react-native-toast-message';
13
  import type { BaseToastProps } from 'react-native-toast-message';
 
7
  import 'react-native-reanimated';
8
  import { SafeAreaView } from 'react-native-safe-area-context';
9
  import Menu from '@/components/menu/menu';
10
+ import Storage from '@/constants/module/storages/storage';
11
  import { useColorScheme } from '@/hooks/useColorScheme';
12
  import Toast, { SuccessToast } from 'react-native-toast-message';
13
  import type { BaseToastProps } from 'react-native-toast-message';
frontend/app/explore/components/widgets.tsx CHANGED
@@ -11,10 +11,10 @@ import axios from 'axios';
11
  import Theme from '@/constants/theme';
12
  import Dropdown from '@/components/dropdown';
13
  import { CONTEXT } from '@/constants/module/context';
14
- import Storage from '@/constants/module/storage';
15
- import ComicStorage from '@/constants/module/comic_storage';
16
- import ImageCacheStorage from '@/constants/module/image_cache_storage';
17
- import ChapterStorage from '@/constants/module/chapter_storage';
18
 
19
  export const PageNavigationWidget = ({setPage}:any) =>{
20
  const Dimensions = useWindowDimensions();
 
11
  import Theme from '@/constants/theme';
12
  import Dropdown from '@/components/dropdown';
13
  import { CONTEXT } from '@/constants/module/context';
14
+ import Storage from '@/constants/module/storages/storage';
15
+ import ComicStorage from '@/constants/module/storages/comic_storage';
16
+ import ImageCacheStorage from '@/constants/module/storages/image_cache_storage';
17
+ import ChapterStorage from '@/constants/module/storages/chapter_storage';
18
 
19
  export const PageNavigationWidget = ({setPage}:any) =>{
20
  const Dimensions = useWindowDimensions();
frontend/app/explore/index.tsx CHANGED
@@ -10,8 +10,8 @@ import Dropdown from '@/components/dropdown';
10
 
11
  import Theme from '@/constants/theme';
12
  import { __styles } from './stylesheet/show_list_styles';
13
- import Storage from '@/constants/module/storage';
14
- import ImageStorage from '@/constants/module/image_cache_storage';
15
  import { CONTEXT } from '@/constants/module/context';
16
  import { get_list } from '@/app/explore/module/content'
17
  import { transformAsync } from '@babel/core';
 
10
 
11
  import Theme from '@/constants/theme';
12
  import { __styles } from './stylesheet/show_list_styles';
13
+ import Storage from '@/constants/module/storages/storage';
14
+ import ImageStorage from '@/constants/module/storages/image_cache_storage';
15
  import { CONTEXT } from '@/constants/module/context';
16
  import { get_list } from '@/app/explore/module/content'
17
  import { transformAsync } from '@babel/core';
frontend/app/explore/module/content.tsx CHANGED
@@ -1,6 +1,6 @@
1
  import axios from 'axios';
2
  import translator from '@/constants/module/translator';
3
- import Storage from '@/constants/module/storage';
4
 
5
  export const get_list = async (setShowCloudflareTurnstile:any,setFeedBack:any,signal:AbortSignal,setIsLoading:any,translate:any,SET_CONTENT:any,search:any,page:number) => {
6
  const API_BASE = await Storage.get("IN_USE_API_BASE")
 
1
  import axios from 'axios';
2
  import translator from '@/constants/module/translator';
3
+ import Storage from '@/constants/module/storages/storage';
4
 
5
  export const get_list = async (setShowCloudflareTurnstile:any,setFeedBack:any,signal:AbortSignal,setIsLoading:any,translate:any,SET_CONTENT:any,search:any,page:number) => {
6
  const API_BASE = await Storage.get("IN_USE_API_BASE")
frontend/app/index.tsx CHANGED
@@ -9,7 +9,7 @@ const Index = () => {
9
  const pathname = usePathname()
10
 
11
  if (pathname === "/" || pathname === "") return (
12
- <Redirect href="/read/colamanga/manga-nf048578?idx=1" />
13
  )
14
 
15
  }
 
9
  const pathname = usePathname()
10
 
11
  if (pathname === "/" || pathname === "") return (
12
+ <Redirect href="/read/colamanga/manga-nf048578?idx=165" />
13
  )
14
 
15
  }
frontend/app/read/[source]/[comic_id]/index.tsx CHANGED
@@ -17,8 +17,8 @@ import NetInfo from "@react-native-community/netinfo";
17
  import { Marquee } from '@animatereactnative/marquee';
18
  import { Slider } from '@rneui/themed-edge';
19
 
20
- import Storage from '@/constants/module/storage';
21
- import ChapterStorage from '@/constants/module/chapter_storage';
22
  import Image from '@/components/Image';
23
  import {CONTEXT} from '@/constants/module/context';
24
  import {blobToBase64, base64ToBlob, getImageLayout} from "@/constants/module/file_manager";
@@ -27,7 +27,7 @@ import ChapterImage from '../../components/chapter_image';
27
  import Menu from '../../components/menu/menu';
28
  import Disqus from '../../components/disqus';
29
  import { get_chapter } from '../../modules/get_chapter';
30
- import ComicStorage from '@/constants/module/comic_storage';
31
 
32
  const Index = ({}:any) => {
33
  const SOURCE = useLocalSearchParams().source;
@@ -41,6 +41,7 @@ const Index = ({}:any) => {
41
  const {showCloudflareTurnstileContext, setShowCloudflareTurnstileContext}:any = useContext(CONTEXT)
42
  const {apiBaseContext, setApiBaseContext}:any = useContext(CONTEXT)
43
 
 
44
  const [firstLoading, setFirstLoading]:any = useState(true)
45
  const [chapterInfo, setChapterInfo]:any = useState({})
46
  const [showOptions, setShowOptions]:any = useState({type:"general",state:false})
@@ -60,9 +61,19 @@ const Index = ({}:any) => {
60
  setShowMenuContext(false)
61
  },[])
62
 
 
63
  useEffect(()=>{(async () => {
 
 
 
 
64
  temp_loading.current = true
65
  const stored_chapter = await ChapterStorage.getByIdx(`${SOURCE}-${COMIC_ID}`,CHAPTER_IDX.current, {exclude_fields:["data"]})
 
 
 
 
 
66
  setChapterInfo({
67
  chapter_id: stored_chapter?.id,
68
  chapter_idx: stored_chapter?.id,
@@ -70,6 +81,8 @@ const Index = ({}:any) => {
70
  })
71
  const stored_chapter_zoom = await Storage.get("CHAPTER_ZOOM") || 0
72
  setZoom(stored_chapter_zoom)
 
 
73
 
74
  const chapter_current = await get_chapter(SOURCE,COMIC_ID,CHAPTER_IDX.current)
75
  if (chapter_current){
@@ -152,319 +165,402 @@ const Index = ({}:any) => {
152
  },[imageKeys, addChapter])
153
 
154
 
155
- return (<>{!firstLoading
156
- ? <>
157
- <View
158
-
159
  style={{
 
 
 
160
  width:"100%",
161
  height:"100%",
162
  backgroundColor:Theme[themeTypeContext].background_color,
163
- zIndex:0
164
  }}
165
- >
166
- <FlashList
167
- data={imageKeys}
168
- renderItem={({item,index}:any) => {
169
- if (item.type === "image"){
170
- item.image_data = images.current[item.value].data
171
- item.layout = images.current[item.value].layout
172
- }
173
- return <ChapterImage key={index} item={item} zoom={zoom} showOptions={showOptions} setShowOptions={setShowOptions}/>
 
 
 
 
 
 
174
  }}
175
- estimatedItemSize={StaticDimensions.height}
176
- extraData={{zoom:zoom,showOptions:showOptions,setShowOptions:setShowOptions}}
177
- onEndReachedThreshold={0.5}
178
- onEndReached={()=>{
179
- setAddChapter(true)
180
- }}
181
- onViewableItemsChanged={async ({ viewableItems, changed }) => {
182
- const expect_chapter_idx = [CHAPTER_IDX.current + 1, CHAPTER_IDX.current - 1]
183
- const current_count = viewableItems.filter((data:any) => data.item.idx === CHAPTER_IDX.current).length
184
- const existed_count = viewableItems.filter((data:any) => expect_chapter_idx.includes(data.item.idx)).length
185
-
186
- if (current_count || existed_count){
187
- const choose_idx = current_count > existed_count ? CHAPTER_IDX.current : viewableItems.find((data:any) => expect_chapter_idx.includes(data.item.idx))?.item.idx
188
- if (choose_idx === CHAPTER_IDX.current) return
189
- const stored_chapter = await ChapterStorage.getByIdx(`${SOURCE}-${COMIC_ID}`,choose_idx, {exclude_fields:["data"]})
190
- setChapterInfo({
191
- chapter_id: stored_chapter?.id,
192
- chapter_idx: stored_chapter?.id,
193
- title: stored_chapter?.title,
194
- })
195
- const stored_comic = await ComicStorage.getByID(SOURCE, COMIC_ID)
196
- if (stored_comic.history.idx && choose_idx > stored_comic.history.idx) {
197
- await ComicStorage.updateHistory(SOURCE, COMIC_ID, {idx:stored_chapter?.idx,id:stored_chapter?.id,title:stored_chapter?.title})
198
- }
199
- router.setParams({idx:choose_idx})
200
- CHAPTER_IDX.current = choose_idx
201
- }
202
-
203
 
204
- }}
205
- />
206
- {isLoading && (
 
 
 
207
  <View
208
  style={{
209
- display:"flex",
210
- width:"100%",
211
- height:"auto",
212
- justifyContent:"center",
213
- padding:16,
214
  }}
215
  >
216
- <ActivityIndicator animating={true} size={(0.03 * ((Dimensions.width+Dimensions.height)/2)) * (1 - zoom/100)}/>
 
 
 
 
 
 
 
 
 
217
  </View>
218
- )}
219
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
220
  </View>
221
- <AnimatePresence exitBeforeEnter>
222
- {showOptions.state &&
223
  <View
 
224
  style={{
225
- position:"absolute",
226
  width:"100%",
227
  height:"100%",
228
- display:"flex",
229
- flexDirection:"column",
230
- zIndex:1,
231
  }}
232
- >
233
- <>{showOptions.type === "general" && <>
234
- <Pressable
235
- onPress={()=>{setShowOptions({...showOptions,state:!showOptions.state})}}
236
- style={{flex:1,backgroundColor:"rgba(0,0,0,0.5)",pointerEvents:"auto"}}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
237
  >
238
- <View
239
- id='reading-options'
240
- style={{
241
- flex:1,
242
- display:"flex",
243
- flexDirection:"column",
244
- alignItems:"flex-start",
245
- backgroundColor:"transparent",
246
- pointerEvents:"auto",
247
- }}
248
- from={{
249
- opacity: 0,
250
- }}
251
- animate={{
252
- opacity: 1,
253
-
254
- }}
255
- exit={{
256
- opacity: 0,
257
- }}
258
- transition={{
259
- type: 'timing',
260
- duration: 500,
261
- }}
262
- exitTransition={{
263
- type: 'timing',
264
- duration: 250,
265
- }}
266
- >
267
-
268
- <View
269
  style={{
270
- width:"100%",
271
- height:"auto",
272
  display:"flex",
273
- flexDirection:"row",
274
- justifyContent:"space-between",
275
- alignItems:"center",
276
- padding:16,
277
- gap:8,
278
- backgroundColor:Theme[themeTypeContext].background_color,
279
- borderBottomWidth:2,
280
- borderColor:Theme[themeTypeContext].border_color,
281
  pointerEvents:"auto",
282
  }}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
283
  >
284
- <TouchableRipple
285
- rippleColor={Theme[themeTypeContext].ripple_color_outlined}
286
- style={{
287
- borderRadius:5,
288
- borderWidth:0,
289
- backgroundColor: "transparent",
290
- padding:5,
291
-
292
- }}
293
-
294
- onPress={()=>{
295
- router.replace(`/view/${SOURCE}/${COMIC_ID}/`)
296
- }}
297
- >
298
- <Icon source={"arrow-left-thin"} size={((Dimensions.width+Dimensions.height)/2)*0.05} color={Theme[themeTypeContext].icon_color}/>
299
- </TouchableRipple>
300
- <View
301
- style={{
302
- flex:1,
303
- }}
304
- >
305
- <Text selectable={false}
306
- numberOfLines={1}
307
  style={{
308
- color:Theme[themeTypeContext].text_color,
309
- fontSize:((Dimensions.width+Dimensions.height)/2)*0.045,
310
- fontFamily:"roboto-bold",
 
 
 
 
 
 
 
 
 
311
  }}
312
  >
313
- {chapterInfo.title}
314
- </Text>
315
- </View>
316
- <TouchableRipple
317
- rippleColor={Theme[themeTypeContext].ripple_color_outlined}
318
- style={{
319
- borderRadius:5,
320
- borderWidth:0,
321
- backgroundColor: "transparent",
322
- padding:5,
323
- }}
324
-
325
- onPress={()=>{
326
- console.log("HO2h2")
327
- }}
328
- >
329
- <Icon source={"cloud-refresh"} size={((Dimensions.width+Dimensions.height)/2)*0.05} color={Theme[themeTypeContext].icon_color}/>
330
- </TouchableRipple>
331
- </View>
332
- <View
333
- style={{
334
- display:"flex",
335
- flexDirection:"column",
336
- width:"100%",
337
- flex:1,
338
- padding:16,
339
- alignItems:"flex-end",
340
- gap:12,
341
- justifyContent:"center",
342
- }}
343
- >
344
- <View style={{width:"auto",height:"auto",display:"flex",flexDirection:"column",alignItems:"center",gap:8, pointerEvents:"auto"}}>
345
- <View style={{
346
- width:"auto",
347
- height:"auto",
348
- backgroundColor: 'rgba(0, 0, 0, 0.5)',
349
- paddingHorizontal:12,
350
- paddingVertical:12,
351
- borderRadius:12,
352
-
353
- }}>
354
- <Slider
355
- style={{
356
- width: ((Dimensions.width+Dimensions.height)/2)*0.06,
357
- height: Dimensions.height*0.525,
358
- pointerEvents:"auto",
359
- }}
360
- value={zoom}
361
- onValueChange={async (value)=>{
362
- await Storage.store("CHAPTER_ZOOM", value)
363
- setZoom(value)
364
  }}
365
 
366
- maximumValue={80}
367
- minimumValue={-80}
368
- step={1}
369
-
370
- orientation="vertical"
371
-
372
- minimumTrackTintColor={Theme[themeTypeContext].text_color}
373
- maximumTrackTintColor={Theme[themeTypeContext].border_color}
374
-
375
- thumbStyle={{
376
- height: "auto",
377
- width: "auto",
378
- backgroundColor: Theme[themeTypeContext].background_color,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
379
  padding:5,
380
-
381
  }}
382
- thumbProps={{children: (<>
383
- <>{zoom < 0
384
- && <Icon source={"magnify-plus-outline"} size={((Dimensions.width+Dimensions.height)/2)*0.05} color={Theme[themeTypeContext].icon_color}/>
385
- }</>
386
- <>{zoom === 0
387
- && <Icon source={"magnify"} size={((Dimensions.width+Dimensions.height)/2)*0.05} color={Theme[themeTypeContext].icon_color}/>
388
- }</>
389
- <>{zoom > 0
390
- && <Icon source={"magnify-minus-outline"} size={((Dimensions.width+Dimensions.height)/2)*0.05} color={Theme[themeTypeContext].icon_color}/>
391
- }</>
392
- </>)}}
393
-
394
 
395
- />
396
-
 
 
 
 
397
  </View>
398
- <TouchableRipple
399
- rippleColor={Theme[themeTypeContext].ripple_color_outlined}
400
  style={{
401
- borderRadius:5,
402
- borderWidth:0,
403
- backgroundColor: "transparent",
404
- padding:5,
405
- pointerEvents:"auto",
406
- }}
407
-
408
- onPress={async ()=>{
409
- await Storage.store("CHAPTER_ZOOM", 0)
410
- setZoom(0)
411
  }}
412
  >
413
- <Icon source={"magnify-remove-cursor"} size={((Dimensions.width+Dimensions.height)/2)*0.05} color={Theme[themeTypeContext].icon_color}/>
414
- </TouchableRipple>
415
- </View>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
416
  </View>
417
-
418
-
419
- </View>
420
-
421
- </Pressable>
422
- </>}</>
423
- <>{showOptions.type === "comments"&& <>
424
- <View
425
- style={{
426
- width:"100%",
427
- height:"auto",
428
- padding:16,
429
- backgroundColor:Theme[themeTypeContext].background_color,
430
- borderBottomWidth:2,
431
- borderColor:Theme[themeTypeContext].border_color,
432
- }}
433
- >
434
- <Text selectable={false}
435
- numberOfLines={1}
436
- style={{
437
- color:Theme[themeTypeContext].text_color,
438
- fontSize:((Dimensions.width+Dimensions.height)/2)*0.045,
439
- fontFamily:"roboto-bold",
440
- }}
441
- >
442
- {chapterInfo.title}
443
- </Text>
444
- </View>
445
- <View
446
- style={{
447
- flex:1,
448
- backgroundColor:Theme[themeTypeContext].background_color,
449
- }}
450
- >
451
- <Disqus title={chapterInfo.title} identifier={`${SOURCE}-${COMIC_ID}-${CHAPTER_IDX.current}`} url={`${apiBaseContext}/read/${SOURCE}/${COMIC_ID}/`}
452
- paddingVertical={16} paddingHorizontal={25}
453
- />
454
  </View>
455
- </>}</>
456
- <Menu showOptions={showOptions} setShowOptions={setShowOptions}/>
457
- </View>
458
- }
459
- </AnimatePresence>
460
-
461
- </>
462
-
463
 
464
- :<View style={{zIndex:5,width:"100%",height:"100%",display:"flex",justifyContent:"center",alignItems:"center",backgroundColor:Theme[themeTypeContext].background_color}}>
465
- <Image setShowCloudflareTurnstile={setShowCloudflareTurnstileContext} source={require("@/assets/gif/cat-loading.gif")} style={{width:((Dimensions.width+Dimensions.height)/2)*0.15,height:((Dimensions.width+Dimensions.height)/2)*0.15}}/>
466
- </View>
467
- }</>)
 
 
468
 
469
 
470
  }
 
17
  import { Marquee } from '@animatereactnative/marquee';
18
  import { Slider } from '@rneui/themed-edge';
19
 
20
+ import Storage from '@/constants/module/storages/storage';
21
+ import ChapterStorage from '@/constants/module/storages/chapter_storage';
22
  import Image from '@/components/Image';
23
  import {CONTEXT} from '@/constants/module/context';
24
  import {blobToBase64, base64ToBlob, getImageLayout} from "@/constants/module/file_manager";
 
27
  import Menu from '../../components/menu/menu';
28
  import Disqus from '../../components/disqus';
29
  import { get_chapter } from '../../modules/get_chapter';
30
+ import ComicStorage from '@/constants/module/storages/comic_storage';
31
 
32
  const Index = ({}:any) => {
33
  const SOURCE = useLocalSearchParams().source;
 
41
  const {showCloudflareTurnstileContext, setShowCloudflareTurnstileContext}:any = useContext(CONTEXT)
42
  const {apiBaseContext, setApiBaseContext}:any = useContext(CONTEXT)
43
 
44
+ const [isError,setIsError]:any = useState({state:false,text:""})
45
  const [firstLoading, setFirstLoading]:any = useState(true)
46
  const [chapterInfo, setChapterInfo]:any = useState({})
47
  const [showOptions, setShowOptions]:any = useState({type:"general",state:false})
 
61
  setShowMenuContext(false)
62
  },[])
63
 
64
+ // First Load
65
  useEffect(()=>{(async () => {
66
+ if (!SOURCE || !COMIC_ID || !CHAPTER_IDX.current){
67
+ setIsError({state:true,text:"Invalid source, comic id or chapter idx!"})
68
+ return
69
+ }
70
  temp_loading.current = true
71
  const stored_chapter = await ChapterStorage.getByIdx(`${SOURCE}-${COMIC_ID}`,CHAPTER_IDX.current, {exclude_fields:["data"]})
72
+ if (stored_chapter?.data_state !== "completed"){
73
+ setIsError({state:true,text:"Chapter is not download yet!"})
74
+ return
75
+ }
76
+
77
  setChapterInfo({
78
  chapter_id: stored_chapter?.id,
79
  chapter_idx: stored_chapter?.id,
 
81
  })
82
  const stored_chapter_zoom = await Storage.get("CHAPTER_ZOOM") || 0
83
  setZoom(stored_chapter_zoom)
84
+
85
+
86
 
87
  const chapter_current = await get_chapter(SOURCE,COMIC_ID,CHAPTER_IDX.current)
88
  if (chapter_current){
 
165
  },[imageKeys, addChapter])
166
 
167
 
168
+ return (<>
169
+ {isError.state
170
+ ? <View
 
171
  style={{
172
+ display:"flex",
173
+ flexDirection:"column",
174
+ gap:8,
175
  width:"100%",
176
  height:"100%",
177
  backgroundColor:Theme[themeTypeContext].background_color,
 
178
  }}
179
+ >
180
+ <View
181
+ style={{
182
+ width:"100%",
183
+ height:"auto",
184
+ display:"flex",
185
+ flexDirection:"row",
186
+ justifyContent:"space-between",
187
+ alignItems:"center",
188
+ padding:16,
189
+ gap:8,
190
+ backgroundColor:Theme[themeTypeContext].background_color,
191
+ borderBottomWidth:2,
192
+ borderColor:Theme[themeTypeContext].border_color,
193
+ pointerEvents:"auto",
194
  }}
195
+ >
196
+ <TouchableRipple
197
+ rippleColor={Theme[themeTypeContext].ripple_color_outlined}
198
+ style={{
199
+ borderRadius:5,
200
+ borderWidth:0,
201
+ backgroundColor: "transparent",
202
+ padding:5,
203
+
204
+ }}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
205
 
206
+ onPress={()=>{
207
+ router.replace("/explore")
208
+ }}
209
+ >
210
+ <Icon source={"arrow-left-thin"} size={((Dimensions.width+Dimensions.height)/2)*0.05} color={Theme[themeTypeContext].icon_color}/>
211
+ </TouchableRipple>
212
  <View
213
  style={{
214
+ flex:1,
 
 
 
 
215
  }}
216
  >
217
+ <Text selectable={false}
218
+ numberOfLines={1}
219
+ style={{
220
+ color:Theme[themeTypeContext].text_color,
221
+ fontSize:((Dimensions.width+Dimensions.height)/2)*0.045,
222
+ fontFamily:"roboto-bold",
223
+ }}
224
+ >
225
+ Explore
226
+ </Text>
227
  </View>
228
+ </View>
229
+ <View
230
+ style={{
231
+ width:"100%",
232
+ height:"auto",
233
+ display:"flex",
234
+ justifyContent:"center",
235
+ alignItems:"center",
236
+ padding:12,
237
+ paddingTop:20,
238
+ }}
239
+ >
240
+ <Text
241
+ style={{
242
+ color:Theme[themeTypeContext].text_color,
243
+ fontFamily:"roboto-medium",
244
+ fontSize:(Dimensions.width+Dimensions.height)/2*0.03
245
+ }}
246
+ >{isError.text}</Text>
247
+ </View>
248
  </View>
249
+ : <>{!firstLoading
250
+ ? <>
251
  <View
252
+
253
  style={{
 
254
  width:"100%",
255
  height:"100%",
256
+ backgroundColor:Theme[themeTypeContext].background_color,
257
+ zIndex:0
 
258
  }}
259
+ >
260
+ <FlashList
261
+ data={imageKeys}
262
+ renderItem={({item,index}:any) => {
263
+ if (item.type === "image"){
264
+ item.image_data = images.current[item.value].data
265
+ item.layout = images.current[item.value].layout
266
+ }
267
+ return <ChapterImage key={index} item={item} zoom={zoom} showOptions={showOptions} setShowOptions={setShowOptions}/>
268
+ }}
269
+ estimatedItemSize={StaticDimensions.height}
270
+ extraData={{zoom:zoom,showOptions:showOptions,setShowOptions:setShowOptions}}
271
+ onEndReachedThreshold={0.5}
272
+ onEndReached={()=>{
273
+ setAddChapter(true)
274
+ }}
275
+ onViewableItemsChanged={async ({ viewableItems, changed }) => {
276
+ const expect_chapter_idx = [CHAPTER_IDX.current + 1, CHAPTER_IDX.current - 1]
277
+ const current_count = viewableItems.filter((data:any) => data.item.idx === CHAPTER_IDX.current).length
278
+ const existed_count = viewableItems.filter((data:any) => expect_chapter_idx.includes(data.item.idx)).length
279
+
280
+ if (current_count || existed_count){
281
+ const choose_idx = current_count > existed_count ? CHAPTER_IDX.current : viewableItems.find((data:any) => expect_chapter_idx.includes(data.item.idx))?.item.idx
282
+ if (choose_idx === CHAPTER_IDX.current) return
283
+ const stored_chapter = await ChapterStorage.getByIdx(`${SOURCE}-${COMIC_ID}`,choose_idx, {exclude_fields:["data"]})
284
+ setChapterInfo({
285
+ chapter_id: stored_chapter?.id,
286
+ chapter_idx: stored_chapter?.id,
287
+ title: stored_chapter?.title,
288
+ })
289
+ const stored_comic = await ComicStorage.getByID(SOURCE, COMIC_ID)
290
+ if (stored_comic.history.idx && choose_idx > stored_comic.history.idx) {
291
+ await ComicStorage.updateHistory(SOURCE, COMIC_ID, {idx:stored_chapter?.idx,id:stored_chapter?.id,title:stored_chapter?.title})
292
+ }
293
+ router.setParams({idx:choose_idx})
294
+ CHAPTER_IDX.current = choose_idx
295
+ }
296
+
297
+
298
+ }}
299
+ />
300
+ {isLoading && (
301
+ <View
302
+ style={{
303
+ display:"flex",
304
+ width:"100%",
305
+ height:"auto",
306
+ justifyContent:"center",
307
+ padding:16,
308
+ }}
309
  >
310
+ <ActivityIndicator animating={true} size={(0.03 * ((Dimensions.width+Dimensions.height)/2)) * (1 - zoom/100)}/>
311
+ </View>
312
+ )}
313
+
314
+ </View>
315
+ <AnimatePresence exitBeforeEnter>
316
+ {showOptions.state &&
317
+ <View
318
+ style={{
319
+ position:"absolute",
320
+ width:"100%",
321
+ height:"100%",
322
+ display:"flex",
323
+ flexDirection:"column",
324
+ zIndex:1,
325
+ }}
326
+ >
327
+ <>{showOptions.type === "general" && <>
328
+ <Pressable
329
+ onPress={()=>{setShowOptions({...showOptions,state:!showOptions.state})}}
330
+ style={{flex:1,backgroundColor:"rgba(0,0,0,0.5)",pointerEvents:"auto"}}
331
+ >
332
+ <View
333
+ id='reading-options'
 
 
 
 
 
 
 
334
  style={{
335
+ flex:1,
 
336
  display:"flex",
337
+ flexDirection:"column",
338
+ alignItems:"flex-start",
339
+ backgroundColor:"transparent",
 
 
 
 
 
340
  pointerEvents:"auto",
341
  }}
342
+ from={{
343
+ opacity: 0,
344
+ }}
345
+ animate={{
346
+ opacity: 1,
347
+
348
+ }}
349
+ exit={{
350
+ opacity: 0,
351
+ }}
352
+ transition={{
353
+ type: 'timing',
354
+ duration: 500,
355
+ }}
356
+ exitTransition={{
357
+ type: 'timing',
358
+ duration: 250,
359
+ }}
360
  >
361
+
362
+ <View
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
363
  style={{
364
+ width:"100%",
365
+ height:"auto",
366
+ display:"flex",
367
+ flexDirection:"row",
368
+ justifyContent:"space-between",
369
+ alignItems:"center",
370
+ padding:16,
371
+ gap:8,
372
+ backgroundColor:Theme[themeTypeContext].background_color,
373
+ borderBottomWidth:2,
374
+ borderColor:Theme[themeTypeContext].border_color,
375
+ pointerEvents:"auto",
376
  }}
377
  >
378
+ <TouchableRipple
379
+ rippleColor={Theme[themeTypeContext].ripple_color_outlined}
380
+ style={{
381
+ borderRadius:5,
382
+ borderWidth:0,
383
+ backgroundColor: "transparent",
384
+ padding:5,
385
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
386
  }}
387
 
388
+ onPress={()=>{
389
+ router.replace(`/view/${SOURCE}/${COMIC_ID}/`)
390
+ }}
391
+ >
392
+ <Icon source={"arrow-left-thin"} size={((Dimensions.width+Dimensions.height)/2)*0.05} color={Theme[themeTypeContext].icon_color}/>
393
+ </TouchableRipple>
394
+ <View
395
+ style={{
396
+ flex:1,
397
+ }}
398
+ >
399
+ <Text selectable={false}
400
+ numberOfLines={1}
401
+ style={{
402
+ color:Theme[themeTypeContext].text_color,
403
+ fontSize:((Dimensions.width+Dimensions.height)/2)*0.045,
404
+ fontFamily:"roboto-bold",
405
+ }}
406
+ >
407
+ {chapterInfo.title}
408
+ </Text>
409
+ </View>
410
+ <TouchableRipple
411
+ rippleColor={Theme[themeTypeContext].ripple_color_outlined}
412
+ style={{
413
+ borderRadius:5,
414
+ borderWidth:0,
415
+ backgroundColor: "transparent",
416
  padding:5,
 
417
  }}
 
 
 
 
 
 
 
 
 
 
 
 
418
 
419
+ onPress={()=>{
420
+ console.log("HO2h2")
421
+ }}
422
+ >
423
+ <Icon source={"cloud-refresh"} size={((Dimensions.width+Dimensions.height)/2)*0.05} color={Theme[themeTypeContext].icon_color}/>
424
+ </TouchableRipple>
425
  </View>
426
+ <View
 
427
  style={{
428
+ display:"flex",
429
+ flexDirection:"column",
430
+ width:"100%",
431
+ flex:1,
432
+ padding:16,
433
+ alignItems:"flex-end",
434
+ gap:12,
435
+ justifyContent:"center",
 
 
436
  }}
437
  >
438
+ <View style={{width:"auto",height:"auto",display:"flex",flexDirection:"column",alignItems:"center",gap:8, pointerEvents:"auto"}}>
439
+ <View style={{
440
+ width:"auto",
441
+ height:"auto",
442
+ backgroundColor: 'rgba(0, 0, 0, 0.5)',
443
+ paddingHorizontal:12,
444
+ paddingVertical:12,
445
+ borderRadius:12,
446
+
447
+ }}>
448
+ <Slider
449
+ style={{
450
+ width: ((Dimensions.width+Dimensions.height)/2)*0.06,
451
+ height: Dimensions.height*0.525,
452
+ pointerEvents:"auto",
453
+ }}
454
+ value={zoom}
455
+ onValueChange={async (value)=>{
456
+ await Storage.store("CHAPTER_ZOOM", value)
457
+ setZoom(value)
458
+ }}
459
+
460
+ maximumValue={80}
461
+ minimumValue={-80}
462
+ step={1}
463
+
464
+ orientation="vertical"
465
+
466
+ minimumTrackTintColor={Theme[themeTypeContext].text_color}
467
+ maximumTrackTintColor={Theme[themeTypeContext].border_color}
468
+
469
+ thumbStyle={{
470
+ height: "auto",
471
+ width: "auto",
472
+ backgroundColor: Theme[themeTypeContext].background_color,
473
+ padding:5,
474
+
475
+ }}
476
+ thumbProps={{children: (<>
477
+ <>{zoom < 0
478
+ && <Icon source={"magnify-plus-outline"} size={((Dimensions.width+Dimensions.height)/2)*0.05} color={Theme[themeTypeContext].icon_color}/>
479
+ }</>
480
+ <>{zoom === 0
481
+ && <Icon source={"magnify"} size={((Dimensions.width+Dimensions.height)/2)*0.05} color={Theme[themeTypeContext].icon_color}/>
482
+ }</>
483
+ <>{zoom > 0
484
+ && <Icon source={"magnify-minus-outline"} size={((Dimensions.width+Dimensions.height)/2)*0.05} color={Theme[themeTypeContext].icon_color}/>
485
+ }</>
486
+ </>)}}
487
+
488
+
489
+ />
490
+
491
+ </View>
492
+ <TouchableRipple
493
+ rippleColor={Theme[themeTypeContext].ripple_color_outlined}
494
+ style={{
495
+ borderRadius:5,
496
+ borderWidth:0,
497
+ backgroundColor: "transparent",
498
+ padding:5,
499
+ pointerEvents:"auto",
500
+ }}
501
+
502
+ onPress={async ()=>{
503
+ await Storage.store("CHAPTER_ZOOM", 0)
504
+ setZoom(0)
505
+ }}
506
+ >
507
+ <Icon source={"magnify-remove-cursor"} size={((Dimensions.width+Dimensions.height)/2)*0.05} color={Theme[themeTypeContext].icon_color}/>
508
+ </TouchableRipple>
509
+ </View>
510
+ </View>
511
+
512
+
513
  </View>
514
+
515
+ </Pressable>
516
+ </>}</>
517
+ <>{showOptions.type === "comments"&& <>
518
+ <View
519
+ style={{
520
+ width:"100%",
521
+ height:"auto",
522
+ padding:16,
523
+ backgroundColor:Theme[themeTypeContext].background_color,
524
+ borderBottomWidth:2,
525
+ borderColor:Theme[themeTypeContext].border_color,
526
+ }}
527
+ >
528
+ <Text selectable={false}
529
+ numberOfLines={1}
530
+ style={{
531
+ color:Theme[themeTypeContext].text_color,
532
+ fontSize:((Dimensions.width+Dimensions.height)/2)*0.045,
533
+ fontFamily:"roboto-bold",
534
+ }}
535
+ >
536
+ {chapterInfo.title}
537
+ </Text>
538
+ </View>
539
+ <View
540
+ style={{
541
+ flex:1,
542
+ backgroundColor:Theme[themeTypeContext].background_color,
543
+ }}
544
+ >
545
+ <Disqus title={chapterInfo.title} identifier={`${SOURCE}-${COMIC_ID}-${CHAPTER_IDX.current}`} url={`${apiBaseContext}/read/${SOURCE}/${COMIC_ID}/`}
546
+ paddingVertical={16} paddingHorizontal={25}
547
+ />
548
+ </View>
549
+ </>}</>
550
+ <Menu showOptions={showOptions} setShowOptions={setShowOptions}/>
551
  </View>
552
+ }
553
+ </AnimatePresence>
554
+
555
+ </>
556
+
 
 
 
557
 
558
+ :<View style={{zIndex:5,width:"100%",height:"100%",display:"flex",justifyContent:"center",alignItems:"center",backgroundColor:Theme[themeTypeContext].background_color}}>
559
+ <Image setShowCloudflareTurnstile={setShowCloudflareTurnstileContext} source={require("@/assets/gif/cat-loading.gif")} style={{width:((Dimensions.width+Dimensions.height)/2)*0.15,height:((Dimensions.width+Dimensions.height)/2)*0.15}}/>
560
+ </View>
561
+ }</>
562
+ }
563
+ </>)
564
 
565
 
566
  }
frontend/app/read/components/chapter_image.tsx CHANGED
@@ -14,7 +14,7 @@ import * as FileSystem from 'expo-file-system';
14
  import NetInfo from "@react-native-community/netinfo";
15
  import JSZip from 'jszip';
16
 
17
- import ChapterStorage from '@/constants/module/chapter_storage';
18
  import Image from '@/components/Image';
19
  import {CONTEXT} from '@/constants/module/context';
20
  import {blobToBase64, base64ToBlob} from "@/constants/module/file_manager";
 
14
  import NetInfo from "@react-native-community/netinfo";
15
  import JSZip from 'jszip';
16
 
17
+ import ChapterStorage from '@/constants/module/storages/chapter_storage';
18
  import Image from '@/components/Image';
19
  import {CONTEXT} from '@/constants/module/context';
20
  import {blobToBase64, base64ToBlob} from "@/constants/module/file_manager";
frontend/app/read/components/menu/components/menu_button.tsx CHANGED
@@ -2,7 +2,7 @@ import React, { useEffect, useState, useContext } from 'react';
2
  import { Link, router, usePathname } from 'expo-router';
3
  import { StyleSheet} from 'react-native';
4
  import { __styles } from '../stylesheet/styles';
5
- import storage from '@/constants/module/storage';
6
  import { Icon, MD3Colors, Button, Text, TouchableRipple } from 'react-native-paper';
7
  import Theme from '@/constants/theme';
8
  import {useWindowDimensions} from 'react-native';
 
2
  import { Link, router, usePathname } from 'expo-router';
3
  import { StyleSheet} from 'react-native';
4
  import { __styles } from '../stylesheet/styles';
5
+ import storage from '@/constants/module/storages/storage';
6
  import { Icon, MD3Colors, Button, Text, TouchableRipple } from 'react-native-paper';
7
  import Theme from '@/constants/theme';
8
  import {useWindowDimensions} from 'react-native';
frontend/app/read/components/menu/menu.tsx CHANGED
@@ -2,7 +2,7 @@ import React, { useEffect, useState } from 'react';
2
  import { Link, usePathname } from 'expo-router';
3
  import { StyleSheet, View} from 'react-native';
4
  import { __styles } from './stylesheet/styles';
5
- import storage from '@/constants/module/storage';
6
  import { Icon, MD3Colors, Button } from 'react-native-paper';
7
  import Theme from '@/constants/theme';
8
  import {useWindowDimensions} from 'react-native';
 
2
  import { Link, usePathname } from 'expo-router';
3
  import { StyleSheet, View} from 'react-native';
4
  import { __styles } from './stylesheet/styles';
5
+ import storage from '@/constants/module/storages/storage';
6
  import { Icon, MD3Colors, Button } from 'react-native-paper';
7
  import Theme from '@/constants/theme';
8
  import {useWindowDimensions} from 'react-native';
frontend/app/read/modules/get_chapter.tsx CHANGED
@@ -1,5 +1,5 @@
1
- import Storage from '@/constants/module/storage';
2
- import ChapterStorage from '@/constants/module/chapter_storage';
3
  import JSZip from 'jszip';
4
  import {blobToBase64, base64ToBlob, getImageLayout} from "@/constants/module/file_manager";
5
  import * as FileSystem from 'expo-file-system';
 
1
+ import Storage from '@/constants/module/storages/storage';
2
+ import ChapterStorage from '@/constants/module/storages/chapter_storage';
3
  import JSZip from 'jszip';
4
  import {blobToBase64, base64ToBlob, getImageLayout} from "@/constants/module/file_manager";
5
  import * as FileSystem from 'expo-file-system';
frontend/app/view/[source]/[comic_id].tsx CHANGED
@@ -16,10 +16,10 @@ import NetInfo from "@react-native-community/netinfo";
16
 
17
  import Theme from '@/constants/theme';
18
  import { __styles } from '../stylesheet/show_styles';
19
- import Storage from '@/constants/module/storage';
20
- import ImageCacheStorage from '@/constants/module/image_cache_storage';
21
- import ChapterStorage from '@/constants/module/chapter_storage';
22
- import ComicStorage from '@/constants/module/comic_storage';
23
  import { CONTEXT } from '@/constants/module/context';
24
  import Dropdown from '@/components/dropdown';
25
  import { PageNavigationWidget, RequestChapterWidget, BookmarkWidget } from '../componenets/widgets';
@@ -80,7 +80,7 @@ const Index = ({}:any) => {
80
 
81
  // Test Section
82
  useEffect(() => {
83
- console.log(CONTENT)
84
  },[CONTENT])
85
 
86
 
 
16
 
17
  import Theme from '@/constants/theme';
18
  import { __styles } from '../stylesheet/show_styles';
19
+ import Storage from '@/constants/module/storages/storage';
20
+ import ImageCacheStorage from '@/constants/module/storages/image_cache_storage';
21
+ import ChapterStorage from '@/constants/module/storages/chapter_storage';
22
+ import ComicStorage from '@/constants/module/storages/comic_storage';
23
  import { CONTEXT } from '@/constants/module/context';
24
  import Dropdown from '@/components/dropdown';
25
  import { PageNavigationWidget, RequestChapterWidget, BookmarkWidget } from '../componenets/widgets';
 
80
 
81
  // Test Section
82
  useEffect(() => {
83
+ // console.log(CONTENT)
84
  },[CONTENT])
85
 
86
 
frontend/app/view/componenets/chapter.tsx CHANGED
@@ -16,10 +16,10 @@ import NetInfo from "@react-native-community/netinfo";
16
 
17
  import Theme from '@/constants/theme';
18
  import { __styles } from '../stylesheet/show_styles';
19
- import Storage from '@/constants/module/storage';
20
- import ImageCacheStorage from '@/constants/module/image_cache_storage';
21
- import ChapterStorage from '@/constants/module/chapter_storage';
22
- import ComicStorage from '@/constants/module/comic_storage';
23
  import { CONTEXT } from '@/constants/module/context';
24
  import Dropdown from '@/components/dropdown';
25
  import { RequestChapterWidget, BookmarkWidget } from './widgets';
 
16
 
17
  import Theme from '@/constants/theme';
18
  import { __styles } from '../stylesheet/show_styles';
19
+ import Storage from '@/constants/module/storages/storage';
20
+ import ImageCacheStorage from '@/constants/module/storages/image_cache_storage';
21
+ import ChapterStorage from '@/constants/module/storages/chapter_storage';
22
+ import ComicStorage from '@/constants/module/storages/comic_storage';
23
  import { CONTEXT } from '@/constants/module/context';
24
  import Dropdown from '@/components/dropdown';
25
  import { RequestChapterWidget, BookmarkWidget } from './widgets';
frontend/app/view/componenets/widgets.tsx CHANGED
@@ -12,10 +12,10 @@ import Theme from '@/constants/theme';
12
  import Dropdown from '@/components/dropdown';
13
  import { CONTEXT } from '@/constants/module/context';
14
  import { store_comic_cover } from '../modules/content';
15
- import Storage from '@/constants/module/storage';
16
- import ComicStorage from '@/constants/module/comic_storage';
17
- import ImageCacheStorage from '@/constants/module/image_cache_storage';
18
- import ChapterStorage from '@/constants/module/chapter_storage';
19
 
20
 
21
  export const PageNavigationWidget = ({MAX_OFFSET,setPage,CONTENT}:any) =>{
 
12
  import Dropdown from '@/components/dropdown';
13
  import { CONTEXT } from '@/constants/module/context';
14
  import { store_comic_cover } from '../modules/content';
15
+ import Storage from '@/constants/module/storages/storage';
16
+ import ComicStorage from '@/constants/module/storages/comic_storage';
17
+ import ImageCacheStorage from '@/constants/module/storages/image_cache_storage';
18
+ import ChapterStorage from '@/constants/module/storages/chapter_storage';
19
 
20
 
21
  export const PageNavigationWidget = ({MAX_OFFSET,setPage,CONTENT}:any) =>{
frontend/app/view/modules/content.tsx CHANGED
@@ -4,10 +4,10 @@ import * as FileSystem from 'expo-file-system';
4
  import { Platform } from 'react-native';
5
 
6
  import translator from '@/constants/module/translator';
7
- import Storage from '@/constants/module/storage';
8
- import ComicStorage from '@/constants/module/comic_storage';
9
- import ImageCacheStorage from '@/constants/module/image_cache_storage';
10
- import ChapterStorage from '@/constants/module/chapter_storage';
11
  import {blobToBase64} from '@/constants/module/file_manager';
12
 
13
 
 
4
  import { Platform } from 'react-native';
5
 
6
  import translator from '@/constants/module/translator';
7
+ import Storage from '@/constants/module/storages/storage';
8
+ import ComicStorage from '@/constants/module/storages/comic_storage';
9
+ import ImageCacheStorage from '@/constants/module/storages/image_cache_storage';
10
+ import ChapterStorage from '@/constants/module/storages/chapter_storage';
11
  import {blobToBase64} from '@/constants/module/file_manager';
12
 
13
 
frontend/app/view/modules/socket.tsx CHANGED
@@ -1,4 +1,4 @@
1
- import Storage from '@/constants/module/storage'; // Adjust the import path as needed
2
  import uuid from 'react-native-uuid';
3
  import NetInfo from '@react-native-community/netinfo';
4
 
 
1
+ import Storage from '@/constants/module/storages/storage'; // Adjust the import path as needed
2
  import uuid from 'react-native-uuid';
3
  import NetInfo from '@react-native-community/netinfo';
4
 
frontend/components/Image.tsx CHANGED
@@ -1,7 +1,7 @@
1
  import { useState, useEffect, useContext, useCallback, useRef } from "react"
2
  import { Image as _Image } from 'expo-image';
3
  import { View } from "react-native"
4
- import ImageCacheStorage from "@/constants/module/image_cache_storage";
5
  import {blobToBase64} from "@/constants/module/file_manager";
6
  import { Icon, Button } from 'react-native-paper';
7
  import { ActivityIndicator } from 'react-native-paper';
 
1
  import { useState, useEffect, useContext, useCallback, useRef } from "react"
2
  import { Image as _Image } from 'expo-image';
3
  import { View } from "react-native"
4
+ import ImageCacheStorage from "@/constants/module/storages/image_cache_storage";
5
  import {blobToBase64} from "@/constants/module/file_manager";
6
  import { Icon, Button } from 'react-native-paper';
7
  import { ActivityIndicator } from 'react-native-paper';
frontend/components/cloudflare_turnstile.tsx CHANGED
@@ -5,7 +5,7 @@ import { Platform, View, Text } from 'react-native';
5
  import axios from 'axios';
6
  import { Button } from 'react-native-paper';
7
 
8
- import Storage from '@/constants/module/storage';
9
 
10
  import Theme from '@/constants/theme';
11
 
 
5
  import axios from 'axios';
6
  import { Button } from 'react-native-paper';
7
 
8
+ import Storage from '@/constants/module/storages/storage';
9
 
10
  import Theme from '@/constants/theme';
11
 
frontend/components/menu/components/menu_button.tsx CHANGED
@@ -2,7 +2,7 @@ import React, { useEffect, useState, useContext } from 'react';
2
  import { Link, router, usePathname } from 'expo-router';
3
  import { StyleSheet} from 'react-native';
4
  import { __styles } from '../stylesheet/styles';
5
- import storage from '@/constants/module/storage';
6
  import { Icon, MD3Colors, Button, Text, TouchableRipple } from 'react-native-paper';
7
  import Theme from '@/constants/theme';
8
  import {useWindowDimensions} from 'react-native';
 
2
  import { Link, router, usePathname } from 'expo-router';
3
  import { StyleSheet} from 'react-native';
4
  import { __styles } from '../stylesheet/styles';
5
+ import storage from '@/constants/module/storages/storage';
6
  import { Icon, MD3Colors, Button, Text, TouchableRipple } from 'react-native-paper';
7
  import Theme from '@/constants/theme';
8
  import {useWindowDimensions} from 'react-native';
frontend/components/menu/menu.tsx CHANGED
@@ -2,7 +2,7 @@ import React, { useEffect, useState } from 'react';
2
  import { Link, usePathname } from 'expo-router';
3
  import { StyleSheet, View} from 'react-native';
4
  import { __styles } from './stylesheet/styles';
5
- import storage from '@/constants/module/storage';
6
  import { Icon, MD3Colors, Button } from 'react-native-paper';
7
  import Theme from '@/constants/theme';
8
  import {useWindowDimensions} from 'react-native';
 
2
  import { Link, usePathname } from 'expo-router';
3
  import { StyleSheet, View} from 'react-native';
4
  import { __styles } from './stylesheet/styles';
5
+ import storage from '@/constants/module/storages/storage';
6
  import { Icon, MD3Colors, Button } from 'react-native-paper';
7
  import Theme from '@/constants/theme';
8
  import {useWindowDimensions} from 'react-native';
frontend/constants/module/{chapter_storage.tsx β†’ storages/chapter_storage.tsx} RENAMED
@@ -3,7 +3,7 @@
3
 
4
  import { Platform } from "react-native";
5
  import * as SQLite from 'expo-sqlite';
6
- import { ensure_safe_table_name } from "./ensure_safe_table_name";
7
 
8
  const DATABASE_NAME = 'ChapterDB';
9
 
 
3
 
4
  import { Platform } from "react-native";
5
  import * as SQLite from 'expo-sqlite';
6
+ import { ensure_safe_table_name } from "../ensure_safe_table_name";
7
 
8
  const DATABASE_NAME = 'ChapterDB';
9
 
frontend/constants/module/{comic_storage.tsx β†’ storages/comic_storage.tsx} RENAMED
File without changes
frontend/constants/module/{image_cache_storage.tsx β†’ storages/image_cache_storage.tsx} RENAMED
@@ -8,7 +8,7 @@ import * as SQLite from 'expo-sqlite';
8
  import * as FileSystem from 'expo-file-system';
9
 
10
  import {blobToBase64} from '@/constants/module/file_manager';
11
- import Storage from '@/constants/module/storage';
12
 
13
  // Most of the code here is generated by A.I with some edit and tweak.
14
  // I'm lazy to sit and implement entire thing :)
 
8
  import * as FileSystem from 'expo-file-system';
9
 
10
  import {blobToBase64} from '@/constants/module/file_manager';
11
+ import Storage from '@/constants/module/storages/storage';
12
 
13
  // Most of the code here is generated by A.I with some edit and tweak.
14
  // I'm lazy to sit and implement entire thing :)
frontend/constants/module/{storage.tsx β†’ storages/storage.tsx} RENAMED
File without changes