diff --git a/app/App.tsx b/app/App.tsx index 708981b4..ff4b6c78 100644 --- a/app/App.tsx +++ b/app/App.tsx @@ -79,7 +79,7 @@ const App = () => { translucent={false} /> - + private navigate: (stack: never, params: never) => void private setAppState: React.Dispatch> @@ -90,7 +91,7 @@ export class AppContainer implements Container { t: TFunction<'translation', undefined>, navigate: (stack: never, params: never) => void, useState: [AppState, React.Dispatch>], - log?: BaseLogger + log?: BifoldLogger ) { this._container = bifoldContainer.container.createChildContainer() this.log = log @@ -113,7 +114,6 @@ export class AppContainer implements Container { lokiUrl: Config.REMOTE_LOGGING_URL, lokiLabels: { application: getApplicationName().toLowerCase(), - job: 'react-native-logs', version: `${getVersion()}-${getBuildNumber()}`, system: `${getSystemName()} v${getSystemVersion()}`, }, diff --git a/app/jestSetup.js b/app/jestSetup.js index 70ccd16c..a3d871b0 100644 --- a/app/jestSetup.js +++ b/app/jestSetup.js @@ -1,7 +1,12 @@ /* eslint-disable no-undef */ import 'react-native-gesture-handler/jestSetup' import mockRNLocalize from 'react-native-localize/mock' +import mockRNDeviceInfo from 'react-native-device-info/jest/react-native-device-info-mock' +mockRNDeviceInfo.getVersion = jest.fn(() => '1') +mockRNDeviceInfo.getBuildNumber = jest.fn(() => '1') + +jest.mock('react-native-device-info', () => mockRNDeviceInfo) jest.mock('react-native/Libraries/Animated/NativeAnimatedHelper') jest.mock('react-native/Libraries/EventEmitter/NativeEventEmitter') jest.mock('react-native-localize', () => mockRNLocalize) diff --git a/app/src/hooks/initialize-agent.ts b/app/src/hooks/initialize-agent.ts index 8e66824e..1b8e16a1 100644 --- a/app/src/hooks/initialize-agent.ts +++ b/app/src/hooks/initialize-agent.ts @@ -190,7 +190,7 @@ const useInitializeBCAgent = () => { if (store.preferences.usePushNotifications) { logger.info('Activating push notifications...') - await activate(newAgent) + activate(newAgent) } // In case the old attestationMonitor is still active, stop it and start a new one diff --git a/app/src/localization/en/index.ts b/app/src/localization/en/index.ts index 95bf785f..8aa24e4f 100644 --- a/app/src/localization/en/index.ts +++ b/app/src/localization/en/index.ts @@ -21,6 +21,10 @@ const translation = { "Message2028": "There was a problem receiving the attestation invitation to connect.", "Title2029": "Unable to handle attestation proof", "Message2029": "There was a problem while handling an attestation proof request.", + "Title2030": "Unable to complete app initialization", + "Message2030": "There was a problem while initializing the app.", + "Title2031": "Unable to complete agent initialization", + "Message2031": "There was a problem while initializing the agent.", "NoMessage": "No Message", }, "CameraDisclosure": { diff --git a/app/src/localization/fr/index.ts b/app/src/localization/fr/index.ts index e5195faa..2c3eabec 100644 --- a/app/src/localization/fr/index.ts +++ b/app/src/localization/fr/index.ts @@ -21,6 +21,10 @@ const translation = { "Message2028": "Un problème est survenu pendant la réception de l'attestation de l'invitation de connection.", "Title2029": "Incapable de gérer la preuve d'attestation.", "Message2029": "Un problème est survenu de la gestion lors de la requête de preuve d'attestation.", + "Title2030": "Unable to complete app initialization (FR)", + "Message2030": "There was a problem while initializing the app. (FR)", + "Title2031": "Unable to complete agent initialization (FR)", + "Message2031": "There was a problem while initializing the agent. (FR)", "NoMessage": "Aucun message", }, "CameraDisclosure": { diff --git a/app/src/localization/pt-br/index.ts b/app/src/localization/pt-br/index.ts index ddcb85d0..897e8048 100644 --- a/app/src/localization/pt-br/index.ts +++ b/app/src/localization/pt-br/index.ts @@ -21,6 +21,10 @@ const translation = { "Message2028": "There was a problem receiving the attestation invitation to connect. (PT-BR)", "Title2029": "Unable to handle attestation proof (PT-BR)", "Message2029": "There was a problem while handling an attestation proof request. (PT-BR)", + "Title2030": "Unable to complete app initialization (PT-BR)", + "Message2030": "There was a problem while initializing the app. (PT-BR)", + "Title2031": "Unable to complete agent initialization (PT-BR)", + "Message2031": "There was a problem while initializing the agent. (PT-BR)", "NoMessage": "No Message (PT-BR)", }, "CameraDisclosure": { diff --git a/app/src/screens/Splash.tsx b/app/src/screens/Splash.tsx index 9ce198c7..3dd5c1ce 100644 --- a/app/src/screens/Splash.tsx +++ b/app/src/screens/Splash.tsx @@ -9,6 +9,7 @@ import { testIdWithKey, TOKENS, useServices, + BifoldError, } from '@hyperledger/aries-bifold-core' import { RemoteOCABundleResolver } from '@hyperledger/aries-oca/build/legacy' import { CommonActions, useNavigation } from '@react-navigation/native' @@ -16,6 +17,7 @@ import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react' import { useTranslation } from 'react-i18next' import { StyleSheet, View, Text, Image, useWindowDimensions, ScrollView } from 'react-native' import { SafeAreaView } from 'react-native-safe-area-context' +import Icon from 'react-native-vector-icons/MaterialCommunityIcons' import ProgressBar from '../components/ProgressBar' import TipCarousel from '../components/TipCarousel' @@ -110,14 +112,23 @@ const Splash = () => { const [initOnboardingCount, setInitOnboardingCount] = useState(0) const [initAgentCount, setInitAgentCount] = useState(0) const [initErrorType, setInitErrorType] = useState(InitErrorTypes.Onboarding) - const [initError, setInitError] = useState(null) + const [initError, setInitError] = useState(null) + const [reported, setReported] = useState(false) const initializing = useRef(false) const { initializeAgent } = useInitializeBCAgent() - const [ocaBundleResolver, { showPreface, enablePushNotifications }] = useServices([ + const [logger, ocaBundleResolver, { showPreface, enablePushNotifications }] = useServices([ + TOKENS.UTIL_LOGGER, TOKENS.UTIL_OCA_RESOLVER, TOKENS.CONFIG, ]) + const report = useCallback(() => { + if (initError) { + logger.report(initError) + } + setReported(true) + }, [logger, initError]) + const steps: string[] = useMemo( () => [ t('Init.Starting'), @@ -274,7 +285,7 @@ const Splash = () => { } } catch (e: unknown) { setInitErrorType(InitErrorTypes.Onboarding) - setInitError(e as Error) + setInitError(new BifoldError(t('Error.Title2030'), t('Error.Message2030'), (e as Error)?.message, 2030)) } }, [ mounted, @@ -335,7 +346,7 @@ const Splash = () => { } catch (e: unknown) { initializing.current = false setInitErrorType(InitErrorTypes.Agent) - setInitError(e as Error) + setInitError(new BifoldError(t('Error.Title2031'), t('Error.Message2031'), (e as Error)?.message, 2031)) } } @@ -350,6 +361,7 @@ const Splash = () => { store.onboarding.didConsiderBiometry, navigation, initAgentCount, + t, ]) const handleErrorCallToActionPressed = () => { @@ -380,6 +392,11 @@ const Splash = () => { message={initError?.message || t('Error.Unknown')} onCallToActionLabel={t('Init.Retry')} onCallToActionPressed={handleErrorCallToActionPressed} + secondaryCallToActionTitle={reported ? t('Error.Reported') : t('Error.ReportThisProblem')} + secondaryCallToActionDisabled={reported} + secondaryCallToActionIcon={reported ? : undefined} + secondaryCallToActionPressed={initError ? report : undefined} + showVersionFooter /> ) : ( diff --git a/app/src/services/attestation.ts b/app/src/services/attestation.ts index 34e0d500..f88ef0c1 100644 --- a/app/src/services/attestation.ts +++ b/app/src/services/attestation.ts @@ -8,12 +8,12 @@ import { ProofState, ProofEventTypes, ProofExchangeRecord, - BaseLogger, ConnectionRecord, } from '@credo-ts/core' import { BifoldError, BifoldAgent, + BifoldLogger, AttestationEventTypes, AttestationMonitor as AttestationMonitorI, } from '@hyperledger/aries-bifold-core' @@ -150,7 +150,7 @@ export class AttestationMonitor implements AttestationMonitorI { private offerSubscription?: Subscription private agent?: Agent private options: AttestationMonitorOptions - private log?: BaseLogger + private log?: BifoldLogger private _attestationWorkflowInProgress = false private _shouldHandleProofRequestAutomatically = false private _proofRequest?: ProofExchangeRecord @@ -158,7 +158,7 @@ export class AttestationMonitor implements AttestationMonitorI { // take in options, agent, and logger. Options should include the attestation service URL // and the proof to watch for along with the cred_ef_id of the attestation credentials. - public constructor(logger: BaseLogger, options: AttestationMonitorOptions) { + public constructor(logger: BifoldLogger, options: AttestationMonitorOptions) { this.log = logger this.options = options const { shouldHandleProofRequestAutomatically } = options