UNPKG

@huantv/vue

Version:
415 lines (384 loc) 10.5 kB
import colorParser from '@css-loader/color-parser'; import { isDef } from 'shared/util'; import { HIPPY_VUE_VERSION, warn, trace, isFunction, } from '../util'; import BackAndroid from './backAndroid'; import * as NetInfo from './netInfo'; const { on, off, emit, bridge: { callNative, callNativeWithPromise, callNativeWithCallbackId, }, device: { platform: { OS: Platform, Localization = {}, }, screen: { scale: PixelRatio, }, }, device: Dimensions, document: UIManagerModule, register: HippyRegister, } = Hippy; const CACHE = {}; const measureInWindowByMethod = function measureInWindowByMethod(el, method) { const empty = { top: -1, left: -1, bottom: -1, right: -1, width: -1, height: -1, }; if (!el.isMounted || !el.nodeId) { return Promise.resolve(empty); } const { nodeId } = el; // FIXME: callNativeWithPromise was broken in iOS, it response // UIManager was called with 3 arguments, but expect 2. // So wrap the function with a Promise. const timeout = new Promise(resolve => setTimeout(() => { resolve(empty); }, 100)); const measure = new Promise(resolve => callNative('UIManagerModule', method, nodeId, (pos) => { // Android error handler. if (!pos || pos === 'this view is null') { return resolve(empty); } return resolve({ top: pos.y, left: pos.x, bottom: pos.y + pos.height, right: pos.x + pos.width, width: pos.width, height: pos.height, }); })); return Promise.race([timeout, measure]); }; /** * Native communication module */ const Native = { /** * Class native methods */ callNative, /** * Call native methods with a promise response. */ callNativeWithPromise, /** * Call native with callId returns */ callNativeWithCallbackId, /** * Draw UI with native language. */ UIManagerModule, /** * Global device event listener */ on, off, emit, /** * Get the device pixel ratio */ PixelRatio, /** * Get the running operating system. */ Platform, /** * Get the localization of country, language and direction */ Localization, /** * Hippy-Vue version */ version: HIPPY_VUE_VERSION, /** * Cookie Module */ Cookie: { /** * Get all of cookies by string * @param {string} url - Get the cookies by specific url. * @return {Promise<string>} - Cookie string, like `name=someone;gender=female`. */ getAll(url) { if (!url) { throw new TypeError('Vue.Native.Cookie.getAll() must have url argument'); } return callNativeWithPromise.call(this, 'network', 'getCookie', url); }, /** * Set cookie key and value * @param {string} url - Set the cookie to specific url. * @param {string} keyValue - Full of key values, like `name=someone;gender=female`. * @param {Date} expireDate - Specific date of expiration. */ set(url, keyValue, expireDate) { if (!url) { throw new TypeError('Vue.Native.Cookie.getAll() must have url argument'); } if (typeof keyValue !== 'string') { throw new TypeError('Vue.Native.Cookie.getAll() only receive string type of keyValue'); } let expireStr = ''; if (expireDate) { if (expireDate instanceof Date) { expireStr = expireDate.toUTCString(); } else { throw new TypeError('Vue.Native.Cookie.getAll() only receive Date type of expires'); } } callNative.call(this, 'network', 'setCookie', url, keyValue, expireStr); }, }, /** * Clipboard Module */ Clipboard: { getString() { return callNativeWithPromise.call(this, 'ClipboardModule', 'getString'); }, setString(content) { callNative.call(this, 'ClipboardModule', 'setString', content); }, }, /** * Determine the device is iPhone X */ get isIPhoneX() { if (!isDef(CACHE.isIPhoneX)) { // Assume false in most cases. let isIPhoneX = false; if (Native.Platform === 'ios') { // iOS12 - iPhone11: 48 Phone12/12 pro/12 pro max: 47 other: 44 const statusBarHeightList = [44, 47, 48]; isIPhoneX = statusBarHeightList.indexOf(Native.Dimensions.screen.statusBarHeight) > -1; } CACHE.isIPhoneX = isIPhoneX; } return CACHE.isIPhoneX; }, /** * Determine the screen is vertical orientation. * Should always retrieve from scratch. */ get screenIsVertical() { return Native.Dimensions.window.width < Native.Dimensions.window.height; }, /** * Get the device information */ get Device() { if (!isDef(CACHE.Device)) { if (Platform === 'ios') { if (global.__HIPPYNATIVEGLOBAL__ && global.__HIPPYNATIVEGLOBAL__.Device) { CACHE.Device = global.__HIPPYNATIVEGLOBAL__.Device; } else { CACHE.Device = 'iPhone'; } } else if (Platform === 'android') { // TODO: Need android native fill the information CACHE.Device = 'Android device'; } else { CACHE.Device = 'Unknown device'; } } return CACHE.Device; }, /** * Get the OS version * TODO: the API is iOS only so far. */ get OSVersion() { if (Platform !== 'ios') { warn('Vue.Native.OSVersion is available in iOS only'); return null; } if (!global.__HIPPYNATIVEGLOBAL__ || !global.__HIPPYNATIVEGLOBAL__.OSVersion) { warn('Vue.Native.OSVersion is only available for iOS SDK > 0.2.0'); return null; } return global.__HIPPYNATIVEGLOBAL__.OSVersion; }, /** * Get the SDK version * TODO: the API is iOS only so far. */ get SDKVersion() { if (Platform !== 'ios') { warn('Vue.Native.SDKVersion is available in iOS only'); return null; } if (!global.__HIPPYNATIVEGLOBAL__ || !global.__HIPPYNATIVEGLOBAL__.OSVersion) { warn('Vue.Native.SDKVersion is only available for iOS SDK > 0.2.0'); return null; } return global.__HIPPYNATIVEGLOBAL__.SDKVersion; }, /** * Get the API version * TODO: the API is Android only so far. */ get APILevel() { if (Platform !== 'android') { warn('Vue.Native.APIVersion is available in Android only'); return null; } if (!global.__HIPPYNATIVEGLOBAL__ || !global.__HIPPYNATIVEGLOBAL__.Platform.APILevel) { warn('Vue.Native.APILevel needs higher Android SDK version to retrieve'); return null; } return global.__HIPPYNATIVEGLOBAL__.Platform.APILevel; }, /** * Get the screen or view size. */ get Dimensions() { const { screen } = Dimensions; // Convert statusBarHeight to dp unit for android platform // Here's a base issue: statusBarHeight for iOS is dp, but for statusBarHeight is pixel. // So make them be same to hippy-vue. let { statusBarHeight } = screen; if (Native.Platform === 'android') { statusBarHeight /= Native.PixelRatio; } return { window: Dimensions.window, screen: { ...screen, statusBarHeight, }, }; }, /** * Get the one pixel size of device */ get OnePixel() { if (!isDef(CACHE.OnePixel)) { const ratio = Native.PixelRatio; let onePixel = Math.round(0.4 * ratio) / ratio; if (!onePixel) { // Assume 0 is false onePixel = 1 / ratio; } CACHE.OnePixel = onePixel; } return CACHE.OnePixel; }, /** * Call native UI methods. */ callUIFunction(...args) { const [el, funcName, ...options] = args; const { nodeId } = el; let [params = [], callback] = options; if (typeof params === 'function') { callback = params; params = []; } trace('callUIFunction', { nodeId, funcName, params }); if (Native.Platform === 'android') { if (isFunction(callback)) { callNative('UIManagerModule', 'callUIFunction', [nodeId, funcName, params], callback); } else { callNative('UIManagerModule', 'callUIFunction', [nodeId, funcName, params]); } } else if (Native.Platform === 'ios' && el.meta.component.name) { let { name: componentName } = el.meta.component; // FIXME: iOS callNative method need the real component name, // but there's no a module named View in __GLOBAL__.NativeModules. // Because only ScrollView use the method so far, so just a workaround here. if (componentName === 'View') { componentName = 'ScrollView'; } if (isFunction(callback) && Array.isArray(params)) { params.push(callback); } callNative('UIManagerModule', 'callUIFunction', [componentName, nodeId, funcName, params]); } }, /** * Measure the component size and position. */ measureInWindow(el) { return measureInWindowByMethod(el, 'measureInWindow'); }, /** * Measure the component size and position. */ measureInAppWindow(el) { if (Native.Platform === 'android') { return measureInWindowByMethod(el, 'measureInWindow'); } return measureInWindowByMethod(el, 'measureInAppWindow'); }, /** * parse the color to int32Color which native can understand. * @param { String | Number } color * @param { {platform: "ios" | "android"} } options * @returns { Number } int32Color */ parseColor(color, options = { platform: Native.Platform }) { const cache = CACHE.COLOR_PARSER || (CACHE.COLOR_PARSER = Object.create(null)); if (!cache[color]) { // cache the calculation result cache[color] = colorParser(color, options); } return cache[color]; }, /** * Key-Value storage system */ AsyncStorage: global.localStorage, /** * Android hardware back button event listener. */ BackAndroid, /** * operations for img */ ImageLoader: { /** * Get the image size before rendering. * * @param {string} url - Get image url. */ getSize(url) { return callNativeWithPromise.call(this, 'ImageLoaderModule', 'getSize', url); }, /** * Prefetch image, to make rendering in next more faster. * * @param {string} url - Prefetch image url. */ prefetch(url) { callNative.call(this, 'ImageLoaderModule', 'prefetch', url); }, }, /** * Network operations */ NetInfo, }; // Public export export default Native; // Private export export { HippyRegister, UIManagerModule, };