Skip to content

Commit

Permalink
chore(refactoring): refactoring some code (#33)
Browse files Browse the repository at this point in the history
- bump deps
- handle unmatched route
- refactoring domain route
- handle domain deeplink
- handle domain errors (400 and 404)
  • Loading branch information
bpouzet authored Mar 10, 2023
1 parent 8a4dd21 commit cc37e35
Show file tree
Hide file tree
Showing 13 changed files with 372 additions and 174 deletions.
10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "nc-domain-finder",
"version": "1.0.1",
"version": "1.1.0",
"main": "index.js",
"scripts": {
"start": "npx expo start --dev-client",
Expand Down Expand Up @@ -41,19 +41,19 @@
"@react-navigation/material-bottom-tabs": "^6.2.13",
"@react-navigation/native": "^6.1.4",
"@react-navigation/native-stack": "^6.9.10",
"@sentry/react-native": "~4.9.0",
"@sentry/react-native": "4.13.0",
"@shopify/flash-list": "1.4.0",
"@tanstack/query-async-storage-persister": "^4.24.6",
"@tanstack/react-query": "^4.24.6",
"@tanstack/react-query-persist-client": "^4.24.6",
"axios": "^1.3.3",
"expo": "~48.0.4",
"expo": "~48.0.5",
"expo-application": "~5.1.1",
"expo-build-properties": "~0.5.1",
"expo-calendar": "~11.1.1",
"expo-community-add-event-to-calendar": "^0.9.0",
"expo-constants": "~14.2.1",
"expo-dev-client": "~2.1.3",
"expo-dev-client": "~2.1.5",
"expo-device": "~5.2.1",
"expo-font": "~11.1.1",
"expo-image": "~1.0.0",
Expand Down Expand Up @@ -82,7 +82,7 @@
"react-native-shimmer-placeholder": "^2.0.9",
"react-native-store-version": "^1.4.0",
"semver": "^7.3.8",
"sentry-expo": "~6.0.0",
"sentry-expo": "~6.1.0",
"sp-react-native-in-app-updates": "^1.3.1",
"zod": "^3.20.6",
"zustand": "^4.3.3"
Expand Down
4 changes: 2 additions & 2 deletions src/app/(root)/favorites.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ export default function Favorites() {

const onPress = (item: DomainList) => () => router.push({
params: {
domain: item.name,
extension: item.extension,
name: item.name,
},
pathname: 'domain/:name',
pathname: 'domain',
}) ;

const renderItem: ListRenderItem<DomainList> = useCallback(({ item }) => (
Expand Down
4 changes: 2 additions & 2 deletions src/app/(root)/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ export default function Index () {

const onPress = (item: DomainList) => () => router.push({
params: {
domain: item.name,
extension: item.extension,
name: item.name,
},
pathname: 'domain/:name',
pathname: 'domain',
}) ;

const renderItem: ListRenderItem<DomainList> = useCallback(({ item }) => (
Expand Down
16 changes: 16 additions & 0 deletions src/app/[...unmatched].tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { useTranslation } from 'react-i18next' ;

import ErrorView from '@components/views/ErrorView' ;

export default function Unmatched() {

const { t } = useTranslation() ;

return (
<ErrorView
description={t('unmatched.description')}
icon='routes'
title={t('unmatched.title')}
/>
) ;
}
140 changes: 98 additions & 42 deletions src/app/domain/[name].tsx → src/app/domain/index.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
import * as Calendar from 'expo-calendar' ;
import * as Linking from 'expo-linking' ;
import Animated, { useAnimatedStyle, useSharedValue, withTiming } from 'react-native-reanimated' ;
import { Appbar, FAB, List, Snackbar, useTheme } from 'react-native-paper' ;
import { Platform, ScrollView, StyleSheet, View, useWindowDimensions } from 'react-native' ;
import { useRouter, useSearchParams } from 'expo-router' ;
import { AxiosError } from 'axios' ;
import { DateTime } from 'luxon' ;
import { startAddEventToCalendarAsync } from 'expo-community-add-event-to-calendar' ;
import { useSafeAreaInsets } from 'react-native-safe-area-context' ;
import { useState } from 'react' ;
import { useTranslation } from 'react-i18next' ;

import { DomainList } from '../../schemas/DomainListSchema' ;
import ErrorView from '@components/views/ErrorView' ;
import LoaderImage from '@components/LoaderImage' ;
import LoaderItems from '@components/LoaderItems' ;
import getFavicon from '@helpers/favicon' ;
Expand All @@ -29,25 +32,39 @@ const options = {
year: 'numeric',
} ;

export default function Name() {
export default function Domain() {
const { t } = useTranslation() ;
const theme = useTheme() ;
const router = useRouter() ;

const { name, extension } = useSearchParams() ;
const { domain, extension } = useSearchParams() ;

const { bottom, top } = useSafeAreaInsets() ;
const { height } = useWindowDimensions() ;

const { data, isLoading } = useDomain(name, extension) ;
const sharedVal = useSharedValue(BOTTOM_APPBAR_HEIGHT + bottom) ;

const animatedStyles = useAnimatedStyle(() => {
return {
transform: [ { translateY: withTiming(sharedVal.value, { duration: 500 }) } ],
} ;
}) ;

const { data, isLoading, error } = useDomain(domain, extension) ;

if(error && error instanceof AxiosError) console.log('error => ', error) ;

if( data ) {
sharedVal.value = 0 ;
}

const [ showSnackBar, setShowSnackBar ] = useState<boolean>(false) ;

const { addFavorite, isFavorite, removeFavorite } = useFavoritesStore() ;

const header = (40 / 100) * height ;

const isItemFavorite = isFavorite({ extension, name }) ;
const isItemFavorite = isFavorite({ extension, name: domain }) ;

const getDate = (date: string) => t('date', {
formatParams: { val: options },
Expand All @@ -73,7 +90,7 @@ export default function Name() {
if(!data) return ;

const timeZone = 'Pacific/Noumea' ;
const eventTitle = t('reminder.title', { val: name + extension }) ;
const eventTitle = t('reminder.title', { val: domain + extension }) ;

let endDate = DateTime.fromISO(data.dateExpiration, { zone: timeZone }) ;
endDate = endDate.plus({ hours: 23, minutes: 59 }) ;
Expand Down Expand Up @@ -121,12 +138,12 @@ export default function Name() {
}
} ;

const onCheckDNS = () => void Linking.openURL(CHECK_DNS_URL + name + extension) ;
const onCheckDNS = () => void Linking.openURL(CHECK_DNS_URL + domain + extension) ;

const onOpenWebsite = () => void Linking.openURL('http://' + name + extension) ;
const onOpenWebsite = () => void Linking.openURL('http://' + domain + extension) ;

const onChangeFavorite = () => {
const fav: DomainList = { extension, name } ;
const fav: DomainList = { extension, name: domain } ;
if(isFavorite(fav)) {
removeFavorite(fav) ;
} else {
Expand Down Expand Up @@ -164,6 +181,39 @@ export default function Name() {
}
} ;

if( !domain || !extension ) {
return (
<ErrorView
description={t('domain.missing.description', { val: (domain + extension) })}
icon='alert'
title={t('domain.missing.title')}
/>
) ;
} else if( error && error instanceof AxiosError ) {

// default
let errorTitle = t('domain.error.title') ;
let errorDescription = t('domain.error.title') ;

if( error.response ) {
if( error.response.status === 404 ) {
errorTitle = t('domain.notFound.title') ;
errorDescription = t('domain.notFound.description', { val: (domain + extension) }) ;
} else {
errorTitle = t('domain.badRequest.title') ;
errorDescription = t('domain.badRequest.description', { val: (domain + extension) }) ;
}
}

return (
<ErrorView
description={errorDescription}
icon='alert'
title={errorTitle}
/>
) ;
}

return (
<>
<View style={{ backgroundColor: theme.colors.background, flex: 1 }}>
Expand All @@ -176,7 +226,7 @@ export default function Name() {
}}
>
<LoaderImage
source={{ uri: THUMB_URL + name + extension }}
source={{ uri: THUMB_URL + domain + extension }}
style={{
borderBottomLeftRadius: 20,
borderBottomRightRadius: 20,
Expand All @@ -198,9 +248,9 @@ export default function Name() {
</View>

<List.Item
title={name}
title={domain}
description={extension}
left={getFavicon(name, extension)}
left={getFavicon(domain, extension)}
/>

{renderContent()}
Expand All @@ -212,50 +262,56 @@ export default function Name() {
style={{ bottom: BOTTOM_APPBAR_HEIGHT }}
>{t('reminder.added')}</Snackbar>

<Appbar
<Animated.View
style={[
styles.bottom,
{
backgroundColor: theme.colors.elevation.level2,
height: BOTTOM_APPBAR_HEIGHT + bottom,
paddingBottom: bottom,
},
animatedStyles,
]}
safeAreaInsets={{ bottom }}
>
<Appbar.Action
accessibilityLabel={t('actions.openWebsite')}
icon="open-in-new"
onPress={onOpenWebsite}
/>
<Appbar.Action
accessibilityLabel={t('actions.checkDNS')}
icon="dns"
onPress={onCheckDNS}
/>
<Appbar.Action
accessibilityLabel={t('actions.addReminder')}
icon="bell-outline"
onPress={onAddReminder}
/>
<FAB
accessibilityLabel={isItemFavorite ? t('actions.removeFavorite') : t('actions.addFavorite')}
mode="flat"
size="medium"
icon={isItemFavorite ? 'heart' : 'heart-outline'}
onPress={onChangeFavorite}
style={[
styles.fab,
{ top: (BOTTOM_APPBAR_HEIGHT - MEDIUM_FAB_HEIGHT) / 2 },
]}
/>
</Appbar>
<Appbar
style={{
backgroundColor: theme.colors.elevation.level2,
height: BOTTOM_APPBAR_HEIGHT,
}}
>
<Appbar.Action
accessibilityLabel={t('actions.openWebsite')}
icon="open-in-new"
onPress={onOpenWebsite}
/>
<Appbar.Action
accessibilityLabel={t('actions.checkDNS')}
icon="dns"
onPress={onCheckDNS}
/>
<Appbar.Action
accessibilityLabel={t('actions.addReminder')}
icon="bell-outline"
onPress={onAddReminder}
/>
<FAB
accessibilityLabel={isItemFavorite ? t('actions.removeFavorite') : t('actions.addFavorite')}
mode="flat"
size="medium"
icon={isItemFavorite ? 'heart' : 'heart-outline'}
onPress={onChangeFavorite}
style={[
styles.fab,
{ top: (BOTTOM_APPBAR_HEIGHT - MEDIUM_FAB_HEIGHT) / 2 },
]}
/>
</Appbar>
</Animated.View>
</>
) ;
}

const styles = StyleSheet.create({
bottom: {
backgroundColor: 'aquamarine',
bottom: 0,
left: 0,
position: 'absolute',
Expand Down
27 changes: 23 additions & 4 deletions src/components/ErrorAppBoundary.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,40 @@
import * as Sentry from 'sentry-expo' ;
import { Button, Text } from 'react-native-paper' ;
import { Avatar, Button, Text, useTheme } from 'react-native-paper' ;
import { FC, useEffect } from 'react' ;
import { ErrorBoundaryProps } from 'expo-router' ;
import { View } from 'react-native' ;
import { useTranslation } from 'react-i18next' ;

import SafeView from '@components/SafeView' ;

const ErrorAppBoundary: FC<ErrorBoundaryProps> = ({ error, retry }) => {

const theme = useTheme() ;
const { t } = useTranslation() ;

useEffect(() => {
Sentry.Native.captureException(error) ;
}, [ error ]) ;

return (
<SafeView>
<Text>{error.message}</Text>
{/* eslint-disable-next-line @typescript-eslint/no-misused-promises */}
<Button onPress={retry}>Try Again?</Button>
<View
style={{
alignItems: 'center',
flex: 1,
gap: 10,
justifyContent: 'center',
}}
>
<Avatar.Icon
icon='bug'
style={{ backgroundColor: theme.colors.error }}
/>
<Text variant='headlineLarge'>{t('errorBoundary.title')}</Text>
<Text>{error.message}</Text>
{/* eslint-disable-next-line @typescript-eslint/no-misused-promises */}
<Button onPress={retry}>{t('actions.tryAgain')}</Button>
</View>
</SafeView>
) ;
} ;
Expand Down
Loading

0 comments on commit cc37e35

Please sign in to comment.