Skip to content

Add possibility to lock all Roots for Overlay usage #191

Description

@aleksandrsakov

When i create a modal and use Overlay with locker, it locks only 1 parent Root, so if I have some modal which should be presented on all screens (like network error modal) I can not use Overlay on App.tsx because all child components have their own Root and it doesn't lock

import { useCallback, useEffect } from 'react'
import { useLockSpatialNavigation } from 'react-tv-space-navigation'

import { useGoBack } from '@/app/navigation/hooks'

interface UseLockProps {
  isOverlayVisible: boolean
  hideOverlay: () => void
}

export const useLockOverlay = ({ isOverlayVisible, hideOverlay }: UseLockProps) => {
  useLockParentSpatialNavigator(isOverlayVisible)
  usePreventNavigationGoBack(isOverlayVisible, hideOverlay)
}

const useLockParentSpatialNavigator = (isOverlayVisible: boolean) => {
  const { lock, unlock } = useLockSpatialNavigation()
  useEffect(() => {
    if (isOverlayVisible) {
      lock()
      return () => {
        unlock()
      }
    }
  }, [isOverlayVisible, lock, unlock])
}

const usePreventNavigationGoBack = (isOverlayVisible: boolean, hideOverlay: () => void) => {
  const hideOverlayListener = useCallback(() => {
    if (isOverlayVisible) {
      hideOverlay()
      return true
    }
    return false
  }, [isOverlayVisible, hideOverlay])
  useGoBack(hideOverlayListener)
}

// Overlay.tsx
export const Overlay = ({ children }: OverlayProps) => {
  return (
    <Portal>
      <View style={styles.container}>
        <SpatialNavigationRoot>{children}</SpatialNavigationRoot>
      </View>
    </Portal>
  )
}

// Modal.tsx
export const Modal = ({ isModalVisible, hideModal, children }: Props) => {
  useLockOverlay({ isOverlayVisible: isModalVisible, hideOverlay: hideModal })

  return (
    <Overlay>
      {children}
    </Overlay>
  )
}

// RootStack.tsx
export function RootStack() {
  const { isNetworkModalVisible, setIsNetworkModalVisible } = useNetworkConnection()

  return (
    <SpatialNavigationRoot>
      <Stack.Navigator
        screenOptions={{
          headerShown: false,
        }}
      >
            <Stack.Screen name={ScreenNames.TabBarScreen} component={TabNavigator} />
            // something else
      </Stack.Navigator>

      <NetworkErrorModal
        isModalVisible={isNetworkModalVisible}
        hideModal={() => setIsNetworkModalVisible(false)}
      />
    </SpatialNavigationRoot>
  )
}

It lock navigation only for parent SpatialNavigationRoot but all SpatialNavigationRoot inside TabNavigator screens doesn't lock and navigation works above Modal

How can we manage such situation? Maybe it is possible to create locker for all Roots and navigate only inside Overlay?

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    questionQuestion about the feasibility of a feature, library limitations, enhancement, ...

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions