mirror of
https://github.com/inaturalist/iNaturalistReactNative.git
synced 2026-05-19 05:47:33 -04:00
Migrate SuggestionsResult to TypeScript (#2901)
* Rename file * Use PressableProps interface for PressableWithTracking * Remove TODO * Update handleLayout types * Update allowed prop type If SuggestionsResult can have ApiTaxon | RealmTaxon, we have to enable it in DisplayTaxonName as well, and rank_level can be undefined according to this union. * Allow null accessibleTaxonName uses currentUser directly from useCurrentUser which can be null. * Use as to declare which type is used * Source might be null
This commit is contained in:
@@ -7,6 +7,7 @@ import {
|
||||
} from "components/SharedComponents";
|
||||
import { Pressable, View } from "components/styledComponents";
|
||||
import React, { useEffect, useRef } from "react";
|
||||
import type { LayoutChangeEvent } from "react-native";
|
||||
import type { RealmTaxon } from "realmModels/types";
|
||||
import { accessibleTaxonName } from "sharedHelpers/taxon.ts";
|
||||
import {
|
||||
@@ -18,7 +19,7 @@ type Props = {
|
||||
handlePress?: ( ) => void,
|
||||
taxon: RealmTaxon | ApiTaxon,
|
||||
testID?: string,
|
||||
updateMaxHeight?: ( ) => void,
|
||||
updateMaxHeight?: ( height: number ) => void,
|
||||
forcedHeight: number
|
||||
}
|
||||
|
||||
@@ -53,14 +54,15 @@ const SuggestionsResult = ( {
|
||||
// A representative photo is dependant on the actual image that was scored by computer vision
|
||||
// and is currently not added to the taxon realm. So, if it is available directly from the
|
||||
// suggestion, i.e. taxonProp, use it. Otherwise, use the default photo from the taxon.
|
||||
const taxonImage = {
|
||||
uri: taxon?.representative_photo?.url
|
||||
|| taxon?.default_photo?.url
|
||||
|| taxon?.defaultPhoto?.url
|
||||
};
|
||||
const uri = ( taxon as ApiTaxon )?.representative_photo?.url
|
||||
|| ( taxon as ApiTaxon )?.default_photo?.url
|
||||
|| ( taxon as RealmTaxon )?.defaultPhoto?.url;
|
||||
const taxonImage = uri
|
||||
? { uri }
|
||||
: undefined;
|
||||
|
||||
// Handle the onLayout event to measure item height
|
||||
const handleLayout = event => {
|
||||
const handleLayout = ( event: LayoutChangeEvent ) => {
|
||||
const { height } = event.nativeEvent.layout;
|
||||
// Only report height once to avoid infinite loops
|
||||
if ( updateMaxHeight && height > 0 && !measuredRef.current ) {
|
||||
@@ -104,7 +106,6 @@ const SuggestionsResult = ( {
|
||||
: undefined}
|
||||
>
|
||||
<ObsImagePreview
|
||||
// TODO fix when ObsImagePreview typed
|
||||
source={taxonImage}
|
||||
testID={`${testID}.photo`}
|
||||
iconicTaxonName={taxon?.iconic_taxon_name}
|
||||
@@ -25,7 +25,7 @@ interface Props extends PropsWithChildren {
|
||||
opaque?: boolean;
|
||||
selectable?: boolean;
|
||||
selected?: boolean;
|
||||
source: {
|
||||
source?: {
|
||||
uri: string;
|
||||
};
|
||||
style?: ViewStyle;
|
||||
|
||||
@@ -1,26 +1,29 @@
|
||||
import { getCurrentRoute } from "navigation/navigationUtils.ts";
|
||||
import React from "react";
|
||||
import type { PressableProps } from "react-native";
|
||||
import { GestureResponderEvent, Pressable } from "react-native";
|
||||
import { log } from "sharedHelpers/logger";
|
||||
|
||||
const logger = log.extend( "PressableWithTracking" );
|
||||
|
||||
const PressableWithTracking = React.forwardRef( ( props, ref ) => {
|
||||
const { onPress, ...otherProps } = props;
|
||||
const PressableWithTracking = React.forwardRef<typeof Pressable, PressableProps>(
|
||||
( props, ref ) => {
|
||||
const { onPress, ...otherProps } = props;
|
||||
|
||||
const handlePressWithTracking = ( event?: GestureResponderEvent ) => {
|
||||
if ( otherProps?.testID ) {
|
||||
const currentRoute = getCurrentRoute( );
|
||||
logger.info( `Button tap: ${otherProps?.testID}-${currentRoute?.name || "undefined"}` );
|
||||
}
|
||||
const handlePressWithTracking = ( event: GestureResponderEvent ) => {
|
||||
if ( otherProps?.testID ) {
|
||||
const currentRoute = getCurrentRoute( );
|
||||
logger.info( `Button tap: ${otherProps?.testID}-${currentRoute?.name || "undefined"}` );
|
||||
}
|
||||
|
||||
if ( onPress ) {
|
||||
onPress( event );
|
||||
}
|
||||
};
|
||||
if ( onPress ) {
|
||||
onPress( event );
|
||||
}
|
||||
};
|
||||
|
||||
// eslint-disable-next-line react/jsx-props-no-spreading
|
||||
return <Pressable {...otherProps} onPress={handlePressWithTracking} ref={ref} />;
|
||||
} );
|
||||
// eslint-disable-next-line react/jsx-props-no-spreading
|
||||
return <Pressable {...otherProps} onPress={handlePressWithTracking} ref={ref} />;
|
||||
}
|
||||
);
|
||||
|
||||
export default PressableWithTracking;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import type { ApiTaxon } from "api/types";
|
||||
import classnames from "classnames";
|
||||
import {
|
||||
Body1, Body3, Body4
|
||||
@@ -33,7 +34,7 @@ interface Props {
|
||||
showOneNameOnly?: boolean;
|
||||
selectable?: boolean;
|
||||
small?: boolean;
|
||||
taxon: RealmTaxon;
|
||||
taxon: RealmTaxon | ApiTaxon;
|
||||
textCentered?: boolean;
|
||||
topTextComponent?: React.ComponentType<TextProps>;
|
||||
underlineTopText?: boolean;
|
||||
|
||||
@@ -14,7 +14,7 @@ interface Props {
|
||||
isTitle?: boolean;
|
||||
keyBase: string;
|
||||
rank?: string;
|
||||
rankLevel: number;
|
||||
rankLevel?: number;
|
||||
rankPiece?: string;
|
||||
scientificNamePieces?: string[];
|
||||
taxonId: string | number;
|
||||
@@ -38,7 +38,7 @@ const ScientificName = ( {
|
||||
}: Props ) => {
|
||||
const { t } = useTranslation( );
|
||||
const scientificNameArray = scientificNamePieces?.map( ( piece, index ) => {
|
||||
const isItalics = piece !== rankPiece && (
|
||||
const isItalics = piece !== rankPiece && rankLevel && (
|
||||
rankLevel <= Taxon.SPECIES_LEVEL || rankLevel === Taxon.GENUS_LEVEL
|
||||
);
|
||||
const spaceChar = ( ( index !== scientificNamePieces.length - 1 ) || isHorizontal )
|
||||
@@ -67,7 +67,7 @@ const ScientificName = ( {
|
||||
);
|
||||
} );
|
||||
|
||||
if ( rank && rankLevel > Taxon.SPECIES_LEVEL ) {
|
||||
if ( rank && rankLevel && rankLevel > Taxon.SPECIES_LEVEL ) {
|
||||
scientificNameArray.unshift( " " );
|
||||
scientificNameArray.unshift( translatedRank( rank, t ) );
|
||||
}
|
||||
|
||||
@@ -99,14 +99,14 @@ export const capitalizeCommonName = ( name: string ) => {
|
||||
|
||||
interface Taxon {
|
||||
rank?: string;
|
||||
rank_level: number;
|
||||
rank_level?: number;
|
||||
preferred_common_name?: string;
|
||||
name?: string;
|
||||
}
|
||||
|
||||
interface TaxonDisplayData {
|
||||
rank?: string;
|
||||
rankLevel: number;
|
||||
rankLevel?: number;
|
||||
commonName?: string;
|
||||
rankPiece?: string;
|
||||
scientificNamePieces?: string[];
|
||||
@@ -160,7 +160,7 @@ interface User {
|
||||
}
|
||||
export function accessibleTaxonName(
|
||||
taxon: Taxon,
|
||||
user: User,
|
||||
user: User | null,
|
||||
t: ( key: string, options: {} ) => string
|
||||
) {
|
||||
const { commonName, scientificName } = generateTaxonPieces( taxon );
|
||||
|
||||
Reference in New Issue
Block a user