import { CommonActions, StackActions, useRoute, } from "@react-navigation/native"; import { pathToRegexp } from "path-to-regexp"; import { useEffect } from "react"; import { SetParamsOptions } from "./Router"; const routes = process.env.ROUTES || {}; let navigator = null; export type Route = { path: string; page: string; public?: boolean; }; export type RouteParams = { [key: string]: string; }; const dispatch = (navigationAction) => { if (!navigator) return; navigator.dispatch(navigationAction); }; export const setTopLevelNavigator = (navigatorRef) => { navigator = navigatorRef; }; export const getRouteProps = (routeName: string, params: RouteParams = {}) => { return { onPress: () => { push(routeName, params); }, }; }; export const getCurrentRoute = ( context?: { req: { url: string } } | { asPath: string } ) => { let path: string; if (!context) return null; if ("req" in context) { [path] = context.req.url.split("?"); } if ("asPath" in context) { [path] = context.asPath.split("?"); } const key = Object.keys(routes).find((routeKey) => { const regexp = pathToRegexp(routes[routeKey].path); return regexp.test(path); }); if (!key || !routes[key]) return {}; return { ...routes[key], key }; }; export const back = () => { dispatch(CommonActions.goBack()); }; export const reset = (name: string, params?: RouteParams) => { if (!navigator) return; const topRoute = navigator.getRootState().routes[0]; if (topRoute.name === name) { dispatch(StackActions.popToTop()); } else { dispatch( CommonActions.reset({ index: 0, routes: [{ name, params }], }) ); } }; interface PushOptions extends SetParamsOptions {} export const push = ( routeName: string, params?: RouteParams, options: PushOptions = {} ) => { if (navigator) { const currentRoute = navigator.getCurrentRoute(); if (currentRoute && currentRoute.name === routeName) { setParams(null, params, { scrollToTop: true, ...options }); return; } } dispatch(StackActions.push(routeName, params)); }; export const replace = ( routeName: string, params?: RouteParams, options: Record = {} ) => { dispatch(StackActions.replace(routeName, params)); }; export const redirect = (routeName: string, ctx?: any) => { return push(routeName, ctx?.query || {}); }; export const setParams = ( route: Route = null, params: RouteParams, options: SetParamsOptions = {} ) => { if (!navigator) return; const currentRoute = navigator.getCurrentRoute(); if (currentRoute) { dispatch({ ...CommonActions.setParams(params), source: currentRoute.key, }); } if (currentRoute?.params?.scrollToTop && options.scrollToTop) { currentRoute.params.scrollToTop(); } }; export const useScreenLoad = (effect, deps) => { useEffect(() => { effect(); }, [...deps]); }; export const useRouter = () => { const route = useRoute(); return { query: route.params || {}, }; }; export default { back, getCurrentRoute, push, redirect, replace, setParams, reset, };