Files
readest/apps/readest-app/src-tauri/tauri.conf.json
T
Huang Xin 82bd90afc5 feat(reader): random-access file reads on Android via rangefile scheme (#4534)
* feat(reader): random-access file reads on Android via rangefile scheme

NativeFile's per-chunk Tauri IPC (open+seek+read+close) is slow on Android, and RemoteFile can't replace it because the WebView mishandles Range requests on intercepted custom-protocol responses — it re-applies the offset to the already-sliced body, so any non-zero-start range returns corrupt data or net::ERR_FAILED (Chromium 40739128, tauri-apps/tauri#12019/#3725).

Add a `rangefile` custom URI scheme that carries the byte range in the URL query (?path=&start=&end=) instead of a Range header. With no Range header the WebView delivers the 200 body verbatim, while bytes still stream through the network stack rather than the IPC bridge. The handler is scope-gated by asset_protocol_scope (same boundary as the asset protocol) plus an explicit traversal/NUL/relative guard.

RemoteFile.fromNativePath() drives the scheme on Android (query-carried range, X-Total-Size for size); nativeAppService.openFile routes Android reads through it with a NativeFile fallback. Verified on-device (Android 16 / WebView 147) via CDP: byte-equal reads at every offset, ~1.8x faster small scattered reads, real book opens/renders; all out-of-scope/traversal/NUL paths rejected 403.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* ci(rust): run cargo unit tests in rust_lint

The rust_lint job ran only fmt + clippy, so the crate's ~40 Rust unit tests (parsers, parser_common, and the new range_file tests) never executed in CI. Add `cargo test -p Readest --lib` to rust_lint — the frontend dist is absent there, but generate_context! already compiles without it (clippy proves this) and the unit tests run headless.

Also add a `test:rust` pnpm script and document it as verification done-condition #6.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 07:37:46 +02:00

182 lines
5.5 KiB
JSON

{
"$schema": "../node_modules/@tauri-apps/cli/config.schema.json",
"productName": "Readest",
"mainBinaryName": "readest",
"identifier": "com.bilingify.readest",
"version": "../package.json",
"build": {
"frontendDist": "../out",
"devUrl": "http://localhost:3000",
"beforeDevCommand": "pnpm dev",
"beforeBuildCommand": "pnpm build"
},
"app": {
"windows": [],
"security": {
"csp": {
"default-src": "'self' 'unsafe-inline' blob: data: customprotocol: asset: http://asset.localhost http://rangefile.localhost ipc: http://ipc.localhost",
"connect-src": "'self' blob: data: asset: http://asset.localhost http://rangefile.localhost ipc: http://ipc.localhost http://*:* https://*:* https://*.sentry.io https://*.posthog.com https://*.deepl.com https://*.wikipedia.org https://*.wiktionary.org https://*.supabase.co https://*.readest.com wss://speech.platform.bing.com https://*.cloudflarestorage.com https://translate.googleapis.com https://translate.toil.cc https://*.microsofttranslator.com https://edge.microsoft.com https://*.googleusercontent.com",
"img-src": "'self' blob: data: asset: http://asset.localhost https://* https://*:* http://* http://*:*",
"style-src": "'self' 'unsafe-inline' blob: asset: http://asset.localhost https://cdn.jsdelivr.net https://fonts.googleapis.com https://cdnjs.cloudflare.com https://storage.readest.com",
"font-src": "'self' blob: data: asset: http://asset.localhost tauri: https://db.onlinewebfonts.com https://cdn.jsdelivr.net https://fonts.gstatic.com https://cdnjs.cloudflare.com https://storage.readest.com",
"frame-src": "'self' blob: asset: http://asset.localhost https://*.stripe.com",
"script-src": "'self' 'unsafe-inline' 'unsafe-eval' data: blob: asset: http://asset.localhost https://*.sentry.io https://*.posthog.com https://*.stripe.com"
},
"assetProtocol": {
"enable": true,
"scope": {
"allow": [
"$RESOURCE/**",
"$APPDATA/**/*",
"$APPCACHE/**/*",
"$TEMP/**/*",
"**/Readest/**/*",
"/private/var/mobile/Containers/Data/Application/**/*"
],
"deny": []
}
}
}
},
"bundle": {
"active": true,
"targets": "all",
"category": "Productivity",
"icon": [
"icons/32x32.png",
"icons/128x128.png",
"icons/128x128@2x.png",
"icons/icon.icns",
"icons/icon.ico"
],
"resources": [],
"windows": {
"webviewInstallMode": {
"type": "embedBootstrapper"
},
"nsis": {
"installerHooks": "nsis/installer-hooks.nsh",
"installMode": "both"
}
},
"macOS": {
"minimumSystemVersion": "12.0"
},
"linux": {
"deb": {
"section": "text"
}
},
"android": {
"minSdkVersion": 26
},
"iOS": {
"developmentTeam": "J5W48D69VR",
"infoPlist": "./Info-ios.plist",
"minimumSystemVersion": "15.0"
},
"fileAssociations": [
{
"name": "epub",
"ext": ["epub"],
"description": "EPUB file",
"mimeType": "application/epub+zip",
"role": "Viewer"
},
{
"name": "mobi",
"ext": ["mobi"],
"description": "MOBI file",
"mimeType": "application/x-mobipocket-ebook",
"role": "Viewer"
},
{
"name": "azw",
"ext": ["azw"],
"description": "AZW file",
"mimeType": "application/vnd.amazon.ebook",
"role": "Viewer"
},
{
"name": "azw3",
"ext": ["azw3"],
"description": "AZW3 file",
"mimeType": "application/vnd.amazon.mobi8-ebook",
"role": "Viewer"
},
{
"name": "fb2",
"ext": ["fb2"],
"description": "FB2 file",
"mimeType": "application/x-fictionbook+xml",
"role": "Viewer"
},
{
"name": "cbz",
"ext": ["cbz"],
"description": "CBZ file",
"mimeType": "application/vnd.comicbook+zip",
"role": "Viewer"
},
{
"name": "pdf",
"ext": ["pdf"],
"description": "PDF file",
"mimeType": "application/pdf",
"role": "Viewer"
}
],
"createUpdaterArtifacts": true
},
"plugins": {
"fs": {
"requireLiteralLeadingDot": false
},
"cli": {
"description": "Readest CLI",
"args": [
{
"name": "file1",
"index": 1,
"takesValue": true
},
{
"name": "file2",
"index": 2,
"takesValue": true
},
{
"name": "file3",
"index": 3,
"takesValue": true
},
{
"name": "file4",
"index": 4,
"takesValue": true
}
]
},
"deep-link": {
"mobile": [
{ "scheme": ["https"], "host": "web.readest.com", "appLink": true },
{ "scheme": ["readest"], "appLink": false }
],
"desktop": {
"schemes": ["readest"]
}
},
"updater": {
"pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IEJFMEQ1QjE2OEU1NEIzNTEKUldSUnMxU09GbHNOdmpEaWFMT1crRFpEV2VORzQ2MklxaFc0M1R0ci9xY2c1bENXS0xhM1R1L2sK",
"endpoints": [
"https://download.readest.com/releases/latest.json",
"https://github.com/readest/readest/releases/latest/download/latest.json"
]
},
"webview-upgrade": {
"minUpgradeMajor": 121,
"minSupportedMajor": 92
}
}
}