mirror of
https://github.com/selfxyz/self.git
synced 2026-01-07 22:04:03 -05:00
remove lazy loading (#1018)
* remove lazy loading * fix tests * formatting * fix imports and web ci * fix tests * fix building * fix * debug ci * fix web ci issue * fix * fix * fix ci * remove web render test * coderabbit feedback * fix ci * use import * fix lint * fix compiling * update lock * update lock * fix: update yarn.lock hash for @selfxyz/mobile-sdk-alpha Resolves CI error where yarn install --immutable failed due to outdated package hash. The hash changed from b2afc4 to f9ebb9. * fix: update yarn.lock hash after mobile-sdk-alpha changes - Hash changed from c0e6b9 to 0d0f72 due to package modifications - Cleaned caches and regenerated lockfile to ensure consistency - This resolves CI cache mismatch where old artifacts had stale hash * fix: update yarn.lock hash after building mobile-sdk-alpha - Final hash: 89f5a6 (includes built dist artifacts) - Built mobile-sdk-alpha to ensure package is in stable state - This should resolve CI immutable install errors * fix yarn lock and build
This commit is contained in:
30
.github/actions/cache-built-deps/action.yml
vendored
Normal file
30
.github/actions/cache-built-deps/action.yml
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
name: cache-built-deps
|
||||
description: Cache built JS artifacts (common + mobile-sdk-alpha)
|
||||
inputs:
|
||||
cache-version:
|
||||
description: Cache version string for cache key
|
||||
required: true
|
||||
outputs:
|
||||
cache-hit:
|
||||
description: Whether cache was hit during restore
|
||||
value: ${{ steps.restore.outputs.cache-hit }}
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- id: restore
|
||||
name: Restore Built Dependencies
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: |
|
||||
common/dist
|
||||
packages/mobile-sdk-alpha/dist
|
||||
key: built-deps-${{ inputs.cache-version }}-${{ hashFiles('common/**/*', 'packages/mobile-sdk-alpha/**/*', '!common/dist/**', '!packages/mobile-sdk-alpha/dist/**') }}
|
||||
fail-on-cache-miss: false
|
||||
- name: Save Built Dependencies
|
||||
if: steps.restore.outputs.cache-hit != 'true'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: |
|
||||
common/dist
|
||||
packages/mobile-sdk-alpha/dist
|
||||
key: built-deps-${{ inputs.cache-version }}-${{ hashFiles('common/**/*', 'packages/mobile-sdk-alpha/**/*', '!common/dist/**', '!packages/mobile-sdk-alpha/dist/**') }}
|
||||
142
.github/workflows/mobile-ci.yml
vendored
142
.github/workflows/mobile-ci.yml
vendored
@@ -69,28 +69,16 @@ jobs:
|
||||
cache-version: ${{ env.GH_CACHE_VERSION }}-${{ env.NODE_VERSION_SANITIZED }}
|
||||
- name: Install Dependencies
|
||||
uses: ./.github/actions/yarn-install
|
||||
- name: Restore Built Dependencies
|
||||
id: built-deps-restore
|
||||
uses: actions/cache/restore@v4
|
||||
- name: Cache Built Dependencies
|
||||
id: built-deps
|
||||
uses: ./.github/actions/cache-built-deps
|
||||
with:
|
||||
path: |
|
||||
common/dist
|
||||
packages/mobile-sdk-alpha/dist
|
||||
key: built-deps-${{ env.GH_CACHE_VERSION }}-${{ env.NODE_VERSION_SANITIZED }}-${{ hashFiles('common/**/*', 'packages/mobile-sdk-alpha/**/*', '!common/dist/**', '!packages/mobile-sdk-alpha/dist/**') }}
|
||||
fail-on-cache-miss: false
|
||||
cache-version: ${{ env.GH_CACHE_VERSION }}-${{ env.NODE_VERSION_SANITIZED }}
|
||||
- name: Build dependencies (cache miss)
|
||||
if: steps.built-deps-restore.outputs.cache-hit != 'true'
|
||||
if: steps.built-deps.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
echo "Cache miss for built dependencies. Building now..."
|
||||
yarn workspace @selfxyz/mobile-app run build:deps
|
||||
- name: Save Built Dependencies
|
||||
if: steps.built-deps-restore.outputs.cache-hit != 'true'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: |
|
||||
common/dist
|
||||
packages/mobile-sdk-alpha/dist
|
||||
key: built-deps-${{ env.GH_CACHE_VERSION }}-${{ env.NODE_VERSION_SANITIZED }}-${{ hashFiles('common/**/*', 'packages/mobile-sdk-alpha/**/*', '!common/dist/**', '!packages/mobile-sdk-alpha/dist/**') }}
|
||||
- name: Run linter
|
||||
run: yarn lint
|
||||
working-directory: ./app
|
||||
@@ -137,30 +125,70 @@ jobs:
|
||||
cache-version: ${{ env.GH_CACHE_VERSION }}-${{ env.NODE_VERSION_SANITIZED }}
|
||||
- name: Install Dependencies
|
||||
uses: ./.github/actions/yarn-install
|
||||
- name: Restore Built Dependencies
|
||||
id: built-deps-restore
|
||||
uses: actions/cache/restore@v4
|
||||
- name: Cache Built Dependencies
|
||||
id: built-deps
|
||||
uses: ./.github/actions/cache-built-deps
|
||||
with:
|
||||
path: |
|
||||
common/dist
|
||||
packages/mobile-sdk-alpha/dist
|
||||
key: built-deps-${{ env.GH_CACHE_VERSION }}-${{ env.NODE_VERSION_SANITIZED }}-${{ hashFiles('common/**/*', 'packages/mobile-sdk-alpha/**/*', '!common/dist/**', '!packages/mobile-sdk-alpha/dist/**') }}
|
||||
fail-on-cache-miss: false
|
||||
cache-version: ${{ env.GH_CACHE_VERSION }}-${{ env.NODE_VERSION_SANITIZED }}
|
||||
- name: Debug Cache Restoration
|
||||
run: |
|
||||
echo "Cache hit: ${{ steps.built-deps.outputs.cache-hit }}"
|
||||
echo "Cache key: built-deps-${{ env.GH_CACHE_VERSION }}-${{ env.NODE_VERSION_SANITIZED }}-${{ hashFiles('common/**/*', 'packages/mobile-sdk-alpha/**/*', '!common/dist/**', '!packages/mobile-sdk-alpha/dist/**') }}"
|
||||
echo "Checking if cached files exist:"
|
||||
ls -la packages/mobile-sdk-alpha/dist/ || echo "❌ mobile-sdk-alpha dist not found"
|
||||
ls -la packages/mobile-sdk-alpha/dist/cjs/ || echo "❌ mobile-sdk-alpha dist/cjs not found"
|
||||
ls -la packages/mobile-sdk-alpha/dist/cjs/index.cjs || echo "❌ mobile-sdk-alpha dist/cjs/index.cjs not found"
|
||||
ls -la common/dist/ || echo "❌ common dist not found"
|
||||
ls -la common/dist/cjs/ || echo "❌ common dist/cjs not found"
|
||||
ls -la common/dist/cjs/index.cjs || echo "❌ common dist/cjs/index.cjs not found"
|
||||
- name: Build dependencies (cache miss)
|
||||
if: steps.built-deps-restore.outputs.cache-hit != 'true'
|
||||
if: steps.built-deps.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
echo "Cache miss for built dependencies. Building now..."
|
||||
yarn workspace @selfxyz/mobile-app run build:deps
|
||||
- name: Save Built Dependencies
|
||||
if: steps.built-deps-restore.outputs.cache-hit != 'true'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: |
|
||||
common/dist
|
||||
packages/mobile-sdk-alpha/dist
|
||||
key: built-deps-${{ env.GH_CACHE_VERSION }}-${{ env.NODE_VERSION_SANITIZED }}-${{ hashFiles('common/**/*', 'packages/mobile-sdk-alpha/**/*', '!common/dist/**', '!packages/mobile-sdk-alpha/dist/**') }}
|
||||
# Verify build completed successfully
|
||||
if [ ! -f "packages/mobile-sdk-alpha/dist/cjs/index.cjs" ] || [ ! -f "common/dist/cjs/index.cjs" ]; then
|
||||
echo "❌ Build failed - required files missing after build"
|
||||
ls -la packages/mobile-sdk-alpha/dist/ || echo "mobile-sdk-alpha dist not found"
|
||||
ls -la common/dist/ || echo "common dist not found"
|
||||
exit 1
|
||||
fi
|
||||
echo "✅ Build completed successfully"
|
||||
- name: Force Build Dependencies If Missing
|
||||
run: |
|
||||
# Force build if required files don't exist, regardless of cache status
|
||||
if [ ! -f "packages/mobile-sdk-alpha/dist/cjs/index.cjs" ] || [ ! -f "common/dist/cjs/index.cjs" ]; then
|
||||
echo "❌ Required dependency files missing, forcing rebuild..."
|
||||
echo "Missing files:"
|
||||
[ ! -f "packages/mobile-sdk-alpha/dist/cjs/index.cjs" ] && echo " - packages/mobile-sdk-alpha/dist/cjs/index.cjs"
|
||||
[ ! -f "common/dist/cjs/index.cjs" ] && echo " - common/dist/cjs/index.cjs"
|
||||
yarn workspace @selfxyz/mobile-app run build:deps
|
||||
# Verify build completed successfully
|
||||
if [ ! -f "packages/mobile-sdk-alpha/dist/cjs/index.cjs" ] || [ ! -f "common/dist/cjs/index.cjs" ]; then
|
||||
echo "❌ Forced build failed - required files still missing"
|
||||
ls -la packages/mobile-sdk-alpha/ || echo "packages/mobile-sdk-alpha not found"
|
||||
ls -la packages/mobile-sdk-alpha/dist/ || echo "mobile-sdk-alpha dist not found"
|
||||
ls -la common/ || echo "common not found"
|
||||
ls -la common/dist/ || echo "common dist not found"
|
||||
exit 1
|
||||
fi
|
||||
echo "✅ Forced build completed successfully"
|
||||
else
|
||||
echo "✅ All required dependency files exist"
|
||||
fi
|
||||
- name: Test
|
||||
run: yarn test
|
||||
run: |
|
||||
# Final verification from app directory perspective
|
||||
echo "Final verification before running tests (from app directory)..."
|
||||
if [ ! -f "../packages/mobile-sdk-alpha/dist/cjs/index.cjs" ] || [ ! -f "../common/dist/cjs/index.cjs" ]; then
|
||||
echo "❌ Dependencies still not found from app directory"
|
||||
ls -la ../packages/mobile-sdk-alpha/dist/ || echo "mobile-sdk-alpha dist not found"
|
||||
ls -la ../common/dist/ || echo "common dist not found"
|
||||
exit 1
|
||||
fi
|
||||
echo "✅ All dependencies verified, running tests..."
|
||||
# Run jest through yarn to avoid the build:deps step since CI already built dependencies
|
||||
yarn jest --passWithNoTests && node --test scripts/tests/*.cjs
|
||||
working-directory: ./app
|
||||
build-ios:
|
||||
runs-on: macos-latest-large
|
||||
@@ -257,28 +285,16 @@ jobs:
|
||||
${{ runner.os }}-xcode-index-${{ env.XCODE_VERSION }}-
|
||||
- name: Install Mobile Dependencies
|
||||
uses: ./.github/actions/yarn-install
|
||||
- name: Restore Built Dependencies
|
||||
id: built-deps-restore
|
||||
uses: actions/cache/restore@v4
|
||||
- name: Cache Built Dependencies
|
||||
id: built-deps
|
||||
uses: ./.github/actions/cache-built-deps
|
||||
with:
|
||||
path: |
|
||||
common/dist
|
||||
packages/mobile-sdk-alpha/dist
|
||||
key: built-deps-${{ env.GH_CACHE_VERSION }}-${{ env.NODE_VERSION_SANITIZED }}-${{ hashFiles('common/**/*', 'packages/mobile-sdk-alpha/**/*', '!common/dist/**', '!packages/mobile-sdk-alpha/dist/**') }}
|
||||
fail-on-cache-miss: false
|
||||
cache-version: ${{ env.GH_CACHE_VERSION }}-${{ env.NODE_VERSION_SANITIZED }}
|
||||
- name: Build dependencies (cache miss)
|
||||
if: steps.built-deps-restore.outputs.cache-hit != 'true'
|
||||
if: steps.built-deps.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
echo "Cache miss for built dependencies. Building now..."
|
||||
yarn workspace @selfxyz/mobile-app run build:deps
|
||||
- name: Save Built Dependencies
|
||||
if: steps.built-deps-restore.outputs.cache-hit != 'true'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: |
|
||||
common/dist
|
||||
packages/mobile-sdk-alpha/dist
|
||||
key: built-deps-${{ env.GH_CACHE_VERSION }}-${{ env.NODE_VERSION_SANITIZED }}-${{ hashFiles('common/**/*', 'packages/mobile-sdk-alpha/**/*', '!common/dist/**', '!packages/mobile-sdk-alpha/dist/**') }}
|
||||
- name: Install Ruby Dependencies
|
||||
run: |
|
||||
echo "Installing Ruby dependencies..."
|
||||
@@ -416,28 +432,16 @@ jobs:
|
||||
run: sdkmanager "ndk;${{ env.ANDROID_NDK_VERSION }}"
|
||||
- name: Install Mobile Dependencies
|
||||
uses: ./.github/actions/yarn-install
|
||||
- name: Restore Built Dependencies
|
||||
id: built-deps-restore
|
||||
uses: actions/cache/restore@v4
|
||||
- name: Cache Built Dependencies
|
||||
id: built-deps
|
||||
uses: ./.github/actions/cache-built-deps
|
||||
with:
|
||||
path: |
|
||||
common/dist
|
||||
packages/mobile-sdk-alpha/dist
|
||||
key: built-deps-${{ env.GH_CACHE_VERSION }}-${{ env.NODE_VERSION_SANITIZED }}-${{ hashFiles('common/**/*', 'packages/mobile-sdk-alpha/**/*', '!common/dist/**', '!packages/mobile-sdk-alpha/dist/**') }}
|
||||
fail-on-cache-miss: false
|
||||
cache-version: ${{ env.GH_CACHE_VERSION }}-${{ env.NODE_VERSION_SANITIZED }}
|
||||
- name: Build dependencies (cache miss)
|
||||
if: steps.built-deps-restore.outputs.cache-hit != 'true'
|
||||
if: steps.built-deps.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
echo "Cache miss for built dependencies. Building now..."
|
||||
yarn workspace @selfxyz/mobile-app run build:deps
|
||||
- name: Save Built Dependencies
|
||||
if: steps.built-deps-restore.outputs.cache-hit != 'true'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: |
|
||||
common/dist
|
||||
packages/mobile-sdk-alpha/dist
|
||||
key: built-deps-${{ env.GH_CACHE_VERSION }}-${{ env.NODE_VERSION_SANITIZED }}-${{ hashFiles('common/**/*', 'packages/mobile-sdk-alpha/**/*', '!common/dist/**', '!packages/mobile-sdk-alpha/dist/**') }}
|
||||
- name: Build Android (with AAPT2 symlink fix)
|
||||
run: yarn android:ci
|
||||
working-directory: ./app
|
||||
|
||||
2
.github/workflows/web.yml
vendored
2
.github/workflows/web.yml
vendored
@@ -22,4 +22,4 @@ jobs:
|
||||
shell: bash
|
||||
run: yarn workspace @selfxyz/common build
|
||||
- name: Build web app
|
||||
run: yarn web:build
|
||||
run: yarn workspace @selfxyz/mobile-app web:build
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
nodeLinker: node-modules
|
||||
enableGlobalCache: true
|
||||
|
||||
@@ -38,6 +38,18 @@ module.exports = {
|
||||
typescript: {
|
||||
alwaysTryTypes: true,
|
||||
project: './tsconfig.json',
|
||||
extensions: [
|
||||
'.ts',
|
||||
'.tsx',
|
||||
'.native.ts',
|
||||
'.native.tsx',
|
||||
'.web.ts',
|
||||
'.web.tsx',
|
||||
'.ios.ts',
|
||||
'.ios.tsx',
|
||||
'.android.ts',
|
||||
'.android.tsx',
|
||||
],
|
||||
},
|
||||
},
|
||||
'import/ignore': ['react-native'],
|
||||
|
||||
@@ -25,7 +25,7 @@ GEM
|
||||
artifactory (3.0.17)
|
||||
atomos (0.1.3)
|
||||
aws-eventstream (1.4.0)
|
||||
aws-partitions (1.1155.0)
|
||||
aws-partitions (1.1156.0)
|
||||
aws-sdk-core (3.232.0)
|
||||
aws-eventstream (~> 1, >= 1.3.0)
|
||||
aws-partitions (~> 1, >= 1.992.0)
|
||||
@@ -37,7 +37,7 @@ GEM
|
||||
aws-sdk-kms (1.112.0)
|
||||
aws-sdk-core (~> 3, >= 3.231.0)
|
||||
aws-sigv4 (~> 1.5)
|
||||
aws-sdk-s3 (1.198.0)
|
||||
aws-sdk-s3 (1.199.0)
|
||||
aws-sdk-core (~> 3, >= 3.231.0)
|
||||
aws-sdk-kms (~> 1)
|
||||
aws-sigv4 (~> 1.5)
|
||||
@@ -256,7 +256,7 @@ GEM
|
||||
trailblazer-option (>= 0.1.1, < 0.2.0)
|
||||
uber (< 0.2.0)
|
||||
retriable (3.1.2)
|
||||
rexml (3.4.2)
|
||||
rexml (3.4.3)
|
||||
rouge (3.28.0)
|
||||
ruby-macho (2.5.1)
|
||||
ruby2_keywords (0.0.5)
|
||||
|
||||
@@ -12,7 +12,6 @@ import com.facebook.react.ReactActivityDelegate
|
||||
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled
|
||||
import com.facebook.react.defaults.DefaultReactActivityDelegate
|
||||
import io.tradle.nfc.RNPassportReaderModule
|
||||
import com.selfxyz.selfSDK.RNSelfPassportReaderModule
|
||||
|
||||
class MainActivity : ReactActivity() {
|
||||
/**
|
||||
|
||||
@@ -15,7 +15,6 @@ import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint
|
||||
import com.facebook.react.defaults.DefaultReactNativeHost
|
||||
import com.facebook.soloader.SoLoader
|
||||
import com.facebook.react.soloader.OpenSourceMergedSoMapping
|
||||
import com.selfxyz.selfSDK.RNSelfPassportReaderPackage
|
||||
|
||||
class MainApplication : Application(), ReactApplication {
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ module.exports = {
|
||||
preset: 'react-native',
|
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
|
||||
transformIgnorePatterns: [
|
||||
'node_modules/(?!(react-native|@react-native|@react-navigation|@react-native-community|@segment/analytics-react-native|@openpassport|react-native-keychain|react-native-check-version|react-native-nfc-manager|react-native-passport-reader|react-native-gesture-handler|uuid|@stablelib|@react-native-google-signin|react-native-cloud-storage|@react-native-clipboard|@react-native-firebase|@selfxyz)/)',
|
||||
'node_modules/(?!(react-native|@react-native|@react-navigation|@react-native-community|@segment/analytics-react-native|@openpassport|react-native-keychain|react-native-check-version|react-native-nfc-manager|react-native-passport-reader|react-native-gesture-handler|uuid|@stablelib|@react-native-google-signin|react-native-cloud-storage|@react-native-clipboard|@react-native-firebase|@selfxyz|@sentry)/)',
|
||||
],
|
||||
setupFiles: ['<rootDir>/jest.setup.js'],
|
||||
testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.[jt]sx?$',
|
||||
|
||||
@@ -157,6 +157,7 @@
|
||||
"@testing-library/react-native": "^13.3.3",
|
||||
"@tsconfig/react-native": "^3.0.6",
|
||||
"@types/add": "^2",
|
||||
"@types/dompurify": "^3.2.0",
|
||||
"@types/elliptic": "^6",
|
||||
"@types/jest": "^29.5.14",
|
||||
"@types/node-forge": "^1.3.14",
|
||||
@@ -170,6 +171,7 @@
|
||||
"@typescript-eslint/parser": "^8.39.0",
|
||||
"@vitejs/plugin-react-swc": "^3.10.2",
|
||||
"babel-plugin-module-resolver": "^5.0.2",
|
||||
"dompurify": "^3.2.6",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-config-prettier": "10.1.8",
|
||||
"eslint-import-resolver-typescript": "^3.7.0",
|
||||
|
||||
18
app/src/components/homeScreen/SvgXmlWrapper.native.tsx
Normal file
18
app/src/components/homeScreen/SvgXmlWrapper.native.tsx
Normal file
@@ -0,0 +1,18 @@
|
||||
// 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 React, { forwardRef } from 'react';
|
||||
import type { StyleProp, ViewStyle } from 'react-native';
|
||||
import { SvgXml as RNSvgXml } from 'react-native-svg';
|
||||
|
||||
type Props = {
|
||||
xml: string;
|
||||
width?: number;
|
||||
height?: number;
|
||||
style?: StyleProp<ViewStyle>;
|
||||
};
|
||||
|
||||
export const SvgXml = forwardRef<any, Props>((p, _ref) => <RNSvgXml {...p} />);
|
||||
SvgXml.displayName = 'SvgXml';
|
||||
export default SvgXml;
|
||||
8
app/src/components/homeScreen/SvgXmlWrapper.tsx
Normal file
8
app/src/components/homeScreen/SvgXmlWrapper.tsx
Normal file
@@ -0,0 +1,8 @@
|
||||
// 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.
|
||||
|
||||
// Re-export from the native version - Metro resolver will automatically
|
||||
// pick the appropriate platform-specific file (.web.tsx or .native.tsx)
|
||||
export { SvgXml } from '@/components/homeScreen/SvgXmlWrapper.native';
|
||||
export { default } from '@/components/homeScreen/SvgXmlWrapper.native';
|
||||
37
app/src/components/homeScreen/SvgXmlWrapper.web.tsx
Normal file
37
app/src/components/homeScreen/SvgXmlWrapper.web.tsx
Normal file
@@ -0,0 +1,37 @@
|
||||
// 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 DOMPurify from 'dompurify';
|
||||
import React, { createElement, forwardRef } from 'react';
|
||||
|
||||
type Props = {
|
||||
xml: string;
|
||||
width?: number;
|
||||
height?: number;
|
||||
style?: React.CSSProperties;
|
||||
} & React.HTMLAttributes<HTMLDivElement>;
|
||||
|
||||
export const SvgXml = forwardRef<HTMLDivElement, Props>(
|
||||
({ xml, width, height, style, ...props }, ref) => {
|
||||
// Initialize DOMPurify for web browser environment
|
||||
const purify = DOMPurify(window);
|
||||
const safe = purify.sanitize(xml, {
|
||||
USE_PROFILES: { svg: true, svgFilters: true },
|
||||
});
|
||||
return createElement('div', {
|
||||
ref,
|
||||
style: {
|
||||
width: width || 'auto',
|
||||
height: height || 'auto',
|
||||
display: 'inline-block',
|
||||
...style,
|
||||
},
|
||||
dangerouslySetInnerHTML: { __html: safe },
|
||||
...props,
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
SvgXml.displayName = 'SvgXml';
|
||||
export default SvgXml;
|
||||
@@ -4,18 +4,18 @@
|
||||
|
||||
import React, { useCallback, useState } from 'react';
|
||||
import { Dimensions, Pressable } from 'react-native';
|
||||
import { SvgXml } from 'react-native-svg';
|
||||
import { Button, Image, Separator, Text, XStack, YStack } from 'tamagui';
|
||||
import { useFocusEffect } from '@react-navigation/native';
|
||||
|
||||
import {
|
||||
attributeToPosition,
|
||||
attributeToPosition_ID,
|
||||
formatMrz,
|
||||
PassportData,
|
||||
} from '@selfxyz/common/dist/esm';
|
||||
import { pad } from '@selfxyz/common/dist/esm/src/utils/passports/passport';
|
||||
} from '@selfxyz/common/constants';
|
||||
import { PassportData } from '@selfxyz/common/types';
|
||||
import { formatMrz } from '@selfxyz/common/utils';
|
||||
import { pad } from '@selfxyz/common/utils/passports/passport';
|
||||
|
||||
import { SvgXml } from '@/components/homeScreen/SvgXmlWrapper';
|
||||
import EPassport from '@/images/icons/epassport.svg';
|
||||
import LogoGray from '@/images/logo_gray.svg';
|
||||
import LogoInversed from '@/images/logo_inversed.svg';
|
||||
|
||||
35
app/src/mocks/react-native-community-blur.ts
Normal file
35
app/src/mocks/react-native-community-blur.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
// 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 React, { createElement, forwardRef } from 'react';
|
||||
|
||||
type BlurViewProps = React.HTMLAttributes<HTMLDivElement> & {
|
||||
blurType?: string;
|
||||
blurAmount?: number;
|
||||
reducedTransparencyFallbackColor?: string;
|
||||
pointerEvents?: 'auto' | 'none';
|
||||
};
|
||||
|
||||
// Mock BlurView component for web builds
|
||||
export const BlurView = forwardRef<HTMLDivElement, BlurViewProps>(
|
||||
({ children, style, pointerEvents, blurAmount, ...props }, ref) => {
|
||||
return createElement(
|
||||
'div',
|
||||
{
|
||||
ref,
|
||||
style: {
|
||||
backgroundColor: 'rgba(255, 255, 255, 0.1)',
|
||||
backdropFilter: `blur(${typeof blurAmount === 'number' ? blurAmount : 10}px)`,
|
||||
pointerEvents: pointerEvents,
|
||||
...style,
|
||||
},
|
||||
// Do not spread pointerEvents as a DOM attribute
|
||||
...props,
|
||||
},
|
||||
children,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
BlurView.displayName = 'BlurView';
|
||||
67
app/src/mocks/react-native-svg.ts
Normal file
67
app/src/mocks/react-native-svg.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
// 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 React from 'react';
|
||||
|
||||
export const Circle = React.forwardRef<
|
||||
SVGCircleElement,
|
||||
React.SVGProps<SVGCircleElement>
|
||||
>((props, ref) => {
|
||||
return React.createElement('circle', { ref, ...props });
|
||||
});
|
||||
|
||||
Circle.displayName = 'Circle';
|
||||
|
||||
export const Path = React.forwardRef<
|
||||
SVGPathElement,
|
||||
React.SVGProps<SVGPathElement>
|
||||
>((props, ref) => {
|
||||
return React.createElement('path', { ref, ...props });
|
||||
});
|
||||
|
||||
Path.displayName = 'Path';
|
||||
|
||||
export const Rect = React.forwardRef<
|
||||
SVGRectElement,
|
||||
React.SVGProps<SVGRectElement>
|
||||
>((props, ref) => {
|
||||
return React.createElement('rect', { ref, ...props });
|
||||
});
|
||||
|
||||
Rect.displayName = 'Rect';
|
||||
|
||||
// Re-export other common SVG components that might be used
|
||||
export const Svg = React.forwardRef<
|
||||
SVGSVGElement,
|
||||
React.SVGProps<SVGSVGElement>
|
||||
>((props, ref) => {
|
||||
return React.createElement('svg', { ref, ...props });
|
||||
});
|
||||
|
||||
Svg.displayName = 'Svg';
|
||||
|
||||
// Mock SvgXml component for web builds
|
||||
export const SvgXml = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
{
|
||||
xml: string;
|
||||
width?: number;
|
||||
height?: number;
|
||||
style?: React.CSSProperties;
|
||||
}
|
||||
>(({ xml, width, height, style, ...props }, ref) => {
|
||||
return React.createElement('div', {
|
||||
ref,
|
||||
style: {
|
||||
width: width || 'auto',
|
||||
height: height || 'auto',
|
||||
display: 'inline-block',
|
||||
...style,
|
||||
},
|
||||
dangerouslySetInnerHTML: { __html: xml },
|
||||
...props,
|
||||
});
|
||||
});
|
||||
|
||||
SvgXml.displayName = 'SvgXml';
|
||||
@@ -2,17 +2,13 @@
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
// NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE.
|
||||
|
||||
import { lazy } from 'react';
|
||||
import type { NativeStackNavigationOptions } from '@react-navigation/native-stack';
|
||||
|
||||
import { ProgressNavBar } from '@/components/NavBar';
|
||||
import { shouldShowAesopRedesign } from '@/hooks/useAesopRedesign';
|
||||
import DocumentOnboardingScreen from '@/screens/aesop/DocumentOnboardingScreen';
|
||||
import { white } from '@/utils/colors';
|
||||
|
||||
const DocumentOnboardingScreen = lazy(
|
||||
() => import('@/screens/aesop/DocumentOnboardingScreen'),
|
||||
);
|
||||
|
||||
const aesopScreens = {
|
||||
DocumentOnboarding: {
|
||||
screen: DocumentOnboardingScreen,
|
||||
|
||||
@@ -2,26 +2,16 @@
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
// NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE.
|
||||
|
||||
import { lazy } from 'react';
|
||||
import type { NativeStackNavigationOptions } from '@react-navigation/native-stack';
|
||||
|
||||
import CreateMockScreen from '@/screens/dev/CreateMockScreen';
|
||||
import CreateMockScreenDeepLink from '@/screens/dev/CreateMockScreenDeepLink';
|
||||
import DevFeatureFlagsScreen from '@/screens/dev/DevFeatureFlagsScreen';
|
||||
import DevHapticFeedbackScreen from '@/screens/dev/DevHapticFeedbackScreen';
|
||||
import DevPrivateKeyScreen from '@/screens/dev/DevPrivateKeyScreen';
|
||||
import DevSettingsScreen from '@/screens/dev/DevSettingsScreen';
|
||||
import { black, white } from '@/utils/colors';
|
||||
|
||||
const DevFeatureFlagsScreen = lazy(
|
||||
() => import('@/screens/dev/DevFeatureFlagsScreen'),
|
||||
);
|
||||
const DevHapticFeedbackScreen = lazy(
|
||||
() => import('@/screens/dev/DevHapticFeedbackScreen'),
|
||||
);
|
||||
const DevPrivateKeyScreen = lazy(
|
||||
() => import('@/screens/dev/DevPrivateKeyScreen'),
|
||||
);
|
||||
const DevSettingsScreen = lazy(() => import('@/screens/dev/DevSettingsScreen'));
|
||||
const CreateMockScreen = lazy(() => import('@/screens/dev/CreateMockScreen'));
|
||||
const CreateMockScreenDeepLink = lazy(
|
||||
() => import('@/screens/dev/CreateMockScreenDeepLink'),
|
||||
);
|
||||
|
||||
const devHeaderOptions: NativeStackNavigationOptions = {
|
||||
headerStyle: {
|
||||
backgroundColor: black,
|
||||
|
||||
@@ -2,30 +2,15 @@
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
// NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE.
|
||||
|
||||
import { lazy } from 'react';
|
||||
import type { NativeStackNavigationOptions } from '@react-navigation/native-stack';
|
||||
|
||||
const DocumentCameraScreen = lazy(
|
||||
() => import('@/screens/document/DocumentCameraScreen'),
|
||||
);
|
||||
const DocumentCameraTroubleScreen = lazy(
|
||||
() => import('@/screens/document/DocumentCameraTroubleScreen'),
|
||||
);
|
||||
const DocumentNFCScanScreen = lazy(
|
||||
() => import('@/screens/document/DocumentNFCScanScreen'),
|
||||
);
|
||||
const DocumentNFCTroubleScreen = lazy(
|
||||
() => import('@/screens/document/DocumentNFCTroubleScreen'),
|
||||
);
|
||||
const DocumentOnboardingScreen = lazy(
|
||||
() => import('@/screens/document/DocumentOnboardingScreen'),
|
||||
);
|
||||
const UnsupportedDocumentScreen = lazy(
|
||||
() => import('@/screens/document/UnsupportedDocumentScreen'),
|
||||
);
|
||||
const DocumentNFCMethodSelectionScreen = lazy(
|
||||
() => import('@/screens/document/DocumentNFCMethodSelectionScreen'),
|
||||
);
|
||||
import DocumentCameraScreen from '@/screens/document/DocumentCameraScreen';
|
||||
import DocumentCameraTroubleScreen from '@/screens/document/DocumentCameraTroubleScreen';
|
||||
import DocumentNFCMethodSelectionScreen from '@/screens/document/DocumentNFCMethodSelectionScreen';
|
||||
import DocumentNFCScanScreen from '@/screens/document/DocumentNFCScanScreen';
|
||||
import DocumentNFCTroubleScreen from '@/screens/document/DocumentNFCTroubleScreen';
|
||||
import DocumentOnboardingScreen from '@/screens/document/DocumentOnboardingScreen';
|
||||
import UnsupportedDocumentScreen from '@/screens/document/UnsupportedDocumentScreen';
|
||||
|
||||
const documentScreens = {
|
||||
DocumentCamera: {
|
||||
|
||||
@@ -2,20 +2,15 @@
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
// NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE.
|
||||
|
||||
import { lazy } from 'react';
|
||||
import type { NativeStackNavigationOptions } from '@react-navigation/native-stack';
|
||||
|
||||
import { HomeNavBar, IdDetailsNavBar } from '@/components/NavBar';
|
||||
import DisclaimerScreen from '@/screens/home/DisclaimerScreen';
|
||||
import HomeScreen from '@/screens/home/HomeScreen';
|
||||
import IdDetailsScreen from '@/screens/home/IdDetailsScreen';
|
||||
import ProofHistoryDetailScreen from '@/screens/home/ProofHistoryDetailScreen';
|
||||
import ProofHistoryScreen from '@/screens/home/ProofHistoryScreen';
|
||||
|
||||
const DisclaimerScreen = lazy(() => import('@/screens/home/DisclaimerScreen'));
|
||||
const HomeScreen = lazy(() => import('@/screens/home/HomeScreen'));
|
||||
const ProofHistoryDetailScreen = lazy(
|
||||
() => import('@/screens/home/ProofHistoryDetailScreen'),
|
||||
);
|
||||
const ProofHistoryScreen = lazy(
|
||||
() => import('@/screens/home/ProofHistoryScreen'),
|
||||
);
|
||||
const IdDetailsScreen = lazy(() => import('@/screens/home/IdDetailsScreen'));
|
||||
const homeScreens = {
|
||||
Disclaimer: {
|
||||
screen: DisclaimerScreen,
|
||||
|
||||
@@ -2,10 +2,9 @@
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
// NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE.
|
||||
|
||||
import React, { Suspense, useEffect } from 'react';
|
||||
import { Platform, View } from 'react-native';
|
||||
import React, { useEffect } from 'react';
|
||||
import { Platform } from 'react-native';
|
||||
import { GestureHandlerRootView } from 'react-native-gesture-handler';
|
||||
import { Text } from 'tamagui';
|
||||
import type { StaticParamList } from '@react-navigation/native';
|
||||
import {
|
||||
createNavigationContainerRef,
|
||||
@@ -63,17 +62,6 @@ declare global {
|
||||
const { trackScreenView } = analytics();
|
||||
const Navigation = createStaticNavigation(AppNavigation);
|
||||
|
||||
const SuspenseFallback = () => {
|
||||
if (Platform.OS === 'web') {
|
||||
return <div>Loading...</div>;
|
||||
}
|
||||
return (
|
||||
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
|
||||
<Text>Loading...</Text>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const NavigationWithTracking = () => {
|
||||
const trackScreen = () => {
|
||||
const currentRoute = navigationRef.getCurrentRoute();
|
||||
@@ -96,9 +84,7 @@ const NavigationWithTracking = () => {
|
||||
|
||||
return (
|
||||
<GestureHandlerRootView>
|
||||
<Suspense fallback={<SuspenseFallback />}>
|
||||
<Navigation ref={navigationRef} onStateChange={trackScreen} />
|
||||
</Suspense>
|
||||
<Navigation ref={navigationRef} onStateChange={trackScreen} />
|
||||
</GestureHandlerRootView>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
// 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';
|
||||
|
||||
// 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>>(
|
||||
factory: () => Promise<{ default: T }>,
|
||||
) {
|
||||
const Component = lazy(factory) as LazyExoticComponent<T> & {
|
||||
preload: () => Promise<{ default: T }>;
|
||||
};
|
||||
Component.preload = factory;
|
||||
return Component;
|
||||
}
|
||||
@@ -2,25 +2,15 @@
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
// NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE.
|
||||
|
||||
import { lazy } from 'react';
|
||||
import type { NativeStackNavigationOptions } from '@react-navigation/native-stack';
|
||||
|
||||
import ConfirmBelongingScreen from '@/screens/prove/ConfirmBelongingScreen';
|
||||
import ProofRequestStatusScreen from '@/screens/prove/ProofRequestStatusScreen';
|
||||
import ProveScreen from '@/screens/prove/ProveScreen';
|
||||
import QRCodeTroubleScreen from '@/screens/prove/QRCodeTroubleScreen';
|
||||
import QRCodeViewFinderScreen from '@/screens/prove/QRCodeViewFinderScreen';
|
||||
import { black, white } from '@/utils/colors';
|
||||
|
||||
const ConfirmBelongingScreen = lazy(
|
||||
() => import('@/screens/prove/ConfirmBelongingScreen'),
|
||||
);
|
||||
const ProofRequestStatusScreen = lazy(
|
||||
() => import('@/screens/prove/ProofRequestStatusScreen'),
|
||||
);
|
||||
const ProveScreen = lazy(() => import('@/screens/prove/ProveScreen'));
|
||||
const QRCodeTroubleScreen = lazy(
|
||||
() => import('@/screens/prove/QRCodeTroubleScreen'),
|
||||
);
|
||||
const QRCodeViewFinderScreen = lazy(
|
||||
() => import('@/screens/prove/QRCodeViewFinderScreen'),
|
||||
);
|
||||
|
||||
const proveScreens = {
|
||||
ConfirmBelonging: {
|
||||
screen: ConfirmBelongingScreen,
|
||||
|
||||
@@ -2,30 +2,16 @@
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
// NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE.
|
||||
|
||||
import { lazy } from 'react';
|
||||
import type { NativeStackNavigationOptions } from '@react-navigation/native-stack';
|
||||
|
||||
import AccountRecoveryChoiceScreen from '@/screens/recovery/AccountRecoveryChoiceScreen';
|
||||
import AccountRecoveryScreen from '@/screens/recovery/AccountRecoveryScreen';
|
||||
import AccountVerifiedSuccessScreen from '@/screens/recovery/AccountVerifiedSuccessScreen';
|
||||
import DocumentDataNotFound from '@/screens/recovery/DocumentDataNotFoundScreen';
|
||||
import RecoverWithPhraseScreen from '@/screens/recovery/RecoverWithPhraseScreen';
|
||||
import SaveRecoveryPhraseScreen from '@/screens/recovery/SaveRecoveryPhraseScreen';
|
||||
import { black, slate300 } from '@/utils/colors';
|
||||
|
||||
const AccountRecoveryChoiceScreen = lazy(
|
||||
() => import('@/screens/recovery/AccountRecoveryChoiceScreen'),
|
||||
);
|
||||
const AccountRecoveryScreen = lazy(
|
||||
() => import('@/screens/recovery/AccountRecoveryScreen'),
|
||||
);
|
||||
const AccountVerifiedSuccessScreen = lazy(
|
||||
() => import('@/screens/recovery/AccountVerifiedSuccessScreen'),
|
||||
);
|
||||
const DocumentDataNotFound = lazy(
|
||||
() => import('@/screens/recovery/DocumentDataNotFoundScreen'),
|
||||
);
|
||||
const RecoverWithPhraseScreen = lazy(
|
||||
() => import('@/screens/recovery/RecoverWithPhraseScreen'),
|
||||
);
|
||||
const SaveRecoveryPhraseScreen = lazy(
|
||||
() => import('@/screens/recovery/SaveRecoveryPhraseScreen'),
|
||||
);
|
||||
|
||||
const recoveryScreens = {
|
||||
AccountRecovery: {
|
||||
screen: AccountRecoveryScreen,
|
||||
|
||||
@@ -2,12 +2,9 @@
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
// NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE.
|
||||
|
||||
import { lazy } from 'react';
|
||||
import type { NativeStackNavigationOptions } from '@react-navigation/native-stack';
|
||||
|
||||
const DocumentDataNotFound = lazy(
|
||||
() => import('@/screens/recovery/DocumentDataNotFoundScreen'),
|
||||
);
|
||||
import DocumentDataNotFound from '@/screens/recovery/DocumentDataNotFoundScreen';
|
||||
|
||||
const recoveryScreens = {
|
||||
DocumentDataNotFound: {
|
||||
|
||||
@@ -2,25 +2,15 @@
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
// NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE.
|
||||
|
||||
import { lazy } from 'react';
|
||||
import type { NativeStackNavigationOptions } from '@react-navigation/native-stack';
|
||||
|
||||
import CloudBackupScreen from '@/screens/settings/CloudBackupScreen';
|
||||
import DocumentDataInfoScreen from '@/screens/settings/DocumentDataInfoScreen';
|
||||
import ManageDocumentsScreen from '@/screens/settings/ManageDocumentsScreen';
|
||||
import SettingsScreen from '@/screens/settings/SettingsScreen';
|
||||
import ShowRecoveryPhraseScreen from '@/screens/settings/ShowRecoveryPhraseScreen';
|
||||
import { black, slate300, white } from '@/utils/colors';
|
||||
|
||||
const CloudBackupScreen = lazy(
|
||||
() => import('@/screens/settings/CloudBackupScreen'),
|
||||
);
|
||||
const ManageDocumentsScreen = lazy(
|
||||
() => import('@/screens/settings/ManageDocumentsScreen'),
|
||||
);
|
||||
const DocumentDataInfoScreen = lazy(
|
||||
() => import('@/screens/settings/DocumentDataInfoScreen'),
|
||||
);
|
||||
const SettingsScreen = lazy(() => import('@/screens/settings/SettingsScreen'));
|
||||
const ShowRecoveryPhraseScreen = lazy(
|
||||
() => import('@/screens/settings/ShowRecoveryPhraseScreen'),
|
||||
);
|
||||
|
||||
const settingsScreens = {
|
||||
CloudBackupSettings: {
|
||||
screen: CloudBackupScreen,
|
||||
|
||||
@@ -2,19 +2,13 @@
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
// NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE.
|
||||
|
||||
import { lazy } from 'react';
|
||||
import type { NativeStackNavigationOptions } from '@react-navigation/native-stack';
|
||||
|
||||
import DocumentDataInfoScreen from '@/screens/settings/DocumentDataInfoScreen';
|
||||
import ManageDocumentsScreen from '@/screens/settings/ManageDocumentsScreen';
|
||||
import SettingsScreen from '@/screens/settings/SettingsScreen';
|
||||
import { black, white } from '@/utils/colors';
|
||||
|
||||
const ManageDocumentsScreen = lazy(
|
||||
() => import('@/screens/settings/ManageDocumentsScreen'),
|
||||
);
|
||||
const DocumentDataInfoScreen = lazy(
|
||||
() => import('@/screens/settings/DocumentDataInfoScreen'),
|
||||
);
|
||||
const SettingsScreen = lazy(() => import('@/screens/settings/SettingsScreen'));
|
||||
|
||||
const settingsScreens = {
|
||||
ManageDocuments: {
|
||||
screen: ManageDocumentsScreen,
|
||||
|
||||
@@ -2,22 +2,16 @@
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
// NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE.
|
||||
|
||||
import React, { lazy } from 'react';
|
||||
import React from 'react';
|
||||
import { SystemBars } from 'react-native-edge-to-edge';
|
||||
import type { NativeStackNavigationOptions } from '@react-navigation/native-stack';
|
||||
|
||||
// Important: SplashScreen is imported directly and not lazy-loaded.
|
||||
// This is because it's used as a fallback for the Suspense boundary in the root navigator,
|
||||
// ensuring it's immediately available at startup.
|
||||
import DeferredLinkingInfoScreen from '@/screens/system/DeferredLinkingInfoScreen';
|
||||
import LaunchScreen from '@/screens/system/LaunchScreen';
|
||||
import LoadingScreen from '@/screens/system/Loading';
|
||||
import ModalScreen from '@/screens/system/ModalScreen';
|
||||
import SplashScreen from '@/screens/system/SplashScreen';
|
||||
|
||||
const LaunchScreen = lazy(() => import('@/screens/system/LaunchScreen'));
|
||||
const LoadingScreen = lazy(() => import('@/screens/system/Loading'));
|
||||
const ModalScreen = lazy(() => import('@/screens/system/ModalScreen'));
|
||||
const DeferredLinkingInfoScreen = lazy(
|
||||
() => import('@/screens/system/DeferredLinkingInfoScreen'),
|
||||
);
|
||||
|
||||
const systemScreens = {
|
||||
Launch: {
|
||||
screen: LaunchScreen,
|
||||
|
||||
@@ -12,8 +12,8 @@ import {
|
||||
usePreventRemove,
|
||||
} from '@react-navigation/native';
|
||||
|
||||
import { PassportData } from '@selfxyz/common/dist/esm';
|
||||
import { DocumentCatalog } from '@selfxyz/common/dist/esm/src/utils/types';
|
||||
import { PassportData } from '@selfxyz/common/types';
|
||||
import { DocumentCatalog } from '@selfxyz/common/utils/types';
|
||||
import { DocumentMetadata, useSelfClient } from '@selfxyz/mobile-sdk-alpha';
|
||||
import { ProofEvents } from '@selfxyz/mobile-sdk-alpha/constants/analytics';
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@ import { Button, Text, XStack, YStack, ZStack } from 'tamagui';
|
||||
import { BlurView } from '@react-native-community/blur';
|
||||
import { useNavigation, useRoute } from '@react-navigation/native';
|
||||
|
||||
import { DocumentCatalog } from '@selfxyz/common/dist/esm/src/utils/types';
|
||||
import { PassportData } from '@selfxyz/common/types';
|
||||
import { DocumentCatalog } from '@selfxyz/common/utils/types';
|
||||
|
||||
import IdCardLayout from '@/components/homeScreen/idCard';
|
||||
import { usePassport } from '@/providers/passportDataProvider';
|
||||
|
||||
@@ -28,6 +28,7 @@ describe('navigation', () => {
|
||||
'DocumentNFCTrouble',
|
||||
'DocumentOnboarding',
|
||||
'Home',
|
||||
'IdDetails',
|
||||
'Launch',
|
||||
'Loading',
|
||||
'ManageDocuments',
|
||||
|
||||
@@ -1,176 +0,0 @@
|
||||
// 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.
|
||||
|
||||
/**
|
||||
* @jest-environment node
|
||||
*/
|
||||
|
||||
// Override global error handling to prevent circular references
|
||||
import { execSync, spawn } from 'child_process';
|
||||
import { afterAll, beforeAll, describe, expect, test } from '@jest/globals';
|
||||
|
||||
const originalError = global.Error;
|
||||
global.Error = class SafeError extends originalError {
|
||||
constructor(...args: any[]) {
|
||||
super(...args);
|
||||
// Ensure no circular references are added to error objects
|
||||
Object.defineProperty(this, 'error', {
|
||||
value: undefined,
|
||||
writable: false,
|
||||
enumerable: false,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// Ensure fetch is available (Node.js 18+ has built-in fetch)
|
||||
if (typeof fetch === 'undefined') {
|
||||
throw new Error(
|
||||
'fetch is not available. This test requires Node.js 18+ with built-in fetch support.',
|
||||
);
|
||||
}
|
||||
|
||||
// Increase default timeouts for build and page load
|
||||
const BUILD_TIMEOUT = 120_000;
|
||||
const PAGE_LOAD_TIMEOUT = 10_000;
|
||||
const PREVIEW_URL = 'http://localhost:4173';
|
||||
|
||||
describe('Web Build and Render', () => {
|
||||
let previewProcess: ReturnType<typeof spawn> | undefined;
|
||||
|
||||
beforeAll(async () => {
|
||||
// Build the web app
|
||||
execSync('yarn web:build', {
|
||||
stdio: 'inherit',
|
||||
timeout: BUILD_TIMEOUT,
|
||||
cwd: process.cwd(),
|
||||
});
|
||||
|
||||
// Start preview server
|
||||
previewProcess = spawn(
|
||||
'yarn',
|
||||
['web:preview', '--port', '4173', '--host'],
|
||||
{
|
||||
cwd: process.cwd(),
|
||||
stdio: 'pipe',
|
||||
},
|
||||
);
|
||||
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
const timeout = setTimeout(
|
||||
() => reject(new Error('Preview server failed to start')),
|
||||
15_000, // Increased timeout to account for Tamagui build time
|
||||
);
|
||||
|
||||
let serverOutput = '';
|
||||
|
||||
if (previewProcess?.stdout) {
|
||||
previewProcess.stdout.on('data', (data: Buffer) => {
|
||||
const output = data.toString();
|
||||
serverOutput += output;
|
||||
|
||||
// Suppress noisy output in tests
|
||||
if (process.env.DEBUG_BUILD_TEST) {
|
||||
console.log('Preview server stdout:', JSON.stringify(output));
|
||||
}
|
||||
|
||||
// Look for the Local: indicator that the server is ready
|
||||
// Be more flexible with pattern matching
|
||||
const isReady =
|
||||
output.includes('Local:') ||
|
||||
output.includes('localhost:4173') ||
|
||||
/Local:\s*http:\/\/localhost:4173/i.test(output) ||
|
||||
/➜\s*Local:/i.test(output) ||
|
||||
(output.includes('4173') && output.includes('Local'));
|
||||
|
||||
if (isReady) {
|
||||
if (process.env.DEBUG_BUILD_TEST) {
|
||||
console.log('Server ready detected!');
|
||||
}
|
||||
clearTimeout(timeout);
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (previewProcess?.stderr) {
|
||||
previewProcess.stderr.on('data', (data: Buffer) => {
|
||||
const error = data.toString();
|
||||
|
||||
console.error('Preview server stderr:', error);
|
||||
serverOutput += error;
|
||||
});
|
||||
}
|
||||
|
||||
previewProcess?.on('error', error => {
|
||||
clearTimeout(timeout);
|
||||
// Avoid circular references by only using the error message string
|
||||
const errorMessage =
|
||||
error?.message || error?.toString() || 'Unknown error';
|
||||
reject(new Error(`Preview server process error: ${errorMessage}`));
|
||||
});
|
||||
|
||||
previewProcess?.on('exit', (code, _signal) => {
|
||||
if (code !== null && code !== 0) {
|
||||
clearTimeout(timeout);
|
||||
reject(
|
||||
new Error(
|
||||
`Preview server exited with code ${code}. Output: ${serverOutput}`,
|
||||
),
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Give the server a moment to fully start
|
||||
await new Promise(resolve => setTimeout(resolve, 3000));
|
||||
}, BUILD_TIMEOUT + 10_000);
|
||||
|
||||
afterAll(async () => {
|
||||
if (previewProcess) {
|
||||
try {
|
||||
previewProcess.kill('SIGTERM');
|
||||
// Give it a moment to terminate gracefully
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
if (!previewProcess.killed) {
|
||||
previewProcess.kill('SIGKILL');
|
||||
}
|
||||
} catch (error) {
|
||||
// Safely log error without circular references
|
||||
const errorMessage =
|
||||
error instanceof Error ? error.message : String(error);
|
||||
console.error('Error killing preview process:', errorMessage);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
test(
|
||||
'web app builds and server responds with valid HTML',
|
||||
async () => {
|
||||
// Test that the server responds with a 200 status
|
||||
const response = await fetch(PREVIEW_URL);
|
||||
expect(response.status).toBe(200);
|
||||
expect(response.headers.get('content-type')).toContain('text/html');
|
||||
|
||||
// Test that the response contains basic HTML structure
|
||||
const html = await response.text();
|
||||
expect(html.toLowerCase()).toContain('<!doctype html>');
|
||||
expect(html).toContain('<html');
|
||||
expect(html).toContain('<head>');
|
||||
expect(html).toContain('<body>');
|
||||
expect(html).toContain('<div id="root">');
|
||||
|
||||
// Test that essential assets are referenced
|
||||
expect(html).toContain('.js');
|
||||
expect(html).toContain('.css');
|
||||
|
||||
// Verify the HTML is not empty or minimal
|
||||
expect(html.length).toBeGreaterThan(500);
|
||||
|
||||
// Test that the title is present
|
||||
expect(html).toContain('<title>');
|
||||
expect(html).toContain('Self App');
|
||||
},
|
||||
PAGE_LOAD_TIMEOUT,
|
||||
);
|
||||
});
|
||||
@@ -34,6 +34,10 @@ export default defineConfig({
|
||||
'@': resolve(__dirname, 'src'),
|
||||
'react-native-svg': 'react-native-svg-web',
|
||||
'lottie-react-native': 'lottie-react',
|
||||
'@react-native-community/blur': resolve(
|
||||
__dirname,
|
||||
'src/mocks/react-native-community-blur.ts',
|
||||
),
|
||||
'react-native-safe-area-context': resolve(
|
||||
__dirname,
|
||||
'src/mocks/react-native-safe-area-context.js',
|
||||
|
||||
@@ -3,28 +3,18 @@
|
||||
// NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE.
|
||||
|
||||
module.exports = {
|
||||
dependencies: {
|
||||
'@selfxyz/mobile-sdk-alpha': {
|
||||
platforms: {
|
||||
ios: {
|
||||
sourceDir: './ios',
|
||||
podspecPath: './mobile-sdk-alpha.podspec',
|
||||
},
|
||||
android: {
|
||||
sourceDir: './android',
|
||||
manifestPath: 'src/main/AndroidManifest.xml',
|
||||
packageImportPath: 'import com.selfxyz.selfSDK.RNSelfPassportReaderPackage;',
|
||||
packageInstance: 'new RNSelfPassportReaderPackage()',
|
||||
},
|
||||
dependency: {
|
||||
platforms: {
|
||||
ios: {
|
||||
sourceDir: './ios',
|
||||
podspecPath: './mobile-sdk-alpha.podspec',
|
||||
},
|
||||
android: {
|
||||
sourceDir: './android',
|
||||
manifestPath: 'src/main/AndroidManifest.xml',
|
||||
packageImportPath: 'import com.selfxyz.selfSDK.RNSelfPassportReaderPackage;',
|
||||
packageInstance: 'new RNSelfPassportReaderPackage()',
|
||||
},
|
||||
},
|
||||
},
|
||||
project: {
|
||||
ios: {
|
||||
sourceDir: './ios',
|
||||
},
|
||||
android: {
|
||||
sourceDir: './android',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user