/** * APP桥接工具函数 * 用于H5页面与原生APP之间的通信 */ import { COMMON_HEADERS } from '@/utils/http.js' /** * 检测是否为iOS系统 * @returns {boolean} */ export function ios() { return /iPad|iPhone|iPod/.test(navigator.userAgent) } /** * 检测是否为Android系统 * @returns {boolean} */ export function android() { return /Android/.test(navigator.userAgent) } /** * 检测是否在APP环境中 * @returns {boolean} */ export function isInApp() { return !!(window.app || window.webkit || window.FlutterPageControl) } /** * 关闭当前页面(返回到Flutter上一页) */ export function closePage() { try { if (window.app && window.app.closePage) { // 使用注入的方法 window.app.closePage() } else if (window.FlutterPageControl) { // 直接使用Flutter通道 window.FlutterPageControl.postMessage('close_page') } else { // 降级处理:浏览器环境 // if (window.history.length > 1) { // window.history.back() // } else { // window.close() // } } } catch (error) { console.error('关闭页面失败:', error) // 降级处理 window.history.back() } } /** * 前往私聊 */ export function gotoPrivateChat(userId) { if (!userId) return try { console.log(`userId:${userId}`) if (window.app && window.app.gotoPrivateChat) { console.log('使用gotoPrivateChat') // 使用注入的方法 window.app.gotoPrivateChat(userId) } else if (window.FlutterPageControl) { // 直接使用Flutter通道 window.FlutterPageControl.postMessage(`private_chat:${userId}`) } } catch (error) { console.error('前往私聊失败:', error) } } /** * 查看个人页面 */ export function viewUserInfo(userId) { if (!userId) return try { console.log(`userId:${userId}`) if (window.app && window.app.viewUserInfo) { console.log('使用viewUserInfo') // 使用注入的方法 window.app.viewUserInfo(userId) } else if (window.FlutterPageControl) { // 直接使用Flutter通道 window.FlutterPageControl.postMessage(`view_user_info:${userId}`) } } catch (error) { console.error('查看个人页面失败:', error) } } /** * 前往房间 */ export function gotoRoom(roomId) { if (!roomId) return try { console.log(`roomId:${roomId}`) if (window.app && window.app.gotoRoom) { console.log('使用gotoRoom') // 使用注入的方法 window.app.gotoRoom(roomId) } else if (window.FlutterPageControl) { // 直接使用Flutter通道 window.FlutterPageControl.postMessage(`go_to_room:${roomId}`) } } catch (error) { console.error('前往房间失败:', error) } } /** * 前往app页面 */ export function gotoAppPage(pageName) { if (!pageName) return try { console.log(`pageName:${pageName}`) // 直接使用Flutter通道 window.FlutterPageControl.postMessage(pageName) } catch (error) { console.error('前往APP页面失败:', error) } } /** * 退出APP */ export function exitApp() { try { if (window.app && window.app.exitApp) { window.app.exitApp() } else if (window.FlutterPageControl) { window.FlutterPageControl.postMessage('exit_app') } } catch (error) { console.error('退出APP失败:', error) } } /** * 处理返回按钮逻辑 * @param {boolean} isHomePage 是否为首页 */ export function handleBackButton(isHomePage = false) { if (isHomePage) { // 首页返回:关闭页面 closePage() } else { // 非首页:正常返回 window.history.back() } } /** * 连接APP并获取访问参数 * @param {Function} renderFun 回调函数,接收APP传递的access参数 */ export function connectApplication(renderFun) { window.renderData = renderFun // 兼容历史版本 window.getIosAccessOriginParam = renderFun try { if (android()) { console.debug('Flutter Android WebView 检测') console.debug('window.app 对象:', window.app) // 检查Flutter注入的接口 if (window.app) { console.debug('window.app 的所有方法:') console.debug(Object.keys(window.app)) // 检查具体的方法 console.debug('getAccessOrigin 方法存在?', typeof window.app.getAccessOrigin) console.debug('getAccessOrigin 是函数?', typeof window.app.getAccessOrigin === 'function') } // 等待Flutter注入完成 const waitForFlutterInterface = () => { let attempts = 0 const maxAttempts = 50 // 最多等待5秒 const checkInterface = () => { attempts++ console.debug(`尝试第 ${attempts} 次检查Flutter接口...`) if ( window.app && window.app.getAccessOrigin && typeof window.app.getAccessOrigin === 'function' ) { console.debug('Flutter接口检测成功,调用 getAccessOrigin') try { const result = window.app.getAccessOrigin() console.debug('getAccessOrigin 返回结果:', result) renderFun(result) } catch (error) { console.error('调用 getAccessOrigin 出错:', error) } } else if (attempts < maxAttempts) { // 继续等待 setTimeout(checkInterface, 100) } else { console.error('Flutter接口注入超时,使用默认数据') // 使用默认的开发数据 const mockAccess = JSON.stringify({ Authorization: 'Bearer FLUTTER_MOCK_TOKEN', 'Req-Lang': 'en', 'Req-App-Intel': 'build=1.0;version=2.1;channel=flutter;Req-Imei=flutter-device', 'Req-Sys-Origin': 'origin=LIKEI;originChild=LIKEI', }) renderFun(mockAccess) } } checkInterface() } // 如果window.app已存在,直接检查,否则等待 if (window.app) { waitForFlutterInterface() } else { console.debug('等待Flutter注入window.app...') // 监听window.app的创建 let checkCount = 0 const checkApp = () => { checkCount++ if (window.app) { console.debug('检测到window.app,开始连接') waitForFlutterInterface() } else if (checkCount < 50) { setTimeout(checkApp, 100) } else { console.error('等待window.app超时') // 手动通知Flutter注入接口 if (window.FlutterApp && window.FlutterApp.postMessage) { window.FlutterApp.postMessage('requestAccessOrigin') } } } checkApp() } } else { /*else if (ios()) { console.debug('ios access detected') // iOS可能需要特殊处理,这里先使用通用方法 if (window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.getAccessOrigin) { window.webkit.messageHandlers.getAccessOrigin.postMessage({}) } else if (window.app && window.app.getAccessOrigin) { renderFun(window.app.getAccessOrigin()) } }*/ console.debug('非移动设备环境') // 非APP环境,可能是浏览器调试 console.warn('Not in APP environment, using mock data for development') // 开发环境可以提供模拟数据 if (process.env.NODE_ENV === 'development') { const mockAccess = JSON.stringify({ Authorization: COMMON_HEADERS.authorization, 'Req-Lang': COMMON_HEADERS['req-lang'], 'Req-App-Intel': COMMON_HEADERS['req-app-intel'], 'Req-Sys-Origin': COMMON_HEADERS['req-sys-origin'], }) setTimeout(() => renderFun(mockAccess), 100) } } } catch (error) { console.error('Failed to connect to APP:', error) } } /** * 解析APP传递的访问参数 * @param {string} access JSON字符串格式的访问参数 * @returns {Object} 解析后的参数对象 */ export function parseAccessOrigin(access) { try { const accessParam = JSON.parse(access) return { success: true, data: accessParam, } } catch (error) { console.error('Failed to parse access origin:', error) return { success: false, error: 'accessOrigin Error.', data: null, } } } /** * 解析请求头信息 * @param {Object} head 请求头对象 * @returns {Object} 解析后的头信息 */ export function parseHeader(head) { if (!head) { return {} } /** * 解析键值对字符串 (如: "key1=value1;key2=value2") * @param {string} values * @returns {Object} */ function getKeyValObj(values) { const keyValBody = {} if (!values) return keyValBody const valueArray = values.split(';') for (let index = 0; index < valueArray.length; index++) { const keyVal = valueArray[index] if (keyVal && keyVal.includes('=')) { const keyValArray = keyVal.split('=') keyValBody[keyValArray[0]] = keyValArray[1] } } return keyValBody } const reqAppIntel = head['Req-App-Intel'] || '' const reqSysOrigin = head['Req-Sys-Origin'] || '' const reqAppIntelObj = getKeyValObj(reqAppIntel) const reqSysOriginObj = getKeyValObj(reqSysOrigin) return { reqLang: head['Req-Lang'], authorization: head['Authorization'], buildVersion: reqAppIntelObj['build'], appVersion: reqAppIntelObj['version'], appChannel: reqAppIntelObj['channel'], reqImei: reqAppIntelObj['Req-Imei'], sysOrigin: reqSysOriginObj['origin'], sysOriginChild: reqSysOriginObj['child'], } } /** * 设置HTTP请求的默认头部信息 * @param {Object} headerInfo 解析后的头部信息 */ export async function setHttpHeaders(headerInfo) { try { const httpModule = await import('../utils/http.js') if (httpModule.setHeadersFromApp) { httpModule.setHeadersFromApp(headerInfo) } } catch (error) { console.error('Failed to update HTTP headers:', error) } console.debug('🔑 Authorization token set:', headerInfo.authorization) console.debug('🌍 Language set:', headerInfo.reqLang) console.debug('📱 App info:', { version: headerInfo.appVersion, build: headerInfo.buildVersion, channel: headerInfo.appChannel, system: headerInfo.sysOrigin, }) }