Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
306f5b2
fix: install the right version of hermes compiler
CD-Z Apr 6, 2026
3de93c5
feat: migrate from rn community cli to rock (#1812)
CD-Z Apr 13, 2026
01596c0
fix: Apply active filters to chapter count display (Closes #1793) (#1…
Definisi Apr 13, 2026
2a919ec
chore: gitignore tsconfig.tsbuildinfo build cache (#1829)
tinywind May 3, 2026
b680a07
fix(browse): use gesture-handler Pressable in PluginListItem (#1828)
tinywind May 3, 2026
eafa545
Use novel refactor (#1838)
CD-Z May 6, 2026
8f47e8f
Theme switcher refactor (#1839)
CD-Z May 7, 2026
2cd5a97
fix: await database operations inside transactions (#1845)
VictorPersona May 10, 2026
25c93af
fix(reader): restore saved chapter progress from db if available (#1850)
Jaky-gh May 24, 2026
60f42ed
chore(build): patch @rock-js/plugin-metro for Windows compatibility (…
tinywind May 24, 2026
34be7a1
fix(native-file): prevent fatal crash when unlinking missing files (#…
tinywind May 24, 2026
57b9d41
fix(service): Correct Notification Throttle Logic in ServiceManager.s…
alirafiqmalik Jul 1, 2026
e8c5550
perf: Optimize Regex for Removing Extra Paragraph Spacing (#1872)
Palloxin Jul 1, 2026
54fedc2
fix(tts): Remove Leading and Trailing Quotes from Normalized Text (#1…
vikas-movva Jul 1, 2026
bbb2645
chore: Clean Reader Preview Content (#1867)
Palloxin Jul 1, 2026
5d996f1
feat(downloads): Make Chapter Download Cooldown Configurable (#1834)
tinywind Jul 1, 2026
93bc5e5
fix: Handle Missing MAL List Entries and Null Progress (Closes #1875)
rajarsheechatterjee Jul 1, 2026
52d5c99
fix: Order EPUB Chapters Across Paginated Pages (Closes #1762)
rajarsheechatterjee Jul 1, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 17 additions & 45 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
name: Build

on:
push:
branches:
Expand All @@ -14,6 +15,7 @@ jobs:
name: Build App
runs-on: ubuntu-latest
timeout-minutes: 60

steps:
- name: Checkout Repository
uses: actions/checkout@v4
Expand All @@ -23,7 +25,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
node-version: '24'

- name: Setup pnpm
uses: pnpm/action-setup@v4
Expand All @@ -41,54 +43,24 @@ jobs:
restore-keys: |
${{ runner.os }}-pnpm-store-

- name: Setup Java
uses: actions/setup-java@v4
with:
distribution: 'zulu'
java-version: '17'

- name: Setup Gradle
uses: gradle/actions/setup-gradle@v4
with:
cache-read-only: false

- name: Install Dependencies
run: pnpm install --frozen-lockfile

- name: Create Environment File
run: |
cat > .env << EOF
MYANIMELIST_CLIENT_ID=${{ vars.MYANIMELIST_CLIENT_ID }}
ANILIST_CLIENT_ID=${{ vars.ANILIST_CLIENT_ID }}
GIT_HASH=$(git rev-parse --short HEAD)
RELEASE_DATE=$(date --utc +'%d/%m/%y %I:%M %p %Z')
BUILD_TYPE=Github Action
EOF

- name: Make Gradlew Executable
run: cd android && chmod +x ./gradlew

- name: Set Environment Variables
run: |
set -x
echo "COMMIT_COUNT=$(git rev-list --count HEAD)" >> $GITHUB_ENV
echo "COMMIT_ID=$(git rev-parse --short HEAD)" >> $GITHUB_ENV

- name: Build Android Release
env:
COMMIT_COUNT: ${{ env.COMMIT_COUNT }}
COMMIT_ID: ${{ env.COMMIT_ID }}
- name: Generate Environment Variables
run: |
sed -i 's/lnreader/lnreader-r${{ env.COMMIT_COUNT }}(${{ env.COMMIT_ID }})/g' android/app/src/main/res/values/strings.xml
cd android && ./gradlew assembleRelease -PcustomAppId=com.rajarsheechatterjee.LNReader.commit_${{ env.COMMIT_ID }} --build-cache
mv app/build/outputs/apk/release/app-release.apk app/build/outputs/apk/release/LNReader-r${{ env.COMMIT_COUNT }}-${{ env.COMMIT_ID }}.apk
pnpm generate:env:release \
--build-type "Github Action" \
--node-env "production" \
--myanimelist-client-id "${{ vars.MYANIMELIST_CLIENT_ID }}" \
--anilist-client-id "${{ vars.ANILIST_CLIENT_ID }}"

- name: Upload Release Artifact
- name: Build Android Release with Rock
uses: callstackincubator/android@v3
env:
COMMIT_COUNT: ${{ env.COMMIT_COUNT }}
COMMIT_ID: ${{ env.COMMIT_ID }}
uses: actions/upload-artifact@v4
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
REPO_OWNER: ${{ github.repository_owner }}
REPO_NAME: ${{ github.event.repository.name }}
with:
name: LNReader-r${{ env.COMMIT_COUNT }}-${{ env.COMMIT_ID }}
path: android/app/build/outputs/apk/release/LNReader-r${{ env.COMMIT_COUNT }}-${{ env.COMMIT_ID }}.apk
retention-days: 30
re-sign: true
github-token: ${{ secrets.GITHUB_TOKEN }}
variant: preRelease
2 changes: 1 addition & 1 deletion .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
node-version: '24'

- name: Setup pnpm
uses: pnpm/action-setup@v4
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/testing.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
node-version: '24'

- name: Setup pnpm
uses: pnpm/action-setup@v4
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/types.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
node-version: '24'

- name: Setup pnpm
uses: pnpm/action-setup@v4
Expand Down
10 changes: 9 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ npm-debug.*
*.mobileprovision
*.orig.*
web-build/
.env
.*env
reader_playground/index.html
# macOS
.DS_Store
Expand Down Expand Up @@ -89,8 +89,16 @@ flake.lock
# pnpm
.pnpm-store

src/generated/**/*

.cursor/
.agents/
.claude/
.jj/
.sisyphus/

# Rock
.rock/

# TypeScript
*.tsbuildinfo
15 changes: 9 additions & 6 deletions App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import AppErrorBoundary, {
import Main from './src/navigators/Main';
import { BottomSheetModalProvider } from '@gorhom/bottom-sheet';
import { useInitDatabase } from '@database/db';
import { ThemeProvider } from '@hooks/persisted/useTheme';

Notifications.setNotificationHandler({
handleNotification: async () => {
Expand Down Expand Up @@ -49,12 +50,14 @@ const App = () => {
<GestureHandlerRootView style={styles.flex}>
<AppErrorBoundary>
<SafeAreaProvider>
<PaperProvider>
<BottomSheetModalProvider>
<StatusBar translucent={true} backgroundColor="transparent" />
<Main />
</BottomSheetModalProvider>
</PaperProvider>
<ThemeProvider>
<PaperProvider>
<BottomSheetModalProvider>
<StatusBar translucent={true} backgroundColor="transparent" />
<Main />
</BottomSheetModalProvider>
</PaperProvider>
</ThemeProvider>
</SafeAreaProvider>
</AppErrorBoundary>
</GestureHandlerRootView>
Expand Down
3 changes: 3 additions & 0 deletions __mocks__/database.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
jest.mock('@database/queries/NovelQueries', () => ({
getNovelById: jest.fn(),
getNovelByPath: jest.fn(),
deleteCachedNovels: jest.fn(),
getCachedNovels: jest.fn(),
Expand Down Expand Up @@ -30,7 +31,9 @@ jest.mock('@database/queries/ChapterQueries', () => ({
insertChapters: jest.fn(),
getCustomPages: jest.fn(),
getChapterCount: jest.fn(),
getChapterCountSync: jest.fn(),
getPageChaptersBatched: jest.fn(),
getNovelChaptersSync: jest.fn(),
getFirstUnreadChapter: jest.fn(),
updateChapterProgress: jest.fn(),
}));
Expand Down
13 changes: 8 additions & 5 deletions __tests-modules__/test-utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { GestureHandlerRootView } from 'react-native-gesture-handler';
import { SafeAreaProvider } from 'react-native-safe-area-context';
import { Provider as PaperProvider } from 'react-native-paper';
import { BottomSheetModalProvider } from '@gorhom/bottom-sheet';
import { ThemeProvider } from '@hooks/persisted/useTheme';

import AppErrorBoundary from '@components/AppErrorBoundary/AppErrorBoundary';
import { NovelContextProvider } from '@screens/novel/NovelContext';
Expand All @@ -13,11 +14,13 @@ const AllTheProviders = ({ children }: { children: React.ReactElement }) => {
return (
<GestureHandlerRootView>
<SafeAreaProvider>
<PaperProvider>
<BottomSheetModalProvider>
<AppErrorBoundary>{children}</AppErrorBoundary>
</BottomSheetModalProvider>
</PaperProvider>
<ThemeProvider>
<PaperProvider>
<BottomSheetModalProvider>
<AppErrorBoundary>{children}</AppErrorBoundary>
</BottomSheetModalProvider>
</PaperProvider>
</ThemeProvider>
</SafeAreaProvider>
</GestureHandlerRootView>
);
Expand Down
17 changes: 14 additions & 3 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ react {
// The folder where the react-native Codegen package is. Default is ../../node_modules/@react-native/codegen
// codegenDir = file("../../node_modules/@react-native/codegen")
// The cli.js file which is the React Native CLI entrypoint. Default is ../../node_modules/react-native/cli.js
// cliFile = file("../../node_modules/react-native/cli.js")
cliFile = file("../../node_modules/rock/dist/src/bin.js")

/* Variants */
// The list of variants to that are debuggable. For those we're going to
Expand Down Expand Up @@ -84,7 +84,7 @@ android {
compileSdk rootProject.ext.compileSdkVersion
namespace "com.rajarsheechatterjee.LNReader"
defaultConfig {
applicationId project.hasProperty('customAppId') ? project.getProperty('customAppId') : 'com.rajarsheechatterjee.LNReader'
applicationId 'com.rajarsheechatterjee.LNReader'
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
// Generated version code. Supports versions up to 1024.1024.2048
Expand All @@ -105,6 +105,17 @@ android {
applicationIdSuffix 'debug'
versionNameSuffix '-debug'
}
preRelease {
initWith release
matchingFallbacks = ["release"]
// Caution! In production, you need to generate your own keystore file.
// see https://reactnative.dev/docs/signed-apk-android.
applicationIdSuffix 'preRelease'
versionNameSuffix '-pre-release'
signingConfig signingConfigs.debug
minifyEnabled enableProguardInReleaseBuilds
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
}
release {
// Caution! In production, you need to generate your own keystore file.
// see https://reactnative.dev/docs/signed-apk-android.
Expand Down Expand Up @@ -134,4 +145,4 @@ dependencies {
} else {
implementation jscFlavor
}
}
}
5 changes: 3 additions & 2 deletions android/app/src/main/assets/js/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ window.tts = new (function () {
this.normalizeText = text => {
if (!text) return '';
return text
.replace(/^["'“”‘’]+|["'“”‘’]+$/g, '')
.replace(/\s+/g, ' ')
.replace(/\s*([.,!?;:])\s*/g, '$1 ')
.trim();
Expand Down Expand Up @@ -780,13 +781,13 @@ window.addEventListener('load', () => {
`${
/\/p>/.test(_)
? _.replace(
/<br>\s*<br>(?:(?=\s*<\/?p[> ])|(?<=<\/?p\b[^>]*><br>\s*<br>))\s*/g,
/<br>\s*<br>(?:(?=\s*<\/?p[> ])|(?<=<\/?p(?:>| [^>]+>)<br>\s*<br>))\s*/g,
'',
)
: _
}`,
) //if p found, delete all double br near p
.replace(/<br>(?:(?=\s*<\/?p[> ])|(?<=<\/?p>\s*<br>))\s*/g, '');
.replace(/<br>(?:(?=\s*<\/?p[> ])|(?<=<\/?p(?:>| [^>]+>)(?:<[^>]+>)*\s*<br>))\s*/g, '');
}
reader.chapterElement.innerHTML = html;
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ class NativeFile(context: ReactApplicationContext) :

override fun unlink(filepath: String) {
val file = File(filepath)
if (!file.exists()) throw Exception("File does not exist")
if (!file.exists()) return
deleteRecursive(file)
}

Expand Down
5 changes: 3 additions & 2 deletions android/settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,11 @@ plugins {
}

extensions.configure(com.facebook.react.ReactSettingsExtension) { ex ->
def npxCmd = System.getProperty('os.name').toLowerCase().contains('windows') ? 'npx.cmd' : 'npx'
if (System.getenv('EXPO_USE_COMMUNITY_AUTOLINKING') == '1') {
ex.autolinkLibrariesFromCommand()
ex.autolinkLibrariesFromCommand([npxCmd, 'rock', 'config', '-p', 'android'])
} else {
ex.autolinkLibrariesFromCommand(expoAutolinking.rnConfigCommand)
ex.autolinkLibrariesFromCommand([npxCmd, 'rock', 'config', '-p', 'android'])
}
}

Expand Down
1 change: 1 addition & 0 deletions babel.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export default function (api) {
'@type': './src/type',
'@specs': './specs',
'@test-utils': './__tests-modules__/test-utils',
'@env': './src/generated/build-info',
'react-native-vector-icons/MaterialCommunityIcons':
'@react-native-vector-icons/material-design-icons',
},
Expand Down
12 changes: 0 additions & 12 deletions env.d.ts

This file was deleted.

2 changes: 1 addition & 1 deletion ios/LNReader.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "set -e\n\nWITH_ENVIRONMENT=\"$REACT_NATIVE_PATH/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"$REACT_NATIVE_PATH/scripts/react-native-xcode.sh\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT $REACT_NATIVE_XCODE\"\n";
shellScript = "set -e\nif [[ -f \"$PODS_ROOT/../.xcode.env\" ]]; then\nsource \"$PODS_ROOT/../.xcode.env\"\nfi\nif [[ -f \"$PODS_ROOT/../.xcode.env.local\" ]]; then\nsource \"$PODS_ROOT/../.xcode.env.local\"\nfi\nexport CONFIG_CMD=\"dummy-workaround-value\"\nexport CLI_PATH=\"$(\"$NODE_BINARY\" --print \"require('path').dirname(require.resolve('rock/package.json')) + '/dist/src/bin.js'\")\"\nWITH_ENVIRONMENT=\"$REACT_NATIVE_PATH/scripts/xcode/with-environment.sh\"\n";
};
00EEFC60759A1932668264C0 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
Expand Down
2 changes: 1 addition & 1 deletion ios/Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ target 'LNReader' do
]
end

config = use_native_modules!(config_command)
config = use_native_modules!(['npx', 'rock', 'config', '-p', 'ios'])(config_command)

use_react_native!(
:path => config[:reactNativePath],
Expand Down
1 change: 1 addition & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const baseModuleNameMapper = {
'^@type/(.*)$': '<rootDir>/src/type/$1',
'^@specs/(.*)$': '<rootDir>/specs/$1',
'^@test-utils$': '<rootDir>/__tests-modules__/test-utils',
'^@env$': '<rootDir>/src/generated/build-info',
// Mock static assets
'\\.(jpg|jpeg|png|gif|webp|svg)$': '<rootDir>/__mocks__/fileMock.js',
};
Expand Down
Loading