From ed3f0e982cdfcd9eb15106a2f4a64506dea7ea59 Mon Sep 17 00:00:00 2001 From: Johannes Klein Date: Fri, 16 May 2025 14:57:25 +0200 Subject: [PATCH] Migrate SuggestionsResult to TypeScript (#2901) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 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 --- ...estionsResult.js => SuggestionsResult.tsx} | 17 +++++----- .../ObservationsFlashList/ObsImagePreview.tsx | 2 +- .../Buttons/PressableWithTracking.tsx | 31 ++++++++++--------- .../SharedComponents/DisplayTaxonName.tsx | 3 +- .../SharedComponents/ScientificName.tsx | 6 ++-- src/sharedHelpers/taxon.ts | 6 ++-- 6 files changed, 35 insertions(+), 30 deletions(-) rename src/components/Match/AdditionalSuggestions/{SuggestionsResult.js => SuggestionsResult.tsx} (90%) diff --git a/src/components/Match/AdditionalSuggestions/SuggestionsResult.js b/src/components/Match/AdditionalSuggestions/SuggestionsResult.tsx similarity index 90% rename from src/components/Match/AdditionalSuggestions/SuggestionsResult.js rename to src/components/Match/AdditionalSuggestions/SuggestionsResult.tsx index e7f62d8b5..68a4ca619 100644 --- a/src/components/Match/AdditionalSuggestions/SuggestionsResult.js +++ b/src/components/Match/AdditionalSuggestions/SuggestionsResult.tsx @@ -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} > { - const { onPress, ...otherProps } = props; +const PressableWithTracking = React.forwardRef( + ( 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 ; -} ); + // eslint-disable-next-line react/jsx-props-no-spreading + return ; + } +); export default PressableWithTracking; diff --git a/src/components/SharedComponents/DisplayTaxonName.tsx b/src/components/SharedComponents/DisplayTaxonName.tsx index d45175863..f7e8092ba 100644 --- a/src/components/SharedComponents/DisplayTaxonName.tsx +++ b/src/components/SharedComponents/DisplayTaxonName.tsx @@ -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; underlineTopText?: boolean; diff --git a/src/components/SharedComponents/ScientificName.tsx b/src/components/SharedComponents/ScientificName.tsx index ace9ab95a..45f5b1c1c 100644 --- a/src/components/SharedComponents/ScientificName.tsx +++ b/src/components/SharedComponents/ScientificName.tsx @@ -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 ) ); } diff --git a/src/sharedHelpers/taxon.ts b/src/sharedHelpers/taxon.ts index b11b3c6a4..bb0d7f9e0 100644 --- a/src/sharedHelpers/taxon.ts +++ b/src/sharedHelpers/taxon.ts @@ -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 );