coolink-ts
Version:
Coocaa Coolink APP JavaScript library base on Thresh-lib.
309 lines (295 loc) • 9.15 kB
text/typescript
/**
* MIT License
*
* Copyright (c) 2020 ManBang Group
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
import BridgeManager from '../manager/BridgeManager'
import UtilManager from '../manager/UtilManager'
import Util from '../shared/Util'
import { ChannelParams, BridgeParams } from '../types/type'
import threshApp from '../core/ThreshApp'
import appContainer from '../core/AppContainer'
import { PerformanceInfo } from '../core/PageContainer'
declare const methodChannel_js_call_flutter: Function
declare const methodChannel_js_call_native: Function
/**
* JS 向 Flutter 发出消息的类型枚举
*/
export enum FlutterMethodChannelType {
none = '', // 改消息会被忽略
setBundleDir = 'setBundleDir',
devtools = 'devtools',
bridgeRequest = 'bridgeRequest',
onError = 'onError',
// UI
mediaQuery = 'mediaQuery',
setAppBarHeight = 'setAppBarHeight',
pushPage = 'pushPage',
pushReplacement = 'pushReplacement',
popPage = 'popPage',
showModal = 'showModal',
showToast = 'showToast',
hideToast = 'hideToast',
setResourcePath = 'setResourcePath',
updateWidget = 'updateWidget',
pageNotFound = 'pageNotFound',
stopAlwaysRender = 'stopAlwaysRender',
onDestroyed = 'onDestroyed',
// Utils
copy = 'copy',
blur = 'blur',
// Widget Methods
updateTitle = 'updateTitle',
scrollTo = 'scrollTo',
stopAsyncOperate = 'stopAsyncOperate',
openActions = 'openActions',
closeActions = 'closeActions',
swipeTo = 'swipeTo',
setValue = 'setValue',
triggerFocus = 'triggerFocus',
jumpTo = 'jumpTo',
animateTo = 'animateTo',
switchTo = 'switchTo',
setNestScrollViewStatus = 'setNestScrollViewStatus',
dragPositionAnimateTo = 'dragPositionAnimateTo',
// video audio
play = 'play',
pause = 'pause',
seekTo = 'seekTo',
setVolume = 'setVolume',
//audio
setSourceUrl = 'setSourceUrl',
//file
fileRequest = 'fileRequest',
// pdf view
openFile = 'openFile',
setPage = 'setPage',
setScale = 'setScale',
switchTheme = 'switchTheme',
getPageCount = 'getPageCount',
getCurrentPage = 'getCurrentPage',
chooseLocalFile = 'chooseLocalFile'
}
/**
* JS 向 Native 发出消息的类型枚举
*/
export enum NativeMethodChannelType {
print = 'print',
reload = 'reload',
pageDidShow = 'pageDidShow',
invokeNativeViewMethod = 'invokeNativeViewMethod',
bridgeRequest = 'bridgeRequest',
sendData = 'sendData',
}
/**
* JS 接收到的消息类型枚举
*/
export enum MethodChannelReceiveType {
mediaQuery = 'mediaQuery',
ready = 'ready',
setupPage = 'setupPage',
needPopPage = 'needPopPage',
hasPopPage = 'hasPopPage',
triggerEvent = 'triggerEvent',
lifeCycle = 'lifeCycle',
bridgeResponse = 'bridgeResponse',
closeWindow = 'closeWindow',
pageDidLoad = 'pageDidLoad',
onDestroyed = 'onDestroyed',
//file
fileResponse = 'fileResponse',
}
/**
* 打印method channel方法参数
*/
const methodChannelConsole = (channelParams: ChannelParams) => {
const { method, params, contextId } = channelParams
console.group('[CHANNEL PRINT] method: ' + method)
if (params) {
if (params.widgetRenderData) {
params.widgetRenderData = JSON.parse(params.widgetRenderData)
}
if (params.widgetUpdateData) {
params.widgetUpdateData = JSON.parse(params.widgetUpdateData)
}
}
console.log('contextId: ', contextId)
console.log('params: ', params)
console.groupEnd()
}
/**
* js与native和flutter通信的方法
* methodChannel_js_call_flutter methodChannel_js_call_native 为 native 注入到当前 js context 中的方法
*/
function jsCallNative(channelParams: ChannelParams) {
try {
channelParams = formatChannelParams(channelParams)
if (channelParams.method === FlutterMethodChannelType.none) return
methodChannel_js_call_native(channelParams)
} catch (e) { } finally {
// if (threshApp.debugMode && process.env.NODE_ENV === 'development') {
// methodChannelConsole(channelParams)
// }
}
}
function jsCallFlutter(channelParams: ChannelParams) {
try {
channelParams = formatChannelParams(channelParams)
if (channelParams.method === FlutterMethodChannelType.none) return
methodChannel_js_call_flutter(channelParams)
} catch (e) { } finally {
// if (threshApp.debugMode && process.env.NODE_ENV === 'development') {
// methodChannelConsole(channelParams)
// }
}
}
function formatChannelParams(channelParams: ChannelParams, stringifyParams: boolean = false): ChannelParams {
let { params } = channelParams
if (Util.isNil(params)) params = {}
if (!Util.isObject(params)) {
UtilManager.error('Channel params must pass in an object!')
return { method: FlutterMethodChannelType.none }
}
// if (!Util.isNil(params.__channelStartTime__)) {
// UtilManager.error('Channel params cannot use "__channelStartTime__" as a key!')
// return { method: FlutterMethodChannelType.none }
// }
// params.__channelStartTime__ = Date.now()
if (!channelParams.contextId) channelParams.contextId = appContainer.contextId
channelParams.params = stringifyParams ? JSON.stringify(params) : params
return channelParams
}
/**
* 通信类
* 封装了js调用native和flutter的方法
*/
export default class MethodChannel {
static MAX_CHUNK_SIZE: number = 1024 * 10
// 调用注入方法
static call({
method,
params = {},
contextId,
}: {
method: FlutterMethodChannelType | NativeMethodChannelType
params?: any
contextId?: string
}) {
jsCallFlutter({
contextId,
method,
params
})
}
// 页面初次渲染完成时通知 native
static pageDidShow(networkTime: number = 0) {
const performanceInfo: PerformanceInfo | undefined = appContainer.getPagePerformanceInfo()
if (!performanceInfo || performanceInfo.hasReported) return
performanceInfo.hasReported = true
const pageShowTimestamp = Date.now()
const pageName = threshApp.pageName || 'unknown'
jsCallNative({
method: NativeMethodChannelType.pageDidShow,
params: {
flutterVersion: threshApp.flutterVersion,
jsVersion: threshApp.jsVersion,
pageName,
// 网络通信耗时
networkTime,
// 页面创建时的时间戳
pageCreateTimestamp: performanceInfo.createTimestamp,
// 页面首帧加载完成的时间戳
pageLoadTimestamp: performanceInfo.loadTimestamp,
// 页面显示时的时间戳(包含网络通信耗时)
pageShowTimestamp,
}
})
UtilManager.log({
pageName,
networkTime,
pageLoadTime: performanceInfo.loadTimestamp - performanceInfo.createTimestamp,
pageShowTime: pageShowTimestamp - performanceInfo.createTimestamp
})
}
// 输出到native
static print(params: any = {}) {
jsCallNative({
method: NativeMethodChannelType.print,
params
})
}
// 重载bundle.js
static reload() {
jsCallNative({
method: NativeMethodChannelType.reload,
params: {}
})
}
// 触发 NativeView 方法
static invokeNativeViewMethod({
methodName,
methodParams = {},
viewType,
viewParams = {},
}: {
methodName: string,
methodParams?: any,
viewType: string,
viewParams?: any,
}) {
jsCallNative({
method: NativeMethodChannelType.invokeNativeViewMethod,
params: {
methodName,
methodParams,
viewType,
viewParams,
}
})
}
// bridge方法
static bridge(methodId: string, params: BridgeParams) {
if (!Util.isProd && BridgeManager.isNetworkRequest(params)) {
jsCallFlutter({
method: FlutterMethodChannelType.bridgeRequest,
params: {
methodId,
request: Util.toString(params),
}
})
return
}
jsCallNative({
method: NativeMethodChannelType.bridgeRequest,
params: {
methodId,
request: params,
}
})
}
// 向Native侧传数据
static sendDataToNative(params: any = {}) {
jsCallNative({
method: NativeMethodChannelType.sendData,
params
})
}
}