mirror of
https://github.com/inaturalist/iNaturalistReactNative.git
synced 2026-02-02 01:51:35 -05:00
Make explore view sticky; default to species view (#1647)
* Remove tab bar when sharing photos into app; closes #1645 * Make explore view sticky with species as default view; closes #1614 * Fix Explore integration test; use default species view
This commit is contained in:
committed by
GitHub
parent
716efc1a78
commit
829fa70f34
@@ -23,7 +23,6 @@ const RootExploreContainerWithContext = ( ): Node => {
|
||||
const currentUser = useCurrentUser( );
|
||||
const storedParams = useStore( state => state.storedParams );
|
||||
const setStoredParams = useStore( state => state.setStoredParams );
|
||||
const setExploreView = useStore( state => state.setExploreView );
|
||||
|
||||
const worldwidePlaceText = t( "Worldwide" );
|
||||
|
||||
@@ -33,10 +32,6 @@ const RootExploreContainerWithContext = ( ): Node => {
|
||||
|
||||
const [showFiltersModal, setShowFiltersModal] = useState( false );
|
||||
|
||||
useEffect( ( ) => {
|
||||
setExploreView( "species" );
|
||||
}, [setExploreView] );
|
||||
|
||||
const updateTaxon = ( taxon: Object ) => {
|
||||
dispatch( {
|
||||
type: EXPLORE_ACTION.CHANGE_TAXON,
|
||||
@@ -167,10 +162,10 @@ const RootExploreContainerWithContext = ( ): Node => {
|
||||
);
|
||||
};
|
||||
|
||||
const ExploreContainer = (): Node => (
|
||||
const RootExploreContainer = (): Node => (
|
||||
<ExploreProvider>
|
||||
<RootExploreContainerWithContext />
|
||||
</ExploreProvider>
|
||||
);
|
||||
|
||||
export default ExploreContainer;
|
||||
export default RootExploreContainer;
|
||||
|
||||
@@ -14,15 +14,10 @@ const useParams = ( ): Object => {
|
||||
const { params } = useRoute( );
|
||||
const { dispatch, setExploreLocation } = useExplore( );
|
||||
const storedParams = useStore( state => state.storedParams );
|
||||
const setExploreView = useStore( state => state.setExploreView );
|
||||
|
||||
const worldwidePlaceText = t( "Worldwide" );
|
||||
|
||||
const updateContextWithParams = useCallback( async ( storedState = { } ) => {
|
||||
if ( params?.viewSpecies ) {
|
||||
setExploreView( "species" );
|
||||
}
|
||||
|
||||
const setWorldwide = ( ) => {
|
||||
dispatch( {
|
||||
type: EXPLORE_ACTION.SET_PLACE,
|
||||
@@ -81,7 +76,6 @@ const useParams = ( ): Object => {
|
||||
dispatch,
|
||||
params,
|
||||
setExploreLocation,
|
||||
setExploreView,
|
||||
worldwidePlaceText
|
||||
] );
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ const ToolbarContainer = ( {
|
||||
syncInProgress,
|
||||
toggleLayout
|
||||
}: Props ): Node => {
|
||||
const setExploreView = useStore( state => state.setExploreView );
|
||||
const currentUser = useCurrentUser( );
|
||||
const navigation = useNavigation( );
|
||||
const deletions = useStore( state => state.deletions );
|
||||
@@ -69,12 +70,15 @@ const ToolbarContainer = ( {
|
||||
] );
|
||||
|
||||
const navToExplore = useCallback(
|
||||
( ) => navigation.navigate( "Explore", {
|
||||
user: currentUser,
|
||||
worldwide: true,
|
||||
resetStoredParams: true
|
||||
} ),
|
||||
[navigation, currentUser]
|
||||
( ) => {
|
||||
setExploreView( "observations" );
|
||||
navigation.navigate( "Explore", {
|
||||
user: currentUser,
|
||||
worldwide: true,
|
||||
resetStoredParams: true
|
||||
} );
|
||||
},
|
||||
[navigation, currentUser, setExploreView]
|
||||
);
|
||||
|
||||
const { t } = useTranslation( );
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
import type { Node } from "react";
|
||||
import React, { useCallback } from "react";
|
||||
import { useTranslation } from "sharedHooks";
|
||||
import useStore from "stores/useStore";
|
||||
|
||||
import AboutProjectType from "./AboutProjectType";
|
||||
|
||||
@@ -26,6 +27,8 @@ type Props = {
|
||||
const ProjectDetails = ( {
|
||||
project, joinProject, leaveProject, loadingProjectMembership
|
||||
}: Props ): Node => {
|
||||
const setExploreView = useStore( state => state.setExploreView );
|
||||
|
||||
const { t } = useTranslation( );
|
||||
const navigation = useNavigation( );
|
||||
|
||||
@@ -39,13 +42,15 @@ const ProjectDetails = ( {
|
||||
);
|
||||
|
||||
const onSpeciesPressed = useCallback(
|
||||
( ) => navigation.navigate( "Explore", {
|
||||
project,
|
||||
worldwide: true,
|
||||
viewSpecies: true,
|
||||
resetStoredParams: true
|
||||
} ),
|
||||
[navigation, project]
|
||||
( ) => {
|
||||
setExploreView( "species" );
|
||||
navigation.navigate( "Explore", {
|
||||
project,
|
||||
worldwide: true,
|
||||
resetStoredParams: true
|
||||
} );
|
||||
},
|
||||
[navigation, project, setExploreView]
|
||||
);
|
||||
|
||||
if ( !project ) {
|
||||
|
||||
@@ -30,6 +30,7 @@ import DeviceInfo from "react-native-device-info";
|
||||
import { useTheme } from "react-native-paper";
|
||||
import { log } from "sharedHelpers/logger";
|
||||
import { useAuthenticatedQuery, useTranslation, useUserMe } from "sharedHooks";
|
||||
import useStore from "stores/useStore";
|
||||
|
||||
import EstablishmentMeans from "./EstablishmentMeans";
|
||||
import TaxonDetailsMediaViewerHeader from "./TaxonDetailsMediaViewerHeader";
|
||||
@@ -48,6 +49,7 @@ const TAXON_URL = "https://www.inaturalist.org/taxa";
|
||||
const isTablet = DeviceInfo.isTablet();
|
||||
|
||||
const TaxonDetails = ( ): Node => {
|
||||
const setExploreView = useStore( state => state.setExploreView );
|
||||
const theme = useTheme( );
|
||||
const navigation = useNavigation( );
|
||||
const { params } = useRoute( );
|
||||
@@ -229,17 +231,20 @@ const TaxonDetails = ( ): Node => {
|
||||
<View className="ml-5">
|
||||
<INatIconButton
|
||||
icon="compass-rose-outline"
|
||||
onPress={( ) => navigation.navigate( "TabNavigator", {
|
||||
screen: "TabStackNavigator",
|
||||
params: {
|
||||
screen: "Explore",
|
||||
onPress={( ) => {
|
||||
setExploreView( "observations" );
|
||||
navigation.navigate( "TabNavigator", {
|
||||
screen: "TabStackNavigator",
|
||||
params: {
|
||||
taxon,
|
||||
worldwide: true,
|
||||
resetStoredParams: true
|
||||
screen: "Explore",
|
||||
params: {
|
||||
taxon,
|
||||
worldwide: true,
|
||||
resetStoredParams: true
|
||||
}
|
||||
}
|
||||
}
|
||||
} )}
|
||||
} );
|
||||
}}
|
||||
accessibilityLabel={t( "See-observations-of-this-taxon-in-explore" )}
|
||||
accessibilityHint={t( "Navigates-to-explore" )}
|
||||
size={30}
|
||||
|
||||
@@ -25,11 +25,13 @@ import {
|
||||
useCurrentUser,
|
||||
useIsConnected
|
||||
} from "sharedHooks";
|
||||
import useStore from "stores/useStore";
|
||||
|
||||
import FollowButtonContainer from "./FollowButtonContainer";
|
||||
import UnfollowSheet from "./UnfollowSheet";
|
||||
|
||||
const UserProfile = ( ): Node => {
|
||||
const setExploreView = useStore( state => state.setExploreView );
|
||||
const navigation = useNavigation( );
|
||||
const currentUser = useCurrentUser( );
|
||||
const { params } = useRoute( );
|
||||
@@ -79,22 +81,27 @@ const UserProfile = ( ): Node => {
|
||||
// }, [navigation, user, currentUser] );
|
||||
|
||||
const onObservationPressed = useCallback(
|
||||
( ) => navigation.navigate( "Explore", {
|
||||
user,
|
||||
worldwide: true,
|
||||
resetStoredParams: true
|
||||
} ),
|
||||
[navigation, user]
|
||||
( ) => {
|
||||
setExploreView( "observations" );
|
||||
navigation.navigate( "Explore", {
|
||||
user,
|
||||
worldwide: true,
|
||||
resetStoredParams: true
|
||||
} );
|
||||
},
|
||||
[navigation, user, setExploreView]
|
||||
);
|
||||
|
||||
const onSpeciesPressed = useCallback(
|
||||
( ) => navigation.navigate( "Explore", {
|
||||
user,
|
||||
worldwide: true,
|
||||
viewSpecies: true,
|
||||
resetStoredParams: true
|
||||
} ),
|
||||
[navigation, user]
|
||||
( ) => {
|
||||
setExploreView( "species" );
|
||||
navigation.navigate( "Explore", {
|
||||
user,
|
||||
worldwide: true,
|
||||
resetStoredParams: true
|
||||
} );
|
||||
},
|
||||
[navigation, user, setExploreView]
|
||||
);
|
||||
|
||||
if ( !user ) {
|
||||
|
||||
@@ -9,6 +9,12 @@ export const initialMapRegion = {
|
||||
longitudeDelta: DELTA
|
||||
};
|
||||
|
||||
const DEFAULT_STATE = {
|
||||
storedParams: {},
|
||||
exploreView: "species",
|
||||
mapRegion: initialMapRegion
|
||||
};
|
||||
|
||||
interface MapRegion {
|
||||
latitude: number,
|
||||
longitude: number,
|
||||
@@ -26,11 +32,9 @@ interface ExploreSlice {
|
||||
}
|
||||
|
||||
const createExploreSlice: StateCreator<ExploreSlice> = set => ( {
|
||||
storedParams: {},
|
||||
...DEFAULT_STATE,
|
||||
setStoredParams: params => set( ( ) => ( { storedParams: params } ) ),
|
||||
exploreView: "observations",
|
||||
setExploreView: exploreView => set( ( ) => ( { exploreView } ) ),
|
||||
mapRegion: initialMapRegion,
|
||||
setMapRegion: region => set( ( ) => ( { mapRegion: region } ) )
|
||||
} );
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { fireEvent, screen } from "@testing-library/react-native";
|
||||
import { fireEvent, screen, userEvent } from "@testing-library/react-native";
|
||||
import ExploreContainer from "components/Explore/ExploreContainer";
|
||||
import inatjs from "inaturalistjs";
|
||||
import React from "react";
|
||||
@@ -17,12 +17,34 @@ const mockRemoteObservation = factory( "RemoteObservation", {
|
||||
taxon: factory.states( "genus" )( "RemoteTaxon" )
|
||||
} );
|
||||
|
||||
const mockTaxon = factory( "LocalTaxon" );
|
||||
|
||||
const actor = userEvent.setup( );
|
||||
|
||||
beforeAll( ( ) => {
|
||||
inatjs.observations.speciesCounts.mockResolvedValue( makeResponse( [{
|
||||
count: 1,
|
||||
taxon: mockTaxon
|
||||
}] ) );
|
||||
inatjs.observations.search.mockResolvedValue( makeResponse( [mockRemoteObservation] ) );
|
||||
} );
|
||||
|
||||
const switchToObservationsView = async ( ) => {
|
||||
const speciesViewIcon = await screen.findByLabelText( /Species View/ );
|
||||
expect( speciesViewIcon ).toBeVisible( );
|
||||
await actor.press( speciesViewIcon );
|
||||
const observationsRadioButton = await screen.findByText( "Observations" );
|
||||
await actor.press( observationsRadioButton );
|
||||
const confirmButton = await screen.findByText( /EXPLORE OBSERVATIONS/ );
|
||||
await actor.press( confirmButton );
|
||||
const obsTaxonNameElt = await screen.findByText( mockRemoteObservation.taxon.name );
|
||||
expect( obsTaxonNameElt ).toBeTruthy( );
|
||||
};
|
||||
|
||||
describe( "Explore", ( ) => {
|
||||
it( "should render", async ( ) => {
|
||||
inatjs.observations.search.mockResolvedValue( makeResponse( [mockRemoteObservation] ) );
|
||||
it( "should render species view and switch to observations view list correctly", async ( ) => {
|
||||
renderAppWithComponent( <ExploreContainer /> );
|
||||
const obsTaxonNameElt = await screen.findByText( mockRemoteObservation.taxon.name );
|
||||
expect( obsTaxonNameElt ).toBeTruthy( );
|
||||
await switchToObservationsView( );
|
||||
expect(
|
||||
await screen.findByTestId( `ObsStatus.${mockRemoteObservation.uuid}` )
|
||||
).toBeTruthy( );
|
||||
@@ -31,11 +53,9 @@ describe( "Explore", ( ) => {
|
||||
).toBeFalsy( );
|
||||
} );
|
||||
|
||||
it( "should display grid item correctly", async ( ) => {
|
||||
inatjs.observations.search.mockResolvedValue( makeResponse( [mockRemoteObservation] ) );
|
||||
it( "should display observations view grid correctly", async ( ) => {
|
||||
renderAppWithComponent( <ExploreContainer /> );
|
||||
const obsTaxonNameElt = await screen.findByText( mockRemoteObservation.taxon.name );
|
||||
expect( obsTaxonNameElt ).toBeTruthy( );
|
||||
await switchToObservationsView( );
|
||||
expect(
|
||||
await screen.findByTestId( "SegmentedButton.grid" )
|
||||
).toBeTruthy( );
|
||||
|
||||
@@ -233,8 +233,8 @@ describe( "logged in", ( ) => {
|
||||
await actor.press( taxonDetailsExploreButton );
|
||||
const defaultGlobalLocation = await screen.findByText( /Worldwide/ );
|
||||
expect( defaultGlobalLocation ).toBeVisible( );
|
||||
const speciesIcon = await screen.findByLabelText( /Species View/ );
|
||||
expect( speciesIcon ).toBeVisible( );
|
||||
const observationsIcon = await screen.findByLabelText( /Observations View/ );
|
||||
expect( observationsIcon ).toBeVisible( );
|
||||
const backButton = screen.queryByTestId( "Explore.BackButton" );
|
||||
await actor.press( backButton );
|
||||
expect( taxonDetailsExploreButton ).toBeVisible( );
|
||||
|
||||
Reference in New Issue
Block a user