import React , { cloneElement , useState } from 'react' ; import camelCase from 'lodash/camelCase' ; import zipObject from 'lodash/zipObject' ; import { Container } from '../container' ; import { Adaptor , AdaptorInstance , AdaptorType , ExportComponentMeta } from './common' ; import { gojiEvents } from '../events' ; import { useInternalComponentUpdate } from '../lifecycles/native/hooks' ; import { OnScrollOptions , OnShareAppMessageOptions , OnResizeOptions , OnTabItemTapOptions , } from '../lifecycles/types' ; export interface WeChatInstance { setData ( data , callback ? ) : void ; [ key ] : any ; __GOJI_CONTAINER ? : Container ; } interface WeChatPageLifecycle { onLoad ? ( this , query ) : void ; onReady ? ( this ) : void ; onUnload ? ( this ) : void ; onShow ? ( this ) : void ; onHide ? ( this ) : void ; onPullDownRefresh ? ( this ) : void ; onReachBottom ? ( this ) : void ; onPageScroll ? ( this , options ) : void ; onShareAppMessage ? ( this , options ) : any ; onResize ? ( this , options ) : void ; onTabItemTap ? ( this , options ) : void ; onTitleClick ? ( this ) : void ; onOptionMenuClick ? ( this ) : void ; onPopMenuClick ? ( this ) : void ; onPullIntercept ? ( this ) : void ; } export interface WeChatPageConfig extends WeChatPageLifecycle { } export interface WeChatComponentConfig { options ? : { addGlobalClass ? : boolean ; } ; methods ? : WeChatPageLifecycle ; properties ? : Record < string , { type : null ; observer ? ( this , newVal ) : void ; } > ; lifetimes ? : { attached ? ( this ) : void ; detached ? ( this ) : void ; } ; } export class WechatAdaptorInstance extends AdaptorInstance { public constructor ( private instance ) { super ( ) ; } public updateData ( data , callback ) { if ( Object . keys ( data ) . length === 0 ) { callback ( ) ; return ; } this . instance . setData ( data , callback ) ; } } const ExportComponentWrapper = ( { instance , children , exportEvents , } ) => { const [ props , setProps ] = useState < object > ( { } ) ; useInternalComponentUpdate ( newProps => { setProps ( { ... props , ... newProps , } ) ; } ) ; const eventProps = zipObject ( exportEvents . map ( event => camelCase ( `on-${ event }` ) ) , exportEvents . map ( event => ( data ) => { instance . triggerEvent ( event , data ) ; } ) ) ; return cloneElement ( children , { ... props , ... eventProps } ) ; } ; export class WeChatAdaptor extends Adaptor { public constructor ( private type , private exportMeta = { } , private disablePageSharing ) { super ( ) ; } public run ( element ) { const pageLifecycles = { onLoad ( this , options ) { const container = new Container ( new WechatAdaptorInstance ( this ) ) ; this . __GOJI_CONTAINER = container ; container . render ( element ) ; this . __GOJI_CONTAINER ! . eventProxy . lifecycleChannel . onLoad . emit ( options ) ; } , onReady ( this ) { this . __GOJI_CONTAINER ! . eventProxy . lifecycleChannel . onReady . emit ( ) ; } , onShow ( this ) { this . __GOJI_CONTAINER ! . eventProxy . lifecycleChannel . onShow . emit ( ) ; } , onHide ( this ) { this . __GOJI_CONTAINER ! . eventProxy . lifecycleChannel . onHide . emit ( ) ; } , onUnload ( this ) { this . __GOJI_CONTAINER ! . eventProxy . lifecycleChannel . onUnload . emit ( ) ; if ( this . __GOJI_CONTAINER ) { this . __GOJI_CONTAINER . render ( null ) ; } this . __GOJI_CONTAINER = undefined ; } , onPullDownRefresh ( this ) { this . __GOJI_CONTAINER ! . eventProxy . lifecycleChannel . onPullDownRefresh . emit ( ) ; } , onReachBottom ( this ) { this . __GOJI_CONTAINER ! . eventProxy . lifecycleChannel . onReachBottom . emit ( ) ; } , onPageScroll ( this , options ) { this . __GOJI_CONTAINER ! . eventProxy . lifecycleChannel . onPageScroll . emit ( options ) ; } , onShareAppMessage ( this , options ) { const results = this . __GOJI_CONTAINER ! . eventProxy . lifecycleChannel . onShareAppMessage . emit ( options ) ; if ( results && results . length > 1 ) { console . warn ( `useOnShareAppMessage should be called only once in one Page, now it's called ${ results . length } times` ) ; } return results [ 0 ] ; } , onResize ( this , options ) { this . __GOJI_CONTAINER ! . eventProxy . lifecycleChannel . onResize . emit ( options ) ; } , onTabItemTap ( this , options ) { this . __GOJI_CONTAINER ! . eventProxy . lifecycleChannel . onTabItemTap . emit ( options ) ; } , onTitleClick ( this ) { this . __GOJI_CONTAINER ! . eventProxy . lifecycleChannel . onTitleClick . emit ( ) ; } , onOptionMenuClick ( this ) { this . __GOJI_CONTAINER ! . eventProxy . lifecycleChannel . onOptionMenuClick . emit ( ) ; } , onPopMenuClick ( this ) { this . __GOJI_CONTAINER ! . eventProxy . lifecycleChannel . onPopMenuClick . emit ( ) ; } , onPullIntercept ( this ) { this . __GOJI_CONTAINER ! . eventProxy . lifecycleChannel . onPullIntercept . emit ( ) ; } , } ; if ( this . disablePageSharing ) { delete pageLifecycles . onShareAppMessage ; } const eventHandler = { e ( evt ) { gojiEvents . triggerEvent ( evt ) ; } , } ; const { type } = this ; if ( type === 'page' ) { const pageConfig = pageLifecycles ; Page ( { ... pageConfig , ... eventHandler , } ) ; } else if ( type === 'component' ) { const componentConfig = { methods : { ... pageLifecycles , ... eventHandler } , } ; Component ( componentConfig ) ; } else if ( type === 'exportComponent' ) { const { events = [ ] , props = [ ] } = this . exportMeta ; const pageConfig = { options : { addGlobalClass : true , } , properties : zipObject ( props , props . map ( prop => ( { type : null , observer ( this , newVal ) { if ( ! this . __GOJI_CONTAINER ) { return ; } this . __GOJI_CONTAINER . eventProxy . internalChannels . exportedComponentUpdate . emit ( { [ prop ] : newVal , } ) ; } , } ) ) ) , lifetimes : { attached ( this ) { const container = new Container ( new WechatAdaptorInstance ( this ) ) ; this . __GOJI_CONTAINER = container ; container . render ( < ExportComponentWrapper instance = { this } exportEvents = { events } > { element } < /ExportComponentWrapper>); this . __GOJI_CONTAINER . eventProxy . internalChannels . exportedComponentUpdate . emit ( this . properties ) ; } , detached ( this ) { if ( this . __GOJI_CONTAINER ) { this . __GOJI_CONTAINER . render ( null ) ; } this . __GOJI_CONTAINER = undefined ; } , } , } ; Component ( { ... pageConfig , pageLifetimes : { hide : pageLifecycles . onHide , show : pageLifecycles . onShow , } , methods : { ... eventHandler } , } ) ; } } }