diff --git a/dev-client/src/components/links/ExternalLink.tsx b/dev-client/src/components/links/ExternalLink.tsx index b6b2af408..002fa0943 100644 --- a/dev-client/src/components/links/ExternalLink.tsx +++ b/dev-client/src/components/links/ExternalLink.tsx @@ -15,7 +15,7 @@ * along with this program. If not, see https://www.gnu.org/licenses/. */ -import React from 'react'; +import React, {useCallback, useMemo} from 'react'; import {Linking, Pressable, StyleSheet, View} from 'react-native'; import {IconButton as NativeIconButton} from 'native-base'; @@ -26,6 +26,7 @@ import { Row, Text, } from 'terraso-mobile-client/components/NativeBaseAdapters'; +import {validateUrl} from 'terraso-mobile-client/util'; export type ExternalLinkProps = { label: string; @@ -34,27 +35,31 @@ export type ExternalLinkProps = { export const ExternalLink = React.forwardRef( ({label, url}: ExternalLinkProps, ref: React.Ref) => { - const icon = ( - } /> - ); + const isValidUrl = useMemo(() => validateUrl(url), [url]); + const openUrl = useCallback(() => Linking.openURL(url), [url]); return ( - - Linking.openURL(url)}> - - - - {label} - - {icon} - - - - + isValidUrl && ( + + + + + + {label} + + } + /> + + + + + ) ); }, ); diff --git a/dev-client/src/components/links/InternalLink.tsx b/dev-client/src/components/links/InternalLink.tsx index 674d7b826..07050c901 100644 --- a/dev-client/src/components/links/InternalLink.tsx +++ b/dev-client/src/components/links/InternalLink.tsx @@ -15,31 +15,32 @@ * along with this program. If not, see https://www.gnu.org/licenses/. */ -import {useCallback} from 'react'; +import {useCallback, useMemo} from 'react'; import {Linking} from 'react-native'; import {Link} from 'native-base'; import {InterfaceLinkProps} from 'native-base/lib/typescript/components/primitives/Link/types'; +import {validateUrl} from 'terraso-mobile-client/util'; + type InternalLinkProps = { label: string; onPress?: InterfaceLinkProps['onPress']; - url?: string; + url: string; }; export default function InternalLink({label, onPress, url}: InternalLinkProps) { - const openUrl = useCallback(() => { - if (url !== undefined) { - Linking.openURL(url); - } - }, [url]); + const isValidUrl = useMemo(() => validateUrl(url), [url]); + const openUrl = useCallback(() => Linking.openURL(url), [url]); return ( - - {label} - + isValidUrl && ( + + {label} + + ) ); } diff --git a/dev-client/src/screens/LocationScreens/components/soilInfo/SoilInfoDisplay.tsx b/dev-client/src/screens/LocationScreens/components/soilInfo/SoilInfoDisplay.tsx index 2e81a9efe..b88b48117 100644 --- a/dev-client/src/screens/LocationScreens/components/soilInfo/SoilInfoDisplay.tsx +++ b/dev-client/src/screens/LocationScreens/components/soilInfo/SoilInfoDisplay.tsx @@ -35,6 +35,7 @@ type SoilInfoDisplayProps = { export function SoilInfoDisplay({dataSource, soilInfo}: SoilInfoDisplayProps) { const {t} = useTranslation(); + return ( diff --git a/dev-client/src/util.ts b/dev-client/src/util.ts index e1e5afcfc..3b1dac914 100644 --- a/dev-client/src/util.ts +++ b/dev-client/src/util.ts @@ -164,3 +164,11 @@ export const isSiteManager = matchesRole([ export const getSoilWebUrl = (coords: Coords) => { return `https://casoilresource.lawr.ucdavis.edu/gmap/?loc=${coords.latitude},${coords.longitude}`; }; + +export const validateUrl = (url?: string): URL | false => { + try { + return url ? new URL(url) : false; + } catch { + return false; + } +};