Skip to content

feat: migrate InkNest to React Native 0.84 / React 19 and add Novels reading (v1.5.0) - #73

Closed
pushpender-singh-ap wants to merge 11 commits into
mainfrom
RN84
Closed

feat: migrate InkNest to React Native 0.84 / React 19 and add Novels reading (v1.5.0)#73
pushpender-singh-ap wants to merge 11 commits into
mainfrom
RN84

Conversation

@pushpender-singh-ap

Copy link
Copy Markdown
Member

Summary

This PR rebuilds InkNest on a fresh React Native 0.84.1 project base (previously 0.76.9) and ships v1.5.0 (versionCode 39, previously 1.4.5 / 34). Rather than upgrading in place, the app was re-scaffolded from the RN 0.84 template and the full app was reimplemented on top of it, which is why the diff is large.

Alongside the platform migration, this PR introduces a complete Novels section, restores the Read Comics Online source with Cloudflare challenge handling, removes AdMob entirely, and migrates the whole app to the Firebase v24 modular API.

Platform / Tooling Migration

  • React Native 0.76.9 → 0.84.1, React 18.3.1 → 19.2.3 (with matching @react-native/* 0.84.1 and CLI 20.x tooling)
  • Node requirement raised to >= 22.11.0; Yarn Berry kept with nodeLinker: node-modules
  • TypeScript 5.0 → 5.8, @types/react 19, react-test-renderer 19
  • Major library upgrades for New Architecture compatibility:
    • React Navigation v6 → v7 (native-stack, bottom-tabs)
    • Reanimated 3.16 → 4.5 + new react-native-worklets dependency
    • Gesture Handler 2.x → 3.0, Screens 3.35 → 4.25
    • MMKV 3.2 → 4.3 (Nitro-based), Nitro Modules 0.36
    • Firebase 21.7.1 → 24.1.1 across all modules (analytics, auth, crashlytics, firestore, in-app-messaging, messaging, perf)
  • Yarn patches added for RN 0.84 compatibility: react-native-sensors@7.3.6 and @candlefinance/faster-image@1.7.2
  • Android: Gradle wrapper update, build.gradle/manifest cleanup, updated launcher icons, react-native-permissions 5.6.0
  • iOS: vector icon fonts configured, Swift bridging header set up, Gemfile/CocoaPods updates

New Feature: Novels

A full novel-reading experience added under src/Screens/Novel/:

  • Home, Search, See All, and Details screens for browsing novels
  • Novel Reader with two modes: native TextReader and WebReader (WebView-based), plus a WTRLab mode selector
  • Reader settings (fonts, themes, layout)
  • Library with reading progress, plus downloads and offline reading (DownloadManager, OfflineStorage)

Comic Sources

  • Restored Read Comics Online behind Cloudflare verification:
    • New cloudflareClearance.js — WebView-based CF Managed Challenge clearance flow
    • New webviewProxy.js and shared userAgent.js for challenge-protected requests
    • New sourceStatus.js + useSourceStatus hook to track per-source availability
    • New cookie handling via @preeternal/react-native-cookie-manager
  • Removed ComicHubFree source integration

Removals

  • AdMob fully removed (react-native-google-mobile-ads and all ad placements)
  • AsyncStorage removed — MangaBook storage migrated to MMKV
  • Docusaurus docs site removed from the repo (docs/)

Fixes

  • Firebase v24 modular API migration app-wide (no more deprecated namespaced calls); community profile queries now use the modular Firestore documentId() helper
  • Prevented stuck loading states and simplified app navigation flows
  • Comic Library screen reworked (history cards, manga history support)

Testing

  • Android debug build (yarn android --active-arch-only)
  • iOS build with vector icons rendering correctly
  • Comics: browse, read, download, history
  • Read Comics Online: Cloudflare challenge clearance and image loading
  • Novels: search, read (text + web mode), download/offline, library
  • Firebase: auth, community, push notifications, Crashlytics

- Bump React Native and related packages from 0.84.0 to 0.84.1
- Update app version to 1.4.9 (build 38)
- Add InkNest-Externals as git submodule
- Configure Android release build signing with keystore
- Add POST_NOTIFICATIONS and VIBRATE permissions to Android manifest
- Update Android icons from PNG to WebP format with adaptive icon support
- Expand iOS app icon set for all device types and scales
- Add CI post-clone script for Homebrew and dependency setup
- Allow app.json to be tracked in git
- Update iOS Pods dependencies to 0.84.1
Restores the complete InkNest feature set on top of the fresh RN 0.84.1
project setup, replacing the placeholder new-app screen with the real
application. 183 files changed (~44k insertions).

App bootstrap & infrastructure
- Replace App.tsx placeholder with App.js wiring up Redux store + persist,
  navigation container, gesture handler, safe-area, toast, and providers
- index.js registers the root component, background handlers, and the
  notification helpers (now MMKV-backed instead of AsyncStorage)
- Add Redux Toolkit store, root reducer, redux-persist with MMKV storage,
  and an axios interceptor controller (src/Redux/*)

Comics
- Home, Details, Reader (ComicBook), Bookmarks/History, Library, Search,
  See-All, and Sources screens (src/Screens/Comic/*)
- Page-flip reader (PageFlipper), zoomable Gallery, vertical reader, and
  offline download manager
- HTML source parsers for home/details/chapter/search (src/Redux/Actions/parsers/*)

Novels
- Full novel module: Home, Details, Reader (text/web), Library, Search,
  See-All, source selector, and offline storage/download manager
  (src/Screens/Novel/*)
- Novel parsers, APIs, and constants including WTR-Lab mode support

Auth, accounts & community
- Firebase integration: app, auth, firestore, analytics, crashlytics,
  messaging, in-app-messaging, perf (GoogleService-Info.plist, firebase.json)
- Google Sign-In and Apple authentication, login prompt and user avatar UI
- Community actions (Redux) for shared/social features

Notifications & source status
- Notifications screen and notification helpers
- Source status tracking with banner/notification UI and useSourceStatus hook

Navigation & shared UI
- App/Bottom navigation, navigation service, and route constants
- Reusable UIComp library (headers, footers, cards, skeletons, markdown,
  error states, loading, gallery popup, parallax carousel)
- ForceUpdate flow, v1.4.6 walkthrough, and About/Settings/Update screens

Tooling & dependencies
- Add ~40 runtime deps: Reanimated 4, gesture-handler, screens, MMKV,
  Firebase suite, redux toolkit/persist, axios, paper, svg, webview, video,
  faster-image (patched), vector-icons, device-info, dotenv, configcat, etc.
- Babel: add export-namespace-from + dotenv plugins; tsconfig path tweak
- iOS: update Podfile/Podfile.lock, project.pbxproj, AppDelegate, privacy
  manifest; Android: build.gradle and launcher icon updates
- Add LICENSE, CODE_OF_CONDUCT, CONTRIBUTING, example.env; refresh yarn.lock

Testing status
- Tested on a physical iOS device — the app builds, launches, and the core
  flows work fine.
- KNOWN ISSUE: react-native-vector-icons are not rendering correctly and
  still need to be fixed.
- NOT YET TESTED on Android — build and runtime behavior there is unverified.
- Treat this as a work-in-progress checkpoint: other unknown issues may
  still be pending and the build needs a deeper end-to-end pass.
… to MMKV

Strip out all Google AdMob / react-native-google-mobile-ads usage across the
app and replace AsyncStorage with MMKV for gravity-scroll settings persistence.

Ad removal:
- Delete Ads/BannerAds.js the AdBanner component and Ads/AppendAd.js the helper
  that injected type ad items every 4th position in lists.
- Remove the rewarded-ad flow: drop showRewardedAd from Redux/Actions/Download.js
  along with its commented-out RewardedAd implementation and @env imports.
- Stop calling showRewardedAd on source-open in WebViewComponent and
  LinkListScreen, and remove the AnimeAdbanner header from LinkListScreen.
- newCard.js no longer renders the AdBanner for item.type === ad; it now
  returns null for ad placeholders.
- MangaBook.js: remove the inline BannerAd, BannerAdSize, and AdBanner imports.
- Drop the showAds flag from FREE/PREMIUM/PRO tiers in SubscriptionFeatures.js.
- Remove the react-native-google-mobile-ads block app IDs, SKAdNetwork items
  from app.json and all AdMob unit-id env vars banner/interstitial/reward and
  the IOS_GOOGLE_CLIENT_ID trailing-newline fix from .env.

Storage migration:
- MangaBook.js now reads/writes gravity-scroll settings and the walkthrough-seen
  flag via mmkvStorage synchronous instead of AsyncStorage, removing the
  AsyncStorage dependency from this screen.
Register bundled vector icon font files in Info.plist so iOS can load
React Native icon fonts correctly.

Add an empty Swift source file and bridging header to enable Swift support
in the iOS target, and update the Xcode project references.

Refresh Podfile.lock with the current CocoaPods version.
- add a persistent hidden WebView proxy that serializes protected GET and POST
  requests, navigates through Cloudflare challenges, and returns rendered HTML
- add a verification prompt and modal WebView flow for manually completing
  Cloudflare checks when automatic verification cannot finish
- capture and persist Cloudflare clearance cookies and the matching user agent,
  then refresh affected screens after verification succeeds
- attach clearance headers to protected comic cover and reader image requests
- update home, comic detail, chapter, and advanced-search parsers for the 2026
  Read Comics Online site redesign
- replace the limited autocomplete search with the CSRF-protected advanced-search
  form to return complete catalog results
- add loading, failure, Cloudflare-protected, and retry states to the comic library
- fix comic detail chapter selection so the complete filtered chapter list is
  returned outside the recent tab
- keep transient Cloudflare prompt and refresh state out of Redux persistence
- add the native cookie manager dependency and update iOS pod resolution
- enable Firebase Crashlytics in the Android Gradle configuration
- bundle vector icon fonts in Android assets
- update react-native-permissions to 5.6.0
- patch react-native-sensors to replace deprecated JCenter repositories with
  Maven Central
- remove ComicHubFree from supported comic hosts and source metadata
- delete ComicHubFree search configuration and result parsing
- stop requesting and displaying ComicHubFree results in global comic search
- remove ComicHubFree search filters, result counts, URL recognition, and fallback selection
- delete ComicHubFree home-page request groups and scraping selectors
- remove ComicHubFree comic detail, chapter, and reader parsing configurations
- remove the ComicHubFree-specific  URL transformation
- change the default comics home source to ReadComicsOnline
- standardize the home section title as Latest Release
- replace the native loading modal with an absolute-positioned overlay to avoid
  frozen touch handling during iOS navigation transitions and prevent Android
  back-button interception
- render the loading overlay only while a request is actively loading
- add a 30-second Axios timeout so stalled API requests cannot leave screens
  stuck indefinitely in a loading state
- remove the Community tab from the bottom navigation
- remove the Read Manga shortcut from the Settings screen
- update Firestore participant queries to use the modular documentId helper
- update the About Us contact email to inknest@capacity.rocks
- remove leftover comic details debug logging
…ueries

Import the documentId helper directly from @react-native-firebase/firestore
and use it when querying participant profiles by user document ID.

This replaces the namespaced firestore.FieldPath.documentId() call, ensuring
the participant preview query uses the supported modular Firestore API while
preserving the existing batching, profile mapping, and result ordering.
@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Migrate to RN 0.84/React 19, add Novels + Cloudflare verification flow

✨ Enhancement ⚙️ Configuration changes 🕐 40+ Minutes

Grey Divider

AI Description

• Re-scaffold InkNest on React Native 0.84.1 / React 19 with upgraded toolchain.
• Add a v1 Novels experience: browse, search, read (text/web), download/offline.
• Restore ReadComicsOnline via Cloudflare WebView proxy + source health tracking.
Diagram

graph TD
  A["App root"] --> B["Redux/MMKV"] --> C["APICaller axios"] --> D["Cloudflare adapter"]
  A --> E["Navigation"] --> F["Comics screens"]
  E --> G["Novel screens"]
  D --> H["WebView proxy"]
  H --> I["CF Verify screen"]
  subgraph Legend
    direction LR
    _ui["UI"] ~~~ _state[("State/Storage")] ~~~ _net["Networking"]
  end
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. In-place RN upgrade
  • ➕ Keeps git history and reduces reimplementation churn
  • ➕ Smaller diff for reviewers and easier bisection
  • ➖ Often blocked by cascading native/module incompatibilities across multiple major versions
  • ➖ Higher risk of latent runtime issues from incremental patches
2. Dedicated HTTP bypass service for Cloudflare sources
  • ➕ Avoids embedding a persistent hidden WebView and custom adapter logic
  • ➕ Centralizes bot-protection handling per source
  • ➖ Requires server infrastructure (cost/maintenance) and increases legal/compliance surface
  • ➖ May still fail if challenge requires interactive browser signals
3. Use an off-the-shelf EPUB/reader engine for novels
  • ➕ Better typography/layout features and accessibility out of the box
  • ➕ Potentially simpler offline packaging and pagination
  • ➖ Novel sources here are web-scraped HTML; conversion to EPUB adds complexity
  • ➖ May constrain multi-source behavior (WTR-Lab modes, WebView reader fallback)

Recommendation: Given the jump from RN 0.76→0.84 (New Architecture ecosystem churn), the re-scaffold/reimplement approach is reasonable and likely lower risk than an in-place upgrade. The Cloudflare WebView proxy is a pragmatic client-only solution for managed challenges; keep it well-isolated (current approach) and ensure retry/timeout paths remain robust. For novels, the current split (TextReader + WebReader + offline) is a good MVP; consider a reader-engine later if formatting/accessibility becomes a priority.

Files changed (135) +19375 / -127945 · 1 not counted

Enhancement (70) +18638 / -902
App.jsMount Cloudflare proxy/gate and v1.4.6 walkthrough handler +67/-13

Mount Cloudflare proxy/gate and v1.4.6 walkthrough handler

• Adds global CloudflareProxy + CloudflareVerifyGate mounts and introduces a Redux-backed walkthrough modal controlled via ConfigCat flags.

App.js

index.jsAdd persistent hidden WebView proxy for Cloudflare-protected pages +147/-0

Add persistent hidden WebView proxy for Cloudflare-protected pages

• Implements a hidden always-mounted WebView used to navigate and extract rendered HTML for Cloudflare-challenged sources, with stuck-challenge detection and verify prompting.

src/Components/CloudflareProxy/index.js

BannerContext.jsUpdate feature-flag default targeting behavior +1/-1

Update feature-flag default targeting behavior

• Changes ConfigCat flag evaluation to use current app version as the default key, aligning gating with version-based rollouts.

src/Components/UIComp/AnimeAdBanner/BannerContext.js

CloudflareVerifyGate.jsAdd global Cloudflare verify modal gate +111/-0

Add global Cloudflare verify modal gate

• Adds a Redux-driven modal prompting the user to open the Cloudflare verification screen when a source hits 403 challenges.

src/Components/UIComp/CloudflareVerifyGate.js

ComicBookHeader.jsRefresh comic header UI for new flows +2/-16

Refresh comic header UI for new flows

• Updates header layout/actions to align with the rebuilt reader/navigation and new status flows.

src/Components/UIComp/ComicBookHeader.js

DownTime.jsTweak downtime UI messaging/behavior +2/-2

Tweak downtime UI messaging/behavior

• Minor adjustments to downtime component used when sources are unavailable.

src/Components/UIComp/DownTime.js

SourceStatusBanner.jsAdd in-app banner for source health/status +283/-0

Add in-app banner for source health/status

• Introduces a banner component to surface source availability, Cloudflare protection, and server-down states.

src/Components/UIComp/SourceStatusBanner.js

SourceStatusNotification.jsAdd source-status notification UI +287/-0

Add source-status notification UI

• Adds a notifications-style component for per-source status events and user actions (retry/switch/verify).

src/Components/UIComp/SourceStatusNotification.js

V146Walkthrough.jsAdd v1.4.6 walkthrough modal content +331/-0

Add v1.4.6 walkthrough modal content

• Adds the v1.4.6 walkthrough flow shown once per user via Redux persistence.

src/Components/Walkthrough/V146Walkthrough.js

V146WalkthroughSvgs.jsAdd walkthrough SVG assets +569/-0

Add walkthrough SVG assets

• Adds SVG/illustration assets used by the v1.4.6 walkthrough.

src/Components/Walkthrough/V146WalkthroughSvgs.js

Navigation.jsAdd novel and Cloudflare verification routes +8/-0

Add novel and Cloudflare verification routes

• Extends navigation route constants for CloudflareVerify and all Novel screens.

src/Constants/Navigation.js

AppNavigation.jsWire novel screens and Cloudflare verify modal into stack navigator +35/-6

Wire novel screens and Cloudflare verify modal into stack navigator

• Adds CloudflareVerify and all Novel routes, and disables back gestures on WebView-heavy screens to avoid stuck navigation states.

src/Navigation/AppNavigation.js

BottomNavigation.jsAdjust bottom tabs and remove community tab entry +1/-22

Adjust bottom tabs and remove community tab entry

• Updates feature-flag usage and removes the Community tab screen entry from bottom navigation.

src/Navigation/BottomNavigation.js

NovelActions.jsAdd Redux thunks for novel home/details/chapter fetching +263/-0

Add Redux thunks for novel home/details/chapter fetching

• Introduces a dedicated novel action layer with caching, error handling, and host/source selection support.

src/Redux/Actions/NovelActions.js

comicDetailParser.jsAdd comic details parsing helper +93/-0

Add comic details parsing helper

• Introduces a dedicated parser for comic detail pages to reduce ad-hoc parsing in screens.

src/Redux/Actions/parsers/comicDetailParser.js

novelChapterParser.jsAdd novel chapter parsing +1377/-0

Add novel chapter parsing

• Implements parsing for novel chapter pages across supported sources, including content normalization and metadata extraction.

src/Redux/Actions/parsers/novelChapterParser.js

novelDetailParser.jsAdd novel details parsing +613/-0

Add novel details parsing

• Implements parsing for novel details pages, chapter lists, and related metadata across sources.

src/Redux/Actions/parsers/novelDetailParser.js

novelHomeParser.jsAdd novel home parsing +323/-0

Add novel home parsing

• Implements parsing for novel home/browse pages across supported sources.

src/Redux/Actions/parsers/novelHomeParser.js

searchParser.jsExtend search parsing for new content types +66/-26

Extend search parsing for new content types

• Updates search parsing to support additional result formats and improved extraction.

src/Redux/Actions/parsers/searchParser.js

Interceptor.jsAdd request timeout and Cloudflare WebView-backed axios adapter +60/-34

Add request timeout and Cloudflare WebView-backed axios adapter

• Adds a 30s timeout to prevent stuck loading, and routes Cloudflare-protected requests through the hidden WebView proxy when needed while keeping Firebase Perf tracing.

src/Redux/Controller/Interceptor.js

index.jsAdd novel state, source status, Cloudflare verify state, and manga history +283/-5

Add novel state, source status, Cloudflare verify state, and manga history

• Extends Redux state for novels (bookmarks/history/reader settings), adds per-source status notifications, and adds Cloudflare verification prompting + clearance nonce signaling.

src/Redux/Reducers/index.js

index.jsAdd Cloudflare verification WebView screen with clearance capture +234/-0

Add Cloudflare verification WebView screen with clearance capture

• Implements a guided WebView flow to pass Cloudflare challenges, capture UA/cookies when possible, reload the proxy session, and return control to the app.

src/Screens/CloudflareVerify/index.js

Home.jsRefactor comics home fetching and add source-status tracking +105/-112

Refactor comics home fetching and add source-status tracking

• Introduces structured parsing helpers (including updated ReadComicsOnline parsing) and records per-source success/error status for user-facing notifications.

src/Screens/Comic/APIs/Home.js

constance.jsUpdate comics API constants for new site structures +16/-78

Update comics API constants for new site structures

• Refreshes class/config mappings used to parse comic sources after upstream site changes and migration.

src/Screens/Comic/APIs/constance.js

homeParser.jsAdd dedicated comics home parser module +173/-0

Add dedicated comics home parser module

• Adds reusable parsing helpers for home/list pages, including updated ReadComicsOnline layout support.

src/Screens/Comic/APIs/homeParser.js

VerticalView.jsRefine vertical reader rendering +7/-6

Refine vertical reader rendering

• Adjusts vertical reading mode behavior and performance for updated RN stack.

src/Screens/Comic/Book/VerticalView.js

index.jsUpdate comic reader container and progress handling +212/-24

Update comic reader container and progress handling

• Refactors comic reader screen to align with new storage, navigation, and UI expectations.

src/Screens/Comic/Book/index.js

MangaBookmarks.jsAdd Manga bookmarks screen +284/-0

Add Manga bookmarks screen

• Adds a dedicated manga bookmarks screen backed by new MangaBookMarks state.

src/Screens/Comic/Bookmarks/MangaBookmarks.js

NovelBookmarks.jsAdd Novel bookmarks screen +285/-0

Add Novel bookmarks screen

• Adds a dedicated novel bookmarks screen backed by new NovelBookMarks state.

src/Screens/Comic/Bookmarks/NovelBookmarks.js

index.jsIntegrate comic/manga/novel bookmark tabs +172/-14

Integrate comic/manga/novel bookmark tabs

• Updates bookmarks index to include MangaBookmarks and NovelBookmarks alongside comics.

src/Screens/Comic/Bookmarks/index.js

ChapterCard.jsUpdate chapter card rendering/actions +2/-10

Update chapter card rendering/actions

• Tweaks chapter card UI and interactions for the rebuilt details/reader flow.

src/Screens/Comic/Details/ChapterCard.js

index.tsxAdd/refresh Comic Home screen entry +12/-0

Add/refresh Comic Home screen entry

• Introduces/updates the typed Comic Home screen entrypoint for the rebuilt app.

src/Screens/Comic/Home/index.tsx

HistoryCard.jsRevise history card UI for comics +29/-35

Revise history card UI for comics

• Updates comic history card layout and metadata display for the redesigned Library screen.

src/Screens/Comic/Library/Components/HistoryCard.js

MangaHistoryCard.jsAdd manga history card component +157/-0

Add manga history card component

• Adds a dedicated history card for manga entries backed by MangaHistory state.

src/Screens/Comic/Library/Components/MangaHistoryCard.js

index.jsRework Library screen with enhanced history and manga support +912/-242

Rework Library screen with enhanced history and manga support

• Large refactor of the Library screen to better represent reading history/progress, including manga history support and updated UI flows.

src/Screens/Comic/Library/index.js

NotificationsScreen.jsUpdate notifications UI for new state/flows +240/-15

Update notifications UI for new state/flows

• Adjusts notifications screen behavior and display for updated reducers and notification bootstrap logic.

src/Screens/Notifications/NotificationsScreen.js

Details.jsAdd novel details fetch/parsing pipeline +436/-0

Add novel details fetch/parsing pipeline

• Implements novel details extraction (metadata, chapters, related info) per supported host source.

src/Screens/Novel/APIs/Details.js

Home.jsAdd novel home/browse API implementation +763/-0

Add novel home/browse API implementation

• Implements novel home endpoints (sections, lists, genres) per supported host source.

src/Screens/Novel/APIs/Home.js

Reader.jsAdd novel chapter reader API implementation +373/-0

Add novel chapter reader API implementation

• Implements chapter retrieval and multi-chapter aggregation support for the reader.

src/Screens/Novel/APIs/Reader.js

Search.jsAdd novel search API implementation +142/-0

Add novel search API implementation

• Implements novel search and author search for supported novel sources.

src/Screens/Novel/APIs/Search.js

constance.jsAdd novel source parsing constants +570/-0

Add novel source parsing constants

• Introduces CSS/selectors/config used across novel home/details/reader/search parsing.

src/Screens/Novel/APIs/constance.js

novelParser.jsAdd legacy-compatible novel parsing helpers +586/-0

Add legacy-compatible novel parsing helpers

• Implements parsers retained for backward compatibility and shared parsing reuse.

src/Screens/Novel/APIs/novelParser.js

DownloadButton.jsAdd novel download button component +165/-0

Add novel download button component

• Adds UI/logic to start/cancel downloads and reflect offline availability in the novel UI.

src/Screens/Novel/Components/DownloadButton.js

NovelCard.jsAdd novel card component for lists/grids +359/-0

Add novel card component for lists/grids

• Provides reusable novel card UI with cover/title/metadata used across novel browse/search flows.

src/Screens/Novel/Components/NovelCard.js

NovelList.jsAdd reusable novel list component +152/-0

Add reusable novel list component

• Adds list rendering for novel collections with consistent styling and navigation hooks.

src/Screens/Novel/Components/NovelList.js

SectionHeader.jsAdd novel section header component +91/-0

Add novel section header component

• Adds headers for novel home sections including actions like See All.

src/Screens/Novel/Components/SectionHeader.js

SourceSelector.jsAdd novel source selector UI +389/-0

Add novel source selector UI

• Adds UI to switch between novel sources (e.g., NovelFire, WTR-Lab) and reflect enabled/active source state.

src/Screens/Novel/Components/SourceSelector.js

ChapterList.jsAdd novel chapter list UI +296/-0

Add novel chapter list UI

• Implements the chapter list UI used on novel detail pages, including navigation into the reader.

src/Screens/Novel/Details/Components/ChapterList.js

GenreTags.jsAdd genre tag UI for novel details +179/-0

Add genre tag UI for novel details

• Adds genre tag display components for novel detail metadata presentation.

src/Screens/Novel/Details/Components/GenreTags.js

NovelInfo.jsAdd novel metadata/info block UI +353/-0

Add novel metadata/info block UI

• Adds novel info component (title, author, stats, synopsis) for the details screen.

src/Screens/Novel/Details/Components/NovelInfo.js

NovelDetails.jsAdd novel details screen +814/-0

Add novel details screen

• Introduces the main novel details screen: metadata display, chapter browsing, bookmarking, and entry into reading/downloading flows.

src/Screens/Novel/Details/NovelDetails.js

index.tsxAdd novel home screen +143/-0

Add novel home screen

• Adds NovelHome screen for browsing sections and navigating into search/details/see-all flows.

src/Screens/Novel/Home/index.tsx

NovelLibrary.jsAdd novel library screen with progress tracking +232/-0

Add novel library screen with progress tracking

• Implements a novel library view backed by NovelHistory/NovelBookMarks, showing progress and quick resume.

src/Screens/Novel/Library/NovelLibrary.js

ReaderSettings.jsAdd reader settings UI for novels +326/-0

Add reader settings UI for novels

• Adds reader settings (theme, font, layout) and persists choices via Redux state.

src/Screens/Novel/Reader/Components/ReaderSettings.js

TextReader.jsAdd native text-mode novel reader +99/-0

Add native text-mode novel reader

• Implements a native text reader component for chapter content with theming and typography support.

src/Screens/Novel/Reader/Components/TextReader.js

WTRLabModeSelector.jsAdd WTR-Lab reading mode selector +263/-0

Add WTR-Lab reading mode selector

• Adds UI to choose among WTR-Lab reading modes (web/webplus/ai) integrated into reader behavior.

src/Screens/Novel/Reader/Components/WTRLabModeSelector.js

WebReader.jsAdd WebView-based novel reader mode +324/-0

Add WebView-based novel reader mode

• Adds a WebView reader mode with request allowlisting and URL construction for supported sources.

src/Screens/Novel/Reader/Components/WebReader.js

NovelReader.jsAdd novel reader screen with progress and mode switching +919/-0

Add novel reader screen with progress and mode switching

• Implements the full novel reader screen: chapter navigation, reading progress tracking, text/web modes, and settings integration.

src/Screens/Novel/Reader/NovelReader.js

NovelSearch.jsAdd novel search screen +378/-0

Add novel search screen

• Implements NovelSearch UI and data fetching for searching novels by title/author.

src/Screens/Novel/Search/NovelSearch.js

index.jsAdd novel see-all screen +212/-0

Add novel see-all screen

• Implements See All listing for novel sections/genres with pagination or extended results.

src/Screens/Novel/SeeAll/index.js

DownloadManager.jsAdd novel download manager +251/-0

Add novel download manager

• Implements download queueing, storage, and lifecycle management for offline novel chapters.

src/Screens/Novel/Utils/DownloadManager.js

OfflineStorage.jsAdd offline storage layer for novels +336/-0

Add offline storage layer for novels

• Adds MMKV/filesystem-backed persistence utilities for storing and retrieving offline novel content.

src/Screens/Novel/Utils/OfflineStorage.js

Search.jsExtend search screen to include Manga and Novels categories +683/-194

Extend search screen to include Manga and Novels categories

• Adds category-based search across comics, manga, and novels, including novel search API integration and updated UI/filters.

src/Screens/Search/Search.js

index.jsUpdate settings to include new reader/source preferences +222/-46

Update settings to include new reader/source preferences

• Extends settings UI to reflect new features (novel reader preferences, updated storage/state, source status flows).

src/Screens/Settings/index.js

APIs.jsRemove ComicHubFree host and add Novel host mapping +4/-1

Remove ComicHubFree host and add Novel host mapping

• Drops the ComicHubFree host entry and introduces NovelHostName mapping used by the new novel APIs.

src/Utils/APIs.js

cloudflareClearance.jsAdd Cloudflare clearance storage and request header helpers +140/-0

Add Cloudflare clearance storage and request header helpers

• Adds MMKV-backed persistence for Cloudflare clearance metadata, cookie/UA capture, and header injection utilities for protected hosts.

src/Utils/cloudflareClearance.js

useSourceStatus.jsAdd hook for reading/publishing source status +157/-0

Add hook for reading/publishing source status

• Introduces a hook to consume and update per-source availability and to drive status UI components.

src/Utils/hooks/useSourceStatus.js

sourceStatus.jsAdd per-source health/status tracking utilities +319/-0

Add per-source health/status tracking utilities

• Implements persistent tracking of source health (working/403 Cloudflare/500+ down) with user-friendly messages and MMKV persistence.

src/Utils/sourceStatus.js

userAgent.jsAdd shared User-Agent constant for Cloudflare flows +20/-0

Add shared User-Agent constant for Cloudflare flows

• Introduces a pinned UA fallback to keep WebView/axios/image requests consistent for Cloudflare clearance reuse.

src/Utils/userAgent.js

webviewProxy.jsAdd WebView navigate-and-read request proxy queue +180/-0

Add WebView navigate-and-read request proxy queue

• Implements a serialized request queue driving a WebView via injected JS to navigate/POST and return rendered HTML via postMessage.

src/Utils/webviewProxy.js

Bug fix (10) +229 / -51
index.tsxFix gallery component exports/types for updated RN stack +2/-5

Fix gallery component exports/types for updated RN stack

• Adjusts gallery entrypoint to match updated TypeScript/RN expectations.

src/Components/Gallery/src/index.tsx

ChaptersView.jsMinor chapter list rendering adjustments +1/-2

Minor chapter list rendering adjustments

• Small fixes/cleanup in chapter list view behavior for the rebuilt readers.

src/Components/UIComp/ChaptersView.js

Image.jsAdd support for Cloudflare clearance headers on images +9/-2

Add support for Cloudflare clearance headers on images

• Updates the shared Image component to better handle remote sources, including header injection for protected hosts.

src/Components/UIComp/Image.js

LoadingModal.jsImprove loading modal robustness +19/-6

Improve loading modal robustness

• Adjusts loading overlay behavior to reduce stuck loading scenarios with request timeouts/retries.

src/Components/UIComp/LoadingModal.js

CommunityActions.jsMigrate Firestore queries and harden auth sync/FCM token handling +68/-12

Migrate Firestore queries and harden auth sync/FCM token handling

• Updates Firestore documentId() usage, debounces duplicate auth syncs, and rate-limits FCM token fetches to avoid server throttling.

src/Redux/Actions/CommunityActions.js

comicBookParser.jsUpdate comic book parsing for new source layouts +82/-3

Update comic book parsing for new source layouts

• Adjusts comic parsing logic to handle updated HTML structures and reader expectations.

src/Redux/Actions/parsers/comicBookParser.js

errorHandlers.jsHarden API error handling and downtime detection +36/-6

Harden API error handling and downtime detection

• Improves shared error handling utilities to work with new timeouts, retries, and per-source statuses.

src/Redux/Actions/utils/errorHandlers.js

Storage.jsMigrate MMKV initialization to createMMKV API +3/-3

Migrate MMKV initialization to createMMKV API

• Updates storage initialization and removeItem behavior to match react-native-mmkv v4 API.

src/Redux/Storage/Storage.js

GalleryImage.tsxAdjust gallery image behavior/types +6/-5

Adjust gallery image behavior/types

• Updates gallery image rendering to work with updated dependencies and types.

src/Screens/Comic/Book/GalleryImage.tsx

ComicDetails.jsImprove comic details behavior and error handling +3/-7

Improve comic details behavior and error handling

• Adjusts comic details screen to work with new parsers, loading behavior, and retries.

src/Screens/Comic/Details/ComicDetails.js

Refactor (18) +136 / -86
index.jsNormalize app registration imports and side-effect initializers +3/-2

Normalize app registration imports and side-effect initializers

• Cleans up AppRegistry/appName imports and preserves required reanimated/gesture-handler initialization ordering.

index.js

AppDelegate.hRemove ObjC AppDelegate header from legacy setup +0/-6

Remove ObjC AppDelegate header from legacy setup

• Removes legacy Objective-C AppDelegate declarations in favor of the new Swift-based AppDelegate.

ios/InkNest/AppDelegate.h

HomeFunc.jsAdjust home screen helper logic for new sources/features +7/-7

Adjust home screen helper logic for new sources/features

• Updates home utility behavior to align with the rebuilt navigation and content sources.

src/Components/Func/HomeFunc.js

index.jsExport walkthrough components +2/-0

Export walkthrough components

• Adds exports for newly introduced walkthrough modules.

src/Components/Walkthrough/index.js

index.jsUpdate navigation exports +1/-17

Update navigation exports

• Refreshes navigation barrel exports to match new structure and screens.

src/Navigation/index.js

GlobalActions.jsUpdate global actions for new readers/sources behavior +58/-20

Update global actions for new readers/sources behavior

• Adjusts app-wide thunks and helpers to work with updated APIs, storage, and navigation flows.

src/Redux/Actions/GlobalActions.js

index.jsUpdate store initialization wiring for new reducers/state +10/-2

Update store initialization wiring for new reducers/state

• Adjusts store setup to support newly added reducers and persistence behavior.

src/Redux/Store/index.js

index.jsMinor About Us screen tweaks +1/-1

Minor About Us screen tweaks

• Small adjustments to About Us screen content/structure under the rebuilt app.

src/Screens/AboutUs/index.js

ComicBook.jsMinor comic book screen adjustment +1/-1

Minor comic book screen adjustment

• Small tweaks to the comic book reader entry component.

src/Screens/Comic/Book/ComicBook.js

Bookmarks.jsUpdate bookmarks screen wiring +2/-6

Update bookmarks screen wiring

• Adjusts bookmark screen to work with updated reducers and navigation.

src/Screens/Comic/Bookmarks/Bookmarks.js

index.jsUpdate comic details module exports +2/-23

Update comic details module exports

• Refreshes exports/wiring for comic details screens under new navigation.

src/Screens/Comic/Details/index.js

index.jsExport novel API surface +34/-0

Export novel API surface

• Adds a central export module for novel APIs, legacy parsers, and per-source config.

src/Screens/Novel/APIs/index.js

index.jsExport NovelDetails screen +1/-0

Export NovelDetails screen

• Adds an index export for the NovelDetails screen module.

src/Screens/Novel/Details/index.js

index.jsExport NovelLibrary screen +1/-0

Export NovelLibrary screen

• Adds an index export for the NovelLibrary module.

src/Screens/Novel/Library/index.js

index.jsExport NovelReader screen +1/-0

Export NovelReader screen

• Adds an index export for the NovelReader module.

src/Screens/Novel/Reader/index.js

index.jsExport NovelSearch screen +1/-0

Export NovelSearch screen

• Adds an index export for the NovelSearch module.

src/Screens/Novel/Search/index.js

index.jsExport all Novel screens +10/-0

Export all Novel screens

• Adds a barrel export for all novel screens (Home/Details/Reader/Search/Library/SeeAll).

src/Screens/Novel/index.js

notificationHelpers.jsAdjust notification helpers for new storage backing +1/-1

Adjust notification helpers for new storage backing

• Small update to notification helpers to align with MMKV-backed storage and rebuilt app wiring.

src/Utils/notificationHelpers.js

Tests (2) +7 / -10
App.test.tsxUpdate App smoke test for new entrypoints +5/-9

Update App smoke test for new entrypoints

• Adjusts Jest snapshot/smoke coverage to match the updated app bootstrap.

tests/App.test.tsx

MockBooks.jsUpdate mock books fixture +2/-1

Update mock books fixture

• Refreshes mock data used for UI/testing flows in the rebuilt reader.

src/Screens/Comic/Book/MockBooks.js

Documentation (3) +60 / -211
README.mdReplace project README with RN template getting-started +60/-199

Replace project README with RN template getting-started

• Replaces the previous InkNest README content with the default React Native scaffold instructions.

README.md

example.app.jsonUpdate example app.json template +0/-9

Update example app.json template

• Updates the example app configuration file used for local setup/documentation.

example.app.json

example.envUpdate example env template +0/-3

Update example env template

• Updates the sample environment variables file for the new project setup.

example.env

Other (32) +305 / -126685
.prettierrc.jsRemove legacy Prettier config +0/-2

Remove legacy Prettier config

• Removes the previous Prettier configuration, relying on the RN 0.84 scaffold/tooling defaults.

.prettierrc.js

faster-image-npm-1.7.2-8497311acf.patchYarn patch for faster-image RN 0.84 compatibility not counted

Yarn patch for faster-image RN 0.84 compatibility

• Adds a Yarn patch to keep @candlefinance/faster-image working with the updated RN toolchain.

.yarn/patches/@candlefinance/faster-image-npm-1.7.2-8497311acf.patch

react-native-sensors-npm-7.3.6-ed34263610.patchYarn patch for react-native-sensors RN 0.84 compatibility +19/-0

Yarn patch for react-native-sensors RN 0.84 compatibility

• Adds a Yarn patch to keep react-native-sensors building/running on RN 0.84.

.yarn/patches/react-native-sensors-npm-7.3.6-ed34263610.patch

.yarnrc.ymlAdjust Yarn configuration +0/-2

Adjust Yarn configuration

• Updates Yarn config (Berry) settings used by the new scaffold.

.yarnrc.yml

GemfileAdd/refresh iOS Ruby tooling dependencies +7/-0

Add/refresh iOS Ruby tooling dependencies

• Adds Ruby gem dependencies used for iOS/CocoaPods workflows under the new RN base.

Gemfile

build.gradleUpdate Android app build config for v1.5.0 and RN 0.84 +6/-41

Update Android app build config for v1.5.0 and RN 0.84

• Bumps versionCode/versionName and aligns Gradle config with RN 0.84 defaults, removing obsolete Firebase Perf plugin wiring and legacy packaging tweaks.

android/app/build.gradle

proguard-rules.proAdd ProGuard rules for updated dependencies +0/-21

Add ProGuard rules for updated dependencies

• Adds shrinker/obfuscation rules for libraries used by the upgraded RN stack.

android/app/proguard-rules.pro

AndroidManifest.xmlAdjust main Android manifest permissions/entries +2/-3

Adjust main Android manifest permissions/entries

• Updates manifest entries to match the new RN template and updated permission needs.

android/app/src/main/AndroidManifest.xml

build.gradleUpgrade Android SDK/Gradle plugin configuration +7/-8

Upgrade Android SDK/Gradle plugin configuration

• Bumps compile/target SDK and updates Google Services/Crashlytics Gradle plugin versions for the upgraded toolchain.

android/build.gradle

gradle.propertiesTune Android Gradle properties for new build +6/-1

Tune Android Gradle properties for new build

• Updates Gradle properties for RN 0.84 build behavior and performance.

android/gradle.properties

gradle-wrapper.propertiesUpdate Gradle wrapper version +1/-1

Update Gradle wrapper version

• Bumps the Gradle wrapper to a newer version compatible with RN 0.84 tooling.

android/gradle/wrapper/gradle-wrapper.properties

gradlewRefresh Gradle wrapper script +5/-6

Refresh Gradle wrapper script

• Updates the Unix gradlew wrapper script as part of the new Android scaffold.

android/gradlew

gradlew.batRefresh Gradle wrapper script (Windows) +7/-2

Refresh Gradle wrapper script (Windows)

• Updates the Windows gradlew.bat wrapper script as part of the new Android scaffold.

android/gradlew.bat

link-assets-manifest.jsonUpdate Android linked assets manifest +0/-4

Update Android linked assets manifest

• Adjusts generated asset linking metadata for RN 0.84.

android/link-assets-manifest.json

app.jsonTrack app.json in repo +4/-0

Track app.json in repo

• Adds/updates app.json to ensure the app name/metadata is versioned with the scaffold.

app.json

babel.config.jsUpdate Babel configuration for RN 0.84/React 19 +8/-10

Update Babel configuration for RN 0.84/React 19

• Aligns Babel preset/plugins with RN 0.84 expectations and updated dependencies.

babel.config.js

Empty.swiftKeep Swift compilation placeholder +1/-1

Keep Swift compilation placeholder

• Maintains a Swift source file to ensure Swift runtime/tooling is correctly enabled.

ios/Empty.swift

project.pbxprojRegenerate iOS project for RN 0.84 + updated assets/fonts +68/-385

Regenerate iOS project for RN 0.84 + updated assets/fonts

• Large Xcode project regeneration to match the RN 0.84 template, updated build phases, resources, and dependency integration.

ios/InkNest.xcodeproj/project.pbxproj

AppDelegate.swiftAdd Swift AppDelegate using RN 0.84 factory delegate +50/-0

Add Swift AppDelegate using RN 0.84 factory delegate

• Introduces a Swift AppDelegate that configures Firebase and starts React Native via RCTReactNativeFactory/Default delegate pattern.

ios/InkNest/AppDelegate.swift

Info.plistUpdate iOS Info.plist for new scaffold and privacy settings +27/-25

Update iOS Info.plist for new scaffold and privacy settings

• Adjusts iOS app metadata/permissions entries required by updated dependencies and iOS platform expectations.

ios/InkNest/Info.plist

InkNest.entitlementsAdd/update iOS entitlements +4/-0

Add/update iOS entitlements

• Adds entitlements required for the rebuilt iOS app configuration.

ios/InkNest/InkNest.entitlements

LaunchScreen.storyboardUpdate iOS launch screen layout +5/-11

Update iOS launch screen layout

• Adjusts launch screen storyboard per new template and assets.

ios/InkNest/LaunchScreen.storyboard

PrivacyInfo.xcprivacyUpdate iOS privacy manifest +2/-6

Update iOS privacy manifest

• Updates PrivacyInfo.xcprivacy content to reflect data access patterns and dependencies.

ios/InkNest/PrivacyInfo.xcprivacy

main.mUpdate iOS main entry for Swift AppDelegate +0/-10

Update iOS main entry for Swift AppDelegate

• Adjusts main.m to work with the Swift AppDelegate-based app startup.

ios/InkNest/main.m

PodfileUpdate CocoaPods integration for RN 0.84 dependencies +8/-5

Update CocoaPods integration for RN 0.84 dependencies

• Adjusts Podfile settings and pods to match RN 0.84 and upgraded libraries.

ios/Podfile

link-assets-manifest.jsonUpdate iOS linked assets manifest +0/-4

Update iOS linked assets manifest

• Adjusts generated asset linking metadata for RN 0.84.

ios/link-assets-manifest.json

metro.config.jsSimplify Metro config to RN defaults +5/-26

Simplify Metro config to RN defaults

• Removes custom SVG transformer wiring and falls back to @react-native/metro-config defaults.

metro.config.js

package.jsonUpgrade RN/React toolchain and dependencies; remove AdMob +56/-57

Upgrade RN/React toolchain and dependencies; remove AdMob

• Bumps React Native to 0.84.1 and React to 19, upgrades major libraries (navigation, reanimated, firebase modular v24), removes react-native-google-mobile-ads, and raises Node engine to >=22.11.0.

package.json

react-native-nitro-modules+0.33.5.patchVendor patch for react-native-nitro-modules +0/-126043

Vendor patch for react-native-nitro-modules

• Adds a large local patch file applied to react-native-nitro-modules to keep MMKV/Nitro i...

@qodo-code-review

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (6) 📘 Rule violations (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Cloudflare host match too loose 🐞 Bug ⛨ Security
Description
isCloudflareProtectedUrl() uses substring matching (url.includes(host)), so non-Cloudflare URLs that
merely contain the host string can be misclassified and routed through the Cloudflare WebView proxy
and/or have clearance headers attached. This can cause incorrect navigation/request behavior and may
leak clearance headers if a misclassified URL is ever used.
Code

src/Utils/cloudflareClearance.js[R35-37]

+/** True if the URL targets a Cloudflare-challenged host we manage clearance for. */
+export const isCloudflareProtectedUrl = url =>
+  typeof url === 'string' && CF_PROTECTED_HOSTS.some(host => url.includes(host));
Evidence
The URL classification is currently based on substring containment, and both the axios adapter and
image loader consume this to decide whether to proxy requests and attach headers; additionally, the
persistent WebView is configured to allow any origin.

src/Utils/cloudflareClearance.js[31-37]
src/Redux/Controller/Interceptor.js[22-33]
src/Components/UIComp/Image.js[20-42]
src/Components/CloudflareProxy/index.js[111-121]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`isCloudflareProtectedUrl()` uses `url.includes(host)`, which does not validate the actual URL hostname and can misclassify arbitrary URLs.

### Issue Context
This function gates:
- axios adapter routing to the hidden WebView proxy
- attaching `Cookie`/`User-Agent` headers for protected resources

### Fix Focus Areas
- src/Utils/cloudflareClearance.js[35-37]
- src/Redux/Controller/Interceptor.js[22-33]
- src/Components/UIComp/Image.js[20-42]
- src/Components/CloudflareProxy/index.js[111-121]

### Proposed fix
- Replace substring matching with strict URL parsing:
 - `const {hostname} = new URL(url)` (guard try/catch)
 - match `hostname === 'readcomicsonline.ru'` (or `hostname.endsWith('.readcomicsonline.ru')` if subdomains are intended)
- Consider tightening WebView `originWhitelist` to `['https://readcomicsonline.ru/*']` (and any other explicitly supported CF origins) to reduce blast radius if a URL ever slips through.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Unresolved manifest placeholder 🐞 Bug ☼ Reliability
Description
AndroidManifest.xml sets android:usesCleartextTraffic="${usesCleartextTraffic}" but the project does
not define a manifestPlaceholder for usesCleartextTraffic, which can break Android manifest
merging/builds. If later defined incorrectly, it could also unintentionally enable cleartext traffic
in release.
Code

android/app/src/main/AndroidManifest.xml[R14-15]

+      android:usesCleartextTraffic="${usesCleartextTraffic}"
+      android:supportsRtl="true">
Evidence
The manifest contains the placeholder, and the app Gradle config shown has no manifestPlaceholders
that would supply it.

android/app/src/main/AndroidManifest.xml[7-16]
android/app/build.gradle[77-116]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The Android manifest references an unresolved placeholder `${usesCleartextTraffic}`.

### Issue Context
No `manifestPlaceholders` configuration is present in `android/app/build.gradle`, so this placeholder is not set by default.

### Fix Focus Areas
- android/app/src/main/AndroidManifest.xml[14-15]
- android/app/build.gradle[77-116]

### Proposed fix
Choose one:
1) **Hardcode a safe value** (recommended):
  - Set `android:usesCleartextTraffic="false"` in the main manifest.
  - If debug needs cleartext, add a debug manifest overlay or build-type specific manifest.

2) **Use manifestPlaceholders explicitly**:
  - In `android/app/build.gradle`:
    - `defaultConfig { manifestPlaceholders = [usesCleartextTraffic: "false"] }`
    - Optionally override in `buildTypes.debug { manifestPlaceholders.usesCleartextTraffic = "true" }` if required.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Proxy POST parsing can throw 🐞 Bug ☼ Reliability
Description
webviewProxy.parseForm() calls decodeURIComponent() on untrusted strings without guarding, so
malformed percent-encoding can throw synchronously. Because pump() sets proxy state (busy/current)
and does not catch around parseForm(), an exception can wedge the proxy and strand subsequent
Cloudflare requests.
Code

src/Utils/webviewProxy.js[R52-61]

+const parseForm = body => {
+  const out = [];
+  String(body || '')
+    .split('&')
+    .filter(Boolean)
+    .forEach(pair => {
+      const i = pair.indexOf('=');
+      const k = decodeURIComponent(pair.slice(0, i));
+      const v = decodeURIComponent(pair.slice(i + 1).replace(/\+/g, ' '));
+      out.push(`<input type="hidden" name="${escapeAttr(k)}" value="${escapeAttr(v)}">`);
Evidence
parseForm performs unguarded decoding, and pump transitions the proxy into a busy state and
immediately calls parseForm without any exception boundary, so a throw can prevent state reset and
queue progress.

src/Utils/webviewProxy.js[52-63]
src/Utils/webviewProxy.js[73-90]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`parseForm()` can throw (notably via `decodeURIComponent()`), and `pump()` does not guard against that; this can leave `busy/current` set and stall the request queue.

### Issue Context
The proxy is a singleton used by the axios adapter for Cloudflare-protected pages; wedging it breaks all such page loads until app restart/unmount.

### Fix Focus Areas
- src/Utils/webviewProxy.js[52-64]
- src/Utils/webviewProxy.js[73-91]

### Proposed fix
- Wrap `parseForm(body)` in `pump()` with `try/catch` and call `settle(null, '...')` (or a dedicated cleanup) on error.
- Make `parseForm` more defensive:
 - skip pairs without `=`
 - wrap `decodeURIComponent` per field; on decode failure, fall back to raw strings
 - optionally accept `URLSearchParams` or object bodies explicitly instead of stringifying arbitrary objects.
- Ensure a `finally` path resets `busy/current` for any synchronous error before/without injecting JS.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

4. Success path calls checkDownTime 🐞 Bug ≡ Correctness
Description
getAdvancedSearchFilters() dispatches checkDownTime({filters}, source) on success, but checkDownTime
only clears downtime/records success when the first argument is null/undefined. This can leave
downTime/source success tracking stale even after a successful filters fetch.
Code

src/Redux/Actions/GlobalActions.js[R284-288]

    const filters = parseAdvancedSearchFilters($, config);

-    dispatch(checkDownTime({filters}));
+    dispatch(checkDownTime({filters}, source));
Evidence
GlobalActions passes a non-null object to checkDownTime on success, while errorHandlers defines the
success branch strictly as if (!error); therefore the intended success side effects will not
occur.

src/Redux/Actions/GlobalActions.js[270-289]
src/Redux/Actions/utils/errorHandlers.js[38-47]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`checkDownTime` is an error/success handler that treats any truthy first argument as an error path. Passing `{filters}` on success prevents the intended success behavior.

### Issue Context
`checkDownTime(!error)` is the only path that dispatches `DownTime(false)` and records per-source success.

### Fix Focus Areas
- src/Redux/Actions/GlobalActions.js[281-289]
- src/Redux/Actions/utils/errorHandlers.js[38-47]

### Proposed fix
- Replace `dispatch(checkDownTime({filters}, source))` with one of:
 - `dispatch(checkDownTime(null, source))` (preferred if you want the per-source success bookkeeping)
 - or explicitly `dispatch(DownTime(false))` and call `recordSourceSuccess(source)` if that’s the intention.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. Cancel download not honored 🐞 Bug ≡ Correctness
Description
NovelDownloadManager.cancelDownload() removes the download entry but downloadChapters() never checks
for cancellation and only stops on PAUSED, so it continues downloading/saving chapters after the
user cancels. This makes cancel ineffective and can waste bandwidth/storage.
Code

src/Screens/Novel/Utils/DownloadManager.js[R217-223]

+  /**
+   * Cancel a download
+   */
+  cancelDownload(novelLink) {
+    this.downloads.delete(novelLink);
+    this.notifyListeners(novelLink, DownloadStatus.IDLE, 0);
+  }
Evidence
The chapter download loop reads status each iteration but only returns early when PAUSED; cancel
removes the status record entirely, which does not trigger any stop condition.

src/Screens/Novel/Utils/DownloadManager.js[116-123]
src/Screens/Novel/Utils/DownloadManager.js[220-223]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`cancelDownload()` doesn't stop an in-flight `downloadChapters()` loop.

### Issue Context
The loop checks only `DownloadStatus.PAUSED`. After cancel, `this.downloads.get()` becomes `undefined`, so the loop continues.

### Fix Focus Areas
- src/Screens/Novel/Utils/DownloadManager.js[116-123]
- src/Screens/Novel/Utils/DownloadManager.js[220-223]

### Proposed fix
- Introduce a per-download cancellation flag/token, e.g. store `{status: 'canceled'}` or `{abort: AbortController}`.
- In the loop, before each chapter (and after network calls), check for canceled and return early.
- Optionally prevent writes (`saveChapterContent`) when canceled mid-flight.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


6. Offline novel slug collisions 🐞 Bug ☼ Reliability
Description
OfflineStorage.getNovelPath() falls back to 'unknown' when novelLink doesn't contain '/book/',
causing multiple novels to share the same offline directory and overwrite each other. Other novel UI
code already anticipates links without '/book/', so this fallback is reachable.
Code

src/Screens/Novel/Utils/OfflineStorage.js[R29-32]

+export function getNovelPath(novelLink) {
+  const slug = novelLink.split('/book/')[1]?.replace(/\//g, '-') || 'unknown';
+  return `${NOVELS_ROOT}/${slug}`;
+}
Evidence
OfflineStorage uses a shared 'unknown' fallback directory when '/book/' is absent, and the novel UI
keying logic explicitly supports the case where '/book/' is missing, implying links may not always
conform.

src/Screens/Novel/Utils/OfflineStorage.js[29-32]
src/Screens/Novel/Components/NovelList.js[19-26]
src/Screens/Novel/SeeAll/index.js[25-31]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
Non-`/book/` novel links map to the same `unknown` directory, corrupting offline metadata/chapters.

### Issue Context
Elsewhere, novel list keys fall back to using the full URL when `/book/` is missing, indicating this can occur in practice.

### Fix Focus Areas
- src/Screens/Novel/Utils/OfflineStorage.js[29-32]
- src/Screens/Novel/Components/NovelList.js[19-26]
- src/Screens/Novel/SeeAll/index.js[25-31]

### Proposed fix
- Derive the directory name from a collision-resistant identifier:
 - Prefer hostname + pathname normalized, then sanitize to safe filename chars, OR
 - Hash the full `novelLink` (e.g., SHA-1/MD5) and use that as the directory key.
- If `novelLink` is missing/invalid, fail explicitly instead of writing to a shared fallback directory.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

Comment on lines +35 to +37
/** True if the URL targets a Cloudflare-challenged host we manage clearance for. */
export const isCloudflareProtectedUrl = url =>
typeof url === 'string' && CF_PROTECTED_HOSTS.some(host => url.includes(host));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. Cloudflare host match too loose 🐞 Bug ⛨ Security

isCloudflareProtectedUrl() uses substring matching (url.includes(host)), so non-Cloudflare URLs that
merely contain the host string can be misclassified and routed through the Cloudflare WebView proxy
and/or have clearance headers attached. This can cause incorrect navigation/request behavior and may
leak clearance headers if a misclassified URL is ever used.
Agent Prompt
### Issue description
`isCloudflareProtectedUrl()` uses `url.includes(host)`, which does not validate the actual URL hostname and can misclassify arbitrary URLs.

### Issue Context
This function gates:
- axios adapter routing to the hidden WebView proxy
- attaching `Cookie`/`User-Agent` headers for protected resources

### Fix Focus Areas
- src/Utils/cloudflareClearance.js[35-37]
- src/Redux/Controller/Interceptor.js[22-33]
- src/Components/UIComp/Image.js[20-42]
- src/Components/CloudflareProxy/index.js[111-121]

### Proposed fix
- Replace substring matching with strict URL parsing:
  - `const {hostname} = new URL(url)` (guard try/catch)
  - match `hostname === 'readcomicsonline.ru'` (or `hostname.endsWith('.readcomicsonline.ru')` if subdomains are intended)
- Consider tightening WebView `originWhitelist` to `['https://readcomicsonline.ru/*']` (and any other explicitly supported CF origins) to reduce blast radius if a URL ever slips through.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +14 to +15
android:usesCleartextTraffic="${usesCleartextTraffic}"
android:supportsRtl="true">

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

2. Unresolved manifest placeholder 🐞 Bug ☼ Reliability

AndroidManifest.xml sets android:usesCleartextTraffic="${usesCleartextTraffic}" but the project does
not define a manifestPlaceholder for usesCleartextTraffic, which can break Android manifest
merging/builds. If later defined incorrectly, it could also unintentionally enable cleartext traffic
in release.
Agent Prompt
### Issue description
The Android manifest references an unresolved placeholder `${usesCleartextTraffic}`.

### Issue Context
No `manifestPlaceholders` configuration is present in `android/app/build.gradle`, so this placeholder is not set by default.

### Fix Focus Areas
- android/app/src/main/AndroidManifest.xml[14-15]
- android/app/build.gradle[77-116]

### Proposed fix
Choose one:
1) **Hardcode a safe value** (recommended):
   - Set `android:usesCleartextTraffic="false"` in the main manifest.
   - If debug needs cleartext, add a debug manifest overlay or build-type specific manifest.

2) **Use manifestPlaceholders explicitly**:
   - In `android/app/build.gradle`:
     - `defaultConfig { manifestPlaceholders = [usesCleartextTraffic: "false"] }`
     - Optionally override in `buildTypes.debug { manifestPlaceholders.usesCleartextTraffic = "true" }` if required.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment thread src/Utils/webviewProxy.js
Comment on lines +52 to +61
const parseForm = body => {
const out = [];
String(body || '')
.split('&')
.filter(Boolean)
.forEach(pair => {
const i = pair.indexOf('=');
const k = decodeURIComponent(pair.slice(0, i));
const v = decodeURIComponent(pair.slice(i + 1).replace(/\+/g, ' '));
out.push(`<input type="hidden" name="${escapeAttr(k)}" value="${escapeAttr(v)}">`);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

3. Proxy post parsing can throw 🐞 Bug ☼ Reliability

webviewProxy.parseForm() calls decodeURIComponent() on untrusted strings without guarding, so
malformed percent-encoding can throw synchronously. Because pump() sets proxy state (busy/current)
and does not catch around parseForm(), an exception can wedge the proxy and strand subsequent
Cloudflare requests.
Agent Prompt
### Issue description
`parseForm()` can throw (notably via `decodeURIComponent()`), and `pump()` does not guard against that; this can leave `busy/current` set and stall the request queue.

### Issue Context
The proxy is a singleton used by the axios adapter for Cloudflare-protected pages; wedging it breaks all such page loads until app restart/unmount.

### Fix Focus Areas
- src/Utils/webviewProxy.js[52-64]
- src/Utils/webviewProxy.js[73-91]

### Proposed fix
- Wrap `parseForm(body)` in `pump()` with `try/catch` and call `settle(null, '...')` (or a dedicated cleanup) on error.
- Make `parseForm` more defensive:
  - skip pairs without `=`
  - wrap `decodeURIComponent` per field; on decode failure, fall back to raw strings
  - optionally accept `URLSearchParams` or object bodies explicitly instead of stringifying arbitrary objects.
- Ensure a `finally` path resets `busy/current` for any synchronous error before/without injecting JS.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines 284 to 288

const filters = parseAdvancedSearchFilters($, config);

dispatch(checkDownTime({filters}));
dispatch(checkDownTime({filters}, source));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remediation recommended

4. Success path calls checkdowntime 🐞 Bug ≡ Correctness

getAdvancedSearchFilters() dispatches checkDownTime({filters}, source) on success, but checkDownTime
only clears downtime/records success when the first argument is null/undefined. This can leave
downTime/source success tracking stale even after a successful filters fetch.
Agent Prompt
### Issue description
`checkDownTime` is an error/success handler that treats any truthy first argument as an error path. Passing `{filters}` on success prevents the intended success behavior.

### Issue Context
`checkDownTime(!error)` is the only path that dispatches `DownTime(false)` and records per-source success.

### Fix Focus Areas
- src/Redux/Actions/GlobalActions.js[281-289]
- src/Redux/Actions/utils/errorHandlers.js[38-47]

### Proposed fix
- Replace `dispatch(checkDownTime({filters}, source))` with one of:
  - `dispatch(checkDownTime(null, source))` (preferred if you want the per-source success bookkeeping)
  - or explicitly `dispatch(DownTime(false))` and call `recordSourceSuccess(source)` if that’s the intention.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +217 to +223
/**
* Cancel a download
*/
cancelDownload(novelLink) {
this.downloads.delete(novelLink);
this.notifyListeners(novelLink, DownloadStatus.IDLE, 0);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remediation recommended

5. Cancel download not honored 🐞 Bug ≡ Correctness

NovelDownloadManager.cancelDownload() removes the download entry but downloadChapters() never checks
for cancellation and only stops on PAUSED, so it continues downloading/saving chapters after the
user cancels. This makes cancel ineffective and can waste bandwidth/storage.
Agent Prompt
### Issue description
`cancelDownload()` doesn't stop an in-flight `downloadChapters()` loop.

### Issue Context
The loop checks only `DownloadStatus.PAUSED`. After cancel, `this.downloads.get()` becomes `undefined`, so the loop continues.

### Fix Focus Areas
- src/Screens/Novel/Utils/DownloadManager.js[116-123]
- src/Screens/Novel/Utils/DownloadManager.js[220-223]

### Proposed fix
- Introduce a per-download cancellation flag/token, e.g. store `{status: 'canceled'}` or `{abort: AbortController}`.
- In the loop, before each chapter (and after network calls), check for canceled and return early.
- Optionally prevent writes (`saveChapterContent`) when canceled mid-flight.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +29 to +32
export function getNovelPath(novelLink) {
const slug = novelLink.split('/book/')[1]?.replace(/\//g, '-') || 'unknown';
return `${NOVELS_ROOT}/${slug}`;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remediation recommended

6. Offline novel slug collisions 🐞 Bug ☼ Reliability

OfflineStorage.getNovelPath() falls back to 'unknown' when novelLink doesn't contain '/book/',
causing multiple novels to share the same offline directory and overwrite each other. Other novel UI
code already anticipates links without '/book/', so this fallback is reachable.
Agent Prompt
### Issue description
Non-`/book/` novel links map to the same `unknown` directory, corrupting offline metadata/chapters.

### Issue Context
Elsewhere, novel list keys fall back to using the full URL when `/book/` is missing, indicating this can occur in practice.

### Fix Focus Areas
- src/Screens/Novel/Utils/OfflineStorage.js[29-32]
- src/Screens/Novel/Components/NovelList.js[19-26]
- src/Screens/Novel/SeeAll/index.js[25-31]

### Proposed fix
- Derive the directory name from a collision-resistant identifier:
  - Prefer hostname + pathname normalized, then sanitize to safe filename chars, OR
  - Hash the full `novelLink` (e.g., SHA-1/MD5) and use that as the directory key.
- If `novelLink` is missing/invalid, fail explicitly instead of writing to a shared fallback directory.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

@pushpender-singh-ap
pushpender-singh-ap deleted the RN84 branch July 16, 2026 08:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant