Avoid back button disappearing when offline (#1908)

* Customize back button; move icon assets into our image dir

* Fix ContextHeader with updated back button

* Fix styling around back buttons

* Fix taxon details header

* Test fix

* Fix signed in e2e test
This commit is contained in:
Amanda Bullington
2024-08-02 09:46:54 -07:00
committed by GitHub
parent 960f3e3b67
commit 5dbf5ef9a1
31 changed files with 126 additions and 111 deletions

View File

@@ -172,7 +172,7 @@ describe( "Signed in user", () => {
await element( by.id( `ObsDetails.${uuid}` ) ).scrollTo( "bottom" );
const comment = element( by.text( "This is a comment" ) );
await waitFor( comment ).toBeVisible().withTimeout( 10000 );
await element( by.label( "Go back" ) ).tap( );
await element( by.id( "ObsDetails.BackButton" ) ).tap( );
await waitFor( username ).toBeVisible( ).withTimeout( 10000 );
/*

View File

@@ -25,7 +25,7 @@ import {
import { getShadowForColor } from "styles/global";
import colors from "styles/tailwindColors";
import Header from "./Header/Header";
import ExploreHeader from "./Header/ExploreHeader";
import useCurrentExploreView from "./hooks/useCurrentExploreView";
import IdentifiersView from "./IdentifiersView";
import ObservationsView from "./ObservationsView";
@@ -104,7 +104,7 @@ const Explore = ( {
const headerCount = count[currentExploreView];
const renderHeader = ( ) => (
<Header
<ExploreHeader
count={headerCount}
exploreView={currentExploreView}
exploreViewIcon={icon}

View File

@@ -17,7 +17,7 @@ import useStore from "stores/useStore";
import Explore from "./Explore";
import mapParamsToAPI from "./helpers/mapParamsToAPI";
import useHeaderCount from "./hooks/useHeaderCount";
import useExploreHeaderCount from "./hooks/useExploreHeaderCount";
import useParams from "./hooks/useParams";
const ExploreContainerWithContext = ( ): Node => {
@@ -84,8 +84,8 @@ const ExploreContainerWithContext = ( ): Node => {
per_page: 20
};
// need this hook to be top-level enough that HeaderCount rerenders
const { count, loadingStatus, updateCount } = useHeaderCount( );
// need this hook to be top-level enough that ExploreHeaderCount rerenders
const { count, loadingStatus, updateCount } = useExploreHeaderCount( );
const closeFiltersModal = ( ) => setShowFiltersModal( false );

View File

@@ -20,7 +20,7 @@ import { useTranslation } from "sharedHooks";
import colors from "styles/tailwindColors";
import placeGuessText from "../helpers/placeGuessText";
import HeaderCount from "./HeaderCount";
import ExploreHeaderCount from "./ExploreHeaderCount";
type Props = {
count: ?number,
@@ -125,7 +125,7 @@ const Header = ( {
)}
</View>
</View>
<HeaderCount
<ExploreHeaderCount
count={count}
exploreView={exploreView}
exploreViewIcon={exploreViewIcon}

View File

@@ -19,7 +19,7 @@ type Props = {
onPress: Function,
}
const HeaderCount = ( {
const ExploreHeaderCount = ( {
count,
exploreView,
exploreViewIcon,
@@ -63,4 +63,4 @@ const HeaderCount = ( {
);
};
export default HeaderCount;
export default ExploreHeaderCount;

View File

@@ -20,7 +20,7 @@ import useStore from "stores/useStore";
import Explore from "./Explore";
import mapParamsToAPI from "./helpers/mapParamsToAPI";
import useHeaderCount from "./hooks/useHeaderCount";
import useExploreHeaderCount from "./hooks/useExploreHeaderCount";
const RootExploreContainerWithContext = ( ): Node => {
const navigation = useNavigation( );
@@ -94,8 +94,8 @@ const RootExploreContainerWithContext = ( ): Node => {
per_page: 20
};
// need this hook to be top-level enough that HeaderCount rerenders
const { count, loadingStatus, updateCount } = useHeaderCount( );
// need this hook to be top-level enough that ExploreHeaderCount rerenders
const { count, loadingStatus, updateCount } = useExploreHeaderCount( );
const closeFiltersModal = ( ) => setShowFiltersModal( false );

View File

@@ -4,7 +4,7 @@ import {
useCallback, useMemo, useState
} from "react";
const useHeaderCount = ( ): Object => {
const useExploreHeaderCount = ( ): Object => {
const [count, setCount] = useState( {
observations: null,
species: null,
@@ -32,4 +32,4 @@ const useHeaderCount = ( ): Object => {
};
};
export default useHeaderCount;
export default useExploreHeaderCount;

View File

@@ -8,10 +8,8 @@ import type { Node } from "react";
import React from "react";
import { useSafeAreaInsets } from "react-native-safe-area-context";
import { dropShadow } from "styles/global";
import colors from "styles/tailwindColors";
type Props = {
navigation: Object,
route: Object,
options: Object
};
@@ -26,7 +24,6 @@ const BACK_BUTTON_STYLE = {
};
const FullPageWebViewHeader = ( {
navigation,
route,
options
}: Props ): Node => {
@@ -67,8 +64,6 @@ const FullPageWebViewHeader = ( {
)}
>
<BackButton
color={colors.black}
onPress={navigation.goBack}
inCustomHeader
customStyles={BACK_BUTTON_STYLE}
/>

View File

@@ -7,11 +7,8 @@ import {
import { View } from "components/styledComponents";
import type { Node } from "react";
import React from "react";
import { useTheme } from "react-native-paper";
import useTranslation from "sharedHooks/useTranslation";
const BACK_BUTTON_STYLE = { position: "absolute", start: 0 };
type Props = {
onClose: Function,
photoCount: number,
@@ -23,7 +20,6 @@ const MediaViewerHeader = ( {
onClose,
soundCount = 0
}: Props ): Node => {
const theme = useTheme( );
const { t } = useTranslation( );
let headerText = t( "X-PHOTOS", { photoCount } );
@@ -36,16 +32,19 @@ const MediaViewerHeader = ( {
}
return (
<View className="flex-row items-center justify-center min-h-[44]">
<View className="flex-row min-h-[44] justify-between">
<BackButton
inCustomHeader
color={theme.colors.onPrimary}
customStyles={BACK_BUTTON_STYLE}
color="white"
onPress={onClose}
className="w-[44px]"
/>
<Heading4 className="color-white">
{headerText}
</Heading4>
<View className="justify-center min-h-[44]">
<Heading4 className="color-white">
{headerText}
</Heading4>
</View>
<View className="w-[44px]" />
</View>
);
};

View File

@@ -6,7 +6,7 @@ import {
INatIconButton
} from "components/SharedComponents";
import {
LinearGradient
LinearGradient, View
} from "components/styledComponents";
import React from "react";
import DeviceInfo from "react-native-device-info";
@@ -56,25 +56,29 @@ const ObsDetailsHeader = ( {
"transparent"
]}
>
<BackButton color="white" inCustomHeader />
{
belongsToCurrentUser
? (
<INatIconButton
testID="ObsDetail.editButton"
onPress={() => {
prepareObsEdit( localObservation );
navigateToObsEdit( navigation );
}}
icon="pencil"
color={!rightIconBlack
? colors.white
: colors.black}
accessibilityLabel={t( "Edit" )}
/>
)
: <HeaderKebabMenu observationId={observationId} white={!rightIconBlack} />
}
<View className="left-4 top-4">
<BackButton color="white" inCustomHeader testID="ObsDetails.BackButton" />
</View>
<View className="right-4">
{
belongsToCurrentUser
? (
<INatIconButton
testID="ObsDetail.editButton"
onPress={() => {
prepareObsEdit( localObservation );
navigateToObsEdit( navigation );
}}
icon="pencil"
color={!rightIconBlack
? colors.white
: colors.black}
accessibilityLabel={t( "Edit" )}
/>
)
: <HeaderKebabMenu observationId={observationId} white={!rightIconBlack} />
}
</View>
</LinearGradient>
);
};

View File

@@ -86,7 +86,7 @@ const EvidenceSection = ( {
};
return (
<View className="mx-6">
<View className="mx-6 mt-4">
{showAddEvidenceSheet && (
<AddEvidenceSheet
disableAddingMoreEvidence={

View File

@@ -14,9 +14,9 @@ import colors from "styles/tailwindColors";
import BottomButtons from "./BottomButtons";
import EvidenceSectionContainer from "./EvidenceSectionContainer";
import Header from "./Header";
import IdentificationSection from "./IdentificationSection";
import MultipleObservationsArrows from "./MultipleObservationsArrows";
import ObsEditHeader from "./ObsEditHeader";
import OtherDataSection from "./OtherDataSection";
const DROP_SHADOW = getShadowForColor( colors.black, {
@@ -81,7 +81,7 @@ const ObsEdit = ( ): Node => {
return (
<>
<ViewWrapper testID="obs-edit">
<Header
<ObsEditHeader
currentObservation={currentObservation}
observations={observations}
/>

View File

@@ -22,7 +22,7 @@ type Props = {
currentObservation: Object
}
const Header = ( {
const ObsEditHeader = ( {
observations,
currentObservation
}: Props ): Node => {
@@ -103,15 +103,13 @@ const Header = ( {
] );
const renderBackButton = useCallback( ( ) => {
const extraPadding = {
marginStart: 15,
paddingVertical: 18,
paddingEnd: 24
const extraStart = {
marginStart: 15
};
return (
<BackButton
onPress={handleBackButtonPress}
customStyles={extraPadding}
customStyles={extraStart}
testID="ObsEdit.BackButton"
/>
);
@@ -198,4 +196,4 @@ const Header = ( {
);
};
export default Header;
export default ObsEditHeader;

View File

@@ -80,6 +80,7 @@ const PhotoSharing = ( ): Node => {
} ) ),
firstObservationDefaults
} );
console.log( "photo sharing and landing group" );
navigation.navigate( "NoBottomTabStackNavigator", { screen: "GroupPhotos" } );
}
}, [

View File

@@ -1,5 +1,6 @@
import { HeaderBackButton } from "@react-navigation/elements";
import { useNavigation } from "@react-navigation/native";
import { Image } from "components/styledComponents";
import type { Node } from "react";
import React from "react";
import { Platform } from "react-native";
@@ -16,12 +17,27 @@ type Props = {
testID?: string
}
const REACT_NAVIGATION_BACK_BUTTON_STYLE = {
start: Platform.OS === "ios"
? -15
: 0,
minWidth: 44,
minHeight: 44
// styling lifted from
// https://github.com/react-navigation/react-navigation/blob/395410a7a751492ad846c7723dd33b55891173e1/packages/elements/src/Header/HeaderBackButton.tsx
const REACT_NAVIGATION_BACK_BUTTON_STYLES = {
container: {
...Platform.select( {
ios: {
paddingLeft: 8,
paddingRight: 22
},
default: {
paddingVertical: 3,
paddingHorizontal: 11
}
} )
},
icon: Platform.select( {
ios: {
height: 21,
width: 13
}
} )
};
const BackButton = ( {
@@ -35,17 +51,31 @@ const BackButton = ( {
const tintColor = color || colors.black;
const { t } = useTranslation( );
const imageStyles = [
!inCustomHeader && REACT_NAVIGATION_BACK_BUTTON_STYLES.icon,
Boolean( tintColor ) && { tintColor },
customStyles
];
const backImage = ( ) => (
<Image
accessibilityLabel={t( "Go-back" )}
accessibilityIgnoresInvertColors
fadeDuration={0}
resizeMode="contain"
source={require( "images/backIcons/back-icon.png" )}
style={imageStyles}
testID="Image.BackButton"
/>
);
if ( navigation?.canGoBack( ) ) {
return (
<HeaderBackButton
accessibilityLabel={t( "Go-back" )}
backImage={backImage}
labelVisible={false}
onPress={onPress || navigation.goBack}
// move backbutton to same start as in react-navigation
style={[
!inCustomHeader && REACT_NAVIGATION_BACK_BUTTON_STYLE,
customStyles
]}
style={REACT_NAVIGATION_BACK_BUTTON_STYLES.container}
testID={testID}
tintColor={tintColor}
/>

View File

@@ -190,20 +190,17 @@ const TaxonDetails = ( ): Node => {
<StatusBar barStyle="light-content" backgroundColor="#000000" />
<View className="flex-1 h-full bg-black">
<View className="w-full h-[420px] shrink-1">
<View className="absolute left-4 top-4 z-10">
<BackButton color="white" />
</View>
<TaxonMedia
loading={isLoading}
photos={photos}
tablet={isTablet}
onChangeIndex={setMediaIndex}
/>
<View className="absolute left-5 top-5">
<BackButton
color={theme.colors.onPrimary}
onPress={( ) => navigation.goBack( )}
/>
</View>
{!hideNavButtons && (
<View className="absolute right-5 top-5">
<View className="absolute right-4 top-1">
<KebabMenu
visible={kebabMenuVisible}
setVisible={setKebabMenuVisible}

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 207 B

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 B

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 373 B

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 B

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 290 B

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 B

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 405 B

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 B

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 761 B

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 207 B

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 812 B

View File

@@ -40,12 +40,17 @@ const ContextHeader = ( {
return options.headerLeft();
}
const extraPadding = {
marginStart: 15
};
return (
back && (
<BackButton
color={colors.black}
onPress={navigation.goBack}
inCustomHeader
customStyles={extraPadding}
/>
)
);
@@ -83,7 +88,9 @@ const ContextHeader = ( {
}
)}
>
{backButton}
<View className="pr-1 pt-1.5">
{backButton}
</View>
{customTitleComponent
? (
options.headerTitle()

View File

@@ -14,11 +14,10 @@ import PermissionGateContainer, {
} from "components/SharedComponents/PermissionGateContainer.tsx";
import SoundRecorder from "components/SoundRecorder/SoundRecorder";
import { t } from "i18next";
import ContextHeader from "navigation/ContextHeader";
import {
hideHeader,
hideHeaderLeft,
showCustomHeader,
showHeader
hideHeaderLeft
} from "navigation/navigationOptions";
import type { Node } from "react";
import React from "react";
@@ -40,10 +39,9 @@ const CAMERA_SCREEN_OPTIONS = {
};
const GROUP_PHOTOS_OPTIONS = {
...showHeader,
...showCustomHeader,
lazy: true,
headerShadowVisible: false
header: ContextHeader,
alignStart: true,
lazy: true
};
const SOUND_RECORDER_OPTIONS = {

View File

@@ -8,8 +8,6 @@ import React from "react";
import { View } from "react-native";
import colors from "styles/tailwindColors";
import ContextHeader from "./ContextHeader";
const baseHeaderOptions: Object = {
headerShown: true,
headerBackTitleVisible: false,
@@ -52,14 +50,6 @@ const showSimpleCustomHeader: Object = {
headerShadowVisible: true
};
const showCustomHeader: Object = {
...baseHeaderOptions,
header: ContextHeader,
headerShadowVisible: true,
alignStart: true,
headerLeft: () => <BackButton inCustomHeader />
};
const hideHeader = {
headerShown: false
};
@@ -87,7 +77,6 @@ export {
hideDrawerHeaderLeft,
hideHeader,
removeBottomBorder,
showCustomHeader,
showHeader,
showLongHeader,
showSimpleCustomHeader

View File

@@ -1,5 +1,5 @@
import { screen } from "@testing-library/react-native";
import Header from "components/ObsEdit/Header";
import ObsEditHeader from "components/ObsEdit/ObsEditHeader";
import React from "react";
import factory from "tests/factory";
import faker from "tests/helpers/faker";
@@ -10,10 +10,10 @@ const mockObservations = [
factory( "LocalObservation" )
];
describe( "Header", () => {
describe( "ObsEditHeader", () => {
it( "has no accessibility errors", () => {
const button = (
<Header
<ObsEditHeader
observations={mockObservations}
/>
);
@@ -23,7 +23,7 @@ describe( "Header", () => {
it( "renders a header title with 1 observation", async () => {
renderComponent(
<Header
<ObsEditHeader
observations={[mockObservations[1]]}
/>
);
@@ -35,7 +35,7 @@ describe( "Header", () => {
it( "renders a header title with multiple observations", async () => {
renderComponent(
<Header
<ObsEditHeader
observations={mockObservations}
/>
);
@@ -50,7 +50,7 @@ describe( "Header", () => {
_created_at: faker.date.past( )
} );
renderComponent(
<Header
<ObsEditHeader
currentObservation={observation}
observations={[observation]}
/>
@@ -63,7 +63,7 @@ describe( "Header", () => {
it( "renders a kebab menu", async () => {
renderComponent(
<Header
<ObsEditHeader
observations={mockObservations}
/>
);
@@ -73,18 +73,15 @@ describe( "Header", () => {
expect( kebabLabel ).toBeVisible();
} );
it( "renders a back button with extra padding for accessibility", () => {
it( "renders a back button", () => {
renderComponent(
<Header
<ObsEditHeader
observations={mockObservations}
/>
);
const backButtonId = screen.getByTestId( "ObsEdit.BackButton" );
expect( backButtonId ).toBeVisible();
expect(
backButtonId
).toHaveStyle( { paddingVertical: 18, paddingEnd: 24 } );
expect( backButtonId ).toBeVisible( );
} );
} );