fix(xwebview): 将 react-native-blob-util 改为懒加载以兼容 RN 0.85 Bridgeless 模式

静态 import 会在模块评估时触发 fs.js:14 调用 ReactNativeBlobUtil.getConstants(),
在 Bridgeless 模式下 TurboModule 未注册时返回 null 导致崩溃。
改为在函数体内 require() 延迟至实际下载时才初始化。

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
这个提交包含在:
XuqmGroup 2026-06-21 09:23:17 +08:00
父节点 ff8f34e5a4
当前提交 51e016e185

查看文件

@ -1,5 +1,4 @@
import { Platform } from 'react-native'
import RNFetchBlob from 'react-native-blob-util'
import type {
XWebViewDownloadDecision,
@ -8,6 +7,11 @@ import type {
XWebViewDownloadResult,
} from '@xuqm/rn-common'
// Lazy import: react-native-blob-util calls getConstants() at module evaluation time,
// which crashes in RN 0.85 Bridgeless mode. Defer the require until actual download use.
// eslint-disable-next-line @typescript-eslint/no-require-imports
const getRNFetchBlob = () => (require('react-native-blob-util') as { default: typeof import('react-native-blob-util').default }).default
function parseContentDispositionFilename(header: string): string | null {
const rfc5987 = header.match(/filename\*=(?:[^']*'[^']*')?([^;\s]+)/i)
if (rfc5987?.[1]) {
@ -70,7 +74,7 @@ async function resolveFilePath(
const full = `${dir}/${filename}`
if (conflict === 'overwrite') return full
const exists = await RNFetchBlob.fs.exists(full)
const exists = await getRNFetchBlob().fs.exists(full)
if (!exists) return full
const dot = filename.lastIndexOf('.')
@ -82,7 +86,7 @@ async function resolveFilePath(
do {
candidate = `${dir}/${base}(${n})${ext}`
n++
} while (await RNFetchBlob.fs.exists(candidate))
} while (await getRNFetchBlob().fs.exists(candidate))
return candidate
}
@ -93,14 +97,14 @@ export async function saveBase64File(
savePath: string | undefined,
conflict: 'rename' | 'overwrite',
): Promise<string> {
const { dirs } = RNFetchBlob.fs
const { dirs } = getRNFetchBlob().fs
const dir =
savePath ??
(Platform.OS === 'android'
? (dirs.DownloadDir ?? dirs.DocumentDir)
: dirs.DocumentDir)
const filePath = await resolveFilePath(dir, filename, conflict)
await RNFetchBlob.fs.writeFile(filePath, base64, 'base64')
await getRNFetchBlob().fs.writeFile(filePath, base64, 'base64')
return filePath
}
@ -176,7 +180,7 @@ export function startDownload(
onComplete: (r: XWebViewDownloadResult) => void,
onError: (error: string) => void,
): DownloadHandle {
const { dirs } = RNFetchBlob.fs
const { dirs } = getRNFetchBlob().fs
const dir =
savePath ??
(Platform.OS === 'android'
@ -192,7 +196,7 @@ export function startDownload(
.then(filePath => {
if (cancelled) return
const task = RNFetchBlob.config({ path: filePath }).fetch('GET', url)
const task = getRNFetchBlob().config({ path: filePath }).fetch('GET', url)
cancelFn = () => task.cancel()
task.progress({ interval: 300 }, (received: number, total: number) => {