import type { ReactElementFiber, ReactHostInstance, ReactStateNode, } from '../element/types'; import getPageStack, { buildPage, ReactNavigationPageInfo, } from '../reactNavigation/getPageStack'; import type Timer from './timer'; export interface PageInfo { rootTag: number; pageKey: string; pageTitle: string; pageManualKey: string; pagePath: string; isBack: boolean; moduleName: string; pageCustom: object; timer: Timer; } export interface NativePageInfo { is_back: boolean; page_title: string; moduleName: string; refer_page_key?: string; refer_page_title?: string; refer_page_manual_key?: string; referrer_page_path?: string; refer_react_tag?: number; } const trackState = { init: false, enable: false, enablePageView: false, enablePageLeave: false, enableClick: false, enableReactNavigation: false, }; const appContainerMap = new Map(); const pageInfoMap = new Map(); const pageInfoAsync = { _resolveSet: new Set(), getPageInfo(rootTag: number): Promise { return new Promise((resolve) => { if (pageInfoMap.has(rootTag)) { resolve(pageInfoMap.get(rootTag)!); } else { this._resolveSet.add({ rootTag, resolve, }); } }); }, trigger() { const removes = []; for (const _resolve of this._resolveSet) { if (pageInfoMap.has(_resolve.rootTag)) { _resolve.resolve(pageInfoMap.get(_resolve.rootTag)!); removes.push(_resolve); } } removes.forEach((_resolve) => this._resolveSet.delete(_resolve)); }, appendCurrentPage(rootTag: number, route?: any, params = {}): Promise { return this.getPageInfo(rootTag).then((pageInfo: PageInfo) => { let sceen = getPageStack(rootTag).getPage(route?.key); if (!sceen) { sceen = getPageStack(rootTag).getCurrent(); } let info: any; if (sceen && trackState.enableReactNavigation) { info = buildPage(sceen); Object.assign(params, info); info.isReactNavigation = true; } else { info = { page_key: pageInfo.pageKey, page_title: pageInfo.pageTitle, page_manual_key: pageInfo.pageManualKey, page_path: pageInfo.pagePath, is_back: pageInfo.isBack, }; Object.assign(params, info); info.isReactNavigation = false; } return info; }); }, }; const currentPageInfo = { rootTag: 0, set(rootTag: number) { this.rootTag = rootTag; }, appendPageInfo(params?: object) { if (!this.rootTag) { return; } if (!params) { return; } if (!pageInfoMap.has(this.rootTag)) { return; } const pageInfo = pageInfoMap.get(this.rootTag)!; if (trackState.enableReactNavigation) { const sceen = getPageStack(this.rootTag).getCurrent(); if (sceen) { const info = buildPage(sceen); Object.assign(params, { page_key: info.page_key, page_manual_key: info.page_manual_key, }); return; } } Object.assign(params, { page_key: pageInfo.pageKey, page_manual_key: pageInfo.pageManualKey, }); }, }; interface PageViewCallbackParams { pageInfo?: PageInfo; reactNavigation?: ReactNavigationPageInfo; } export type PageViewCallback = (params: PageViewCallbackParams) => void; const pageviewListener = { _listeners: [] as PageViewCallback[], add(callback: PageViewCallback) { this._listeners.push(callback); }, remove(callback: PageViewCallback) { this._listeners = this._listeners.filter((v) => v !== callback); }, trigger(params: PageViewCallbackParams) { for (const callback of this._listeners) { callback && callback(params); } }, }; const moduleNameMap = new Map(); const initialPropsMap = new Map(); const pageTitleMap = new Map(); interface DevtoolsInjects { bundleType: number; version: any; rendererPackageName: any; rendererConfig: any; currentDispatcherRef: any; findHostInstanceByFiber: ( fiber: ReactElementFiber ) => ReactHostInstance | undefined; findFiberByHostInstance: (nativeTag: number) => ReactElementFiber | undefined; } const devtoolsInjects: DevtoolsInjects = { bundleType: 0, version: '', rendererPackageName: '', rendererConfig: null, currentDispatcherRef: null, findHostInstanceByFiber: (_) => undefined, findFiberByHostInstance: (_) => undefined, }; export { trackState, appContainerMap, pageInfoMap, pageInfoAsync, currentPageInfo, pageviewListener, moduleNameMap, initialPropsMap, pageTitleMap, devtoolsInjects, };