UNPKG

@tarojs/taro-h5

Version:
1,314 lines (1,277 loc) 274 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var Taro = require('@tarojs/api'); var router$1 = require('@tarojs/router'); var shared = require('@tarojs/shared'); var runtime = require('@tarojs/runtime'); var base64Js = require('base64-js'); var tslib = require('tslib'); var platform = require('platform'); var isNil = require('lodash-es/isNil'); var queryString = require('query-string'); var throttle = require('lodash-es/throttle'); var ics = require('ics'); var components = require('@tarojs/components/dist/components'); var isMobile = require('is-mobile'); require('whatwg-fetch'); require('abortcontroller-polyfill/dist/abortcontroller-polyfill-only'); var jsonpRetry = require('jsonp-retry'); function _interopNamespaceDefault(e) { var n = Object.create(null); if (e) { Object.keys(e).forEach(function (k) { if (k !== 'default') { var d = Object.getOwnPropertyDescriptor(e, k); Object.defineProperty(n, k, d.get ? d : { enumerable: true, get: function () { return e[k]; } }); } }); } n.default = e; return Object.freeze(n); } var ics__namespace = /*#__PURE__*/_interopNamespaceDefault(ics); class MethodHandler { constructor({ name, success, fail, complete }) { this.isHandlerError = false; this.methodName = name; this.__success = success; this.__fail = fail; this.__complete = complete; this.isHandlerError = shared.isFunction(this.__complete) || shared.isFunction(this.__fail); } success(res = {}, promise = {}) { if (!res.errMsg) { res.errMsg = `${this.methodName}:ok`; } shared.isFunction(this.__success) && this.__success(res); shared.isFunction(this.__complete) && this.__complete(res); const { resolve = Promise.resolve.bind(Promise) } = promise; return resolve(res); } fail(res = {}, promise = {}) { if (!res.errMsg) { res.errMsg = `${this.methodName}:fail`; } else { res.errMsg = `${this.methodName}:fail ${res.errMsg}`; } shared.isFunction(this.__fail) && this.__fail(res); shared.isFunction(this.__complete) && this.__complete(res); const { resolve = Promise.resolve.bind(Promise), reject = Promise.reject.bind(Promise) } = promise; return this.isHandlerError ? resolve(res) : reject(res); } } class CallbackManager { constructor() { this.callbacks = []; /** 添加回调 */ this.add = (opt) => { if (opt) this.callbacks.push(opt); }; /** 移除回调 */ this.remove = (opt) => { if (opt) { let pos = -1; this.callbacks.forEach((callback, k) => { if (callback === opt) { pos = k; } }); if (pos > -1) { this.callbacks.splice(pos, 1); } } else { // Note: 参数为空,则取消所有的事件监听 this.callbacks = []; } }; /** 获取回调函数数量 */ this.count = () => { return this.callbacks.length; }; /** 触发回调 */ this.trigger = (...args) => { this.callbacks.forEach(opt => { if (shared.isFunction(opt)) { opt(...args); } else { const { callback, ctx } = opt; shared.isFunction(callback) && callback.call(ctx, ...args); } }); }; /** 清空所有回调 */ this.clear = () => { this.callbacks = []; }; } } /** * ease-in-out的函数 * @param t 0-1的数字 */ const easeInOut = (t) => (t < 0.5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1); const getTimingFunc = (easeFunc, frameCnt) => { return x => { if (frameCnt <= 1) { return easeFunc(1); } const t = x / (frameCnt - 1); return easeFunc(t); }; }; function createDownload(url = '', download = '') { const link = document.createElement('a'); link.style.display = 'none'; link.href = url; link.download = download; // Note: 需要注意,该方案不能监听用户取消或禁止下载等操作,亦不能获取下载成功或失败状态 link.click(); } const VALID_COLOR_REG = /^#[0-9a-fA-F]{6}$/; const isValidColor = (color) => { return VALID_COLOR_REG.test(color); }; /* eslint-disable prefer-promise-reject-errors */ function shouldBeObject(target) { if (target && typeof target === 'object') return { flag: true }; return { flag: false, msg: getParameterError({ correct: 'Object', wrong: target }) }; } function findDOM(inst) { if (inst && runtime.hooks.isExist('getDOMNode')) { return runtime.hooks.call('getDOMNode', inst); } const page = runtime.Current.page; const path = page === null || page === void 0 ? void 0 : page.path; const msg = '没有找到已经加载了的页面,请在页面加载完成后使用此 API。'; if (path == null) { throw new Error(msg); } const el = document.getElementById(path); if (el == null) { throw new Error('在已加载页面中没有找到对应的容器元素。'); } return el; } function getParameterError({ name = '', para, correct, wrong, level = 'error' }) { const parameter = para ? `parameter.${para}` : 'parameter'; const errorType = upperCaseFirstLetter(wrong === null ? 'Null' : typeof wrong); return `${name ? `${name}:fail ` : ''}parameter ${level}: ${parameter} should be ${correct} instead of ${errorType}`; } function upperCaseFirstLetter(string) { if (typeof string !== 'string') return string; string = string.replace(/^./, match => match.toUpperCase()); return string; } function inlineStyle(style) { let res = ''; for (const attr in style) res += `${attr}: ${style[attr]};`; if (res.indexOf('display: flex;') >= 0) res += 'display: -webkit-box;display: -webkit-flex;'; res = res.replace(/transform:(.+?);/g, (s, $1) => `${s}-webkit-transform:${$1};`); res = res.replace(/flex-direction:(.+?);/g, (s, $1) => `${s}-webkit-flex-direction:${$1};`); return res; } function setTransform(el, val) { el.style.webkitTransform = val; el.style.transform = val; } function serializeParams(params) { if (!params) { return ''; } return Object.keys(params) .map(key => (`${encodeURIComponent(key)}=${typeof (params[key]) === 'object' ? encodeURIComponent(JSON.stringify(params[key])) : encodeURIComponent(params[key])}`)) .join('&'); } function temporarilyNotSupport(name = '') { return (option = {}, ...args) => { const { success, fail, complete } = option; const handle = new MethodHandler({ name, success, fail, complete }); const errMsg = '暂时不支持 API'; Taro.eventCenter.trigger('__taroNotSupport', { name, args: [option, ...args], type: 'method', category: 'temporarily', }); if (process.env.NODE_ENV === 'production') { console.warn(errMsg); return handle.success({ errMsg }); } else { return handle.fail({ errMsg }); } }; } function weixinCorpSupport(name) { return (option = {}, ...args) => { const { success, fail, complete } = option; const handle = new MethodHandler({ name, success, fail, complete }); const errMsg = 'h5 端当前仅在微信公众号 JS-SDK 环境下支持此 API'; Taro.eventCenter.trigger('__taroNotSupport', { name, args: [option, ...args], type: 'method', category: 'weixin_corp', }); if (process.env.NODE_ENV === 'production') { console.warn(errMsg); return handle.success({ errMsg }); } else { return handle.fail({ errMsg }); } }; } function permanentlyNotSupport(name = '') { return (option = {}, ...args) => { const { success, fail, complete } = option; const handle = new MethodHandler({ name, success, fail, complete }); const errMsg = '不支持 API'; Taro.eventCenter.trigger('__taroNotSupport', { name, args: [option, ...args], type: 'method', category: 'permanently', }); if (process.env.NODE_ENV === 'production') { console.warn(errMsg); return handle.success({ errMsg }); } else { return handle.fail({ errMsg }); } }; } function processOpenApi({ name, defaultOptions, standardMethod, formatOptions = options => options, formatResult = res => res }) { const notSupported = weixinCorpSupport(name); return (options = {}, ...args) => { var _a; // @ts-ignore const targetApi = (_a = window === null || window === void 0 ? void 0 : window.wx) === null || _a === void 0 ? void 0 : _a[name]; const opts = formatOptions(Object.assign({}, defaultOptions, options)); if (shared.isFunction(targetApi)) { return new Promise((resolve, reject) => { ['fail', 'success', 'complete'].forEach(k => { opts[k] = preRef => { const res = formatResult(preRef); options[k] && options[k](res); if (k === 'success') { resolve(res); } else if (k === 'fail') { reject(res); } }; return targetApi(opts); }); }); } else if (shared.isFunction(standardMethod)) { return standardMethod(opts); } else { return notSupported(options, ...args); } }; } /** * 获取当前页面路径 * @returns */ function getCurrentPath() { var _a, _b, _c, _d, _e, _f; const appConfig = window.__taroAppConfig || {}; const routePath = runtime.getCurrentPage((_a = appConfig.router) === null || _a === void 0 ? void 0 : _a.mode, (_b = appConfig.router) === null || _b === void 0 ? void 0 : _b.basename); const homePath = runtime.getHomePage((_d = (_c = appConfig.routes) === null || _c === void 0 ? void 0 : _c[0]) === null || _d === void 0 ? void 0 : _d.path, (_e = appConfig.router) === null || _e === void 0 ? void 0 : _e.basename, (_f = appConfig.router) === null || _f === void 0 ? void 0 : _f.customRoutes, appConfig.entryPagePath); /** * createPageConfig 时根据 stack 的长度来设置 stamp 以保证页面 path 的唯一,此函数是在 createPageConfig 之前调用,预先设置 stamp=1 * url 上没有指定应用的启动页面时使用 homePath */ return `${routePath === '/' ? homePath : routePath}?stamp=1`; } // 广告 const createRewardedVideoAd = /* @__PURE__ */ temporarilyNotSupport('createRewardedVideoAd'); const createInterstitialAd = /* @__PURE__ */ temporarilyNotSupport('createInterstitialAd'); // 人脸识别 const stopFaceDetect = /* @__PURE__ */ temporarilyNotSupport('stopFaceDetect'); const initFaceDetect = /* @__PURE__ */ temporarilyNotSupport('initFaceDetect'); const faceDetect = /* @__PURE__ */ temporarilyNotSupport('faceDetect'); // AI推理 const getInferenceEnvInfo = /* @__PURE__ */ temporarilyNotSupport('getInferenceEnvInfo'); const createInferenceSession = /* @__PURE__ */ temporarilyNotSupport('createInferenceSession'); // 判断支持版本 const isVKSupport = /* @__PURE__ */ temporarilyNotSupport('isVKSupport'); // 视觉算法 const createVKSession = /* @__PURE__ */ temporarilyNotSupport('createVKSession'); // AliPay const getOpenUserInfo = /* @__PURE__ */ temporarilyNotSupport('getOpenUserInfo'); const tradePay = /* @__PURE__ */ temporarilyNotSupport('tradePay'); // 加密 const getUserCryptoManager = /* @__PURE__ */ temporarilyNotSupport('getUserCryptoManager'); const setEnableDebug = /* @__PURE__ */ temporarilyNotSupport('setEnableDebug'); const getRealtimeLogManager = /* @__PURE__ */ temporarilyNotSupport('getRealtimeLogManager'); const getLogManager = /* @__PURE__ */ temporarilyNotSupport('getLogManager'); // 性能 const reportPerformance = /* @__PURE__ */ temporarilyNotSupport('reportPerformance'); const getPerformance = /* @__PURE__ */ temporarilyNotSupport('getPerformance'); const preloadWebview = /* @__PURE__ */ temporarilyNotSupport('preloadWebview'); const preloadSkylineView = /* @__PURE__ */ temporarilyNotSupport('preloadSkylineView'); const preloadAssets = /* @__PURE__ */ temporarilyNotSupport('preloadAssets'); /** 跳转系统蓝牙设置页 */ const openSystemBluetoothSetting = /* @__PURE__ */ temporarilyNotSupport('openSystemBluetoothSetting'); /** 跳转系统微信授权管理页 */ const openAppAuthorizeSetting = /* @__PURE__ */ temporarilyNotSupport('openAppAuthorizeSetting'); /** 获取窗口信息 */ const getWindowInfo = () => { const info = { /** 设备像素比 */ pixelRatio: window.devicePixelRatio, /** 屏幕宽度,单位px */ screenWidth: window.screen.width, /** 屏幕高度,单位px */ screenHeight: window.screen.height, /** 可使用窗口宽度,单位px */ windowWidth: document.documentElement.clientWidth, /** 可使用窗口高度,单位px */ windowHeight: document.documentElement.clientHeight, /** 状态栏的高度,单位px */ statusBarHeight: NaN, /** 在竖屏正方向下的安全区域 */ safeArea: { bottom: 0, height: 0, left: 0, right: 0, top: 0, width: 0 } }; return info; }; /** 获取设备设置 */ const getSystemSetting = () => { const isLandscape = window.screen.width >= window.screen.height; const info = { /** 蓝牙的系统开关 */ bluetoothEnabled: false, /** 地理位置的系统开关 */ locationEnabled: false, /** Wi-Fi 的系统开关 */ wifiEnabled: false, /** 设备方向 */ deviceOrientation: isLandscape ? 'landscape' : 'portrait' }; return info; }; /** 获取设备设置 */ const getDeviceInfo = () => { var _a, _b; const info = { /** 应用二进制接口类型(仅 Android 支持) */ abi: '', /** 设备二进制接口类型(仅 Android 支持) */ deviceAbi: '', /** 设备性能等级(仅Android小游戏)。取值为:-2 或 0(该设备无法运行小游戏),-1(性能未知),>=1(设备性能值,该值越高,设备性能越好,目前最高不到50) */ benchmarkLevel: -1, /** 设备品牌 */ brand: platform.manufacturer || 'unknown', /** 设备型号 */ model: platform.product || 'unknown', /** 操作系统及版本 */ system: ((_a = platform.os) === null || _a === void 0 ? void 0 : _a.toString()) || 'unknown', /** 客户端平台 */ platform: ((_b = platform.os) === null || _b === void 0 ? void 0 : _b.family) || 'unknown', /** 设备二进制接口类型(仅 Android 支持) */ CPUType: '', }; return info; }; /** 获取微信APP基础信息 */ const getAppBaseInfo = () => { var _a; let isDarkMode = false; if ((_a = window.matchMedia) === null || _a === void 0 ? void 0 : _a.call(window, '(prefers-color-scheme: dark)').matches) { isDarkMode = true; } const info = { /** 客户端基础库版本 */ SDKVersion: '', /** 是否已打开调试。可通过右上角菜单或 [Taro.setEnableDebug](/docs/apis/base/debug/setEnableDebug) 打开调试。 */ enableDebug: process.env.NODE_ENV !== 'production', /** 当前小程序运行的宿主环境 */ // host: { appId: '' }, /** 微信设置的语言 */ language: navigator.language, /** 微信版本号 */ version: '', /** 系统当前主题,取值为light或dark,全局配置"darkmode":true时才能获取,否则为 undefined (不支持小游戏) */ theme: isDarkMode ? 'dark' : 'light' }; return info; }; /** 获取微信APP授权设置 */ const getAppAuthorizeSetting = () => { const info = { /** 允许微信使用相册的开关(仅 iOS 有效) */ albumAuthorized: 'not determined', /** 允许微信使用蓝牙的开关(仅 iOS 有效) */ bluetoothAuthorized: 'not determined', /** 允许微信使用摄像头的开关 */ cameraAuthorized: 'not determined', /** 允许微信使用定位的开关 */ locationAuthorized: 'not determined', /** 定位准确度。true 表示模糊定位,false 表示精确定位(仅 iOS 有效) */ locationReducedAccuracy: false, /** 允许微信使用麦克风的开关 */ microphoneAuthorized: 'not determined', /** 允许微信通知的开关 */ notificationAuthorized: 'not determined', /** 允许微信通知带有提醒的开关(仅 iOS 有效) */ notificationAlertAuthorized: 'not determined', /** 允许微信通知带有标记的开关(仅 iOS 有效) */ notificationBadgeAuthorized: 'not determined', /** 允许微信通知带有声音的开关(仅 iOS 有效) */ notificationSoundAuthorized: 'not determined', /** 允许微信使用日历的开关 */ phoneCalendarAuthorized: 'not determined' }; return info; }; /** 获取设备设置 */ const getSystemInfoSync = () => { const windowInfo = getWindowInfo(); const systemSetting = getSystemSetting(); const deviceInfo = getDeviceInfo(); const appBaseInfo = getAppBaseInfo(); const appAuthorizeSetting = getAppAuthorizeSetting(); delete deviceInfo.abi; const info = Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, windowInfo), systemSetting), deviceInfo), appBaseInfo), { /** 用户字体大小(单位px)。以微信客户端「我-设置-通用-字体大小」中的设置为准 */ fontSizeSetting: NaN, /** 允许微信使用相册的开关(仅 iOS 有效) */ albumAuthorized: appAuthorizeSetting.albumAuthorized === 'authorized', /** 允许微信使用摄像头的开关 */ cameraAuthorized: appAuthorizeSetting.cameraAuthorized === 'authorized', /** 允许微信使用定位的开关 */ locationAuthorized: appAuthorizeSetting.locationAuthorized === 'authorized', /** 允许微信使用麦克风的开关 */ microphoneAuthorized: appAuthorizeSetting.microphoneAuthorized === 'authorized', /** 允许微信通知的开关 */ notificationAuthorized: appAuthorizeSetting.notificationAuthorized === 'authorized', /** 允许微信通知带有提醒的开关(仅 iOS 有效) */ notificationAlertAuthorized: appAuthorizeSetting.notificationAlertAuthorized === 'authorized', /** 允许微信通知带有标记的开关(仅 iOS 有效) */ notificationBadgeAuthorized: appAuthorizeSetting.notificationBadgeAuthorized === 'authorized', /** 允许微信通知带有声音的开关(仅 iOS 有效) */ notificationSoundAuthorized: appAuthorizeSetting.notificationSoundAuthorized === 'authorized', /** 允许微信使用日历的开关 */ phoneCalendarAuthorized: appAuthorizeSetting.phoneCalendarAuthorized === 'authorized', /** `true` 表示模糊定位,`false` 表示精确定位,仅 iOS 支持 */ locationReducedAccuracy: appAuthorizeSetting.locationReducedAccuracy, /** 小程序当前运行环境 */ environment: '' }); return info; }; /** 获取系统信息 */ const getSystemInfoAsync = (...args_1) => tslib.__awaiter(void 0, [...args_1], void 0, function* (options = {}) { const { success, fail, complete } = options; const handle = new MethodHandler({ name: 'getSystemInfoAsync', success, fail, complete }); try { const info = yield getSystemInfoSync(); return handle.success(info); } catch (error) { return handle.fail({ errMsg: error }); } }); /** 获取系统信息 */ const getSystemInfo = (...args_2) => tslib.__awaiter(void 0, [...args_2], void 0, function* (options = {}) { const { success, fail, complete } = options; const handle = new MethodHandler({ name: 'getSystemInfo', success, fail, complete }); try { const info = yield getSystemInfoSync(); return handle.success(info); } catch (error) { return handle.fail({ errMsg: error }); } }); const getSkylineInfoSync = /* @__PURE__ */ temporarilyNotSupport('getSkylineInfoSync'); const getSkylineInfo = /* @__PURE__ */ temporarilyNotSupport('getSkylineInfo'); const getRendererUserAgent = /* @__PURE__ */ temporarilyNotSupport('getRendererUserAgent'); // 更新 const updateWeChatApp = /* @__PURE__ */ temporarilyNotSupport('updateWeChatApp'); const getUpdateManager = /* @__PURE__ */ temporarilyNotSupport('getUpdateManager'); const unhandledRejectionCallbackManager = new CallbackManager(); const themeChangeCallbackManager = new CallbackManager(); const pageNotFoundCallbackManager = new CallbackManager(); const errorCallbackManager = new CallbackManager(); const appShowCallbackManager = new CallbackManager(); const appHideCallbackManager = new CallbackManager(); const unhandledRejectionListener = (res) => { unhandledRejectionCallbackManager.trigger(res); }; let themeMatchMedia = null; const themeChangeListener = (res) => { themeChangeCallbackManager.trigger({ theme: res.matches ? 'dark' : 'light' }); }; const pageNotFoundListener = (res) => { pageNotFoundCallbackManager.trigger(res); }; const errorListener = (res) => { // @ts-ignore errorCallbackManager.trigger(res.stack || res.message || res); }; const getApp$1 = () => { var _a; const path = (_a = Taro.Current.page) === null || _a === void 0 ? void 0 : _a.path; return { /** 小程序切前台的路径 */ path: (path === null || path === void 0 ? void 0 : path.substring(0, path.indexOf('?'))) || '', /** 小程序切前台的 query 参数 */ query: queryString.parse(location.search), /** 来源信息。 */ referrerInfo: {}, /** 小程序切前台的[场景值](https://developers.weixin.qq.com/miniprogram/dev/framework/app-service/scene.html) */ scene: 0, /** shareTicket,详见[获取更多转发信息](https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/share.html) */ shareTicket: '' }; }; const appShowListener = () => { if (document.visibilityState !== 'hidden') { appShowCallbackManager.trigger(getApp$1()); } }; const appHideListener = () => { if (document.visibilityState === 'hidden') { appHideCallbackManager.trigger(getApp$1()); } }; // 应用级事件 const onUnhandledRejection = callback => { unhandledRejectionCallbackManager.add(callback); if (unhandledRejectionCallbackManager.count() === 1) { window.addEventListener('unhandledrejection', unhandledRejectionListener); } }; const onThemeChange = callback => { themeChangeCallbackManager.add(callback); if (themeChangeCallbackManager.count() === 1) { if (isNil(themeMatchMedia)) { themeMatchMedia = window.matchMedia('(prefers-color-scheme: light)'); } themeMatchMedia.addEventListener('change', themeChangeListener); } }; const onPageNotFound = callback => { pageNotFoundCallbackManager.add(callback); if (pageNotFoundCallbackManager.count() === 1) { Taro.eventCenter.on('__taroRouterNotFound', pageNotFoundListener); } }; const onLazyLoadError = /* @__PURE__ */ temporarilyNotSupport('onLazyLoadError'); const onError = callback => { errorCallbackManager.add(callback); if (errorCallbackManager.count() === 1) { window.addEventListener('error', errorListener); } }; const onAudioInterruptionEnd = /* @__PURE__ */ temporarilyNotSupport('onAudioInterruptionEnd'); const onAudioInterruptionBegin = /* @__PURE__ */ temporarilyNotSupport('onAudioInterruptionBegin'); const onAppShow = callback => { appShowCallbackManager.add(callback); if (appShowCallbackManager.count() === 1) { window.addEventListener('visibilitychange', appShowListener); } }; const onAppHide = callback => { appHideCallbackManager.add(callback); if (appHideCallbackManager.count() === 1) { window.addEventListener('visibilitychange', appHideListener); } }; const offUnhandledRejection = callback => { unhandledRejectionCallbackManager.remove(callback); if (unhandledRejectionCallbackManager.count() === 0) { window.removeEventListener('unhandledrejection', unhandledRejectionListener); } }; const offThemeChange = callback => { themeChangeCallbackManager.remove(callback); if (themeChangeCallbackManager.count() === 0) { if (isNil(themeMatchMedia)) { themeMatchMedia = window.matchMedia('(prefers-color-scheme: light)'); } themeMatchMedia.removeEventListener('change', themeChangeListener); themeMatchMedia = null; } }; const offPageNotFound = callback => { pageNotFoundCallbackManager.remove(callback); if (pageNotFoundCallbackManager.count() === 0) { Taro.eventCenter.off('__taroRouterNotFound', pageNotFoundListener); } }; const offLazyLoadError = /* @__PURE__ */ temporarilyNotSupport('offLazyLoadError'); const offError = callback => { errorCallbackManager.remove(callback); if (errorCallbackManager.count() === 0) { window.removeEventListener('error', errorListener); } }; const offAudioInterruptionEnd = /* @__PURE__ */ temporarilyNotSupport('offAudioInterruptionEnd'); const offAudioInterruptionBegin = /* @__PURE__ */ temporarilyNotSupport('offAudioInterruptionBegin'); const offAppShow = callback => { appShowCallbackManager.remove(callback); if (appShowCallbackManager.count() === 0) { window.removeEventListener('visibilitychange', appShowListener); } }; const offAppHide = callback => { appHideCallbackManager.remove(callback); if (appHideCallbackManager.count() === 0) { window.removeEventListener('visibilitychange', appHideListener); } }; const launchOptions = { path: '', query: {}, scene: 0, shareTicket: '', referrerInfo: {} }; function initLaunchOptions(options = {}) { Object.assign(launchOptions, options); } Taro.eventCenter.once('__taroRouterLaunch', initLaunchOptions); // 生命周期 const getLaunchOptionsSync = () => launchOptions; const getEnterOptionsSync = () => launchOptions; const env = { FRAMEWORK: process.env.FRAMEWORK, TARO_ENV: process.env.TARO_ENV, TARO_PLATFORM: process.env.TARO_PLATFORM, TARO_VERSION: process.env.TARO_VERSION, }; // Note: 该方法由 taro-plugin-platform-h5 实现 // export const canIUse = /* @__PURE__ */ temporarilyNotSupport('canIUse') function arrayBufferToBase64(arrayBuffer) { return base64Js.fromByteArray(arrayBuffer); } function base64ToArrayBuffer(base64) { return base64Js.toByteArray(base64).buffer; } const TextBaseLineMap = { top: 'top', bottom: 'bottom', middle: 'middle', normal: 'alphabetic', hanging: 'hanging', alphabetic: 'alphabetic', ideographic: 'ideographic' }; class CanvasContext { constructor(canvas, ctx) { this.actions = []; this.canvas = canvas; this.ctx = ctx; } set ctx(e) { this.__raw__ = e; } get ctx() { return this.__raw__ || {}; } emptyActions() { this.actions.length = 0; } enqueueActions(func, ...args) { this.actions.push({ func, args }); } set fillStyle(e) { this.enqueueActions(() => { this.ctx.fillStyle = e; }); } get fillStyle() { return this.ctx.fillStyle; } set font(e) { this.ctx.font = e; } get font() { return this.ctx.font; } set globalAlpha(e) { this.enqueueActions(() => { this.ctx.globalAlpha = e; }); } get globalAlpha() { return this.ctx.globalAlpha; } set globalCompositeOperation(e) { this.enqueueActions(() => { this.ctx.globalCompositeOperation = e; }); } get globalCompositeOperation() { return this.ctx.globalCompositeOperation; } set lineCap(e) { this.enqueueActions(() => { this.ctx.lineCap = e; }); } get lineCap() { return this.ctx.lineCap; } set lineDashOffset(e) { this.enqueueActions(() => { this.ctx.lineDashOffset = e; }); } get lineDashOffset() { return this.ctx.lineDashOffset; } set lineJoin(e) { this.enqueueActions(() => { this.ctx.lineJoin = e; }); } get lineJoin() { return this.ctx.lineJoin; } set lineWidth(e) { this.enqueueActions(() => { this.ctx.lineWidth = e; }); } get lineWidth() { return this.ctx.lineWidth; } set miterLimit(e) { this.enqueueActions(() => { this.ctx.miterLimit = e; }); } get miterLimit() { return this.ctx.miterLimit; } set shadowBlur(e) { this.enqueueActions(() => { this.ctx.shadowBlur = e; }); } get shadowBlur() { return this.ctx.shadowBlur; } set shadowColor(e) { this.enqueueActions(() => { this.ctx.shadowColor = e; }); } get shadowColor() { return this.ctx.shadowColor; } set shadowOffsetX(e) { this.enqueueActions(() => { this.ctx.shadowOffsetX = e; }); } get shadowOffsetX() { return this.ctx.shadowOffsetX; } set shadowOffsetY(e) { this.enqueueActions(() => { this.ctx.shadowOffsetY = e; }); } get shadowOffsetY() { return this.ctx.shadowOffsetY; } set strokeStyle(e) { this.enqueueActions(() => { this.ctx.strokeStyle = e; }); } get strokeStyle() { return this.ctx.strokeStyle; } /** 小程序文档中不包括 ↓↓↓ */ set textAlign(e) { this.ctx.textAlign = e; } get textAlign() { return this.ctx.textAlign; } set textBaseline(e) { this.ctx.textBaseline = e; } get textBaseline() { return this.ctx.textBaseline; } set direction(e) { this.ctx.direction = e; } get direction() { return this.ctx.direction; } set imageSmoothingEnabled(e) { this.enqueueActions(() => { this.ctx.imageSmoothingEnabled = e; }); } get imageSmoothingEnabled() { return this.ctx.imageSmoothingEnabled; } set imageSmoothingQuality(e) { this.enqueueActions(() => { this.ctx.imageSmoothingQuality = e; }); } get imageSmoothingQuality() { return this.ctx.imageSmoothingQuality; } set filter(e) { this.enqueueActions(() => { this.ctx.filter = e; }); } get filter() { return this.ctx.filter; } /** 小程序文档中不包括 ↑↑↑ */ arc(...args) { return this.enqueueActions(this.ctx.arc, ...args); } arcTo(...args) { return this.enqueueActions(this.ctx.arcTo, ...args); } beginPath(...args) { return this.enqueueActions(this.ctx.beginPath, ...args); } bezierCurveTo(...args) { return this.enqueueActions(this.ctx.bezierCurveTo, ...args); } clearRect(...args) { return this.enqueueActions(this.ctx.clearRect, ...args); } clip(...args) { return this.enqueueActions(this.ctx.clip, ...args); } closePath(...args) { return this.enqueueActions(this.ctx.closePath, ...args); } createPattern(imageResource, repetition) { // 需要转换为 Image if (typeof imageResource === 'string') { const img = new Image(); img.src = imageResource; return new Promise((resolve, reject) => { img.onload = () => { resolve(this.ctx.createPattern(img, repetition)); }; img.onerror = reject; }); } return this.ctx.createPattern(imageResource, repetition); } /** * 将之前在绘图上下文中的描述(路径、变形、样式)画到 canvas 中。 * @todo 每次 draw 都会读取 width 和 height */ draw(reserve, callback) { return tslib.__awaiter(this, void 0, void 0, function* () { try { if (!reserve) { this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); } // 部分 action 是异步的 for (const { func, args } of this.actions) { yield func.apply(this.ctx, args); } this.emptyActions(); callback && callback(); } catch (e) { /* eslint-disable no-throw-literal */ throw { errMsg: e.message }; } }); } drawImage(imageResource, ...extra) { this.enqueueActions(() => { // 需要转换为 Image if (typeof imageResource === 'string') { const img = new Image(); img.src = imageResource; return new Promise((resolve, reject) => { img.onload = () => { this.ctx.drawImage(img, ...extra); resolve(); }; img.onerror = reject; }); } this.ctx.drawImage(imageResource, ...extra); }); } fill(...args) { return this.enqueueActions(this.ctx.fill, ...args); } fillRect(...args) { return this.enqueueActions(this.ctx.fillRect, ...args); } fillText(...args) { return this.enqueueActions(this.ctx.fillText, ...args); } lineTo(...args) { return this.enqueueActions(this.ctx.lineTo, ...args); } moveTo(...args) { return this.enqueueActions(this.ctx.moveTo, ...args); } quadraticCurveTo(...args) { return this.enqueueActions(this.ctx.quadraticCurveTo, ...args); } rect(...args) { return this.enqueueActions(this.ctx.rect, ...args); } // @ts-ignore reset() { return this.ctx.reset(); } restore() { return this.ctx.restore(); } rotate(...args) { return this.enqueueActions(this.ctx.rotate, ...args); } save() { return this.ctx.save(); } scale(...args) { return this.enqueueActions(this.ctx.scale, ...args); } setFillStyle(color) { this.enqueueActions(() => { this.ctx.fillStyle = color; }); } setFontSize(fontSize) { const arr = this.font.split(/\s/); const idx = arr.findIndex(e => /^\d+px$/.test(e)); if (idx !== -1) { arr[idx] = `${fontSize}px`; this.font = arr.join(' '); } } setGlobalAlpha(alpha) { this.globalAlpha = alpha; } setLineCap(lineCap) { this.lineCap = lineCap; } setLineDash(pattern, offset) { this.enqueueActions(() => { this.ctx.setLineDash(pattern); this.ctx.lineDashOffset = offset; }); } setLineJoin(lineJoin) { this.lineJoin = lineJoin; } setLineWidth(lineWidth) { this.lineWidth = lineWidth; } setMiterLimit(miterLimit) { this.miterLimit = miterLimit; } setShadow(offsetX, offsetY, blur, color) { this.enqueueActions(() => { this.ctx.shadowOffsetX = offsetX; this.ctx.shadowOffsetY = offsetY; this.ctx.shadowColor = color; this.ctx.shadowBlur = blur; }); } setStrokeStyle(color) { this.enqueueActions(() => { this.ctx.strokeStyle = color; }); } setTextAlign(align) { this.textAlign = align; } setTextBaseline(textBaseline) { this.textBaseline = TextBaseLineMap[textBaseline] || 'alphabetic'; } setTransform(...args) { return this.enqueueActions(this.ctx.setTransform, ...args); } stroke(...args) { return this.enqueueActions(this.ctx.stroke, ...args); } strokeRect(...args) { return this.enqueueActions(this.ctx.strokeRect, ...args); } strokeText(...args) { return this.enqueueActions(this.ctx.strokeText, ...args); } transform(...args) { return this.enqueueActions(this.ctx.transform, ...args); } translate(...args) { return this.enqueueActions(this.ctx.translate, ...args); } measureText(text) { return this.ctx.measureText(text); } createCircularGradient(x, y, r) { const radialGradient = this.ctx.createRadialGradient(x, y, 0, x, y, r); return radialGradient; } createLinearGradient(x0, y0, x1, y1) { return this.ctx.createLinearGradient(x0, y0, x1, y1); } } /** * 创建 canvas 的绘图上下文 CanvasContext 对象 */ const createCanvasContext = (canvasId, inst) => { const el = findDOM(inst); const canvas = el === null || el === void 0 ? void 0 : el.querySelector(`canvas[canvas-id="${canvasId}"]`); const ctx = canvas === null || canvas === void 0 ? void 0 : canvas.getContext('2d'); const context = new CanvasContext(canvas, ctx); if (!ctx) return context; context.canvas = canvas; context.ctx = ctx; return context; }; /** * 把当前画布指定区域的内容导出生成指定大小的图片。在 draw() 回调里调用该方法才能保证图片导出成功。 * @todo 暂未支持尺寸相关功能 */ const canvasToTempFilePath = ({ canvasId, fileType, quality, success, fail, complete }, inst) => { const handle = new MethodHandler({ name: 'canvasToTempFilePath', success, fail, complete }); const el = findDOM(inst); const canvas = el === null || el === void 0 ? void 0 : el.querySelector(`canvas[canvas-id="${canvasId}"]`); try { const dataURL = canvas === null || canvas === void 0 ? void 0 : canvas.toDataURL(`image/${(fileType === 'jpg' ? 'jpeg' : fileType) || 'png'}`, quality); return handle.success({ tempFilePath: dataURL }); } catch (e) { return handle.fail({ errMsg: e.message }); } }; /** * 将像素数据绘制到画布。在自定义组件下,第二个参数传入自定义组件实例 this,以操作组件内 <canvas> 组件 * @todo 暂未支持尺寸相关功能 */ const canvasPutImageData = ({ canvasId, data, x, y, success, fail, complete }, inst) => { const handle = new MethodHandler({ name: 'canvasPutImageData', success, fail, complete }); const el = findDOM(inst); const canvas = el === null || el === void 0 ? void 0 : el.querySelector(`canvas[canvas-id="${canvasId}"]`); try { const ctx = canvas.getContext('2d'); // TODO Uint8ClampedArray => ImageData ctx === null || ctx === void 0 ? void 0 : ctx.putImageData(data, x, y); return handle.success(); } catch (e) { return handle.fail({ errMsg: e.message }); } }; /** * 获取 canvas 区域隐含的像素数据。 */ const canvasGetImageData = ({ canvasId, success, fail, complete, x, y, width, height }, inst) => { const handle = new MethodHandler({ name: 'canvasGetImageData', success, fail, complete }); const el = findDOM(inst); const canvas = el === null || el === void 0 ? void 0 : el.querySelector(`canvas[canvas-id="${canvasId}"]`); try { const ctx = canvas === null || canvas === void 0 ? void 0 : canvas.getContext('2d'); // TODO ImageData => Uint8ClampedArray const data = ctx === null || ctx === void 0 ? void 0 : ctx.getImageData(x, y, width, height); return handle.success({ width, height, data }); } catch (e) { return handle.fail({ errMsg: e.message }); } }; // 画布 /** 创建离屏 canvas 实例 */ const createOffscreenCanvas = /* @__PURE__ */ temporarilyNotSupport('createOffscreenCanvas'); class cloud { constructor() { this.init = temporarilyNotSupport('cloud.init'); this.CloudID = temporarilyNotSupport('cloud.CloudID'); // @ts-ignore this.callFunction = temporarilyNotSupport('cloud.callFunction'); // @ts-ignore this.uploadFile = temporarilyNotSupport('cloud.uploadFile'); // @ts-ignore this.downloadFile = temporarilyNotSupport('cloud.downloadFile'); // @ts-ignore this.getTempFileURL = temporarilyNotSupport('cloud.getTempFileURL'); // @ts-ignore this.deleteFile = temporarilyNotSupport('cloud.deleteFile'); // @ts-ignore this.database = temporarilyNotSupport('cloud.database'); // @ts-ignore this.callContainer = temporarilyNotSupport('cloud.callContainer'); } } const reportMonitor = /* @__PURE__ */ temporarilyNotSupport('reportMonitor'); const reportAnalytics = /* @__PURE__ */ temporarilyNotSupport('reportAnalytics'); const reportEvent = /* @__PURE__ */ temporarilyNotSupport('reportEvent'); const getExptInfoSync = /* @__PURE__ */ temporarilyNotSupport('getExptInfoSync'); const callbackManager$3 = new CallbackManager(); let devicemotionListener; /** * 停止监听加速度数据。 */ const stopAccelerometer = ({ success, fail, complete } = {}) => { const res = {}; const handle = new MethodHandler({ name: 'stopAccelerometer', success, fail, complete }); try { window.removeEventListener('devicemotion', devicemotionListener, true); return handle.success(res); } catch (e) { res.errMsg = e.message; return handle.fail(res); } }; const INTERVAL_MAP$1 = { game: { interval: 20, frequency: 50 }, ui: { interval: 60, frequency: 16.67 }, normal: { interval: 200, frequency: 5 } }; /** * 开始监听加速度数据。 */ const startAccelerometer = ({ interval = 'normal', success, fail, complete } = {}) => { const handle = new MethodHandler({ name: 'startAccelerometer', success, fail, complete }); try { if (window.DeviceMotionEvent) { const intervalObj = INTERVAL_MAP$1[interval]; if (devicemotionListener) { stopAccelerometer(); } devicemotionListener = throttle((evt) => { var _a, _b, _c; callbackManager$3.trigger({ x: ((_a = evt.acceleration) === null || _a === void 0 ? void 0 : _a.x) || 0, y: ((_b = evt.acceleration) === null || _b === void 0 ? void 0 : _b.y) || 0, z: ((_c = evt.acceleration) === null || _c === void 0 ? void 0 : _c.z) || 0 }); }, intervalObj.interval); window.addEventListener('devicemotion', devicemotionListener, true); } else { throw new Error('accelerometer is not supported'); } return handle.success(); } catch (e) { return handle.fail({ errMsg: e.message }); } }; /** * 监听加速度数据事件。频率根据 Taro.startAccelerometer() 的 interval 参数。可使用 Taro.stopAccelerometer() 停止监听。 */ const onAccelerometerChange = callback => { callbackManager$3.add(callback); }; /** * 取消监听加速度数据事件,参数为空,则取消所有的事件监听 */ const offAccelerometerChange = callback => { callbackManager$3.remove(callback); }; // 无障碍 const checkIsOpenAccessibility = /* @__PURE__ */ temporarilyNotSupport('checkIsOpenAccessibility'); // 电量 // Note: 浏览器标准下不支持,其他实现方案不准确,不建议开发者使用 const getBatteryInfoSync = /* @__PURE__ */ permanentlyNotSupport('getBatteryInfoSync'); const getBatteryInfo = (...args_1) => tslib.__awaiter(void 0, [...args_1], void 0, function* ({ success, fail, complete } = {}) { var _a; const handle = new MethodHandler({ name: 'getBatteryInfo', success, fail, complete }); try { // @ts-ignore const battery = yield ((_a = navigator.getBattery) === null || _a === void 0 ? void 0 : _a.call(navigator)); return handle.success({ isCharging: battery.charging, level: Number(battery.level || 0) * 100 }); } catch (error) { return handle.fail({ errMsg: (error === null || error === void 0 ? void 0 : error.message) || error }); } }); // 蓝牙-通用 const stopBluetoothDevicesDiscovery = /* @__PURE__ */ temporarilyNotSupport('stopBluetoothDevicesDiscovery'); const startBluetoothDevicesDiscovery = /* @__PURE__ */ temporarilyNotSupport('startBluetoothDevicesDiscovery'); const openBluetoothAdapter = /* @__PURE__ */ temporarilyNotSupport('openBluetoothAdapter'); const onBluetoothDeviceFound = /* @__PURE__ */ temporarilyNotSupport('onBluetoothDeviceFound'); const onBluetoothAdapterStateChange = /* @__PURE__ */ temporarilyNotSupport('onBluetoothAdapterStateChange'); const offBluetoothDeviceFound = /* @__PURE__ */ temporarilyNotSupport('offBluetoothDeviceFound'); const offBluetoothAdapterStateChange = /* @__PURE__ */ temporarilyNotSupport('offBluetoothAdapterStateChange'); const makeBluetoothPair = /* @__PURE__ */ temporarilyNotSupport('makeBluetoothPair'); const isBluetoothDevicePaired = /* @__PURE__ */ temporarilyNotSupport('isBluetoothDevicePaired'); const getConnectedBluetoothDevices = /* @__PURE__ */ temporarilyNotSupport('getConnectedBluetoothDevices'); const getBluetoothDevices = /* @__PURE__ */ temporarilyNotSupport('getBluetoothDevices'); const getBluetoothAdapterState = /* @__PURE__ */ temporarilyNotSupport('getBluetoothAdapterState'); const closeBluetoothAdapter = /* @__PURE__ */ temporarilyNotSupport('closeBluetoothAdapter'); // 蓝牙-低功耗中心设备 const writeBLECharacteristicValue = /* @__PURE__ */ temporarilyNotSupport('writeBLECharacteristicValue'); const setBLEMTU = /* @__PURE__ */ temporarilyNotSupport('setBLEMTU'); const readBLECharacteristicValue = /* @__PURE__ */ temporarilyNotSupport('readBLECharacteristicValue'); const onBLEMTUChange = /* @__PURE__ */ temporarilyNotSupport('onBLEMTUChange'); const onBLEConnectionStateChange = /* @__PURE__ */ temporarilyNotSupport('onBLEConnectionStateChange'); const onBLECharacteristicValueChange = /* @__PURE__ */ temporarilyNotSupport('onBLECharacteristicValueChange'); const offBLEMTUChange = /* @__PURE__ */ temporarilyNotSupport('offBLEMTUChange'); const offBLEConnectionStateChange = /* @__PURE__ */ temporarilyNotSupport('offBLEConnectionStateChange'); const offBLECharacteristicValueChange = /* @__PURE__ */ temporarilyNotSupport('offBLECharacteristicValueChange'); const notifyBLECharacteristicValueChange = /* @__PURE__ */ temporarilyNotSupport('notifyBLECharacteristicValueChange'); const getBLEMTU = /* @__PURE__ */ temporarilyNotSupport('getBLEMTU'); const getBLEDeviceServices = /* @__PURE__ */ temporarilyNotSupport('getBLEDeviceServices'); const getBLEDeviceRSSI = /* @__PURE__ */ temporarilyNotSupport('getBLEDeviceRSSI'); const getBLEDeviceCharacteristics = /* @__PURE__ */ temporarilyNotSupport('getBLEDeviceCharacteristics'); const createBLEConnection = /* @__PURE__ */ temporarilyNotSupport('createBLEConnection'); const closeBLEConnection = /* @__PURE__ */ temporarilyNotSupport('closeBLEConnection'); // 蓝牙-低功耗外围设备 const onBLEPeripheralConnectionStateChanged = /* @__PURE__ */ temporarilyNotSupport('onBLEPeripheralConnectionStateChanged'); const offBLEPeripheralConnectionStateChanged = /* @__PURE__ */ temporarilyNotSupport('offBLEPeripheralConnectionStateChanged'); const createBLEPeripheralServer = /* @__PURE__ */ temporarilyNotSupport('createBLEPeripheralServer'); // 日历 const addPhoneRepeatCalendar = (options) => { const methodName = 'addPhoneRepeatCalendar'; // options must be an Object const isObject = shouldBeObject(options); if (!isObject.flag) { const res = { errMsg: `${methodName}:fail ${isObject.msg}` }; console.error(res.errMsg); return Promise.reject(res); } const { title, startTime = new Date().getTime(), allDay = false, description = '', location = '', endTime, alarm = true, alarmOffset = 0, repeatInterval = 'month', repeatEndTime, success, fail, complete, } = options; const handle = new MethodHandler({ name: methodName, success, fail, complete }); if (typeof title !== 'string') { return handle.fail({ errMsg: getParameterError({ para: 'title', correct: 'String', wrong: title }) }); } const start = new Date(startTime); const end = new Date(endTime || startTime); if (!endTime && allDay) { end.setDate(end.getDate() + 1); } const interval = 1000 * 60 * 60 * 24; let days = 1; let repeat = 1; if (repeatEndTime) { const repeatEnd = new Date(repeatEndTime); if (repeatEnd < start) { return handle.fail({ errMsg: 'repeatEndTime must be greater than startTime' }); } switch (repeatInterval) { case 'week': days = 7; break; case 'month': days = 30; break; case 'year': days = 365; break; default: } repeat = Math.ceil((repeatEnd.getTime() - start.getTime()) / (interval * days)); } const { error, value } = ics__namespace.createEvent({ title, start: parseTime2Array(start, allDay), description, location, end: parseTime2Array(end, allDay), alarms: alarm ? [{ action: 'display', description, trigger: { before: true, seconds: alarmOffset, }, duration: { days, }, repeat, }] : [], }); if (error || !value) { return handle.fail({ errMsg: error === null || error === void 0 ? void 0 : error.message }); } const url = URL.createObjectURL(new Blob([value])); createDownload(url, `${title}.ics`); return handle.success(); }; const addPhoneCalendar = (options) => { const methodName = 'addPhoneCalendar'; // options must be an Object const isObject = shouldBeObject(options); if (!isObject.flag) { const res = { errMsg: `${methodName}:fail ${isObject.msg}` }; console.error(res.errMsg); return Promise.reject(res); } const { title, startTime = new Date().getTime(), allDay = false, description = '', location = '', endTime, alarm = true, alarmOffset = 0, success, fail, complete, } = options; const handle = new MethodHandler({ name: methodName, success, fail, complete }); if (typeof title !== 'string') { return handle.fail({ errMsg: getParameterError({ para: 'title', correct: 'String', wrong: title }) }); } const start = new Date(startTime); const end = new Date(endTime || startTime); if (!endTime && allDay) { end.setDate(end.getDate() + 1); } const { error, value } = ics__namespace.createEvent({ title, start: parseTime2Array(start, allDay), description, location, end: parseTime2Array(end, allDay), alarms: alarm ? [{ action: 'display', description, trigger: { before: true, seconds: alarmOffset, }, }] : [], }); if (error || !value) { return handle.fail({ errMsg: error === null || error === void 0 ? void 0 : error.message }); } const url = URL.createObjectURL(new Blob([value])); createDownload(url, `${title}.ics`); return handle.success(); }; function parseTime2Array(time, allDay = false) { const t = new Date(time); const timeArr = [ t.getFullYear(), t.getMonth() + 1, t.getDate(), ]; if (!allDay) { timeArr.push(t.getHours(), t.getMinutes()); } re