@mpxjs/api-proxy 2.9.71 → 2.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/@types/index.d.ts CHANGED
@@ -98,6 +98,7 @@ export const clearStorage: WechatMiniprogram.Wx['clearStorage']
98
98
  export const clearStorageSync: WechatMiniprogram.Wx['clearStorageSync']
99
99
  export const getSystemInfo: WechatMiniprogram.Wx['getSystemInfo']
100
100
  export const getSystemInfoSync: WechatMiniprogram.Wx['getSystemInfoSync']
101
+ export const getWindowInfo: WechatMiniprogram.Wx['getWindowInfo']
101
102
  export const setTabBarItem: WechatMiniprogram.Wx['setTabBarItem']
102
103
  export const setTabBarStyle: WechatMiniprogram.Wx['setTabBarStyle']
103
104
  export const showTabBar: WechatMiniprogram.Wx['showTabBar']
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mpxjs/api-proxy",
3
- "version": "2.9.71",
3
+ "version": "2.10.0",
4
4
  "description": "convert miniprogram API at each end",
5
5
  "module": "src/index.js",
6
6
  "types": "@types/index.d.ts",
@@ -37,11 +37,10 @@
37
37
  },
38
38
  "homepage": "https://github.com/didi/mpx#readme",
39
39
  "dependencies": {
40
- "@mpxjs/utils": "^2.9.70",
40
+ "@mpxjs/utils": "^2.10.0",
41
41
  "axios": "^1.7.3"
42
42
  },
43
43
  "peerDependencies": {
44
- "@ant-design/react-native": "^5.1.3",
45
44
  "@react-native-async-storage/async-storage": "^1.23.1",
46
45
  "@react-native-community/netinfo": "^11.2.1",
47
46
  "react-native-device-info": "^10.13.2",
@@ -65,12 +64,9 @@
65
64
  "react-native-get-location": {
66
65
  "optional": true
67
66
  },
68
- "@ant-design/react-native": {
69
- "optional": true
70
- },
71
67
  "react-native-haptic-feedback": {
72
68
  "optional": true
73
69
  }
74
70
  },
75
- "gitHead": "38446f301a17e78dbe3ca7dacd771c79eb7a8ede"
71
+ "gitHead": "d9f3e76c6367341e4fc168b37f063c41f7321a7c"
76
72
  }
@@ -14,24 +14,37 @@ const blackList = [
14
14
  'stopBackgroundAudio',
15
15
  'showNavigationBarLoading',
16
16
  'hideNavigationBarLoading',
17
- 'createAnimation',
18
- 'createAnimationVideo',
19
- 'createSelectorQuery',
20
- 'createIntersectionObserver',
21
17
  'getPerformance',
22
18
  'hideKeyboard',
23
19
  'stopPullDownRefresh',
24
- 'createWorker',
25
20
  'pageScrollTo',
26
21
  'reportAnalytics',
27
22
  'getMenuButtonBoundingClientRect',
28
23
  'reportMonitor',
29
- 'createOffscreenCanvas',
30
24
  'reportEvent',
31
25
  'connectSocket',
32
26
  'base64ToArrayBuffer',
27
+ 'arrayBufferToBase64',
33
28
  'getDeviceInfo',
34
- 'getWindowInfo'
29
+ 'getWindowInfo',
30
+ 'getAppBaseInfo',
31
+ 'getAppAuthorizeSetting',
32
+ 'getApiCategory',
33
+ 'postMessageToReferrerPage',
34
+ 'postMessageToReferrerMiniProgram',
35
+ 'reportPerformance',
36
+ 'getPerformance',
37
+ 'preDownloadSubpackage',
38
+ 'router',
39
+ 'nextTick',
40
+ 'checkIsPictureInPictureActive',
41
+ 'worklet',
42
+ 'revokeBufferURL',
43
+ 'reportEvent',
44
+ 'getExptInfoSync',
45
+ 'reserveChannelsLive',
46
+ 'getNFCAdapter',
47
+ 'isVKSupport'
35
48
  ]
36
49
 
37
50
  function getMapFromList (list) {
@@ -55,7 +68,7 @@ function promisify (listObj, whiteList, customBlackList) {
55
68
  } else {
56
69
  return !(blackListMap[key] || // 特别指定的方法
57
70
  /^get\w*Manager$/.test(key) || // 获取manager的api
58
- /^create\w*Context$/.test(key) || // 创建上下文相关api
71
+ /^create(?!BLEConnection|BLEPeripheralServer)\w*$/.test(key) || // 创建上下文相关api
59
72
  /^(on|off)/.test(key) || // 以 on* 或 off开头的方法
60
73
  /\w+Sync$/.test(key) // 以Sync结尾的方法
61
74
  )
@@ -1,4 +1,5 @@
1
1
  import { hasOwn, noop, getEnvObj, getFocusedNavigation } from '@mpxjs/utils'
2
+ import { getCurrentInstance } from '@mpxjs/core'
2
3
 
3
4
  /**
4
5
  *
@@ -87,6 +88,12 @@ function failHandle (result, fail, complete) {
87
88
  typeof complete === 'function' && complete(result)
88
89
  }
89
90
 
91
+ function getCurrentPageId () {
92
+ const currentInstance = getCurrentInstance()
93
+ const id = currentInstance?.getPageId() || getFocusedNavigation()?.pageId || null
94
+ return id
95
+ }
96
+
90
97
  const ENV_OBJ = getEnvObj()
91
98
 
92
99
  export {
@@ -101,5 +108,6 @@ export {
101
108
  defineUnsupportedProps,
102
109
  successHandle,
103
110
  failHandle,
104
- getFocusedNavigation
111
+ getFocusedNavigation,
112
+ getCurrentPageId
105
113
  }
@@ -1,111 +1,169 @@
1
- import { View, TouchableHighlight, Text, StyleSheet, TouchableOpacity } from 'react-native'
2
- import { successHandle, failHandle } from '../../../common/js'
3
- import { Portal } from '@ant-design/react-native'
1
+ import { useEffect } from 'react'
2
+ import { View, Text, StyleSheet } from 'react-native'
3
+ import { successHandle, failHandle, getCurrentPageId } from '../../../common/js'
4
+ import Portal from '@mpxjs/webpack-plugin/lib/runtime/components/react/dist/mpx-portal/index'
4
5
  import { getWindowInfo } from '../system/rnSystem'
5
6
  import Animated, {
6
7
  useSharedValue,
7
8
  useAnimatedStyle,
8
- withTiming
9
+ withTiming,
10
+ Easing,
11
+ runOnJS
9
12
  } from 'react-native-reanimated'
10
- function showActionSheet (options = {}) {
11
- const { alertText, itemList = [], itemColor = '#000000', success, fail, complete } = options
12
- const windowInfo = getWindowInfo()
13
- const bottom = windowInfo.screenHeight - windowInfo.safeArea.bottom
14
- let actionSheetKey = null
15
- const styles = StyleSheet.create({
16
- actionActionMask: {
17
- left: 0,
18
- top: 0,
19
- bottom: 0,
20
- right: 0,
21
- backgroundColor: 'rgba(0,0,0,0.6)',
22
- position: 'absolute',
23
- zIndex: 1000
24
- },
25
- actionSheetContent: {
26
- backgroundColor: '#ffffff',
27
- borderTopLeftRadius: 10,
28
- borderTopRightRadius: 10,
29
- position: 'absolute',
30
- bottom: 0,
31
- left: 0,
32
- right: 0,
33
- paddingBottom: bottom
34
- },
35
- itemStyle: {
36
- paddingTop: 15,
37
- paddingBottom: 15,
38
- justifyContent: 'center',
39
- alignItems: 'center',
40
- borderBottomWidth: 1,
41
- borderBottomStyle: 'solid',
42
- borderBottomColor: 'rgba(0,0,0,0.1)'
43
- },
44
- itemTextStyle: {
45
- fontSize: 18
46
- },
47
- buttonStyle: {
48
- fontSize: 18,
49
- paddingTop: 10,
50
- paddingBottom: 10
51
- }
52
- })
53
- function ActionSheet () {
54
- const offset = useSharedValue(1000);
13
+ const actionSheetMap = new Map()
14
+
15
+ const remove = function (id) {
16
+ if (actionSheetMap.get(id)) { // 页面维度判断是否要清除之前渲染的actionsheet
17
+ Portal.remove(actionSheetMap.get(id))
18
+ actionSheetMap.delete(id)
19
+ }
20
+ }
55
21
 
56
- const animatedStyles = useAnimatedStyle(() => ({
57
- transform: [{ translateY: offset.value }],
58
- }))
22
+ const windowInfo = getWindowInfo()
23
+ const bottom = windowInfo.screenHeight - windowInfo.safeArea.bottom
59
24
 
60
- const slideOut = () => {
61
- // Will change fadeAnim value to 1 in 5 seconds
62
- offset.value = withTiming(1000)
63
- }
25
+ const styles = StyleSheet.create({
26
+ actionAction: {
27
+ left: 0,
28
+ top: 0,
29
+ bottom: 0,
30
+ right: 0,
31
+ position: 'absolute',
32
+ zIndex: 1000
33
+ },
34
+ maskWrap: {
35
+ left: 0,
36
+ top: 0,
37
+ bottom: 0,
38
+ right: 0,
39
+ position: 'absolute'
40
+ },
41
+ actionActionMask: {
42
+ left: 0,
43
+ top: 0,
44
+ bottom: 0,
45
+ right: 0,
46
+ backgroundColor: 'rgba(0,0,0,0.6)',
47
+ position: 'absolute'
48
+ },
49
+ actionSheetContent: {
50
+ backgroundColor: '#ffffff',
51
+ borderTopLeftRadius: 10,
52
+ borderTopRightRadius: 10,
53
+ position: 'absolute',
54
+ bottom: 0,
55
+ left: 0,
56
+ right: 0,
57
+ paddingBottom: bottom
58
+ },
59
+ itemStyle: {
60
+ paddingTop: 15,
61
+ paddingBottom: 15,
62
+ justifyContent: 'center',
63
+ alignItems: 'center',
64
+ borderBottomWidth: 1,
65
+ borderBottomStyle: 'solid',
66
+ borderBottomColor: 'rgba(0,0,0,0.1)'
67
+ },
68
+ itemTextStyle: {
69
+ fontSize: 18,
70
+ height: 22,
71
+ lineHeight: 22
72
+ },
73
+ buttonStyle: {
74
+ paddingTop: 10,
75
+ paddingBottom: 10,
76
+ justifyContent: 'center',
77
+ alignItems: 'center'
78
+ }
79
+ })
64
80
 
65
- offset.value = withTiming(0)
81
+ function ActionSheet ({itemColor, height, success, fail, complete, alertText, itemList}) {
82
+ const slide = useSharedValue(height)
83
+ const fade = useSharedValue(0)
66
84
 
67
- const selectAction = function (index) {
68
- const result = {
69
- errMsg: 'showActionSheet:ok',
70
- tapIndex: index
71
- }
72
- successHandle(result, success, complete)
73
- remove()
85
+ const actionAnimatedStyles = useAnimatedStyle(() => {
86
+ return {
87
+ transform: [{ translateY: slide.value }]
74
88
  }
75
-
76
- const remove = function () {
77
- if (actionSheetKey) {
78
- slideOut()
79
- setTimeout(() => {
80
- Portal.remove(actionSheetKey)
81
- actionSheetKey = null
82
- }, 200)
83
- }
89
+ })
90
+ const maskAnimatedStyles = useAnimatedStyle(() => {
91
+ return {
92
+ opacity: fade.value
84
93
  }
94
+ })
85
95
 
86
- const cancelAction = function () {
87
- const result = {
88
- errMsg: 'showActionSheet:fail cancel'
89
- }
90
- failHandle(result, fail, complete)
91
- remove()
96
+ useEffect(() => {
97
+ fade.value = withTiming(1, {
98
+ easing: Easing.inOut(Easing.poly(3)),
99
+ duration: 250
100
+ })
101
+ slide.value = withTiming(0, {
102
+ easing: Easing.out(Easing.poly(3)),
103
+ duration: 250
104
+ })
105
+ }, [])
106
+
107
+ const removeActionSheet = function () {
108
+ const id = getCurrentPageId()
109
+ remove(id)
110
+ }
111
+
112
+ const selectAction = function (index) {
113
+ removeActionSheet()
114
+ const result = {
115
+ errMsg: 'showActionSheet:ok',
116
+ tapIndex: index
117
+ }
118
+ successHandle(result, success, complete)
119
+ }
120
+ const cancelAction = function () {
121
+ removeActionSheet()
122
+ const result = {
123
+ errMsg: 'showActionSheet:fail cancel'
124
+ }
125
+ failHandle(result, fail, complete)
126
+ }
127
+ return (
128
+ <View style={styles.actionAction}>
129
+ <Animated.View style={[styles.maskWrap, maskAnimatedStyles]}>
130
+ <View activeOpacity={1} style={styles.actionActionMask} onTouchEnd={cancelAction}></View>
131
+ </Animated.View>
132
+ <Animated.View style={[styles.actionSheetContent, actionAnimatedStyles]}>
133
+ { alertText ? <View style={ styles.itemStyle }><Text style={[styles.itemTextStyle, { color: '#666666' }]}>{alertText}</Text></View> : null }
134
+ { itemList.map((item, index) => <View onTouchEnd={() => selectAction(index)} key={index} style={ [styles.itemStyle, itemList.length -1 === index ? {
135
+ borderBottomWidth: 6,
136
+ borderBottomStyle: 'solid',
137
+ borderBottomColor: '#f7f7f7'
138
+ } : {}] }><Text style={[styles.itemTextStyle, { color: itemColor }]}>{item}</Text></View>) }
139
+ <View style={styles.buttonStyle} onTouchEnd={cancelAction}><Text style={{ color: "#000000", fontSize: 18, lineHeight: 22, height: 22, width: "100%", textAlign: "center" }}>取消</Text></View>
140
+ </Animated.View>
141
+ </View>
142
+ )
143
+ }
144
+ function showActionSheet (options = {}) {
145
+ const id = getCurrentPageId()
146
+ remove(id)
147
+ const { alertText, itemList = [], itemColor = '#000000', success, fail, complete } = options
148
+ if (id === null) {
149
+ const result = {
150
+ errMsg: 'showActionSheet:fail cannot be invoked outside the mpx life cycle in React Native environments'
151
+ }
152
+ failHandle(result, fail, complete)
153
+ return
154
+ }
155
+ const len = itemList.length
156
+ if (len > 6) {
157
+ const result = {
158
+ errMsg: 'showActionSheet:fail parameter error: itemList should not be large than 6'
92
159
  }
93
- return (
94
- <TouchableHighlight underlayColor="rgba(0,0,0,0.6)" activeOpacity={1} onPress={cancelAction} style={styles.actionActionMask}>
95
- <Animated.View style={[styles.actionSheetContent, animatedStyles]} >
96
- { alertText ? <View style={ styles.itemStyle }><Text style={[styles.itemTextStyle, { color: '#666666' }]}>{alertText}</Text></View> : null }
97
- { itemList.map((item, index) => <TouchableHighlight key={index} underlayColor="#ececec" onPress={() => selectAction(index)} style={ [styles.itemStyle, itemList.length -1 === index ? {
98
- borderBottomWidth: 6,
99
- borderBottomStyle: 'solid',
100
- borderBottomColor: '#f7f7f7'
101
- } : {}] }><Text style={[styles.itemTextStyle, { color: itemColor }]}>{item}</Text></TouchableHighlight>) }
102
- <View style={styles.buttonStyle}><TouchableOpacity onPress={cancelAction}><Text style={{ color: "#000000", width: "100%", textAlign: "center" }}>取消</Text></TouchableOpacity></View>
103
- </Animated.View>
104
- </TouchableHighlight>
105
- )
160
+ failHandle(result, fail, complete)
161
+ return
106
162
  }
163
+ const height = len * 53 + 46 + bottom + (alertText ? 52 : 0)
107
164
 
108
- actionSheetKey = Portal.add(<ActionSheet/>)
165
+ const actionSheetKey = Portal.add(<ActionSheet itemColor={itemColor} height={height} success={success} fail={fail} complete={complete} alertText={alertText} itemList={itemList} />, id)
166
+ actionSheetMap.set(id, actionSheetKey)
109
167
  }
110
168
 
111
169
  export {
@@ -1,8 +1,7 @@
1
- import { isArray, isObject, isString, noop } from '@mpxjs/utils'
1
+ import { isArray, isObject, isString, noop, warn } from '@mpxjs/utils'
2
2
  import throttle from 'lodash/throttle'
3
3
  import { Dimensions } from 'react-native'
4
4
  import { getFocusedNavigation } from '../../../common/js'
5
-
6
5
  const WindowRefStr = 'window'
7
6
  const IgnoreTarget = 'ignore'
8
7
  const DefaultMargin = { top: 0, bottom: 0, left: 0, right: 0 }
@@ -12,13 +11,19 @@ class RNIntersectionObserver {
12
11
  constructor (component, options, intersectionCtx) {
13
12
  this.id = idCount++
14
13
  this.component = component
15
- this.options = options
16
- this.thresholds = options.thresholds.sort((a, b) => a - b) || [0]
17
- this.initialRatio = options.initialRatio || 0
18
- this.observeAll = options.observeAll || false
14
+ this.mpxFileResource = component.__mpxProxy?.options?.mpxFileResource || ''
15
+ this.options = Object.assign({
16
+ thresholds: [0],
17
+ initialRatio: 0,
18
+ observeAll: false,
19
+ throttleTime: 100
20
+ }, options || {})
21
+ this.thresholds = this.options.thresholds.sort((a, b) => a - b)
22
+ this.initialRatio = this.options.initialRatio
23
+ this.observeAll = this.options.observeAll
19
24
 
20
25
  // 组件上挂载对应的observers,用于在组件销毁的时候进行批量disconnect
21
- this.component._intersectionObservers = this.component.__intersectionObservers || []
26
+ this.component._intersectionObservers = this.component._intersectionObservers || []
22
27
  this.component._intersectionObservers.push(this)
23
28
 
24
29
  this.observerRefs = null
@@ -26,7 +31,7 @@ class RNIntersectionObserver {
26
31
  this.margins = DefaultMargin
27
32
  this.callback = noop
28
33
 
29
- this.throttleMeasure = this.getThrottleMeasure(options.throttleTime || 100)
34
+ this.throttleMeasure = this.getThrottleMeasure(this.options.throttleTime)
30
35
 
31
36
  // 记录上一次相交的比例
32
37
  this.previousIntersectionRatio = []
@@ -52,7 +57,7 @@ class RNIntersectionObserver {
52
57
  this.relativeRef = relativeRef
53
58
  this.margins = Object.assign({}, DefaultMargin, margins)
54
59
  } else {
55
- console.warn(`node ${selector}is not found. The relative node for intersection observer will be ignored`)
60
+ warn(`node ${selector}is not found. The relative node for intersection observer will be ignored`, this.mpxFileResource)
56
61
  }
57
62
  return this
58
63
  }
@@ -65,7 +70,7 @@ class RNIntersectionObserver {
65
70
 
66
71
  observe (selector, callback) {
67
72
  if (this.observerRefs) {
68
- console.error('"observe" call can be only called once in IntersectionObserver')
73
+ warn('"observe" call can be only called once in IntersectionObserver', this.mpxFileResource)
69
74
  return
70
75
  }
71
76
  let targetRef = null
@@ -75,7 +80,7 @@ class RNIntersectionObserver {
75
80
  targetRef = this.component.__selectRef(selector, 'node')
76
81
  }
77
82
  if (!targetRef || targetRef.length === 0) {
78
- console.error('intersection observer target not found')
83
+ warn('intersection observer target not found', this.mpxFileResource)
79
84
  return
80
85
  }
81
86
  this.observerRefs = isArray(targetRef) ? targetRef : [targetRef]
@@ -95,10 +100,10 @@ class RNIntersectionObserver {
95
100
  }
96
101
 
97
102
  const windowRect = {
98
- top: navigationLayout.y + this.margins.top,
99
- left: this.margins.left,
100
- right: navigationLayout.width - this.margins.right,
101
- bottom: navigationLayout.y + navigationLayout.height - this.margins.bottom
103
+ top: navigationLayout.y - this.margins.top,
104
+ left: 0 - this.margins.left,
105
+ right: navigationLayout.width + this.margins.right,
106
+ bottom: navigationLayout.y + navigationLayout.height + this.margins.bottom
102
107
  }
103
108
 
104
109
  this.windowRect = windowRect
@@ -227,7 +232,7 @@ class RNIntersectionObserver {
227
232
  }
228
233
  })
229
234
  }).catch((e) => {
230
- console.log('_measureTarget fail', e)
235
+ warn('_measureTarget fail', this.mpxFileResource, e)
231
236
  })
232
237
  }
233
238
 
@@ -1,8 +1,10 @@
1
1
  import { View, Dimensions, Text, StyleSheet, TouchableOpacity, ScrollView, TextInput } from 'react-native'
2
- import { successHandle, failHandle } from '../../../common/js'
3
- import { Portal } from '@ant-design/react-native'
2
+ import { successHandle, failHandle, getCurrentPageId } from '../../../common/js'
3
+ import Portal from '@mpxjs/webpack-plugin/lib/runtime/components/react/dist/mpx-portal/index'
4
4
  const { width, height } = Dimensions.get('window')
5
+ const modalMap = new Map()
5
6
  const showModal = function (options = {}) {
7
+ const id = getCurrentPageId()
6
8
  const {
7
9
  title,
8
10
  content,
@@ -17,6 +19,23 @@ const showModal = function (options = {}) {
17
19
  fail,
18
20
  complete
19
21
  } = options
22
+ if (id === null) {
23
+ const result = {
24
+ errMsg: 'showModal:fail cannot be invoked outside the mpx life cycle in React Native environments'
25
+ }
26
+ failHandle(result, fail, complete)
27
+ return
28
+ }
29
+ const setCurrentModalKey = function (modalKey) {
30
+ const currentArr = modalMap.get(id) || []
31
+ currentArr.push(modalKey)
32
+ modalMap.set(id, currentArr)
33
+ }
34
+ const getCurrentModalKey = function () {
35
+ const currentArr = modalMap.get(id) || []
36
+ return currentArr.pop()
37
+ }
38
+
20
39
  const modalWidth = width * 0.8
21
40
  const styles = StyleSheet.create({
22
41
  modalTask: {
@@ -82,7 +101,6 @@ const showModal = function (options = {}) {
82
101
  borderStyle: 'solid',
83
102
  }
84
103
  })
85
- let modalKey
86
104
  let ModalView
87
105
  let modalTitle = []
88
106
  let modalContent = []
@@ -97,8 +115,10 @@ const showModal = function (options = {}) {
97
115
  contentText = text
98
116
  }
99
117
  const closeModal = function (buttonInfo) {
100
- Portal.remove(modalKey)
101
- modalKey = null
118
+ const modalKey = getCurrentModalKey()
119
+ if(modalKey) {
120
+ Portal.remove(modalKey)
121
+ }
102
122
  const result = {
103
123
  errMsg: 'showModal:ok'
104
124
  }
@@ -156,7 +176,8 @@ const showModal = function (options = {}) {
156
176
  </View>
157
177
  </View>
158
178
  try {
159
- modalKey = Portal.add(ModalView)
179
+ const modalKey = Portal.add(ModalView, id)
180
+ setCurrentModalKey(modalKey)
160
181
  } catch (e) {
161
182
  const result = {
162
183
  errMsg: `showModal:fail invalid ${e}`
@@ -33,10 +33,29 @@ function resolvePath (relative, base) {
33
33
  }
34
34
  return stack.join('/')
35
35
  }
36
+ let timerId = null
37
+ function isLock (navigationHelper, type, options) {
38
+ if (navigationHelper.lastSuccessCallback && navigationHelper.lastFailCallback) {
39
+ const res = { errMsg: `${type}:fail the previous routing event didn't complete` }
40
+ failHandle(res, options.fail, options.complete)
41
+ return true
42
+ }
43
+ clearTimeout(timerId)
44
+ timerId = setTimeout(() => {
45
+ if (navigationHelper.lastSuccessCallback && navigationHelper.lastFailCallback) {
46
+ navigationHelper.lastFailCallback('timeout')
47
+ navigationHelper.lastFailCallback = null
48
+ }
49
+ }, 350)
50
+ return false
51
+ }
36
52
 
37
53
  function navigateTo (options = {}) {
38
- const navigation = Object.values(global.__mpxPagesMap || {})[0]?.[1]
39
54
  const navigationHelper = global.__navigationHelper
55
+ if (isLock(navigationHelper, 'navigateTo', options)) {
56
+ return
57
+ }
58
+ const navigation = Object.values(global.__mpxPagesMap || {})[0]?.[1]
40
59
  if (navigation && navigationHelper) {
41
60
  const { path, queryObj } = parseUrl(options.url)
42
61
  const basePath = getBasePath(navigation)
@@ -56,6 +75,9 @@ function navigateTo (options = {}) {
56
75
  function redirectTo (options = {}) {
57
76
  const navigation = Object.values(global.__mpxPagesMap || {})[0]?.[1]
58
77
  const navigationHelper = global.__navigationHelper
78
+ if (isLock(navigationHelper, 'redirectTo', options)) {
79
+ return
80
+ }
59
81
  if (navigation && navigationHelper) {
60
82
  const { path, queryObj } = parseUrl(options.url)
61
83
  const basePath = getBasePath(navigation)
@@ -75,24 +97,27 @@ function redirectTo (options = {}) {
75
97
  function navigateBack (options = {}) {
76
98
  const navigation = Object.values(global.__mpxPagesMap || {})[0]?.[1]
77
99
  const navigationHelper = global.__navigationHelper
100
+ if (isLock(navigationHelper, 'navigateBack', options)) {
101
+ return
102
+ }
78
103
  if (navigation && navigationHelper) {
79
104
  const delta = options.delta || 1
80
105
  const routeLength = navigation.getState().routes.length
106
+ navigationHelper.lastSuccessCallback = () => {
107
+ const res = { errMsg: 'navigateBack:ok' }
108
+ successHandle(res, options.success, options.complete)
109
+ }
110
+ navigationHelper.lastFailCallback = (msg) => {
111
+ const res = { errMsg: `navigateBack:fail ${msg}` }
112
+ failHandle(res, options.fail, options.complete)
113
+ }
81
114
  if (delta >= routeLength && global.__mpx?.config.rnConfig.onAppBack?.(delta - routeLength + 1)) {
82
115
  nextTick(() => {
83
- const res = { errMsg: 'navigateBack:ok' }
84
- successHandle(res, options.success, options.complete)
116
+ navigationHelper.lastSuccessCallback()
117
+ navigationHelper.lastSuccessCallback = null
85
118
  })
86
119
  } else {
87
120
  navigation.pop(delta)
88
- navigationHelper.lastSuccessCallback = () => {
89
- const res = { errMsg: 'navigateBack:ok' }
90
- successHandle(res, options.success, options.complete)
91
- }
92
- navigationHelper.lastFailCallback = (msg) => {
93
- const res = { errMsg: `navigateBack:fail ${msg}` }
94
- failHandle(res, options.fail, options.complete)
95
- }
96
121
  }
97
122
  }
98
123
  }
@@ -100,6 +125,9 @@ function navigateBack (options = {}) {
100
125
  function reLaunch (options = {}) {
101
126
  const navigation = Object.values(global.__mpxPagesMap || {})[0]?.[1]
102
127
  const navigationHelper = global.__navigationHelper
128
+ if (isLock(navigationHelper, 'reLaunch', options)) {
129
+ return
130
+ }
103
131
  if (navigation && navigationHelper) {
104
132
  const { path, queryObj } = parseUrl(options.url)
105
133
  const basePath = getBasePath(navigation)
@@ -10,6 +10,7 @@ const getWindowInfo = function () {
10
10
  const insets = Object.assign(initialWindowMetricsInset, navigationInsets)
11
11
  let safeArea = {}
12
12
  const { top = 0, bottom = 0, left = 0, right = 0 } = insets
13
+
13
14
  const screenHeight = __mpx_mode__ === 'ios' ? dimensionsScreen.height : dimensionsScreen.height - bottom // 解决安卓开启屏幕内三建导航安卓把安全区计算进去后产生的影响
14
15
  const screenWidth = __mpx_mode__ === 'ios' ? dimensionsScreen.width : dimensionsScreen.width - right
15
16
  const layout = navigation.layout || {}
@@ -1,13 +1,11 @@
1
1
  import { View, Text, Image, StyleSheet, ActivityIndicator, Dimensions } from 'react-native'
2
- import { successHandle, failHandle } from '../../../common/js'
3
- import { Portal } from '@ant-design/react-native'
2
+ import { successHandle, failHandle, getCurrentPageId } from '../../../common/js'
3
+ import Portal from '@mpxjs/webpack-plugin/lib/runtime/components/react/dist/mpx-portal/index'
4
4
 
5
- let toastKey
6
5
  let isLoadingShow
7
6
  const dimensionsScreen = Dimensions.get('screen')
8
7
  const screenHeight = dimensionsScreen.height
9
- const contentTop = parseInt(screenHeight * 0.35)
10
- let tId // show duration 计时id
8
+ const contentTop = parseInt(screenHeight * 0.4)
11
9
  const styles = StyleSheet.create({
12
10
  toastContent: {
13
11
  maxWidth: '60%',
@@ -53,9 +51,22 @@ const styles = StyleSheet.create({
53
51
  marginTop: 10
54
52
  }
55
53
  })
56
-
54
+ const toastMap = new Map()
55
+ const timerMap = new Map()
57
56
  function showToast (options = {}) {
57
+ const id = getCurrentPageId()
58
58
  const { title, icon = 'success', image, duration = 1500, mask = false, success, fail, complete, isLoading } = options
59
+ if (id === null) {
60
+ const result = {
61
+ errMsg: 'showToast:fail cannot be invoked outside the mpx life cycle in React Native environments'
62
+ }
63
+ failHandle(result, fail, complete)
64
+ return
65
+ }
66
+
67
+ const timeoutId = timerMap.get(id)
68
+ clearTimeout(timeoutId)
69
+ timerMap.delete(id)
59
70
  let ToastView
60
71
  const successPng = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFwAAABcAgMAAACegTrLAAAADFBMVEUAAAD////R0dHj4+PcME2AAAAAAXRSTlMAQObYZgAAANNJREFUSMft1FEKwkAMBNBGyBFyH4/gR8f+ehSPLtiyQ+wM2C8Rmp+WQN90N8tOZ/1/4SbbYfpp+sBVMqafgGQKs+FvkjF8GR6aj4M8NB+GT8OX5i+GT8OX4aH5MHwZHpoPw+c3fA0xGl/zYBrP92o8vwVwF3NO8tySjXmINQLAs/WX9S8bP9UGJUZSi8MAuUqsj75payPxuWn1BmrjewCCfAvA4Fmjvx8HQL4HiJEHeRmg5k2+B8gTFeRFwL7NzREB/sCKwsG7KN2VSb7XMp31i3oBatNdEForTOoAAAAASUVORK5CYII='
61
72
  const errorPng = 'data:image/png;base64,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'
@@ -65,19 +76,15 @@ function showToast (options = {}) {
65
76
  }
66
77
  const pointerEvents = mask ? 'auto' : 'none'
67
78
  isLoadingShow = isLoading
68
- if (tId) {
69
- clearTimeout(tId)
70
- }
71
- tId = null
72
79
  if (image || icon === 'success' || icon === 'error') {
73
- ToastView = <View style={styles.toastWrap} pointerEvents={pointerEvents}>
80
+ ToastView = <View style={[styles.toastWrap, {pointerEvents}]}>
74
81
  <View style={[styles.toastContent, styles.toastHasIcon]}>
75
82
  <Image style={ styles.toastImg } source={{uri: image || iconImg[icon]}}></Image>
76
83
  { title ? <Text style={styles.toastText}>{title}</Text> : null }
77
84
  </View>
78
85
  </View>
79
86
  } else if (icon === 'loading') {
80
- ToastView = <View style={styles.toastWrap} pointerEvents={pointerEvents}>
87
+ ToastView = <View style={[styles.toastWrap, {pointerEvents}]}>
81
88
  <View style={[styles.toastContent, styles.toastHasIcon]}>
82
89
  <ActivityIndicator
83
90
  animating
@@ -88,7 +95,7 @@ function showToast (options = {}) {
88
95
  </View>
89
96
  </View>
90
97
  } else {
91
- ToastView = <View style={styles.toastWrap} pointerEvents={pointerEvents}>
98
+ ToastView = <View style={[styles.toastWrap, {pointerEvents}]}>
92
99
  <View style={styles.toastContent}>
93
100
  { title ? <Text numberOfLines={2} style={{ ...styles.toastText, ...(icon === 'none' ? {
94
101
  height: 'auto',
@@ -98,15 +105,18 @@ function showToast (options = {}) {
98
105
  </View>
99
106
  }
100
107
  try {
101
- if (toastKey) {
102
- Portal.remove(toastKey)
108
+ if (toastMap.get(id)) { // 页面维度判断是否要清除toast
109
+ Portal.remove(toastMap.get(id))
110
+ toastMap.delete(id)
103
111
  }
104
- toastKey = Portal.add(ToastView)
112
+ const toastKey = Portal.add(ToastView, id)
113
+ toastMap.set(id, toastKey)
105
114
  if (!isLoading) {
106
- tId = setTimeout(() => {
107
- Portal.remove(toastKey)
108
- toastKey = null
115
+ const timeoutId = setTimeout(() => {
116
+ Portal.remove(toastMap.get(id))
117
+ toastMap.delete(id)
109
118
  }, duration)
119
+ timerMap.set(id, timeoutId)
110
120
  }
111
121
  const result = {
112
122
  errMsg: 'showToast:ok'
@@ -121,15 +131,16 @@ function showToast (options = {}) {
121
131
  }
122
132
 
123
133
  function hideToast(options = {}) {
134
+ const id = getCurrentPageId()
124
135
  const { noConflict = false, success, fail, complete } = options
125
136
 
126
137
  if (isLoadingShow && noConflict) {
127
138
  return
128
139
  }
129
140
  try {
130
- if (toastKey) {
131
- Portal.remove(toastKey)
132
- toastKey = null
141
+ if (toastMap.get(id)) {
142
+ Portal.remove(toastMap.get(id))
143
+ toastMap.delete(id)
133
144
  }
134
145
  const result = {
135
146
  errMsg: 'hideToast:ok'
@@ -166,15 +177,16 @@ function showLoading (options = {}) {
166
177
  }
167
178
 
168
179
  function hideLoading (options = {}) {
180
+ const id = getCurrentPageId()
169
181
  const { noConflict = false, success, fail, complete } = options
170
182
  if (!isLoadingShow && noConflict) {
171
183
  return
172
184
  }
173
185
  isLoadingShow = false
174
186
  try {
175
- if (toastKey) {
176
- Portal.remove(toastKey)
177
- toastKey = null
187
+ if (toastMap.get(id)) {
188
+ Portal.remove(toastMap.get(id))
189
+ toastMap.delete(id)
178
190
  }
179
191
  const result = {
180
192
  errMsg: 'hideLoading:ok'