UNPKG

t-comm

Version:

专业、稳定、纯粹的工具库

363 lines (360 loc) 15.1 kB
import { _ as __assign } from '../tslib.es6-096fffdd.js'; import { initEnv } from '../env/env.mjs'; import { loader } from '../loader/little-loader.mjs'; import { merge as _merge } from '../lodash-mini/merge.mjs'; import { closeWebView } from '../msdk/msdk.mjs'; import '@babel/runtime/helpers/typeof'; // const closeWebView = () => console.log('closeWebView'); // type ILaunchAppParams = any; // type IEnv = any; /** * @description 通过 location.href 来拉起 * @param {String} scheme 必须,协议 * @ignore */ function launchByHref(scheme) { if (!scheme) return; var win = window !== top && top ? top : window; win.location.href = scheme; } /** * @description 通过可见性来判断是否唤起成功 * @param {Object} params * @param {Function} params.successCallback 可选,唤起成功回调 * @param {Function} params.failCallback 可选,唤起失败回调 * @param {int} params.delay 可选,延迟多少时间后,判断是否拉起成功 * @ignore */ function checkLaunchResultByVisibility(_a) { var successCallback = _a.successCallback, failCallback = _a.failCallback, _b = _a.delay, delay = _b === void 0 ? 3500 : _b; var hasCallback = false; var hiddenProperty = 'hidden'; // visibilityChangeEvent if ('hidden' in document) { hiddenProperty = 'hidden'; } else if ('webkitHidden' in document) { hiddenProperty = 'webkitHidden'; } else if ('mozHidden' in document) { hiddenProperty = 'mozHidden'; } var visibilityChangeEvent = hiddenProperty.replace(/hidden/i, 'visibilitychange'); // eventHandler var onVisibilityChange = function onVisibilityChange() { if (document[hiddenProperty]) { hasCallback = true; successCallback === null || successCallback === void 0 ? void 0 : successCallback(); } }; document.removeEventListener(visibilityChangeEvent, onVisibilityChange); document.addEventListener(visibilityChangeEvent, onVisibilityChange); setTimeout(function () { if (!hasCallback) { failCallback === null || failCallback === void 0 ? void 0 : failCallback(); } document.removeEventListener(visibilityChangeEvent, onVisibilityChange); }, delay); } /** * @description 通过定时器来判断是否唤起成功,适用于安卓 * @param {Object} params * @param {Function} params.successCallback 可选,唤起成功回调 * @param {Function} params.failCallback 可选,唤起失败回调 * @ignore */ function checkLaunchResultByTimer(_a) { var successCallback = _a.successCallback, failCallback = _a.failCallback, _b = _a.maxTime, maxTime = _b === void 0 ? 3000 : _b; var startTime = Date.now(); // document.hidden 兼容性 var hiddenProperty = 'hidden'; if ('hidden' in document) { hiddenProperty = 'hidden'; } else if ('webkitHidden' in document) { hiddenProperty = 'webkitHidden'; } else if ('mozHidden' in document) { hiddenProperty = 'mozHidden'; } // 检查定时器是否准确,若拉起 App,页面运行在后台会导致 setInterval 不准 // 对于 Android 来说,setTimeout 不受影响,所以选 setInterval function check(elsTime) { if (elsTime > maxTime || document[hiddenProperty]) { successCallback === null || successCallback === void 0 ? void 0 : successCallback(); } else { failCallback === null || failCallback === void 0 ? void 0 : failCallback(); } } // 启动间隔20ms运行的定时器,并检测累计消耗时间是否超过3000ms,超过则结束 var count = 0; var interval = setInterval(function () { count += 1; var endTime = Date.now(); var duration = endTime - startTime; if (count >= 100 || duration > maxTime) { clearInterval(interval); check(duration); } }, 20); } /** * @description 在微信内,需要通过微信 JSSDK API 来唤起 * @param {Object} params * @param {String} params.appid 必填,供iOS使用 * @param {String} params.weixinScheme 必填,scheme://parameter 通过系统接口拉起第三方app。中文或特殊字符需要encode * @param {Function} params.successCallback 可选,唤起成功回调 * @param {Function} params.failCallback 可选,唤起失败回调 * @ignore */ function launchInWeiXin(_a) { var appid = _a.appid, weixinScheme = _a.weixinScheme, successCallback = _a.successCallback, failCallback = _a.failCallback; var sdkUrl = 'https://image-1251917893.file.myqcloud.com/commjs/jweixin-1.6.0.js'; var invokeParams = { schemeUrl: weixinScheme, appID: appid }; var afterInvoke = function afterInvoke(res) { var _a; console.log('[launchInWeiXin] result', { res: res }); var isSuccess = ((_a = res === null || res === void 0 ? void 0 : res.err_msg) === null || _a === void 0 ? void 0 : _a.indexOf('ok')) !== -1; if (isSuccess) { successCallback === null || successCallback === void 0 ? void 0 : successCallback(); } else { failCallback === null || failCallback === void 0 ? void 0 : failCallback(); } }; var onBridgeReady = function onBridgeReady() { console.log('onBridgeReady...'); loader(sdkUrl, function () { var _a; console.log('[onBridgeReady]'); (_a = window.WeixinJSBridge) === null || _a === void 0 ? void 0 : _a.invoke('launchApplication', invokeParams, afterInvoke); }); }; // WeixinJSBridge 接口加载后再 invoke if (typeof window.WeixinJSBridge === 'undefined') { console.log('WeixinJSBridge undefined'); if (document.addEventListener) { document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false); } else if (document.attachEvent) { document.attachEvent('WeixinJSBridgeReady', onBridgeReady); document.attachEvent('onWeixinJSBridgeReady', onBridgeReady); } } else { console.log('WeixinJSBridge not undefined'); onBridgeReady(); } } /** * @description 在手Q内,调用手Q JSSDK API 唤起 * @param {Object} params * @param {Object} params.env 必须,环境信息,内部自动传递 * @param {String} params.qqAppScheme 必填,仅供 iOS 使用,scheme://parameter 通过系统接口拉起第三方app。中文或特殊字符需要encode * @param {String} params.qqAppPackageName 必填,仅供 Android 使用,安装包包名 * @param {Function} params.successCallback 可选,唤起成功回调 * @param {Function} params.failCallback 可选,唤起失败回调 * @ignore */ function launchInMobileQQ(_a) { var env = _a.env, isUseSchemeParams = _a.isUseSchemeParams, qqAppScheme = _a.qqAppScheme, qqAppPackageName = _a.qqAppPackageName, successCallback = _a.successCallback, failCallback = _a.failCallback; // 在手Q下,通过 visibility 事件判断是否成功拉起 var check = function check() { checkLaunchResultByVisibility({ successCallback: successCallback, failCallback: failCallback }); }; // API不支持传参,所以如果 scheme 包含参数,直接拉起 if (isUseSchemeParams) { launchByHref(qqAppScheme); check(); // 判断是否拉起 // 无参数,通过 API 拉起 } else { loader('https://pub.idqqimg.com/qqmobile/qqapi.js?_bid=152', function () { var scheme = env.isIos ? qqAppScheme : qqAppPackageName; window.mqq.app.launchApp(scheme); check(); // 判断是否拉起 }); } } /** * @description 在 iOS 原生浏览器内,直接拉起 * @param {Object} params * @param {Object} params.env 必须,环境信息,内部自动传递 * @param {String} params.browserAppScheme 必填,scheme://parameter 通过系统接口拉起第三方app。中文或特殊字符需要encode * @param {Function} params.successCallback 可选,唤起成功回调 * @param {Function} params.failCallback 可选,唤起失败回调 * @ignore */ function launchInIOSBrowser(_a) { var browserAppScheme = _a.browserAppScheme, successCallback = _a.successCallback, failCallback = _a.failCallback; launchByHref(browserAppScheme); // 检查唤起结果 checkLaunchResultByVisibility({ successCallback: successCallback, failCallback: failCallback }); } /** * @description 在 Android 原生浏览器内,直接使用原生支持的 Universal Links 形式,但通过 iframe 形式唤起 * @param {Object} params * @param {String} params.env 必须,环境信息,内部自动传递 * @param {String} params.browserApkScheme 必填,scheme://parameter 通过系统接口拉起第三方app。中文或特殊字符需要encode * @param {Function} params.successCallback 可选,唤起成功回调 * @param {Function} params.failCallback 可选,唤起失败回调 * @ignore */ function launchInAndroidBrowser(_a) { var browserApkScheme = _a.browserApkScheme, successCallback = _a.successCallback, failCallback = _a.failCallback; // 通过 iframe 唤起 var div = document.createElement('div'); div.style.visibility = 'hidden'; div.innerHTML = "<iframe id=\"scheme\" src=\"".concat(browserApkScheme, "\" scrolling=\"no\" width=\"1\" height=\"1\"></iframe>"); document.body.appendChild(div); // 通过定时器是否延时来检查是否成功唤起 checkLaunchResultByTimer({ successCallback: successCallback, failCallback: failCallback }); } /** * @description 兼容微信、手Q、手机原生浏览器、游戏内环境的唤起第三方 APP 方法。用于替代 launch 方法,优化传参以及底层实现。 * @param {Object} args 必须,参数对象 * @param {String} args.appid 必须,用于微信内拉起,微信开放平台的 appID,向游戏公众号管理者索取。 * @param {String} args.weixinScheme 必须,用于微信内拉起,目标 App 的 URL Scheme * @param {String} args.browserAppScheme 必须,用于 iOS 原生浏览器拉起,目标 App 的 URL Scheme * @param {String} args.browserApkScheme 必须,用于 Android 原生浏览器拉起,目标 App 的 URL Scheme * @param {String} args.qqAppScheme 必须,用于 iOS + 手 Q 内拉起,目标 App 的 URL Scheme * @param {String} args.qqAppPackageName 必须,用于 Android + 手 Q 内拉起,目标 App 的安卓包名,例如 com.tencent.tmgp.sgame * @param {Boolean} args.isUseSchemeParams 可选,默认 false,scheme 是否携带参数,用于手Q内判断切换拉起方式 * @param {Boolean} args.openMarket 可选,默认 false,若跳转失败,拉起应用下载地址 * @param {String} args.appMarketUrl 可选,默认空,Appstore 下载地址,例如 https://itunes.apple.com/cn/app/id989673964 * @param {String} args.apkMarketUrl 可选,默认空,安卓应用下载地址,例如 market://details?id=com.tencent.tmgp.sgame * @param {Boolean} args.needRedirect 可选,默认 false,若不跳转下载,是否跳转其他地址 * @param {String} args.redirectUrl 可选,默认空,跳转其他地址,例如某官网地址 * @param {String} args.failTips 可选,默认空,若不跳转下载 or 其他地址,而是开启拉起失败提示,该处填写提示内容 * @param {Function} args.successCallback 可选,默认空,拉起成功回调 * @param {Function} args.failCallback 可选,默认空,拉起失败回调 */ function launchApp(args) { var _a; if (args === void 0) { args = {}; } (_a = args === null || args === void 0 ? void 0 : args.Toast) === null || _a === void 0 ? void 0 : _a.showLoading('启动中...'); var env = initEnv(); var baseParams = { isUseSchemeParams: false, // 微信内拉起 appid: '', weixinScheme: '', // 网页内拉起 browserAppScheme: '', browserApkScheme: '', // 手Q内拉起 qqAppScheme: '', qqAppPackageName: '', // 唤起失败处理开启优先级:错误回调 > 跳转下载 > 跳转链接 > 弹窗提示 // 如果跳转失败,拉起下载 openMarket: false, appMarketUrl: '', apkMarketUrl: '', // 如果不拉起下载,选择跳转 needRedirect: false, redirectUrl: '', // 不拉起下载 or 跳转,通过提示 failTips: '', // 错误回调 failCallback: null, // 成功回调 successCallback: null }; // 合并默认参数 var params = _merge({}, baseParams, __assign({ env: env }, args)); console.log('[params]', params); console.log('[env]', env); // 二次封装失败、成功回调 var customFailCallback = params.failCallback; var customSuccCallback = params.successCallback; var onSuccHandler = function onSuccHandler() { var _a; (_a = args === null || args === void 0 ? void 0 : args.Toast) === null || _a === void 0 ? void 0 : _a.dismissLoading(); console.log('[launchApp] onSuccHandler'); customSuccCallback === null || customSuccCallback === void 0 ? void 0 : customSuccCallback(); }; // 错误处理:错误回调 > 跳转下载 > 跳转链接 > 弹窗提示 var onFailHandler = function onFailHandler() { var _a, _b, _c; console.log('[launchApp] onFailHandler'); (_a = args === null || args === void 0 ? void 0 : args.Toast) === null || _a === void 0 ? void 0 : _a.dismissLoading(); if (customFailCallback) { customFailCallback(); } else if (params.openMarket) { if (env.isIOS) { params.appMarketUrl && (window.location.href = params.appMarketUrl); } else { params.apkMarketUrl && (window.location.href = params.apkMarketUrl); } if (env.isWeixin && !env.isMiniProgram) { checkLaunchResultByVisibility({ successCallback: function successCallback() {}, failCallback: function failCallback() { var _a, _b; if (params.failTips) { (_b = (_a = args.Dialog) === null || _a === void 0 ? void 0 : _a.showTipsDialog) === null || _b === void 0 ? void 0 : _b.call(_a, params.failTips); } }, delay: 2000 }); } } else if (params.needRedirect) { params.redirectUrl && (window.location.href = params.redirectUrl); } else if (params.failTips !== '') { (_c = (_b = args.Dialog) === null || _b === void 0 ? void 0 : _b.showTipsDialog) === null || _c === void 0 ? void 0 : _c.call(_b, params.failTips); } }; params.failCallback = onFailHandler; params.successCallback = onSuccHandler; // 在游戏内 if (env.isInGame) { closeWebView(); // 关闭当前页面 // 在微信内 } else if (env.isWeixin && !env.isMiniProgram) { launchInWeiXin(params); // 在微信小程序内 } else if (env.isWeixin && env.isMiniProgram) { onFailHandler(); // 在手Q、QQ浏览器内 } else if (env.isQQ) { launchInMobileQQ(params); // 原生浏览器 or 其他 } else { // android if (env.isAndroid) { launchInAndroidBrowser(params); // iOS } else { launchInIOSBrowser(params); } } } export { launchApp };