Skip to content

Conversation

@transphorm
Copy link
Member

@transphorm transphorm commented Jul 28, 2025

Summary

  • configure manualChunks in vite.config.ts
  • lazy load navigation screens
  • wrap app navigation in Suspense
  • dynamically load heavy providers
  • add crypto loader util

Testing

  • yarn lint
  • yarn build
  • yarn workspace @selfxyz/contracts build (fails: Invalid account in config)
  • yarn types
  • yarn workspace @selfxyz/common test
  • yarn workspace @selfxyz/circuits test (fails: Unsupported signature algorithm)
  • yarn workspace @selfxyz/mobile-app test

https://chatgpt.com/codex/tasks/task_b_68879ec34774832d8a74781f0833f1a7

Summary by CodeRabbit

  • New Features

    • Added dynamic loading for several app screens, improving startup performance and enabling code-splitting.
    • Introduced a loading fallback UI during navigation transitions.
    • Added utility functions for dynamic loading of cryptographic and animation assets.
  • Improvements

    • Enhanced safe area handling for better device compatibility.
    • Optimized build and bundling with custom chunking and improved Metro bundler configuration.
    • Refined import paths and modularized code for improved maintainability and bundle size.
  • Chores

    • Updated build scripts, workflow steps, and dependency management for more reliable CI/CD.
    • Increased JVM and Gradle heap sizes for more stable Android builds.
    • Updated Ruby gem versioning for development dependencies.
    • Modified iOS dependency installation scripts for streamlined setup.
    • Enabled Hermes engine in iOS build configurations for improved performance.
  • Style/Refactor

    • Reorganized imports to clarify type-only usage and improve code clarity.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jul 28, 2025

Walkthrough

This update introduces dynamic imports and lazy loading for multiple screen components, adds new utility modules for dynamic resource loading, and reorganizes import paths for improved modularity. It also enhances bundler and build configurations, updates workflow automation, and includes memory optimizations for Android builds. No exported APIs or public interfaces were changed.

Changes

Cohort / File(s) Change Summary
Dynamic Screen Lazy Loading
app/src/navigation/aesop.ts, app/src/navigation/dev.ts, app/src/navigation/passport.ts, app/src/navigation/prove.ts, app/src/navigation/recovery.ts, app/src/navigation/settings.ts
Refactored to use React's lazy for dynamic/lazy loading of screen components, replacing static imports to enable code-splitting and deferred loading.
Suspense Integration for Navigation
app/src/navigation/index.tsx
Wrapped navigation in React's Suspense with a fallback UI to support lazy-loaded screens. Added a simple fallback component.
New Dynamic Loader Utilities
app/src/assets/animations/loader.ts, app/src/utils/cryptoLoader.ts
Added utility modules for dynamic import of animation JSONs and cryptographic/proving libraries, supporting parallel and on-demand loading.
Import Path Modularization
app/src/components/Disclosures.tsx, app/src/providers/passportDataProvider.tsx, app/src/screens/dev/MockDataScreen.tsx, app/src/screens/dev/MockDataScreenDeepLink.tsx, app/src/screens/misc/LoadingScreen.tsx, app/src/screens/passport/PassportNFCScanScreen.tsx, app/src/screens/prove/ProveScreen.tsx, app/src/screens/settings/PassportDataInfoScreen.tsx, app/src/stores/proof-types.ts, app/src/stores/proofHistoryStore.ts, app/src/stores/protocolStore.ts, app/src/stores/selfAppStore.tsx, app/src/utils/nfcScanner.ts, app/src/utils/ofac.ts, app/src/utils/proving/attest.ts, app/src/utils/proving/provingInputs.ts, app/src/utils/proving/provingMachine.ts, app/src/utils/proving/provingUtils.ts, app/src/utils/proving/validateDocument.ts
Refactored import statements to use more granular submodule paths and type-only imports, clarifying boundaries between types and runtime code. No logic changes.
Proof Request Status Screen Refactor
app/src/screens/prove/ProofRequestStatusScreen.tsx
Updated to use useCallback for the main handler, refined effect dependencies, and switched to direct useRef import for timer references.
Metro & Vite Bundler Configuration
app/metro.config.cjs, app/vite.config.ts
Enhanced Metro config with custom resolver logic and aliasing; Vite config updated to define custom chunk splitting for optimized bundling.
Safe Area Provider Integration
app/App.tsx
Wrapped the app in SafeAreaProvider to ensure UI respects device safe areas.
Build & Workflow Automation
.github/workflows/app.yml, .github/workflows/general-checks.yml
Added steps to build dependencies before linting and type-checking in CI workflows.
Android Build & Memory Optimization
app/android/app/build.gradle, app/android/gradle.properties
Increased Java heap/metaspace, added string deduplication, improved Hermes path resolution, and made signing config more robust.
Cursor Ignore & Ruby Dependency Updates
.cursorignore, app/Gemfile
Stopped ignoring Ruby dependency files and updated the Nokogiri gem version constraint.
Test Mock Path Update
app/tests/utils/proving/provingMachine.generatePayload.test.ts
Changed mocked module path to target a more specific utility submodule.
TypeScript Module Output
app/tsconfig.json
Set TypeScript module output to esnext for modern module syntax.
Babel Plugin Addition
app/babel.config.cjs
Added @tamagui/babel-plugin with native platform option to Babel plugins.
Package.json Script & Dependency Updates
app/package.json
Reordered release scripts, enhanced iOS clean scripts, updated setup scripts, and added a new dev dependency.
iOS Podfile Update
app/ios/Podfile
Enabled Hermes JavaScript engine and changed source URL quoting style.

Sequence Diagram(s)

sequenceDiagram
  participant App
  participant SafeAreaProvider
  participant ErrorBoundary
  participant Providers
  participant Suspense
  participant Navigation

  App->>SafeAreaProvider: Render
  SafeAreaProvider->>ErrorBoundary: Render
  ErrorBoundary->>Providers: Render
  Providers->>Suspense: Render
  Suspense->>Navigation: Render (with fallback)
  Navigation-->>Suspense: Loads screens (some via React.lazy)
  Suspense-->>Providers: Show fallback if loading
Loading
sequenceDiagram
  participant Navigation
  participant React.lazy
  participant SuspenseFallback

  Navigation->>React.lazy: Request screen component (e.g., PassportOnboardingScreen)
  React.lazy-->>Navigation: Loads component asynchronously
  alt Loading
    Navigation->>SuspenseFallback: Show "Loading..." UI
  else Loaded
    Navigation->>Screen: Render screen
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~40 minutes

  • Multiple navigation files refactored for lazy loading
  • New dynamic loader utilities added
  • Bundler and build configs significantly updated
  • Numerous files with modularized imports
  • Some workflow and Android build changes
  • No major business logic or API changes, but breadth and cross-cutting concerns increase review time

Possibly related PRs

Poem

🚀
Lazy screens now load on cue,
With Suspense to guide them through.
Crypto, chunks, and loaders new,
Imports trimmed and paths askew.
Android builds with memory wide,
CI steps now build with pride.

Code, like poetry, refines the view!


📜 Recent review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f6defcf and 2b1ba18.

📒 Files selected for processing (1)
  • app/package.json (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • app/package.json
⏰ Context from checks skipped due to timeout of 300000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build
✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch codex/implement-code-splitting-for-react-native-web-app

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@transphorm transphorm changed the title Implement basic code splitting SEL-508: Implement code splitting and lazy loading Jul 28, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 9

🔭 Outside diff range comments (2)
app/src/screens/dev/MockDataScreenDeepLink.tsx (1)

51-51: Replace explicit any with proper typing.

The type assertion as any circumvents TypeScript's type safety and is flagged by ESLint. Consider using a more specific type or type guard.

-nationality: storeState.deepLinkNationality as any,
+nationality: storeState.deepLinkNationality as keyof typeof countryCodes,
app/src/navigation/index.tsx (1)

69-69: Remove console.log statement to fix linting violation.

The ESLint rule no-console is violated by this console.log statement. Consider using a proper logging utility or removing debug logging.

-      console.log(`Screen View: ${currentRoute.name}`);
🧹 Nitpick comments (4)
app/src/utils/proving/provingUtils.ts (1)

3-6: Consider lazy-loading node-forge to cut initial bundle weight.

node-forge is ~700 KB min-gzip; pulling it into the main chunk undercuts the code-splitting effort. A tiny refactor pushes it to an async path:

-import { WS_DB_RELAYER, WS_DB_RELAYER_STAGING } from '@selfxyz/common';
-import type { EndpointType } from '@selfxyz/common';
-import { initElliptic } from '@selfxyz/common';
-import forge from 'node-forge';
+import { WS_DB_RELAYER, WS_DB_RELAYER_STAGING } from '@selfxyz/common';
+import type { EndpointType } from '@selfxyz/common';
+import { initElliptic } from '@selfxyz/common';
+
+// Lazy-load to keep the critical path lean
+let forge: typeof import('node-forge') | null = null;
+async function getForge() {
+  if (!forge) forge = await import('node-forge');
+  return forge;
+}

Then in encryptAES256GCM:

-export function encryptAES256GCM(
+export async function encryptAES256GCM(
   plaintext: string,
   key: forge.util.ByteStringBuffer,
 ) {
-  const iv = forge.random.getBytesSync(12);
+  const f = await getForge();
+  const iv = f.random.getBytesSync(12);
+  const cipher = f.cipher.createCipher('AES-GCM', key);

This defers the heft until encryption is actually invoked.

app/src/assets/animations/loader.ts (1)

3-4: Return the JSON object directly for smoother call-sites.

Consumers typically want the parsed JSON, not the module wrapper. A tiny tweak avoids the extra .then(m => m.default) everywhere:

-export const loadPassportAnimation = () => import('./passport_verify.json');
-export const loadMiscAnimation = () => import('./loading/misc.json');
+export const loadPassportAnimation = () =>
+  import('./passport_verify.json').then(m => m.default);
+export const loadMiscAnimation = () =>
+  import('./loading/misc.json').then(m => m.default);
app/src/providers/passportDataProvider.tsx (1)

47-47: Consider consolidating imports to avoid duplication

The separate import statement for DocumentCategory and PassportData may be causing the import duplication warnings flagged by ESLint. Consider keeping these imports grouped with the other imports from @selfxyz/common for better organization.

The pipeline shows import/no-duplicates warnings. Please consolidate the imports from @selfxyz/common:

-import {
-  brutforceSignatureAlgorithmDsc,
-  parseCertificateSimple,
-  PublicKeyDetailsECDSA,
-  PublicKeyDetailsRSA,
-} from '@selfxyz/common';
-import { DocumentCategory, PassportData } from '@selfxyz/common';
+import {
+  brutforceSignatureAlgorithmDsc,
+  parseCertificateSimple,
+  PublicKeyDetailsECDSA,
+  PublicKeyDetailsRSA,
+  DocumentCategory,
+  PassportData,
+} from '@selfxyz/common';
app/vite.config.ts (1)

101-110: Consider chunk size optimization for screen bundles.

While the screen-specific chunking is well-organized, consider monitoring chunk sizes to ensure optimal loading performance. Large screen chunks might need further subdivision.

Add chunk size monitoring to your build process:

// Consider adding to rollupOptions
output: {
  manualChunks: {
    // existing chunks...
  },
  // Add chunk size warnings
  chunkFileNames: (chunkInfo) => {
    const facadeModuleId = chunkInfo.facadeModuleId ? chunkInfo.facadeModuleId.split('/').pop() : 'chunk';
    return `[name]-[hash].js`;
  }
}
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ee7bba3 and 6ca3946.

📒 Files selected for processing (23)
  • app/App.tsx (2 hunks)
  • app/src/assets/animations/loader.ts (1 hunks)
  • app/src/navigation/aesop.ts (1 hunks)
  • app/src/navigation/dev.ts (1 hunks)
  • app/src/navigation/index.tsx (2 hunks)
  • app/src/navigation/passport.ts (1 hunks)
  • app/src/navigation/prove.ts (1 hunks)
  • app/src/navigation/recovery.ts (1 hunks)
  • app/src/navigation/settings.ts (1 hunks)
  • app/src/providers/passportDataProvider.tsx (1 hunks)
  • app/src/screens/dev/MockDataScreen.tsx (1 hunks)
  • app/src/screens/dev/MockDataScreenDeepLink.tsx (1 hunks)
  • app/src/screens/passport/PassportNFCScanScreen.tsx (1 hunks)
  • app/src/screens/prove/ProveScreen.tsx (1 hunks)
  • app/src/stores/proof-types.ts (1 hunks)
  • app/src/stores/selfAppStore.tsx (1 hunks)
  • app/src/utils/cryptoLoader.ts (1 hunks)
  • app/src/utils/proving/provingInputs.ts (1 hunks)
  • app/src/utils/proving/provingMachine.ts (1 hunks)
  • app/src/utils/proving/provingUtils.ts (1 hunks)
  • app/src/utils/proving/validateDocument.ts (1 hunks)
  • app/tsconfig.json (1 hunks)
  • app/vite.config.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
app/src/**/*.{ts,tsx,js,jsx}

⚙️ CodeRabbit Configuration File

app/src/**/*.{ts,tsx,js,jsx}: Review React Native TypeScript code for:

  • Component architecture and reusability
  • State management patterns
  • Performance optimizations
  • TypeScript type safety
  • React hooks usage and dependencies
  • Navigation patterns

Files:

  • app/src/screens/dev/MockDataScreen.tsx
  • app/src/screens/passport/PassportNFCScanScreen.tsx
  • app/src/screens/prove/ProveScreen.tsx
  • app/src/utils/proving/provingInputs.ts
  • app/src/navigation/aesop.ts
  • app/src/utils/proving/provingUtils.ts
  • app/src/utils/proving/validateDocument.ts
  • app/src/navigation/recovery.ts
  • app/src/navigation/passport.ts
  • app/src/providers/passportDataProvider.tsx
  • app/src/utils/proving/provingMachine.ts
  • app/src/navigation/dev.ts
  • app/src/screens/dev/MockDataScreenDeepLink.tsx
  • app/src/utils/cryptoLoader.ts
  • app/src/stores/selfAppStore.tsx
  • app/src/navigation/prove.ts
  • app/src/navigation/settings.ts
  • app/src/assets/animations/loader.ts
  • app/src/navigation/index.tsx
  • app/src/stores/proof-types.ts
🧠 Learnings (2)
📓 Common learnings
Learnt from: transphorm
PR: selfxyz/self#636
File: app/ios/Podfile:14-14
Timestamp: 2025-06-30T15:27:13.795Z
Learning: React Native 0.80 supports iOS 15.1 as the minimum deployment target, not iOS 16.0. This allows for broader device compatibility while still being compatible with the React Native 0.80 upgrade.
app/src/screens/passport/PassportNFCScanScreen.tsx (1)

Learnt from: transphorm
PR: #636
File: app/src/components/native/QRCodeScanner.tsx:135-142
Timestamp: 2025-07-16T02:20:44.173Z
Learning: In app/src/components/native/QRCodeScanner.tsx, the Android camera dimension multipliers (screenWidth * 3 and screenHeight * 2) are intentionally set to these values and should not be changed. These multipliers are correct and any visual issues with black areas in the camera preview are caused by other factors, not the dimension calculations.

🪛 GitHub Actions: General Self CI
app/src/screens/dev/MockDataScreen.tsx

[warning] 10-250: ESLint warnings: Multiple 'Unexpected console statement' (no-console) and 'imported multiple times' (import/no-duplicates) issues detected.

app/src/screens/passport/PassportNFCScanScreen.tsx

[warning] 8-341: ESLint warnings: Multiple 'Unexpected console statement' (no-console), 'Unexpected any' (@typescript-eslint/no-explicit-any), and 'imported multiple times' (import/no-duplicates) issues detected.

app/src/screens/prove/ProveScreen.tsx

[error] 5-5: ESLint error: Unable to resolve path to module '@selfxyz/common/utils/scope' (import/no-unresolved).

app/src/providers/passportDataProvider.tsx

[warning] 46-486: ESLint warnings: Multiple 'Unexpected console statement' (no-console) and 'imported multiple times' (import/no-duplicates) issues detected.

app/src/screens/dev/MockDataScreenDeepLink.tsx

[warning] 4-51: ESLint warnings: 'imported multiple times' (import/no-duplicates) and 'Unexpected any' (@typescript-eslint/no-explicit-any) issues detected.

app/src/navigation/index.tsx

[warning] 69-69: ESLint warning: 'Unexpected console statement' (no-console) issue detected.

🪛 GitHub Check: lint
app/src/screens/prove/ProveScreen.tsx

[failure] 5-5:
Unable to resolve path to module '@selfxyz/common/utils/scope'

⏰ Context from checks skipped due to timeout of 300000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build
🔇 Additional comments (20)
app/src/stores/selfAppStore.tsx (1)

3-4: Import split looks good.

Moving SelfApp behind import type cleanly strips it from the runtime bundle while keeping the value import for WS_DB_RELAYER. No issues spotted.

app/src/utils/proving/provingInputs.ts (1)

17-23: Type-only import is a tidy win.

Converting DocumentCategory, PassportData, etc. to a pure type import avoids bundling unused runtime objects. 👍

app/src/stores/proof-types.ts (1)

3-3: Pure type import is correct.

EndpointType and UserIdType are referenced only in the type system, so this change prevents an unnecessary runtime dependency.

app/tsconfig.json (1)

5-5: LGTM! Module configuration supports code-splitting

The explicit "module": "esnext" setting properly enables dynamic import syntax and supports the lazy loading implementation throughout the app. This aligns well with the PR's code-splitting objectives.

app/src/utils/proving/provingMachine.ts (1)

7-7: LGTM! Proper use of type-only imports

Converting the imports to import type is excellent practice when these types are only used for type annotations. This optimization prevents unnecessary runtime code inclusion and aligns with TypeScript best practices for tree-shaking.

app/src/screens/prove/ProveScreen.tsx (1)

4-4: Excellent TypeScript optimization!

Using type-only imports for SelfAppDisclosureConfig helps reduce bundle size by preventing runtime inclusion of type definitions. This aligns well with the code-splitting objectives of this PR.

app/src/navigation/recovery.ts (1)

4-23: Excellent code-splitting implementation!

The conversion to lazy-loaded imports for all recovery screens is well-executed and aligns perfectly with the PR's code-splitting objectives. This will significantly improve initial load times by deferring the loading of recovery screens until they're actually needed.

The consistent pattern across all screen components maintains good code organization and readability.

app/src/navigation/passport.ts (1)

4-26: Consistent and effective code-splitting pattern!

The lazy loading implementation for passport screens mirrors the excellent pattern used in the recovery navigation. This consistent approach across navigation modules will provide significant performance benefits by reducing the initial bundle size and enabling on-demand loading of passport functionality.

app/src/navigation/aesop.ts (1)

4-11: Consistent application of lazy loading pattern!

The conversion of PassportOnboardingScreen to lazy loading maintains consistency with the code-splitting approach applied across all navigation modules. Even with just one screen, this consistent pattern contributes to the overall bundle optimization strategy.

app/App.tsx (3)

6-6: Excellent addition of React imports for lazy loading.

Properly imports lazy and Suspense from React to support the code splitting implementation.


16-20: Well-implemented lazy loading pattern.

The PassportProvider is correctly converted to a lazy-loaded component using React.lazy with proper named export extraction. This will help reduce the initial bundle size.


34-42: Proper Suspense boundary implementation.

The Suspense wrapper with LoadingScreen fallback provides excellent UX during the lazy loading of PassportProvider. The provider nesting structure is maintained correctly.

app/src/navigation/dev.ts (1)

4-18: Systematic lazy loading implementation for dev screens.

All development screen components are properly converted to lazy imports using React.lazy. This enables effective code splitting for development screens, which is particularly beneficial since these screens can be excluded or loaded on-demand in production builds.

app/src/navigation/prove.ts (1)

4-18: Consistent lazy loading pattern for prove screens.

All prove-related screen components are systematically converted to lazy imports, maintaining consistency with the code splitting strategy across navigation modules. This will improve initial load performance for the core proof functionality.

app/src/navigation/settings.ts (1)

4-18: Effective lazy loading for settings screens.

Settings screen components are properly converted to lazy imports, which is particularly beneficial since settings screens are accessed less frequently than core functionality. This implementation supports the overall code splitting strategy effectively.

app/src/utils/cryptoLoader.ts (1)

4-8: Excellent concurrent loading pattern for performance.

The use of Promise.all for concurrent dynamic imports is well implemented and will significantly improve loading performance compared to sequential imports.

app/src/navigation/index.tsx (2)

87-89: Excellent Suspense implementation for lazy-loaded navigation.

The Suspense wrapper around the Navigation component is properly implemented and will handle lazy-loaded screen components gracefully. This aligns well with the code-splitting objectives.


9-9: Proper React import update for Suspense.

The import statement correctly includes Suspense, which is essential for the lazy loading implementation.

app/vite.config.ts (2)

66-113: Well-designed chunking strategy that aligns perfectly with code-splitting goals.

The manual chunk configuration is excellently structured with logical groupings:

  • Vendor libraries separated by functionality (React, UI, crypto, device, analytics)
  • Screen-specific chunks align with lazy loading implementation
  • Crypto chunk matches the cryptoLoader.ts dynamic imports

This will significantly improve initial load times and enable efficient code splitting.


77-85: Crypto chunk aligns well with cryptoLoader utility.

The vendor-crypto chunk includes the same libraries (elliptic, node-forge, ethers) that are dynamically imported in cryptoLoader.ts, ensuring consistent bundling strategy.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
.github/workflows/general-checks.yml (1)

12-13: yarn build at repo-root may be fragile & slow — tighten the scope or guard it.

Running yarn build from the monorepo root triggers every package’s build script.
• Cycles that don’t need a build (e.g. docs packages) will still execute, adding minutes to CI.
• Packages with native add-ons or platform-specific steps can fail on Ubuntu, blocking the lint job.

Consider one of these tweaks:

-      - name: Build Dependencies
-        run: yarn build
+      - name: Build Dependencies
+        # Only build packages that expose a build script; ignore silent packages.
+        run: yarn workspaces foreach --topological-dev --if-present run build

or, if only the mobile app truly needs compiling:

run: yarn workspace @selfxyz/mobile-app build

Either approach keeps the safety net while trimming CI time and unexpected breakage.

.github/workflows/app.yml (1)

25-27: Duplicated build work — align with build:deps (test job) to avoid doing the same work twice.

The lint job now compiles the app with yarn build, but the test job later calls yarn build:deps. Unless these scripts perform distinct tasks, we’re burning CI minutes twice and maintaining two commands.

If they are equivalent, unify them for consistency:

-      - name: Build Dependencies
-        run: yarn build
+      - name: Build Dependencies
+        run: yarn build:deps   # already used in the test job

If they’re intentionally different, drop a quick comment explaining the distinction so future maintainers don’t accidentally “simplify” it away.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d15a9b7 and 6eae489.

📒 Files selected for processing (3)
  • .github/workflows/app.yml (1 hunks)
  • .github/workflows/general-checks.yml (1 hunks)
  • app/src/screens/prove/ProofRequestStatusScreen.tsx (3 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
app/src/**/*.{ts,tsx,js,jsx}

⚙️ CodeRabbit Configuration File

app/src/**/*.{ts,tsx,js,jsx}: Review React Native TypeScript code for:

  • Component architecture and reusability
  • State management patterns
  • Performance optimizations
  • TypeScript type safety
  • React hooks usage and dependencies
  • Navigation patterns

Files:

  • app/src/screens/prove/ProofRequestStatusScreen.tsx
🧬 Code Graph Analysis (1)
app/src/screens/prove/ProofRequestStatusScreen.tsx (1)
app/src/utils/haptic/index.ts (1)
  • buttonTap (19-19)
🔇 Additional comments (3)
app/src/screens/prove/ProofRequestStatusScreen.tsx (3)

5-5: LGTM: Import optimization aligns with code splitting goals

Adding useCallback and useRef to the React import statement is a good practice that supports the performance optimizations made in this component. This change aligns well with the PR's code splitting and lazy loading objectives.


51-51: LGTM: Consistent hook usage pattern

Changing from React.useRef to direct useRef usage is consistent with the other hooks in the component and follows modern React patterns. This maintains consistency with the updated import statement.


53-59: Excellent performance optimization with useCallback

Converting onOkPress to a memoized callback prevents unnecessary re-renders of child components that receive this function as a prop. The dependency array [goHome, cleanSelfApp] is correctly specified, ensuring the callback updates when these dependencies change.

Comment on lines +135 to +137
selfApp,
countdownStarted,
countdown,
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

Verify effect dependency changes for correctness

The dependency changes need careful consideration:

  1. selfApp?.deeplinkCallbackselfApp: This broadens the dependency scope, potentially causing more frequent effect executions when any selfApp property changes, not just deeplinkCallback.

  2. Adding countdown: This creates a potential infinite loop risk since the effect can modify countdown state (line 94: setCountdown(5)), which would then retrigger the effect.

Please verify that these dependency changes don't cause performance issues or infinite loops. Consider whether selfApp?.deeplinkCallback was more appropriate as a dependency, or if countdown should be excluded from dependencies to prevent the effect from retriggering when it sets the countdown value.


🏁 Script executed:

#!/bin/bash
# Search for other useEffect patterns with countdown dependencies in the codebase
ast-grep --pattern 'useEffect($_, [$$$, countdown, $$$])'

# Search for similar patterns where an effect sets state that's also in its dependency array
rg -A 10 -B 5 "useEffect.*countdown.*setCountdown"

Length of output: 7203


Narrow the first useEffect’s dependency array to avoid unintended re-runs

I verified that in ProofRequestStatusScreen.tsx there are exactly two useEffect hooks:

  • The second one (lines 140–160) correctly depends on [countdown, selfApp?.deeplinkCallback, onOkPress] for the timer/redirect logic.
  • The first one (lines 74–138, deps at 127–138) currently lists
      currentState,
      isFocused,
      appName,
      sessionId,
      errorCode,
      reason,
      updateProofStatus,
      selfApp,
      countdownStarted,
      countdown,
    which causes the entire effect (including notifications, status update, and countdown start) to re-run whenever any property on selfApp changes or when countdownStarted/countdown update—leading to duplicate side-effects.

Recommendations:

  • Replace selfApp with the specific selfApp?.deeplinkCallback dependency.
  • Remove countdownStarted and countdown from this array (they belong only in the timer effect).
  • If you need to guard the countdown start, consider a separate useEffect or memoizing the callback.

Suggested diff:

   }, [
-    currentState,
-    isFocused,
-    appName,
-    sessionId,
-    errorCode,
-    reason,
-    updateProofStatus,
-    selfApp,
-    countdownStarted,
-    countdown,
+    currentState,
+    isFocused,
+    appName,
+    sessionId,
+    errorCode,
+    reason,
+    updateProofStatus,
+    selfApp?.deeplinkCallback,
   ]);
🤖 Prompt for AI Agents
In app/src/screens/prove/ProofRequestStatusScreen.tsx around lines 127 to 138,
the first useEffect hook's dependency array is too broad, including the entire
selfApp object and countdown-related variables, causing unintended re-runs and
duplicate side-effects. Narrow the dependencies by replacing selfApp with
selfApp?.deeplinkCallback, and remove countdownStarted and countdown from this
array. If countdown start logic needs guarding, move it to a separate useEffect
or memoize the callback to prevent unnecessary executions.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🔭 Outside diff range comments (4)
app/src/utils/proving/attest.ts (4)

113-114: Remove @ts-ignore and fix type safety issue

Using @ts-ignore suppresses TypeScript's type checking, which defeats the purpose of using TypeScript for type safety. This is particularly concerning in security-critical code handling attestation verification.

- //@ts-ignore
- if (!attestationDoc[field]) {
+ if (!(field in attestationDoc) || !attestationDoc[field as keyof AttestationDoc]) {

Alternatively, consider creating a proper type guard function to validate the attestation document structure.


176-181: Security concern: PCR0 validation bypass in development

While bypassing PCR0 validation in development mode may be convenient, this creates a significant security risk if the development flag is accidentally enabled in production or if the condition logic is compromised.

Consider implementing a more secure approach:

  • Use environment-specific configuration files instead of __DEV__
  • Add additional validation layers even in development mode
  • Log security bypasses more prominently with timestamps
- if (!isPCR0Set && !__DEV__) {
-   throw new Error('Invalid image hash');
- }
- if (__DEV__ && !isPCR0Set) {
-   console.warn('\x1b[31m%s\x1b[0m', '⚠️  WARNING: PCR0 CHECK SKIPPED ⚠️');
- }
+ if (!isPCR0Set) {
+   if (process.env.NODE_ENV === 'production') {
+     throw new Error('Invalid image hash');
+   } else {
+     console.error('\x1b[31m%s\x1b[0m', `⚠️  SECURITY WARNING: PCR0 CHECK BYPASSED IN ${process.env.NODE_ENV} MODE - ${new Date().toISOString()} ⚠️`);
+   }
+ }

228-228: Potential null pointer dereference

The non-null assertion operator (!) is used on base64.match() without proper validation, which could cause runtime errors if the regex fails to match.

- base64.match(/.{1,64}/g)!.join('\n') +
+ (base64.match(/.{1,64}/g) || []).join('\n') +

100-202: Consider refactoring large function for better maintainability

The verifyAttestation function handles multiple responsibilities (parsing, validation, certificate verification, cryptographic verification) and is over 100 lines long. This makes it harder to test, debug, and maintain.

Consider breaking it down into smaller, focused functions:

export const verifyAttestation = async (attestation: Array<number>) => {
  const attestationDoc = await parseAndValidateAttestation(attestation);
  await validateAttestationStructure(attestationDoc);
  await verifyPCR0Mapping(attestation);
  await verifyCertificateChain(attestationDoc);
  await verifyCryptographicSignature(attestation, attestationDoc);
  return true;
};

const parseAndValidateAttestation = async (attestation: Array<number>) => {
  // COSE_Sign1 parsing logic
};

const validateAttestationStructure = async (attestationDoc: AttestationDoc) => {
  // Field validation logic
};

This approach improves:

  • Testability (each function can be unit tested independently)
  • Readability and maintainability
  • Error isolation and debugging
  • Code reusability
🧹 Nitpick comments (3)
app/src/screens/misc/LoadingScreen.tsx (1)

39-207: Consider refactoring for better separation of concerns.

While the current implementation works, this component has significant responsibilities: data loading, state management, animation control, and UI rendering. Consider extracting some logic into custom hooks for better maintainability:

  • Extract passport data loading logic into a custom hook
  • Separate animation state management
  • Consider using a reducer for complex state transitions

This would improve testability and make the component easier to understand.

app/src/screens/settings/PassportDataInfoScreen.tsx (1)

18-18: Address the TODO comment for data display requirements.

The TODO comment indicates uncertainty about which metadata keys should be displayed. Consider clarifying the requirements to ensure the most relevant passport metadata is shown to users.

Would you like me to help analyze the current metadata keys and suggest which ones might be most valuable for user display?

app/src/utils/proving/attest.ts (1)

269-279: Move type definitions to top of file or separate module

The AttestationDoc type definition is placed in the middle of the implementation code. For better code organization and TypeScript best practices, consider moving type definitions to the top of the file or a separate types module.

+ // Move to top of file after imports
+ type AttestationDoc = {
+   module_id: string;
+   digest: string;
+   timestamp: number;
+   pcrs: { [key: number]: Buffer };
+   certificate: Buffer;
+   cabundle: Array<Buffer>;
+   public_key: string | null;
+   user_data: string | null;
+   nonce: string | null;
+ };
+
  // ... rest of implementation

- type AttestationDoc = {
-   module_id: string;
-   digest: string;
-   timestamp: number;
-   pcrs: { [key: number]: Buffer };
-   certificate: Buffer;
-   cabundle: Array<Buffer>;
-   public_key: string | null;
-   user_data: string | null;
-   nonce: string | null;
- };
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6eae489 and ff0c386.

📒 Files selected for processing (21)
  • .github/workflows/app.yml (1 hunks)
  • .github/workflows/general-checks.yml (2 hunks)
  • app/src/components/Disclosures.tsx (1 hunks)
  • app/src/providers/passportDataProvider.tsx (1 hunks)
  • app/src/screens/dev/MockDataScreen.tsx (1 hunks)
  • app/src/screens/dev/MockDataScreenDeepLink.tsx (1 hunks)
  • app/src/screens/misc/LoadingScreen.tsx (1 hunks)
  • app/src/screens/passport/PassportNFCScanScreen.tsx (1 hunks)
  • app/src/screens/prove/ProveScreen.tsx (1 hunks)
  • app/src/screens/settings/PassportDataInfoScreen.tsx (1 hunks)
  • app/src/stores/proof-types.ts (1 hunks)
  • app/src/stores/proofHistoryStore.ts (1 hunks)
  • app/src/stores/protocolStore.ts (1 hunks)
  • app/src/stores/selfAppStore.tsx (1 hunks)
  • app/src/utils/nfcScanner.ts (1 hunks)
  • app/src/utils/ofac.ts (1 hunks)
  • app/src/utils/proving/attest.ts (1 hunks)
  • app/src/utils/proving/provingInputs.ts (1 hunks)
  • app/src/utils/proving/provingMachine.ts (1 hunks)
  • app/src/utils/proving/provingUtils.ts (1 hunks)
  • app/src/utils/proving/validateDocument.ts (1 hunks)
✅ Files skipped from review due to trivial changes (12)
  • app/src/stores/proofHistoryStore.ts
  • app/src/utils/ofac.ts
  • app/src/stores/protocolStore.ts
  • app/src/stores/proof-types.ts
  • app/src/screens/prove/ProveScreen.tsx
  • app/src/stores/selfAppStore.tsx
  • app/src/screens/dev/MockDataScreenDeepLink.tsx
  • app/src/utils/proving/provingUtils.ts
  • app/src/screens/passport/PassportNFCScanScreen.tsx
  • app/src/components/Disclosures.tsx
  • app/src/screens/dev/MockDataScreen.tsx
  • app/src/providers/passportDataProvider.tsx
🚧 Files skipped from review as they are similar to previous changes (5)
  • .github/workflows/general-checks.yml
  • .github/workflows/app.yml
  • app/src/utils/proving/provingInputs.ts
  • app/src/utils/proving/provingMachine.ts
  • app/src/utils/proving/validateDocument.ts
🧰 Additional context used
📓 Path-based instructions (1)
app/src/**/*.{ts,tsx,js,jsx}

⚙️ CodeRabbit Configuration File

app/src/**/*.{ts,tsx,js,jsx}: Review React Native TypeScript code for:

  • Component architecture and reusability
  • State management patterns
  • Performance optimizations
  • TypeScript type safety
  • React hooks usage and dependencies
  • Navigation patterns

Files:

  • app/src/utils/nfcScanner.ts
  • app/src/utils/proving/attest.ts
  • app/src/screens/settings/PassportDataInfoScreen.tsx
  • app/src/screens/misc/LoadingScreen.tsx
🧠 Learnings (1)
app/src/screens/misc/LoadingScreen.tsx (1)

Learnt from: transphorm
PR: #795
File: app/src/screens/prove/ProveScreen.tsx:5-5
Timestamp: 2025-07-28T19:18:48.270Z
Learning: The import path '@selfxyz/common/utils/scope' is valid when the common package has a "./utils/" export mapping in package.json, even if ESLint shows resolution errors before the package is built. The package.json exports field properly maps "./utils/" to the compiled files in dist/.

🔇 Additional comments (4)
app/src/utils/nfcScanner.ts (1)

5-5: LGTM! Type-only import correctly implemented.

The change from a direct import to a type-only import for PassportData is appropriate since it's only used for type annotations. This aligns with the PR's code splitting objectives and improves bundle optimization.

app/src/screens/misc/LoadingScreen.tsx (1)

4-4: LGTM! Type-only import correctly implemented.

The change to a type-only import for PassportData is appropriate since it's only used for type annotations. This supports the code splitting optimization goals.

app/src/screens/settings/PassportDataInfoScreen.tsx (1)

4-4: LGTM! Type-only import with appropriate granular path.

The change to a type-only import for PassportMetadata is correct since it's only used for type annotations. The specific import path from the passport parsing submodule is appropriately granular and aligns with the code splitting optimization strategy.

app/src/utils/proving/attest.ts (1)

4-7: LGTM: Import refactoring improves modularity

The change from importing directly from @selfxyz/common to the more specific @selfxyz/common/constants/constants aligns with the broader refactoring effort to improve import hygiene and modularity across the codebase.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (3)
app/package.json (1)

27-29: Extract the Bundler + CocoaPods step into its own reusable script

The "cd ios && bundle install && bundle exec pod install && cd .." sequence is now duplicated in both install-app and install-app:setup. Duplicated shell fragments tend to drift over time (e.g., one gains a --repo-update or --deployment flag while the other does not), which can lead to subtle CI / local-build mismatches.

A small helper script keeps the intent DRY and makes future tweaks a one-liner:

@@
-    "install-app": "yarn install-app:setup && cd ios && bundle install && bundle exec pod install && cd .. && yarn clean:xcode-env-local",
+    "pod:install": "cd ios && bundle install --deployment && bundle exec pod install && cd ..",
+    "install-app": "yarn install-app:setup && yarn pod:install && yarn clean:xcode-env-local",
@@
-    "install-app:setup": "yarn install && yarn build:deps && cd ios && bundle install && bundle exec pod install && cd ..",
+    "install-app:setup": "yarn install && yarn build:deps && yarn pod:install",

Benefits:
• Eliminates duplication and risk of divergence
• Adds --deployment to bundle install for reproducible gem versions (optional but recommended)
• Makes future flags (--repo-update, etc.) a single-point change

app/tests/utils/proving/provingMachine.generatePayload.test.ts (2)

136-166: Test coverage could be enhanced with edge cases and error scenarios.

While the current tests cover the happy path for all three circuit types, consider adding test cases for:

  • Error handling when getSolidityPackedUserContextData fails
  • Invalid circuit types
  • Missing or malformed store state
  • Encryption failures in encryptAES256GCM

The current assertions are good but could be more comprehensive. For example, verifying the complete payload structure rather than just selected properties.

Consider adding error scenario tests:

it('should handle hash function errors gracefully', async () => {
  const mockHashError = jest.fn().mockRejectedValue(new Error('Hash failed'));
  jest.mocked(require('@selfxyz/common/utils/hash').getSolidityPackedUserContextData)
    .mockImplementation(mockHashError);
  
  useProvingStore.setState({ circuitType: 'register' });
  
  await expect(useProvingStore.getState()._generatePayload())
    .rejects.toThrow('Hash failed');
});

23-23: Consider using more realistic mock data for better test fidelity.

The fixed return value '0x1234' for getSolidityPackedUserContextData is simple but may not catch issues related to data format or length validation. Consider using a more realistic hash-like value that better represents actual function output.

-    getSolidityPackedUserContextData: jest.fn(() => '0x1234'),
+    getSolidityPackedUserContextData: jest.fn(() => '0x1234567890abcdef1234567890abcdef12345678'),
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8ae1f96 and e73d349.

⛔ Files ignored due to path filters (1)
  • app/Gemfile.lock is excluded by !**/*.lock
📒 Files selected for processing (4)
  • app/Gemfile (1 hunks)
  • app/package.json (1 hunks)
  • app/src/utils/proving/provingMachine.ts (1 hunks)
  • app/tests/utils/proving/provingMachine.generatePayload.test.ts (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • app/Gemfile
🚧 Files skipped from review as they are similar to previous changes (1)
  • app/src/utils/proving/provingMachine.ts
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{test,spec}.{ts,js,tsx,jsx}

⚙️ CodeRabbit Configuration File

**/*.{test,spec}.{ts,js,tsx,jsx}: Review test files for:

  • Test coverage completeness
  • Test case quality and edge cases
  • Mock usage appropriateness
  • Test readability and maintainability

Files:

  • app/tests/utils/proving/provingMachine.generatePayload.test.ts
🧠 Learnings (1)
app/tests/utils/proving/provingMachine.generatePayload.test.ts (1)

Learnt from: transphorm
PR: #795
File: app/src/screens/prove/ProveScreen.tsx:5-5
Timestamp: 2025-07-28T19:18:48.270Z
Learning: The import path '@selfxyz/common/utils/scope' is valid when the common package has a "./utils/" export mapping in package.json, even if ESLint shows resolution errors before the package is built. The package.json exports field properly maps "./utils/" to the compiled files in dist/.

🔇 Additional comments (2)
app/tests/utils/proving/provingMachine.generatePayload.test.ts (2)

19-25: Well-targeted mock refinement improves test specificity.

The change from mocking the entire @selfxyz/common module to specifically targeting @selfxyz/common/utils/hash is a solid improvement. This approach provides better isolation and aligns with the modularization efforts across the codebase.

The preservation of actual implementation while overriding only getSolidityPackedUserContextData follows testing best practices.


74-134: Comprehensive test setup enhances reliability.

The beforeEach setup is thorough and properly initializes all required store states. This approach ensures consistent test conditions and reduces flakiness. The use of jest.clearAllMocks() is particularly good for preventing test interdependencies.

The mock data appears realistic and covers the necessary properties for the proving machine functionality.

- uses: actions/checkout@v4
- name: Install Dependencies
uses: ./.github/actions/yarn-install
- name: Build Dependencies
Copy link
Member Author

Choose a reason for hiding this comment

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

build dependencies so yarn lint does fail when looking up the nested file paths

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
app/metro.config.cjs (1)

48-70: Consider improvements to the custom resolver implementation

While the resolver correctly handles TypeScript module resolution, consider these enhancements:

  1. The path check using string matching could be more robust
  2. Multiple resolution attempts might impact performance in large codebases
    resolveRequest: (context, moduleName, platform) => {
-     // If this is a relative import ending in .js from within the common package
-     if (moduleName.endsWith('.js') && context.originModulePath.includes('/common/src/')) {
+     // Only process .js imports from the common package source
+     const isFromCommonSrc = context.originModulePath.includes(path.join('common', 'src'));
+     if (moduleName.endsWith('.js') && isFromCommonSrc) {
        const tsModuleName = moduleName.replace(/\.js$/, '.ts');
        const tsxModuleName = moduleName.replace(/\.js$/, '.tsx');

        // Try to resolve as .ts first, then .tsx
        try {
          return context.resolveRequest(context, tsModuleName, platform);
-       } catch {
+       } catch (tsError) {
          try {
            return context.resolveRequest(context, tsxModuleName, platform);
-         } catch {
+         } catch (tsxError) {
            // Fall back to default resolution
            return context.resolveRequest(context, moduleName, platform);
          }
        }
      }

      // Default resolution for everything else
      return context.resolveRequest(context, moduleName, platform);
    },

This makes the path check more reliable and preserves error information for debugging.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b8ccef2 and 7b96b16.

📒 Files selected for processing (2)
  • app/App.tsx (2 hunks)
  • app/metro.config.cjs (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • app/App.tsx
🧰 Additional context used
🧠 Learnings (1)
app/metro.config.cjs (1)

Learnt from: transphorm
PR: #795
File: app/src/screens/prove/ProveScreen.tsx:5-5
Timestamp: 2025-07-28T19:18:48.270Z
Learning: The import path '@selfxyz/common/utils/scope' is valid when the common package has a "./utils/" export mapping in package.json, even if ESLint shows resolution errors before the package is built. The package.json exports field properly maps "./utils/" to the compiled files in dist/.

⏰ Context from checks skipped due to timeout of 300000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build
🔇 Additional comments (3)
app/metro.config.cjs (3)

34-34: Good choice for enabling code splitting

Disabling import/export transformation is the correct approach for supporting dynamic imports and code splitting. This preserves ES module syntax, which is essential for the lazy loading implementation mentioned in the PR objectives.


46-47: Appropriate resolver configuration for multi-platform support

The resolverMainFields priority order correctly prefers React Native implementations while maintaining web compatibility. Adding 'web' to platforms aligns with modern React Native apps that target multiple platforms.


15-15: Verify production bundling of @selfxyz/common alias
Before merging, please confirm that pointing Metro at the common package’s src folder won’t break your release build—since the package’s exports only reference dist. In particular:

• Ensure Metro’s transformer setup (Babel + TypeScript) is applied in production so all .ts/.tsx files under @selfxyz/common/src are correctly transpiled.
• Double-check that disableImportExportTransform doesn’t prevent any module syntax Metro needs at runtime.
• Validate your custom resolver handles index files and deep imports (e.g. @selfxyz/common/utils/foo.ts) exactly as it would when resolving the compiled dist outputs.
• Run a production-mode bundle locally (or in CI) and smoke-test any code paths that depend on common—watch for missing polyfills or runtime errors caused by skipping post-build transformations (the post-build script only emits package.json in each dist subfolder).

If you run into hiccups in CI or on-device, consider aliasing to common/dist in production or conditionally swapping the alias based on process.env.NODE_ENV.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🔭 Outside diff range comments (1)
app/android/app/build.gradle (1)

52-79: Dynamic Hermes path concatenation may mis-handle Windows path separators

String-concatenating "/" when building dynamicPath risks producing mixed separators on Windows (e.g. C:\foo/bar\baz.exe). Although the JVM usually tolerates this, Gradle’s exec task occasionally doesn’t, and it’s safer to rely on new File to join path fragments:

-        def dynamicPath = "${hermesPath}/${platformDir}/${executableName}"
+        def dynamicPath = new File(new File(hermesPath, platformDir), executableName).absolutePath

Keeps the logic portable without affecting *nix builds.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2812620 and 52ef986.

📒 Files selected for processing (3)
  • app/android/app/build.gradle (3 hunks)
  • app/android/gradle.properties (1 hunks)
  • app/metro.config.cjs (3 hunks)
✅ Files skipped from review due to trivial changes (1)
  • app/android/gradle.properties
🚧 Files skipped from review as they are similar to previous changes (1)
  • app/metro.config.cjs
🧰 Additional context used
📓 Path-based instructions (1)
app/android/**/*

⚙️ CodeRabbit Configuration File

app/android/**/*: Review Android-specific code for:

  • Platform-specific implementations
  • Performance considerations
  • Security best practices for mobile

Files:

  • app/android/app/build.gradle

Comment on lines +114 to +118
// Build optimizations
dexOptions {
javaMaxHeapSize "4g"
preDexLibraries false
}
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

dexOptions block is deprecated in AGP 7+

javaMaxHeapSize is now honoured automatically by the D8 pipeline and preDexLibraries was removed. Newer AGP versions ignore (and will soon error on) this stanza. Consider:

// AGP 7.4+
android {
    buildTypes.configureEach {
        dexing {
            jumboMode = true          // if required
        }
    }
    // Gradle JVM heap (when memory is the issue)
    tasks.withType(JavaCompile).configureEach {
        options.forkOptions.memoryMaximumSize = "4g"
    }
}

This future-proofs the build and avoids warning spam.

🤖 Prompt for AI Agents
In app/android/app/build.gradle around lines 114 to 118, the dexOptions block is
deprecated in Android Gradle Plugin 7 and above. Remove the entire dexOptions
block and instead configure dexing options inside the android buildTypes block,
such as enabling jumboMode if needed. Also, set the Java compile task's
forkOptions.memoryMaximumSize to "4g" to control heap size. This update aligns
with AGP 7+ requirements and prevents build warnings or errors.

// Dynamic path that works across different platforms (macOS, Linux, Windows)
hermesCommand = {
def hermesPath = "../node_modules/react-native/sdks/hermesc"
def hermesPath = file("${rootProject.projectDir}/../../node_modules/react-native/sdks/hermesc").absolutePath
Copy link
Member Author

Choose a reason for hiding this comment

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

fix hermes path issues when building from the android directory

"clean:android": "rm -rf android/app/build android/build",
"clean:build": "rm -rf ios/build android/app/build android/build",
"clean:ios": "rm -rf ios/Pods ios/Podfile.lock",
"clean:ios": "rm -rf ios/Pods ios/Podfile.lock && rm -rf Gemfile.lock",
Copy link
Member Author

Choose a reason for hiding this comment

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

fixes stale Gemfile.lock

"format": "yarn nice",
"ia": "yarn install-app",
"install-app": "yarn install-app:setup && cd ios && bundle exec pod install && cd .. && yarn clean:xcode-env-local",
"install-app": "yarn install-app:setup && cd ios && bundle install && bundle exec pod install && cd .. && yarn clean:xcode-env-local",
Copy link
Member Author

Choose a reason for hiding this comment

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

we need to run bundle install AND bundle exec pod install

if not, we run into weird build pipeline errors:
https://github.com/selfxyz/self/actions/runs/16587650502/job/46916055932?pr=795

@hackertron hackertron merged commit 9229c76 into dev Jul 29, 2025
10 checks passed
@hackertron hackertron deleted the codex/implement-code-splitting-for-react-native-web-app branch July 29, 2025 09:00
@hackertron hackertron restored the codex/implement-code-splitting-for-react-native-web-app branch July 29, 2025 09:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants