Skip to content

Add possibility to lock all Roots for Overlay usageΒ #191

@aleksandrsakov

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?

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