diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index f200221..f6f0561 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -39,6 +39,8 @@ + + diff --git a/src/components/firmware/FirmwareListItem.tsx b/src/components/firmware/FirmwareListItem.tsx index be03485..80d2549 100644 --- a/src/components/firmware/FirmwareListItem.tsx +++ b/src/components/firmware/FirmwareListItem.tsx @@ -2,6 +2,7 @@ import type { FC } from 'react'; import { useCallback, useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import { Badge, Divider, List, Text, useTheme } from 'react-native-paper'; +import Toast from 'react-native-toast-message'; import { Linking, View } from 'react-native'; @@ -18,6 +19,7 @@ import useDtuState from '@/hooks/useDtuState'; import useHasAuthConfigured from '@/hooks/useHasAuthConfigured'; import capitalize from '@/utils/capitalize'; +import { rootLogging } from '@/utils/log'; import { minimumOpenDtuFirmwareVersion, spacing } from '@/constants'; import type { SupportedLanguage } from '@/translations'; @@ -35,6 +37,8 @@ const needsCapitalization: Record = { de: true, }; +const log = rootLogging.extend('FirmwareListItem'); + const FirmwareListItem: FC = ({ release, selectRelease, @@ -53,8 +57,14 @@ const FirmwareListItem: FC = ({ if (await Linking.canOpenURL(url)) { await Linking.openURL(url); + } else { + log.error(`Cannot open URL: ${url}`); + Toast.show({ + type: 'error', + text1: t('cannotOpenUrl'), + }); } - }, [release.html_url]); + }, [release.html_url, t]); const handleInstallFirmware = useCallback(() => { selectRelease(release); diff --git a/src/components/modals/ChangeLanguageModal.tsx b/src/components/modals/ChangeLanguageModal.tsx index 7446975..f12cfde 100644 --- a/src/components/modals/ChangeLanguageModal.tsx +++ b/src/components/modals/ChangeLanguageModal.tsx @@ -10,6 +10,7 @@ import { Text, useTheme, } from 'react-native-paper'; +import Toast from 'react-native-toast-message'; import { Linking } from 'react-native'; @@ -53,10 +54,13 @@ const ChangeLanguageModal: FC> = props => { if (await Linking.canOpenURL(weblateUrl)) { await Linking.openURL(weblateUrl); } else { - // TODO: Better error handling (issue #101) log.error('Cannot open Weblate URL'); + Toast.show({ + type: 'error', + text1: t('cannotOpenUrl'), + }); } - }, []); + }, [t]); return ( diff --git a/src/translations b/src/translations index 730dabd..fe5fb1e 160000 --- a/src/translations +++ b/src/translations @@ -1 +1 @@ -Subproject commit 730dabd97144a8616226258cc3309401003c3847 +Subproject commit fe5fb1e82a6f7cc2f861629935174212df81dfa9 diff --git a/src/views/navigation/screens/InformationGroup/LicensesScreen.tsx b/src/views/navigation/screens/InformationGroup/LicensesScreen.tsx index 31d7b06..1902d4b 100644 --- a/src/views/navigation/screens/InformationGroup/LicensesScreen.tsx +++ b/src/views/navigation/screens/InformationGroup/LicensesScreen.tsx @@ -2,17 +2,22 @@ import type { FC } from 'react'; import { useTranslation } from 'react-i18next'; import { Box } from 'react-native-flex-layout'; import { Appbar, List, useTheme } from 'react-native-paper'; +import Toast from 'react-native-toast-message'; import { Linking, ScrollView, View } from 'react-native'; import type { Licenses } from 'npm-license-crawler'; +import { rootLogging } from '@/utils/log'; + import { spacing } from '@/constants'; import { StyledView } from '@/style'; import type { PropsWithNavigation } from '@/views/navigation/NavigationStack'; import licenses from '@root/licenses.json'; +const log = rootLogging.extend('LicensesScreen'); + const LicensesScreen: FC = ({ navigation }) => { const { t } = useTranslation(); const theme = useTheme(); @@ -41,6 +46,12 @@ const LicensesScreen: FC = ({ navigation }) => { const url = repository || licenseUrl; if (await Linking.canOpenURL(url)) { await Linking.openURL(url); + } else { + log.error(`Cannot open URL: ${url}`); + Toast.show({ + type: 'error', + text1: t('cannotOpenUrl'), + }); } } : undefined diff --git a/src/views/navigation/screens/InformationGroup/SystemInformationScreen.tsx b/src/views/navigation/screens/InformationGroup/SystemInformationScreen.tsx index 75b478d..32a983b 100644 --- a/src/views/navigation/screens/InformationGroup/SystemInformationScreen.tsx +++ b/src/views/navigation/screens/InformationGroup/SystemInformationScreen.tsx @@ -3,6 +3,7 @@ import { useCallback, useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import { Box } from 'react-native-flex-layout'; import { Appbar, Badge, List, Switch, useTheme } from 'react-native-paper'; +import Toast from 'react-native-toast-message'; import { Linking, ScrollView, View } from 'react-native'; @@ -20,6 +21,7 @@ import useHasNewOpenDtuVersion from '@/hooks/useHasNewOpenDtuVersion'; import correctTag from '@/utils/correctTag'; import formatBytes from '@/utils/formatBytes'; +import { rootLogging } from '@/utils/log'; import percentage from '@/utils/percentage'; import { colors, spacing } from '@/constants'; @@ -27,6 +29,8 @@ import { useAppDispatch, useAppSelector } from '@/store'; import { StyledView } from '@/style'; import type { PropsWithNavigation } from '@/views/navigation/NavigationStack'; +const log = rootLogging.extend('SystemInformationScreen'); + const SystemInformationScreen: FC = ({ navigation }) => { const theme = useTheme(); const { t } = useTranslation(); @@ -62,8 +66,14 @@ const SystemInformationScreen: FC = ({ navigation }) => { if (await Linking.canOpenURL(url)) { await Linking.openURL(url); + } else { + log.error(`Cannot open URL: ${url}`); + Toast.show({ + type: 'error', + text1: t('cannotOpenUrl'), + }); } - }, [systemStatus]); + }, [systemStatus, t]); const versionString = useMemo(() => { if (!latestVersion || !systemStatus?.git_hash)