Skip to content

Commit

Permalink
feat: Remove ErrorView and navigate to new ErrorScreen instead
Browse files Browse the repository at this point in the history
Current ErrorView implementation doesn't contains any design so the
displayed error is very raw and is not user friendly

We want to improve this UI but instead of modifying the ErrorView we
replace it by the new generic error page from ErrorScreen. This would
improve code homogeneity

Also we now use the `navigateToError` function to analyse the error
object and chose which error to display
  • Loading branch information
Ldoppea committed Jul 18, 2023
1 parent 815442e commit 8360d04
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 140 deletions.
2 changes: 1 addition & 1 deletion src/app/domain/errors/makeHtmlErrorPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ export const makeHtmlErrorPage = ({
const showDetailsButton = document.getElementById('showDetails')
if (showDetailsButton) {
showDetailsButton.onclick = (e) => {
window.alert(\`${errorDetails}\`)
window.alert(\`${errorDetails ?? 'no details'}\`)
}
}
})
Expand Down
73 changes: 73 additions & 0 deletions src/app/domain/errors/navigateToError.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import strings from '/constants/strings.json'
import { routes } from '/constants/routes'
import { navigate } from '/libs/RootNavigation'
import { isFetchError } from '/libs/clientHelpers/types'

/**
* Navigate to the Error page corresponding to the given error
*
* If no dedicated Error page is found for the given error, then
* retidrect to Generic Error page
*/
export const navigateToError = (
errorMessage: string,
error: Error,
backgroundColor: string
): void => {
if (isErrorAboutNotOnboardedCozy(error)) {
navigate(routes.error, {
type: strings.errorScreens.cozyNotOnboarded,
backgroundColor
})
return
}

if (isErrorAboutBlockedCozy(error)) {
navigate(routes.error, {
type: strings.errorScreens.cozyBlocked,
backgroundColor
})
return
}

navigate(routes.error, {
type: strings.errorScreens.genericError,
backgroundColor,
error: {
message: errorMessage,
details: JSON.stringify(error, null, ' ')
}
})
}

const isErrorAboutNotOnboardedCozy = (error: unknown): boolean => {
if (!isFetchError(error)) {
return false
}

return (
error.status === 412 &&
!Array.isArray(error.reason) &&
typeof error.reason !== 'string' &&
error.reason?.error === 'the instance has not been onboarded'
)
}

const isErrorAboutBlockedCozy = (error: unknown): boolean => {
if (!isFetchError(error)) {
return false
}

return (
error.status === 503 &&
Array.isArray(error.reason) &&
error.reason.some(
reason =>
typeof reason === 'object' &&
reason !== null &&
'title' in reason &&
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
reason.title === 'Blocked'
)
)
}
11 changes: 7 additions & 4 deletions src/libs/clientHelpers/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,13 @@ interface FetchError extends Error {
response: string
url: string
status: number
reason?: {
two_factor_token?: string
error?: string
}
reason?:
| string
| unknown[]
| {
two_factor_token?: string
error?: string
}
}

export const isFetchError = (error: unknown): error is FetchError => {
Expand Down
27 changes: 3 additions & 24 deletions src/screens/login/LoginScreen.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ import { BackHandler, StyleSheet, View } from 'react-native'
import Minilog from '@cozy/minilog'

import { ClouderyView } from './components/ClouderyView'
import { ErrorView } from './components/ErrorView'
import { OidcOnboardingView } from './components/OidcOnboardingView'
import { PasswordView } from './components/PasswordView'
import { TransitionToPasswordView } from './components/transitions/TransitionToPasswordView'
import { TransitionToAuthorizeView } from './components/transitions/TransitionToAuthorizeView'
import { TwoFactorAuthenticationView } from './components/TwoFactorAuthenticationView'

import { navigateToError } from '/app/domain/errors/navigateToError'
import {
callInitClient,
call2FAInitClient,
Expand Down Expand Up @@ -46,7 +46,6 @@ const TWO_FACTOR_AUTHENTICATION_STEP = 'TWO_FACTOR_AUTHENTICATION_STEP'
const TWO_FACTOR_AUTHENTICATION_PASSWORD_STEP =
'TWO_FACTOR_AUTHENTICATION_PASSWORD_STEP'
const AUTHORIZE_TRANSITION_STEP = 'AUTHORIZE_TRANSITION_STEP'
const ERROR_STEP = 'ERROR_STEP'

const OAUTH_USER_CANCELED_ERROR = 'USER_CANCELED'

Expand Down Expand Up @@ -492,15 +491,9 @@ const LoginSteps = ({

const setError = useCallback(
(errorMessage, error) => {
setState(oldState => ({
...oldState,
step: ERROR_STEP,
errorMessage: errorMessage,
error: error,
previousStep: state.step
}))
navigateToError(errorMessage, error, clouderyTheme.backgroundColor)
},
[state]
[clouderyTheme]
)

const startTransitionToPassword = avatarPosition => {
Expand Down Expand Up @@ -649,20 +642,6 @@ const LoginSteps = ({
if (state.step === LOADING_STEP) {
return null
}

if (state.step === ERROR_STEP) {
return (
<ErrorView
errorMessage={state.errorMessage}
error={state.error}
button={{
callback: cancelLogin,
title: 'Restart login'
}}
backgroundColor={clouderyTheme.backgroundColor}
/>
)
}
}

export const LoginScreen = ({
Expand Down
33 changes: 3 additions & 30 deletions src/screens/login/OnboardingScreen.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import React, { useCallback, useEffect, useState } from 'react'
import { StyleSheet, View } from 'react-native'

import { ErrorView } from './components/ErrorView'
import { OnboardingPasswordView } from './components/OnboardingPasswordView'

import Minilog from '@cozy/minilog'

import { navigateToError } from '/app/domain/errors/navigateToError'
import {
callMagicLinkOnboardingInitClient,
callOnboardingInitClient
Expand All @@ -26,7 +26,6 @@ Minilog.enable()
const LOADING_STEP = 'LOADING_STEP'
const PASSWORD_STEP = 'PASSWORD_STEP'
const MAGIC_LINK_STEP = 'MAGIC_LINK_STEP'
const ERROR_STEP = 'ERROR_STEP'

const OAUTH_USER_CANCELED_ERROR = 'USER_CANCELED'

Expand Down Expand Up @@ -143,27 +142,15 @@ const OnboardingSteps = ({
})
}

const cancelLogin = () => {
setState({
step: LOADING_STEP
})
}

const cancelOnboarding = useCallback(() => {
navigation.navigate(routes.authenticate)
}, [navigation])

const setError = useCallback(
(errorMessage, error) => {
setState({
...state,
step: ERROR_STEP,
errorMessage: errorMessage,
error: error,
previousStep: state.step
})
navigateToError(errorMessage, error, clouderyTheme.backgroundColor)
},
[state]
[clouderyTheme]
)

const startOAuth = useCallback(async () => {
Expand Down Expand Up @@ -229,20 +216,6 @@ const OnboardingSteps = ({
if (state.step === LOADING_STEP || state.step === MAGIC_LINK_STEP) {
return <CozyLogoScreen backgroundColor={clouderyTheme.backgroundColor} />
}

if (state.step === ERROR_STEP) {
return (
<ErrorView
errorMessage={state.errorMessage}
error={state.error}
button={{
callback: cancelLogin,
title: 'Cancel OAuth'
}}
backgroundColor={clouderyTheme.backgroundColor}
/>
)
}
}

export const OnboardingScreen = ({ setClient, route, navigation }) => {
Expand Down
71 changes: 0 additions & 71 deletions src/screens/login/components/ErrorView.js

This file was deleted.

10 changes: 0 additions & 10 deletions src/screens/login/components/ErrorView.styles.js

This file was deleted.

0 comments on commit 8360d04

Please sign in to comment.