Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
ec57382
Improve demo app safe area handling
transphorm Sep 28, 2025
fb824c6
refactor: centralize mobile demo screen navigation
transphorm Sep 28, 2025
dcc04bf
update lock
transphorm Sep 29, 2025
4f170c1
Merge branch 'dev' into codex/review-mobile-sdk-demo-app-for-polish-s…
transphorm Sep 29, 2025
1e1842c
update podfile lock
transphorm Sep 29, 2025
417a428
fix pipelines
transphorm Sep 29, 2025
f848a6f
fix tests
transphorm Sep 30, 2025
cca68fb
save wip polish
transphorm Sep 30, 2025
3d3d434
polish app
transphorm Sep 30, 2025
3b875b4
simplify and standardize screens
transphorm Sep 30, 2025
fe02213
small fixes
transphorm Sep 30, 2025
fc5c4ec
fix tests
transphorm Sep 30, 2025
296d757
Use SDK SelfClientProvider in demo (#1162)
transphorm Sep 30, 2025
dd87f4d
fix types
transphorm Sep 30, 2025
84eb9fc
Fix mobile SDK demo Jest mock
transphorm Sep 30, 2025
7560493
Merge pull request #1164 from selfxyz/codex/fix-failing-pipelines-for…
transphorm Sep 30, 2025
039e6c9
force react-native-svg to 15.12.1
transphorm Sep 30, 2025
0580892
Merge branch 'codex/review-mobile-sdk-demo-app-for-polish-suggestions…
transphorm Sep 30, 2025
0bb30c5
Merge branch 'dev' into codex/review-mobile-sdk-demo-app-for-polish-s…
transphorm Oct 1, 2025
be49dc6
fix tests
transphorm Oct 1, 2025
0c1b322
add types script
transphorm Oct 1, 2025
800cb21
fix document list
transphorm Oct 1, 2025
854d31e
Merge branch 'dev' into codex/review-mobile-sdk-demo-app-for-polish-s…
transphorm Oct 1, 2025
ac33d1f
Merge branch 'dev' into codex/review-mobile-sdk-demo-app-for-polish-s…
transphorm Oct 1, 2025
19e515e
fix types and metro config
transphorm Oct 1, 2025
4071be7
add ignore files to speed up watchman and eslint
transphorm Oct 1, 2025
6602f67
save wip tweaks
transphorm Oct 1, 2025
9f1f556
save mock doc screen wip
transphorm Oct 1, 2025
320c2f7
use persistant document store
transphorm Oct 1, 2025
e12b1c1
save polish work in progress
transphorm Oct 1, 2025
e678847
add polish to screens
transphorm Oct 1, 2025
43c065e
save wip secure storage
transphorm Oct 1, 2025
fb95439
allow cursor to examine react configs
transphorm Oct 1, 2025
fde191d
convert tests to vitest and fix
transphorm Oct 1, 2025
b1959fa
fix tests
transphorm Oct 1, 2025
3ce39ff
prettier
transphorm Oct 1, 2025
1296db8
cr feedback
transphorm Oct 1, 2025
c1a270a
fix tests and remove skipped
transphorm Oct 1, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions app/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1520,7 +1520,7 @@ PODS:
- React-Core
- react-native-netinfo (11.4.1):
- React-Core
- react-native-nfc-manager (3.16.3):
- react-native-nfc-manager (3.17.1):
- React-Core
- react-native-safe-area-context (5.6.1):
- DoubleConversion
Expand Down Expand Up @@ -1904,7 +1904,7 @@ PODS:
- ReactCommon/turbomodule/bridging
- ReactCommon/turbomodule/core
- Yoga
- RNDeviceInfo (14.0.4):
- RNDeviceInfo (14.1.1):
- React-Core
- RNFBApp (19.3.0):
- Firebase/CoreOnly (= 10.24.0)
Expand Down Expand Up @@ -2070,7 +2070,7 @@ PODS:
- ReactCommon/turbomodule/core
- Sentry/HybridSDK (= 8.53.2)
- Yoga
- RNSVG (15.12.1):
- RNSVG (15.13.0):
- DoubleConversion
- glog
- hermes-engine
Expand All @@ -2090,9 +2090,9 @@ PODS:
- ReactCodegen
- ReactCommon/turbomodule/bridging
- ReactCommon/turbomodule/core
- RNSVG/common (= 15.12.1)
- RNSVG/common (= 15.13.0)
- Yoga
- RNSVG/common (15.12.1):
- RNSVG/common (15.13.0):
- DoubleConversion
- glog
- hermes-engine
Expand All @@ -2113,7 +2113,7 @@ PODS:
- ReactCommon/turbomodule/bridging
- ReactCommon/turbomodule/core
- Yoga
- segment-analytics-react-native (2.21.2):
- segment-analytics-react-native (2.21.3):
- React-Core
- sovran-react-native
- Sentry/HybridSDK (8.53.2)
Expand Down Expand Up @@ -2520,7 +2520,7 @@ SPEC CHECKSUMS:
react-native-cloud-storage: 8d89f2bc574cf11068dfd90933905974087fb9e9
react-native-get-random-values: d16467cf726c618e9c7a8c3c39c31faa2244bbba
react-native-netinfo: cec9c4e86083cb5b6aba0e0711f563e2fbbff187
react-native-nfc-manager: 66a00e5ddab9704efebe19d605b1b8afb0bb1bd7
react-native-nfc-manager: e5e91b4e9af0551755cdb6eaec55a8ff820ccdc6
react-native-safe-area-context: 90a89cb349c7f8168a707e6452288c2f665b9fd1
react-native-sqlite-storage: 0c84826214baaa498796c7e46a5ccc9a82e114ed
React-nativeconfig: 415626a63057638759bcc75e0a96e2e07771a479
Expand Down Expand Up @@ -2552,7 +2552,7 @@ SPEC CHECKSUMS:
ReactCommon: b2eb96a61b826ff327a773a74357b302cf6da678
RNCAsyncStorage: 0003b916f1a69fe2d20b7910e0d08da3d32c7bd6
RNCClipboard: a4827e134e4774e97fa86f7f986694dd89320f13
RNDeviceInfo: d863506092aef7e7af3a1c350c913d867d795047
RNDeviceInfo: bcce8752b5043a623fe3c26789679b473f705d3c
RNFBApp: 4097f75673f8b42a7cd1ba17e6ea85a94b45e4d1
RNFBMessaging: 92325b0d5619ac90ef023a23cfd16fd3b91d0a88
RNFBRemoteConfig: a569bacaa410acfcaba769370e53a787f80fd13b
Expand All @@ -2562,8 +2562,8 @@ SPEC CHECKSUMS:
RNReactNativeHapticFeedback: e526ac4a7ca9fb23c7843ea4fd7d823166054c73
RNScreens: 806e1449a8ec63c2a4e4cf8a63cc80203ccda9b8
RNSentry: 6ad982be2c8e32dab912afb4132b6a0d88484ea0
RNSVG: 0c1fc3e7b147949dc15644845e9124947ac8c9bb
segment-analytics-react-native: bad4c2c7b63818bd493caa2b5759fca59e4ae9a7
RNSVG: 836ba92eb666c7c321509d53bc3053c6dd2ec897
segment-analytics-react-native: a0c29c75ede1989118b50cac96b9495ea5c91a1d
Sentry: 59993bffde4a1ac297ba6d268dc4bbce068d7c1b
SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748
sovran-react-native: a3ad3f8ff90c2002b2aa9790001a78b0b0a38594
Expand Down
16 changes: 13 additions & 3 deletions app/scripts/mobile-ci-build-android.sh
Original file line number Diff line number Diff line change
Expand Up @@ -232,9 +232,19 @@ fi
# Restore original package files
log "Restoring original package files..."
if [[ -f "package.json.backup" ]] && [[ -f "../yarn.lock.backup" ]]; then
mv package.json.backup package.json
mv ../yarn.lock.backup ../yarn.lock
log "✅ Package files restored successfully"
if mv package.json.backup package.json && mv ../yarn.lock.backup ../yarn.lock; then
log "✅ Package files restored successfully"

# Verify restoration by checking yarn.lock doesn't contain tarball references
if grep -q "file:/tmp/mobile-sdk-alpha-ci.tgz" ../yarn.lock 2>/dev/null; then
log "WARNING: yarn.lock still contains tarball references after restoration"
log "This may cause 'yarn.lock is out of date' errors in CI"
fi
else
log "ERROR: Failed to restore package files"
log "This may cause 'yarn.lock is out of date' errors in CI"
exit 1
fi
else
log "WARNING: Backup files not found - package.json may still reference tarball"
log "Please run 'yarn add @selfxyz/mobile-sdk-alpha@workspace:^' manually"
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"resolutions": {
"@babel/core": "^7.28.4",
"@babel/runtime": "^7.28.4",
"@swc/core": "1.7.36",
"@tamagui/animations-react-native": "1.126.14",
"@tamagui/toast": "1.126.14",
"@types/node": "^22.18.3",
Expand Down
1 change: 0 additions & 1 deletion packages/mobile-sdk-alpha/ios/SelfSDK/PassportReader.swift
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,6 @@ class PassportReader: NSObject {
skipCA: skipCABool,
skipPACE: skipPACEBool,
useExtendedMode: extendedModeBool,
usePacePolling: usePacePollingBool,
Copy link
Member Author

Choose a reason for hiding this comment

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

@seshanthS fyi the demo wouldn't build with this param

customDisplayMessage: customMessageHandler
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ class SelfMRZScannerModule: NSObject, RCTBridgeModule {

@objc func startScanning(_ resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
DispatchQueue.main.async {
guard let rootViewController = UIApplication.shared.keyWindow?.rootViewController else {
guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
let rootViewController = windowScene.windows.first?.rootViewController else {
reject("error", "Unable to find root view controller", nil)
return
}
Expand Down
3 changes: 3 additions & 0 deletions packages/mobile-sdk-demo/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ node_modules/
.expo/
.expo-shared/

# Generated files
build/

# iOS
ios/build/
ios/DerivedData/
Expand Down
206 changes: 25 additions & 181 deletions packages/mobile-sdk-demo/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,202 +2,46 @@
// SPDX-License-Identifier: BUSL-1.1
// NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE.

import React, { useState } from 'react';
import { ScrollView, StyleSheet, Text, TouchableOpacity, View } from 'react-native';
import React, { useEffect, useState } from 'react';

import type { IDDocument } from '@selfxyz/common';
import type { IDDocument } from '@selfxyz/common/dist/esm/src/utils/types.js';

type Screen = 'home' | 'register' | 'generate' | 'prove' | 'camera' | 'nfc' | 'onboarding' | 'qr';
type GenerateMockCmp = typeof import('./src/GenerateMock').default;
type RegisterDocumentCmp = typeof import('./src/RegisterDocument').default;
type ProveQRCodeCmp = typeof import('./src/ProveQRCode').default;
import HomeScreen from './src/screens/HomeScreen';
import { screenMap, type ScreenContext, type ScreenRoute } from './src/screens';

function App() {
const [screen, setScreen] = useState<Screen>('home');
const [screen, setScreen] = useState<ScreenRoute>('home');
const [mockDocument, setMockDocument] = useState<IDDocument | null>(null);

const navigate = (next: Screen) => setScreen(next);
const navigate = (next: ScreenRoute) => setScreen(next);

if (screen === 'generate') {
const GenerateMock = require('./src/GenerateMock').default as GenerateMockCmp;
return <GenerateMock onGenerate={setMockDocument} onNavigate={navigate} onBack={() => navigate('home')} />;
}

if (screen === 'register') {
const RegisterDocument = require('./src/RegisterDocument').default as RegisterDocumentCmp;
return <RegisterDocument document={mockDocument} onBack={() => navigate('home')} />;
}
const screenContext: ScreenContext = {
navigate,
goHome: () => setScreen('home'),
mockDocument,
setMockDocument,
};

if (screen === 'prove') {
const ProveQRCode = require('./src/ProveQRCode').default as ProveQRCodeCmp;
return <ProveQRCode document={mockDocument} onBack={() => navigate('home')} />;
}

if (screen === 'camera') {
const DocumentCamera = require('./src/DocumentCamera').default;
return <DocumentCamera onBack={() => navigate('home')} />;
}
useEffect(() => {
if (screen !== 'home' && !screenMap[screen]) {
setScreen('home');
}
}, [screen]);

if (screen === 'nfc') {
const DocumentNFCScan = require('./src/DocumentNFCScan').default;
return <DocumentNFCScan onBack={() => navigate('home')} />;
if (screen === 'home') {
return <HomeScreen screenContext={screenContext} />;
}

if (screen === 'onboarding') {
const DocumentOnboarding = require('./src/DocumentOnboarding').default;
return <DocumentOnboarding onBack={() => navigate('home')} />;
}
const descriptor = screenMap[screen];

if (screen === 'qr') {
const QRCodeViewFinder = require('./src/QRCodeViewFinder').default;
return <QRCodeViewFinder onBack={() => navigate('home')} />;
if (!descriptor) {
return null;
}

const MenuButton = ({
title,
onPress,
isWorking = false,
}: {
title: string;
onPress: () => void;
isWorking?: boolean;
}) => (
<TouchableOpacity
style={[styles.menuButton, isWorking ? styles.workingButton : styles.placeholderButton]}
onPress={onPress}
activeOpacity={0.7}
>
<Text style={[styles.menuButtonText, isWorking ? styles.workingButtonText : styles.placeholderButtonText]}>
{title}
</Text>
</TouchableOpacity>
);

return (
<ScrollView contentContainerStyle={styles.container}>
<View style={styles.header}>
<Text style={styles.title}>Self Demo App</Text>
<Text style={styles.subtitle}>Mobile SDK Alpha - Available Screens</Text>
</View>

<View style={styles.section}>
<Text style={styles.sectionTitle}>🎯 Core Features</Text>
<MenuButton title="✅ Generate Mock Data" onPress={() => navigate('generate')} isWorking={true} />
<MenuButton
title="⏳ Register Document"
onPress={() => navigate('register')}
isWorking={Boolean(mockDocument)}
/>
<MenuButton title="⏳ Prove QR Code" onPress={() => navigate('prove')} isWorking={Boolean(mockDocument)} />
</View>
const ScreenComponent = descriptor.load();
const props = descriptor.getProps?.(screenContext) ?? {};

<View style={styles.section}>
<Text style={styles.sectionTitle}>📷 Document Scanning</Text>
<MenuButton title="⏳ Document Camera" onPress={() => navigate('camera')} />
<MenuButton title="⏳ Document NFC Scan" onPress={() => navigate('nfc')} />
<MenuButton title="⏳ Document Onboarding" onPress={() => navigate('onboarding')} />
</View>

<View style={styles.section}>
<Text style={styles.sectionTitle}>📱 QR Code Features</Text>
<MenuButton title="⏳ QR Code View Finder" onPress={() => navigate('qr')} />
</View>

<View style={styles.footer}>
<Text style={styles.footerText}>✅ Working | ⏳ Placeholder (Not Implemented)</Text>
<Text style={styles.footerSubtext}>Tap any screen to explore the demo interface</Text>
</View>
</ScrollView>
);
return <ScreenComponent {...props} />;
}

const styles = StyleSheet.create({
container: {
flexGrow: 1,
backgroundColor: '#f8f9fa',
padding: 20,
},
header: {
alignItems: 'center',
marginBottom: 32,
paddingTop: 20,
},
title: {
fontSize: 28,
fontWeight: 'bold',
textAlign: 'center',
color: '#1a1a1a',
marginBottom: 8,
},
subtitle: {
fontSize: 16,
color: '#666',
textAlign: 'center',
},
section: {
marginBottom: 32,
},
sectionTitle: {
fontSize: 20,
fontWeight: 'bold',
marginBottom: 16,
color: '#333',
textAlign: 'center',
},
menuButton: {
width: '100%',
paddingVertical: 16,
paddingHorizontal: 20,
borderRadius: 12,
marginBottom: 12,
shadowColor: '#000',
shadowOffset: {
width: 0,
height: 2,
},
shadowOpacity: 0.1,
shadowRadius: 3.84,
elevation: 5,
},
workingButton: {
backgroundColor: '#007AFF',
},
placeholderButton: {
backgroundColor: '#fff',
borderWidth: 1,
borderColor: '#e1e5e9',
},
menuButtonText: {
fontSize: 16,
fontWeight: '600',
textAlign: 'center',
},
workingButtonText: {
color: '#fff',
},
placeholderButtonText: {
color: '#666',
},
footer: {
marginTop: 20,
padding: 20,
backgroundColor: '#fff',
borderRadius: 12,
borderWidth: 1,
borderColor: '#e1e5e9',
},
footerText: {
textAlign: 'center',
color: '#666',
fontSize: 14,
fontWeight: '500',
marginBottom: 8,
},
footerSubtext: {
textAlign: 'center',
color: '#999',
fontSize: 12,
},
});

export default App;
Loading
Loading