提交 5e6062fc 编写于 作者: Q qiang

Merge branch 'dev' into alpha

<template>
<view v-show="matches">
<slot />
</view>
</template>
<script>
let mediaQueryObserver
export default {
name: 'UniMatchMedia',
props: {
width: {
type: [Number, String],
default: ''
},
minWidth: {
type: [Number, String],
default: ''
},
maxWidth: {
type: [Number, String],
default: ''
},
height: {
type: [Number, String],
default: ''
},
minHeight: {
type: [Number, String],
default: ''
},
maxHeight: {
type: [Number, String],
default: ''
},
orientation: {
type: String,
default: ''
}
},
data () {
return {
matches: true,
}
},
mounted() {
mediaQueryObserver = uni.createMediaQueryObserver(this)
mediaQueryObserver.observe({
width: this.width,
maxWidth: this.maxWidth,
minWidth: this.minWidth,
height: this.height,
minHeight: this.minHeight,
maxHeight: this.maxHeight,
orientation: this.orientation
}, matches => {
this.matches = matches
})
},
destroyed() {
mediaQueryObserver.disconnect()
}
}
</script>
<style>
view {
display: block;
}
</style>
......@@ -463,7 +463,7 @@ function parseUsingAutoImportComponents (usingAutoImportComponents) {
return autoImportComponents
}
const BUILT_IN_COMPONENTS = ['page-meta', 'navigation-bar', 'match-media']
const BUILT_IN_COMPONENTS = ['page-meta', 'navigation-bar', 'uni-match-media']
function isBuiltInComponent (name) {
return BUILT_IN_COMPONENTS.includes(name)
......@@ -474,7 +474,7 @@ function isBuiltInComponentPath (modulePath) {
}
module.exports = {
isBuiltInComponent,
isBuiltInComponent,
isBuiltInComponentPath,
getMainEntry,
getNVueMainEntry,
......
......@@ -28,7 +28,14 @@ function getSourceRoot () {
}
function moduleFilenameTemplate (info) {
if (!info.allLoaders && info.resourcePath) {
if (
info.resourcePath &&
(
!info.allLoaders ||
info.query.includes('type=script&lang=ts') ||
info.resourcePath.endsWith('.ts')
)
) {
const filepath = normalizePath(path.relative(getSourceRoot(), info.absoluteResourcePath))
if (filepath.indexOf('../') === 0) {
return
......
......@@ -41,5 +41,4 @@ module.exports = {
video: ['app-plus', 'mp-weixin', 'h5'],
view: ['app-plus', 'mp-weixin', 'h5'],
'web-view': ['app-plus', 'mp-weixin'],
'match-media': ['app-plus', 'mp-weixin', 'h5']
}
......@@ -45,7 +45,6 @@ const TAGS = [
'video',
'view',
'web-view',
'match-media'
]
const EVENTS = {
......
......@@ -87,7 +87,10 @@ function compileTemplate (source, options, compile) {
}
const compilerModule = {
preTransformNode (el, options) {
preTransformNode (el, options) {
if (el.tag === 'match-media' && process.env.UNI_PLATFORM !== 'mp-weixin') {
el.tag = 'uni-match-media'
}
if (process.env.UNI_PLATFORM === 'quickapp-native') {
// 排查所有标签
(options.isUnaryTag.autoComponents || (options.isUnaryTag.autoComponents = new Set())).add(el.tag)
......
......@@ -48,7 +48,6 @@ const tags = [
'view',
'web-view',
'editor',
'match-media'
]
const baseCompiler = {
......
......@@ -2228,9 +2228,15 @@ var HTML5History = (function (History$$1) {
HTML5History.prototype.push = function push (location, onComplete , onAbort ) {
var this$1 = this;
if (typeof location === 'object') { // fixed by xxxxxx
if (typeof location === 'object') { // fixed by xxxxxx
location.params = location.params || {};
var hasId = location.params.__id__;
switch (location.type) {
case 'navigateTo':
case 'navigateTo':
if (!hasId) {
this.router.id++;
}
break
case 'redirectTo':
case 'reLaunch':
this.router.id++;
......@@ -2238,8 +2244,9 @@ var HTML5History = (function (History$$1) {
case 'switchTab':
break
}
location.params = location.params || {};
location.params.__id__ = this.router.id;
if (!hasId) {
location.params.__id__ = this.router.id;
}
}
var ref = this;
......@@ -2369,9 +2376,15 @@ var HashHistory = (function (History$$1) {
HashHistory.prototype.push = function push (location, onComplete , onAbort ) {
var this$1 = this;
if (typeof location === 'object') { // fixed by xxxxxx
if (typeof location === 'object') { // fixed by xxxxxx
location.params = location.params || {};
var hasId = location.params.__id__;
switch (location.type) {
case 'navigateTo':
case 'navigateTo':
if (!hasId) {
this.router.id++;
}
break
case 'redirectTo':
case 'reLaunch':
this.router.id++;
......@@ -2379,8 +2392,10 @@ var HashHistory = (function (History$$1) {
case 'switchTab':
break
}
location.params = location.params || {};
location.params.__id__ = this.router.id;
if (!hasId) {
location.params.__id__ = this.router.id;
}
}
var ref = this;
......
......@@ -2226,9 +2226,15 @@ var HTML5History = (function (History$$1) {
HTML5History.prototype.push = function push (location, onComplete , onAbort ) {
var this$1 = this;
if (typeof location === 'object') { // fixed by xxxxxx
if (typeof location === 'object') { // fixed by xxxxxx
location.params = location.params || {};
var hasId = location.params.__id__;
switch (location.type) {
case 'navigateTo':
case 'navigateTo':
if (!hasId) {
this.router.id++;
}
break
case 'redirectTo':
case 'reLaunch':
this.router.id++;
......@@ -2236,8 +2242,9 @@ var HTML5History = (function (History$$1) {
case 'switchTab':
break
}
location.params = location.params || {};
location.params.__id__ = this.router.id;
if (!hasId) {
location.params.__id__ = this.router.id;
}
}
var ref = this;
......@@ -2367,9 +2374,15 @@ var HashHistory = (function (History$$1) {
HashHistory.prototype.push = function push (location, onComplete , onAbort ) {
var this$1 = this;
if (typeof location === 'object') { // fixed by xxxxxx
if (typeof location === 'object') { // fixed by xxxxxx
location.params = location.params || {};
var hasId = location.params.__id__;
switch (location.type) {
case 'navigateTo':
case 'navigateTo':
if (!hasId) {
this.router.id++;
}
break
case 'redirectTo':
case 'reLaunch':
this.router.id++;
......@@ -2377,8 +2390,10 @@ var HashHistory = (function (History$$1) {
case 'switchTab':
break
}
location.params = location.params || {};
location.params.__id__ = this.router.id;
if (!hasId) {
location.params.__id__ = this.router.id;
}
}
var ref = this;
......
......@@ -2232,9 +2232,15 @@ var HTML5History = (function (History$$1) {
HTML5History.prototype.push = function push (location, onComplete , onAbort ) {
var this$1 = this;
if (typeof location === 'object') { // fixed by xxxxxx
if (typeof location === 'object') { // fixed by xxxxxx
location.params = location.params || {};
var hasId = location.params.__id__;
switch (location.type) {
case 'navigateTo':
case 'navigateTo':
if (!hasId) {
this.router.id++;
}
break
case 'redirectTo':
case 'reLaunch':
this.router.id++;
......@@ -2242,8 +2248,9 @@ var HTML5History = (function (History$$1) {
case 'switchTab':
break
}
location.params = location.params || {};
location.params.__id__ = this.router.id;
if (!hasId) {
location.params.__id__ = this.router.id;
}
}
var ref = this;
......@@ -2373,9 +2380,15 @@ var HashHistory = (function (History$$1) {
HashHistory.prototype.push = function push (location, onComplete , onAbort ) {
var this$1 = this;
if (typeof location === 'object') { // fixed by xxxxxx
if (typeof location === 'object') { // fixed by xxxxxx
location.params = location.params || {};
var hasId = location.params.__id__;
switch (location.type) {
case 'navigateTo':
case 'navigateTo':
if (!hasId) {
this.router.id++;
}
break
case 'redirectTo':
case 'reLaunch':
this.router.id++;
......@@ -2383,8 +2396,10 @@ var HashHistory = (function (History$$1) {
case 'switchTab':
break
}
location.params = location.params || {};
location.params.__id__ = this.router.id;
if (!hasId) {
location.params.__id__ = this.router.id;
}
}
var ref = this;
......
......@@ -757,11 +757,13 @@ Dep.SharedObject.targetStack = [];
function pushTarget (target) {
Dep.SharedObject.targetStack.push(target);
Dep.SharedObject.target = target;
Dep.target = target;
}
function popTarget () {
Dep.SharedObject.targetStack.pop();
Dep.SharedObject.target = Dep.SharedObject.targetStack[Dep.SharedObject.targetStack.length - 1];
Dep.target = Dep.SharedObject.target;
}
/* */
......
......@@ -764,11 +764,13 @@ Dep.SharedObject.targetStack = [];
function pushTarget (target) {
Dep.SharedObject.targetStack.push(target);
Dep.SharedObject.target = target;
Dep.target = target;
}
function popTarget () {
Dep.SharedObject.targetStack.pop();
Dep.SharedObject.target = Dep.SharedObject.targetStack[Dep.SharedObject.targetStack.length - 1];
Dep.target = Dep.SharedObject.target;
}
/* */
......
......@@ -755,11 +755,13 @@ Dep.SharedObject.targetStack = [];
function pushTarget (target) {
Dep.SharedObject.targetStack.push(target);
Dep.SharedObject.target = target;
Dep.target = target;
}
function popTarget () {
Dep.SharedObject.targetStack.pop();
Dep.SharedObject.target = Dep.SharedObject.targetStack[Dep.SharedObject.targetStack.length - 1];
Dep.target = Dep.SharedObject.target;
}
/* */
......
......@@ -761,11 +761,13 @@
function pushTarget (target) {
Dep.SharedObject.targetStack.push(target);
Dep.SharedObject.target = target;
Dep.target = target;
}
function popTarget () {
Dep.SharedObject.targetStack.pop();
Dep.SharedObject.target = Dep.SharedObject.targetStack[Dep.SharedObject.targetStack.length - 1];
Dep.target = Dep.SharedObject.target;
}
/* */
......
......@@ -748,11 +748,13 @@ Dep.SharedObject.targetStack = [];
function pushTarget (target) {
Dep.SharedObject.targetStack.push(target);
Dep.SharedObject.target = target;
Dep.target = target;
}
function popTarget () {
Dep.SharedObject.targetStack.pop();
Dep.SharedObject.target = Dep.SharedObject.targetStack[Dep.SharedObject.targetStack.length - 1];
Dep.target = Dep.SharedObject.target;
}
/* */
......
......@@ -746,11 +746,13 @@ Dep.SharedObject.targetStack = [];
function pushTarget (target) {
Dep.SharedObject.targetStack.push(target);
Dep.SharedObject.target = target;
Dep.target = target;
}
function popTarget () {
Dep.SharedObject.targetStack.pop();
Dep.SharedObject.target = Dep.SharedObject.targetStack[Dep.SharedObject.targetStack.length - 1];
Dep.target = Dep.SharedObject.target;
}
/* */
......
......@@ -752,11 +752,13 @@
function pushTarget (target) {
Dep.SharedObject.targetStack.push(target);
Dep.SharedObject.target = target;
Dep.target = target;
}
function popTarget () {
Dep.SharedObject.targetStack.pop();
Dep.SharedObject.target = Dep.SharedObject.targetStack[Dep.SharedObject.targetStack.length - 1];
Dep.target = Dep.SharedObject.target;
}
/* */
......
......@@ -740,11 +740,13 @@ Dep.SharedObject.targetStack = [];
function pushTarget (target) {
Dep.SharedObject.targetStack.push(target);
Dep.SharedObject.target = target;
Dep.target = target;
}
function popTarget () {
Dep.SharedObject.targetStack.pop();
Dep.SharedObject.target = Dep.SharedObject.targetStack[Dep.SharedObject.targetStack.length - 1];
Dep.target = Dep.SharedObject.target;
}
/* */
......
......@@ -136,8 +136,7 @@ if (process.env.UNI_USING_V3) {
'textarea',
'video',
'view',
'web-view',
'match-media'
'web-view'
]
const BG_PROPS = [
......
......@@ -158,5 +158,8 @@ if (pixelRatio !== 1) {
export function wrapper (canvas) {
canvas.width = canvas.offsetWidth * pixelRatio
canvas.height = canvas.offsetHeight * pixelRatio
canvas.getContext('2d').__hidpi__ = true
canvas.__hidpi__ = true
// 避免低版本安卓上 context 实例被回收
canvas.__context2d__ = canvas.getContext('2d')
canvas.__context2d__.__hidpi__ = true
}
import getRealPath from 'uni-platform/helpers/get-real-path'
export const saveFile = {
tempFilePath: {
type: String,
required: true,
validator (value, params) {
params.tempFilePath = getRealPath(value)
}
}
}
const TYPES = ['md5', 'sha1']
export const getFileInfo = {
filePath: {
type: String,
required: true,
validator (value, params) {
params.filePath = getRealPath(value)
}
},
digestAlgorithm: {
type: String,
validator (value, params) {
params.digestAlgorithm = TYPES.includes(value) ? value : TYPES[0]
},
default: TYPES[0]
}
}
export const getSavedFileInfo = {
filePath: {
type: String,
required: true,
validator (value, params) {
params.filePath = getRealPath(value)
}
}
}
export const removeSavedFile = {
filePath: {
type: String,
required: true,
validator (value, params) {
params.filePath = getRealPath(value)
}
}
}
......@@ -17,22 +17,9 @@ export const chooseImage = {
required: false,
default: SIZE_TYPES,
validator (sizeType, params) {
// 非必传的参数,不符合预期时处理为默认值。
const length = sizeType.length
if (!length) {
params.sizeType = SIZE_TYPES
} else if (typeof sizeType === 'string') {
if (!~SIZE_TYPES.indexOf(sizeType)) {
params.sizeType = SIZE_TYPES
}
} else {
for (let i = 0; i < length; i++) {
if (typeof sizeType[i] !== 'string' || !~SIZE_TYPES.indexOf(sizeType[i])) {
params.sizeType = SIZE_TYPES
break
}
}
}
sizeType = typeof sizeType === 'string' ? [sizeType] : sizeType
sizeType = sizeType.filter(sizeType => SIZE_TYPES.includes(sizeType))
params.sizeType = sizeType.length ? sizeType : SIZE_TYPES
}
},
sourceType: {
......@@ -40,17 +27,8 @@ export const chooseImage = {
required: false,
default: SOURCE_TYPES,
validator (sourceType, params) {
const length = sourceType.length
if (!length) {
params.sourceType = SOURCE_TYPES
} else {
for (let i = 0; i < length; i++) {
if (typeof sourceType[i] !== 'string' || !~SOURCE_TYPES.indexOf(sourceType[i])) {
params.sourceType = SOURCE_TYPES
break
}
}
}
sourceType = sourceType.filter(sourceType => SOURCE_TYPES.includes(sourceType))
params.sourceType = sourceType.length ? sourceType : SOURCE_TYPES
}
}
}
}
......@@ -6,17 +6,16 @@ export const chooseVideo = {
required: false,
default: SOURCE_TYPES,
validator (sourceType, params) {
const length = sourceType.length
if (!length) {
params.sourceType = SOURCE_TYPES
} else {
for (let i = 0; i < length; i++) {
if (typeof sourceType[i] !== 'string' || !~SOURCE_TYPES.indexOf(sourceType[i])) {
params.sourceType = SOURCE_TYPES
break
}
}
}
sourceType = sourceType.filter(sourceType => SOURCE_TYPES.includes(sourceType))
params.sourceType = sourceType.length ? sourceType : SOURCE_TYPES
}
},
maxDuration: {
type: Number,
default: 60
},
camera: {
type: String,
default: 'back'
}
}
}
......@@ -2,7 +2,7 @@ module.exports = [
'uni-app',
'uni-layout',
'uni-content',
'uni-main',
'uni-main',
'uni-top-window',
'uni-left-window',
'uni-right-window',
......@@ -58,6 +58,5 @@ module.exports = [
'uni-textarea',
'uni-video',
'uni-view',
'uni-web-view',
'uni-match-media'
'uni-web-view'
]
......@@ -257,15 +257,11 @@ var methods3 = ['setFillStyle', 'setTextAlign', 'setStrokeStyle', 'setGlobalAlph
'setTextBaseline', 'setLineDash'
]
var tempCanvas
function getTempCanvas (width = 0, height = 0) {
if (!tempCanvas) {
tempCanvas = document.createElement('canvas')
}
tempCanvas.width = width
tempCanvas.height = height
return tempCanvas
function measureText (text, font) {
const canvas = document.createElement('canvas')
const c2d = canvas.getContext('2d')
c2d.font = font
return c2d.measureText(text).width || 0
}
function TextMetrics (width) {
......@@ -335,16 +331,14 @@ export class CanvasContext {
measureText (text, callback) {
const font = this.state.font
if (__PLATFORM__ === 'h5') {
const canvas = getTempCanvas()
const c2d = canvas.getContext('2d')
c2d.font = font
const textMetrics = new TextMetrics(c2d.measureText(text).width || 0)
const width = measureText(text, font)
const textMetrics = new TextMetrics(width)
if (typeof callback === 'function') {
setTimeout(() => callback(textMetrics), 0)
}
return textMetrics
} else {
const textMetrics = new TextMetrics(0)
let textMetrics = new TextMetrics(0)
if (typeof callback === 'function') {
const callbackId = canvasEventCallbacks.push(function ({ width }) {
callback(new TextMetrics(width))
......@@ -355,7 +349,14 @@ export class CanvasContext {
callbackId
})
} else {
console.error('warning: measureText missing required arguments: callback')
const webview = plus.webview.getWebviewById(String(this.pageId))
if (webview && webview.evalJSSync) {
const js = `(${measureText.toString()})(${JSON.stringify(text)},${JSON.stringify(font)})`
const width = webview.evalJSSync(js) || 0
textMetrics = new TextMetrics(width)
} else {
console.error('warning: measureText missing required arguments: callback')
}
}
return textMetrics
}
......
import {
invoke
} from 'uni-core/service/bridge'
import {
onMethod
} from '../../platform'
function on (method) {
const callbacks = []
onMethod(method, data => {
callbacks.forEach(callbackId => {
invoke(callbackId, data)
})
})
return function (callbackId) {
callbacks.push(callbackId)
}
}
export const onBluetoothDeviceFound = on('onBluetoothDeviceFound')
export const onBluetoothAdapterStateChange = on('onBluetoothAdapterStateChange')
export const onBLEConnectionStateChange = on('onBLEConnectionStateChange')
export const onBLECharacteristicValueChange = on('onBLECharacteristicValueChange')
......@@ -41,7 +41,7 @@ export function requestMediaQueryObserver ({
throw new Error(`Not Found:Page[${pageId}]`)
}
const pageVm = page.$vm
// const pageVm = page.$vm
// 创建一个媒体查询对象
const mediaQueryObserver = mediaQueryObservers[reqId] = window.matchMedia(handleMediaQueryStr(options))
......@@ -51,7 +51,7 @@ export function requestMediaQueryObserver ({
UniViewJSBridge.publishHandler('onRequestMediaQueryObserver', {
reqId,
res: e.matches
}, pageVm.$page.id)
}, pages[pages.length - 1].$page.id)
}
listener(mediaQueryObserver) // 监听前执行一次媒体查询
......
......@@ -107,10 +107,7 @@ export default {
this._images = {}
},
mounted () {
this._resize({
width: this.$refs.sensor.$el.offsetWidth,
height: this.$refs.sensor.$el.offsetHeight
})
this._resize()
},
beforeDestroy () {
const canvas = this.$refs.canvas
......@@ -131,10 +128,10 @@ export default {
if (canvas.width > 0 && canvas.height > 0) {
var context = canvas.getContext('2d')
var imageData = context.getImageData(0, 0, canvas.width, canvas.height)
wrapper(this.$refs.canvas)
wrapper(canvas)
context.putImageData(imageData, 0, 0)
} else {
wrapper(this.$refs.canvas)
wrapper(canvas)
}
},
_touchmove (event) {
......
<template>
<uni-match-media
v-show="MediaQueryListRes"
v-on="$listeners"
>
<slot />
</uni-match-media>
</template>
<script>
export default {
name: 'MatchMedia',
props: {
width: {
type: [Number, String],
default: ''
},
minWidth: {
type: [Number, String],
default: ''
},
maxWidth: {
type: [Number, String],
default: ''
},
height: {
type: [Number, String],
default: ''
},
minHeight: {
type: [Number, String],
default: ''
},
maxHeight: {
type: [Number, String],
default: ''
},
orientation: {
type: String,
default: ''
}
},
data () {
return {
MediaQueryListRes: true,
mql: null
}
},
computed: {
handleMediaQueryStr () {
let mediaQueryStr = []
const { $props } = this
const propsMenu = [
'width',
'minWidth',
'maxWidth',
'height',
'minHeight',
'maxHeight',
'orientation'
]
for (const item of propsMenu) {
if (item !== 'orientation' && $props[item] !== '' && Number($props[item]) >= 0) {
mediaQueryStr.push(`(${this.humpToLine(item)}: ${Number($props[item])}px)`)
}
if (item === 'orientation' && $props[item]) {
mediaQueryStr.push(`(${this.humpToLine(item)}: ${$props[item]})`)
}
}
mediaQueryStr = mediaQueryStr.join(' and ')
return mediaQueryStr
}
},
watch: {
handleMediaQueryStr: 'replaceListener'
},
mounted () {
this.mql = window.matchMedia(this.handleMediaQueryStr)
this.handleMediaQuery(this.mql)
this.mql.addListener(this.handleMediaQuery)
},
beforeDestroy () {
this.mql.removeListener(this.handleMediaQuery)
},
methods: {
handleMediaQuery (e) {
if (e.matches) {
this.MediaQueryListRes = true
} else {
this.MediaQueryListRes = false
}
},
replaceListener () {
this.mql.removeListener(this.handleMediaQuery)
this.mql = window.matchMedia(this.handleMediaQueryStr)
this.handleMediaQuery(this.mql)
this.mql.addListener(this.handleMediaQuery)
},
humpToLine (name) {
return name.replace(/([A-Z])/g, '-$1').toLowerCase()
}
}
}
</script>
<style>
uni-match-media {
display: block;
}
uni-match-media[hidden] {
display: none;
}
</style>
import {
invoke,
publish
} from '../../bridge'
warpPlusEvent,
warpPlusMethod
} from '../util'
/**
* 执行蓝牙相关方法
*/
function bluetoothExec (method, callbackId, data = {}, beforeSuccess) {
var deviceId = data.deviceId
export const onBluetoothDeviceFound = warpPlusEvent(plus.bluetooth, 'onBluetoothDeviceFound')
export const onBluetoothAdapterStateChange = warpPlusEvent(plus.bluetooth, 'onBluetoothAdapterStateChange')
export const onBLEConnectionStateChange = warpPlusEvent(plus.bluetooth, 'onBLEConnectionStateChange')
export const onBLECharacteristicValueChange = warpPlusEvent(plus.bluetooth, 'onBLECharacteristicValueChange')
function toUpperCase (options = {}) {
const deviceId = options.deviceId
if (deviceId) {
data.deviceId = deviceId.toUpperCase()
options.deviceId = deviceId.toUpperCase()
}
var serviceId = data.serviceId
const serviceId = options.serviceId
if (serviceId) {
data.serviceId = serviceId.toUpperCase()
options.serviceId = serviceId.toUpperCase()
}
plus.bluetooth[method.replace('Changed', 'Change')](Object.assign(data, {
success (data) {
if (typeof beforeSuccess === 'function') {
beforeSuccess(data)
}
invoke(callbackId, Object.assign({}, data, {
errMsg: `${method}:ok`,
code: undefined,
message: undefined
}))
},
fail (error = {}) {
invoke(callbackId, {
errMsg: `${method}:fail ${error.message || ''}`,
errCode: error.code || 0
})
}
}))
}
/**
* 监听蓝牙相关事件
*/
function bluetoothOn (method, beforeSuccess) {
plus.bluetooth[method.replace('Changed', 'Change')](function (data) {
if (typeof beforeSuccess === 'function') {
beforeSuccess(data)
}
publish(method, Object.assign({}, data, {
code: undefined,
message: undefined
}))
})
return true
}
var onBluetoothAdapterStateChange
var onBluetoothDeviceFound
var onBLEConnectionStateChange
var onBLECharacteristicValueChange
export function openBluetoothAdapter (data, callbackId) {
onBluetoothAdapterStateChange = onBluetoothAdapterStateChange || bluetoothOn('onBluetoothAdapterStateChange')
bluetoothExec('openBluetoothAdapter', callbackId)
}
export function closeBluetoothAdapter (data, callbackId) {
bluetoothExec('closeBluetoothAdapter', callbackId)
}
export function getBluetoothAdapterState (data, callbackId) {
bluetoothExec('getBluetoothAdapterState', callbackId)
}
export function startBluetoothDevicesDiscovery (data, callbackId) {
onBluetoothDeviceFound = onBluetoothDeviceFound || bluetoothOn('onBluetoothDeviceFound')
bluetoothExec('startBluetoothDevicesDiscovery', callbackId, data)
}
export function stopBluetoothDevicesDiscovery (data, callbackId) {
bluetoothExec('stopBluetoothDevicesDiscovery', callbackId)
}
export function getBluetoothDevices (data, callbackId) {
bluetoothExec('getBluetoothDevices', callbackId, {})
}
export function getConnectedBluetoothDevices (data, callbackId) {
bluetoothExec('getConnectedBluetoothDevices', callbackId, data)
}
export function createBLEConnection (data, callbackId) {
onBLEConnectionStateChange = onBLEConnectionStateChange || bluetoothOn('onBLEConnectionStateChange')
bluetoothExec('createBLEConnection', callbackId, data)
}
export function closeBLEConnection (data, callbackId) {
bluetoothExec('closeBLEConnection', callbackId, data)
}
export function getBLEDeviceServices (data, callbackId) {
bluetoothExec('getBLEDeviceServices', callbackId, data)
}
export function getBLEDeviceCharacteristics (data, callbackId) {
bluetoothExec('getBLEDeviceCharacteristics', callbackId, data)
}
export function notifyBLECharacteristicValueChange (data, callbackId) {
onBLECharacteristicValueChange = onBLECharacteristicValueChange || bluetoothOn('onBLECharacteristicValueChange')
bluetoothExec('notifyBLECharacteristicValueChange', callbackId, data)
}
export function notifyBLECharacteristicValueChanged (data, callbackId) {
onBLECharacteristicValueChange = onBLECharacteristicValueChange || bluetoothOn('onBLECharacteristicValueChange')
bluetoothExec('notifyBLECharacteristicValueChanged', callbackId, data)
}
export function readBLECharacteristicValue (data, callbackId) {
onBLECharacteristicValueChange = onBLECharacteristicValueChange || bluetoothOn('onBLECharacteristicValueChange')
bluetoothExec('readBLECharacteristicValue', callbackId, data)
}
export function writeBLECharacteristicValue (data, callbackId) {
bluetoothExec('writeBLECharacteristicValue', callbackId, data)
}
export function setBLEMTU (data, callbackId) {
bluetoothExec('setBLEMTU', callbackId, data)
}
export function getBLEDeviceRSSI (data, callbackId) {
bluetoothExec('getBLEDeviceRSSI', callbackId, data)
}
return options
}
export const openBluetoothAdapter = warpPlusMethod(plus.bluetooth, 'openBluetoothAdapter')
export const closeBluetoothAdapter = warpPlusMethod(plus.bluetooth, 'closeBluetoothAdapter')
export const getBluetoothAdapterState = warpPlusMethod(plus.bluetooth, 'getBluetoothAdapterState')
export const startBluetoothDevicesDiscovery = warpPlusMethod(plus.bluetooth, 'startBluetoothDevicesDiscovery', toUpperCase)
export const stopBluetoothDevicesDiscovery = warpPlusMethod(plus.bluetooth, 'stopBluetoothDevicesDiscovery')
export const getBluetoothDevices = warpPlusMethod(plus.bluetooth, 'getBluetoothDevices')
export const getConnectedBluetoothDevices = warpPlusMethod(plus.bluetooth, 'getConnectedBluetoothDevices', toUpperCase)
export const createBLEConnection = warpPlusMethod(plus.bluetooth, 'createBLEConnection', toUpperCase)
export const closeBLEConnection = warpPlusMethod(plus.bluetooth, 'closeBLEConnection', toUpperCase)
export const getBLEDeviceServices = warpPlusMethod(plus.bluetooth, 'getBLEDeviceServices', toUpperCase)
export const getBLEDeviceCharacteristics = warpPlusMethod(plus.bluetooth, 'getBLEDeviceCharacteristics', toUpperCase)
export const notifyBLECharacteristicValueChange = warpPlusMethod(plus.bluetooth, 'notifyBLECharacteristicValueChange', toUpperCase)
export const readBLECharacteristicValue = warpPlusMethod(plus.bluetooth, 'readBLECharacteristicValue', toUpperCase)
export const writeBLECharacteristicValue = warpPlusMethod(plus.bluetooth, 'writeBLECharacteristicValue', toUpperCase)
export const setBLEMTU = warpPlusMethod(plus.bluetooth, 'setBLEMTU', toUpperCase)
export const getBLEDeviceRSSI = warpPlusMethod(plus.bluetooth, 'getBLEDeviceRSSI', toUpperCase)
import {
invoke
} from '../../bridge'
warpPlusEvent,
warpPlusMethod
} from '../util'
export function onBeaconUpdate (callbackId) {
plus.ibeacon.onBeaconUpdate(data => invoke(callbackId, data))
}
export const onBeaconUpdate = warpPlusEvent(plus.ibeacon, 'onBeaconUpdate')
export const onBeaconServiceChange = warpPlusEvent(plus.ibeacon, 'onBeaconServiceChange')
export function onBeaconServiceChange (callbackId) {
plus.ibeacon.onBeaconServiceChange(data => invoke(callbackId, data))
}
export const onBeaconServiceChanged = onBeaconServiceChange
export function getBeacons (params, callbackId) {
plus.ibeacon.getBeacons({
success: (result) => {
invoke(callbackId, {
errMsg: 'getBeacons:ok',
beacons: result.beacons
})
},
fail: (error) => {
invoke(callbackId, {
errMsg: 'getBeacons:fail:' + error.message
})
}
})
}
export function startBeaconDiscovery ({
uuids,
ignoreBluetoothAvailable = false
}, callbackId) {
plus.ibeacon.startBeaconDiscovery({
uuids,
ignoreBluetoothAvailable,
success: (result) => {
invoke(callbackId, {
errMsg: 'startBeaconDiscovery:ok',
beacons: result.beacons
})
},
fail: (error) => {
invoke(callbackId, {
errMsg: 'startBeaconDiscovery:fail:' + error.message
})
}
})
}
export function stopBeaconDiscovery (params, callbackId) {
plus.ibeacon.stopBeaconDiscovery({
success: (result) => {
invoke(callbackId, Object.assign(result, {
errMsg: 'stopBeaconDiscovery:ok'
}))
},
fail: (error) => {
invoke(callbackId, {
errMsg: 'stopBeaconDiscovery:fail:' + error.message
})
}
})
}
export const getBeacons = warpPlusMethod(plus.ibeacon, 'getBeacons')
export const startBeaconDiscovery = warpPlusMethod(plus.ibeacon, 'startBeaconDiscovery')
export const stopBeaconDiscovery = warpPlusMethod(plus.ibeacon, 'stopBeaconDiscovery')
import {
getRealPath
warpPlusMethod,
warpPlusErrorCallback,
getFileName
} from '../util'
import {
......@@ -8,67 +10,39 @@ import {
const SAVED_DIR = 'uniapp_save'
const SAVE_PATH = `_doc/${SAVED_DIR}`
const REGEX_FILENAME = /^.*[/]/
function getSavedFileDir (success, fail) {
fail = fail || function () {}
fail = fail || function () { }
plus.io.requestFileSystem(plus.io.PRIVATE_DOC, fs => { // 请求_doc fs
fs.root.getDirectory(SAVED_DIR, { // 获取文件保存目录对象
create: true
}, dir => {
success(dir)
}, err => {
fail('目录[' + SAVED_DIR + ']创建失败' + err.message)
})
}, err => {
fail('目录[_doc]读取失败' + err.message)
})
}, success, fail)
}, fail)
}
export function saveFile ({
tempFilePath
} = {}, callbackId) {
let fileName = tempFilePath.replace(REGEX_FILENAME, '')
if (fileName) {
let extName = ''
if (~fileName.indexOf('.')) {
extName = '.' + fileName.split('.').pop()
}
const errorCallback = warpPlusErrorCallback(callbackId, 'saveFile')
let fileName = getFileName(tempFilePath)
fileName = `${Date.now()}_${fileName}`
fileName = (+new Date()) + '' + extName
plus.io.resolveLocalFileSystemURL(getRealPath(tempFilePath), entry => { // 读取临时文件 FileEntry
getSavedFileDir(dir => {
entry.copyTo(dir, fileName, () => { // 复制临时文件 FileEntry,为了避免把相册里的文件删除,使用 copy,微信中是要删除临时文件的
const savedFilePath = SAVE_PATH + '/' + fileName
invoke(callbackId, {
errMsg: 'saveFile:ok',
savedFilePath
})
}, err => {
invoke(callbackId, {
errMsg: 'saveFile:fail 保存文件[' + tempFilePath +
'] copyTo 失败:' + err.message
})
})
}, message => {
plus.io.resolveLocalFileSystemURL(tempFilePath, entry => { // 读取临时文件 FileEntry
getSavedFileDir(dir => {
entry.copyTo(dir, fileName, () => { // 复制临时文件 FileEntry,为了避免把相册里的文件删除,使用 copy,微信中是要删除临时文件的
const savedFilePath = SAVE_PATH + '/' + fileName
invoke(callbackId, {
errMsg: 'saveFile:fail ' + message
errMsg: 'saveFile:ok',
savedFilePath
})
})
}, err => {
invoke(callbackId, {
errMsg: 'saveFile:fail 文件[' + tempFilePath + ']读取失败' + err.message
})
})
} else {
return {
errMsg: 'saveFile:fail 文件名[' + tempFilePath + ']不存在'
}
}
}, errorCallback)
}, errorCallback)
}, errorCallback)
}
export function getSavedFileList (options, callbackId) {
const errorCallback = warpPlusErrorCallback(callbackId, 'getSavedFileList')
getSavedFileDir(entry => {
var reader = entry.createReader()
......@@ -88,11 +62,7 @@ export function getSavedFileList (options, callbackId) {
fileList
})
}
}, error => {
invoke(callbackId, {
errMsg: 'getSavedFileList:fail ' + error.message
})
}, false)
}, errorCallback, false)
})
} else {
invoke(callbackId, {
......@@ -100,82 +70,38 @@ export function getSavedFileList (options, callbackId) {
fileList
})
}
}, error => {
invoke(callbackId, {
errMsg: 'getSavedFileList:fail ' + error.message
})
})
}, message => {
invoke(callbackId, {
errMsg: 'getSavedFileList:fail ' + message
})
})
}, errorCallback)
}, errorCallback)
}
export function getFileInfo ({
filePath,
digestAlgorithm = 'md5'
} = {}, callbackId) {
// TODO 计算文件摘要
plus.io.resolveLocalFileSystemURL(getRealPath(filePath), entry => {
entry.getMetadata(meta => {
invoke(callbackId, {
errMsg: 'getFileInfo:ok',
size: meta.size,
digestAlgorithm: ''
})
}, err => {
invoke(callbackId, {
errMsg: 'getFileInfo:fail 文件[' +
filePath +
'] getMetadata 失败:' + err.message
})
})
}, err => {
invoke(callbackId, {
errMsg: 'getFileInfo:fail 文件[' + filePath + ']读取失败:' + err.message
})
})
}
export const getFileInfo = warpPlusMethod(plus.io, 'getFileInfo')
export function getSavedFileInfo ({
filePath
} = {}, callbackId) {
plus.io.resolveLocalFileSystemURL(getRealPath(filePath), entry => {
const errorCallback = warpPlusErrorCallback(callbackId, 'getSavedFileInfo')
plus.io.resolveLocalFileSystemURL(filePath, entry => {
entry.getMetadata(meta => {
invoke(callbackId, {
createTime: meta.modificationTime.getTime(),
size: meta.size,
errMsg: 'getSavedFileInfo:ok'
})
}, error => {
invoke(callbackId, {
errMsg: 'getSavedFileInfo:fail ' + error.message
})
}, false)
}, () => {
invoke(callbackId, {
errMsg: 'getSavedFileInfo:fail file not find'
})
})
}, errorCallback, false)
}, errorCallback)
}
export function removeSavedFile ({
filePath
} = {}, callbackId) {
plus.io.resolveLocalFileSystemURL(getRealPath(filePath), entry => {
const errorCallback = warpPlusErrorCallback(callbackId, 'removeSavedFile')
plus.io.resolveLocalFileSystemURL(filePath, entry => {
entry.remove(() => {
invoke(callbackId, {
errMsg: 'removeSavedFile:ok'
})
}, err => {
invoke(callbackId, {
errMsg: 'removeSavedFile:fail 文件[' + filePath + ']删除失败:' + err.message
})
})
}, () => {
invoke(callbackId, {
errMsg: 'removeSavedFile:fail file not find'
})
})
}, errorCallback)
}, errorCallback)
}
......@@ -6,6 +6,11 @@ import {
invoke
} from '../../bridge'
import {
warpPlusErrorCallback,
getFileName
} from '../util'
/**
* 获取文件信息
* @param {string} filePath 文件路径
......@@ -14,142 +19,116 @@ import {
function getFileInfo (filePath) {
return new Promise((resolve, reject) => {
plus.io.resolveLocalFileSystemURL(filePath, function (entry) {
entry.getMetadata(function (meta) {
resolve({
size: meta.size
})
}, reject, false)
entry.getMetadata(resolve, reject, false)
}, reject)
})
}
const invokeChooseImage = function (callbackId, type, sizeType, tempFilePaths = []) {
if (!tempFilePaths.length) {
invoke(callbackId, {
code: sizeType,
errMsg: `chooseImage:${type}`
function compressImage (tempFilePath) {
const dstPath = `${TEMP_PATH}/compressed/${Date.now()}_${getFileName(tempFilePath)}`
return new Promise((resolve, reject) => {
plus.nativeUI.showWaiting()
plus.zip.compressImage({
src: tempFilePath,
dst: dstPath,
overwrite: true
}, () => {
plus.nativeUI.closeWaiting()
resolve(dstPath)
}, (error) => {
plus.nativeUI.closeWaiting()
reject(error)
})
return
}
var tempFiles = []
// plus.zip.compressImage 压缩文件并发调用在iOS端容易出现问题(图像错误、闪退),改为队列执行
tempFilePaths.reduce((promise, tempFilePath, index, array) => {
return promise
.then(() => {
return getFileInfo(tempFilePath)
})
.then(fileInfo => {
var size = fileInfo.size
})
}
export function chooseImage ({
count,
sizeType,
sourceType
} = {}, callbackId) {
const errorCallback = warpPlusErrorCallback(callbackId, 'chooseImage', 'cancel')
function successCallback (paths) {
const tempFiles = []
const tempFilePaths = []
// plus.zip.compressImage 压缩文件并发调用在iOS端容易出现问题(图像错误、闪退),改为队列执行
paths.reduce((promise, path) => {
return promise.then(() => {
return getFileInfo(path)
}).then(fileInfo => {
const size = fileInfo.size
// 压缩阈值 0.5 兆
var threshold = 1024 * 1024 * 0.5
const THRESHOLD = 1024 * 1024 * 0.5
// 判断是否需要压缩
if ((sizeType.indexOf('compressed') >= 0 && sizeType.indexOf('original') < 0) || (((
sizeType.indexOf(
'compressed') < 0 && sizeType.indexOf('original') < 0) || (sizeType
.indexOf('compressed') >= 0 && sizeType.indexOf(
'original') >= 0)) && size > threshold)) {
return new Promise((resolve, reject) => {
var dstPath = TEMP_PATH + '/compressed/' + Date.now() + (
tempFilePath.match(/\.\S+$/) || [''])[0]
plus.nativeUI.showWaiting()
plus.zip.compressImage({
src: tempFilePath,
dst: dstPath,
overwrite: true
}, () => {
resolve(dstPath)
}, (error) => {
reject(error)
})
if (sizeType.includes('compressed') && size > THRESHOLD) {
return compressImage(path).then(dstPath => {
path = dstPath
return getFileInfo(path)
})
.then(dstPath => {
array[index] = tempFilePath = dstPath
return getFileInfo(tempFilePath)
})
.then(fileInfo => {
return tempFiles.push({
path: tempFilePath,
size: fileInfo.size
})
})
}
return tempFiles.push({
path: tempFilePath,
size: size
return fileInfo
}).then(({ size }) => {
tempFilePaths.push(path)
tempFiles.push({
path,
size
})
})
}, Promise.resolve())
.then(() => {
plus.nativeUI.closeWaiting()
}, Promise.resolve()).then(() => {
invoke(callbackId, {
errMsg: `chooseImage:${type}`,
errMsg: 'chooseImage:ok',
tempFilePaths,
tempFiles
})
}).catch(() => {
plus.nativeUI.closeWaiting()
invoke(callbackId, {
errMsg: `chooseImage:${type}`
}).catch(errorCallback)
}
function openCamera () {
const camera = plus.camera.getCamera()
camera.captureImage(path => successCallback([path]),
errorCallback, {
filename: TEMP_PATH + '/camera/',
resolution: 'high'
})
}
function openAlbum () {
plus.gallery.pick(({ files }) => successCallback(files), errorCallback, {
maximum: count,
multiple: true,
system: false,
filename: TEMP_PATH + '/gallery/'
})
}
const openCamera = function (callbackId, sizeType) {
const camera = plus.camera.getCamera()
camera.captureImage(e => invokeChooseImage(callbackId, 'ok', sizeType, [e]),
e => invokeChooseImage(callbackId, 'fail', 1), {
filename: TEMP_PATH + '/camera/',
resolution: 'high'
})
}
const openAlbum = function (callbackId, sizeType, count) {
// TODO Android 需要拷贝到 temp 目录
plus.gallery.pick(e => invokeChooseImage(callbackId, 'ok', sizeType, e.files.map(file => {
return file
})), e => {
invokeChooseImage(callbackId, 'fail', 2)
}, {
maximum: count,
multiple: true,
system: false,
filename: TEMP_PATH + '/gallery/'
})
}
}
export function chooseImage ({
count = 9,
sizeType = ['original', 'compressed'],
sourceType = ['album', 'camera']
} = {}, callbackId) {
let fallback = true
if (sourceType.length === 1) {
if (sourceType[0] === 'album') {
fallback = false
openAlbum(callbackId, sizeType, count)
} else if (sourceType[0] === 'camera') {
fallback = false
openCamera(callbackId, sizeType)
if (sourceType.includes('album')) {
openAlbum()
return
} else if (sourceType.includes('camera')) {
openCamera()
return
}
}
if (fallback) {
plus.nativeUI.actionSheet({
cancel: '取消',
buttons: [{
title: '拍摄'
}, {
title: '从手机相册选择'
}]
}, (e) => {
switch (e.index) {
case 0:
invokeChooseImage(callbackId, 'fail', 0)
break
case 1:
openCamera(callbackId, sizeType)
break
case 2:
openAlbum(callbackId, sizeType, count)
break
}
})
}
plus.nativeUI.actionSheet({
cancel: '取消',
buttons: [{
title: '拍摄'
}, {
title: '从手机相册选择'
}]
}, (e) => {
switch (e.index) {
case 1:
openCamera()
break
case 2:
openAlbum()
break
default:
errorCallback()
break
}
})
}
......@@ -6,92 +6,79 @@ import {
invoke
} from '../../bridge'
const invokeChooseVideo = function (callbackId, type, tempFilePath = '') {
const callbackResult = {
errMsg: `chooseVideo:${type}`,
tempFilePath: tempFilePath,
duration: 0,
size: 0,
height: 0,
width: 0
import {
warpPlusErrorCallback
} from '../util'
export function chooseVideo ({
sourceType,
maxDuration,
camera
} = {}, callbackId) {
const errorCallback = warpPlusErrorCallback(callbackId, 'chooseVideo', 'cancel')
function successCallback (tempFilePath = '') {
plus.io.getVideoInfo({
filePath: tempFilePath,
success (videoInfo) {
const result = {
errMsg: 'chooseVideo:ok',
tempFilePath: tempFilePath
}
result.size = videoInfo.size
result.duration = videoInfo.duration
result.width = videoInfo.width
result.height = videoInfo.height
invoke(callbackId, result)
},
errorCallback
})
}
if (type !== 'ok') {
invoke(callbackId, callbackResult)
return
function openAlbum () {
plus.gallery.pick(successCallback, errorCallback, {
filter: 'video',
system: false,
filename: TEMP_PATH + '/gallery/'
})
}
function openCamera () {
const plusCamera = plus.camera.getCamera()
plusCamera.startVideoCapture(successCallback, errorCallback, {
index: camera === 'front' ? 2 : 1,
videoMaximumDuration: maxDuration,
filename: TEMP_PATH + '/camera/'
})
}
plus.io.getVideoInfo({
filePath: tempFilePath,
success (videoInfo) {
callbackResult.size = videoInfo.size
callbackResult.duration = videoInfo.duration
callbackResult.width = videoInfo.width
callbackResult.height = videoInfo.height
invoke(callbackId, callbackResult)
},
fail () {
invoke(callbackId, callbackResult)
},
complete () {
invoke(callbackId, callbackResult)
}
})
}
const openCamera = function (callbackId, maxDuration, cameraIndex) {
const camera = plus.camera.getCamera()
camera.startVideoCapture(e => invokeChooseVideo(callbackId, 'ok', e), e => invokeChooseVideo(
callbackId, 'fail'), {
index: cameraIndex,
videoMaximumDuration: maxDuration,
filename: TEMP_PATH + '/camera/'
})
}
const openAlbum = function (callbackId) {
plus.gallery.pick(e => {
invokeChooseVideo(callbackId, 'ok', e)
}, e => invokeChooseVideo(callbackId, 'fail'), {
filter: 'video',
system: false,
filename: TEMP_PATH + '/gallery/'
})
}
export function chooseVideo ({
sourceType = ['album', 'camera'],
maxDuration = 60,
camera = 'back'
} = {}, callbackId) {
let fallback = true
const cameraIndex = (camera === 'front') ? 2 : 1
if (sourceType.length === 1) {
if (sourceType[0] === 'album') {
fallback = false
openAlbum(callbackId)
} else if (sourceType[0] === 'camera') {
fallback = false
openCamera(callbackId, maxDuration, cameraIndex)
if (sourceType.includes('album')) {
openAlbum()
return
} else if (sourceType.includes('camera')) {
openCamera()
return
}
}
if (fallback) {
plus.nativeUI.actionSheet({
cancel: '取消',
buttons: [{
title: '拍摄'
}, {
title: '从手机相册选择'
}]
}, e => {
switch (e.index) {
case 0:
invokeChooseVideo(callbackId, 'fail')
break
case 1:
openCamera(callbackId, maxDuration, cameraIndex)
break
case 2:
openAlbum(callbackId)
break
}
})
}
plus.nativeUI.actionSheet({
cancel: '取消',
buttons: [{
title: '拍摄'
}, {
title: '从手机相册选择'
}]
}, e => {
switch (e.index) {
case 1:
openCamera()
break
case 2:
openAlbum()
break
default:
errorCallback()
break
}
})
}
import {
invoke
} from '../../bridge'
warpPlusMethod
} from '../util'
export function getImageInfo ({
src
} = {}, callbackId) {
// fixed by hxy
plus.io.getImageInfo({
src,
success (imageInfo) {
invoke(callbackId, {
errMsg: 'getImageInfo:ok',
...imageInfo
})
},
fail () {
invoke(callbackId, {
errMsg: 'getImageInfo:fail'
})
}
})
}
export const getImageInfo = warpPlusMethod(plus.io, 'getImageInfo')
......@@ -149,9 +149,7 @@ export function showActionSheet ({
options.title = title
}
if (plus.os.name === 'iOS') {
options.cancel = ''
}
options.cancel = ''
plus.nativeUI.actionSheet(Object.assign(options, { popover }), (e) => {
if (e.index > 0) {
......
import {
invoke
} from '../bridge'
export {
isTabBarPage
} from '../bridge'
......@@ -162,3 +166,48 @@ export function getScreenInfo () {
screenHeight: Math.round(resolutionHeight)
}
}
export function warpPlusEvent (origin, name) {
return function (callbackId) {
origin[name](function (data) {
if (data) {
delete data.code
delete data.message
}
invoke(callbackId, data)
})
}
}
export function warpPlusErrorCallback (callbackId, neme, errMsg) {
return function errorCallback (error) {
error = error || {}
invoke(callbackId, {
errMsg: `${neme}:fail ${error.message || errMsg || ''}`,
errCode: error.code || 0
})
}
}
export function warpPlusMethod (origin, name, before) {
return function (options, callbackId) {
if (typeof before === 'function') {
options = before(options)
}
origin[name](Object.assign(options, {
success (data = {}) {
delete data.code
delete data.message
invoke(callbackId, Object.assign({}, data, {
errMsg: `${name}:ok`
}))
},
fail: warpPlusErrorCallback(callbackId, name)
}))
}
}
export function getFileName (path) {
const array = path.split('/')
return array[array.length - 1]
}
......@@ -6,7 +6,7 @@ import {
import {
MOUNTED_DATA,
UPDATED_DATA,
UPDATED_DATA,
VD_SYNC_VERSION
} from '../../../constants'
......@@ -137,6 +137,10 @@ function parseExternalClasses (clazz, vm) {
return clazz
}
function isNotSafeString (value) {
return value === 'null' || value === 'true' || value === 'false' || !isNaN(Number(value)) || (value.startsWith('[') && value.endsWith(']')) || (value.startsWith('{') && value.endsWith('}'))
}
function setData (id, name, value) {
switch (name) {
case B_CLASS:
......@@ -157,7 +161,7 @@ function setData (id, name, value) {
return setForData.call(this, id, value)
}
// TODO 暂时先传递 dataset 至 view 层(理论上不需要)
if (name.indexOf('a-data-') === 0) {
if (name.indexOf('a-data-') === 0 && (typeof value !== 'string' || isNotSafeString(value))) {
try {
value = JSON.stringify(value)
} catch (e) {}
......@@ -203,4 +207,4 @@ function setForData (id, value) {
(vForData[forIndex] || (vForData[forIndex] = {}))['k' + value.keyIndex] = key
}
return key
}
}
......@@ -46,15 +46,15 @@ export function initPicker () {
bounce: 'none',
cachemode: 'noCache'
})
pickerWebview.addEventListener('hide', () => {
_pickerHideCallback && _pickerHideCallback()
_pickerHideCallback = null
})
window.__pickerCallback = function () {
delete window.__pickerCallback
pickerWebviewCreated = true
}
}
pickerWebview.addEventListener('hide', () => {
_pickerHideCallback && _pickerHideCallback()
_pickerHideCallback = null
})
}
export function showPicker (data = {}, callback) {
......
import createMediaQueryObserver from '../../../mp-weixin/helpers/create-media-query-observer'
import {
isFn,
hasOwn
......@@ -104,3 +105,5 @@ export function createIntersectionObserver (component, options) {
}
return my.createIntersectionObserver(options)
}
export { createMediaQueryObserver }
import createMediaQueryObserver from '../../../mp-weixin/helpers/create-media-query-observer'
export function requestPayment (params) {
let parseError = false
if (typeof params.orderInfo === 'string') {
......@@ -15,3 +17,5 @@ export function requestPayment (params) {
swan.requestPolymerPayment(params)
}
}
export { createMediaQueryObserver }
import Vue from 'vue'
import {
initHooks,
initMocks
} from 'uni-wrapper/util'
const hooks = [
'onShow',
'onHide',
'onError',
'onPageNotFound'
]
export default function parseBaseApp (vm, {
mocks,
initRefs
}) {
if (vm.$options.store) {
Vue.prototype.$store = vm.$options.store
}
Vue.prototype.mpHost = __PLATFORM__
Vue.mixin({
beforeCreate () {
if (!this.$options.mpType) {
return
}
this.mpType = this.$options.mpType
this.$mp = {
data: {},
[this.mpType]: this.$options.mpInstance
}
this.$scope = this.$options.mpInstance
delete this.$options.mpType
delete this.$options.mpInstance
if (this.mpType !== 'app') {
initRefs(this)
initMocks(this, mocks)
}
}
})
const appOptions = {
onLaunch (args) {
if (this.$vm) { // 已经初始化过了,主要是为了百度,百度 onShow 在 onLaunch 之前
return
}
this.$vm = vm
this.$vm.$mp = {
app: this
}
this.$vm.$scope = this
// vm 上也挂载 globalData
this.$vm.globalData = this.globalData
this.$vm._isMounted = true
this.$vm.__call_hook('mounted', args)
this.$vm.__call_hook('onLaunch', args)
}
}
// 兼容旧版本 globalData
appOptions.globalData = vm.$options.globalData || {}
// 将 methods 中的方法挂在 getApp() 中
const methods = vm.$options.methods
if (methods) {
Object.keys(methods).forEach(name => {
appOptions[name] = methods[name]
})
}
initHooks(appOptions, hooks)
return appOptions
}
import parseBaseApp from './app-base-parser'
import {
mocks,
initRefs
} from './util'
import parseBaseApp from '../../../mp-weixin/runtime/wrapper/app-parser'
export default function parseApp (vm) {
return parseBaseApp(vm, {
mocks,
initRefs
})
}
return parseBaseApp(vm)
}
import Vue from 'vue'
import {
initData,
initSlots,
initVueIds,
handleEvent,
initBehaviors,
initProperties,
initVueComponent
} from 'uni-wrapper/util'
import {
handleLink,
initBehavior
} from './util'
export default function parseBaseComponent (vueComponentOptions, {
isPage,
initRelation
} = {}) {
const [VueComponent, vueOptions] = initVueComponent(Vue, vueComponentOptions)
const options = {
multipleSlots: true,
addGlobalClass: true
}
const componentOptions = {
options,
data: initData(vueOptions, Vue.prototype),
behaviors: initBehaviors(vueOptions, initBehavior),
properties: initProperties(vueOptions.props, false, vueOptions.__file),
lifetimes: {
attached () {
const properties = this.properties
const options = {
mpType: isPage.call(this) ? 'page' : 'component',
mpInstance: this,
propsData: properties
}
initVueIds(properties.vueId, this)
// 处理父子关系
initRelation.call(this, {
vuePid: this._$vuePid,
vueOptions: options
})
// 初始化 vue 实例
this.$vm = new VueComponent(options)
// 处理$slots,$scopedSlots(暂不支持动态变化$slots)
initSlots(this.$vm, properties.vueSlots)
// 触发首次 setData
this.$vm.$mount()
},
ready () {
// 当组件 props 默认值为 true,初始化时传入 false 会导致 created,ready 触发, 但 attached 不触发
// https://developers.weixin.qq.com/community/develop/doc/00066ae2844cc0f8eb883e2a557800
if (this.$vm) {
this.$vm._isMounted = true
this.$vm.__call_hook('mounted')
this.$vm.__call_hook('onReady')
} else {
// this.is && console.warn(this.is + ' is not attached')
}
},
detached () {
this.$vm.$destroy()
}
},
pageLifetimes: {
show (args) {
this.$vm && this.$vm.__call_hook('onPageShow', args)
},
hide () {
this.$vm && this.$vm.__call_hook('onPageHide')
},
resize (size) {
this.$vm && this.$vm.__call_hook('onPageResize', size)
}
},
methods: {
__l: handleLink,
__e: handleEvent
}
}
if (Array.isArray(vueOptions.wxsCallMethods)) {
vueOptions.wxsCallMethods.forEach(callMethod => {
componentOptions.methods[callMethod] = function (args) {
return this.$vm[callMethod](args)
}
})
}
if (isPage) {
return componentOptions
}
return [componentOptions, VueComponent]
}
import parseBaseComponent from './component-base-parser'
import {
isPage,
initRelation
} from './util'
import parseBaseComponent from '../../../mp-weixin/runtime/wrapper/component-parser'
export default function parseComponent (vueComponentOptions) {
return parseBaseComponent(vueComponentOptions, {
isPage,
initRelation
})
}
return parseBaseComponent(vueComponentOptions)
}
import {
initHooks,
PAGE_EVENT_HOOKS
} from 'uni-wrapper/util'
import parseComponent from 'uni-platform/runtime/wrapper/component-parser'
const hooks = [
'onShow',
'onHide',
'onUnload'
]
hooks.push(...PAGE_EVENT_HOOKS)
export default function parseBasePage (vuePageOptions, {
isPage,
initRelation
}) {
const pageOptions = parseComponent(vuePageOptions, {
isPage,
initRelation
})
initHooks(pageOptions.methods, hooks, vuePageOptions)
pageOptions.methods.onLoad = function (args) {
this.$vm.$mp.query = args // 兼容 mpvue
this.$vm.__call_hook('onLoad', args)
}
return pageOptions
}
import parseBasePage from './page-base-parser'
import {
isPage,
initRelation
} from './util'
import parseBasePage from '../../../mp-weixin/runtime/wrapper/page-parser'
export default function parsePage (vuePageOptions) {
return parseBasePage(vuePageOptions, {
isPage,
initRelation
})
}
return parseBasePage(vuePageOptions)
}
/* 快手也使用__wxExparserNodeId__和__wxWebviewId__ */
export const mocks = ['__route__', '__wxExparserNodeId__', '__wxWebviewId__']
export function findVmByVueId (vm, vuePid) {
const $children = vm.$children
// 优先查找直属
let parentVm = $children.find(childVm => childVm.$scope._$vueId === vuePid)
if (parentVm) {
return parentVm
}
// 反向递归查找
for (let i = $children.length - 1; i >= 0; i--) {
parentVm = findVmByVueId($children[i], vuePid)
if (parentVm) {
return parentVm
}
}
}
export function initBehavior (options) {
return Behavior(options)
}
export function isPage () {
return !!this.route
}
export function initRelation (detail) {
this.triggerEvent('__l', detail)
}
export function initRefs (vm) {
const mpInstance = vm.$scope
Object.defineProperty(vm, '$refs', {
get () {
const $refs = {}
const components = mpInstance.selectAllComponents('.vue-ref')
components.forEach(component => {
const ref = component.dataset.ref
$refs[ref] = component.$vm || component
})
const forComponents = mpInstance.selectAllComponents('.vue-ref-in-for')
forComponents.forEach(component => {
const ref = component.dataset.ref
if (!$refs[ref]) {
$refs[ref] = []
}
$refs[ref].push(component.$vm || component)
})
return $refs
}
})
}
export function handleLink (event) {
const {
vuePid,
vueOptions
} = event.detail || event.value // detail 是微信,value 是百度(dipatch)
let parentVm
if (vuePid) {
parentVm = findVmByVueId(this.$vm, vuePid)
}
if (!parentVm) {
parentVm = this.$vm
}
vueOptions.parent = parentVm
}
import createMediaQueryObserver from '../../../mp-weixin/helpers/create-media-query-observer'
export { createMediaQueryObserver }
import createMediaQueryObserver from '../../../mp-weixin/helpers/create-media-query-observer'
export { createMediaQueryObserver }
export default function createMediaQueryObserver () {
const mediaQueryObserver = {}
const {
windowWidth,
windowHeight
} = __GLOBAL__.getSystemInfoSync()
const orientation = windowWidth < windowHeight ? 'portrait' : 'landscape'
mediaQueryObserver.observe = (options, callback) => {
let matches = false
for (const item in options) {
const itemValue = item === 'orientation' ? options[item] : Number(options[item])
if (options[item] !== '') {
if (item === 'width') {
if (itemValue === windowWidth) {
matches = true
} else {
matches = false
callback(matches)
return matches
}
}
if (item === 'minWidth') {
if (windowWidth >= itemValue) {
matches = true
} else {
matches = false
callback(matches)
return matches
}
}
if (item === 'maxWidth') {
if (windowWidth <= itemValue) {
matches = true
} else {
matches = false
callback(matches)
return matches
}
}
if (item === 'height') {
if (itemValue === windowHeight) {
matches = true
} else {
matches = false
callback(matches)
return matches
}
}
if (item === 'minHeight') {
if (windowHeight >= itemValue) {
matches = true
} else {
matches = false
callback(matches)
return matches
}
}
if (item === 'maxHeight') {
if (windowHeight <= itemValue) {
matches = true
} else {
matches = false
callback(matches)
return matches
}
}
if (item === 'orientation') {
if (options[item] === orientation) {
matches = true
} else {
matches = false
callback(matches)
return matches
}
}
}
}
callback(matches)
return matches
}
mediaQueryObserver.disconnect = () => {
}
return mediaQueryObserver
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册