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>
这个提交包含在:
父节点
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) => {
|
||||
|
||||
正在加载...
在新工单中引用
屏蔽一个用户