Skip to content

Commit

Permalink
改造portal
Browse files Browse the repository at this point in the history
  • Loading branch information
wangcuijuan committed Jan 21, 2025
1 parent 638bc95 commit 34f1e0a
Show file tree
Hide file tree
Showing 9 changed files with 118 additions and 35 deletions.
12 changes: 11 additions & 1 deletion packages/api-proxy/src/common/js/utils.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { hasOwn, noop, getEnvObj, getFocusedNavigation } from '@mpxjs/utils'
import { getCurrentInstance } from '@mpxjs/core'

/**
*
Expand Down Expand Up @@ -87,6 +88,14 @@ function failHandle (result, fail, complete) {
typeof complete === 'function' && complete(result)
}

function getPageId () {
const navigation = getFocusedNavigation()
const currentInstance = getCurrentInstance()
console.log(currentInstance, currentInstance?.getPageId, navigation, navigation?.pageId)
const id = currentInstance?.getPageId || navigation?.pageId || null
return id
}

const ENV_OBJ = getEnvObj()

export {
Expand All @@ -101,5 +110,6 @@ export {
defineUnsupportedProps,
successHandle,
failHandle,
getFocusedNavigation
getFocusedNavigation,
getPageId
}
14 changes: 11 additions & 3 deletions packages/api-proxy/src/platform/api/action-sheet/rnActionSheet.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { View, Text, StyleSheet } from 'react-native'
import { successHandle, failHandle } from '../../../common/js'
import { successHandle, failHandle, getPageId, error } from '../../../common/js'
import Portal from '@mpxjs/webpack-plugin/lib/runtime/components/react/dist/mpx-portal/index'
import { getWindowInfo } from '../system/rnSystem'
import Animated, {
Expand All @@ -9,7 +9,16 @@ import Animated, {
} from 'react-native-reanimated'

function showActionSheet (options = {}) {
const id = getPageId()
const { alertText, itemList = [], itemColor = '#000000', success, fail, complete } = options
if (id === null) {
error('showActionSheet cannot be invoked outside the mpx life cycle in React Native environments')
const result = {
errMsg: 'showActionSheet:fail cannot be invoked outside the mpx life cycle in React Native environments'
}
failHandle(result, fail, complete)
return
}
if (itemList.length > 6) {
const result = {
errMsg: 'showActionSheet:fail parameter error: itemList should not be large than 6'
Expand Down Expand Up @@ -116,8 +125,7 @@ function showActionSheet (options = {}) {
</View>
)
}

actionSheetKey = Portal.add(<ActionSheet/>)
actionSheetKey = Portal.add(<ActionSheet />, id)
}

export {
Expand Down
13 changes: 11 additions & 2 deletions packages/api-proxy/src/platform/api/modal/rnModal.jsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { View, Dimensions, Text, StyleSheet, TouchableOpacity, ScrollView, TextInput } from 'react-native'
import { successHandle, failHandle } from '../../../common/js'
import { successHandle, failHandle, getPageId, error } from '../../../common/js'
import Portal from '@mpxjs/webpack-plugin/lib/runtime/components/react/dist/mpx-portal/index'
const { width, height } = Dimensions.get('window')
const showModal = function (options = {}) {
const id = getPageId()
const {
title,
content,
Expand All @@ -17,6 +18,14 @@ const showModal = function (options = {}) {
fail,
complete
} = options
if (id === null) {
error('showModal cannot be invoked outside the mpx life cycle in React Native environments')
const result = {
errMsg: 'showModal:fail cannot be invoked outside the mpx life cycle in React Native environments'
}
failHandle(result, fail, complete)
return
}
const modalWidth = width * 0.8
const styles = StyleSheet.create({
modalTask: {
Expand Down Expand Up @@ -156,7 +165,7 @@ const showModal = function (options = {}) {
</View>
</View>
try {
modalKey = Portal.add(ModalView)
modalKey = Portal.add(ModalView, id)
} catch (e) {
const result = {
errMsg: `showModal:fail invalid ${e}`
Expand Down
4 changes: 2 additions & 2 deletions packages/api-proxy/src/platform/api/route/index.ios.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ function resolvePath (relative, base) {
}
return stack.join('/')
}
function isLock(navigationHelper, type, options) {
function isLock (navigationHelper, type, options) {
if (navigationHelper.lastSuccessCallback && navigationHelper.lastFailCallback) {
const res = { errMsg: `${type}:fail the previous routing event didn't complete` }
failHandle(res, options.fail, options.complete)
Expand All @@ -48,7 +48,7 @@ function isLock(navigationHelper, type, options) {
return false
}

function navigateTo (options = {}) {
function navigateTo (options = {}) {
const navigationHelper = global.__navigationHelper
if (isLock(navigationHelper, 'navigateTo', options)) {
return
Expand Down
13 changes: 11 additions & 2 deletions packages/api-proxy/src/platform/api/toast/rnToast.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { View, Text, Image, StyleSheet, ActivityIndicator, Dimensions } from 'react-native'
import { successHandle, failHandle } from '../../../common/js'
import { successHandle, failHandle, getPageId, error } from '../../../common/js'
import Portal from '@mpxjs/webpack-plugin/lib/runtime/components/react/dist/mpx-portal/index'

let toastKey
Expand Down Expand Up @@ -55,7 +55,16 @@ const styles = StyleSheet.create({
})

function showToast (options = {}) {
const id = getPageId()
const { title, icon = 'success', image, duration = 1500, mask = false, success, fail, complete, isLoading } = options
if (id === null) {
error('showToast cannot be invoked outside the mpx life cycle in React Native environments')
const result = {
errMsg: 'showToast:fail cannot be invoked outside the mpx life cycle in React Native environments'
}
failHandle(result, fail, complete)
return
}
let ToastView
const successPng = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFwAAABcAgMAAACegTrLAAAADFBMVEUAAAD////R0dHj4+PcME2AAAAAAXRSTlMAQObYZgAAANNJREFUSMft1FEKwkAMBNBGyBFyH4/gR8f+ehSPLtiyQ+wM2C8Rmp+WQN90N8tOZ/1/4SbbYfpp+sBVMqafgGQKs+FvkjF8GR6aj4M8NB+GT8OX5i+GT8OX4aH5MHwZHpoPw+c3fA0xGl/zYBrP92o8vwVwF3NO8tySjXmINQLAs/WX9S8bP9UGJUZSi8MAuUqsj75payPxuWn1BmrjewCCfAvA4Fmjvx8HQL4HiJEHeRmg5k2+B8gTFeRFwL7NzREB/sCKwsG7KN2VSb7XMp31i3oBatNdEForTOoAAAAASUVORK5CYII='
const errorPng = 'data:image/png;base64,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'
Expand Down Expand Up @@ -101,7 +110,7 @@ function showToast (options = {}) {
if (toastKey) {
Portal.remove(toastKey)
}
toastKey = Portal.add(ToastView)
toastKey = Portal.add(ToastView, id)
if (!isLoading) {
tId = setTimeout(() => {
Portal.remove(toastKey)
Expand Down
5 changes: 3 additions & 2 deletions packages/core/src/platform/patch/getDefaultOptions.ios.js
Original file line number Diff line number Diff line change
Expand Up @@ -489,7 +489,6 @@ export function getDefaultOptions ({ type, rawOptions = {}, currentInject }) {
const currentPageId = useMemo(() => ++pageId, [])
const intersectionObservers = useRef({})
usePageStatus(navigation, currentPageId)

useLayoutEffect(() => {
const isCustom = pageConfig.navigationStyle === 'custom'
navigation.setOptions({
Expand Down Expand Up @@ -566,7 +565,9 @@ export function getDefaultOptions ({ type, rawOptions = {}, currentInject }) {
value: intersectionObservers.current
},
createElement(Provider,
null,
{
pageId: currentPageId
},
createElement(defaultOptions,
{
navigation,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export interface PortalManagerContextValue {
}

export interface PortalContextValue {
mount: (children: React.ReactNode, key?: number) => number| undefined
mount: (children: React.ReactNode, key?: number, id?: number) => number| undefined
update: (key: number, children: React.ReactNode) => void
unmount: (key: number) => void
manager?: PortalManagerContextValue
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { ReactNode } from 'react'
import { PortalContext, PortalContextValue } from '../context'
import PortalConsumer from './portal-consumer'
import { useNavigation } from '@react-navigation/native'
import PortalHost, { portal } from './portal-host'

export type PortalProps = {
Expand All @@ -9,10 +10,13 @@ export type PortalProps = {
*/
children?: ReactNode
key?: string
manager?: PortalContextValue
manager?: PortalContextValue,
pageId?: number
}

const Portal = ({ children }:PortalProps): JSX.Element => {
const navigation = useNavigation()
const pageId = navigation?.pageId
return (
<PortalContext.Consumer>
{(manager) => (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useEffect, useRef, ReactNode } from 'react'
import { useEffect, useRef, ReactNode, useMemo } from 'react'
import {
View,
DeviceEventEmitter,
Expand All @@ -11,7 +11,8 @@ import { useNavigation } from '@react-navigation/native'
import { PortalManagerContextValue, PortalContext } from '../context'

export type PortalHostProps = {
children: ReactNode
children: ReactNode,
pageId: number
}

type addIdsMapsType = {
Expand All @@ -38,9 +39,9 @@ const styles = StyleSheet.create({

class PortalGuard {
private nextKey = 10000
add = (e: ReactNode) => {
add = (e: ReactNode, id: number) => {
const key = this.nextKey++
TopViewEventEmitter.emit(addType, e, key)
TopViewEventEmitter.emit(addType, e, key, id)
return key
}

Expand All @@ -57,61 +58,102 @@ class PortalGuard {
*/
export const portal = new PortalGuard()

const PortalHost = ({ children } :PortalHostProps): JSX.Element => {
const PortalHost = ({ children, pageId } :PortalHostProps): JSX.Element => {
const isMounted = useRef<boolean>(false)
const _nextKey = useRef(0)
const _addType = useRef<EventSubscription | null>(null)
const _removeType = useRef<EventSubscription | null>(null)
const _updateType = useRef<EventSubscription | null>(null)
const manager = useRef<PortalManagerContextValue | null>(null)
const focusState = useRef<Boolean>(false)
const _mount = (children: ReactNode, _key?: number) => {
if (!focusState.current) {
return
const queue = useRef<Array<{ type: string, key: number; children: ReactNode }>>([])
const _mount = (children: ReactNode, _key?: number, id?: number) => {
if (id !== pageId) return
const key = _key || _nextKey.current++
if (!isMounted.current) {
queue.current.push({ type: 'mount', key, children })
} else if (manager.current) {
manager.current.mount(key, children)
}
return key
}

const _unmount = (key: number) => {
if (!isMounted.current) {
queue.current.push({ type: 'unmount', key, children })
} else if (manager.current) {
manager.current.unmount(key)
}
}

const _update = (key: number, children?: ReactNode) => {
if (!isMounted.current) {
const operation = { type: 'mount', key, children }
const index = queue.current.findIndex((q) => q.key === key)
if (index > -1) {
queue.current[index] = operation
} else {
queue.current.push(operation)
}
} else if (manager.current) {
manager.current.update(key, children)
}
}

const mount = (children: ReactNode, _key?: number) => {
const key = _key || _nextKey.current++
if (manager.current) {
manager.current.mount(key, children)
}
return key
}

const _unmount = (key: number) => {
const unmount = (key: number) => {
if (manager.current) {
manager.current.unmount(key)
}
}

const _update = (key: number, children?: ReactNode, curPageId?: number) => {
const update = (key: number, children?: ReactNode) => {
if (manager.current) {
manager.current.update(key, children)
}
}
const navigation = useNavigation()
useEffect(() => {

useMemo(() => {
_addType.current = TopViewEventEmitter.addListener(addType, _mount)
_removeType.current = TopViewEventEmitter.addListener(removeType, _unmount)
_updateType.current = TopViewEventEmitter.addListener(updateType, _update)
}, [])
const navigation = useNavigation()
useEffect(() => {
while (queue.current.length && manager.current) {
const operation = queue.current.shift()
if (!operation) return
switch (operation.type) {
case 'mount':
manager.current.mount(operation.key, operation.children)
break
case 'unmount':
manager.current.unmount(operation.key)
}
}
const focusSubscription = navigation.addListener('focus', () => {
focusState.current = true
})
const blurSubscription = navigation.addListener('blur', () => {
focusState.current = false
isMounted.current = true
})

return () => {
_addType.current?.remove()
_removeType.current?.remove()
_updateType.current?.remove()
focusSubscription()
blurSubscription()
}
}, [])
return (
<PortalContext.Provider
value={{
mount: _mount,
update: _update,
unmount: _unmount
mount,
update,
unmount
}}
>
<View style={styles.container} collapsable={false}>
Expand Down

0 comments on commit 34f1e0a

Please sign in to comment.