@mpxjs/core 2.9.67 → 2.9.69-beta.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.
Files changed (40) hide show
  1. package/package.json +19 -7
  2. package/src/convertor/convertor.js +11 -32
  3. package/src/convertor/wxToAli.js +3 -3
  4. package/src/convertor/wxToReact.js +1 -1
  5. package/src/convertor/wxToSwan.js +3 -3
  6. package/src/convertor/wxToWeb.js +3 -3
  7. package/src/core/proxy.js +18 -12
  8. package/src/dynamic/dynamicRenderMixin.js +2 -2
  9. package/src/index.js +3 -14
  10. package/src/observer/reactive.js +5 -4
  11. package/src/observer/ref.js +3 -2
  12. package/src/observer/scheduler.js +4 -0
  13. package/src/observer/watch.js +5 -4
  14. package/src/platform/builtInMixins/directiveHelperMixin.ios.js +4 -1
  15. package/src/platform/builtInMixins/styleHelperMixin.ios.js +28 -25
  16. package/src/platform/createApp.ios.js +57 -23
  17. package/src/platform/createApp.js +7 -9
  18. package/src/platform/env/event.js +108 -0
  19. package/src/platform/env/index.ios.js +51 -0
  20. package/src/platform/env/index.js +8 -0
  21. package/src/platform/env/index.web.js +48 -0
  22. package/src/{external → platform/env}/vuePlugin.js +1 -1
  23. package/src/platform/export/index.js +1 -1
  24. package/src/platform/patch/{ali/getDefaultOptions.js → getDefaultOptions.ali.js} +3 -3
  25. package/src/platform/patch/{react/getDefaultOptions.ios.js → getDefaultOptions.ios.js} +264 -191
  26. package/src/platform/patch/{wx/getDefaultOptions.js → getDefaultOptions.js} +11 -7
  27. package/src/platform/patch/{web/getDefaultOptions.js → getDefaultOptions.web.js} +5 -5
  28. package/src/platform/patch/index.js +4 -21
  29. package/src/platform/patch/{ali/lifecycle.js → lifecycle/index.ali.js} +2 -0
  30. package/src/platform/patch/lifecycle/index.js +1 -0
  31. package/src/platform/patch/{swan/lifecycle.js → lifecycle/index.swan.js} +2 -0
  32. package/src/platform/patch/{web/lifecycle.js → lifecycle/index.web.js} +4 -0
  33. package/src/platform/patch/{wx/lifecycle.js → lifecycle/index.wx.js} +2 -0
  34. package/LICENSE +0 -433
  35. package/src/external/vue.js +0 -1
  36. package/src/external/vue.web.js +0 -6
  37. package/src/platform/patch/react/getDefaultOptions.js +0 -1
  38. package/src/platform/patch/swan/getDefaultOptions.js +0 -34
  39. /package/src/platform/export/{apiInject.js → inject.js} +0 -0
  40. /package/src/platform/export/{apiInject.web.js → inject.web.js} +0 -0
@@ -1,14 +1,15 @@
1
1
  import transferOptions from '../core/transferOptions'
2
2
  import builtInKeysMap from './patch/builtInKeysMap'
3
- import { makeMap, spreadProp, parseUrlQuery } from '@mpxjs/utils'
3
+ import { makeMap, spreadProp, parseUrlQuery, getFocusedNavigation, hasOwn, extend } from '@mpxjs/utils'
4
4
  import { mergeLifecycle } from '../convertor/mergeLifecycle'
5
- import * as wxLifecycle from '../platform/patch/wx/lifecycle'
5
+ import { LIFECYCLE } from '../platform/patch/lifecycle/index'
6
6
  import Mpx from '../index'
7
7
  import { createElement, memo, useRef, useEffect } from 'react'
8
8
  import * as ReactNative from 'react-native'
9
+ import { Image } from 'react-native'
9
10
  import { ref } from '../observer/ref'
10
11
 
11
- const appHooksMap = makeMap(mergeLifecycle(wxLifecycle.LIFECYCLE).app)
12
+ const appHooksMap = makeMap(mergeLifecycle(LIFECYCLE).app)
12
13
 
13
14
  function getOrientation (window = ReactNative.Dimensions.get('window')) {
14
15
  return window.width > window.height ? 'landscape' : 'portrait'
@@ -30,11 +31,7 @@ function filterOptions (options, appData) {
30
31
  }
31
32
 
32
33
  function createAppInstance (appData) {
33
- const instance = {
34
- ...Mpx.prototype,
35
- ...appData
36
- }
37
- return instance
34
+ return extend({}, Mpx.prototype, appData)
38
35
  }
39
36
 
40
37
  export default function createApp (option, config = {}) {
@@ -84,12 +81,6 @@ export default function createApp (option, config = {}) {
84
81
  }
85
82
  }
86
83
 
87
- global.__mpxAppCbs = global.__mpxAppCbs || {
88
- show: [],
89
- hide: [],
90
- error: []
91
- }
92
-
93
84
  global.__mpxAppLaunched = false
94
85
 
95
86
  global.__mpxAppFocusedState = ref('show')
@@ -140,18 +131,39 @@ export default function createApp (option, config = {}) {
140
131
  if (defaultOptions.onError) {
141
132
  global.__mpxAppCbs.error.push(defaultOptions.onError.bind(instance))
142
133
  }
134
+ if (defaultOptions.onUnhandledRejection) {
135
+ global.__mpxAppCbs.rejection.push(defaultOptions.onUnhandledRejection.bind(instance))
136
+ }
143
137
 
144
138
  const changeSubscription = ReactNative.AppState.addEventListener('change', (currentState) => {
145
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
+ }
146
153
  global.__mpxAppCbs.show.forEach((cb) => {
147
- cb(global.__mpxEnterOptions)
154
+ cb(options)
148
155
  })
149
- global.__mpxAppFocusedState.value = 'show'
150
- } else if (currentState === 'inactive') {
156
+ if (navigation && hasOwn(global.__mpxPageStatusMap, navigation.pageId)) {
157
+ global.__mpxPageStatusMap[navigation.pageId] = 'show'
158
+ }
159
+ } else if (currentState === 'inactive' || currentState === 'background') {
151
160
  global.__mpxAppCbs.hide.forEach((cb) => {
152
161
  cb()
153
162
  })
154
- global.__mpxAppFocusedState.value = 'hide'
163
+ const navigation = getFocusedNavigation()
164
+ if (navigation && hasOwn(global.__mpxPageStatusMap, navigation.pageId)) {
165
+ global.__mpxPageStatusMap[navigation.pageId] = 'hide'
166
+ }
155
167
  }
156
168
  })
157
169
 
@@ -161,7 +173,10 @@ export default function createApp (option, config = {}) {
161
173
  const orientation = getOrientation(window)
162
174
  if (orientation === lastOrientation) return
163
175
  lastOrientation = orientation
164
- global.__mpxAppFocusedState.value = `resize${count++}`
176
+ const navigation = getFocusedNavigation()
177
+ if (navigation && hasOwn(global.__mpxPageStatusMap, navigation.pageId)) {
178
+ global.__mpxPageStatusMap[navigation.pageId] = `resize${count++}`
179
+ }
165
180
  })
166
181
  return () => {
167
182
  changeSubscription && changeSubscription.remove()
@@ -170,6 +185,20 @@ export default function createApp (option, config = {}) {
170
185
  }, [])
171
186
 
172
187
  const { initialRouteName, initialParams } = initialRouteRef.current
188
+ const headerBackImageProps = Mpx.config.rnConfig.headerBackImageProps || null
189
+ const navScreenOpts = {
190
+ gestureEnabled: true,
191
+ // 7.x替换headerBackTitleVisible
192
+ // headerBackButtonDisplayMode: 'minimal',
193
+ headerBackTitleVisible: false,
194
+ // 安卓上会出现初始化时闪现导航条的问题
195
+ headerShown: false
196
+ }
197
+ if (headerBackImageProps) {
198
+ navScreenOpts.headerBackImage = () => {
199
+ return createElement(Image, headerBackImageProps)
200
+ }
201
+ }
173
202
  return createElement(SafeAreaProvider,
174
203
  null,
175
204
  createElement(NavigationContainer,
@@ -180,9 +209,7 @@ export default function createApp (option, config = {}) {
180
209
  createElement(Stack.Navigator,
181
210
  {
182
211
  initialRouteName,
183
- headerBackButtonDisplayMode: 'minimal',
184
- headerMode: 'float',
185
- gestureEnabled: true
212
+ screenOptions: navScreenOpts
186
213
  },
187
214
  ...getPageScreens(initialRouteName, initialParams)
188
215
  )
@@ -191,7 +218,7 @@ export default function createApp (option, config = {}) {
191
218
  })
192
219
 
193
220
  global.getCurrentPages = function () {
194
- const navigation = Object.values(global.__mpxPagesMap || {})[0]?.[1]
221
+ const navigation = getFocusedNavigation()
195
222
  if (navigation) {
196
223
  return navigation.getState().routes.map((route) => {
197
224
  return global.__mpxPagesMap[route.key] && global.__mpxPagesMap[route.key][0]
@@ -199,4 +226,11 @@ export default function createApp (option, config = {}) {
199
226
  }
200
227
  return []
201
228
  }
229
+
230
+ global.setCurrentPageStatus = function (status) {
231
+ const navigation = getFocusedNavigation()
232
+ if (navigation && hasOwn(global.__mpxPageStatusMap, navigation.pageId)) {
233
+ global.__mpxPageStatusMap[navigation.pageId] = status
234
+ }
235
+ }
202
236
  }
@@ -3,11 +3,11 @@ import mergeOptions from '../core/mergeOptions'
3
3
  import builtInKeysMap from './patch/builtInKeysMap'
4
4
  import { makeMap, spreadProp, isBrowser } from '@mpxjs/utils'
5
5
  import { mergeLifecycle } from '../convertor/mergeLifecycle'
6
- import * as webLifecycle from '../platform/patch/web/lifecycle'
6
+ import { LIFECYCLE } from '../platform/patch/lifecycle/index'
7
7
  import Mpx from '../index'
8
- import { initAppProvides } from './export/apiInject'
8
+ import { initAppProvides } from './export/inject'
9
9
 
10
- const webAppHooksMap = makeMap(mergeLifecycle(webLifecycle.LIFECYCLE).app)
10
+ const appHooksMap = makeMap(mergeLifecycle(LIFECYCLE).app)
11
11
 
12
12
  function filterOptions (options, appData) {
13
13
  const newOptions = {}
@@ -15,7 +15,7 @@ function filterOptions (options, appData) {
15
15
  if (builtInKeysMap[key]) {
16
16
  return
17
17
  }
18
- if (__mpx_mode__ === 'web' && !webAppHooksMap[key] && key !== 'provide') {
18
+ if (__mpx_mode__ === 'web' && !appHooksMap[key] && key !== 'provide') {
19
19
  appData[key] = options[key]
20
20
  } else {
21
21
  newOptions[key] = options[key]
@@ -47,11 +47,6 @@ export default function createApp (option, config = {}) {
47
47
  }
48
48
  global.__mpxEnterOptions = options
49
49
  this.$options.onLaunch && this.$options.onLaunch.call(this, options)
50
- global.__mpxAppCbs = global.__mpxAppCbs || {
51
- show: [],
52
- hide: [],
53
- error: []
54
- }
55
50
  if (isBrowser) {
56
51
  if (this.$options.onShow) {
57
52
  this.$options.onShow.call(this, options)
@@ -63,6 +58,9 @@ export default function createApp (option, config = {}) {
63
58
  if (this.$options.onError) {
64
59
  global.__mpxAppCbs.error.push(this.$options.onError.bind(this))
65
60
  }
61
+ if (this.$options.onUnhandledRejection) {
62
+ global.__mpxAppCbs.rejection.push(this.$options.onUnhandledRejection.bind(this))
63
+ }
66
64
  }
67
65
  }
68
66
  })
@@ -0,0 +1,108 @@
1
+ import { isBrowser } from '@mpxjs/utils'
2
+
3
+ function extendEvent (e, extendObj = {}) {
4
+ Object.keys(extendObj).forEach((key) => {
5
+ Object.defineProperty(e, key, {
6
+ value: extendObj[key],
7
+ enumerable: true,
8
+ configurable: true,
9
+ writable: true
10
+ })
11
+ })
12
+ }
13
+
14
+ function MpxEvent (layer) {
15
+ this.targetElement = null
16
+ this.touches = []
17
+ this.touchStartX = 0
18
+ this.touchStartY = 0
19
+ this.startTimer = null
20
+ this.needTap = true
21
+ this.isTouchDevice = document && ('ontouchstart' in document.documentElement)
22
+
23
+ this.onTouchStart = (event) => {
24
+ if (event.targetTouches?.length > 1) {
25
+ return true
26
+ }
27
+ this.touches = event.targetTouches
28
+ this.targetElement = event.target
29
+ this.needTap = true
30
+ this.startTimer = null
31
+ this.touchStartX = this.touches[0].pageX
32
+ this.touchStartY = this.touches[0].pageY
33
+ this.startTimer = setTimeout(() => {
34
+ this.needTap = false
35
+ this.sendEvent(this.targetElement, 'longpress', event)
36
+ this.sendEvent(this.targetElement, 'longtap', event)
37
+ }, 350)
38
+ }
39
+
40
+ this.onTouchMove = (event) => {
41
+ const touch = event.changedTouches[0]
42
+ if (Math.abs(touch.pageX - this.touchStartX) > 1 || Math.abs(touch.pageY - this.touchStartY) > 1) {
43
+ this.needTap = false
44
+ this.startTimer && clearTimeout(this.startTimer)
45
+ this.startTimer = null
46
+ }
47
+ }
48
+
49
+ this.onTouchEnd = (event) => {
50
+ if (event.targetTouches?.length > 1) {
51
+ return true
52
+ }
53
+ this.startTimer && clearTimeout(this.startTimer)
54
+ this.startTimer = null
55
+ if (this.needTap) {
56
+ this.sendEvent(this.targetElement, 'tap', event)
57
+ }
58
+ }
59
+
60
+ this.onClick = (event) => {
61
+ this.targetElement = event.target
62
+ this.sendEvent(this.targetElement, 'tap', event)
63
+ }
64
+ this.sendEvent = (targetElement, type, event) => {
65
+ const touchEvent = new CustomEvent(type, {
66
+ bubbles: true,
67
+ cancelable: true
68
+ })
69
+ const changedTouches = event.changedTouches || []
70
+ extendEvent(touchEvent, {
71
+ timeStamp: event.timeStamp,
72
+ changedTouches,
73
+ touches: changedTouches,
74
+ detail: {
75
+ // pc端点击事件可能没有changedTouches,所以直接从 event中取
76
+ x: changedTouches[0]?.pageX || event.pageX || 0,
77
+ y: changedTouches[0]?.pageY || event.pageY || 0
78
+ }
79
+ })
80
+ targetElement && targetElement.dispatchEvent(touchEvent)
81
+ }
82
+
83
+ this.addListener = () => {
84
+ if (this.isTouchDevice) {
85
+ layer.addEventListener('touchstart', this.onTouchStart, true)
86
+ layer.addEventListener('touchmove', this.onTouchMove, true)
87
+ layer.addEventListener('touchend', this.onTouchEnd, true)
88
+ } else {
89
+ layer.addEventListener('click', this.onClick, true)
90
+ }
91
+ }
92
+ this.addListener()
93
+ }
94
+
95
+ export function initEvent () {
96
+ if (isBrowser && !global.__mpxCreatedEvent) {
97
+ global.__mpxCreatedEvent = true
98
+ if (document.readyState === 'complete' || document.readyState === 'interactive') {
99
+ // eslint-disable-next-line no-new
100
+ new MpxEvent(document.body)
101
+ } else {
102
+ document.addEventListener('DOMContentLoaded', function () {
103
+ // eslint-disable-next-line no-new
104
+ new MpxEvent(document.body)
105
+ }, false)
106
+ }
107
+ }
108
+ }
@@ -0,0 +1,51 @@
1
+ import { createI18n } from '../builtInMixins/i18nMixin'
2
+
3
+ export function init (Mpx) {
4
+ global.__mpx = Mpx
5
+ global.__mpxAppCbs = global.__mpxAppCbs || {
6
+ show: [],
7
+ hide: [],
8
+ error: [],
9
+ rejection: []
10
+ }
11
+ if (global.i18n) {
12
+ Mpx.i18n = createI18n(global.i18n)
13
+ }
14
+ initGlobalErrorHandling()
15
+ }
16
+
17
+ function initGlobalErrorHandling () {
18
+ if (global.ErrorUtils) {
19
+ const defaultHandler = global.ErrorUtils.getGlobalHandler()
20
+ global.ErrorUtils.setGlobalHandler((error, isFatal) => {
21
+ if (global.__mpxAppCbs && global.__mpxAppCbs.error && global.__mpxAppCbs.error.length) {
22
+ global.__mpxAppCbs.error.forEach((cb) => {
23
+ cb(error)
24
+ })
25
+ } else if (defaultHandler) {
26
+ defaultHandler(error, isFatal)
27
+ } else {
28
+ console.error(`${error.name}: ${error.message}\n`)
29
+ }
30
+ })
31
+ }
32
+
33
+ const rejectionTrackingOptions = {
34
+ allRejections: true,
35
+ onUnhandled (id, error) {
36
+ if (global.__mpxAppCbs && global.__mpxAppCbs.rejection && global.__mpxAppCbs.rejection.length) {
37
+ global.__mpxAppCbs.rejection.forEach((cb) => {
38
+ cb(error, id)
39
+ })
40
+ } else {
41
+ console.warn(`UNHANDLED PROMISE REJECTION (id: ${id}): ${error}\n`)
42
+ }
43
+ }
44
+ }
45
+
46
+ if (global?.HermesInternal?.hasPromise?.()) {
47
+ global.HermesInternal?.enablePromiseRejectionTracker?.(rejectionTrackingOptions)
48
+ } else {
49
+ require('promise/setimmediate/rejection-tracking').enable(rejectionTrackingOptions)
50
+ }
51
+ }
@@ -0,0 +1,8 @@
1
+ import { createI18n } from '../builtInMixins/i18nMixin'
2
+
3
+ export function init (Mpx) {
4
+ global.__mpx = Mpx
5
+ if (global.i18n) {
6
+ Mpx.i18n = createI18n(global.i18n)
7
+ }
8
+ }
@@ -0,0 +1,48 @@
1
+ import Vue from 'vue'
2
+ import install from './vuePlugin'
3
+ import { isBrowser, error, warn } from '@mpxjs/utils'
4
+ import { initEvent } from './event'
5
+
6
+ export function init (Mpx) {
7
+ global.__mpx = Mpx
8
+ global.__mpxAppCbs = global.__mpxAppCbs || {
9
+ show: [],
10
+ hide: [],
11
+ error: [],
12
+ rejection: []
13
+ }
14
+ Mpx.__vue = Vue
15
+ Vue.use(install)
16
+ initEvent()
17
+ initGlobalErrorHandling()
18
+ }
19
+
20
+ function initGlobalErrorHandling () {
21
+ Vue.config.errorHandler = (e, vm, info) => {
22
+ error(`Unhandled error occurs${info ? ` during execution of [${info}]` : ''}!`, vm?.__mpxProxy?.options.mpxFileResource, e)
23
+ }
24
+ Vue.config.warnHandler = (msg, vm, trace) => {
25
+ warn(msg, vm?.__mpxProxy?.options.mpxFileResource, trace)
26
+ }
27
+
28
+ if (isBrowser) {
29
+ window.addEventListener('error', (event) => {
30
+ if (global.__mpxAppCbs && global.__mpxAppCbs.error && global.__mpxAppCbs.error.length) {
31
+ global.__mpxAppCbs.error.forEach((cb) => {
32
+ cb(event.error)
33
+ })
34
+ } else {
35
+ console.error(`${event.type}: ${event.message}\n`)
36
+ }
37
+ })
38
+ window.addEventListener('unhandledrejection', (event) => {
39
+ if (global.__mpxAppCbs && global.__mpxAppCbs.rejection && global.__mpxAppCbs.rejection.length) {
40
+ global.__mpxAppCbs.rejection.forEach((cb) => {
41
+ cb(event.reason, event.promise)
42
+ })
43
+ } else {
44
+ console.warn(`UNHANDLED PROMISE REJECTION: ${event.reason}\n`)
45
+ }
46
+ })
47
+ }
48
+ }
@@ -1,7 +1,7 @@
1
1
  import { walkChildren, parseSelector, error, hasOwn, collectDataset } from '@mpxjs/utils'
2
2
  import { createSelectorQuery, createIntersectionObserver } from '@mpxjs/api-proxy'
3
3
  import { EffectScope } from 'vue'
4
- import { PausedState } from '../helper/const'
4
+ import { PausedState } from '../../helper/const'
5
5
 
6
6
  const hackEffectScope = () => {
7
7
  EffectScope.prototype.pause = function () {
@@ -46,4 +46,4 @@ export {
46
46
  export {
47
47
  provide,
48
48
  inject
49
- } from './apiInject'
49
+ } from './inject'
@@ -1,6 +1,6 @@
1
- import MpxProxy from '../../../core/proxy'
2
- import builtInKeysMap from '../builtInKeysMap'
3
- import mergeOptions from '../../../core/mergeOptions'
1
+ import MpxProxy from '../../core/proxy'
2
+ import builtInKeysMap from './builtInKeysMap'
3
+ import mergeOptions from '../../core/mergeOptions'
4
4
  import { error, diffAndCloneA, hasOwn, noop, wrapMethodsWithErrorHandling } from '@mpxjs/utils'
5
5
 
6
6
  function transformApiForProxy (context, currentInject) {