Merge pull request #1439 from selfxyz/release/staging-2025-11-20
Release to Staging - 2025-11-20
2
.github/workflows/gitleaks.yml
vendored
@@ -13,7 +13,7 @@ jobs:
|
||||
- name: Install gitleaks
|
||||
uses: gitleaks/gitleaks-action@v2.3.9
|
||||
with:
|
||||
config-path: .gitleaks.toml
|
||||
config-path: gitleaks-override.toml
|
||||
fail: true
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
20
.github/workflows/mobile-deploy.yml
vendored
@@ -150,9 +150,16 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
# Guard against auto-closed PRs (GitHub reports merged == false when a PR closes without merging)
|
||||
if: |
|
||||
(github.event_name != 'pull_request' || github.event.pull_request.merged == true) &&
|
||||
!contains(github.event.pull_request.labels.*.name, 'deploy:skip')
|
||||
(
|
||||
github.event_name != 'pull_request' ||
|
||||
(github.event.action == 'closed' && github.event.pull_request.merged == true)
|
||||
) &&
|
||||
(
|
||||
github.event_name != 'pull_request' ||
|
||||
!contains(github.event.pull_request.labels.*.name, 'deploy:skip')
|
||||
)
|
||||
outputs:
|
||||
version: ${{ steps.bump.outputs.version }}
|
||||
ios_build: ${{ steps.bump.outputs.ios_build }}
|
||||
@@ -262,7 +269,8 @@ jobs:
|
||||
contents: read
|
||||
actions: write
|
||||
if: |
|
||||
(github.event_name != 'pull_request' || github.event.pull_request.merged == true) &&
|
||||
(github.event_name != 'pull_request' ||
|
||||
(github.event.action == 'closed' && github.event.pull_request.merged == true)) &&
|
||||
(
|
||||
(inputs.platform == 'ios' || inputs.platform == 'both') ||
|
||||
(github.event_name == 'pull_request' && !contains(github.event.pull_request.labels.*.name, 'deploy:android'))
|
||||
@@ -829,7 +837,8 @@ jobs:
|
||||
actions: write
|
||||
id-token: write
|
||||
if: |
|
||||
(github.event_name != 'pull_request' || github.event.pull_request.merged == true) &&
|
||||
(github.event_name != 'pull_request' ||
|
||||
(github.event.action == 'closed' && github.event.pull_request.merged == true)) &&
|
||||
(
|
||||
(inputs.platform == 'android' || inputs.platform == 'both') ||
|
||||
(github.event_name == 'pull_request' && !contains(github.event.pull_request.labels.*.name, 'deploy:ios'))
|
||||
@@ -1241,7 +1250,8 @@ jobs:
|
||||
needs: [bump-version, build-ios, build-android]
|
||||
if: |
|
||||
always() &&
|
||||
(github.event_name != 'pull_request' || github.event.pull_request.merged == true) &&
|
||||
(github.event_name != 'pull_request' ||
|
||||
(github.event.action == 'closed' && github.event.pull_request.merged == true)) &&
|
||||
(needs.build-ios.result == 'success' || needs.build-android.result == 'success')
|
||||
env:
|
||||
APP_PATH: ${{ github.workspace }}/app
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
f506113a22e5b147132834e4659f5af308448389:app/tests/utils/deeplinks.test.ts:generic-api-key:183
|
||||
5a67b5cc50f291401d1da4e51706d0cfcf1c2316:app/tests/utils/deeplinks.test.ts:generic-api-key:182
|
||||
0e4555eee6589aa9cca68f451227b149277d8c90:app/tests/src/utils/points/api.test.ts:generic-api-key:34
|
||||
feb433e3553f8a7fa6c724b2de5a3e32ef079880:app/ios/Podfile.lock:generic-api-key:2594
|
||||
3d0e1b4589680df2451031913d067b1b91dafa60:app/ios/Podfile.lock:generic-api-key:2594
|
||||
3d0e1b4589680df2451031913d067b1b91dafa60:app/tests/utils/deeplinks.test.ts:generic-api-key:208
|
||||
app/ios/Podfile.lock:generic-api-key:2594
|
||||
app/tests/src/navigation/deeplinks.test.ts:generic-api-key:208
|
||||
circuits/circuits/gcp_jwt_verifier/example_jwt.txt:jwt:1
|
||||
cadd7ae5b768c261230f84426eac879c1853ce70:app/ios/Podfile.lock:generic-api-key:2586
|
||||
|
||||
@@ -77,6 +77,8 @@ Gitleaks will scan staged changes on each commit via `yarn gitleaks`.
|
||||
|
||||
## Development Documentation
|
||||
|
||||
> **Note:** We do not accept text-only pull request changes. While we appreciate the feedback, we will not merge external pull requests that only modify markdown files or code comments (e.g., typo fixes in documentation or comments). Pull requests must include functional code changes.
|
||||
|
||||
For detailed development patterns and conventions, see:
|
||||
|
||||
- **[Development Patterns](docs/development-patterns.md)** - React Native architecture, navigation, state management, and code organization
|
||||
|
||||
@@ -165,6 +165,18 @@ module.exports = {
|
||||
},
|
||||
],
|
||||
|
||||
// Custom rule to prevent export * (bad for tree shaking)
|
||||
// This rule prevents the use of export * which disables tree shaking
|
||||
// and can significantly increase bundle size. Use selective exports instead.
|
||||
'no-restricted-syntax': [
|
||||
'error',
|
||||
{
|
||||
selector: 'ExportAllDeclaration',
|
||||
message:
|
||||
'export * is forbidden. Use selective exports for better tree shaking. Example: export { specific1, specific2 } from "./module"',
|
||||
},
|
||||
],
|
||||
|
||||
// Override rules conflicting with TypeScript union formatting
|
||||
|
||||
'@typescript-eslint/indent': 'off',
|
||||
@@ -191,11 +203,11 @@ module.exports = {
|
||||
{
|
||||
// Disable export sorting for files with dependency issues
|
||||
files: [
|
||||
'src/components/NavBar/BaseNavBar.tsx',
|
||||
'src/components/navbar/BaseNavBar.tsx',
|
||||
'src/navigation/index.tsx',
|
||||
'src/providers/passportDataProvider.tsx',
|
||||
'src/utils/cloudBackup/helpers.ts',
|
||||
'src/utils/haptic/index.ts',
|
||||
'src/services/cloud-backup/helpers.ts',
|
||||
'src/integrations/haptics/index.ts',
|
||||
],
|
||||
rules: {
|
||||
'sort-exports/sort-exports': 'off',
|
||||
@@ -268,13 +280,6 @@ module.exports = {
|
||||
'no-console': 'off',
|
||||
},
|
||||
},
|
||||
{
|
||||
// Allow require imports for dynamic imports in proving machine
|
||||
files: ['src/utils/proving/provingMachine.ts'],
|
||||
rules: {
|
||||
'@typescript-eslint/no-require-imports': 'off',
|
||||
},
|
||||
},
|
||||
{
|
||||
// Allow require imports for conditional loading in navigation
|
||||
files: ['src/navigation/index.tsx'],
|
||||
|
||||
10
app/App.tsx
@@ -19,6 +19,11 @@ import {
|
||||
TURNKEY_ORGANIZATION_ID,
|
||||
} from './env';
|
||||
import ErrorBoundary from './src/components/ErrorBoundary';
|
||||
import { initSentry, wrapWithSentry } from './src/config/sentry';
|
||||
import {
|
||||
TURNKEY_OAUTH_REDIRECT_URI_ANDROID,
|
||||
TURNKEY_OAUTH_REDIRECT_URI_IOS,
|
||||
} from './src/devtools/mocks';
|
||||
import AppNavigation from './src/navigation';
|
||||
import { AuthProvider } from './src/providers/authProvider';
|
||||
import { DatabaseProvider } from './src/providers/databaseProvider';
|
||||
@@ -28,11 +33,6 @@ import { NotificationTrackingProvider } from './src/providers/notificationTracki
|
||||
import { PassportProvider } from './src/providers/passportDataProvider';
|
||||
import { RemoteConfigProvider } from './src/providers/remoteConfigProvider';
|
||||
import { SelfClientProvider } from './src/providers/selfClientProvider';
|
||||
import { initSentry, wrapWithSentry } from './src/Sentry';
|
||||
import {
|
||||
TURNKEY_OAUTH_REDIRECT_URI_ANDROID,
|
||||
TURNKEY_OAUTH_REDIRECT_URI_IOS,
|
||||
} from './src/utils/constants';
|
||||
|
||||
import 'react-native-get-random-values';
|
||||
import 'react-native-url-polyfill/auto';
|
||||
|
||||
@@ -22,7 +22,7 @@ GEM
|
||||
artifactory (3.0.17)
|
||||
atomos (0.1.3)
|
||||
aws-eventstream (1.4.0)
|
||||
aws-partitions (1.1183.0)
|
||||
aws-partitions (1.1184.0)
|
||||
aws-sdk-core (3.237.0)
|
||||
aws-eventstream (~> 1, >= 1.3.0)
|
||||
aws-partitions (~> 1, >= 1.992.0)
|
||||
|
||||
@@ -135,7 +135,7 @@ android {
|
||||
minSdkVersion rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
versionCode 121
|
||||
versionName "2.9.1"
|
||||
versionName "2.9.2"
|
||||
manifestPlaceholders = [appAuthRedirectScheme: 'com.proofofpassportapp']
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
|
||||
71
app/babel.config.test.cjs
Normal file
@@ -0,0 +1,71 @@
|
||||
// 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.
|
||||
|
||||
// Babel config for Jest tests that excludes hermes-parser to avoid WebAssembly issues
|
||||
// Based on React Native babel preset but with hermes parser plugin removed
|
||||
|
||||
module.exports = {
|
||||
presets: [
|
||||
[
|
||||
'@babel/preset-env',
|
||||
{
|
||||
targets: {
|
||||
node: 'current',
|
||||
},
|
||||
},
|
||||
],
|
||||
'@babel/preset-typescript',
|
||||
[
|
||||
'@babel/preset-react',
|
||||
{
|
||||
runtime: 'automatic',
|
||||
},
|
||||
],
|
||||
],
|
||||
plugins: [
|
||||
// Module resolver for @ alias
|
||||
[
|
||||
'module-resolver',
|
||||
{
|
||||
root: ['./src'],
|
||||
alias: { '@': './src' },
|
||||
},
|
||||
],
|
||||
|
||||
// Core React Native transforms (minimal set needed for tests)
|
||||
['@babel/plugin-transform-class-properties', { loose: true }],
|
||||
['@babel/plugin-transform-classes', { loose: true }],
|
||||
['@babel/plugin-transform-private-methods', { loose: true }],
|
||||
['@babel/plugin-transform-private-property-in-object', { loose: true }],
|
||||
'@babel/plugin-syntax-dynamic-import',
|
||||
'@babel/plugin-syntax-export-default-from',
|
||||
'@babel/plugin-transform-export-namespace-from',
|
||||
'@babel/plugin-transform-unicode-regex',
|
||||
['@babel/plugin-transform-destructuring', { useBuiltIns: true }],
|
||||
'@babel/plugin-transform-spread',
|
||||
[
|
||||
'@babel/plugin-transform-object-rest-spread',
|
||||
{ loose: true, useBuiltIns: true },
|
||||
],
|
||||
['@babel/plugin-transform-optional-chaining', { loose: true }],
|
||||
['@babel/plugin-transform-nullish-coalescing-operator', { loose: true }],
|
||||
['@babel/plugin-transform-logical-assignment-operators', { loose: true }],
|
||||
// Flow type stripping to support React Native's Flow-based sources
|
||||
['@babel/plugin-syntax-flow'],
|
||||
['@babel/plugin-transform-flow-strip-types', { allowDeclareFields: true }],
|
||||
|
||||
// Environment variable support
|
||||
[
|
||||
'module:react-native-dotenv',
|
||||
{
|
||||
moduleName: '@env',
|
||||
path: '.env',
|
||||
blacklist: null,
|
||||
whitelist: null,
|
||||
safe: false,
|
||||
allowUndefined: true,
|
||||
},
|
||||
],
|
||||
],
|
||||
};
|
||||
@@ -19,7 +19,7 @@ import App from './App';
|
||||
import { name as appName } from './app.json';
|
||||
import tamaguiConfig from './tamagui.config';
|
||||
|
||||
import './src/utils/ethers';
|
||||
import './src/utils/crypto/ethers';
|
||||
import 'react-native-gesture-handler';
|
||||
|
||||
// Set global Buffer before any other imports
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>2.9.1</string>
|
||||
<string>2.9.2</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleURLTypes</key>
|
||||
|
||||
@@ -1465,7 +1465,7 @@ PODS:
|
||||
- ReactCommon/turbomodule/bridging
|
||||
- ReactCommon/turbomodule/core
|
||||
- Yoga
|
||||
- react-native-app-auth (8.0.3):
|
||||
- react-native-app-auth (8.1.0):
|
||||
- AppAuth (>= 1.7.6)
|
||||
- React-Core
|
||||
- react-native-biometrics (3.0.1):
|
||||
@@ -1560,7 +1560,7 @@ PODS:
|
||||
- ReactCommon/turbomodule/bridging
|
||||
- ReactCommon/turbomodule/core
|
||||
- Yoga
|
||||
- react-native-safe-area-context (5.6.1):
|
||||
- react-native-safe-area-context (5.6.2):
|
||||
- DoubleConversion
|
||||
- glog
|
||||
- hermes-engine
|
||||
@@ -1573,8 +1573,8 @@ PODS:
|
||||
- React-featureflags
|
||||
- React-graphics
|
||||
- React-ImageManager
|
||||
- react-native-safe-area-context/common (= 5.6.1)
|
||||
- react-native-safe-area-context/fabric (= 5.6.1)
|
||||
- react-native-safe-area-context/common (= 5.6.2)
|
||||
- react-native-safe-area-context/fabric (= 5.6.2)
|
||||
- React-NativeModulesApple
|
||||
- React-RCTFabric
|
||||
- React-rendererdebug
|
||||
@@ -1583,7 +1583,7 @@ PODS:
|
||||
- ReactCommon/turbomodule/bridging
|
||||
- ReactCommon/turbomodule/core
|
||||
- Yoga
|
||||
- react-native-safe-area-context/common (5.6.1):
|
||||
- react-native-safe-area-context/common (5.6.2):
|
||||
- DoubleConversion
|
||||
- glog
|
||||
- hermes-engine
|
||||
@@ -1604,7 +1604,7 @@ PODS:
|
||||
- ReactCommon/turbomodule/bridging
|
||||
- ReactCommon/turbomodule/core
|
||||
- Yoga
|
||||
- react-native-safe-area-context/fabric (5.6.1):
|
||||
- react-native-safe-area-context/fabric (5.6.2):
|
||||
- DoubleConversion
|
||||
- glog
|
||||
- hermes-engine
|
||||
@@ -2021,7 +2021,7 @@ PODS:
|
||||
- ReactCommon/turbomodule/bridging
|
||||
- ReactCommon/turbomodule/core
|
||||
- Yoga
|
||||
- RNLocalize (3.5.3):
|
||||
- RNLocalize (3.6.0):
|
||||
- DoubleConversion
|
||||
- glog
|
||||
- hermes-engine
|
||||
@@ -2131,7 +2131,7 @@ PODS:
|
||||
- ReactCommon/turbomodule/core
|
||||
- Sentry/HybridSDK (= 8.53.2)
|
||||
- Yoga
|
||||
- RNSVG (15.14.0):
|
||||
- RNSVG (15.15.0):
|
||||
- DoubleConversion
|
||||
- glog
|
||||
- hermes-engine
|
||||
@@ -2151,9 +2151,9 @@ PODS:
|
||||
- ReactCodegen
|
||||
- ReactCommon/turbomodule/bridging
|
||||
- ReactCommon/turbomodule/core
|
||||
- RNSVG/common (= 15.14.0)
|
||||
- RNSVG/common (= 15.15.0)
|
||||
- Yoga
|
||||
- RNSVG/common (15.14.0):
|
||||
- RNSVG/common (15.15.0):
|
||||
- DoubleConversion
|
||||
- glog
|
||||
- hermes-engine
|
||||
@@ -2583,7 +2583,7 @@ SPEC CHECKSUMS:
|
||||
React-logger: c4052eb941cca9a097ef01b59543a656dc088559
|
||||
React-Mapbuffer: 9343a5c14536d4463c80f09a960653d754daae21
|
||||
React-microtasksnativemodule: c7cafd8f4470cf8a4578ee605daa4c74d3278bf8
|
||||
react-native-app-auth: eb42594042a25455119a8c57194b4fd25b9352f4
|
||||
react-native-app-auth: e21c8ee920876b960e38c9381971bd189ebea06b
|
||||
react-native-biometrics: 43ed5b828646a7862dbc7945556446be00798e7d
|
||||
react-native-blur: 6334d934a9b5e67718b8f5725c44cc0a12946009
|
||||
react-native-cloud-storage: 8d89f2bc574cf11068dfd90933905974087fb9e9
|
||||
@@ -2592,7 +2592,7 @@ SPEC CHECKSUMS:
|
||||
react-native-netinfo: cec9c4e86083cb5b6aba0e0711f563e2fbbff187
|
||||
react-native-nfc-manager: 66a00e5ddab9704efebe19d605b1b8afb0bb1bd7
|
||||
react-native-passkey: 8853c3c635164864da68a6dbbcec7148506c3bcf
|
||||
react-native-safe-area-context: 90a89cb349c7f8168a707e6452288c2f665b9fd1
|
||||
react-native-safe-area-context: a7aad44fe544b55e2369a3086e16a01be60ce398
|
||||
react-native-sqlite-storage: 0c84826214baaa498796c7e46a5ccc9a82e114ed
|
||||
react-native-webview: 3f45e19f0ffc3701168768a6c37695e0f252410e
|
||||
React-nativeconfig: 415626a63057638759bcc75e0a96e2e07771a479
|
||||
@@ -2631,11 +2631,11 @@ SPEC CHECKSUMS:
|
||||
RNGestureHandler: a63b531307e5b2e6ea21d053a1a7ad4cf9695c57
|
||||
RNInAppBrowser: 6d3eb68d471b9834335c664704719b8be1bfdb20
|
||||
RNKeychain: 471ceef8c13f15a5534c3cd2674dbbd9d0680e52
|
||||
RNLocalize: 7683e450496a5aea9a2dab3745bfefa7341d3f5e
|
||||
RNLocalize: 4f5e4a46d2bccd04ccb96721e438dcb9de17c2e0
|
||||
RNReactNativeHapticFeedback: e526ac4a7ca9fb23c7843ea4fd7d823166054c73
|
||||
RNScreens: 806e1449a8ec63c2a4e4cf8a63cc80203ccda9b8
|
||||
RNSentry: 6ad982be2c8e32dab912afb4132b6a0d88484ea0
|
||||
RNSVG: e1cf5a9a5aa12c69f2ec47031defbd87ae7fb697
|
||||
RNSVG: 39476f26bbbe72ffe6194c6fc8f6acd588087957
|
||||
segment-analytics-react-native: a0c29c75ede1989118b50cac96b9495ea5c91a1d
|
||||
Sentry: 59993bffde4a1ac297ba6d268dc4bbce068d7c1b
|
||||
SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748
|
||||
|
||||
@@ -546,7 +546,7 @@
|
||||
"$(PROJECT_DIR)",
|
||||
"$(PROJECT_DIR)/MoproKit/Libs",
|
||||
);
|
||||
MARKETING_VERSION = 2.9.1;
|
||||
MARKETING_VERSION = 2.9.2;
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-ObjC",
|
||||
@@ -686,7 +686,7 @@
|
||||
"$(PROJECT_DIR)",
|
||||
"$(PROJECT_DIR)/MoproKit/Libs",
|
||||
);
|
||||
MARKETING_VERSION = 2.9.1;
|
||||
MARKETING_VERSION = 2.9.2;
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-ObjC",
|
||||
|
||||
@@ -3,8 +3,18 @@
|
||||
// NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE.
|
||||
|
||||
module.exports = {
|
||||
preset: 'react-native',
|
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'cjs', 'json', 'node'],
|
||||
moduleFileExtensions: [
|
||||
'ios.js',
|
||||
'android.js',
|
||||
'native.js',
|
||||
'ts',
|
||||
'tsx',
|
||||
'js',
|
||||
'jsx',
|
||||
'cjs',
|
||||
'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|@sentry|@anon-aadhaar|react-native-svg|react-native-svg-circle-country-flags)/)',
|
||||
],
|
||||
@@ -16,6 +26,7 @@ module.exports = {
|
||||
testPathIgnorePatterns: [
|
||||
'/node_modules/',
|
||||
'/scripts/tests/', // Node.js native test runner tests
|
||||
'/babel\\.config\\.test\\.cjs',
|
||||
],
|
||||
moduleNameMapper: {
|
||||
'^@env$': '<rootDir>/tests/__setup__/@env.js',
|
||||
@@ -50,7 +61,7 @@ module.exports = {
|
||||
'<rootDir>/../common/node_modules/@anon-aadhaar/core/dist/index.js',
|
||||
},
|
||||
transform: {
|
||||
'\\.[jt]sx?$': 'babel-jest',
|
||||
'\\.[jt]sx?$': ['babel-jest', { configFile: './babel.config.test.cjs' }],
|
||||
},
|
||||
globals: {
|
||||
'ts-jest': {
|
||||
|
||||
@@ -282,17 +282,13 @@ jest.mock(
|
||||
|
||||
// Mock react-native-gesture-handler to prevent getConstants errors
|
||||
jest.mock('react-native-gesture-handler', () => {
|
||||
const React = require('react');
|
||||
// Avoid requiring React to prevent nested require memory issues
|
||||
|
||||
// Mock the components directly without requiring react-native
|
||||
// to avoid triggering hermes-parser WASM errors
|
||||
const MockScrollView = props =>
|
||||
React.createElement('ScrollView', props, props.children);
|
||||
const MockTouchableOpacity = props =>
|
||||
React.createElement('TouchableOpacity', props, props.children);
|
||||
const MockTouchableHighlight = props =>
|
||||
React.createElement('TouchableHighlight', props, props.children);
|
||||
const MockFlatList = props => React.createElement('FlatList', props);
|
||||
// Mock the components as simple pass-through functions
|
||||
const MockScrollView = jest.fn(props => props.children || null);
|
||||
const MockTouchableOpacity = jest.fn(props => props.children || null);
|
||||
const MockTouchableHighlight = jest.fn(props => props.children || null);
|
||||
const MockFlatList = jest.fn(props => null);
|
||||
|
||||
return {
|
||||
...jest.requireActual('react-native-gesture-handler/jestSetup'),
|
||||
@@ -306,13 +302,11 @@ jest.mock('react-native-gesture-handler', () => {
|
||||
|
||||
// Mock react-native-safe-area-context
|
||||
jest.mock('react-native-safe-area-context', () => {
|
||||
const React = require('react');
|
||||
// Use React.createElement directly instead of requiring react-native to avoid memory issues
|
||||
// Avoid requiring React to prevent nested require memory issues
|
||||
return {
|
||||
__esModule: true,
|
||||
SafeAreaProvider: ({ children }) =>
|
||||
React.createElement('View', null, children),
|
||||
SafeAreaView: ({ children }) => React.createElement('View', null, children),
|
||||
SafeAreaProvider: jest.fn(({ children }) => children || null),
|
||||
SafeAreaView: jest.fn(({ children }) => children || null),
|
||||
useSafeAreaInsets: () => ({ top: 0, bottom: 0, left: 0, right: 0 }),
|
||||
};
|
||||
});
|
||||
@@ -766,8 +760,8 @@ const NativeModules = {
|
||||
// Make it available globally for any code that expects it
|
||||
global.NativeModules = NativeModules;
|
||||
|
||||
// Mock @/utils/passportReader to properly expose the interface expected by tests
|
||||
jest.mock('./src/utils/passportReader', () => {
|
||||
// Mock @/integrations/nfc/passportReader to properly expose the interface expected by tests
|
||||
jest.mock('./src/integrations/nfc/passportReader', () => {
|
||||
const mockScanPassport = jest.fn();
|
||||
// Mock the parameter count for scanPassport (iOS native method takes 9 parameters)
|
||||
Object.defineProperty(mockScanPassport, 'length', { value: 9 });
|
||||
@@ -903,53 +897,106 @@ jest.mock('react-native-localize', () => ({
|
||||
languageTag: 'en-US',
|
||||
isRTL: false,
|
||||
}),
|
||||
default: {
|
||||
getLocales: jest.fn().mockReturnValue([
|
||||
{
|
||||
countryCode: 'US',
|
||||
languageTag: 'en-US',
|
||||
languageCode: 'en',
|
||||
isRTL: false,
|
||||
},
|
||||
]),
|
||||
getCountry: jest.fn().mockReturnValue('US'),
|
||||
getTimeZone: jest.fn().mockReturnValue('America/New_York'),
|
||||
getCurrencies: jest.fn().mockReturnValue(['USD']),
|
||||
getTemperatureUnit: jest.fn().mockReturnValue('celsius'),
|
||||
getFirstWeekDay: jest.fn().mockReturnValue(0),
|
||||
uses24HourClock: jest.fn().mockReturnValue(false),
|
||||
usesMetricSystem: jest.fn().mockReturnValue(false),
|
||||
findBestAvailableLanguage: jest.fn().mockReturnValue({
|
||||
languageTag: 'en-US',
|
||||
isRTL: false,
|
||||
}),
|
||||
},
|
||||
}));
|
||||
|
||||
jest.mock('./src/utils/notifications/notificationService', () =>
|
||||
// Ensure mobile-sdk-alpha's bundled react-native-localize dependency is mocked as well
|
||||
jest.mock(
|
||||
'../packages/mobile-sdk-alpha/node_modules/react-native-localize',
|
||||
() => ({
|
||||
getLocales: jest.fn().mockReturnValue([
|
||||
{
|
||||
countryCode: 'US',
|
||||
languageTag: 'en-US',
|
||||
languageCode: 'en',
|
||||
isRTL: false,
|
||||
},
|
||||
]),
|
||||
getCountry: jest.fn().mockReturnValue('US'),
|
||||
getTimeZone: jest.fn().mockReturnValue('America/New_York'),
|
||||
getCurrencies: jest.fn().mockReturnValue(['USD']),
|
||||
getTemperatureUnit: jest.fn().mockReturnValue('celsius'),
|
||||
getFirstWeekDay: jest.fn().mockReturnValue(0),
|
||||
uses24HourClock: jest.fn().mockReturnValue(false),
|
||||
usesMetricSystem: jest.fn().mockReturnValue(false),
|
||||
findBestAvailableLanguage: jest.fn().mockReturnValue({
|
||||
languageTag: 'en-US',
|
||||
isRTL: false,
|
||||
}),
|
||||
default: {
|
||||
getLocales: jest.fn().mockReturnValue([
|
||||
{
|
||||
countryCode: 'US',
|
||||
languageTag: 'en-US',
|
||||
languageCode: 'en',
|
||||
isRTL: false,
|
||||
},
|
||||
]),
|
||||
getCountry: jest.fn().mockReturnValue('US'),
|
||||
getTimeZone: jest.fn().mockReturnValue('America/New_York'),
|
||||
getCurrencies: jest.fn().mockReturnValue(['USD']),
|
||||
getTemperatureUnit: jest.fn().mockReturnValue('celsius'),
|
||||
getFirstWeekDay: jest.fn().mockReturnValue(0),
|
||||
uses24HourClock: jest.fn().mockReturnValue(false),
|
||||
usesMetricSystem: jest.fn().mockReturnValue(false),
|
||||
findBestAvailableLanguage: jest.fn().mockReturnValue({
|
||||
languageTag: 'en-US',
|
||||
isRTL: false,
|
||||
}),
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
jest.mock('./src/services/notifications/notificationService', () =>
|
||||
require('./tests/__setup__/notificationServiceMock.js'),
|
||||
);
|
||||
|
||||
// Mock react-native-svg
|
||||
jest.mock('react-native-svg', () => {
|
||||
const React = require('react');
|
||||
// Avoid requiring React to prevent nested require memory issues
|
||||
|
||||
// Mock SvgXml component that handles XML strings
|
||||
const SvgXml = React.forwardRef(
|
||||
({ 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,
|
||||
});
|
||||
},
|
||||
);
|
||||
const SvgXml = jest.fn(() => null);
|
||||
SvgXml.displayName = 'SvgXml';
|
||||
|
||||
return {
|
||||
__esModule: true,
|
||||
default: SvgXml,
|
||||
SvgXml,
|
||||
Svg: props => React.createElement('Svg', props, props.children),
|
||||
Circle: props => React.createElement('Circle', props, props.children),
|
||||
Path: props => React.createElement('Path', props, props.children),
|
||||
G: props => React.createElement('G', props, props.children),
|
||||
Rect: props => React.createElement('Rect', props, props.children),
|
||||
Defs: props => React.createElement('Defs', props, props.children),
|
||||
LinearGradient: props =>
|
||||
React.createElement('LinearGradient', props, props.children),
|
||||
Stop: props => React.createElement('Stop', props, props.children),
|
||||
ClipPath: props => React.createElement('ClipPath', props, props.children),
|
||||
Polygon: props => React.createElement('Polygon', props, props.children),
|
||||
Polyline: props => React.createElement('Polyline', props, props.children),
|
||||
Line: props => React.createElement('Line', props, props.children),
|
||||
Text: props => React.createElement('Text', props, props.children),
|
||||
TSpan: props => React.createElement('TSpan', props, props.children),
|
||||
Svg: jest.fn(() => null),
|
||||
Circle: jest.fn(() => null),
|
||||
Path: jest.fn(() => null),
|
||||
G: jest.fn(() => null),
|
||||
Rect: jest.fn(() => null),
|
||||
Defs: jest.fn(() => null),
|
||||
LinearGradient: jest.fn(() => null),
|
||||
Stop: jest.fn(() => null),
|
||||
ClipPath: jest.fn(() => null),
|
||||
Polygon: jest.fn(() => null),
|
||||
Polyline: jest.fn(() => null),
|
||||
Line: jest.fn(() => null),
|
||||
Text: jest.fn(() => null),
|
||||
TSpan: jest.fn(() => null),
|
||||
};
|
||||
});
|
||||
|
||||
@@ -998,12 +1045,11 @@ jest.mock('@react-navigation/core', () => {
|
||||
});
|
||||
|
||||
// Mock react-native-webview globally to avoid ESM parsing and native behaviors
|
||||
// Note: Individual test files can override this with their own more specific mocks
|
||||
jest.mock('react-native-webview', () => {
|
||||
const React = require('react');
|
||||
// Use React.createElement directly instead of requiring react-native to avoid memory issues
|
||||
const MockWebView = React.forwardRef((props, ref) => {
|
||||
return React.createElement('View', { ref, testID: 'webview', ...props });
|
||||
});
|
||||
// Avoid requiring React to prevent nested require memory issues
|
||||
// Return a simple pass-through mock - tests can override with JSX mocks if needed
|
||||
const MockWebView = jest.fn(() => null);
|
||||
MockWebView.displayName = 'MockWebView';
|
||||
return {
|
||||
__esModule: true,
|
||||
@@ -1014,15 +1060,12 @@ jest.mock('react-native-webview', () => {
|
||||
|
||||
// Mock ExpandableBottomLayout to simple containers to avoid SDK internals in tests
|
||||
jest.mock('@/layouts/ExpandableBottomLayout', () => {
|
||||
const React = require('react');
|
||||
// Use React.createElement directly instead of requiring react-native to avoid memory issues
|
||||
const Layout = ({ children }) => React.createElement('View', null, children);
|
||||
const TopSection = ({ children }) =>
|
||||
React.createElement('View', null, children);
|
||||
const BottomSection = ({ children }) =>
|
||||
React.createElement('View', null, children);
|
||||
const FullSection = ({ children }) =>
|
||||
React.createElement('View', null, children);
|
||||
// Avoid requiring React to prevent nested require memory issues
|
||||
// These need to pass through children so WebView is rendered
|
||||
const Layout = ({ children, ...props }) => children;
|
||||
const TopSection = ({ children, ...props }) => children;
|
||||
const BottomSection = ({ children, ...props }) => children;
|
||||
const FullSection = ({ children, ...props }) => children;
|
||||
return {
|
||||
__esModule: true,
|
||||
ExpandableBottomLayout: { Layout, TopSection, BottomSection, FullSection },
|
||||
@@ -1031,21 +1074,26 @@ jest.mock('@/layouts/ExpandableBottomLayout', () => {
|
||||
|
||||
// Mock mobile-sdk-alpha components used by NavBar (Button, XStack)
|
||||
jest.mock('@selfxyz/mobile-sdk-alpha/components', () => {
|
||||
const React = require('react');
|
||||
// Use React.createElement directly instead of requiring react-native to avoid memory issues
|
||||
const Button = ({ children, onPress, icon, ...props }) =>
|
||||
React.createElement(
|
||||
'TouchableOpacity',
|
||||
{ onPress, ...props, testID: 'msdk-button' },
|
||||
icon
|
||||
? React.createElement('View', { testID: 'msdk-button-icon' }, icon)
|
||||
: null,
|
||||
children,
|
||||
// Avoid requiring React to prevent nested require memory issues
|
||||
// Create mock components that work with React testing library
|
||||
// Button needs to render a host element with onPress so tests can interact with it
|
||||
const Button = jest.fn(({ testID, icon, onPress, children, ...props }) => {
|
||||
// Render as a mock-touchable-opacity host element so fireEvent.press works
|
||||
// This allows tests to query by testID and press the button
|
||||
return (
|
||||
<mock-touchable-opacity testID={testID} onPress={onPress} {...props}>
|
||||
{icon || children || null}
|
||||
</mock-touchable-opacity>
|
||||
);
|
||||
const XStack = ({ children, ...props }) =>
|
||||
React.createElement('View', { ...props, testID: 'msdk-xstack' }, children);
|
||||
const Text = ({ children, ...props }) =>
|
||||
React.createElement('Text', { ...props }, children);
|
||||
});
|
||||
Button.displayName = 'MockButton';
|
||||
|
||||
const XStack = jest.fn(({ children, ...props }) => children || null);
|
||||
XStack.displayName = 'MockXStack';
|
||||
|
||||
const Text = jest.fn(({ children, ...props }) => children || null);
|
||||
Text.displayName = 'MockText';
|
||||
|
||||
return {
|
||||
__esModule: true,
|
||||
Button,
|
||||
@@ -1055,18 +1103,110 @@ jest.mock('@selfxyz/mobile-sdk-alpha/components', () => {
|
||||
};
|
||||
});
|
||||
|
||||
// Mock Tamagui to avoid hermes-parser WASM memory issues during transformation
|
||||
jest.mock('tamagui', () => {
|
||||
// Avoid requiring React to prevent nested require memory issues
|
||||
// Create mock components that work with React testing library
|
||||
|
||||
// Helper to create a simple pass-through mock component
|
||||
const createMockComponent = displayName => {
|
||||
const Component = jest.fn(props => props.children || null);
|
||||
Component.displayName = displayName;
|
||||
return Component;
|
||||
};
|
||||
|
||||
// Mock styled function - simplified version that returns the component
|
||||
const styled = jest.fn(Component => Component);
|
||||
|
||||
// Create all Tamagui component mocks
|
||||
const Button = createMockComponent('MockButton');
|
||||
const XStack = createMockComponent('MockXStack');
|
||||
const YStack = createMockComponent('MockYStack');
|
||||
const ZStack = createMockComponent('MockZStack');
|
||||
const Text = createMockComponent('MockText');
|
||||
const View = createMockComponent('MockView');
|
||||
const ScrollView = createMockComponent('MockScrollView');
|
||||
const Spinner = createMockComponent('MockSpinner');
|
||||
const Image = createMockComponent('MockImage');
|
||||
const Card = createMockComponent('MockCard');
|
||||
const Separator = createMockComponent('MockSeparator');
|
||||
const TextArea = createMockComponent('MockTextArea');
|
||||
const Input = createMockComponent('MockInput');
|
||||
const Anchor = createMockComponent('MockAnchor');
|
||||
|
||||
// Mock Select component with nested components
|
||||
const Select = Object.assign(createMockComponent('MockSelect'), {
|
||||
Trigger: createMockComponent('MockSelectTrigger'),
|
||||
Value: createMockComponent('MockSelectValue'),
|
||||
Content: createMockComponent('MockSelectContent'),
|
||||
Item: createMockComponent('MockSelectItem'),
|
||||
Group: createMockComponent('MockSelectGroup'),
|
||||
Label: createMockComponent('MockSelectLabel'),
|
||||
Viewport: createMockComponent('MockSelectViewport'),
|
||||
ScrollUpButton: createMockComponent('MockSelectScrollUpButton'),
|
||||
ScrollDownButton: createMockComponent('MockSelectScrollDownButton'),
|
||||
});
|
||||
|
||||
// Mock Sheet component with nested components
|
||||
const Sheet = Object.assign(createMockComponent('MockSheet'), {
|
||||
Frame: createMockComponent('MockSheetFrame'),
|
||||
Overlay: createMockComponent('MockSheetOverlay'),
|
||||
Handle: createMockComponent('MockSheetHandle'),
|
||||
ScrollView: createMockComponent('MockSheetScrollView'),
|
||||
});
|
||||
|
||||
// Mock Adapt component
|
||||
const Adapt = createMockComponent('MockAdapt');
|
||||
|
||||
// Mock TamaguiProvider - simple pass-through that renders children
|
||||
const TamaguiProvider = jest.fn(({ children }) => children || null);
|
||||
TamaguiProvider.displayName = 'MockTamaguiProvider';
|
||||
|
||||
// Mock configuration factory functions
|
||||
const createFont = jest.fn(() => ({}));
|
||||
const createTamagui = jest.fn(() => ({}));
|
||||
|
||||
return {
|
||||
__esModule: true,
|
||||
styled,
|
||||
Button,
|
||||
XStack,
|
||||
YStack,
|
||||
ZStack,
|
||||
Text,
|
||||
View,
|
||||
ScrollView,
|
||||
Spinner,
|
||||
Image,
|
||||
Card,
|
||||
Separator,
|
||||
TextArea,
|
||||
Input,
|
||||
Anchor,
|
||||
Select,
|
||||
Sheet,
|
||||
Adapt,
|
||||
TamaguiProvider,
|
||||
createFont,
|
||||
createTamagui,
|
||||
// Provide default exports for other common components
|
||||
default: jest.fn(() => null),
|
||||
};
|
||||
});
|
||||
|
||||
// Mock Tamagui lucide icons to simple components to avoid theme context
|
||||
jest.mock('@tamagui/lucide-icons', () => {
|
||||
const React = require('react');
|
||||
// Use React.createElement directly instead of requiring react-native to avoid memory issues
|
||||
// Avoid requiring React to prevent nested require memory issues
|
||||
// Return mock components that can be queried by testID
|
||||
const makeIcon = name => {
|
||||
const Icon = ({ size, color, opacity }) =>
|
||||
React.createElement('View', {
|
||||
testID: `icon-${name}`,
|
||||
size,
|
||||
color,
|
||||
opacity,
|
||||
});
|
||||
// Use a mock element tag that React can render
|
||||
const Icon = props => ({
|
||||
$$typeof: Symbol.for('react.element'),
|
||||
type: `mock-icon-${name}`,
|
||||
props: { testID: `icon-${name}`, ...props },
|
||||
key: null,
|
||||
ref: null,
|
||||
});
|
||||
Icon.displayName = `MockIcon(${name})`;
|
||||
return Icon;
|
||||
};
|
||||
@@ -1074,14 +1214,13 @@ jest.mock('@tamagui/lucide-icons', () => {
|
||||
__esModule: true,
|
||||
ExternalLink: makeIcon('external-link'),
|
||||
X: makeIcon('x'),
|
||||
Clipboard: makeIcon('clipboard'),
|
||||
};
|
||||
});
|
||||
|
||||
// Mock WebViewFooter to avoid SDK rendering complexity
|
||||
jest.mock('@/components/WebViewFooter', () => {
|
||||
const React = require('react');
|
||||
// Use React.createElement directly instead of requiring react-native to avoid memory issues
|
||||
const WebViewFooter = () =>
|
||||
React.createElement('View', { testID: 'webview-footer' });
|
||||
// Avoid requiring React to prevent nested require memory issues
|
||||
const WebViewFooter = jest.fn(() => null);
|
||||
return { __esModule: true, WebViewFooter };
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@selfxyz/mobile-app",
|
||||
"version": "2.9.1",
|
||||
"version": "2.9.2",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
@@ -56,17 +56,18 @@
|
||||
"sync-versions": "bundle exec fastlane ios sync_version && bundle exec fastlane android sync_version",
|
||||
"tag:release": "node scripts/tag.cjs release",
|
||||
"tag:remove": "node scripts/tag.cjs remove",
|
||||
"test": "yarn build:deps && jest --passWithNoTests && node --test scripts/tests/*.cjs",
|
||||
"test": "yarn build:deps && yarn jest:run --passWithNoTests && node --test scripts/tests/*.cjs",
|
||||
"test:build": "yarn build:deps && yarn types && node ./scripts/bundle-analyze-ci.cjs ios && yarn test",
|
||||
"test:ci": "jest --passWithNoTests && node --test scripts/tests/*.cjs",
|
||||
"test:coverage": "jest --coverage --passWithNoTests",
|
||||
"test:coverage:ci": "jest --coverage --passWithNoTests --ci --coverageReporters=lcov --coverageReporters=text --coverageReporters=json",
|
||||
"test:ci": "yarn jest:run --passWithNoTests && node --test scripts/tests/*.cjs",
|
||||
"test:coverage": "yarn jest:run --coverage --passWithNoTests",
|
||||
"test:coverage:ci": "yarn jest:run --coverage --passWithNoTests --ci --coverageReporters=lcov --coverageReporters=text --coverageReporters=json",
|
||||
"test:e2e:android": "./scripts/mobile-ci-build-android.sh && maestro test tests/e2e/launch.android.flow.yaml",
|
||||
"test:e2e:ios": "xcodebuild -workspace ios/OpenPassport.xcworkspace -scheme OpenPassport -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build && maestro test tests/e2e/launch.ios.flow.yaml",
|
||||
"test:fastlane": "bundle exec ruby -Itest fastlane/test/helpers_test.rb",
|
||||
"test:tree-shaking": "node ./scripts/test-tree-shaking.cjs",
|
||||
"test:web-build": "jest tests/web-build-render.test.ts --testTimeout=180000",
|
||||
"test:web-build": "yarn jest:run tests/web-build-render.test.ts --testTimeout=180000",
|
||||
"types": "tsc --noEmit",
|
||||
"jest:run": "node ./node_modules/jest/bin/jest.js",
|
||||
"watch:sdk": "yarn workspace @selfxyz/mobile-sdk-alpha watch",
|
||||
"web": "vite",
|
||||
"web:build": "yarn build:deps && vite build",
|
||||
@@ -168,9 +169,13 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.28.3",
|
||||
"@babel/plugin-syntax-flow": "^7.27.1",
|
||||
"@babel/plugin-transform-classes": "^7.27.1",
|
||||
"@babel/plugin-transform-export-namespace-from": "^7.27.1",
|
||||
"@babel/plugin-transform-flow-strip-types": "^7.27.1",
|
||||
"@babel/plugin-transform-private-methods": "^7.27.1",
|
||||
"@babel/preset-env": "^7.28.3",
|
||||
"@babel/preset-react": "^7.27.1",
|
||||
"@react-native-community/cli": "^16.0.3",
|
||||
"@react-native/babel-preset": "0.76.9",
|
||||
"@react-native/eslint-config": "0.76.9",
|
||||
|
||||
@@ -179,14 +179,14 @@ describe('alias-imports transform', () => {
|
||||
const appRoot = tempRoot;
|
||||
const srcDir = join(appRoot, 'src');
|
||||
const testsSrcDir = join(appRoot, 'tests', 'src');
|
||||
const fileHaptic = join(srcDir, 'utils', 'haptic.ts');
|
||||
const fileHaptic = join(srcDir, 'integrations', 'haptics.ts');
|
||||
const deepSpecDir = join(testsSrcDir, 'deep');
|
||||
const deepSpecFile = join(deepSpecDir, 'spec.ts');
|
||||
|
||||
writeFileEnsured(fileHaptic, 'export const h = 1;\n');
|
||||
writeFileEnsured(
|
||||
deepSpecFile,
|
||||
"import { h } from '../../../src/utils/haptic';\nexport const v = h;\n",
|
||||
"import { h } from '../../../src/integrations/haptics';\nexport const v = h;\n",
|
||||
);
|
||||
|
||||
const project = new Project({
|
||||
@@ -203,21 +203,24 @@ describe('alias-imports transform', () => {
|
||||
const specFile = project.getSourceFileOrThrow(deepSpecFile);
|
||||
const imports = specFile.getImportDeclarations();
|
||||
assert.strictEqual(imports.length, 1);
|
||||
assert.strictEqual(imports[0].getModuleSpecifierValue(), '@/utils/haptic');
|
||||
assert.strictEqual(
|
||||
imports[0].getModuleSpecifierValue(),
|
||||
'@/integrations/haptics',
|
||||
);
|
||||
});
|
||||
|
||||
it("transforms deep relative require '../../../src/...' to @src alias from tests", () => {
|
||||
const appRoot = tempRoot;
|
||||
const srcDir = join(appRoot, 'src');
|
||||
const testsSrcDir = join(appRoot, 'tests', 'src');
|
||||
const fileHaptic = join(srcDir, 'utils', 'haptic.ts');
|
||||
const fileHaptic = join(srcDir, 'integrations', 'haptics.ts');
|
||||
const deepSpecDir = join(testsSrcDir, 'deep');
|
||||
const deepSpecFile = join(deepSpecDir, 'req.ts');
|
||||
|
||||
writeFileEnsured(fileHaptic, 'module.exports = { h: 1 };\n');
|
||||
writeFileEnsured(
|
||||
deepSpecFile,
|
||||
"const h = require('../../../src/utils/haptic');\nexport const v = h;\n",
|
||||
"const h = require('../../../src/integrations/haptics');\nexport const v = h;\n",
|
||||
);
|
||||
|
||||
const project = new Project({
|
||||
@@ -232,7 +235,7 @@ describe('alias-imports transform', () => {
|
||||
transformProjectToAliasImports(project, appRoot);
|
||||
|
||||
const specFile = project.getSourceFileOrThrow(deepSpecFile);
|
||||
assert.ok(specFile.getText().includes("require('@/utils/haptic')"));
|
||||
assert.ok(specFile.getText().includes("require('@/integrations/haptics')"));
|
||||
});
|
||||
|
||||
it('aliases export star re-exports with ../ from sibling directory', () => {
|
||||
|
||||
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 4.6 KiB After Width: | Height: | Size: 4.6 KiB |
|
Before Width: | Height: | Size: 845 B After Width: | Height: | Size: 845 B |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 444 B After Width: | Height: | Size: 444 B |
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 5.0 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 505 B After Width: | Height: | Size: 505 B |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 105 KiB After Width: | Height: | Size: 105 KiB |
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 4.0 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 223 B After Width: | Height: | Size: 223 B |
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 4.5 KiB |
|
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 4.8 KiB |
|
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 767 B After Width: | Height: | Size: 767 B |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 326 B After Width: | Height: | Size: 326 B |
|
Before Width: | Height: | Size: 162 KiB After Width: | Height: | Size: 162 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 205 KiB After Width: | Height: | Size: 205 KiB |
|
Before Width: | Height: | Size: 152 KiB After Width: | Height: | Size: 152 KiB |
|
Before Width: | Height: | Size: 186 KiB After Width: | Height: | Size: 186 KiB |
|
Before Width: | Height: | Size: 208 KiB After Width: | Height: | Size: 208 KiB |
|
Before Width: | Height: | Size: 839 B After Width: | Height: | Size: 839 B |
|
Before Width: | Height: | Size: 860 B After Width: | Height: | Size: 860 B |
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 131 KiB After Width: | Height: | Size: 131 KiB |
|
Before Width: | Height: | Size: 468 KiB After Width: | Height: | Size: 468 KiB |
|
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 68 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
@@ -9,9 +9,9 @@ import type { Country3LetterCode } from '@selfxyz/common/constants';
|
||||
import { countryCodes } from '@selfxyz/common/constants';
|
||||
import type { SelfAppDisclosureConfig } from '@selfxyz/common/utils';
|
||||
import { BodyText } from '@selfxyz/mobile-sdk-alpha/components';
|
||||
import { slate200, slate500 } from '@selfxyz/mobile-sdk-alpha/constants/colors';
|
||||
|
||||
import CheckMark from '@/images/icons/checkmark.svg';
|
||||
import { slate200, slate500 } from '@/utils/colors';
|
||||
import CheckMark from '@/assets/icons/checkmark.svg';
|
||||
|
||||
interface DisclosureProps {
|
||||
disclosures: SelfAppDisclosureConfig;
|
||||
|
||||
@@ -6,8 +6,8 @@ import type { ErrorInfo } from 'react';
|
||||
import React, { Component } from 'react';
|
||||
import { Text, View } from 'react-native';
|
||||
|
||||
import { captureException } from '@/Sentry';
|
||||
import { flushAllAnalytics, trackNfcEvent } from '@/utils/analytics';
|
||||
import { captureException } from '@/config/sentry';
|
||||
import { flushAllAnalytics, trackNfcEvent } from '@/services/analytics';
|
||||
|
||||
interface Props {
|
||||
children: React.ReactNode;
|
||||
|
||||
@@ -7,9 +7,14 @@ import { Alert, Modal, StyleSheet, Text, TextInput, View } from 'react-native';
|
||||
import { Button, XStack, YStack } from 'tamagui';
|
||||
|
||||
import { Caption } from '@selfxyz/mobile-sdk-alpha/components';
|
||||
|
||||
import { black, slate400, white, zinc800, zinc900 } from '@/utils/colors';
|
||||
import { advercase, dinot } from '@/utils/fonts';
|
||||
import {
|
||||
black,
|
||||
slate400,
|
||||
white,
|
||||
zinc800,
|
||||
zinc900,
|
||||
} from '@selfxyz/mobile-sdk-alpha/constants/colors';
|
||||
import { advercase, dinot } from '@selfxyz/mobile-sdk-alpha/constants/fonts';
|
||||
|
||||
interface FeedbackModalProps {
|
||||
visible: boolean;
|
||||
|
||||
@@ -12,11 +12,11 @@ import {
|
||||
SecondaryButton,
|
||||
Title,
|
||||
} from '@selfxyz/mobile-sdk-alpha/components';
|
||||
import { white } from '@selfxyz/mobile-sdk-alpha/constants/colors';
|
||||
|
||||
import ModalClose from '@/images/icons/modal_close.svg';
|
||||
import LogoInversed from '@/images/logo_inversed.svg';
|
||||
import { white } from '@/utils/colors';
|
||||
import { confirmTap, impactLight } from '@/utils/haptic';
|
||||
import ModalClose from '@/assets/icons/modal_close.svg';
|
||||
import LogoInversed from '@/assets/images/logo_inversed.svg';
|
||||
import { confirmTap, impactLight } from '@/integrations/haptics';
|
||||
|
||||
const ModalBackDrop = styled(View, {
|
||||
display: 'flex',
|
||||
|
||||
@@ -8,9 +8,6 @@ import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
||||
import { Text, View, XStack, YStack } from 'tamagui';
|
||||
|
||||
import { DelayedLottieView } from '@selfxyz/mobile-sdk-alpha';
|
||||
|
||||
import CloseWarningIcon from '@/images/icons/close-warning.svg';
|
||||
import Plus from '@/images/icons/plus_slate600.svg';
|
||||
import {
|
||||
black,
|
||||
cyan300,
|
||||
@@ -19,9 +16,12 @@ import {
|
||||
white,
|
||||
zinc500,
|
||||
zinc900,
|
||||
} from '@/utils/colors';
|
||||
import { extraYPadding } from '@/utils/constants';
|
||||
import { advercase, dinot } from '@/utils/fonts';
|
||||
} from '@selfxyz/mobile-sdk-alpha/constants/colors';
|
||||
import { advercase, dinot } from '@selfxyz/mobile-sdk-alpha/constants/fonts';
|
||||
|
||||
import CloseWarningIcon from '@/assets/icons/close_warning.svg';
|
||||
import Plus from '@/assets/icons/plus_slate600.svg';
|
||||
import { extraYPadding } from '@/utils/styleUtils';
|
||||
|
||||
interface LoadingUIProps {
|
||||
animationSource: LottieView['props']['source'];
|
||||
@@ -6,7 +6,6 @@ import React, { useCallback, useState } from 'react';
|
||||
import { Button, Text, XStack, YStack } from 'tamagui';
|
||||
import Clipboard from '@react-native-clipboard/clipboard';
|
||||
|
||||
import { useSettingStore } from '@/stores/settingStore';
|
||||
import {
|
||||
black,
|
||||
slate50,
|
||||
@@ -15,8 +14,10 @@ import {
|
||||
slate500,
|
||||
teal500,
|
||||
white,
|
||||
} from '@/utils/colors';
|
||||
import { confirmTap } from '@/utils/haptic';
|
||||
} from '@selfxyz/mobile-sdk-alpha/constants/colors';
|
||||
|
||||
import { confirmTap } from '@/integrations/haptics';
|
||||
import { useSettingStore } from '@/stores/settingStore';
|
||||
|
||||
interface MnemonicProps {
|
||||
words?: string[];
|
||||
|
||||
@@ -1,8 +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.
|
||||
|
||||
export { AadhaarNavBar } from '@/components/NavBar/AadhaarNavBar';
|
||||
export { DefaultNavBar } from '@/components/NavBar/DefaultNavBar';
|
||||
export { HomeNavBar } from '@/components/NavBar/HomeNavBar';
|
||||
export { IdDetailsNavBar } from '@/components/NavBar/IdDetailsNavBar';
|
||||
@@ -13,10 +13,6 @@ import { Card, Text, View, XStack, YStack } from 'tamagui';
|
||||
|
||||
import { useSelfClient } from '@selfxyz/mobile-sdk-alpha';
|
||||
import { PointEvents } from '@selfxyz/mobile-sdk-alpha/constants/analytics';
|
||||
|
||||
import HeartIcon from '@/images/icons/heart.svg';
|
||||
import StarBlackIcon from '@/images/icons/star_black.svg';
|
||||
import { usePointEventStore } from '@/stores/pointEventStore';
|
||||
import {
|
||||
black,
|
||||
blue600,
|
||||
@@ -26,9 +22,13 @@ import {
|
||||
slate400,
|
||||
slate500,
|
||||
white,
|
||||
} from '@/utils/colors';
|
||||
import { dinot, plexMono } from '@/utils/fonts';
|
||||
import type { PointEvent } from '@/utils/points';
|
||||
} from '@selfxyz/mobile-sdk-alpha/constants/colors';
|
||||
import { dinot, plexMono } from '@selfxyz/mobile-sdk-alpha/constants/fonts';
|
||||
|
||||
import HeartIcon from '@/assets/icons/heart.svg';
|
||||
import StarBlackIcon from '@/assets/icons/star_black.svg';
|
||||
import type { PointEvent } from '@/services/points';
|
||||
import { usePointEventStore } from '@/stores/pointEventStore';
|
||||
|
||||
type Section = {
|
||||
title: string;
|
||||
|
||||
@@ -6,8 +6,7 @@ import React from 'react';
|
||||
import { Text, View } from 'tamagui';
|
||||
|
||||
import { Caption } from '@selfxyz/mobile-sdk-alpha/components';
|
||||
|
||||
import { slate500 } from '@/utils/colors';
|
||||
import { slate500 } from '@selfxyz/mobile-sdk-alpha/constants/colors';
|
||||
|
||||
export interface TipProps {
|
||||
title: string;
|
||||
|
||||
@@ -6,9 +6,13 @@ import React from 'react';
|
||||
import { ArrowLeft, ArrowRight, RotateCcw } from '@tamagui/lucide-icons';
|
||||
|
||||
import { Button, XStack, YStack } from '@selfxyz/mobile-sdk-alpha/components';
|
||||
import {
|
||||
black,
|
||||
slate50,
|
||||
slate400,
|
||||
} from '@selfxyz/mobile-sdk-alpha/constants/colors';
|
||||
|
||||
import { black, slate50, slate400 } from '@/utils/colors';
|
||||
import { buttonTap } from '@/utils/haptic';
|
||||
import { buttonTap } from '@/integrations/haptics';
|
||||
|
||||
export interface WebViewFooterProps {
|
||||
canGoBack: boolean;
|
||||
|
||||
@@ -14,11 +14,6 @@ import {
|
||||
} from '@selfxyz/common/constants';
|
||||
import type { PassportData } from '@selfxyz/common/types/passport';
|
||||
import { isAadhaarDocument, isMRZDocument } from '@selfxyz/common/utils/types';
|
||||
import AadhaarIcon from '@selfxyz/mobile-sdk-alpha/svgs/icons/aadhaar.svg';
|
||||
import EPassport from '@selfxyz/mobile-sdk-alpha/svgs/icons/epassport.svg';
|
||||
|
||||
import { SvgXml } from '@/components/homeScreen/SvgXmlWrapper';
|
||||
import LogoGray from '@/images/logo_gray.svg';
|
||||
import {
|
||||
black,
|
||||
slate100,
|
||||
@@ -26,8 +21,13 @@ import {
|
||||
slate400,
|
||||
slate500,
|
||||
white,
|
||||
} from '@/utils/colors';
|
||||
import { dinot, plexMono } from '@/utils/fonts';
|
||||
} from '@selfxyz/mobile-sdk-alpha/constants/colors';
|
||||
import { dinot, plexMono } from '@selfxyz/mobile-sdk-alpha/constants/fonts';
|
||||
import AadhaarIcon from '@selfxyz/mobile-sdk-alpha/svgs/icons/aadhaar.svg';
|
||||
import EPassport from '@selfxyz/mobile-sdk-alpha/svgs/icons/epassport.svg';
|
||||
|
||||
import LogoGray from '@/assets/images/logo_gray.svg';
|
||||
import { SvgXml } from '@/components/homescreen/SvgXmlWrapper';
|
||||
|
||||
// Import the logo SVG as a string
|
||||
const logoSvg = `<svg width="47" height="46" viewBox="0 0 47 46" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
@@ -4,5 +4,5 @@
|
||||
|
||||
// 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';
|
||||
export { SvgXml } from '@/components/homescreen/SvgXmlWrapper.native';
|
||||
export { default } from '@/components/homescreen/SvgXmlWrapper.native';
|
||||
@@ -8,12 +8,16 @@ import type { NativeStackHeaderProps } from '@react-navigation/native-stack';
|
||||
import { ChevronLeft, HelpCircle } from '@tamagui/lucide-icons';
|
||||
|
||||
import { Button, XStack, YStack } from '@selfxyz/mobile-sdk-alpha/components';
|
||||
import {
|
||||
black,
|
||||
slate100,
|
||||
slate300,
|
||||
} from '@selfxyz/mobile-sdk-alpha/constants/colors';
|
||||
import { dinot } from '@selfxyz/mobile-sdk-alpha/constants/fonts';
|
||||
|
||||
import { NavBar } from '@/components/NavBar/BaseNavBar';
|
||||
import { black, slate100, slate300 } from '@/utils/colors';
|
||||
import { extraYPadding } from '@/utils/constants';
|
||||
import { dinot } from '@/utils/fonts';
|
||||
import { buttonTap } from '@/utils/haptic';
|
||||
import { NavBar } from '@/components/navbar/BaseNavBar';
|
||||
import { buttonTap } from '@/integrations/haptics';
|
||||
import { extraYPadding } from '@/utils/styleUtils';
|
||||
|
||||
export const AadhaarNavBar = (props: NativeStackHeaderProps) => {
|
||||
const insets = useSafeAreaInsets();
|
||||
@@ -7,10 +7,11 @@ import type { TextStyle, ViewStyle } from 'react-native';
|
||||
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
||||
import type { NativeStackHeaderProps } from '@react-navigation/native-stack';
|
||||
|
||||
import { NavBar } from '@/components/NavBar/BaseNavBar';
|
||||
import { white } from '@/utils/colors';
|
||||
import { extraYPadding } from '@/utils/constants';
|
||||
import { buttonTap } from '@/utils/haptic';
|
||||
import { white } from '@selfxyz/mobile-sdk-alpha/constants/colors';
|
||||
|
||||
import { NavBar } from '@/components/navbar/BaseNavBar';
|
||||
import { buttonTap } from '@/integrations/haptics';
|
||||
import { extraYPadding } from '@/utils/styleUtils';
|
||||
|
||||
export const DefaultNavBar = (props: NativeStackHeaderProps) => {
|
||||
const { goBack, canGoBack } = props.navigation;
|
||||
@@ -7,9 +7,10 @@ import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
||||
import { useNavigation } from '@react-navigation/native';
|
||||
import { HelpCircle } from '@tamagui/lucide-icons';
|
||||
|
||||
import { NavBar } from '@/components/NavBar/BaseNavBar';
|
||||
import { slate100 } from '@/utils/colors';
|
||||
import { dinot } from '@/utils/fonts';
|
||||
import { slate100 } from '@selfxyz/mobile-sdk-alpha/constants/colors';
|
||||
import { dinot } from '@selfxyz/mobile-sdk-alpha/constants/fonts';
|
||||
|
||||
import { NavBar } from '@/components/navbar/BaseNavBar';
|
||||
|
||||
export const DocumentFlowNavBar = ({
|
||||
title,
|
||||
@@ -11,14 +11,18 @@ import { Clipboard as ClipboardIcon } from '@tamagui/lucide-icons';
|
||||
|
||||
import type { SelfApp } from '@selfxyz/common/utils/appType';
|
||||
import { useSelfClient } from '@selfxyz/mobile-sdk-alpha';
|
||||
import {
|
||||
black,
|
||||
charcoal,
|
||||
slate50,
|
||||
} from '@selfxyz/mobile-sdk-alpha/constants/colors';
|
||||
|
||||
import { NavBar } from '@/components/NavBar/BaseNavBar';
|
||||
import CogHollowIcon from '@/images/icons/cog_hollow.svg';
|
||||
import PlusCircleIcon from '@/images/icons/plus_circle.svg';
|
||||
import ScanIcon from '@/images/icons/qr_scan.svg';
|
||||
import { black, charcoal, slate50 } from '@/utils/colors';
|
||||
import { extraYPadding } from '@/utils/constants';
|
||||
import { buttonTap } from '@/utils/haptic';
|
||||
import CogHollowIcon from '@/assets/icons/cog_hollow.svg';
|
||||
import PlusCircleIcon from '@/assets/icons/plus_circle.svg';
|
||||
import ScanIcon from '@/assets/icons/qr_scan.svg';
|
||||
import { NavBar } from '@/components/navbar/BaseNavBar';
|
||||
import { buttonTap } from '@/integrations/haptics';
|
||||
import { extraYPadding } from '@/utils/styleUtils';
|
||||
|
||||
export const HomeNavBar = (props: NativeStackHeaderProps) => {
|
||||
const selfClient = useSelfClient();
|
||||
@@ -7,11 +7,15 @@ import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
||||
import type { NativeStackHeaderProps } from '@react-navigation/native-stack';
|
||||
|
||||
import { Button, Text, View } from '@selfxyz/mobile-sdk-alpha/components';
|
||||
import {
|
||||
black,
|
||||
charcoal,
|
||||
slate50,
|
||||
} from '@selfxyz/mobile-sdk-alpha/constants/colors';
|
||||
|
||||
import { NavBar } from '@/components/NavBar/BaseNavBar';
|
||||
import { black, charcoal, slate50 } from '@/utils/colors';
|
||||
import { extraYPadding } from '@/utils/constants';
|
||||
import { buttonTap } from '@/utils/haptic';
|
||||
import { NavBar } from '@/components/navbar/BaseNavBar';
|
||||
import { buttonTap } from '@/integrations/haptics';
|
||||
import { extraYPadding } from '@/utils/styleUtils';
|
||||
|
||||
export const IdDetailsNavBar = (props: NativeStackHeaderProps) => {
|
||||
const insets = useSafeAreaInsets();
|
||||
@@ -12,20 +12,6 @@ import { HelpCircle } from '@tamagui/lucide-icons';
|
||||
|
||||
import { useSelfClient } from '@selfxyz/mobile-sdk-alpha';
|
||||
import { PointEvents } from '@selfxyz/mobile-sdk-alpha/constants/analytics';
|
||||
|
||||
import { PointHistoryList } from '@/components/PointHistoryList';
|
||||
import { useIncomingPoints, usePoints } from '@/hooks/usePoints';
|
||||
import { usePointsGuardrail } from '@/hooks/usePointsGuardrail';
|
||||
import BellWhiteIcon from '@/images/icons/bell_white.svg';
|
||||
import ClockIcon from '@/images/icons/clock.svg';
|
||||
import LockWhiteIcon from '@/images/icons/lock_white.svg';
|
||||
import StarBlackIcon from '@/images/icons/star_black.svg';
|
||||
import LogoInversed from '@/images/logo_inversed.svg';
|
||||
import MajongImage from '@/images/majong.png';
|
||||
import type { RootStackParamList } from '@/navigation';
|
||||
import { usePointEventStore } from '@/stores/pointEventStore';
|
||||
import { useSettingStore } from '@/stores/settingStore';
|
||||
import analytics from '@/utils/analytics';
|
||||
import {
|
||||
black,
|
||||
blue600,
|
||||
@@ -33,20 +19,34 @@ import {
|
||||
slate200,
|
||||
slate500,
|
||||
white,
|
||||
} from '@/utils/colors';
|
||||
import { dinot } from '@/utils/fonts';
|
||||
import { registerModalCallbacks } from '@/utils/modalCallbackRegistry';
|
||||
} from '@selfxyz/mobile-sdk-alpha/constants/colors';
|
||||
import { dinot } from '@selfxyz/mobile-sdk-alpha/constants/fonts';
|
||||
|
||||
import BellWhiteIcon from '@/assets/icons/bell_white.svg';
|
||||
import ClockIcon from '@/assets/icons/clock.svg';
|
||||
import LockWhiteIcon from '@/assets/icons/lock_white.svg';
|
||||
import StarBlackIcon from '@/assets/icons/star_black.svg';
|
||||
import LogoInversed from '@/assets/images/logo_inversed.svg';
|
||||
import MajongImage from '@/assets/images/majong.png';
|
||||
import { PointHistoryList } from '@/components/PointHistoryList';
|
||||
import { useIncomingPoints, usePoints } from '@/hooks/usePoints';
|
||||
import { usePointsGuardrail } from '@/hooks/usePointsGuardrail';
|
||||
import type { RootStackParamList } from '@/navigation';
|
||||
import analytics from '@/services/analytics';
|
||||
import {
|
||||
isTopicSubscribed,
|
||||
requestNotificationPermission,
|
||||
subscribeToTopics,
|
||||
} from '@/utils/notifications/notificationService';
|
||||
} from '@/services/notifications/notificationService';
|
||||
import {
|
||||
formatTimeUntilDate,
|
||||
POINT_VALUES,
|
||||
recordBackupPointEvent,
|
||||
recordNotificationPointEvent,
|
||||
} from '@/utils/points';
|
||||
import { POINT_VALUES } from '@/utils/points/types';
|
||||
} from '@/services/points';
|
||||
import { usePointEventStore } from '@/stores/pointEventStore';
|
||||
import { useSettingStore } from '@/stores/settingStore';
|
||||
import { registerModalCallbacks } from '@/utils/modalCallbackRegistry';
|
||||
|
||||
const Points: React.FC = () => {
|
||||
const selfClient = useSelfClient();
|
||||
@@ -7,11 +7,11 @@ import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
||||
import type { NativeStackHeaderProps } from '@react-navigation/native-stack';
|
||||
|
||||
import { Text, View } from '@selfxyz/mobile-sdk-alpha/components';
|
||||
import { black, slate50 } from '@selfxyz/mobile-sdk-alpha/constants/colors';
|
||||
|
||||
import { NavBar } from '@/components/NavBar/BaseNavBar';
|
||||
import { black, slate50 } from '@/utils/colors';
|
||||
import { extraYPadding } from '@/utils/constants';
|
||||
import { buttonTap } from '@/utils/haptic';
|
||||
import { NavBar } from '@/components/navbar/BaseNavBar';
|
||||
import { buttonTap } from '@/integrations/haptics';
|
||||
import { extraYPadding } from '@/utils/styleUtils';
|
||||
|
||||
export const PointsNavBar = (props: NativeStackHeaderProps) => {
|
||||
const insets = useSafeAreaInsets();
|
||||
@@ -8,10 +8,10 @@ import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
||||
import { ExternalLink, X } from '@tamagui/lucide-icons';
|
||||
|
||||
import { Button, XStack } from '@selfxyz/mobile-sdk-alpha/components';
|
||||
import { black } from '@selfxyz/mobile-sdk-alpha/constants/colors';
|
||||
import { dinot } from '@selfxyz/mobile-sdk-alpha/constants/fonts';
|
||||
|
||||
import { black } from '@/utils/colors';
|
||||
import { dinot } from '@/utils/fonts';
|
||||
import { buttonTap } from '@/utils/haptic';
|
||||
import { buttonTap } from '@/integrations/haptics';
|
||||
|
||||
export interface WebViewNavBarProps {
|
||||
title?: string;
|
||||