diff --git a/apps/native/app/src/messages/en.ts b/apps/native/app/src/messages/en.ts index fb99a50f24e9..a9532c767412 100644 --- a/apps/native/app/src/messages/en.ts +++ b/apps/native/app/src/messages/en.ts @@ -270,6 +270,8 @@ export const en: TranslatedMessages = { 'walletPass.barcodeErrorNotConnected': 'Not possible to scan barcode if the device is not connected to the internet.', 'walletPass.barcodeErrorFailedToFetch': 'Could not fetch barcode', + 'walletPass.barcodeErrorBadSession': + 'Too little time since license was accessed on another device', 'walletPass.validLicense': 'Valid', 'walletPass.expiredLicense': 'Expired', 'walletPass.passportNumber': 'Passport number: {licenseNumber}', diff --git a/apps/native/app/src/messages/is.ts b/apps/native/app/src/messages/is.ts index 85f6c6f64af1..a54817ba64b0 100644 --- a/apps/native/app/src/messages/is.ts +++ b/apps/native/app/src/messages/is.ts @@ -406,6 +406,8 @@ export const is = { 'walletPass.barcodeErrorNotConnected': 'Ekki er hægt að skanna skírteini nema að tækið sé nettengt.', 'walletPass.barcodeErrorFailedToFetch': 'Ekki tókst að sækja barkóða', + 'walletPass.barcodeErrorBadSession': + 'Of stutt síðan skírteini var sótt á öðru tæki', 'walletPass.validLicense': 'Í gildi', 'walletPass.expiredLicense': 'Útrunnið', 'walletPass.passportNumber': 'Númer vegabréfs: {licenseNumber}', diff --git a/apps/native/app/src/screens/wallet-pass/wallet-pass.tsx b/apps/native/app/src/screens/wallet-pass/wallet-pass.tsx index 15b2865e52a1..f1ab7762242a 100644 --- a/apps/native/app/src/screens/wallet-pass/wallet-pass.tsx +++ b/apps/native/app/src/screens/wallet-pass/wallet-pass.tsx @@ -401,7 +401,7 @@ export const WalletPassScreen: NavigationFunctionComponent<{ type={licenseType} title={data?.payload?.metadata?.name ?? undefined} loading={res.loading} - error={!!res.error} + error={res.error} logo={ isBarcodeEnabled && data?.license?.type === GenericLicenseType.DriversLicense diff --git a/apps/native/app/src/ui/lib/card/license-card.tsx b/apps/native/app/src/ui/lib/card/license-card.tsx index 878a828c4e40..ef95e2d24654 100644 --- a/apps/native/app/src/ui/lib/card/license-card.tsx +++ b/apps/native/app/src/ui/lib/card/license-card.tsx @@ -8,6 +8,7 @@ import { ViewStyle, } from 'react-native' import styled, { useTheme } from 'styled-components/native' +import { ApolloError } from '@apollo/client' import { Barcode } from '../barcode/barcode' import { Skeleton } from '../skeleton/skeleton' @@ -22,6 +23,10 @@ import { dynamicColor } from '../../utils/dynamic-color' import { Typography } from '../typography/typography' import { screenWidth } from '../../../utils/dimensions' import { BARCODE_MAX_WIDTH } from '../../../screens/wallet-pass/wallet-pass.constants' +import { + findProblemInApolloError, + ProblemType, +} from '@island.is/shared/problem' const Host = styled(Animated.View)` position: relative; @@ -123,7 +128,7 @@ interface LicenseCardProps { backgroundColor?: string showBarcodeOfflineMessage?: boolean loading?: boolean - error?: boolean + error?: ApolloError barcode?: { value?: string | null loading?: boolean @@ -166,6 +171,10 @@ export function LicenseCard({ : screenWidth - theme.spacing[4] * 2 - theme.spacing.smallGutter * 2 const barcodeHeight = barcodeWidth / 3 + const badSessionError = error + ? findProblemInApolloError(error as any, [ProblemType.BAD_SESSION]) + : undefined + return ( {intl.formatMessage({ id: error - ? 'walletPass.barcodeErrorFailedToFetch' + ? badSessionError + ? 'walletPass.barcodeErrorBadSession' + : 'walletPass.barcodeErrorFailedToFetch' : 'walletPass.barcodeErrorNotConnected', })} diff --git a/libs/shared/problem/src/utils/findProblemInApolloError.spec.ts b/libs/shared/problem/src/utils/findProblemInApolloError.spec.ts index 507c7bcd97d6..44f4affe9b99 100644 --- a/libs/shared/problem/src/utils/findProblemInApolloError.spec.ts +++ b/libs/shared/problem/src/utils/findProblemInApolloError.spec.ts @@ -74,6 +74,32 @@ describe('findProblemInApolloError', () => { expect(problem).toMatchObject({ type: ProblemType.HTTP_NOT_FOUND }) }) + it('return first problem matching types when problem is nested in exception object', () => { + // Arrange + const error = new ApolloError({ + graphQLErrors: [ + new GraphQLError('Error', null, null, null, null, null, { + exception: { + problem: { type: ProblemType.HTTP_BAD_REQUEST }, + }, + }), + new GraphQLError('Error', null, null, null, null, null, { + exception: { + problem: { type: ProblemType.HTTP_NOT_FOUND }, + }, + }), + ], + }) + + // Act + const problem = findProblemInApolloError(error, [ + ProblemType.HTTP_NOT_FOUND, + ]) + + // Assert + expect(problem).toMatchObject({ type: ProblemType.HTTP_NOT_FOUND }) + }) + it('return undefined if no problem matches types', () => { // Arrange const error = new ApolloError({ @@ -81,6 +107,11 @@ describe('findProblemInApolloError', () => { new GraphQLError('Error', null, null, null, null, null, { problem: { type: ProblemType.HTTP_BAD_REQUEST }, }), + new GraphQLError('Error', null, null, null, null, null, { + exception: { + problem: { type: ProblemType.HTTP_BAD_REQUEST }, + }, + }), ], }) diff --git a/libs/shared/problem/src/utils/findProblemInApolloError.ts b/libs/shared/problem/src/utils/findProblemInApolloError.ts index 17fd6106c335..997f3fa16460 100644 --- a/libs/shared/problem/src/utils/findProblemInApolloError.ts +++ b/libs/shared/problem/src/utils/findProblemInApolloError.ts @@ -1,6 +1,13 @@ import type { ApolloError } from '@apollo/client' import { Problem } from '../Problem' +interface ProblemExtensions { + problem?: Problem + exception?: { + problem?: Problem + } +} + export const findProblemInApolloError = ( error: ApolloError | undefined, types?: string[], @@ -8,15 +15,20 @@ export const findProblemInApolloError = ( if (!error) { return undefined } - const graphQLError = error.graphQLErrors.find((value) => { - const problem = value.extensions?.problem as Problem | undefined - return problem && (!types || types.includes(problem.type)) - }) - if (!graphQLError) { + const problems = error.graphQLErrors + .map((value) => { + const extensions = value.extensions as ProblemExtensions | undefined + const problem = extensions?.problem || extensions?.exception?.problem + if (problem && (!types || types.includes(problem.type))) { + return problem + } + }) + .filter((problem) => problem) as Problem[] + + if (problems.length === 0) { return undefined } - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return graphQLError.extensions!.problem as Problem + return problems[0] }