Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/src/RemoteConfig.web.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ class MockFirebaseRemoteConfig implements RemoteConfigBackend {

getAll(): Record<string, RemoteConfigValue> {
const result: Record<string, RemoteConfigValue> = {};
for (const [key, value] of Object.entries(this.config)) {
for (const [key, _value] of Object.entries(this.config)) {
result[key] = this.getValue(key);
}
return result;
Expand Down
2 changes: 1 addition & 1 deletion app/src/components/NavBar/HomeNavBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export const HomeNavBar = (props: NativeStackHeaderProps) => {
try {
Clipboard.setString('');
} catch {}
props.navigation.navigate('ProveScreen');
props.navigation.navigate('Prove');
} catch (error) {
console.error('Error consuming token:', error);
if (
Expand Down
2 changes: 1 addition & 1 deletion app/src/hooks/useModal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import { useCallback, useRef, useState } from 'react';
import { useNavigation } from '@react-navigation/native';

import type { ModalParams } from '@/screens/misc/ModalScreen';
import type { ModalParams } from '@/screens/system/ModalScreen';
import {
getModalCallbacks,
registerModalCallbacks,
Expand Down
10 changes: 5 additions & 5 deletions app/src/navigation/aesop.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,17 @@ import { ProgressNavBar } from '@/components/NavBar';
import { shouldShowAesopRedesign } from '@/hooks/useAesopRedesign';
import { white } from '@/utils/colors';

const PassportOnboardingScreen = lazy(
() => import('@/screens/aesop/PassportOnboardingScreen'),
const DocumentOnboardingScreen = lazy(
() => import('@/screens/aesop/DocumentOnboardingScreen'),
);

const aesopScreens = {
PassportOnboarding: {
screen: PassportOnboardingScreen,
DocumentOnboarding: {
screen: DocumentOnboardingScreen,
options: {
animation: 'slide_from_bottom',
header: ProgressNavBar,
title: 'Scan your passport',
title: 'Scan your document',
headerStyle: {
backgroundColor: white,
},
Expand Down
47 changes: 18 additions & 29 deletions app/src/navigation/devTools.ts → app/src/navigation/dev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,35 @@
import { lazy } from 'react';
import type { NativeStackNavigationOptions } from '@react-navigation/native-stack';

// DevPrivateKeyScreen is loaded lazily to avoid bundling in production
import { black, white } from '@/utils/colors';

const DevFeatureFlagsScreen = lazy(
() => import('@/screens/dev/DevFeatureFlagsScreen'),
);
const DevHapticFeedbackScreen = lazy(
() => import('@/screens/dev/DevHapticFeedback'),
() => import('@/screens/dev/DevHapticFeedbackScreen'),
);
const DevSettingsScreen = lazy(() => import('@/screens/dev/DevSettingsScreen'));
const MockDataScreen = lazy(() => import('@/screens/dev/MockDataScreen'));
const MockDataScreenDeepLink = lazy(
() => import('@/screens/dev/MockDataScreenDeepLink'),
);
const DevPrivateKeyScreen = lazy(
() => import('@/screens/dev/DevPrivateKeyScreen'),
const CreateMockScreen = lazy(() => import('@/screens/dev/CreateMockScreen'));
const CreateMockScreenDeepLink = lazy(
() => import('@/screens/dev/CreateMockScreenDeepLink'),
);

const devHeaderOptions: NativeStackNavigationOptions = {
headerStyle: {
backgroundColor: black,
},
headerTitleStyle: {
color: white,
},
headerBackTitle: 'close',
};
Comment on lines +22 to +30
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Back arrow and icon tint may be invisible on dark headers

You set a black header and white title but didn’t set headerTintColor, so back chevron and header buttons may be low-contrast depending on theme/platform. Set headerTintColor to white in the shared options.

 const devHeaderOptions: NativeStackNavigationOptions = {
   headerStyle: {
     backgroundColor: black,
   },
   headerTitleStyle: {
     color: white,
   },
+  headerTintColor: white,
   headerBackTitle: 'close',
 };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const devHeaderOptions: NativeStackNavigationOptions = {
headerStyle: {
backgroundColor: black,
},
headerTitleStyle: {
color: white,
},
headerBackTitle: 'close',
};
const devHeaderOptions: NativeStackNavigationOptions = {
headerStyle: {
backgroundColor: black,
},
headerTitleStyle: {
color: white,
},
headerTintColor: white,
headerBackTitle: 'close',
};
🤖 Prompt for AI Agents
In app/src/navigation/dev.ts around lines 21 to 29, the shared devHeaderOptions
sets a black header and white title but omits headerTintColor so the back
chevron and header buttons can be low-contrast; update devHeaderOptions to
include headerTintColor: white so icons and back arrow are tinted white and
remain visible against the dark header.


const devScreens = {
CreateMock: {
screen: MockDataScreen,
screen: CreateMockScreen,
options: {
...devHeaderOptions,
title: 'Mock Document',
headerStyle: {
backgroundColor: black,
Expand All @@ -37,7 +44,7 @@ const devScreens = {
} as NativeStackNavigationOptions,
},
MockDataDeepLink: {
screen: MockDataScreenDeepLink,
screen: CreateMockScreenDeepLink,
options: {
headerShown: false,
} as NativeStackNavigationOptions,
Expand All @@ -51,14 +58,8 @@ const devScreens = {
DevSettings: {
screen: DevSettingsScreen,
options: {
...devHeaderOptions,
title: 'Dev Mode',
headerStyle: {
backgroundColor: black,
},
headerTitleStyle: {
color: white,
},
headerBackTitle: 'close',
} as NativeStackNavigationOptions,
},
DevFeatureFlags: {
Expand All @@ -70,18 +71,6 @@ const devScreens = {
},
} as NativeStackNavigationOptions,
},
DevPrivateKey: {
screen: DevPrivateKeyScreen,
options: {
title: 'Private Key',
headerStyle: {
backgroundColor: black,
},
headerTitleStyle: {
color: white,
},
} as NativeStackNavigationOptions,
},
};

export default devScreens;
60 changes: 30 additions & 30 deletions app/src/navigation/passport.ts → app/src/navigation/document.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,46 +5,46 @@
import { lazy } from 'react';
import type { NativeStackNavigationOptions } from '@react-navigation/native-stack';

const PassportCameraScreen = lazy(
() => import('@/screens/passport/PassportCameraScreen'),
const DocumentCameraScreen = lazy(
() => import('@/screens/document/DocumentCameraScreen'),
);
const PassportCameraTrouble = lazy(
() => import('@/screens/passport/PassportCameraTroubleScreen'),
const DocumentCameraTroubleScreen = lazy(
() => import('@/screens/document/DocumentCameraTroubleScreen'),
);
const PassportNFCScanScreen = lazy(
() => import('@/screens/passport/PassportNFCScanScreen'),
const DocumentNFCScanScreen = lazy(
() => import('@/screens/document/DocumentNFCScanScreen'),
);
const PassportNFCTrouble = lazy(
() => import('@/screens/passport/PassportNFCTroubleScreen'),
const DocumentNFCTroubleScreen = lazy(
() => import('@/screens/document/DocumentNFCTroubleScreen'),
);
const PassportOnboardingScreen = lazy(
() => import('@/screens/passport/PassportOnboardingScreen'),
const DocumentOnboardingScreen = lazy(
() => import('@/screens/document/DocumentOnboardingScreen'),
);
const UnsupportedPassportScreen = lazy(
() => import('@/screens/passport/UnsupportedPassportScreen'),
const UnsupportedDocumentScreen = lazy(
() => import('@/screens/document/UnsupportedDocumentScreen'),
);
const NFCMethodSelectionScreen = lazy(
() => import('@/screens/passport/NFCMethodSelectionScreen'),
const DocumentNFCMethodSelectionScreen = lazy(
() => import('@/screens/document/DocumentNFCMethodSelectionScreen'),
);

const passportScreens = {
PassportCamera: {
screen: PassportCameraScreen,
const documentScreens = {
DocumentCamera: {
screen: DocumentCameraScreen,
options: {
headerShown: false,
animation: 'slide_from_bottom',
} as NativeStackNavigationOptions,
},
PassportCameraTrouble: {
screen: PassportCameraTrouble,
DocumentCameraTrouble: {
screen: DocumentCameraTroubleScreen,
options: {
headerShown: false,
animation: 'slide_from_bottom',
presentation: 'modal',
} as NativeStackNavigationOptions,
},
PassportNFCScan: {
screen: PassportNFCScanScreen,
DocumentNFCScan: {
screen: DocumentNFCScanScreen,
options: {
headerShown: false,
animation: 'slide_from_bottom',
Expand All @@ -55,38 +55,38 @@ const passportScreens = {
dateOfExpiry: '',
},
},
PassportNFCTrouble: {
screen: PassportNFCTrouble,
DocumentNFCTrouble: {
screen: DocumentNFCTroubleScreen,
options: {
headerShown: false,
animation: 'slide_from_bottom',
presentation: 'modal',
} as NativeStackNavigationOptions,
},
PassportOnboarding: {
screen: PassportOnboardingScreen,
DocumentOnboarding: {
screen: DocumentOnboardingScreen,
options: {
animation: 'slide_from_bottom',
// presentation: 'modal' wanted to do this but seems to break stuff
headerShown: false,
} as NativeStackNavigationOptions,
},
UnsupportedPassport: {
screen: UnsupportedPassportScreen,
UnsupportedDocument: {
screen: UnsupportedDocumentScreen,
options: {
headerShown: false,
} as NativeStackNavigationOptions,
initialParams: {
passportData: null,
},
},
PassportNFCMethodSelection: {
screen: NFCMethodSelectionScreen,
DocumentNFCMethodSelection: {
screen: DocumentNFCMethodSelectionScreen,
options: {
headerShown: false,
animation: 'slide_from_bottom',
} as NativeStackNavigationOptions,
},
};

export default passportScreens;
export default documentScreens;
10 changes: 5 additions & 5 deletions app/src/navigation/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,20 @@ import { createNativeStackNavigator } from '@react-navigation/native-stack';
import { DefaultNavBar } from '@/components/NavBar';
import AppLayout from '@/layouts/AppLayout';
import { getAesopScreens } from '@/navigation/aesop';
import devScreens from '@/navigation/devTools';
import devScreens from '@/navigation/dev';
import documentScreens from '@/navigation/document';
import homeScreens from '@/navigation/home';
import miscScreens from '@/navigation/misc';
import passportScreens from '@/navigation/passport';
import proveScreens from '@/navigation/prove';
import recoveryScreens from '@/navigation/recovery';
import settingsScreens from '@/navigation/settings';
import systemScreens from '@/navigation/system';
import analytics from '@/utils/analytics';
import { white } from '@/utils/colors';
import { setupUniversalLinkListenerInNavigation } from '@/utils/deeplinks';

export const navigationScreens = {
...miscScreens,
...passportScreens,
...systemScreens,
...documentScreens,
...homeScreens,
...proveScreens,
...settingsScreens,
Expand Down
19 changes: 19 additions & 0 deletions app/src/navigation/lazyWithPreload.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// SPDX-FileCopyrightText: 2025 Social Connect Labs, Inc.
// SPDX-License-Identifier: BUSL-1.1
// NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE.

import { lazy, type LazyExoticComponent } from 'react';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Import ComponentType to avoid React namespace type issues

Referencing React.ComponentType without importing the React namespace can fail under stricter TS configs (NodeNext/Bundler). Import the type explicitly.

-import { lazy, type LazyExoticComponent } from 'react';
+import { lazy, type LazyExoticComponent, type ComponentType } from 'react';
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import { lazy, type LazyExoticComponent } from 'react';
import { lazy, type LazyExoticComponent, type ComponentType } from 'react';
🤖 Prompt for AI Agents
In app/src/navigation/lazyWithPreload.ts around line 5, the file imports lazy
and LazyExoticComponent but references React.ComponentType elsewhere which can
break under strict TS configs; update the import to also include the
ComponentType type from 'react' (e.g. add ComponentType to the existing named
import) and replace any occurrences of React.ComponentType in this file with the
imported ComponentType to avoid namespace/type resolution issues.


// Helper around React.lazy that exposes the underlying dynamic import
// so callers can manually preload a screen when debugging or profiling.
// Prefer using React.lazy directly and opt into this only when you need
// to eagerly load a component.
export function lazyWithPreload<T extends React.ComponentType<any>>(

Check warning on line 11 in app/src/navigation/lazyWithPreload.ts

View workflow job for this annotation

GitHub Actions / build-deps

Unexpected any. Specify a different type
factory: () => Promise<{ default: T }>,
) {
Comment on lines +11 to +13
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Remove any and add explicit return type for stronger type-safety

Eliminate any, align with static analysis, and make the API surface explicit. Also type preload via typeof factory to prevent drift.

-export function lazyWithPreload<T extends React.ComponentType<any>>(
-  factory: () => Promise<{ default: T }>,
-) {
+export function lazyWithPreload<T extends ComponentType<unknown>>(
+  factory: () => Promise<{ default: T }>,
+): LazyExoticComponent<T> & { preload: typeof factory } {

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 GitHub Check: build-deps

[warning] 11-11:
Unexpected any. Specify a different type

const Component = lazy(factory) as LazyExoticComponent<T> & {
preload: () => Promise<{ default: T }>;
};
Component.preload = factory;
return Component;
}
8 changes: 4 additions & 4 deletions app/src/navigation/prove.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,24 +18,24 @@ const QRCodeTroubleScreen = lazy(
() => import('@/screens/prove/QRCodeTroubleScreen'),
);
const QRCodeViewFinderScreen = lazy(
() => import('@/screens/prove/ViewFinderScreen'),
() => import('@/screens/prove/QRCodeViewFinderScreen'),
);

const proveScreens = {
ConfirmBelongingScreen: {
ConfirmBelonging: {
screen: ConfirmBelongingScreen,
options: {
headerShown: false,
} as NativeStackNavigationOptions,
},
ProofRequestStatusScreen: {
ProofRequestStatus: {
screen: ProofRequestStatusScreen,
options: {
headerShown: false,
animation: 'slide_from_bottom',
} as NativeStackNavigationOptions,
},
ProveScreen: {
Prove: {
screen: ProveScreen,
options: {
title: 'Request Proof',
Expand Down
8 changes: 4 additions & 4 deletions app/src/navigation/recovery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ const AccountRecoveryScreen = lazy(
const AccountVerifiedSuccessScreen = lazy(
() => import('@/screens/recovery/AccountVerifiedSuccessScreen'),
);
const PassportDataNotFound = lazy(
() => import('@/screens/recovery/PassportDataNotFoundScreen'),
const DocumentDataNotFound = lazy(
() => import('@/screens/recovery/DocumentDataNotFoundScreen'),
);
Comment on lines +19 to 21
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Preload recovery fallback screen and verify route/key propagation

  • Swap to lazyWithPreload so DEBUG_SCREEN or error paths can warm this screen.
  • Check that linking and tests reference DocumentDataNotFound everywhere.

Apply within these hunks:

-const DocumentDataNotFound = lazy(
+const DocumentDataNotFound = lazyWithPreload(
  () => import('@/screens/recovery/DocumentDataNotFoundScreen'),
);

Add the helper import:

import { lazyWithPreload } from '@/utils/lazyWithPreload';

Quick checks:

Also applies to: 49-57


🏁 Script executed:

#!/bin/bash
rg -nP "PassportDataNotFound\b|navigate\\(['\"]PassportDataNotFound['\"]|name:\\s*['\"]PassportDataNotFound['\"]" -S

Length of output: 124


🏁 Script executed:

#!/bin/bash
rg -nP "DocumentDataNotFound\b|navigate\(['\"]DocumentDataNotFound['\"]\)|name:\s*['\"]DocumentDataNotFound['\"]" -S

Length of output: 699


Preload recovery fallback screens

  • Replace lazy with lazyWithPreload for DocumentDataNotFound in both
    app/src/navigation/recovery.ts (lines 19, 49–57)
    app/src/navigation/recovery.web.ts (lines 8, 13–14)
  • Add import { lazyWithPreload } from '@/utils/lazyWithPreload'; to both files
  • No changes needed for tests (app/tests/src/navigation.test.ts) or provingMachine.ts, which already reference DocumentDataNotFound
🤖 Prompt for AI Agents
In app/src/navigation/recovery.ts (around lines 19 and 49–57) and
app/src/navigation/recovery.web.ts (around lines 8 and 13–14), replace the use
of React.lazy for the DocumentDataNotFound screen with the project's
lazyWithPreload helper: add the import "import { lazyWithPreload } from
'@/utils/lazyWithPreload';" at the top of both files, change the
DocumentDataNotFound lazy initialization to use lazyWithPreload(...) instead of
lazy(...), and ensure exported references remain the same; do not modify tests
or provingMachine.ts.

const RecoverWithPhraseScreen = lazy(
() => import('@/screens/recovery/RecoverWithPhraseScreen'),
Expand Down Expand Up @@ -46,8 +46,8 @@ const recoveryScreens = {
animation: 'slide_from_bottom',
} as NativeStackNavigationOptions,
},
PassportDataNotFound: {
screen: PassportDataNotFound,
DocumentDataNotFound: {
screen: DocumentDataNotFound,
options: {
headerShown: false,
gestureEnabled: false,
Expand Down
8 changes: 4 additions & 4 deletions app/src/navigation/recovery.web.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@
import { lazy } from 'react';
import type { NativeStackNavigationOptions } from '@react-navigation/native-stack';

const PassportDataNotFound = lazy(
() => import('@/screens/recovery/PassportDataNotFoundScreen'),
const DocumentDataNotFound = lazy(
() => import('@/screens/recovery/DocumentDataNotFoundScreen'),
);
Comment on lines +8 to 10
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Web parity: consider lazyWithPreload here too

Keep recovery.web.ts consistent with native for predictable chunking/preload behavior.

-const DocumentDataNotFound = lazy(
+const DocumentDataNotFound = lazyWithPreload(
  () => import('@/screens/recovery/DocumentDataNotFoundScreen'),
);

Add:

import { lazyWithPreload } from '@/utils/lazyWithPreload';

Also applies to: 13-15

🤖 Prompt for AI Agents
In app/src/navigation/recovery.web.ts around lines 8-10 and 13-15, the file uses
React.lazy for screens but the native code uses lazyWithPreload; add the import
"import { lazyWithPreload } from '@/utils/lazyWithPreload';" near other imports
and replace React.lazy calls for the listed screens with lazyWithPreload so the
web build matches native chunking/preload behavior and supports preloading the
same way.


const recoveryScreens = {
PassportDataNotFound: {
screen: PassportDataNotFound,
DocumentDataNotFound: {
screen: DocumentDataNotFound,
options: {
headerShown: false,
gestureEnabled: false,
Expand Down
10 changes: 5 additions & 5 deletions app/src/navigation/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ const CloudBackupScreen = lazy(
const ManageDocumentsScreen = lazy(
() => import('@/screens/settings/ManageDocumentsScreen'),
);
const PassportDataInfoScreen = lazy(
() => import('@/screens/settings/PassportDataInfoScreen'),
const DocumentDataInfoScreen = lazy(
() => import('@/screens/settings/DocumentDataInfoScreen'),
);
const SettingsScreen = lazy(() => import('@/screens/settings/SettingsScreen'));
const ShowRecoveryPhraseScreen = lazy(
Expand Down Expand Up @@ -46,10 +46,10 @@ const settingsScreens = {
},
} as NativeStackNavigationOptions,
},
PassportDataInfo: {
screen: PassportDataInfoScreen,
DocumentDataInfo: {
screen: DocumentDataInfoScreen,
options: {
title: 'Passport Data Info',
title: 'Document Data Info',
headerStyle: {
backgroundColor: white,
},
Expand Down
Loading
Loading