|
import { log } from "@lib/Logger"; |
|
import { createRef, ReactNode } from "react"; |
|
import { StackScreenArguments } from "./NavigationScreen"; |
|
import { DrawerActions, EventListenerCallback, NavigationContainerEventMap, NavigationContainerRef, NavigationState, PartialState, StackActions } from "@react-navigation/native"; |
|
|
|
/** |
|
* Reference to the root `NavigationContainer` component. Used to dispatch |
|
* actions and commands from anywhere within the app. |
|
*/ |
|
export const navigationRef = createRef<NavigationContainerRef>(); |
|
|
|
/** |
|
* Dispatches a `navigate` navigation action to the provided route name, along with the provided payload. |
|
* @param {string} routeName - The name of the route to navigate to. |
|
* @param {Object} [params] - The payload to send to the route. |
|
* @param {boolean} [shouldPush] - Wether or not to navigate to the route if one with the same name is already present on the stack |
|
*/ |
|
export function navigate<TName extends keyof StackScreenArguments>(routeName: TName, params?: StackScreenArguments[TName]) { |
|
if (!navigationRef.current) { |
|
log("Navigation", "Tried to navigate without a navigator ref", "warn"); |
|
return; |
|
} |
|
|
|
navigationRef.current.navigate(routeName as string, params ?? {}); |
|
} |
|
|
|
/** |
|
* Dispatches a `push` navigation action to the provided route name, along with the provided payload |
|
* @param routeName The name of the route to navigate to. |
|
* @param params The payload to send to the route. |
|
*/ |
|
export function push<TName extends keyof StackScreenArguments>(routeName: TName, params?: StackScreenArguments[TName]) { |
|
if (!navigationRef.current) { |
|
log("Navigation", "Tried to push without a navigator ref", "warn"); |
|
return; |
|
} |
|
|
|
navigationRef.current.dispatch( |
|
StackActions.push(routeName as string, params ?? {}) |
|
); |
|
} |
|
|
|
/** |
|
* Resets the navigation state so that the provided route is the only active one. |
|
* @param routeName The name of the route to navigate to |
|
* @param params The payload to send to the route |
|
*/ |
|
export function reset(state: NavigationState | PartialState<NavigationState>) { |
|
if (!navigationRef.current) { |
|
log("Navigation", "Tried to reset without a navigator ref", "warn"); |
|
return; |
|
} |
|
|
|
navigationRef.current.reset(state); |
|
} |
|
|
|
/** |
|
* Dispatches a `back` navigation event to go back to the previous screen. |
|
*/ |
|
export function goBack() { |
|
if (!navigationRef.current) { |
|
log("Navigation", "Tried to go back without a navigator ref", "warn"); |
|
return; |
|
} |
|
|
|
else if (navigationRef.current.canGoBack()) { |
|
navigationRef.current.goBack(); |
|
} |
|
|
|
else { |
|
log("Navigation", "Tried to go back without any previous screen", "warn"); |
|
} |
|
} |
|
|
|
/** |
|
* Opens the drawer |
|
*/ |
|
export function openDrawer() { |
|
if (!navigationRef.current) { |
|
log("Navigation", "Tried to open drawer without a navigator ref", "warn"); |
|
return; |
|
} |
|
|
|
navigationRef.current.dispatch( |
|
DrawerActions.openDrawer() |
|
); |
|
} |
|
|
|
/** |
|
* Closes the drawer |
|
*/ |
|
export function closeDrawer() { |
|
if (!navigationRef.current) { |
|
log("Navigation", "Tried to close drawer without a navigator ref", "warn"); |
|
return; |
|
} |
|
|
|
navigationRef.current.dispatch( |
|
DrawerActions.closeDrawer() |
|
); |
|
} |
|
|
|
/** |
|
* Toggles the drawer |
|
*/ |
|
export function toggleDrawer() { |
|
if (!navigationRef.current) { |
|
log("Navigation", "Tried to toggle drawer without a navigator ref", "warn"); |
|
return; |
|
} |
|
|
|
navigationRef.current.dispatch( |
|
DrawerActions.toggleDrawer() |
|
); |
|
} |
|
|
|
/** |
|
* Subscribes to a navigation event. |
|
* @param eventName The name of the event to subscribe to. |
|
* @param callback The function to call when said event occurs. |
|
*/ |
|
export function addNavigationListener<T extends "state" | "options">(eventName: T, callback: EventListenerCallback<NavigationContainerEventMap, T>) { |
|
if (!navigationRef.current) { |
|
return () => { }; |
|
} |
|
|
|
return navigationRef.current?.addListener(eventName, callback); |
|
} |