From e5021187e96b78b53203bd95d08d6818aea47d17 Mon Sep 17 00:00:00 2001
From: "Thomas F. K. Jorna" <thomasfkjorna@gmail.com>
Date: Wed, 14 Jul 2021 15:10:31 +0200
Subject: New Ignite 7.0.6 app

---
 app/navigators/navigation-utilities.tsx | 127 ++++++++++++++++++++++++++++++++
 1 file changed, 127 insertions(+)
 create mode 100644 app/navigators/navigation-utilities.tsx

(limited to 'app/navigators/navigation-utilities.tsx')

diff --git a/app/navigators/navigation-utilities.tsx b/app/navigators/navigation-utilities.tsx
new file mode 100644
index 0000000..de1ea05
--- /dev/null
+++ b/app/navigators/navigation-utilities.tsx
@@ -0,0 +1,127 @@
+import React, { useState, useEffect, useRef } from "react"
+import { BackHandler } from "react-native"
+import { PartialState, NavigationState, NavigationContainerRef } from "@react-navigation/native"
+
+export const RootNavigation = {
+  navigate(name: string) {
+    name // eslint-disable-line no-unused-expressions
+  },
+  goBack() {}, // eslint-disable-line @typescript-eslint/no-empty-function
+  resetRoot(state?: PartialState<NavigationState> | NavigationState) {}, // eslint-disable-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-empty-function
+  getRootState(): NavigationState {
+    return {} as any
+  },
+}
+
+export const setRootNavigation = (ref: React.RefObject<NavigationContainerRef>) => {
+  for (const method in RootNavigation) {
+    RootNavigation[method] = (...args: any) => {
+      if (ref.current) {
+        return ref.current[method](...args)
+      }
+    }
+  }
+}
+
+/**
+ * Gets the current screen from any navigation state.
+ */
+export function getActiveRouteName(state: NavigationState | PartialState<NavigationState>) {
+  const route = state.routes[state.index]
+
+  // Found the active route -- return the name
+  if (!route.state) return route.name
+
+  // Recursive call to deal with nested routers
+  return getActiveRouteName(route.state)
+}
+
+/**
+ * Hook that handles Android back button presses and forwards those on to
+ * the navigation or allows exiting the app.
+ */
+export function useBackButtonHandler(
+  ref: React.RefObject<NavigationContainerRef>,
+  canExit: (routeName: string) => boolean,
+) {
+  const canExitRef = useRef(canExit)
+
+  useEffect(() => {
+    canExitRef.current = canExit
+  }, [canExit])
+
+  useEffect(() => {
+    // We'll fire this when the back button is pressed on Android.
+    const onBackPress = () => {
+      const navigation = ref.current
+
+      if (navigation == null) {
+        return false
+      }
+
+      // grab the current route
+      const routeName = getActiveRouteName(navigation.getRootState())
+
+      // are we allowed to exit?
+      if (canExitRef.current(routeName)) {
+        // let the system know we've not handled this event
+        return false
+      }
+
+      // we can't exit, so let's turn this into a back action
+      if (navigation.canGoBack()) {
+        navigation.goBack()
+
+        return true
+      }
+
+      return false
+    }
+
+    // Subscribe when we come to life
+    BackHandler.addEventListener("hardwareBackPress", onBackPress)
+
+    // Unsubscribe when we're done
+    return () => BackHandler.removeEventListener("hardwareBackPress", onBackPress)
+  }, [ref])
+}
+
+/**
+ * Custom hook for persisting navigation state.
+ */
+export function useNavigationPersistence(storage: any, persistenceKey: string) {
+  const [initialNavigationState, setInitialNavigationState] = useState()
+  const [isRestoringNavigationState, setIsRestoringNavigationState] = useState(true)
+
+  const routeNameRef = useRef()
+  const onNavigationStateChange = (state) => {
+    const previousRouteName = routeNameRef.current
+    const currentRouteName = getActiveRouteName(state)
+
+    if (previousRouteName !== currentRouteName) {
+      // track screens.
+      __DEV__ && console.tron.log(currentRouteName)
+    }
+
+    // Save the current route name for later comparision
+    routeNameRef.current = currentRouteName
+
+    // Persist state to storage
+    storage.save(persistenceKey, state)
+  }
+
+  const restoreState = async () => {
+    try {
+      const state = await storage.load(persistenceKey)
+      if (state) setInitialNavigationState(state)
+    } finally {
+      setIsRestoringNavigationState(false)
+    }
+  }
+
+  useEffect(() => {
+    if (isRestoringNavigationState) restoreState()
+  }, [isRestoringNavigationState])
+
+  return { onNavigationStateChange, restoreState, initialNavigationState }
+}
-- 
cgit v1.2.3

