import { getNativeBridgeWindow, hasFlutterBridge } from './environment' import { mobileUtil } from './mobileUtil' /** 原生文件选择桥接名(按优先级) */ const NATIVE_FILE_PICKER_BRIDGES = [ 'pickFile', 'chooseFile', 'filePicker', 'selectFile', 'openFilePicker', 'fileAlbum', 'documentPicker', 'chooseDocument', ] export interface NativePickedFile { name?: string size?: number | string filePath?: string path?: string content?: string } export function getNativeFilePickerBridge(): string | null { for (const name of NATIVE_FILE_PICKER_BRIDGES) { if (hasFlutterBridge(name)) return name } return null } export function hasNativeFilePicker(): boolean { return !!getNativeFilePickerBridge() } function normalizePickedFiles(data: any): NativePickedFile[] { if (!data) return [] if (Array.isArray(data.files)) return data.files if (Array.isArray(data)) return data return [data] } /** * App 内打开系统文件选择器(需 Flutter 侧实现对应桥接)。 * 返回 true 表示已发起原生调用。 */ export function openNativeFilePicker( options: { accept?: string multiple?: boolean onSuccess: (files: NativePickedFile[]) => void onError?: (message?: string) => void }, ): boolean { const bridgeName = getNativeFilePickerBridge() if (!bridgeName) return false mobileUtil.execute({ funcName: bridgeName, param: { accept: options.accept || '*/*', multiple: options.multiple ?? true, }, callbackFunc: (result: any) => { if (result?.status === 'success') { const files = normalizePickedFiles(result.data) if (files.length > 0) options.onSuccess(files) else options.onError?.('未选择文件') return } if (result?.data?.status === 'cancelled') return options.onError?.(result?.message || result?.msg || '文件选择失败') }, }) return true } /** 同步触发浏览器 file input(须在用户点击事件的同一调用栈内) */ export function triggerBrowserFileInput(input: HTMLInputElement | undefined | null): boolean { if (!input) return false input.value = '' input.click() return true } /** 调试:列出当前 window 上已注入的桥接名 */ export function listNativeBridges(): string[] { const win = getNativeBridgeWindow() return Object.keys(win).filter(key => typeof win[key]?.postMessage === 'function') }