From 18a549e389e04bfc306f4bfd263bc82a4eac2e0a Mon Sep 17 00:00:00 2001 From: FLGMwt Date: Fri, 3 Apr 2026 10:56:43 -0500 Subject: [PATCH] relace all useNetInfo imports w/ wrapper --- src/components/Explore/ObservationsView.js | 4 ++-- src/components/Explore/RootExploreContainer.js | 4 ++-- .../Explore/SearchScreens/EmptySearchResults.tsx | 4 ++-- src/components/Match/Match.tsx | 4 ++-- src/components/Match/MatchContainer.tsx | 4 ++-- src/components/Menu/Menu.tsx | 4 ++-- .../MyObservations/MyObservationsContainer.tsx | 4 ++-- .../MyObservations/hooks/useSyncObservations.ts | 4 ++-- .../Notifications/NotificationsContainer.tsx | 4 ++-- src/components/ObsDetails/DQAContainer.js | 4 ++-- src/components/ObsDetails/ObsDetailsContainer.js | 4 ++-- .../ObsDetailsDefaultModeScreensWrapper.tsx | 4 ++-- .../ObsDetailsDefaultMode/SavedMatch/SavedMatch.tsx | 4 ++-- .../Media/SoundContainer.tsx | 4 ++-- src/components/ObsEdit/BottomButtonsContainer.tsx | 4 ++-- src/components/ProjectDetails/ProjectMembers.tsx | 4 ++-- src/components/Projects/Projects.tsx | 4 ++-- src/components/Settings/LoggedInDefaultSettings.tsx | 4 ++-- src/components/Suggestions/SuggestionsContainer.tsx | 4 ++-- src/components/TaxonDetails/TaxonDetails.js | 5 +++-- src/components/UserProfile/FollowersList.tsx | 4 ++-- src/components/UserProfile/FollowingList.tsx | 4 ++-- src/navigation/OfflineNavigationGuard.tsx | 4 ++-- src/sharedHooks/useSuggestions/useOnlineSuggestions.ts | 4 ++-- src/sharedHooks/useSuggestions/useSuggestions.ts | 4 ++-- tests/integration/SavedMatch.test.js | 4 ++-- .../broken/SuggestionsWithUnsyncedObs.test.js | 10 +++++----- .../components/BottomTabNavigator/CustomTabBar.test.js | 6 +++--- tests/unit/components/Settings/Settings.test.js | 4 ++-- 29 files changed, 63 insertions(+), 62 deletions(-) diff --git a/src/components/Explore/ObservationsView.js b/src/components/Explore/ObservationsView.js index f2855bfd3..0fe6986fd 100644 --- a/src/components/Explore/ObservationsView.js +++ b/src/components/Explore/ObservationsView.js @@ -1,6 +1,5 @@ // @flow -import { useNetInfo } from "@react-native-community/netinfo"; import { searchObservations, } from "api/observations"; @@ -18,6 +17,7 @@ import { useDeviceOrientation, useQuery, } from "sharedHooks"; +import useConnectionStatus from "sharedHooks/useConnectionStatus"; import MapView from "./MapView"; @@ -88,7 +88,7 @@ const ObservationsView = ( { handleUpdateCount( "observations", totalCount ); }, [handleUpdateCount, totalCount] ); - const { isConnected } = useNetInfo( ); + const { isConnected } = useConnectionStatus( ); if ( !layout ) { return null; } diff --git a/src/components/Explore/RootExploreContainer.js b/src/components/Explore/RootExploreContainer.js index a83d3fb63..90bc36e63 100644 --- a/src/components/Explore/RootExploreContainer.js +++ b/src/components/Explore/RootExploreContainer.js @@ -1,6 +1,5 @@ // @flow -import { useNetInfo } from "@react-native-community/netinfo"; import { useNavigation } from "@react-navigation/native"; import { EXPLORE_ACTION, @@ -16,6 +15,7 @@ import React, { useState, } from "react"; import { useCurrentUser, useFeatureFlag } from "sharedHooks"; +import useConnectionStatus from "sharedHooks/useConnectionStatus"; import useLocationPermission from "sharedHooks/useLocationPermission"; import { FeatureFlag } from "stores/createFeatureFlagSlice"; import useStore from "stores/useStore"; @@ -27,7 +27,7 @@ import useExploreHeaderCount from "./hooks/useExploreHeaderCount"; const RootExploreContainerWithContext = ( ): Node => { const navigation = useNavigation( ); - const { isConnected } = useNetInfo( ); + const { isConnected } = useConnectionStatus( ); const currentUser = useCurrentUser( ); const exploreV2Enabled = useFeatureFlag( FeatureFlag.ExploreV2Enabled ); const rootExploreView = useStore( state => state.rootExploreView ); diff --git a/src/components/Explore/SearchScreens/EmptySearchResults.tsx b/src/components/Explore/SearchScreens/EmptySearchResults.tsx index fc211a100..ea1117db7 100644 --- a/src/components/Explore/SearchScreens/EmptySearchResults.tsx +++ b/src/components/Explore/SearchScreens/EmptySearchResults.tsx @@ -1,4 +1,3 @@ -import { useNetInfo } from "@react-native-community/netinfo"; import { ActivityIndicator, Body2, @@ -9,6 +8,7 @@ import React from "react"; import { useTranslation, } from "sharedHooks"; +import useConnectionStatus from "sharedHooks/useConnectionStatus"; interface Props { isLoading: boolean; @@ -24,7 +24,7 @@ const EmptySearchResults = ( { skipOfflineNotice, }: Props ) => { const { t } = useTranslation( ); - const { isConnected } = useNetInfo( ); + const { isConnected } = useConnectionStatus( ); if ( searchQuery === "" ) { return null; diff --git a/src/components/Match/Match.tsx b/src/components/Match/Match.tsx index 96b446872..61e64e52f 100644 --- a/src/components/Match/Match.tsx +++ b/src/components/Match/Match.tsx @@ -1,4 +1,3 @@ -import { useNetInfo } from "@react-native-community/netinfo"; import type { ApiPhoto, ApiSuggestion, ApiTaxon } from "api/types"; import LocationSection from "components/ObsDetailsDefaultMode/LocationSection/LocationSection"; @@ -15,6 +14,7 @@ import type { RealmObservation, RealmObservationPhoto, RealmPhoto, RealmTaxon, } from "realmModels/types"; import { useTranslation } from "sharedHooks"; +import useConnectionStatus from "sharedHooks/useConnectionStatus"; import AdditionalSuggestionsScroll from "./AdditionalSuggestions/AdditionalSuggestionsScroll"; @@ -64,7 +64,7 @@ const Match = ( { taxonToSave, }: Props ) => { const { t } = useTranslation( ); - const { isConnected } = useNetInfo( ); + const { isConnected } = useConnectionStatus( ); const latitude = observation?.privateLatitude || observation?.latitude; const taxon = topSuggestion?.taxon; diff --git a/src/components/Match/MatchContainer.tsx b/src/components/Match/MatchContainer.tsx index 3e3a750ba..fbfdea1cd 100644 --- a/src/components/Match/MatchContainer.tsx +++ b/src/components/Match/MatchContainer.tsx @@ -1,4 +1,3 @@ -import { useNetInfo } from "@react-native-community/netinfo"; import { useNavigation } from "@react-navigation/native"; import type { NativeStackNavigationProp } from "@react-navigation/native-stack"; import type { ApiPhoto, ApiSuggestion } from "api/types"; @@ -23,6 +22,7 @@ import shouldFetchObservationLocation from "sharedHelpers/shouldFetchObservation import { useExitObservationFlow, useLocationPermission, useSuggestions, useWatchPosition, } from "sharedHooks"; +import useConnectionStatus from "sharedHooks/useConnectionStatus"; import { isDebugMode } from "sharedHooks/useDebugMode"; import { internalUseSuggestionsInitialSuggestions, @@ -142,7 +142,7 @@ const MatchContainer = ( ) => { skipStoreReset: true, } ); - const { isConnected } = useNetInfo( ); + const { isConnected } = useConnectionStatus( ); const evidenceHasLocation = !!currentObservation?.latitude; diff --git a/src/components/Menu/Menu.tsx b/src/components/Menu/Menu.tsx index cd734b124..e6720aa85 100644 --- a/src/components/Menu/Menu.tsx +++ b/src/components/Menu/Menu.tsx @@ -1,4 +1,3 @@ -import { useNetInfo } from "@react-native-community/netinfo"; import { useNavigation } from "@react-navigation/native"; import { useQueryClient } from "@tanstack/react-query"; import { @@ -23,6 +22,7 @@ import { valueToBreakpoint } from "sharedHelpers/breakpoint"; import { log } from "sharedHelpers/logger"; import getStorageMetrics from "sharedHelpers/storageMetrics"; import { useCurrentUser, useLayoutPrefs, useTranslation } from "sharedHooks"; +import useConnectionStatus from "sharedHooks/useConnectionStatus"; import { zustandStorage } from "stores/useStore"; import colors from "styles/tailwindColors"; @@ -104,7 +104,7 @@ const Menu = ( ) => { const { t } = useTranslation( ); const insets = useSafeAreaInsets(); - const { isConnected } = useNetInfo( ); + const { isConnected } = useConnectionStatus( ); const layoutPrefs = useLayoutPrefs(); const [modalState, setModalState] = useState( null ); diff --git a/src/components/MyObservations/MyObservationsContainer.tsx b/src/components/MyObservations/MyObservationsContainer.tsx index be934dc22..c94c47c28 100644 --- a/src/components/MyObservations/MyObservationsContainer.tsx +++ b/src/components/MyObservations/MyObservationsContainer.tsx @@ -1,4 +1,3 @@ -import { useNetInfo } from "@react-native-community/netinfo"; import { useFocusEffect, useNavigation } from "@react-navigation/native"; import type { FlashListRef } from "@shopify/flash-list"; import { fetchSpeciesCounts } from "api/observations"; @@ -30,6 +29,7 @@ import { useStoredLayout, useTranslation, } from "sharedHooks"; +import useConnectionStatus from "sharedHooks/useConnectionStatus"; import { UPLOAD_PENDING, } from "stores/createUploadObservationsSlice"; @@ -97,7 +97,7 @@ const MyObservationsContainer = ( ) => { const prevObservationsLength = useRef( observations.length ); const { layout, writeLayoutToStorage } = useStoredLayout( "myObservationsLayout" ); - const { isConnected } = useNetInfo( ); + const { isConnected } = useConnectionStatus( ); const currentUser = useCurrentUser( ); const currentUserId = currentUser?.id; const canUpload = !!currentUser && !!isConnected; diff --git a/src/components/MyObservations/hooks/useSyncObservations.ts b/src/components/MyObservations/hooks/useSyncObservations.ts index e944bc3bb..5be21b170 100644 --- a/src/components/MyObservations/hooks/useSyncObservations.ts +++ b/src/components/MyObservations/hooks/useSyncObservations.ts @@ -1,10 +1,10 @@ -import { useNetInfo } from "@react-native-community/netinfo"; import { INatApiError } from "api/error"; import { deleteRemoteObservation } from "api/observations"; import { RealmContext } from "providers/contexts"; import { useCallback, useEffect, useState } from "react"; import Observation from "realmModels/Observation"; import { useAuthenticatedMutation } from "sharedHooks"; +import useConnectionStatus from "sharedHooks/useConnectionStatus"; import { AUTOMATIC_SYNC_IN_PROGRESS, BEGIN_AUTOMATIC_SYNC, @@ -22,7 +22,7 @@ const useSyncObservations = ( currentUserId: number, startUploadObservations: ( _skipSomeUuids: string[] | undefined ) => void, ) => { - const { isConnected } = useNetInfo( ); + const { isConnected } = useConnectionStatus( ); const loggedIn = !!( currentUserId ); const deleteQueue = useStore( state => state.deleteQueue ); const deletionsCompletedAt = useStore( state => state.deletionsCompletedAt ); diff --git a/src/components/Notifications/NotificationsContainer.tsx b/src/components/Notifications/NotificationsContainer.tsx index 690f30f03..321fa9443 100644 --- a/src/components/Notifications/NotificationsContainer.tsx +++ b/src/components/Notifications/NotificationsContainer.tsx @@ -1,4 +1,3 @@ -import { useNetInfo } from "@react-native-community/netinfo"; import { useNavigation } from "@react-navigation/native"; import type { ApiObservationsUpdatesParams } from "api/types"; import NotificationsList from "components/Notifications/NotificationsList"; @@ -6,6 +5,7 @@ import React, { useEffect, useState } from "react"; import type { RealmUser } from "realmModels/types"; import { log } from "sharedHelpers/logger"; import { useInfiniteNotificationsScroll, usePerformance } from "sharedHooks"; +import useConnectionStatus from "sharedHooks/useConnectionStatus"; import { isDebugMode } from "sharedHooks/useDebugMode"; const logger = log.extend( "NotificationsContainer" ); @@ -22,7 +22,7 @@ const NotificationsContainer = ( { onRefresh: onRefreshProp, }: Props ) => { const navigation = useNavigation( ); - const { isConnected } = useNetInfo( ); + const { isConnected } = useConnectionStatus( ); const [refreshing, setRefreshing] = useState( false ); const { diff --git a/src/components/ObsDetails/DQAContainer.js b/src/components/ObsDetails/DQAContainer.js index ae9a9a824..5f5d2c5b6 100644 --- a/src/components/ObsDetails/DQAContainer.js +++ b/src/components/ObsDetails/DQAContainer.js @@ -1,7 +1,6 @@ // @flow import { refresh as refreshNetInfo, - useNetInfo, } from "@react-native-community/netinfo"; import { useRoute } from "@react-navigation/native"; import { faveObservation, unfaveObservation } from "api/observations"; @@ -25,12 +24,13 @@ import { useAuthenticatedQuery, useLocalObservation, } from "sharedHooks"; +import useConnectionStatus from "sharedHooks/useConnectionStatus"; import useRemoteObservation from "sharedHooks/useRemoteObservation"; const logger = log.extend( "DQAContainer" ); const DQAContainer = ( ): React.Node => { - const { isConnected } = useNetInfo( ); + const { isConnected } = useConnectionStatus( ); const { params } = useRoute( ); const { observationUUID } = params; const [loadingAgree, setLoadingAgree] = useState( false ); diff --git a/src/components/ObsDetails/ObsDetailsContainer.js b/src/components/ObsDetails/ObsDetailsContainer.js index 1851de8c6..6e3b1c4e5 100644 --- a/src/components/ObsDetails/ObsDetailsContainer.js +++ b/src/components/ObsDetails/ObsDetailsContainer.js @@ -1,5 +1,4 @@ // @flow -import { useNetInfo } from "@react-native-community/netinfo"; import { useRoute } from "@react-navigation/native"; import IdentificationSheets from "components/ObsDetailsDefaultMode/IdentificationSheets"; import useMarkViewedMutation @@ -18,6 +17,7 @@ import { useLocalObservation, useTranslation, } from "sharedHooks"; +import useConnectionStatus from "sharedHooks/useConnectionStatus"; import useRemoteObservation from "sharedHooks/useRemoteObservation"; import { OBS_DETAILS_TAB } from "stores/createLayoutSlice"; @@ -42,7 +42,7 @@ const ObsDetailsContainer = ( ): Node => { uuid, } = params; const { t } = useTranslation( ); - const { isConnected } = useNetInfo( ); + const { isConnected } = useConnectionStatus( ); const [remoteObsWasDeleted, setRemoteObsWasDeleted] = useState( false ); const { diff --git a/src/components/ObsDetailsDefaultMode/ObsDetailsDefaultModeScreensWrapper.tsx b/src/components/ObsDetailsDefaultMode/ObsDetailsDefaultModeScreensWrapper.tsx index 360cc8041..e6ad0641d 100644 --- a/src/components/ObsDetailsDefaultMode/ObsDetailsDefaultModeScreensWrapper.tsx +++ b/src/components/ObsDetailsDefaultMode/ObsDetailsDefaultModeScreensWrapper.tsx @@ -1,4 +1,3 @@ -import { useNetInfo } from "@react-native-community/netinfo"; import { useRoute } from "@react-navigation/native"; import ObsDetailsDefaultModeContainer from "components/ObsDetailsDefaultMode/ObsDetailsDefaultModeContainer"; @@ -9,6 +8,7 @@ import { useLocalObservation, useRemoteObservation, } from "sharedHooks"; +import useConnectionStatus from "sharedHooks/useConnectionStatus"; import SavedMatchContainer from "./SavedMatch/SavedMatchContainer"; @@ -24,7 +24,7 @@ const ObsDetailsDefaultModeScreensWrapper = () => { uuid, } = params as RouteParams; const currentUser = useCurrentUser( ); - const isConnected = !!useNetInfo( ).isConnected; + const isConnected = !!useConnectionStatus( ).isConnected; const [remoteObsWasDeleted, setRemoteObsWasDeleted] = useState( false ); diff --git a/src/components/ObsDetailsDefaultMode/SavedMatch/SavedMatch.tsx b/src/components/ObsDetailsDefaultMode/SavedMatch/SavedMatch.tsx index 4141b30c6..4ed01b8ec 100644 --- a/src/components/ObsDetailsDefaultMode/SavedMatch/SavedMatch.tsx +++ b/src/components/ObsDetailsDefaultMode/SavedMatch/SavedMatch.tsx @@ -1,4 +1,3 @@ -import { useNetInfo } from "@react-native-community/netinfo"; import { matchCardClassBottom, matchCardClassTop } from "components/Match/Match"; import MatchHeader from "components/Match/MatchHeader"; import PhotosSection from "components/Match/PhotosSection"; @@ -10,6 +9,7 @@ import { View } from "components/styledComponents"; import React from "react"; import type { RealmObservation } from "realmModels/types"; import { useTranslation } from "sharedHooks"; +import useConnectionStatus from "sharedHooks/useConnectionStatus"; interface Props { observation: RealmObservation; @@ -21,7 +21,7 @@ const SavedMatch = ( { navToTaxonDetails, }: Props ) => { const { t } = useTranslation( ); - const { isConnected } = useNetInfo( ); + const { isConnected } = useConnectionStatus( ); const latitude = observation?.privateLatitude || observation?.latitude; const { taxon } = observation; diff --git a/src/components/ObsDetailsSharedComponents/Media/SoundContainer.tsx b/src/components/ObsDetailsSharedComponents/Media/SoundContainer.tsx index b1b444c22..a47b7dcbc 100644 --- a/src/components/ObsDetailsSharedComponents/Media/SoundContainer.tsx +++ b/src/components/ObsDetailsSharedComponents/Media/SoundContainer.tsx @@ -1,6 +1,5 @@ import { refresh as refreshNetInfo, - useNetInfo, } from "@react-native-community/netinfo"; import Slider from "@react-native-community/slider"; import { useFocusEffect } from "@react-navigation/native"; @@ -14,6 +13,7 @@ import React, { } from "react"; import AudioRecorderPlayer from "react-native-audio-recorder-player"; import { useTranslation } from "sharedHooks"; +import useConnectionStatus from "sharedHooks/useConnectionStatus"; import colors from "styles/tailwindColors"; interface SoundSliderProps { @@ -61,7 +61,7 @@ const SoundContainer = ( { sound, }: SoundContainerProps ) => { const needsInternet = sound.file_url.includes( "https://" ); - const { isConnected } = useNetInfo( ); + const { isConnected } = useConnectionStatus( ); const playerRef = useRef( new AudioRecorderPlayer( ) ); const player = playerRef.current; const { t } = useTranslation( ); diff --git a/src/components/ObsEdit/BottomButtonsContainer.tsx b/src/components/ObsEdit/BottomButtonsContainer.tsx index e0f29be5e..ee6c5e4b8 100644 --- a/src/components/ObsEdit/BottomButtonsContainer.tsx +++ b/src/components/ObsEdit/BottomButtonsContainer.tsx @@ -1,4 +1,3 @@ -import { useNetInfo } from "@react-native-community/netinfo"; import { REQUIRED_LOCATION_ACCURACY } from "components/LocationPicker/CrosshairCircle"; import useUploadObservations from "components/MyObservations/hooks/useUploadObservations"; import { RealmContext } from "providers/contexts"; @@ -9,6 +8,7 @@ import { useCurrentUser, useExitObservationFlow, } from "sharedHooks"; +import useConnectionStatus from "sharedHooks/useConnectionStatus"; import useStore from "stores/useStore"; import type { ButtonType, ButtonTypeNonNull } from "./BottomButtons"; @@ -35,7 +35,7 @@ const BottomButtonsContainer = ( { setCurrentObservationIndex, transitionAnimation, }: Props ) => { - const { isConnected } = useNetInfo( ); + const { isConnected } = useConnectionStatus( ); const currentUser = useCurrentUser( ); const cameraRollUris = useStore( state => state.cameraRollUris ); const unsavedChanges = useStore( state => state.unsavedChanges ); diff --git a/src/components/ProjectDetails/ProjectMembers.tsx b/src/components/ProjectDetails/ProjectMembers.tsx index b01efc2b3..1245707f8 100644 --- a/src/components/ProjectDetails/ProjectMembers.tsx +++ b/src/components/ProjectDetails/ProjectMembers.tsx @@ -1,4 +1,3 @@ -import { useNetInfo } from "@react-native-community/netinfo"; import { useNavigation, useRoute } from "@react-navigation/native"; import { fetchProjectMembers } from "api/projects"; import { @@ -9,9 +8,10 @@ import UserList from "components/UserList/UserList"; import React, { useCallback, useEffect, useMemo } from "react"; import User from "realmModels/User"; import { useInfiniteScroll, useTranslation } from "sharedHooks"; +import useConnectionStatus from "sharedHooks/useConnectionStatus"; const ProjectMembers = ( ) => { - const { isConnected } = useNetInfo( ); + const { isConnected } = useConnectionStatus( ); const navigation = useNavigation( ); const { t } = useTranslation( ); const { params } = useRoute( ); diff --git a/src/components/Projects/Projects.tsx b/src/components/Projects/Projects.tsx index 827b2c670..a8e6d7895 100644 --- a/src/components/Projects/Projects.tsx +++ b/src/components/Projects/Projects.tsx @@ -1,4 +1,3 @@ -import { useNetInfo } from "@react-native-community/netinfo"; import { useNavigation } from "@react-navigation/native"; import ProjectList from "components/ProjectList/ProjectList"; import { @@ -18,6 +17,7 @@ import React, { useCallback, useEffect } from "react"; import { useTranslation, } from "sharedHooks"; +import useConnectionStatus from "sharedHooks/useConnectionStatus"; import FlashListEmptyWrapper from "../SharedComponents/FlashList/FlashListEmptyWrapper"; import { TAB_ID } from "./ProjectsContainer"; @@ -54,7 +54,7 @@ const Projects = ( { }: Props ) => { const { t } = useTranslation( ); const navigation = useNavigation( ); - const { isConnected } = useNetInfo( ); + const { isConnected } = useConnectionStatus( ); const hideLoadingWheel = !isFetchingNextPage || projects?.length === 0; diff --git a/src/components/Settings/LoggedInDefaultSettings.tsx b/src/components/Settings/LoggedInDefaultSettings.tsx index 4fb6d8854..f5d3237b0 100644 --- a/src/components/Settings/LoggedInDefaultSettings.tsx +++ b/src/components/Settings/LoggedInDefaultSettings.tsx @@ -1,4 +1,3 @@ -import { useNetInfo } from "@react-native-community/netinfo"; import { useFocusEffect, useNavigation } from "@react-navigation/native"; import { useQueryClient } from "@tanstack/react-query"; import { @@ -24,6 +23,7 @@ import { useTranslation, useUserMe, } from "sharedHooks"; +import useConnectionStatus from "sharedHooks/useConnectionStatus"; import LanguageSetting from "./LanguageSetting"; import TaxonNamesSetting from "./TaxonNamesSetting"; @@ -35,7 +35,7 @@ const FINISHED_WEB_SETTINGS = "finished-web-settings"; const LoggedInDefaultSettings = ( ) => { const realm = useRealm( ); - const { isConnected } = useNetInfo( ); + const { isConnected } = useConnectionStatus( ); const navigation = useNavigation( ); const { t } = useTranslation( ); const { diff --git a/src/components/Suggestions/SuggestionsContainer.tsx b/src/components/Suggestions/SuggestionsContainer.tsx index 330772ffc..80e8beef6 100644 --- a/src/components/Suggestions/SuggestionsContainer.tsx +++ b/src/components/Suggestions/SuggestionsContainer.tsx @@ -1,4 +1,3 @@ -import { useNetInfo } from "@react-native-community/netinfo"; import { useNavigation, useRoute } from "@react-navigation/native"; import MediaViewerModal from "components/MediaViewer/MediaViewerModal"; import isEqual from "lodash/isEqual"; @@ -16,6 +15,7 @@ import { usePerformance, useSuggestions, } from "sharedHooks"; +import useConnectionStatus from "sharedHooks/useConnectionStatus"; import { isDebugMode } from "sharedHooks/useDebugMode"; import { internalUseSuggestionsInitialSuggestions, @@ -120,7 +120,7 @@ const reducer = ( state, action ) => { const SuggestionsContainer = ( ) => { const navigation = useNavigation( ); const { params } = useRoute( ); - const { isConnected } = useNetInfo( ); + const { isConnected } = useConnectionStatus( ); const currentObservation = useStore( state => state.currentObservation ); const innerPhotos = ObservationPhoto.mapInnerPhotos( currentObservation ); // ObservationPhoto.mapObsPhotoUris returns *new* strings with every call, diff --git a/src/components/TaxonDetails/TaxonDetails.js b/src/components/TaxonDetails/TaxonDetails.js index e1639efad..51240ccf0 100644 --- a/src/components/TaxonDetails/TaxonDetails.js +++ b/src/components/TaxonDetails/TaxonDetails.js @@ -1,6 +1,6 @@ // @flow -import { refresh, useNetInfo } from "@react-native-community/netinfo"; +import { refresh } from "@react-native-community/netinfo"; import { useNavigation, useNavigationState, useRoute } from "@react-navigation/native"; import { fetchSpeciesCounts } from "api/observations"; import MatchSaveDiscardButtons from "components/Match/SaveDiscardButtons"; @@ -44,6 +44,7 @@ import { useTranslation, useUserMe, } from "sharedHooks"; +import useConnectionStatus from "sharedHooks/useConnectionStatus"; import useStore from "stores/useStore"; import colors from "styles/tailwindColors"; @@ -93,7 +94,7 @@ const TaxonDetails = ( ): Node => { } = params; const insets = useSafeAreaInsets(); const { t } = useTranslation( ); - const { isConnected } = useNetInfo( ); + const { isConnected } = useConnectionStatus( ); const { remoteUser } = useUserMe( ); const exitObservationFlow = useExitObservationFlow( { skipStoreReset: true, diff --git a/src/components/UserProfile/FollowersList.tsx b/src/components/UserProfile/FollowersList.tsx index 2f53ee3df..e868da13a 100644 --- a/src/components/UserProfile/FollowersList.tsx +++ b/src/components/UserProfile/FollowersList.tsx @@ -1,4 +1,3 @@ -import { useNetInfo } from "@react-native-community/netinfo"; import { useNavigation, useRoute } from "@react-navigation/native"; import { fetchUsers } from "api/users"; import { @@ -18,9 +17,10 @@ import { useInfiniteUserScroll, useTranslation, } from "sharedHooks"; +import useConnectionStatus from "sharedHooks/useConnectionStatus"; const FollowersList = ( ) => { - const { isConnected } = useNetInfo( ); + const { isConnected } = useConnectionStatus( ); const currentUser = useCurrentUser( ); const navigation = useNavigation( ); const { params } = useRoute( ); diff --git a/src/components/UserProfile/FollowingList.tsx b/src/components/UserProfile/FollowingList.tsx index 43a8fa3b0..312474cf1 100644 --- a/src/components/UserProfile/FollowingList.tsx +++ b/src/components/UserProfile/FollowingList.tsx @@ -1,4 +1,3 @@ -import { useNetInfo } from "@react-native-community/netinfo"; import { useNavigation, useRoute } from "@react-navigation/native"; import { fetchUsers } from "api/users"; import { @@ -18,9 +17,10 @@ import { useInfiniteUserScroll, useTranslation, } from "sharedHooks"; +import useConnectionStatus from "sharedHooks/useConnectionStatus"; const FollowingList = ( ) => { - const { isConnected } = useNetInfo( ); + const { isConnected } = useConnectionStatus( ); const currentUser = useCurrentUser( ); const navigation = useNavigation( ); const { params } = useRoute( ); diff --git a/src/navigation/OfflineNavigationGuard.tsx b/src/navigation/OfflineNavigationGuard.tsx index cf3a64395..7d7f51e6f 100644 --- a/src/navigation/OfflineNavigationGuard.tsx +++ b/src/navigation/OfflineNavigationGuard.tsx @@ -1,4 +1,3 @@ -import { useNetInfo } from "@react-native-community/netinfo"; import { NavigationContainer } from "@react-navigation/native"; import { useReactNavigationDevTools } from "@rozenite/react-navigation-plugin"; import type { PropsWithChildren } from "react"; @@ -6,12 +5,13 @@ import React, { useRef } from "react"; import { Alert } from "react-native"; import { logFirebaseScreenView } from "sharedHelpers/tracking"; import { useTranslation } from "sharedHooks"; +import useConnectionStatus from "sharedHooks/useConnectionStatus"; import { navigationRef } from "./navigationUtils"; const OfflineNavigationGuard = ( { children }: PropsWithChildren ) => { const routeNameRef = useRef( navigationRef.current?.getCurrentRoute()?.name ); - const { isConnected } = useNetInfo( ); + const { isConnected } = useConnectionStatus( ); const { t } = useTranslation( ); useReactNavigationDevTools( { ref: navigationRef } ); diff --git a/src/sharedHooks/useSuggestions/useOnlineSuggestions.ts b/src/sharedHooks/useSuggestions/useOnlineSuggestions.ts index 2296c045c..1dd697e3d 100644 --- a/src/sharedHooks/useSuggestions/useOnlineSuggestions.ts +++ b/src/sharedHooks/useSuggestions/useOnlineSuggestions.ts @@ -1,4 +1,3 @@ -import { useNetInfo } from "@react-native-community/netinfo"; import { useQueryClient } from "@tanstack/react-query"; import scoreImage from "api/computerVision"; import i18n from "i18next"; @@ -13,6 +12,7 @@ import { useAuthenticatedQuery, useCurrentUser, } from "sharedHooks"; +import useConnectionStatus from "sharedHooks/useConnectionStatus"; import useStore from "stores/useStore"; import { startOfflineExperimentInBackground } from "./suggestionComparisonExperiment"; @@ -87,7 +87,7 @@ const useOnlineSuggestions = ( const queryClient = useQueryClient( ); const [timedOut, setTimedOut] = useState( false ); - const { isConnected } = useNetInfo( ); + const { isConnected } = useConnectionStatus( ); const currentUser = useCurrentUser(); // Use locale in case there is no user session const locale = i18n?.language ?? "en"; diff --git a/src/sharedHooks/useSuggestions/useSuggestions.ts b/src/sharedHooks/useSuggestions/useSuggestions.ts index 45f04a14d..e6d34cee9 100644 --- a/src/sharedHooks/useSuggestions/useSuggestions.ts +++ b/src/sharedHooks/useSuggestions/useSuggestions.ts @@ -1,5 +1,5 @@ -import { useNetInfo } from "@react-native-community/netinfo"; import { useMemo } from "react"; +import useConnectionStatus from "sharedHooks/useConnectionStatus"; import filterSuggestions from "./filterSuggestions"; import type { UseSuggestionsOptions, UseSuggestionsResult } from "./types"; @@ -10,7 +10,7 @@ const useSuggestions = ( photoUri: string, options: UseSuggestionsOptions, ): UseSuggestionsResult => { - const { isConnected } = useNetInfo( ); + const { isConnected } = useConnectionStatus( ); const { shouldFetchOnlineSuggestions, onFetchError, diff --git a/tests/integration/SavedMatch.test.js b/tests/integration/SavedMatch.test.js index c27f11548..ff353fc3a 100644 --- a/tests/integration/SavedMatch.test.js +++ b/tests/integration/SavedMatch.test.js @@ -1,8 +1,8 @@ -import { useNetInfo } from "@react-native-community/netinfo"; import { screen } from "@testing-library/react-native"; import SavedMatchContainer from "components/ObsDetailsDefaultMode/SavedMatch/SavedMatchContainer"; import { t } from "i18next"; import React from "react"; +import useConnectionStatus from "sharedHooks/useConnectionStatus"; import factory from "tests/factory"; import faker from "tests/helpers/faker"; import { renderAppWithComponent } from "tests/helpers/render"; @@ -82,7 +82,7 @@ describe( "SavedMatch", ( ) => { } ); it( "should not show learn more button when offline", async ( ) => { - useNetInfo.mockImplementation( ( ) => ( { isConnected: false } ) ); + useConnectionStatus.mockImplementation( ( ) => ( { isConnected: false } ) ); renderAppWithComponent( ); const learnMoreButton = screen.queryByText( t( "LEARN-MORE-ABOUT-THIS-SPECIES" ) ); expect( learnMoreButton ).toBeFalsy( ); diff --git a/tests/integration/broken/SuggestionsWithUnsyncedObs.test.js b/tests/integration/broken/SuggestionsWithUnsyncedObs.test.js index fbb0e20ae..c138bba2d 100644 --- a/tests/integration/broken/SuggestionsWithUnsyncedObs.test.js +++ b/tests/integration/broken/SuggestionsWithUnsyncedObs.test.js @@ -1,4 +1,3 @@ -import { useNetInfo } from "@react-native-community/netinfo"; import { screen, userEvent, @@ -8,6 +7,7 @@ import { import * as usePredictions from "components/Camera/AICamera/hooks/usePredictions"; import inatjs from "inaturalistjs"; import { Animated } from "react-native"; +import useConnectionStatus from "sharedHooks/useConnectionStatus"; import * as useLocationPermission from "sharedHooks/useLocationPermission"; import { SCREEN_AFTER_PHOTO_EVIDENCE } from "stores/createLayoutSlice"; import useStore from "stores/useStore"; @@ -374,7 +374,7 @@ describe( "from AICamera directly", ( ) => { describe( "suggestions while offline", ( ) => { it( "should not call score_image and should not show any location buttons", async ( ) => { - useNetInfo.mockImplementation( ( ) => ( { isConnected: false } ) ); + useConnectionStatus.mockImplementation( ( ) => ( { isConnected: false } ) ); await setupAppWithSignedInUser( ); await navigateToSuggestionsViaAICamera( ); expect( inatjs.computervision.score_image ).not.toHaveBeenCalled( ); @@ -391,7 +391,7 @@ describe( "from AICamera directly", ( ) => { getPredictionsForImage.mockImplementation( async ( ) => ( mockModelResult ), ); - useNetInfo.mockImplementation( ( ) => ( { isConnected: false } ) ); + useConnectionStatus.mockImplementation( ( ) => ( { isConnected: false } ) ); await setupAppWithSignedInUser( ); await navigateToSuggestionsViaAICamera( ); const topTaxonSuggestion = await screen.findByLabelText( /Choose top taxon/ ); @@ -406,7 +406,7 @@ describe( "from AICamera directly", ( ) => { getPredictionsForImage.mockImplementation( async ( ) => ( mockModelResultNoConfidence ), ); - useNetInfo.mockImplementation( ( ) => ( { isConnected: false } ) ); + useConnectionStatus.mockImplementation( ( ) => ( { isConnected: false } ) ); await setupAppWithSignedInUser( ); await navigateToSuggestionsViaAICamera( ); @@ -426,7 +426,7 @@ describe( "from AICamera directly", ( ) => { getPredictionsForImage.mockImplementation( async ( ) => ( mockModelResultWithHuman ), ); - useNetInfo.mockImplementation( ( ) => ( { isConnected: false } ) ); + useConnectionStatus.mockImplementation( ( ) => ( { isConnected: false } ) ); await setupAppWithSignedInUser( ); await navigateToSuggestionsViaAICamera( ); diff --git a/tests/unit/components/BottomTabNavigator/CustomTabBar.test.js b/tests/unit/components/BottomTabNavigator/CustomTabBar.test.js index 1d2aacb13..4ff580653 100644 --- a/tests/unit/components/BottomTabNavigator/CustomTabBar.test.js +++ b/tests/unit/components/BottomTabNavigator/CustomTabBar.test.js @@ -1,7 +1,7 @@ -import { useNetInfo } from "@react-native-community/netinfo"; import { screen } from "@testing-library/react-native"; import CustomTabBarContainer from "navigation/BottomTabNavigator/CustomTabBarContainer"; import React from "react"; +import useConnectionStatus from "sharedHooks/useConnectionStatus"; import * as useCurrentUser from "sharedHooks/useCurrentUser"; import useStore from "stores/useStore"; import factory from "tests/factory"; @@ -62,7 +62,7 @@ describe( "CustomTabBar", () => { } ); it( "should display person icon when connectivity is low", async ( ) => { - useNetInfo.mockImplementation( ( ) => ( { isConnected: false } ) ); + useConnectionStatus.mockImplementation( ( ) => ( { isConnected: false } ) ); renderComponent( ); const personIcon = screen.getByTestId( "NavButton.personIcon" ); @@ -83,7 +83,7 @@ describe( "CustomTabBar with advanced user layout", () => { beforeEach( ( ) => { jest.resetAllMocks(); - useNetInfo.mockImplementation( ( ) => ( { isConnected: true } ) ); + useConnectionStatus.mockImplementation( ( ) => ( { isConnected: true } ) ); // Re-establish the safe area context mock after resetAllMocks const safeAreaContext = require( "react-native-safe-area-context" ); safeAreaContext.useSafeAreaInsets.mockImplementation( () => ( { diff --git a/tests/unit/components/Settings/Settings.test.js b/tests/unit/components/Settings/Settings.test.js index a1ed57a0d..ad3659928 100644 --- a/tests/unit/components/Settings/Settings.test.js +++ b/tests/unit/components/Settings/Settings.test.js @@ -1,9 +1,9 @@ -import { useNetInfo } from "@react-native-community/netinfo"; import { fireEvent, screen } from "@testing-library/react-native"; import Settings from "components/Settings/Settings"; import i18n from "i18next"; import inatjs from "inaturalistjs"; import React from "react"; +import useConnectionStatus from "sharedHooks/useConnectionStatus"; import * as useCurrentUser from "sharedHooks/useCurrentUser"; import useStore from "stores/useStore"; import factory, { makeResponse } from "tests/factory"; @@ -89,7 +89,7 @@ describe( "Settings", ( ) => { describe( "no internet", ( ) => { beforeEach( ( ) => { - useNetInfo.mockImplementation( ( ) => ( { isConnected: false } ) ); + useConnectionStatus.mockImplementation( ( ) => ( { isConnected: false } ) ); } ); it( "should not navigate to iNaturalist settings if no internet", async ( ) => {