feat: introduce novel reading module with multi-source and offline support#71
feat: introduce novel reading module with multi-source and offline support#71pushpender-singh-ap merged 9 commits intomainfrom
Conversation
Add comprehensive novel reading functionality: Features: - Novel home, details, reader, search, and library screens - Text and WebView reader modes with customizable settings (theme, font, line height) - Chapter progress tracking and reading history - Novel bookmarks management - Integration with existing search (comics, manga, novels unified) - Novel tab added to Bookmarks and Library screens Navigation: - 6 new navigation routes for novel screens Redux state: - NovelBookMarks, NovelHistory for bookmarks and reading progress - Novel reader settings (mode, theme, fontSize, lineHeight, fontFamily) Components: - NovelCard, NovelList, ChapterList, GenreTags, NovelInfo - ReaderSettings, TextReader, WebReader - DownloadButton (UI only - Redux actions pending) Utils: - DownloadManager and OfflineStorage for offline reading - Novel parser and API modules Note: Novel offline download Redux actions (DownloadNovelChapter, RemoveNovelChapter, clearNovelDownloads) and NovelDownloads state are referenced but not yet implemented in reducers.
Implement a comprehensive source health monitoring system that tracks and notifies users when content sources (comics, anime, manga) experience errors. New Features: - Source status tracking utility () with MMKV persistence - Distinguishes between Cloudflare protection (403) and server down (500+) errors - Custom React hooks for source status management () - UI components for status display: - - inline banners, badges, and toasts - - notification list component Redux Integration: - Added state with deduplication (5-min window) - New actions: set, mark read, remove, and clear notifications - Limits to 20 notifications max Error Handling Updates: - and now accept parameter - Automatic notification dispatch for 403/500+ errors - Added Cloudflare-specific error message API Updates: - , , , now pass source context - , , include source tracking UI Updates: - Notifications screen shows combined source status and community notifications - Library screen tracks unread source status notifications - New component with dismiss functionality Other: - Updated InkNest-Externals submodule
Update email address from inknest@mail.p2devs.engineer to inknest@capacity.rocks across README and documentation pages.
The persistNotificationList function is synchronous and returns undefined, not a Promise. Calling .catch() on undefined caused catch error. Removed the .catch() since MMKV storage operations are synchronous.
- Change background color from #0F0F1A to #14142A to match Library screen - Fix header title centering using absolute positioning for proper alignment
Refactor Novel APIs to support multiple sources via hostKey parameter, enabling the app to fetch content from both NovelFire and WTR-Lab. APIs: - Refactor Reader.js, Search.js, Details.js, Home.js to accept optional hostKey parameter (default: 'novelfire') - Add getHostKeyFromLink() for auto-detecting source from URLs - Add WTR-Lab reader API integration with POST-based chapter fetching - Add reading mode fallback logic (web → ai) for WTR-Lab chapters - Add source-specific CSS selector configs in new constance.js - Update index.js exports to include source configs and new functions Components: - Add SourceSelector component for switching between novel sources with status indicators (working/protected/down) - Add WTRLabModeSelector component for selecting reading mode (web, webplus, ai) with persistence via Redux - Refactor TextReader to split content into paragraphs with spacing - Refactor WebReader with HTML document builder, URL builder, origin whitelisting, and WTR-Lab cookie/session support Novel Reader: - Add WTR-Lab text extraction via hidden WebView with injected JS - Add fallback metadata builder for non-AI reading modes - Fix scroll restoration to account for async content loading - Add loading overlay during text extraction - Add language mode button in header for WTR-Lab chapters Source Status: - Add recordSourceSuccess/recordSourceError tracking for novel APIs - Register novel sources (novelfire, wtrlab) in sourceStatus.js - Add NovelHostName config in APIs.js Parsers: - Add novelChapterParser.js with WTR-Lab chapter parsing - Add novelDetailParser.js for source-agnostic detail parsing - Add novelHomeParser.js for source-agnostic home page parsing - Add NovelActions.js with switchNovelSource action - Update Redux reducer to handle novel source state Tests: - Add novelChapterParser.test.js for parser validation iOS: - Update Podfile and Podfile.lock for new dependencies - Update Xcode project.pbxproj for new resource files
Review Summary by QodoIntroduce Novel Reading Module with Multi-Source Support and Offline Capabilities
WalkthroughsDescription• **Novel Reading Module**: Comprehensive novel discovery, reading, and management system with support for multiple sources (NovelFire, WTR-Lab) • **Multi-Source Architecture**: Implemented parsers and APIs for novel metadata extraction, chapter fetching, and content rendering from multiple sources • **WTR-Lab Integration**: Added specific support for WTR-Lab including encrypted content decryption, multiple reading modes (web/webplus/ai), and host key detection • **Offline Reading Support**: Implemented download manager and offline storage utilities enabling users to download chapters for offline viewing • **Source Status Tracking**: Introduced comprehensive system to monitor and notify users about source availability, downtime, and health status via notifications and status indicators • **Novel Reader Component**: Full-featured reader with text and webview modes, theme customization (dark/light/sepia), scroll position restoration, and reading progress tracking • **Search & Discovery**: Multi-category search interface supporting Comics, Manga, and Novels with unified result rendering and novel-specific search functionality • **Library Integration**: Added novel tab to library with bookmarks, reading history, continue reading functionality, and source selector • **Reader Customization**: Settings modal for font size, line height, font family, theme, and reading mode preferences • **UI/UX Improvements**: Enhanced Search component layout with centered header, updated background color, and improved category/source tab design • **Redux State Management**: Added novel-specific state for bookmarks, reading history, chapter progress, and reader preferences • **Error Handling**: Enhanced error tracking with source context and improved API error handling with hostkey parameter Diagramflowchart LR
A["Novel Sources<br/>NovelFire, WTR-Lab"] -->|"Parse & Extract"| B["Novel Parsers<br/>novelChapterParser,<br/>novelDetailParser"]
B -->|"Fetch Data"| C["Novel APIs<br/>Home, Details,<br/>Reader, Search"]
C -->|"Render UI"| D["Novel Screens<br/>Home, Details,<br/>Reader, Search"]
D -->|"Manage State"| E["Redux Store<br/>Bookmarks, History,<br/>Preferences"]
E -->|"Persist"| F["Offline Storage<br/>Download Manager"]
D -->|"Track Status"| G["Source Status<br/>Notifications,<br/>Indicators"]
H["Search Module"] -->|"Integrate"| D
I["Library"] -->|"Include"| D
File Changes1. src/Redux/Actions/parsers/novelChapterParser.js
|
Code Review by Qodo
1. Broken hook import paths
|
| import {useSelector, useDispatch} from 'react-redux'; | ||
| import {useCallback, useEffect, useState} from 'react'; | ||
| import { | ||
| markSourceStatusNotificationRead, | ||
| removeSourceStatusNotification, | ||
| clearSourceStatusNotifications, | ||
| } from '../Redux/Reducers'; | ||
| import { | ||
| getSourceStatus, | ||
| getAllSourceStatuses, | ||
| SOURCE_STATUS, | ||
| formatLastChecked, | ||
| getSourceLabel, | ||
| } from '../Utils/sourceStatus'; |
There was a problem hiding this comment.
1. Broken hook import paths 🐞 Bug ✓ Correctness
src/Utils/hooks/useSourceStatus.js imports ../Redux/Reducers and ../Utils/sourceStatus, which do not exist relative to src/Utils/hooks, causing a module-resolution failure when the hook is imported.
Agent Prompt
## Issue description
`src/Utils/hooks/useSourceStatus.js` uses incorrect relative import paths (`../Redux/Reducers` and `../Utils/sourceStatus`) that cannot resolve from inside `src/Utils/hooks/`, leading to bundler/runtime "module not found" failures.
## Issue Context
The correct modules live under `src/Redux/Reducers` and `src/Utils/sourceStatus`.
## Fix Focus Areas
- src/Utils/hooks/useSourceStatus.js[1-14]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
| } | ||
| } | ||
| dispatch(checkDownTime(response)); | ||
| dispatch(checkDownTime(response, baseUrl)); |
There was a problem hiding this comment.
2. Downtime never clears 🐞 Bug ⛯ Reliability
Several success paths pass an Axios response object (or a non-error object) into checkDownTime, but checkDownTime only reads error.response.status, so DownTime(false) and recordSourceSuccess() are skipped and downtime/source-status can remain stuck after failures.
Agent Prompt
## Issue description
`checkDownTime()` is used with both Axios error objects and Axios success response objects. After the change, it only inspects `error.response.status`, so when callers pass a success `response` (with `response.status`) or other truthy placeholders, downtime/source-status is not cleared.
## Issue Context
Call sites in `HomeFunc` and `GlobalActions` dispatch `checkDownTime(response, sourceKey)` / `checkDownTime({filters}, source)` on success, but `checkDownTime` only clears downtime when the first argument is falsy.
## Fix Focus Areas
- src/Redux/Actions/utils/errorHandlers.js[38-95]
- src/Components/Func/HomeFunc.js[80-86]
- src/Components/Func/HomeFunc.js[167-179]
- src/Redux/Actions/GlobalActions.js[280-288]
## Suggested direction
Either:
- Update all success-path callers to dispatch `checkDownTime(null, sourceKey)` (and stop passing response/placeholder objects), OR
- Make `checkDownTime(result, sourceKey)` handle both shapes by deriving `statusCode` from `result.response?.status ?? result.status` and treating 2xx/3xx as success (dispatch `DownTime(false)` + `recordSourceSuccess(sourceKey)`).
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
| export function getNovelPath(novelLink) { | ||
| const slug = novelLink.split('/book/')[1]?.replace(/\//g, '-') || 'unknown'; | ||
| return `${NOVELS_ROOT}/${slug}`; | ||
| } |
There was a problem hiding this comment.
3. Offline novel path collision 🐞 Bug ✓ Correctness
OfflineStorage.getNovelPath() derives the novel directory using only
novelLink.split('/book/')[1] and falls back to 'unknown', but WTR-Lab novel URLs use /novel/,
so WTR-Lab downloads will collide in the same directory and overwrite metadata/chapters.
Agent Prompt
## Issue description
Offline novel storage path generation assumes URLs contain `/book/`. For WTR-Lab (which uses `/novel/`), `getNovelPath()` falls back to `'unknown'`, so all WTR-Lab novels share the same directory and overwrite each other.
## Issue Context
This impacts offline downloads (chapters + metadata) and can cause user data loss/corruption.
## Fix Focus Areas
- src/Screens/Novel/Utils/OfflineStorage.js[29-32]
- src/Screens/Novel/APIs/constance.js[109-116]
## Suggested direction
Derive a stable, filesystem-safe, unique directory name from the full URL (e.g., host + pathname) using `new URL(novelLink)` and then sanitize, or use a hash (e.g., SHA1/MD5) of `novelLink`.
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
This PR introduces the highly anticipated Novel Reading Module to InkNest, enabling users to discover, read, and download novels. It also includes comprehensive source status tracking, multi-source integrations (including WTR-Lab), and various UI/UX improvements across the app.
Key Changes & Features:
src/Screens/Novel). Includes a clean reader interface with customizable settings (TextReader,WebReader,ReaderSettings).WTRLabModeSelector.js,SourceSelector.js).OfflineStorage.js,DownloadManager.js,DownloadButton.js).SourceStatusBanner.js,SourceStatusNotification.js,useSourceStatus.js).Searchcomponent.NovelDetailsandSearchcomponents..catch()blocks on synchronous notification persists.inknest@capacity.rocks.