import * as React from 'react' ; import { SHOW , HIDE } from './constants' ; import router from './router' ; import type { UseEffect , Listener } from './types' ; const visibleListeners = { } ; function addPageLifeCycle ( cycle , callback ) { const pathname = router . current . pathname ; if ( ! visibleListeners [ pathname ] ) { visibleListeners [ pathname ] = { [ SHOW ] : [ ] , [ HIDE ] : [ ] } ; } visibleListeners [ pathname ] [ cycle ] . push ( callback ) ; } export function emit ( cycle , pathname ? , ... args ) { if ( visibleListeners [ pathname ] && visibleListeners [ pathname ] [ cycle ] ) { for ( let i = 0 , l = visibleListeners [ pathname ] [ cycle ] . length ; i < l ; i ++ ) { visibleListeners [ pathname ] [ cycle ] [ i ] ( ... args ) ; } } } function createPageLifeCycle ( useEffect ) { return ( cycle , callback ) => { useEffect ( ( ) => { if ( cycle === SHOW ) { callback ( ) ; } const pathname = router . current . pathname ; addPageLifeCycle ( cycle , callback ) ; return ( ) => { if ( visibleListeners [ pathname ] ) { const index = visibleListeners [ pathname ] [ cycle ] . indexOf ( callback ) ; if ( index > - 1 ) { visibleListeners [ pathname ] [ cycle ] . splice ( index , 1 ) ; } } } ; } , [ ] ) ; } ; } export function withPageLifeCycle < P > ( Component ) { class Wrapper extends Component { private onShow : ( ) => void ; private onHide : ( ) => void ; private pathname : string ; constructor ( props , context ? ) { super ( props , context ) ; if ( this . onShow ) { this . onShow ( ) ; addPageLifeCycle ( SHOW , this . onShow . bind ( this ) ) ; } if ( this . onHide ) { addPageLifeCycle ( HIDE , this . onHide . bind ( this ) ) ; } this . pathname = router . current . pathname ; } public componentWillUnmount ( ) { super . componentWillUnmount ?. ( ) ; visibleListeners [ this . pathname ] = null ; } } Wrapper . displayName = `withPageLifeCycle(${ Component . displayName || Component . name })` ; return Wrapper as React . ComponentClass ; } export function createUsePageLifeCycle ( { useEffect } ) { const usePageShow = ( callback ) => { createPageLifeCycle ( useEffect ) ( SHOW , callback ) ; } ; const usePageHide = ( callback ) => { createPageLifeCycle ( useEffect ) ( HIDE , callback ) ; } ; return { usePageShow , usePageHide } ; }