@mpxjs/core 2.10.4-beta.1 → 2.10.4-beta.10
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/package.json
CHANGED
|
@@ -4,10 +4,12 @@ import { makeMap, spreadProp, getFocusedNavigation, hasOwn } from '@mpxjs/utils'
|
|
|
4
4
|
import { mergeLifecycle } from '../convertor/mergeLifecycle'
|
|
5
5
|
import { LIFECYCLE } from '../platform/patch/lifecycle/index'
|
|
6
6
|
import Mpx from '../index'
|
|
7
|
+
import { ref } from '../observer/ref'
|
|
8
|
+
import { watch } from '../observer/watch'
|
|
7
9
|
import { createElement, memo, useRef, useEffect } from 'react'
|
|
8
10
|
import * as ReactNative from 'react-native'
|
|
9
11
|
import { initAppProvides } from './export/inject'
|
|
10
|
-
import { NavigationContainer,
|
|
12
|
+
import { NavigationContainer, createNativeStackNavigator, SafeAreaProvider } from './env/navigationHelper'
|
|
11
13
|
|
|
12
14
|
const appHooksMap = makeMap(mergeLifecycle(LIFECYCLE).app)
|
|
13
15
|
|
|
@@ -52,25 +54,25 @@ export default function createApp (options) {
|
|
|
52
54
|
|
|
53
55
|
const pages = currentInject.getPages() || {}
|
|
54
56
|
const firstPage = currentInject.firstPage
|
|
55
|
-
const Stack =
|
|
57
|
+
const Stack = createNativeStackNavigator()
|
|
56
58
|
const getPageScreens = (initialRouteName, initialParams) => {
|
|
57
59
|
return Object.entries(pages).map(([key, item]) => {
|
|
58
|
-
const options = {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
}
|
|
60
|
+
// const options = {
|
|
61
|
+
// // __mpxPageStatusMap 为编译注入的全局变量
|
|
62
|
+
// headerShown: !(Object.assign({}, global.__mpxPageConfig, global.__mpxPageConfigsMap[key]).navigationStyle === 'custom')
|
|
63
|
+
// }
|
|
62
64
|
if (key === initialRouteName) {
|
|
63
65
|
return createElement(Stack.Screen, {
|
|
64
66
|
name: key,
|
|
65
67
|
component: item,
|
|
66
|
-
initialParams
|
|
67
|
-
options
|
|
68
|
+
initialParams
|
|
69
|
+
// options
|
|
68
70
|
})
|
|
69
71
|
}
|
|
70
72
|
return createElement(Stack.Screen, {
|
|
71
73
|
name: key,
|
|
72
|
-
component: item
|
|
73
|
-
options
|
|
74
|
+
component: item
|
|
75
|
+
// options
|
|
74
76
|
})
|
|
75
77
|
})
|
|
76
78
|
}
|
|
@@ -90,6 +92,82 @@ export default function createApp (options) {
|
|
|
90
92
|
global.__navigationHelper.lastFailCallback = null
|
|
91
93
|
}
|
|
92
94
|
}
|
|
95
|
+
const appState = ref('')
|
|
96
|
+
watch(() => appState.value, (value) => {
|
|
97
|
+
if (value === 'show') {
|
|
98
|
+
let options = global.__mpxEnterOptions || {}
|
|
99
|
+
const navigation = getFocusedNavigation()
|
|
100
|
+
if (navigation) {
|
|
101
|
+
const state = navigation.getState()
|
|
102
|
+
const current = state.routes[state.index]
|
|
103
|
+
options = {
|
|
104
|
+
path: current.name,
|
|
105
|
+
query: current.params,
|
|
106
|
+
scene: 0,
|
|
107
|
+
shareTicket: '',
|
|
108
|
+
referrerInfo: {}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
global.__mpxAppCbs.show.forEach((cb) => {
|
|
112
|
+
cb(options)
|
|
113
|
+
})
|
|
114
|
+
} else if (value === 'hide') {
|
|
115
|
+
global.__mpxAppCbs.hide.forEach((cb) => {
|
|
116
|
+
cb({
|
|
117
|
+
reason: 3
|
|
118
|
+
})
|
|
119
|
+
})
|
|
120
|
+
}
|
|
121
|
+
})
|
|
122
|
+
const onAppStateChange = (currentState) => {
|
|
123
|
+
const navigation = getFocusedNavigation()
|
|
124
|
+
if (currentState === 'active') {
|
|
125
|
+
appState.value = 'show'
|
|
126
|
+
if (navigation && hasOwn(global.__mpxPageStatusMap, navigation.pageId)) {
|
|
127
|
+
global.__mpxPageStatusMap[navigation.pageId] = 'show'
|
|
128
|
+
}
|
|
129
|
+
} else if (currentState === 'inactive' || currentState === 'background') {
|
|
130
|
+
appState.value = 'hide'
|
|
131
|
+
if (navigation && hasOwn(global.__mpxPageStatusMap, navigation.pageId)) {
|
|
132
|
+
global.__mpxPageStatusMap[navigation.pageId] = 'hide'
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const onAppStateChange = (currentState) => {
|
|
138
|
+
// 业务上配置禁止的话就不响应监听事件
|
|
139
|
+
if (currentState === 'active') {
|
|
140
|
+
let options = global.__mpxEnterOptions || {}
|
|
141
|
+
const navigation = getFocusedNavigation()
|
|
142
|
+
if (navigation) {
|
|
143
|
+
const state = navigation.getState()
|
|
144
|
+
const current = state.routes[state.index]
|
|
145
|
+
options = {
|
|
146
|
+
path: current.name,
|
|
147
|
+
query: current.params,
|
|
148
|
+
scene: 0,
|
|
149
|
+
shareTicket: '',
|
|
150
|
+
referrerInfo: {}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
global.__mpxAppCbs.show.forEach((cb) => {
|
|
154
|
+
cb(options)
|
|
155
|
+
})
|
|
156
|
+
if (navigation && hasOwn(global.__mpxPageStatusMap, navigation.pageId)) {
|
|
157
|
+
global.__mpxPageStatusMap[navigation.pageId] = 'show'
|
|
158
|
+
}
|
|
159
|
+
} else if (currentState === 'inactive' || currentState === 'background') {
|
|
160
|
+
global.__mpxAppCbs.hide.forEach((cb) => {
|
|
161
|
+
cb({
|
|
162
|
+
reason: 3
|
|
163
|
+
})
|
|
164
|
+
})
|
|
165
|
+
const navigation = getFocusedNavigation()
|
|
166
|
+
if (navigation && hasOwn(global.__mpxPageStatusMap, navigation.pageId)) {
|
|
167
|
+
global.__mpxPageStatusMap[navigation.pageId] = 'hide'
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
93
171
|
|
|
94
172
|
global.__mpxAppLaunched = false
|
|
95
173
|
global.__mpxOptionsMap[currentInject.moduleId] = memo((props) => {
|
|
@@ -127,47 +205,17 @@ export default function createApp (options) {
|
|
|
127
205
|
global.__mpxLaunchOptions = options
|
|
128
206
|
defaultOptions.onLaunch && defaultOptions.onLaunch.call(appInstance, options)
|
|
129
207
|
}
|
|
130
|
-
|
|
131
|
-
cb(options)
|
|
132
|
-
})
|
|
208
|
+
appState.value = 'show'
|
|
133
209
|
global.__mpxAppLaunched = true
|
|
134
210
|
global.__mpxAppHotLaunched = true
|
|
135
211
|
}
|
|
136
212
|
}
|
|
137
213
|
|
|
138
214
|
useEffect(() => {
|
|
139
|
-
const changeSubscription = ReactNative.AppState.addEventListener('change', (
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
if (navigation) {
|
|
144
|
-
const state = navigation.getState()
|
|
145
|
-
const current = state.routes[state.index]
|
|
146
|
-
options = {
|
|
147
|
-
path: current.name,
|
|
148
|
-
query: current.params,
|
|
149
|
-
scene: 0,
|
|
150
|
-
shareTicket: '',
|
|
151
|
-
referrerInfo: {}
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
global.__mpxAppCbs.show.forEach((cb) => {
|
|
155
|
-
cb(options)
|
|
156
|
-
})
|
|
157
|
-
if (navigation && hasOwn(global.__mpxPageStatusMap, navigation.pageId)) {
|
|
158
|
-
global.__mpxPageStatusMap[navigation.pageId] = 'show'
|
|
159
|
-
}
|
|
160
|
-
} else if (currentState === 'inactive' || currentState === 'background') {
|
|
161
|
-
global.__mpxAppCbs.hide.forEach((cb) => {
|
|
162
|
-
cb({
|
|
163
|
-
reason: 3
|
|
164
|
-
})
|
|
165
|
-
})
|
|
166
|
-
const navigation = getFocusedNavigation()
|
|
167
|
-
if (navigation && hasOwn(global.__mpxPageStatusMap, navigation.pageId)) {
|
|
168
|
-
global.__mpxPageStatusMap[navigation.pageId] = 'hide'
|
|
169
|
-
}
|
|
170
|
-
}
|
|
215
|
+
const changeSubscription = ReactNative.AppState.addEventListener('change', (state) => {
|
|
216
|
+
// 外层可能会异常设置此配置,因此加载监听函数内部
|
|
217
|
+
if (Mpx.config.rnConfig.disableReactNativeAppStateChange) return
|
|
218
|
+
onAppStateChange(state)
|
|
171
219
|
})
|
|
172
220
|
|
|
173
221
|
let count = 0
|
|
@@ -195,32 +243,10 @@ export default function createApp (options) {
|
|
|
195
243
|
|
|
196
244
|
const { initialRouteName, initialParams } = initialRouteRef.current
|
|
197
245
|
const navScreenOpts = {
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
// 整体切换native-stack时进行修改如下
|
|
203
|
-
// statusBarTranslucent: true,
|
|
204
|
-
// statusBarBackgroundColor: 'transparent'
|
|
205
|
-
}
|
|
206
|
-
if (__mpx_mode__ === 'ios') {
|
|
207
|
-
// ios使用native-stack
|
|
208
|
-
const headerBackImageSource = Mpx.config.rnConfig.headerBackImageSource || null
|
|
209
|
-
if (headerBackImageSource) {
|
|
210
|
-
navScreenOpts.headerBackImageSource = headerBackImageSource
|
|
211
|
-
}
|
|
212
|
-
} else {
|
|
213
|
-
// 安卓上会出现导航条闪现的问题所以默认加headerShown false(stack版本, native-stack版本可以干掉)
|
|
214
|
-
// iOS加上默认headerShown false的话会因为iOS根高度是screenHeight - useHeaderHeight()会导致出现渲染两次情况,因此iOS不加此默认值
|
|
215
|
-
navScreenOpts.headerShown = false
|
|
216
|
-
// 安卓和鸿蒙先用stack
|
|
217
|
-
const headerBackImageProps = Mpx.config.rnConfig.headerBackImageProps || null
|
|
218
|
-
if (headerBackImageProps) {
|
|
219
|
-
navScreenOpts.headerBackImage = () => {
|
|
220
|
-
return createElement(ReactNative.Image, headerBackImageProps)
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
}
|
|
246
|
+
headerShown: false,
|
|
247
|
+
statusBarTranslucent: true,
|
|
248
|
+
statusBarBackgroundColor: 'transparent'
|
|
249
|
+
}
|
|
224
250
|
|
|
225
251
|
return createElement(SafeAreaProvider,
|
|
226
252
|
null,
|
|
@@ -256,4 +282,12 @@ export default function createApp (options) {
|
|
|
256
282
|
global.__mpxPageStatusMap[navigation.pageId] = status
|
|
257
283
|
}
|
|
258
284
|
}
|
|
285
|
+
|
|
286
|
+
// 用于外层业务用来设置App的展示情况
|
|
287
|
+
global.setAppShow = function () {
|
|
288
|
+
onAppStateChange('active')
|
|
289
|
+
}
|
|
290
|
+
global.setAppHide = function () {
|
|
291
|
+
onAppStateChange('inactive')
|
|
292
|
+
}
|
|
259
293
|
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { createElement, useState, useMemo } from 'react'
|
|
2
|
+
import { useSafeAreaInsets } from 'react-native-safe-area-context'
|
|
3
|
+
import * as ReactNative from 'react-native'
|
|
4
|
+
import Mpx from '../../index'
|
|
5
|
+
|
|
6
|
+
export function useInnerHeaderHeight (pageconfig) {
|
|
7
|
+
if (pageconfig.navigationStyle === 'custom') {
|
|
8
|
+
return 0
|
|
9
|
+
} else {
|
|
10
|
+
const safeAreaTop = useSafeAreaInsets()?.top || 0
|
|
11
|
+
const headerHeight = safeAreaTop + getTitleHeight()
|
|
12
|
+
return headerHeight
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// 固定写死高度
|
|
17
|
+
function getTitleHeight () {
|
|
18
|
+
return 44
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// 计算颜色亮度
|
|
22
|
+
const getColorBrightness = (color) => {
|
|
23
|
+
const processedColor = ReactNative.processColor(color)
|
|
24
|
+
if (typeof processedColor === 'number') {
|
|
25
|
+
const r = (processedColor >> 16) & 255
|
|
26
|
+
const g = (processedColor >> 8) & 255
|
|
27
|
+
const b = processedColor & 255
|
|
28
|
+
return (r * 299 + g * 587 + b * 114) / 1000
|
|
29
|
+
}
|
|
30
|
+
return 0
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const styles = ReactNative.StyleSheet.create({
|
|
34
|
+
header: {
|
|
35
|
+
elevation: 3
|
|
36
|
+
},
|
|
37
|
+
headerContent: {
|
|
38
|
+
flexDirection: 'row',
|
|
39
|
+
alignItems: 'center',
|
|
40
|
+
justifyContent: 'center'
|
|
41
|
+
},
|
|
42
|
+
backButton: {
|
|
43
|
+
position: 'absolute',
|
|
44
|
+
height: '100%',
|
|
45
|
+
width: 40,
|
|
46
|
+
left: 0,
|
|
47
|
+
top: 0,
|
|
48
|
+
alignItems: 'center',
|
|
49
|
+
justifyContent: 'center'
|
|
50
|
+
},
|
|
51
|
+
backButtonImage: {
|
|
52
|
+
width: 22,
|
|
53
|
+
height: 22
|
|
54
|
+
},
|
|
55
|
+
title: {
|
|
56
|
+
fontSize: 17,
|
|
57
|
+
fontWeight: 600
|
|
58
|
+
}
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
export function innerNav ({ props, navigation }) {
|
|
62
|
+
const { pageConfig } = props
|
|
63
|
+
const [innerPageConfig, setPageConfig] = useState(pageConfig || {})
|
|
64
|
+
navigation.setPageConfig = (config) => {
|
|
65
|
+
const newConfig = Object.assign({}, innerPageConfig, config)
|
|
66
|
+
setPageConfig(newConfig)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const isCustom = innerPageConfig.navigationStyle === 'custom'
|
|
70
|
+
if (isCustom) return null
|
|
71
|
+
const safeAreaTop = useSafeAreaInsets()?.top || 0
|
|
72
|
+
|
|
73
|
+
// 回退按钮的颜色,根据背景色的亮度来进行调节
|
|
74
|
+
const backButtonColor = useMemo(() => {
|
|
75
|
+
return getColorBrightness(innerPageConfig.navigationBarBackgroundColor) > 128 ? '#000000' : '#ffffff'
|
|
76
|
+
}, [innerPageConfig.navigationBarBackgroundColor])
|
|
77
|
+
|
|
78
|
+
// 假设是栈导航,获取栈的长度
|
|
79
|
+
const stackLength = navigation.getState()?.routes?.length
|
|
80
|
+
// 用于外部注册打开RN容器之前的栈长度
|
|
81
|
+
const beforeStackLength = Mpx.config?.rnConfig?.beforeStackLength || 0
|
|
82
|
+
|
|
83
|
+
// 回退按钮与图标
|
|
84
|
+
const backElement = stackLength + beforeStackLength > 1
|
|
85
|
+
? createElement(ReactNative.TouchableOpacity, {
|
|
86
|
+
style: [styles.backButton],
|
|
87
|
+
onPress: () => { navigation.goBack() }
|
|
88
|
+
}, createElement(ReactNative.Image, {
|
|
89
|
+
source: { uri: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAABICAYAAACqT5alAAAA2UlEQVR4nO3bMQrCUBRE0Yla6AYEN2nnBrTL+izcitW3MRDkEUWSvPzJvfCqgMwhZbAppWhNbbIHzB1g9wATERFRVyvpkj1irlpJ5X326D7WHh1hbdFD2CLpLmmftm7kfsEe09aNHFiBrT+wAlt/YAW2/sAKbP2BFdj6Ayuwy+ufz6XPL893krZ//O6iu2n4LT8kndLWTRTo4EC7BDo40C6BDg60S6CDA+0S6OBAuwQ6uNWiD2nrJmoIfU7cNWkR2hbb1UfbY7uuWhGWiIg+a/iHuHmA3QPs3gu4JW9Gan+OJAAAAABJRU5ErkJggg==' },
|
|
90
|
+
style: [styles.backButtonImage, { tintColor: backButtonColor }]
|
|
91
|
+
}))
|
|
92
|
+
: null
|
|
93
|
+
|
|
94
|
+
return createElement(ReactNative.View, {
|
|
95
|
+
style: [styles.header, {
|
|
96
|
+
paddingTop: safeAreaTop,
|
|
97
|
+
backgroundColor: innerPageConfig.navigationBarBackgroundColor || '#000000'
|
|
98
|
+
}]
|
|
99
|
+
},
|
|
100
|
+
createElement(ReactNative.View, {
|
|
101
|
+
style: styles.headerContent,
|
|
102
|
+
height: getTitleHeight()
|
|
103
|
+
}, backElement,
|
|
104
|
+
createElement(ReactNative.Text, {
|
|
105
|
+
style: [styles.title, { color: innerPageConfig.navigationBarTextStyle || 'white' }]
|
|
106
|
+
}, innerPageConfig.navigationBarTitleText?.trim() || ''))
|
|
107
|
+
)
|
|
108
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createNativeStackNavigator } from '@react-navigation/native-stack'
|
|
2
2
|
import { NavigationContainer, StackActions } from '@react-navigation/native'
|
|
3
3
|
import PortalHost from '@mpxjs/webpack-plugin/lib/runtime/components/react/dist/mpx-portal/portal-host'
|
|
4
4
|
import { useHeaderHeight } from '@react-navigation/elements'
|
|
@@ -6,7 +6,7 @@ import { SafeAreaProvider, useSafeAreaInsets } from 'react-native-safe-area-cont
|
|
|
6
6
|
import { GestureHandlerRootView } from 'react-native-gesture-handler'
|
|
7
7
|
|
|
8
8
|
export {
|
|
9
|
-
|
|
9
|
+
createNativeStackNavigator,
|
|
10
10
|
NavigationContainer,
|
|
11
11
|
useHeaderHeight,
|
|
12
12
|
StackActions,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createNativeStackNavigator
|
|
1
|
+
import { createNativeStackNavigator } from '@react-navigation/native-stack'
|
|
2
2
|
import { NavigationContainer, StackActions } from '@react-navigation/native'
|
|
3
3
|
import PortalHost from '@mpxjs/webpack-plugin/lib/runtime/components/react/dist/mpx-portal/portal-host'
|
|
4
4
|
import { useHeaderHeight } from '@react-navigation/elements'
|
|
@@ -6,7 +6,7 @@ import { SafeAreaProvider, useSafeAreaInsets } from 'react-native-safe-area-cont
|
|
|
6
6
|
import { GestureHandlerRootView } from 'react-native-gesture-handler'
|
|
7
7
|
|
|
8
8
|
export {
|
|
9
|
-
|
|
9
|
+
createNativeStackNavigator,
|
|
10
10
|
NavigationContainer,
|
|
11
11
|
useHeaderHeight,
|
|
12
12
|
StackActions,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useEffect,
|
|
1
|
+
import { useEffect, useSyncExternalStore, useRef, useMemo, createElement, memo, forwardRef, useImperativeHandle, useContext, Fragment, cloneElement, createContext } from 'react'
|
|
2
2
|
import * as ReactNative from 'react-native'
|
|
3
3
|
import { ReactiveEffect } from '../../observer/effect'
|
|
4
4
|
import { watch } from '../../observer/watch'
|
|
@@ -15,7 +15,8 @@ import {
|
|
|
15
15
|
KeyboardAvoidContext,
|
|
16
16
|
RouteContext
|
|
17
17
|
} from '@mpxjs/webpack-plugin/lib/runtime/components/react/dist/context'
|
|
18
|
-
import { PortalHost, useSafeAreaInsets, GestureHandlerRootView
|
|
18
|
+
import { PortalHost, useSafeAreaInsets, GestureHandlerRootView } from '../env/navigationHelper'
|
|
19
|
+
import { innerNav, useInnerHeaderHeight } from '../env/nav'
|
|
19
20
|
|
|
20
21
|
const ProviderContext = createContext(null)
|
|
21
22
|
function getSystemInfo () {
|
|
@@ -51,7 +52,7 @@ function createEffect (proxy, components) {
|
|
|
51
52
|
if (tagName === 'block') return Fragment
|
|
52
53
|
const appComponents = global.__getAppComponents?.() || {}
|
|
53
54
|
const generichash = proxy.target.generichash || ''
|
|
54
|
-
const genericComponents = global.__mpxGenericsMap[generichash] || noop
|
|
55
|
+
const genericComponents = global.__mpxGenericsMap?.[generichash] || noop
|
|
55
56
|
return components[tagName] || genericComponents(tagName) || appComponents[tagName] || getByPath(ReactNative, tagName)
|
|
56
57
|
}
|
|
57
58
|
const innerCreateElement = (type, ...rest) => {
|
|
@@ -445,9 +446,28 @@ const checkRelation = (options) => {
|
|
|
445
446
|
hasAncestorRelation
|
|
446
447
|
}
|
|
447
448
|
}
|
|
449
|
+
function getLayoutData (headerHeight) {
|
|
450
|
+
const screenDimensions = ReactNative.Dimensions.get('screen')
|
|
451
|
+
const windowDimensions = ReactNative.Dimensions.get('window')
|
|
452
|
+
// 在横屏状态下 screen.height = window.height + bottomVirtualHeight
|
|
453
|
+
// 在正常状态 screen.height = window.height + bottomVirtualHeight + statusBarHeight
|
|
454
|
+
const isLandscape = screenDimensions.height < screenDimensions.width
|
|
455
|
+
const bottomVirtualHeight = isLandscape ? screenDimensions.height - windowDimensions.height : ((screenDimensions.height - windowDimensions.height - ReactNative.StatusBar.currentHeight) || 0)
|
|
456
|
+
return {
|
|
457
|
+
x: 0,
|
|
458
|
+
y: headerHeight,
|
|
459
|
+
left: 0,
|
|
460
|
+
top: headerHeight,
|
|
461
|
+
// 此处必须为windowDimensions.width,在横屏状态下windowDimensions.width才符合预期
|
|
462
|
+
width: windowDimensions.width,
|
|
463
|
+
height: screenDimensions.height - headerHeight - bottomVirtualHeight,
|
|
464
|
+
// ios为0 android为实际statusbar高度
|
|
465
|
+
statusBarHeight: ReactNative.StatusBar.currentHeight || 0,
|
|
466
|
+
bottomVirtualHeight: bottomVirtualHeight,
|
|
467
|
+
isLandscape: isLandscape
|
|
468
|
+
}
|
|
469
|
+
}
|
|
448
470
|
|
|
449
|
-
// 临时用来存储安卓底部(iOS没有这个)的高度(虚拟按键等高度)根据第一次进入推算
|
|
450
|
-
let bottomVirtualHeight = null
|
|
451
471
|
export function PageWrapperHOC (WrappedComponent) {
|
|
452
472
|
return function PageWrapperCom ({ navigation, route, pageConfig = {}, ...props }) {
|
|
453
473
|
const rootRef = useRef(null)
|
|
@@ -464,59 +484,15 @@ export function PageWrapperHOC (WrappedComponent) {
|
|
|
464
484
|
error('Using pageWrapper requires passing navigation and route')
|
|
465
485
|
return null
|
|
466
486
|
}
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
navigation.setOptions({
|
|
470
|
-
title: currentPageConfig.navigationBarTitleText?.trim() || '',
|
|
471
|
-
headerStyle: {
|
|
472
|
-
backgroundColor: currentPageConfig.navigationBarBackgroundColor || '#000000'
|
|
473
|
-
},
|
|
474
|
-
headerTintColor: currentPageConfig.navigationBarTextStyle || 'white'
|
|
475
|
-
})
|
|
476
|
-
|
|
477
|
-
// TODO 此部分内容在native-stack可删除,用setOptions设置
|
|
478
|
-
if (__mpx_mode__ !== 'ios') {
|
|
479
|
-
ReactNative.StatusBar.setBarStyle(currentPageConfig.barStyle || 'dark-content')
|
|
480
|
-
ReactNative.StatusBar.setTranslucent(true) // 控制statusbar是否占位
|
|
481
|
-
ReactNative.StatusBar.setBackgroundColor('transparent')
|
|
482
|
-
}
|
|
483
|
-
}, [])
|
|
484
|
-
|
|
485
|
-
const headerHeight = useHeaderHeight()
|
|
487
|
+
const headerHeight = useInnerHeaderHeight(currentPageConfig)
|
|
488
|
+
navigation.layout = getLayoutData(headerHeight)
|
|
486
489
|
const onLayout = () => {
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
navigation.layout = {
|
|
490
|
-
x: 0,
|
|
491
|
-
y: headerHeight,
|
|
492
|
-
width: screenDimensions.width,
|
|
493
|
-
height: screenDimensions.height - headerHeight
|
|
494
|
-
}
|
|
495
|
-
} else {
|
|
496
|
-
if (bottomVirtualHeight === null) {
|
|
497
|
-
rootRef.current?.measureInWindow((x, y, width, height) => {
|
|
498
|
-
// 沉浸模式的计算方式
|
|
499
|
-
bottomVirtualHeight = screenDimensions.height - height - headerHeight
|
|
500
|
-
// 非沉浸模式(translucent=true)计算方式, 现在默认是全用沉浸模式,所以先不算这个
|
|
501
|
-
// bottomVirtualHeight = windowDimensions.height - height - headerHeight
|
|
502
|
-
navigation.layout = {
|
|
503
|
-
x: 0,
|
|
504
|
-
y: headerHeight,
|
|
505
|
-
width: screenDimensions.width,
|
|
506
|
-
height: height
|
|
507
|
-
}
|
|
508
|
-
})
|
|
509
|
-
} else {
|
|
510
|
-
navigation.layout = {
|
|
511
|
-
x: 0,
|
|
512
|
-
y: headerHeight, // 这个y值
|
|
513
|
-
width: screenDimensions.width,
|
|
514
|
-
// 后续页面的layout是通过第一次路由进入时候推算出来的底部区域来推算出来的
|
|
515
|
-
height: screenDimensions.height - bottomVirtualHeight - headerHeight
|
|
516
|
-
}
|
|
517
|
-
}
|
|
518
|
-
}
|
|
490
|
+
// 当用户处于横屏或者竖屏状态的时候,需要进行layout修正
|
|
491
|
+
navigation.layout = getLayoutData(headerHeight)
|
|
519
492
|
}
|
|
493
|
+
|
|
494
|
+
usePageStatus(navigation, currentPageId)
|
|
495
|
+
|
|
520
496
|
const withKeyboardAvoidingView = (element) => {
|
|
521
497
|
return createElement(KeyboardAvoidContext.Provider,
|
|
522
498
|
{
|
|
@@ -535,26 +511,26 @@ export function PageWrapperHOC (WrappedComponent) {
|
|
|
535
511
|
)
|
|
536
512
|
)
|
|
537
513
|
}
|
|
538
|
-
|
|
514
|
+
// android存在第一次打开insets都返回为0情况,后续会触发第二次渲染后正确
|
|
539
515
|
navigation.insets = useSafeAreaInsets()
|
|
540
|
-
|
|
541
516
|
return createElement(GestureHandlerRootView,
|
|
542
517
|
{
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
height: ReactNative.Dimensions.get('screen').height - useHeaderHeight()
|
|
547
|
-
}
|
|
548
|
-
: {
|
|
549
|
-
flex: 1
|
|
550
|
-
}
|
|
518
|
+
style: {
|
|
519
|
+
flex: 1
|
|
520
|
+
}
|
|
551
521
|
},
|
|
522
|
+
createElement(innerNav, {
|
|
523
|
+
props: { pageConfig: currentPageConfig },
|
|
524
|
+
navigation
|
|
525
|
+
}),
|
|
552
526
|
withKeyboardAvoidingView(
|
|
553
527
|
createElement(ReactNative.View,
|
|
554
528
|
{
|
|
555
529
|
style: {
|
|
556
530
|
flex: 1,
|
|
557
|
-
backgroundColor: currentPageConfig?.backgroundColor || '#fff'
|
|
531
|
+
backgroundColor: currentPageConfig?.backgroundColor || '#fff',
|
|
532
|
+
// 解决页面内有元素定位relative left为负值的时候,回退的时候还能看到对应元素问题
|
|
533
|
+
overflow: 'hidden'
|
|
558
534
|
},
|
|
559
535
|
ref: rootRef,
|
|
560
536
|
onLayout
|
|
@@ -582,7 +558,6 @@ export function PageWrapperHOC (WrappedComponent) {
|
|
|
582
558
|
))
|
|
583
559
|
}
|
|
584
560
|
}
|
|
585
|
-
|
|
586
561
|
export function getDefaultOptions ({ type, rawOptions = {}, currentInject }) {
|
|
587
562
|
rawOptions = mergeOptions(rawOptions, type, false)
|
|
588
563
|
const components = Object.assign({}, rawOptions.components, currentInject.getComponents())
|
|
@@ -656,8 +631,13 @@ export function getDefaultOptions ({ type, rawOptions = {}, currentInject }) {
|
|
|
656
631
|
return () => {
|
|
657
632
|
proxy.unmounted()
|
|
658
633
|
proxy.target.__resetInstance()
|
|
634
|
+
// 热更新下会销毁旧页面并创建新页面组件,且旧页面组件销毁时机晚于新页面组件创建,此时__mpxPagesMap中存储的为新页面组件,不应该删除
|
|
635
|
+
// 所以需要判断路由表中存储的页面实例是否为当前页面实例
|
|
659
636
|
if (type === 'page') {
|
|
660
|
-
|
|
637
|
+
const routeKey = props.route.key
|
|
638
|
+
if (global.__mpxPagesMap[routeKey] && global.__mpxPagesMap[routeKey][0] === instance) {
|
|
639
|
+
delete global.__mpxPagesMap[routeKey]
|
|
640
|
+
}
|
|
661
641
|
}
|
|
662
642
|
}
|
|
663
643
|
}, [])
|