diff --git a/app/Gemfile.lock b/app/Gemfile.lock index 4069d41b6..8b97a10a4 100644 --- a/app/Gemfile.lock +++ b/app/Gemfile.lock @@ -25,7 +25,7 @@ GEM artifactory (3.0.17) atomos (0.1.3) aws-eventstream (1.4.0) - aws-partitions (1.1172.0) + aws-partitions (1.1173.0) aws-sdk-core (3.233.0) aws-eventstream (~> 1, >= 1.3.0) aws-partitions (~> 1, >= 1.992.0) @@ -34,10 +34,10 @@ GEM bigdecimal jmespath (~> 1, >= 1.6.1) logger - aws-sdk-kms (1.113.0) + aws-sdk-kms (1.114.0) aws-sdk-core (~> 3, >= 3.231.0) aws-sigv4 (~> 1.5) - aws-sdk-s3 (1.199.1) + aws-sdk-s3 (1.200.0) aws-sdk-core (~> 3, >= 3.231.0) aws-sdk-kms (~> 1) aws-sigv4 (~> 1.5) diff --git a/app/metro.config.cjs b/app/metro.config.cjs index 768039970..74fcb51fd 100644 --- a/app/metro.config.cjs +++ b/app/metro.config.cjs @@ -66,11 +66,18 @@ const config = { new RegExp('packages/mobile-sdk-alpha/node_modules/react(/|$)'), new RegExp('packages/mobile-sdk-alpha/node_modules/react-dom(/|$)'), new RegExp('packages/mobile-sdk-alpha/node_modules/react-native(/|$)'), + new RegExp( + 'packages/mobile-sdk-alpha/node_modules/lottie-react-native(/|$)', + ), new RegExp('packages/mobile-sdk-alpha/node_modules/scheduler(/|$)'), + new RegExp( + 'packages/mobile-sdk-alpha/node_modules/react-native-svg(/|$)', + ), new RegExp('packages/mobile-sdk-demo/node_modules/react(/|$)'), new RegExp('packages/mobile-sdk-demo/node_modules/react-dom(/|$)'), new RegExp('packages/mobile-sdk-demo/node_modules/react-native(/|$)'), new RegExp('packages/mobile-sdk-demo/node_modules/scheduler(/|$)'), + new RegExp('packages/mobile-sdk-demo/node_modules/react-native-svg(/|$)'), ], // Enable automatic workspace package resolution enableGlobalPackages: true, @@ -95,6 +102,10 @@ const config = { assert: require.resolve('assert'), events: require.resolve('events'), process: require.resolve('process'), + 'react-native-svg': path.resolve( + projectRoot, + 'node_modules/react-native-svg', + ), // App-specific alias '@': path.join(__dirname, 'src'), }, diff --git a/app/src/components/loading/LoadingUI.tsx b/app/src/components/loading/LoadingUI.tsx index 2b746034b..9ae720f71 100644 --- a/app/src/components/loading/LoadingUI.tsx +++ b/app/src/components/loading/LoadingUI.tsx @@ -7,7 +7,8 @@ import React from 'react'; import { useSafeAreaInsets } from 'react-native-safe-area-context'; import { Text, View, XStack, YStack } from 'tamagui'; -import { DelayedLottieView } from '@/components/DelayedLottieView'; +import { DelayedLottieView } from '@selfxyz/mobile-sdk-alpha'; + import CloseWarningIcon from '@/images/icons/close-warning.svg'; import Plus from '@/images/icons/plus_slate600.svg'; import { diff --git a/app/src/layouts/ExpandableBottomLayout.tsx b/app/src/layouts/ExpandableBottomLayout.tsx index 2b46f6800..db660c08c 100644 --- a/app/src/layouts/ExpandableBottomLayout.tsx +++ b/app/src/layouts/ExpandableBottomLayout.tsx @@ -3,51 +3,32 @@ // NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE. import React from 'react'; -import { - Dimensions, - PixelRatio, - Platform, - ScrollView, - StyleSheet, -} from 'react-native'; import { SystemBars } from 'react-native-edge-to-edge'; import { useSafeAreaInsets } from 'react-native-safe-area-context'; -import type { ViewProps } from 'tamagui'; -import { View } from 'tamagui'; -import { black, white } from '@/utils/colors'; -import { extraYPadding } from '@/utils/constants'; +import type { + BottomSectionProps, + FullSectionProps, + LayoutProps, + TopSectionProps, +} from '@selfxyz/mobile-sdk-alpha'; +import { ExpandableBottomLayout as BaseExpandableBottomLayout } from '@selfxyz/mobile-sdk-alpha'; -// Get the current font scale factor -const fontScale = PixelRatio.getFontScale(); -// fontScale > 1 means the user has increased text size in accessibility settings -const isLargerTextEnabled = fontScale > 1.3; +import { black } from '@/utils/colors'; -interface ExpandableBottomLayoutProps extends ViewProps { - children: React.ReactNode; - backgroundColor: string; -} - -interface TopSectionProps extends ViewProps { - children: React.ReactNode; - backgroundColor: string; - roundTop?: boolean; -} - -interface BottomSectionProps extends ViewProps { - children: React.ReactNode; - backgroundColor: string; -} - -const Layout: React.FC = ({ +const Layout: React.FC = ({ children, backgroundColor, + ...props }) => { return ( - + {children} - + ); }; @@ -57,24 +38,18 @@ const TopSection: React.FC = ({ ...props }) => { const { top } = useSafeAreaInsets(); - const { roundTop, ...restProps } = props; + return ( - {children} - + ); }; -type FullSectionProps = ViewProps; /* * Rather than using a top and bottom section, this component is te entire thing. * It leave space for the safe area insets and provides basic padding @@ -85,75 +60,38 @@ const FullSection: React.FC = ({ ...props }: FullSectionProps) => { const { top, bottom } = useSafeAreaInsets(); + return ( - {children} - + ); }; const BottomSection: React.FC = ({ children, - style, ...props }) => { const { bottom: safeAreaBottom } = useSafeAreaInsets(); - const incomingBottom = props.paddingBottom ?? 0; - const minBottom = safeAreaBottom + extraYPadding; - const totalBottom = - typeof incomingBottom === 'number' ? minBottom + incomingBottom : minBottom; - - let panelHeight: number | 'auto' = 'auto'; - // set bottom section height to 38% of screen height - // and wrap children in a scroll view if larger text is enabled - if (isLargerTextEnabled) { - const windowHeight = Dimensions.get('window').height; - panelHeight = windowHeight * 0.38; - children = ( - - {children} - - ); - } return ( - {children} - + ); }; /** - * This component is a layout that has a top and bottom section. Bottom section - * automatically expands to as much space as it needs while the top section - * takes up the remaining space. - * - * Usage: - * - * import { ExpandableBottomLayout } from '../components/ExpandableBottomLayout'; - * - * - * - * <...top section content...> - * - * - * <...bottom section content...> - * - * + * This component is a wrapper around the ExpandableBottomLayout component from the mobile SDK + * pacakge. It handles the safe area insets and system bars. */ export const ExpandableBottomLayout = { Layout, @@ -161,32 +99,3 @@ export const ExpandableBottomLayout = { FullSection, BottomSection, }; - -const styles = StyleSheet.create({ - roundTop: { - marginTop: 12, - overflow: 'hidden', - borderTopRightRadius: 30, - borderTopLeftRadius: 30, - }, - layout: { - height: '100%', - flexDirection: 'column', - }, - topSection: { - alignSelf: 'stretch', - flexGrow: 1, - flexShrink: Platform.select({ web: 0, default: 1 }), - alignItems: 'center', - justifyContent: 'center', - backgroundColor: black, - overflow: 'hidden', - padding: 20, - }, - bottomSection: { - backgroundColor: white, - paddingTop: 30, - paddingLeft: 20, - paddingRight: 20, - }, -}); diff --git a/app/src/providers/selfClientProvider.tsx b/app/src/providers/selfClientProvider.tsx index 47b100c7f..1f5c9592e 100644 --- a/app/src/providers/selfClientProvider.tsx +++ b/app/src/providers/selfClientProvider.tsx @@ -6,17 +6,15 @@ import type { PropsWithChildren } from 'react'; import { useMemo } from 'react'; import { Platform } from 'react-native'; -import type { - Adapters, - TrackEventParams, - WsConn, -} from '@selfxyz/mobile-sdk-alpha'; import { + type Adapters, createListenersMap, reactNativeScannerAdapter, SdkEvents, SelfClientProvider as SDKSelfClientProvider, + type TrackEventParams, webNFCScannerShim, + type WsConn, } from '@selfxyz/mobile-sdk-alpha'; import type { RootStackParamList } from '@/navigation'; diff --git a/app/src/screens/app/SplashScreen.tsx b/app/src/screens/app/SplashScreen.tsx index 530031a87..dc6d4d060 100644 --- a/app/src/screens/app/SplashScreen.tsx +++ b/app/src/screens/app/SplashScreen.tsx @@ -8,12 +8,12 @@ import { useNavigation } from '@react-navigation/native'; import type { NativeStackNavigationProp } from '@react-navigation/native-stack'; import { + DelayedLottieView, hasAnyValidRegisteredDocument, useSelfClient, } from '@selfxyz/mobile-sdk-alpha'; import splashAnimation from '@/assets/animations/splash.json'; -import { DelayedLottieView } from '@/components/DelayedLottieView'; import type { RootStackParamList } from '@/navigation'; import { migrateToSecureKeychain, useAuth } from '@/providers/authProvider'; import { diff --git a/app/src/screens/documents/scanning/DocumentCameraScreen.tsx b/app/src/screens/documents/scanning/DocumentCameraScreen.tsx index 0bf74f621..04ebfd57a 100644 --- a/app/src/screens/documents/scanning/DocumentCameraScreen.tsx +++ b/app/src/screens/documents/scanning/DocumentCameraScreen.tsx @@ -8,6 +8,7 @@ import { View, XStack, YStack } from 'tamagui'; import { useIsFocused } from '@react-navigation/native'; import { + DelayedLottieView, hasAnyValidRegisteredDocument, useSelfClient, } from '@selfxyz/mobile-sdk-alpha'; @@ -24,7 +25,6 @@ import { } from '@selfxyz/mobile-sdk-alpha/onboarding/read-mrz'; import passportScanAnimation from '@/assets/animations/passport_scan.json'; -import { DelayedLottieView } from '@/components/DelayedLottieView'; import { PassportCamera } from '@/components/native/PassportCamera'; import useHapticNavigation from '@/hooks/useHapticNavigation'; import Scan from '@/images/icons/passport_camera_scan.svg'; diff --git a/app/src/screens/documents/selection/ConfirmBelongingScreen.tsx b/app/src/screens/documents/selection/ConfirmBelongingScreen.tsx index 97d4b3eca..92dcdee8c 100644 --- a/app/src/screens/documents/selection/ConfirmBelongingScreen.tsx +++ b/app/src/screens/documents/selection/ConfirmBelongingScreen.tsx @@ -7,7 +7,11 @@ import type { StaticScreenProps } from '@react-navigation/native'; import { usePreventRemove } from '@react-navigation/native'; import type { DocumentCategory } from '@selfxyz/common/utils/types'; -import { loadSelectedDocument, useSelfClient } from '@selfxyz/mobile-sdk-alpha'; +import { + DelayedLottieView, + loadSelectedDocument, + useSelfClient, +} from '@selfxyz/mobile-sdk-alpha'; import { Description, PrimaryButton, @@ -20,7 +24,6 @@ import { import { getPreRegistrationDescription } from '@selfxyz/mobile-sdk-alpha/onboarding/confirm-identification'; import successAnimation from '@/assets/animations/loading/success.json'; -import { DelayedLottieView } from '@/components/DelayedLottieView'; import useHapticNavigation from '@/hooks/useHapticNavigation'; import { ExpandableBottomLayout } from '@/layouts/ExpandableBottomLayout'; import { styles } from '@/screens/verification/ProofRequestStatusScreen'; diff --git a/app/src/screens/onboarding/AccountVerifiedSuccessScreen.tsx b/app/src/screens/onboarding/AccountVerifiedSuccessScreen.tsx index 1469839d1..ec1627902 100644 --- a/app/src/screens/onboarding/AccountVerifiedSuccessScreen.tsx +++ b/app/src/screens/onboarding/AccountVerifiedSuccessScreen.tsx @@ -7,6 +7,7 @@ import { YStack } from 'tamagui'; import { useNavigation } from '@react-navigation/native'; import type { NativeStackNavigationProp } from '@react-navigation/native-stack'; +import { DelayedLottieView } from '@selfxyz/mobile-sdk-alpha'; import { Description, PrimaryButton, @@ -15,7 +16,6 @@ import { import { BackupEvents } from '@selfxyz/mobile-sdk-alpha/constants/analytics'; import proofSuccessAnimation from '@/assets/animations/proof_success.json'; -import { DelayedLottieView } from '@/components/DelayedLottieView'; import { ExpandableBottomLayout } from '@/layouts/ExpandableBottomLayout'; import type { RootStackParamList } from '@/navigation'; import { styles } from '@/screens/verification/ProofRequestStatusScreen'; diff --git a/app/src/screens/onboarding/DisclaimerScreen.tsx b/app/src/screens/onboarding/DisclaimerScreen.tsx index 28a68253e..5f8ceb562 100644 --- a/app/src/screens/onboarding/DisclaimerScreen.tsx +++ b/app/src/screens/onboarding/DisclaimerScreen.tsx @@ -8,6 +8,7 @@ import { YStack } from 'tamagui'; import { useNavigation } from '@react-navigation/native'; import type { NativeStackNavigationProp } from '@react-navigation/native-stack'; +import { DelayedLottieView } from '@selfxyz/mobile-sdk-alpha'; import { Caution, PrimaryButton, @@ -16,7 +17,6 @@ import { import { AppEvents } from '@selfxyz/mobile-sdk-alpha/constants/analytics'; import warningAnimation from '@/assets/animations/warning.json'; -import { DelayedLottieView } from '@/components/DelayedLottieView'; import { ExpandableBottomLayout } from '@/layouts/ExpandableBottomLayout'; import type { RootStackParamList } from '@/navigation'; import { useSettingStore } from '@/stores/settingStore'; diff --git a/packages/mobile-sdk-alpha/package.json b/packages/mobile-sdk-alpha/package.json index 478fc71fc..b97185255 100644 --- a/packages/mobile-sdk-alpha/package.json +++ b/packages/mobile-sdk-alpha/package.json @@ -137,6 +137,7 @@ "eslint-plugin-simple-import-sort": "^12.1.1", "eslint-plugin-sort-exports": "^0.9.1", "jsdom": "^25.0.1", + "lottie-react-native": "7.2.2", "prettier": "^3.5.3", "react": "^18.3.1", "react-dom": "^18.3.1", @@ -149,6 +150,7 @@ "vitest": "^2.1.8" }, "peerDependencies": { + "lottie-react-native": "7.2.2", "react": "^18.3.1", "react-native": "0.76.9", "react-native-haptic-feedback": "*", diff --git a/packages/mobile-sdk-alpha/src/animations/passport_scan.json b/packages/mobile-sdk-alpha/src/animations/passport_scan.json new file mode 100644 index 000000000..1d5fd4871 --- /dev/null +++ b/packages/mobile-sdk-alpha/src/animations/passport_scan.json @@ -0,0 +1,2366 @@ +{ + "assets": [ + { + "h": 252, + "id": "0", + "p": "data:image/png;base64,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", + "u": "", + "w": 373, + "e": 1 + }, + { + "id": "8", + "layers": [ + { "ind": 7, "ty": 2, "parent": 6, "ks": {}, "ip": 0, "op": 121, "st": 0, "refId": "0" }, + { + "ind": 6, + "ty": 3, + "ks": { "p": { "a": 0, "k": [-0.029, 0] }, "s": { "a": 0, "k": [94.84, 94.84] } }, + "ip": 0, + "op": 121, + "st": 0 + } + ] + }, + { + "id": "12", + "layers": [ + { + "ind": 10, + "ty": 0, + "ks": { "p": { "a": 0, "k": [20, 20] } }, + "w": 353.7, + "h": 239, + "ip": 0, + "op": 121, + "st": 0, + "refId": "8" + }, + { + "ind": 11, + "ty": 4, + "ks": {}, + "ip": 0, + "op": 121, + "st": 0, + "shapes": [ + { + "ty": "rc", + "p": { "a": 0, "k": [196.85, 139.5] }, + "r": { "a": 0, "k": 0 }, + "s": { "a": 0, "k": [393.7, 279] } + }, + { "ty": "fl", "c": { "a": 0, "k": [0, 0, 0, 0] }, "o": { "a": 0, "k": 0 } } + ] + } + ] + }, + { + "id": "15", + "layers": [ + { + "ind": 14, + "ty": 0, + "parent": 5, + "ks": { "p": { "a": 0, "k": [-20, -20] } }, + "ef": [ + { + "ty": 29, + "ef": [ + { + "ty": 0, + "nm": "", + "v": { + "a": 1, + "k": [ + { "t": 0, "s": [33.33], "h": 1 }, + { "t": 24.6, "s": [33.33], "i": { "x": 0.174, "y": 0.759 }, "o": { "x": 0.011, "y": 0.227 } }, + { "t": 57, "s": [3.67], "i": { "x": 0.722, "y": 1 }, "o": { "x": 0.35, "y": 0.828 } }, + { "t": 89.4, "s": [0], "h": 1 }, + { "t": 120, "s": [0], "h": 1 } + ] + } + }, + { "ty": 7, "nm": "", "v": { "a": 0, "k": 1 } }, + { "ty": 7, "nm": "", "v": { "a": 0, "k": 0 } } + ] + } + ], + "w": 393.7, + "h": 279, + "ip": 0, + "op": 121, + "st": 0, + "refId": "12" + }, + { "ind": 5, "ty": 3, "ks": { "p": { "a": 0, "k": [21, 21] } }, "ip": 0, "op": 121, "st": 0 } + ] + }, + { + "id": "19", + "layers": [ + { + "ind": 17, + "ty": 0, + "ks": { + "a": { "a": 0, "k": [21, 21] }, + "o": { + "a": 1, + "k": [ + { "t": 0, "s": [0], "h": 1 }, + { "t": 24.6, "s": [0], "i": { "x": 0, "y": 1 }, "o": { "x": 0, "y": 0 } }, + { "t": 89.4, "s": [100], "h": 1 }, + { "t": 120, "s": [100], "h": 1 } + ] + }, + "p": { "a": 0, "k": [41, 41] } + }, + "w": 395, + "h": 280, + "ip": 0, + "op": 121, + "st": 0, + "refId": "15" + }, + { + "ind": 18, + "ty": 4, + "ks": {}, + "ip": 0, + "op": 121, + "st": 0, + "shapes": [ + { + "ty": "rc", + "p": { "a": 0, "k": [227.85, 170.5] }, + "r": { "a": 0, "k": 0 }, + "s": { "a": 0, "k": [455.7, 341] } + }, + { "ty": "fl", "c": { "a": 0, "k": [0, 0, 0, 0] }, "o": { "a": 0, "k": 0 } } + ] + } + ] + }, + { + "id": "22", + "layers": [ + { + "ind": 21, + "ty": 0, + "parent": 4, + "ks": { "p": { "a": 0, "k": [-41, -41] } }, + "ef": [ + { + "ty": 29, + "ef": [ + { + "ty": 0, + "nm": "", + "v": { + "a": 1, + "k": [ + { "t": 0, "s": [0], "h": 1 }, + { "t": 72, "s": [0], "i": { "x": 0.65, "y": 0.172 }, "o": { "x": 0.278, "y": 0 } }, + { "t": 96, "s": [3.67], "i": { "x": 0.989, "y": 0.773 }, "o": { "x": 0.826, "y": 0.241 } }, + { "t": 120, "s": [33.33], "h": 1 } + ] + } + }, + { "ty": 7, "nm": "", "v": { "a": 0, "k": 1 } }, + { "ty": 7, "nm": "", "v": { "a": 0, "k": 0 } } + ] + } + ], + "w": 455.7, + "h": 341, + "ip": 0, + "op": 121, + "st": 0, + "refId": "19" + }, + { "ind": 4, "ty": 3, "ks": { "p": { "a": 0, "k": [41, 41] } }, "ip": 0, "op": 121, "st": 0 } + ] + }, + { + "id": "28", + "layers": [ + { + "ind": 27, + "ty": 4, + "ks": {}, + "ip": 0, + "op": 121, + "st": 0, + "shapes": [ + { + "ty": "rc", + "p": { "a": 0, "k": [176.5, 116] }, + "r": { "a": 0, "k": 0 }, + "s": { "a": 0, "k": [353, 232] } + }, + { "ty": "fl", "c": { "a": 0, "k": [0, 0, 0, 0] }, "o": { "a": 0, "k": 0 } } + ] + }, + { + "ind": 0, + "ty": 4, + "ks": { "s": { "a": 0, "k": [133.33, 133.33] } }, + "ip": 0, + "op": 121, + "st": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ty": "gr", + "it": [ + { + "ty": "sh", + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [0, 0], + [0, -2.21], + [0, 0], + [10.49, 0], + [0, 0], + [0, 10.49], + [0, 0], + [-2.21, 0] + ], + "o": [ + [0, 0], + [2.21, 0], + [0, 0], + [0, 10.49], + [0, 0], + [-10.49, 0], + [0, 0], + [0, -2.21], + [0, 0] + ], + "v": [ + [5, 1], + [348, 1], + [352, 5], + [352, 212], + [333, 231], + [20, 231], + [1, 212], + [1, 5], + [5, 1] + ] + } + } + }, + { + "ty": "st", + "c": { "a": 0, "k": [1, 1, 1, 1] }, + "lc": 1, + "lj": 1, + "ml": 4, + "o": { "a": 0, "k": 100 }, + "w": { "a": 0, "k": 1 } + }, + { "ty": "tr", "o": { "a": 0, "k": 100 }, "s": { "a": 0, "k": [75, 75] } } + ] + }, + { "ty": "tr", "o": { "a": 0, "k": 100 } } + ] + } + ] + } + ] + }, + { + "id": "59", + "layers": [ + { + "ind": 58, + "ty": 4, + "parent": 57, + "ks": {}, + "ip": 0, + "op": 121, + "st": 0, + "shapes": [ + { + "ty": "rc", + "p": { + "a": 1, + "k": [ + { "t": 0, "s": [165.5, 109], "i": { "x": [1, 1], "y": [1, 1] }, "o": { "x": [0, 0], "y": [0, 0] } }, + { + "t": 60, + "s": [165.5, 109], + "i": { "x": [0, 1], "y": [1, 1] }, + "o": { "x": [0.5, 0], "y": [0, 0] } + }, + { "t": 120, "s": [0, 109], "h": 1 } + ] + }, + "r": { "a": 0, "k": 0 }, + "s": { + "a": 1, + "k": [ + { "t": 0, "s": [331, 218], "i": { "x": [1, 1], "y": [1, 1] }, "o": { "x": [0, 0], "y": [0, 0] } }, + { "t": 60, "s": [331, 218], "i": { "x": [0, 1], "y": [1, 1] }, "o": { "x": [0.5, 0], "y": [0, 0] } }, + { "t": 120, "s": [0, 218], "h": 1 } + ] + } + }, + { "ty": "fl", "c": { "a": 0, "k": [0, 0, 0] }, "o": { "a": 0, "k": 100 } } + ] + }, + { "ind": 57, "ty": 3, "parent": 56, "ks": {}, "ip": 0, "op": 121, "st": 0 }, + { "ind": 56, "ty": 3, "ks": { "p": { "a": 0, "k": [166, 0] } }, "ip": 0, "op": 121, "st": 0 } + ] + }, + { + "id": "63", + "layers": [ + { + "ind": 61, + "ty": 0, + "parent": 55, + "ks": { "a": { "a": 0, "k": [166, 0] } }, + "w": 497, + "h": 218, + "ip": 0, + "op": 121, + "st": 0, + "refId": "59" + }, + { + "ind": 62, + "ty": 4, + "parent": 55, + "ks": { + "o": { + "a": 1, + "k": [ + { "t": 0, "s": [100], "h": 1 }, + { "t": 60, "s": [100], "h": 1 }, + { "t": 60, "s": [0], "h": 1 }, + { "t": 120, "s": [0], "h": 1 }, + { "t": 120, "s": [100], "h": 1 } + ] + } + }, + "ip": 0, + "op": 121, + "st": 0, + "shapes": [ + { + "ty": "rc", + "p": { "a": 0, "k": [176.5, 116] }, + "r": { "a": 0, "k": 0 }, + "s": { "a": 0, "k": [353, 232] } + }, + { "ty": "fl", "c": { "a": 0, "k": [0, 0, 0] }, "o": { "a": 0, "k": 100 } } + ] + }, + { "ind": 55, "ty": 3, "ks": { "p": { "a": 0, "k": [166, 0] } }, "ip": 0, "op": 121, "st": 0 } + ] + }, + { + "id": "45", + "layers": [ + { + "ind": 44, + "ty": 4, + "parent": 43, + "ks": {}, + "ip": 0, + "op": 121, + "st": 0, + "shapes": [ + { + "ty": "rc", + "p": { + "a": 1, + "k": [ + { "t": 0, "s": [0, 109], "i": { "x": [0, 1], "y": [1, 1] }, "o": { "x": [0.5, 0], "y": [0, 0] } }, + { "t": 60, "s": [165.5, 109], "i": { "x": [1, 1], "y": [1, 1] }, "o": { "x": [0, 0], "y": [0, 0] } }, + { "t": 120, "s": [165.5, 109], "h": 1 } + ] + }, + "r": { "a": 0, "k": 0 }, + "s": { + "a": 1, + "k": [ + { "t": 0, "s": [0, 218], "i": { "x": [0, 1], "y": [1, 1] }, "o": { "x": [0.5, 0], "y": [0, 0] } }, + { "t": 60, "s": [331, 218], "i": { "x": [1, 1], "y": [1, 1] }, "o": { "x": [0, 0], "y": [0, 0] } }, + { "t": 120, "s": [331, 218], "h": 1 } + ] + } + }, + { "ty": "fl", "c": { "a": 0, "k": [0, 0, 0] }, "o": { "a": 0, "k": 100 } } + ] + }, + { + "ind": 43, + "ty": 3, + "parent": 42, + "ks": { + "p": { + "a": 1, + "k": [ + { "t": 0, "s": [331, 0], "i": { "x": [0, 1], "y": [1, 1] }, "o": { "x": [0.5, 0], "y": [0, 0] } }, + { "t": 60, "s": [0, 0], "i": { "x": [1, 1], "y": [1, 1] }, "o": { "x": [0, 0], "y": [0, 0] } }, + { "t": 120, "s": [0, 0], "h": 1 } + ] + } + }, + "ip": 0, + "op": 121, + "st": 0 + }, + { "ind": 42, "ty": 3, "ks": { "p": { "a": 0, "k": [166, 0] } }, "ip": 0, "op": 121, "st": 0 } + ] + }, + { + "id": "49", + "layers": [ + { + "ind": 47, + "ty": 0, + "parent": 41, + "ks": { "a": { "a": 0, "k": [166, 0] } }, + "w": 828, + "h": 218, + "ip": 0, + "op": 121, + "st": 0, + "refId": "45" + }, + { + "ind": 48, + "ty": 4, + "parent": 41, + "ks": { + "o": { + "a": 1, + "k": [ + { "t": 0, "s": [0], "h": 1 }, + { "t": 60, "s": [0], "h": 1 }, + { "t": 60, "s": [100], "h": 1 }, + { "t": 120, "s": [100], "h": 1 } + ] + } + }, + "ip": 0, + "op": 121, + "st": 0, + "shapes": [ + { + "ty": "rc", + "p": { "a": 0, "k": [176.5, 116] }, + "r": { "a": 0, "k": 0 }, + "s": { "a": 0, "k": [353, 232] } + }, + { "ty": "fl", "c": { "a": 0, "k": [0, 0, 0] }, "o": { "a": 0, "k": 100 } } + ] + }, + { "ind": 41, "ty": 3, "ks": { "p": { "a": 0, "k": [166, 0] } }, "ip": 0, "op": 121, "st": 0 } + ] + }, + { + "id": "35", + "layers": [ + { + "ind": 34, + "ty": 4, + "ks": {}, + "ip": 0, + "op": 121, + "st": 0, + "shapes": [ + { + "ty": "rc", + "p": { "a": 0, "k": [176.5, 116] }, + "r": { "a": 0, "k": 0 }, + "s": { "a": 0, "k": [353, 232] } + }, + { "ty": "fl", "c": { "a": 0, "k": [0, 0, 0, 0] }, "o": { "a": 0, "k": 0 } } + ] + }, + { + "ind": 0, + "ty": 4, + "ks": { "s": { "a": 0, "k": [133.33, 133.33] } }, + "ip": 0, + "op": 121, + "st": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "ty": "gr", + "it": [ + { + "ty": "sh", + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [18.52, 151.45], + [18.52, 149.89], + [24.98, 146.28], + [24.98, 147.87], + [20.01, 150.61], + [20.01, 150.73], + [24.98, 153.46], + [24.98, 155.07] + ] + } + } + }, + { + "ty": "sh", + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [29.02, 151.45], + [29.02, 149.89], + [35.47, 146.28], + [35.47, 147.87], + [30.5, 150.61], + [30.5, 150.73], + [35.47, 153.46], + [35.47, 155.07] + ] + } + } + }, + { + "ty": "sh", + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [39.51, 151.45], + [39.51, 149.89], + [45.96, 146.28], + [45.96, 147.87], + [41, 150.61], + [41, 150.73], + [45.96, 153.46], + [45.96, 155.07] + ] + } + } + }, + { + "ty": "sh", + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [50.01, 151.45], + [50.01, 149.89], + [56.46, 146.28], + [56.46, 147.87], + [51.49, 150.61], + [51.49, 150.73], + [56.46, 153.46], + [56.46, 155.07] + ] + } + } + }, + { + "ty": "sh", + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [60.5, 151.45], + [60.5, 149.89], + [66.95, 146.28], + [66.95, 147.87], + [61.99, 150.61], + [61.99, 150.73], + [66.95, 153.46], + [66.95, 155.07] + ] + } + } + }, + { + "ty": "sh", + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [71, 151.45], + [71, 149.89], + [77.45, 146.28], + [77.45, 147.87], + [72.48, 150.61], + [72.48, 150.73], + [77.45, 153.46], + [77.45, 155.07] + ] + } + } + }, + { + "ty": "sh", + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [81.49, 151.45], + [81.49, 149.89], + [87.94, 146.28], + [87.94, 147.87], + [82.98, 150.61], + [82.98, 150.73], + [87.94, 153.46], + [87.94, 155.07] + ] + } + } + }, + { + "ty": "sh", + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [91.98, 151.45], + [91.98, 149.89], + [98.43, 146.28], + [98.43, 147.87], + [93.47, 150.61], + [93.47, 150.73], + [98.43, 153.46], + [98.43, 155.07] + ] + } + } + }, + { + "ty": "sh", + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [102.48, 151.45], + [102.48, 149.89], + [108.93, 146.28], + [108.93, 147.87], + [103.96, 150.61], + [103.96, 150.73], + [108.93, 153.46], + [108.93, 155.07] + ] + } + } + }, + { + "ty": "sh", + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [112.97, 151.45], + [112.97, 149.89], + [119.42, 146.28], + [119.42, 147.87], + [114.46, 150.61], + [114.46, 150.73], + [119.42, 153.46], + [119.42, 155.07] + ] + } + } + }, + { + "ty": "sh", + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [123.46, 151.45], + [123.46, 149.89], + [129.92, 146.28], + [129.92, 147.87], + [124.95, 150.61], + [124.95, 150.73], + [129.92, 153.46], + [129.92, 155.07] + ] + } + } + }, + { + "ty": "sh", + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [133.96, 151.45], + [133.96, 149.89], + [140.41, 146.28], + [140.41, 147.87], + [135.45, 150.61], + [135.45, 150.73], + [140.41, 153.46], + [140.41, 155.07] + ] + } + } + }, + { + "ty": "sh", + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [144.45, 151.45], + [144.45, 149.89], + [150.91, 146.28], + [150.91, 147.87], + [145.94, 150.61], + [145.94, 150.73], + [150.91, 153.46], + [150.91, 155.07] + ] + } + } + }, + { + "ty": "sh", + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [154.95, 151.45], + [154.95, 149.89], + [161.4, 146.28], + [161.4, 147.87], + [156.43, 150.61], + [156.43, 150.73], + [161.4, 153.46], + [161.4, 155.07] + ] + } + } + }, + { + "ty": "sh", + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [165.44, 151.45], + [165.44, 149.89], + [171.89, 146.28], + [171.89, 147.87], + [166.93, 150.61], + [166.93, 150.73], + [171.89, 153.46], + [171.89, 155.07] + ] + } + } + }, + { + "ty": "sh", + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [175.94, 151.45], + [175.94, 149.89], + [182.39, 146.28], + [182.39, 147.87], + [177.42, 150.61], + [177.42, 150.73], + [182.39, 153.46], + [182.39, 155.07] + ] + } + } + }, + { + "ty": "sh", + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [186.43, 151.45], + [186.43, 149.89], + [192.88, 146.28], + [192.88, 147.87], + [187.92, 150.61], + [187.92, 150.73], + [192.88, 153.46], + [192.88, 155.07] + ] + } + } + }, + { + "ty": "sh", + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [196.93, 151.45], + [196.93, 149.89], + [203.38, 146.28], + [203.38, 147.87], + [198.41, 150.61], + [198.41, 150.73], + [203.38, 153.46], + [203.38, 155.07] + ] + } + } + }, + { + "ty": "sh", + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [207.42, 151.45], + [207.42, 149.89], + [213.87, 146.28], + [213.87, 147.87], + [208.9, 150.61], + [208.9, 150.73], + [213.87, 153.46], + [213.87, 155.07] + ] + } + } + }, + { + "ty": "sh", + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [217.91, 151.45], + [217.91, 149.89], + [224.36, 146.28], + [224.36, 147.87], + [219.4, 150.61], + [219.4, 150.73], + [224.36, 153.46], + [224.36, 155.07] + ] + } + } + }, + { + "ty": "sh", + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [228.41, 151.45], + [228.41, 149.89], + [234.86, 146.28], + [234.86, 147.87], + [229.89, 150.61], + [229.89, 150.73], + [234.86, 153.46], + [234.86, 155.07] + ] + } + } + }, + { + "ty": "sh", + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [238.9, 151.45], + [238.9, 149.89], + [245.35, 146.28], + [245.35, 147.87], + [240.39, 150.61], + [240.39, 150.73], + [245.35, 153.46], + [245.35, 155.07] + ] + } + } + }, + { "ty": "fl", "c": { "a": 0, "k": [0, 1, 0.71, 1] }, "o": { "a": 0, "k": 100 } }, + { "ty": "tr", "o": { "a": 0, "k": 100 } } + ] + }, + { + "ty": "gr", + "it": [ + { + "ty": "sh", + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [18.52, 132.33], + [18.52, 130.77], + [24.98, 127.16], + [24.98, 128.75], + [20.01, 131.49], + [20.01, 131.61], + [24.98, 134.34], + [24.98, 135.95] + ] + } + } + }, + { + "ty": "sh", + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [29.02, 132.33], + [29.02, 130.77], + [35.47, 127.16], + [35.47, 128.75], + [30.5, 131.49], + [30.5, 131.61], + [35.47, 134.34], + [35.47, 135.95] + ] + } + } + }, + { + "ty": "sh", + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [39.51, 132.33], + [39.51, 130.77], + [45.96, 127.16], + [45.96, 128.75], + [41, 131.49], + [41, 131.61], + [45.96, 134.34], + [45.96, 135.95] + ] + } + } + }, + { + "ty": "sh", + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [50.01, 132.33], + [50.01, 130.77], + [56.46, 127.16], + [56.46, 128.75], + [51.49, 131.49], + [51.49, 131.61], + [56.46, 134.34], + [56.46, 135.95] + ] + } + } + }, + { + "ty": "sh", + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [60.5, 132.33], + [60.5, 130.77], + [66.95, 127.16], + [66.95, 128.75], + [61.99, 131.49], + [61.99, 131.61], + [66.95, 134.34], + [66.95, 135.95] + ] + } + } + }, + { + "ty": "sh", + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [71, 132.33], + [71, 130.77], + [77.45, 127.16], + [77.45, 128.75], + [72.48, 131.49], + [72.48, 131.61], + [77.45, 134.34], + [77.45, 135.95] + ] + } + } + }, + { + "ty": "sh", + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [81.49, 132.33], + [81.49, 130.77], + [87.94, 127.16], + [87.94, 128.75], + [82.98, 131.49], + [82.98, 131.61], + [87.94, 134.34], + [87.94, 135.95] + ] + } + } + }, + { + "ty": "sh", + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [91.98, 132.33], + [91.98, 130.77], + [98.43, 127.16], + [98.43, 128.75], + [93.47, 131.49], + [93.47, 131.61], + [98.43, 134.34], + [98.43, 135.95] + ] + } + } + }, + { + "ty": "sh", + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [102.48, 132.33], + [102.48, 130.77], + [108.93, 127.16], + [108.93, 128.75], + [103.96, 131.49], + [103.96, 131.61], + [108.93, 134.34], + [108.93, 135.95] + ] + } + } + }, + { + "ty": "sh", + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [112.97, 132.33], + [112.97, 130.77], + [119.42, 127.16], + [119.42, 128.75], + [114.46, 131.49], + [114.46, 131.61], + [119.42, 134.34], + [119.42, 135.95] + ] + } + } + }, + { + "ty": "sh", + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [123.46, 132.33], + [123.46, 130.77], + [129.92, 127.16], + [129.92, 128.75], + [124.95, 131.49], + [124.95, 131.61], + [129.92, 134.34], + [129.92, 135.95] + ] + } + } + }, + { + "ty": "sh", + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [133.96, 132.33], + [133.96, 130.77], + [140.41, 127.16], + [140.41, 128.75], + [135.45, 131.49], + [135.45, 131.61], + [140.41, 134.34], + [140.41, 135.95] + ] + } + } + }, + { + "ty": "sh", + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [144.45, 132.33], + [144.45, 130.77], + [150.91, 127.16], + [150.91, 128.75], + [145.94, 131.49], + [145.94, 131.61], + [150.91, 134.34], + [150.91, 135.95] + ] + } + } + }, + { + "ty": "sh", + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [154.95, 132.33], + [154.95, 130.77], + [161.4, 127.16], + [161.4, 128.75], + [156.43, 131.49], + [156.43, 131.61], + [161.4, 134.34], + [161.4, 135.95] + ] + } + } + }, + { + "ty": "sh", + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [165.44, 132.33], + [165.44, 130.77], + [171.89, 127.16], + [171.89, 128.75], + [166.93, 131.49], + [166.93, 131.61], + [171.89, 134.34], + [171.89, 135.95] + ] + } + } + }, + { + "ty": "sh", + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [175.94, 132.33], + [175.94, 130.77], + [182.39, 127.16], + [182.39, 128.75], + [177.42, 131.49], + [177.42, 131.61], + [182.39, 134.34], + [182.39, 135.95] + ] + } + } + }, + { + "ty": "sh", + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [186.43, 132.33], + [186.43, 130.77], + [192.88, 127.16], + [192.88, 128.75], + [187.92, 131.49], + [187.92, 131.61], + [192.88, 134.34], + [192.88, 135.95] + ] + } + } + }, + { + "ty": "sh", + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [196.93, 132.33], + [196.93, 130.77], + [203.38, 127.16], + [203.38, 128.75], + [198.41, 131.49], + [198.41, 131.61], + [203.38, 134.34], + [203.38, 135.95] + ] + } + } + }, + { + "ty": "sh", + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [207.42, 132.33], + [207.42, 130.77], + [213.87, 127.16], + [213.87, 128.75], + [208.9, 131.49], + [208.9, 131.61], + [213.87, 134.34], + [213.87, 135.95] + ] + } + } + }, + { + "ty": "sh", + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [217.91, 132.33], + [217.91, 130.77], + [224.36, 127.16], + [224.36, 128.75], + [219.4, 131.49], + [219.4, 131.61], + [224.36, 134.34], + [224.36, 135.95] + ] + } + } + }, + { + "ty": "sh", + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [228.41, 132.33], + [228.41, 130.77], + [234.86, 127.16], + [234.86, 128.75], + [229.89, 131.49], + [229.89, 131.61], + [234.86, 134.34], + [234.86, 135.95] + ] + } + } + }, + { + "ty": "sh", + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "o": [ + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0], + [0, 0] + ], + "v": [ + [238.9, 132.33], + [238.9, 130.77], + [245.35, 127.16], + [245.35, 128.75], + [240.39, 131.49], + [240.39, 131.61], + [245.35, 134.34], + [245.35, 135.95] + ] + } + } + }, + { "ty": "fl", "c": { "a": 0, "k": [0, 1, 0.71, 1] }, "o": { "a": 0, "k": 100 } }, + { "ty": "tr", "o": { "a": 0, "k": 100 } } + ] + }, + { "ty": "tr", "o": { "a": 0, "k": 100 } } + ] + } + ] + } + ] + }, + { + "id": "38", + "layers": [ + { "ind": 37, "ty": 0, "parent": 33, "ks": {}, "w": 353, "h": 232, "ip": 0, "op": 121, "st": 0, "refId": "35" }, + { + "ind": 33, + "ty": 3, + "parent": 32, + "ks": { "s": { "a": 0, "k": [93.77, 93.97] } }, + "ip": 0, + "op": 121, + "st": 0 + }, + { "ind": 32, "ty": 3, "ks": {}, "ip": 0, "op": 121, "st": 0 } + ] + }, + { + "id": "52", + "layers": [ + { + "ind": 51, + "ty": 0, + "td": 1, + "parent": 31, + "ks": { "a": { "a": 0, "k": [166, 0] } }, + "w": 994, + "h": 232, + "ip": 0, + "op": 121, + "st": 0, + "refId": "49" + }, + { + "ind": 40, + "ty": 0, + "tt": 1, + "parent": 31, + "ks": {}, + "w": 353, + "h": 232, + "ip": 0, + "op": 121, + "st": 0, + "refId": "38" + }, + { "ind": 31, "ty": 3, "ks": {}, "ip": 0, "op": 121, "st": 0 } + ] + }, + { + "id": "66", + "layers": [ + { + "ind": 65, + "ty": 0, + "td": 1, + "ks": { "a": { "a": 0, "k": [166, 0] } }, + "w": 663, + "h": 232, + "ip": 0, + "op": 121, + "st": 0, + "refId": "63" + }, + { "ind": 54, "ty": 0, "tt": 1, "ks": {}, "w": 353, "h": 232, "ip": 0, "op": 121, "st": 0, "refId": "52" } + ] + } + ], + "fr": 60, + "h": 398, + "ip": 0, + "layers": [ + { + "ind": 24, + "ty": 0, + "parent": 3, + "ks": { + "a": { "a": 0, "k": [41, 41] }, + "o": { + "a": 1, + "k": [ + { "t": 0, "s": [100], "h": 1 }, + { "t": 72, "s": [100], "i": { "x": 1, "y": 1 }, "o": { "x": 1, "y": 0 } }, + { "t": 120, "s": [0], "h": 1 } + ] + } + }, + "w": 456, + "h": 341, + "ip": 0, + "op": 121, + "st": 0, + "refId": "22" + }, + { "ind": 3, "ty": 3, "parent": 2, "ks": { "p": { "a": 0, "k": [20, 82] } }, "ip": 0, "op": 121, "st": 0 }, + { "ind": 30, "ty": 0, "parent": 26, "ks": {}, "w": 353, "h": 232, "ip": 0, "op": 121, "st": 0, "refId": "28" }, + { "ind": 26, "ty": 3, "parent": 25, "ks": { "s": { "a": 0, "k": [93.2, 93.1] } }, "ip": 0, "op": 121, "st": 0 }, + { "ind": 25, "ty": 3, "parent": 2, "ks": { "p": { "a": 0, "k": [32, 94] } }, "ip": 0, "op": 121, "st": 0 }, + { + "ind": 68, + "ty": 0, + "parent": 2, + "ks": { + "o": { + "a": 1, + "k": [ + { "t": 0, "s": [100], "h": 1 }, + { "t": 120, "s": [100], "h": 1 }, + { "t": 120, "s": [0], "h": 1 } + ] + }, + "p": { "a": 0, "k": [31, 93] } + }, + "w": 353, + "h": 232, + "ip": 0, + "op": 121, + "st": 0, + "refId": "66" + }, + { "ind": 2, "ty": 3, "parent": 1, "ks": {}, "ip": 0, "op": 121, "st": 0 }, + { "ind": 1, "ty": 3, "ks": {}, "ip": 0, "op": 121, "st": 0 } + ], + "meta": { "g": "https://jitter.video" }, + "op": 120, + "v": "5.7.4", + "w": 393 +} diff --git a/packages/mobile-sdk-alpha/src/browser.ts b/packages/mobile-sdk-alpha/src/browser.ts index e2482ed4b..e8b57181a 100644 --- a/packages/mobile-sdk-alpha/src/browser.ts +++ b/packages/mobile-sdk-alpha/src/browser.ts @@ -34,7 +34,18 @@ export type { PassportValidationCallbacks } from './validation/document'; export type { SDKEvent, SDKEventMap } from './types/events'; export type { SdkErrorCategory } from './errors'; +export { + type BottomSectionProps, + ExpandableBottomLayout, + type FullSectionProps, + type LayoutProps, + type TopSectionProps, +} from './layouts/ExpandableBottomLayout'; + +export { DelayedLottieView } from './components/DelayedLottieView.web'; + export { type ProvingStateType } from './proving/provingMachine'; + export { SCANNER_ERROR_CODES, notImplemented, sdkError } from './errors'; export { SdkEvents } from './types/events'; diff --git a/app/src/components/DelayedLottieView.tsx b/packages/mobile-sdk-alpha/src/components/DelayedLottieView.tsx similarity index 53% rename from app/src/components/DelayedLottieView.tsx rename to packages/mobile-sdk-alpha/src/components/DelayedLottieView.tsx index e05ffc737..e00e98197 100644 --- a/app/src/components/DelayedLottieView.tsx +++ b/packages/mobile-sdk-alpha/src/components/DelayedLottieView.tsx @@ -4,7 +4,8 @@ import type { LottieViewProps } from 'lottie-react-native'; import LottieView from 'lottie-react-native'; -import React, { forwardRef, useEffect, useRef } from 'react'; +import type React from 'react'; +import { forwardRef, useEffect, useRef } from 'react'; /** * Wrapper around LottieView that fixes iOS native module initialization timing. @@ -20,29 +21,30 @@ import React, { forwardRef, useEffect, useRef } from 'react'; * @example * */ -export const DelayedLottieView = forwardRef( - (props, forwardedRef) => { - const internalRef = useRef(null); - const ref = (forwardedRef as React.RefObject) || internalRef; - - useEffect(() => { - // Only auto-trigger for autoPlay animations - if (props.autoPlay) { - const timer = setTimeout(() => { - ref.current?.play(); - }, 100); - - return () => clearTimeout(timer); - } - }, [props.autoPlay, ref]); - - // For autoPlay animations, disable native autoPlay and control it ourselves - const modifiedProps = props.autoPlay - ? { ...props, autoPlay: false } - : props; - - return ; - }, -); +export const DelayedLottieView = forwardRef((props, forwardedRef) => { + // If LottieView is undefined (peer dependency not installed), return null + if (typeof LottieView === 'undefined') { + return null; + } + + const internalRef = useRef(null); + const ref = (forwardedRef as React.RefObject) || internalRef; + + useEffect(() => { + // Only auto-trigger for autoPlay animations + if (props.autoPlay) { + const timer = setTimeout(() => { + ref.current?.play(); + }, 100); + + return () => clearTimeout(timer); + } + }, [props.autoPlay, ref]); + + // For autoPlay animations, disable native autoPlay and control it ourselves + const modifiedProps = props.autoPlay ? { ...props, autoPlay: false } : props; + + return ; +}); DelayedLottieView.displayName = 'DelayedLottieView'; diff --git a/packages/mobile-sdk-alpha/src/components/DelayedLottieView.web.tsx b/packages/mobile-sdk-alpha/src/components/DelayedLottieView.web.tsx new file mode 100644 index 000000000..907521a0b --- /dev/null +++ b/packages/mobile-sdk-alpha/src/components/DelayedLottieView.web.tsx @@ -0,0 +1,10 @@ +// 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. + +/** + * DelayedLottieView for web placeholder component. + */ +export const DelayedLottieView = () => { + return
; +}; diff --git a/packages/mobile-sdk-alpha/src/components/MRZScannerView.tsx b/packages/mobile-sdk-alpha/src/components/MRZScannerView.tsx index 3abc5cc93..86076f114 100644 --- a/packages/mobile-sdk-alpha/src/components/MRZScannerView.tsx +++ b/packages/mobile-sdk-alpha/src/components/MRZScannerView.tsx @@ -4,7 +4,7 @@ import { useCallback, useRef } from 'react'; import type { DimensionValue, NativeSyntheticEvent, ViewProps, ViewStyle } from 'react-native'; -import { NativeModules, PixelRatio, Platform, requireNativeComponent, StyleSheet, View } from 'react-native'; +import { NativeModules, PixelRatio, Platform, requireNativeComponent, View } from 'react-native'; import { extractMRZInfo, formatDateToYYMMDD } from '../mrz'; import type { MRZInfo } from '../types/public'; @@ -99,7 +99,6 @@ export const MRZScannerView: React.FC = ({ ); const containerStyle = [ - styles.container, height !== undefined && { height }, width !== undefined && { width }, aspectRatio !== undefined && { aspectRatio }, @@ -112,8 +111,8 @@ export const MRZScannerView: React.FC = ({ = ({ isMounted={true} style={{ height: PixelRatio.getPixelSizeForLayoutSize(800), - width: PixelRatio.getPixelSizeForLayoutSize(800), + width: PixelRatio.getPixelSizeForLayoutSize(400), }} onError={handleError} onPassportRead={handleMRZDetected} @@ -139,18 +138,4 @@ export const MRZScannerView: React.FC = ({ } }; -// TODO Check this -const styles = StyleSheet.create({ - container: { - width: '100%', - minHeight: 200, - aspectRatio: 1, - }, - scanner: { - flex: 1, - width: '100%', - height: '100%', - }, -}); - export const SelfMRZScannerModule = NativeModules.SelfMRZScannerModule; diff --git a/packages/mobile-sdk-alpha/src/components/layout/View.tsx b/packages/mobile-sdk-alpha/src/components/layout/View.tsx index 4f37f881a..83f163bc4 100644 --- a/packages/mobile-sdk-alpha/src/components/layout/View.tsx +++ b/packages/mobile-sdk-alpha/src/components/layout/View.tsx @@ -198,6 +198,7 @@ export const View: React.FC = ({ flexGrow, flexShrink, width, + maxWidth, height, flexDirection, justifyContent, @@ -226,6 +227,7 @@ export const View: React.FC = ({ ...(flexGrow !== undefined && { flexGrow }), ...(flexShrink !== undefined && { flexShrink }), ...(width !== undefined && { width }), + ...(maxWidth !== undefined && { maxWidth }), ...(height !== undefined && { height }), ...(flexDirection && { flexDirection }), ...(justifyContent && { justifyContent }), diff --git a/packages/mobile-sdk-alpha/src/constants/layout.ts b/packages/mobile-sdk-alpha/src/constants/layout.ts new file mode 100644 index 000000000..9c15d3da1 --- /dev/null +++ b/packages/mobile-sdk-alpha/src/constants/layout.ts @@ -0,0 +1,5 @@ +// 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 const extraYPadding = 15; diff --git a/packages/mobile-sdk-alpha/src/flows/onboarding/document-camera-screen.tsx b/packages/mobile-sdk-alpha/src/flows/onboarding/document-camera-screen.tsx new file mode 100644 index 000000000..e9ec1ee4e --- /dev/null +++ b/packages/mobile-sdk-alpha/src/flows/onboarding/document-camera-screen.tsx @@ -0,0 +1,119 @@ +// 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 { useCallback, useRef } from 'react'; +import { StyleSheet } from 'react-native'; +import passportScanAnimation from 'src/animations/passport_scan.json'; +import { Additional, Description, SecondaryButton, Title, View, XStack, YStack } from 'src/components'; +import { DelayedLottieView } from 'src/components/DelayedLottieView'; +import { MRZScannerView } from 'src/components/MRZScannerView'; +import { PassportEvents } from 'src/constants/analytics'; +import { black, slate400, slate800, white } from 'src/constants/colors'; +import { useSelfClient } from 'src/context'; +import { mrzReadInstructions, useReadMRZ } from 'src/flows/onboarding/read-mrz'; +import type { SafeAreaInsets } from 'src/layouts/ExpandableBottomLayout'; +import { ExpandableBottomLayout } from 'src/layouts/ExpandableBottomLayout'; +import { SdkEvents } from 'src/types/events'; +import type { MRZInfo } from 'src/types/public'; + +import Scan from '../../../svgs/icons/passport_camera_scan.svg'; +import { dinot } from '../../constants/fonts'; + +type Props = { + onBack?: () => void; + onSuccess?: () => void; + safeAreaInsets?: SafeAreaInsets; +}; + +export const DocumentCameraScreen = ({ onBack, onSuccess, safeAreaInsets }: Props) => { + const scanStartTimeRef = useRef(Date.now()); + const selfClient = useSelfClient(); + const { onPassportRead } = useReadMRZ(scanStartTimeRef); + + const handleMRZDetected = useCallback( + (mrzData: MRZInfo) => { + onPassportRead(null, mrzData); + + onSuccess?.(); + }, + [onPassportRead], + ); + + const handleScannerError = useCallback( + (error: string) => { + selfClient.emit(SdkEvents.ERROR, new Error(`MRZ scanner error: ${error}`)); + }, + [selfClient], + ); + + return ( + + + + + + + + + Scan your ID + + + + + + Open to the photograph page + {mrzReadInstructions()} + + + + + SELF WILL NOT CAPTURE AN IMAGE OF YOUR PASSPORT. + + {})}> + Cancel + + + + + ); +}; + +const styles = StyleSheet.create({ + animation: { + position: 'absolute', + width: '100%', + height: '100%', + }, + subheader: { + color: slate800, + textAlign: 'left', + textAlignVertical: 'top', + }, + description: { + textAlign: 'left', + }, + disclaimer: { + fontFamily: dinot, + textAlign: 'center', + fontSize: 11, + color: slate400, + textTransform: 'uppercase', + width: '100%', + alignSelf: 'center', + letterSpacing: 0.44, + marginTop: 0, + marginBottom: 10, + }, +}); diff --git a/packages/mobile-sdk-alpha/src/index.ts b/packages/mobile-sdk-alpha/src/index.ts index 8ed35acd5..aa1c2279d 100644 --- a/packages/mobile-sdk-alpha/src/index.ts +++ b/packages/mobile-sdk-alpha/src/index.ts @@ -49,6 +49,17 @@ export type { SDKEvent, SDKEventMap } from './types/events'; export type { SdkErrorCategory } from './errors'; // Screen Components (React Native-based) export type { provingMachineCircuitType } from './proving/provingMachine'; + +export { + type BottomSectionProps, + ExpandableBottomLayout, + type FullSectionProps, + type LayoutProps, + type TopSectionProps, +} from './layouts/ExpandableBottomLayout'; + +export { DelayedLottieView } from './components/DelayedLottieView'; + export { InitError, LivenessError, @@ -59,10 +70,8 @@ export { notImplemented, sdkError, } from './errors'; -export { NFCScannerScreen } from './components/screens/NFCScannerScreen'; -// Context and Client -export { PassportCameraScreen } from './components/screens/PassportCameraScreen'; +export { NFCScannerScreen } from './components/screens/NFCScannerScreen'; export { type ProvingStateType } from './proving/provingMachine'; // Components diff --git a/packages/mobile-sdk-alpha/src/layouts/ExpandableBottomLayout.tsx b/packages/mobile-sdk-alpha/src/layouts/ExpandableBottomLayout.tsx new file mode 100644 index 000000000..baee68309 --- /dev/null +++ b/packages/mobile-sdk-alpha/src/layouts/ExpandableBottomLayout.tsx @@ -0,0 +1,175 @@ +// 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 type React from 'react'; +import { Dimensions, PixelRatio, Platform, ScrollView, StyleSheet } from 'react-native'; + +import type { ViewProps } from '../components'; +import { View } from '../components'; +import { black, white } from '../constants/colors'; +import { extraYPadding } from '../constants/layout'; + +const SAFE_AREA_TOP_DEFAULT = 0; +const SAFE_AREA_BOTTOM_DEFAULT = 0; + +// Get the current font scale factor +const fontScale = PixelRatio.getFontScale(); +// fontScale > 1 means the user has increased text size in accessibility settings +const isLargerTextEnabled = fontScale > 1.3; + +export interface BottomSectionProps extends ViewProps { + children: React.ReactNode; + backgroundColor: string; + safeAreaBottom?: number; +} + +export type FullSectionProps = ViewProps & { + safeAreaTop?: number; + safeAreaBottom?: number; +}; + +export interface LayoutProps extends ViewProps { + children: React.ReactNode; + backgroundColor: string; + safeAreaTop?: number; + safeAreaBottom?: number; +} + +const Layout: React.FC = ({ children, backgroundColor }) => { + return ( + + {children} + + ); +}; + +const TopSection: React.FC = ({ children, backgroundColor, ...props }) => { + const { safeAreaTop = SAFE_AREA_TOP_DEFAULT } = props; + const { roundTop, ...restProps } = props; + + return ( + + {children} + + ); +}; + +/** + * This component is a layout that has a top and bottom section. Bottom section + * automatically expands to as much space as it needs while the top section + * takes up the remaining space. + * + * Usage: + * + * import { ExpandableBottomLayout } from '../components/ExpandableBottomLayout'; + * + * + * + * <...top section content...> + * + * + * <...bottom section content...> + * + * + */ +export type SafeAreaInsets = { + top: number; + bottom: number; +}; +/* + * Rather than using a top and bottom section, this component is te entire thing. + * It leave space for the safe area insets and provides basic padding + */ +const FullSection: React.FC = ({ children, backgroundColor, ...props }: FullSectionProps) => { + const { safeAreaTop = SAFE_AREA_TOP_DEFAULT, safeAreaBottom = SAFE_AREA_BOTTOM_DEFAULT } = props; + return ( + + {children} + + ); +}; + +const BottomSection: React.FC = ({ children, style, ...props }) => { + const incomingBottom = props.paddingBottom ?? 0; + const { safeAreaBottom = SAFE_AREA_BOTTOM_DEFAULT } = props; + const minBottom = safeAreaBottom + extraYPadding; + const totalBottom = typeof incomingBottom === 'number' ? minBottom + incomingBottom : minBottom; + + let panelHeight: number | 'auto' = 'auto'; + // set bottom section height to 38% of screen height + // and wrap children in a scroll view if larger text is enabled + if (isLargerTextEnabled) { + const windowHeight = Dimensions.get('window').height; + panelHeight = windowHeight * 0.38; + children = ( + + {children} + + ); + } + + return ( + + {children} + + ); +}; + +export interface TopSectionProps extends ViewProps { + children: React.ReactNode; + backgroundColor: string; + roundTop?: boolean; + safeAreaTop?: number; +} + +export const ExpandableBottomLayout = { + Layout, + TopSection, + FullSection, + BottomSection, +}; + +const styles = StyleSheet.create({ + roundTop: { + marginTop: 12, + overflow: 'hidden', + borderTopRightRadius: 30, + borderTopLeftRadius: 30, + }, + layout: { + height: '100%', + flexDirection: 'column', + }, + topSection: { + alignSelf: 'stretch', + flexGrow: 1, + flexShrink: Platform.select({ web: 0, default: 1 }), + alignItems: 'center', + justifyContent: 'center', + backgroundColor: black, + overflow: 'hidden', + padding: 20, + }, + bottomSection: { + backgroundColor: white, + paddingTop: 30, + paddingLeft: 20, + paddingRight: 20, + }, +}); diff --git a/packages/mobile-sdk-alpha/svgs/icons/passport_camera_scan.svg b/packages/mobile-sdk-alpha/svgs/icons/passport_camera_scan.svg new file mode 100644 index 000000000..cf47854f6 --- /dev/null +++ b/packages/mobile-sdk-alpha/svgs/icons/passport_camera_scan.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/mobile-sdk-alpha/tests/setup.ts b/packages/mobile-sdk-alpha/tests/setup.ts index 5c81ee4ba..5eeea990e 100644 --- a/packages/mobile-sdk-alpha/tests/setup.ts +++ b/packages/mobile-sdk-alpha/tests/setup.ts @@ -67,6 +67,12 @@ vi.mock('react-native', () => ({ Dimensions: { get: vi.fn(() => ({ width: 375, height: 667 })), }, + PixelRatio: { + get: vi.fn(() => 2), + getFontScale: vi.fn(() => 1), + getPixelSizeForLayoutSize: vi.fn((size: number) => size * 2), + roundToNearestPixel: vi.fn((size: number) => Math.round(size)), + }, StatusBar: { setBarStyle: vi.fn(), }, @@ -192,3 +198,56 @@ vi.mock('react-native-localize', () => ({ isRTL: false, }), })); + +// Mock react-native-svg +vi.mock('react-native-svg', () => ({ + default: 'svg', + Svg: 'svg', + Circle: 'circle', + Ellipse: 'ellipse', + G: 'g', + Text: 'text', + TSpan: 'tspan', + TextPath: 'textPath', + Path: 'path', + Polygon: 'polygon', + Polyline: 'polyline', + Line: 'line', + Rect: 'rect', + Use: 'use', + Image: 'image', + Symbol: 'symbol', + Defs: 'defs', + LinearGradient: 'linearGradient', + RadialGradient: 'radialGradient', + Stop: 'stop', + ClipPath: 'clipPath', + Pattern: 'pattern', + Mask: 'mask', +})); + +// Mock react-native-svg-circle-country-flags +vi.mock('react-native-svg-circle-country-flags', () => ({ + default: {}, +})); + +// Mock lottie-react-native +vi.mock('lottie-react-native', () => ({ + default: 'div', +})); + +// Mock react-native-haptic-feedback +vi.mock('react-native-haptic-feedback', () => ({ + default: { + trigger: vi.fn(), + }, + HapticFeedbackTypes: { + impactLight: 'impactLight', + impactMedium: 'impactMedium', + impactHeavy: 'impactHeavy', + notificationSuccess: 'notificationSuccess', + notificationWarning: 'notificationWarning', + notificationError: 'notificationError', + selection: 'selection', + }, +})); diff --git a/packages/mobile-sdk-demo/metro.config.cjs b/packages/mobile-sdk-demo/metro.config.cjs index 8c96308c2..f4f46d152 100644 --- a/packages/mobile-sdk-demo/metro.config.cjs +++ b/packages/mobile-sdk-demo/metro.config.cjs @@ -67,8 +67,11 @@ const config = { unstable_conditionNames: ['react-native', 'import', 'require'], unstable_enableSymlinks: true, nodeModulesPaths: [path.resolve(projectRoot, 'node_modules'), path.resolve(workspaceRoot, 'node_modules')], + + // SVG support assetExts: assetExts.filter(ext => ext !== 'svg'), sourceExts: [...sourceExts, 'svg'], + extraNodeModules: { // Add workspace packages for proper resolution '@selfxyz/common': path.resolve(workspaceRoot, 'common'), diff --git a/packages/mobile-sdk-demo/package.json b/packages/mobile-sdk-demo/package.json index f4a27ac3a..d7b4ec8f7 100644 --- a/packages/mobile-sdk-demo/package.json +++ b/packages/mobile-sdk-demo/package.json @@ -38,6 +38,8 @@ "buffer": "^6.0.3", "constants-browserify": "^1.0.0", "ethers": "^6.11.0", + "lottie-react": "^2.4.1", + "lottie-react-native": "7.2.2", "react": "^18.3.1", "react-native": "0.76.9", "react-native-get-random-values": "^1.11.0", diff --git a/packages/mobile-sdk-demo/src/hooks/useMRZScanner.ts b/packages/mobile-sdk-demo/src/hooks/useMRZScanner.ts deleted file mode 100644 index 39b5ba4f0..000000000 --- a/packages/mobile-sdk-demo/src/hooks/useMRZScanner.ts +++ /dev/null @@ -1,183 +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 { useCallback, useEffect, useMemo, useRef, useState } from 'react'; -import { AccessibilityInfo, PermissionsAndroid, Platform } from 'react-native'; - -import type { MRZInfo } from '@selfxyz/mobile-sdk-alpha'; -import { useReadMRZ } from '@selfxyz/mobile-sdk-alpha/onboarding/read-mrz'; - -import type { NormalizedMRZResult } from '../utils/camera'; -import { normalizeMRZPayload } from '../utils/camera'; - -type PermissionState = 'loading' | 'granted' | 'denied'; -type ScanState = 'idle' | 'scanning' | 'success' | 'error'; - -function announceForAccessibility(message: string) { - if (!message) { - return; - } - - try { - AccessibilityInfo.announceForAccessibility?.(message); - } catch { - // Intentionally swallow to avoid crashing accessibility users on announce failures. - } -} - -export interface DocumentScannerCopy { - instructions: string; - success: string; - error: string; - permissionDenied: string; - resetAnnouncement: string; -} - -export interface DocumentScannerState { - permissionStatus: PermissionState; - scanState: ScanState; - mrzResult: NormalizedMRZResult | null; - error: string | null; - requestPermission: () => Promise; - handleMRZDetected: (payload: MRZInfo) => void; - handleScannerError: (error: string) => void; - handleScanAgain: () => void; -} - -export function useMRZScanner(copy: DocumentScannerCopy): DocumentScannerState { - const [permissionStatus, setPermissionStatus] = useState('loading'); - const [scanState, setScanState] = useState('idle'); - const [mrzResult, setMrzResult] = useState(null); - const [error, setError] = useState(null); - - const scanStartTimeRef = useRef(Date.now()); - const { onPassportRead } = useReadMRZ(scanStartTimeRef); - - const requestPermission = useCallback(async () => { - setPermissionStatus('loading'); - setError(null); - - if (Platform.OS === 'android') { - try { - const result = await PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.CAMERA, { - title: 'Camera permission', - message: 'We need your permission to access the camera for MRZ scanning.', - buttonPositive: 'Allow', - buttonNegative: 'Cancel', - buttonNeutral: 'Ask me later', - }); - - if (result === PermissionsAndroid.RESULTS.GRANTED) { - setPermissionStatus('granted'); - } else { - setPermissionStatus('denied'); - } - } catch { - setPermissionStatus('denied'); - setError('Camera permission request failed. Please try again.'); - } - } else { - setPermissionStatus('granted'); - } - }, []); - - useEffect(() => { - requestPermission(); - }, [requestPermission]); - - useEffect(() => { - if (permissionStatus === 'granted') { - announceForAccessibility(copy.instructions); - setScanState(current => { - if (current === 'success') { - return current; - } - scanStartTimeRef.current = Date.now(); - return 'scanning'; - }); - } else if (permissionStatus === 'denied') { - announceForAccessibility(copy.permissionDenied); - setScanState('idle'); - } - }, [copy.instructions, copy.permissionDenied, permissionStatus]); - - useEffect(() => { - if (scanState === 'success') { - announceForAccessibility(copy.success); - } else if (scanState === 'error') { - announceForAccessibility(copy.error); - } - }, [copy.error, copy.success, scanState]); - - useEffect(() => { - if (error) { - announceForAccessibility(error); - } - }, [error]); - - const handleMRZDetected = useCallback( - (payload: MRZInfo) => { - setError(null); - - setScanState(current => { - if (current === 'success') { - return current; - } - return 'scanning'; - }); - - try { - const normalized = normalizeMRZPayload(payload); - setMrzResult(normalized); - setScanState('success'); - onPassportRead(null, normalized.info); - } catch { - setScanState('error'); - setError('Unable to validate the MRZ data from the scan.'); - } - }, - [onPassportRead], - ); - - const handleScannerError = useCallback((scannerError: string) => { - setScanState('error'); - setError(scannerError || 'An unexpected camera error occurred.'); - }, []); - - const handleScanAgain = useCallback(() => { - if (permissionStatus === 'denied') { - requestPermission(); - return; - } - - scanStartTimeRef.current = Date.now(); - setMrzResult(null); - setError(null); - setScanState('scanning'); - announceForAccessibility(copy.resetAnnouncement); - }, [copy.resetAnnouncement, permissionStatus, requestPermission]); - - return useMemo( - () => ({ - permissionStatus, - scanState, - mrzResult, - error, - requestPermission, - handleMRZDetected, - handleScannerError, - handleScanAgain, - }), - [ - error, - handleMRZDetected, - handleScanAgain, - handleScannerError, - mrzResult, - permissionStatus, - requestPermission, - scanState, - ], - ); -} diff --git a/packages/mobile-sdk-demo/src/screens/DocumentCamera.tsx b/packages/mobile-sdk-demo/src/screens/DocumentCamera.tsx index a065b4070..192b4f554 100644 --- a/packages/mobile-sdk-demo/src/screens/DocumentCamera.tsx +++ b/packages/mobile-sdk-demo/src/screens/DocumentCamera.tsx @@ -2,225 +2,19 @@ // SPDX-License-Identifier: BUSL-1.1 // NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE. -import React, { useCallback } from 'react'; -import { ActivityIndicator, Alert, StyleSheet, Text, TouchableOpacity, View } from 'react-native'; +import React from 'react'; -import { MRZScannerView } from '@selfxyz/mobile-sdk-alpha/onboarding/read-mrz'; - -import ScreenLayout from '../components/ScreenLayout'; -import DocumentScanResultCard from '../components/DocumentScanResultCard'; -import { useMRZScanner } from '../hooks/useMRZScanner'; +import { DocumentCameraScreen } from '@selfxyz/mobile-sdk-alpha/onboarding/document-camera-screen'; type Props = { onBack: () => void; + onSuccess: () => void; }; -const instructionsText = 'Align the machine-readable text with the frame and hold steady while we scan.'; - -const successMessage = 'Document scan successful. Review the details below.'; -const errorMessage = 'We could not read your document. Adjust lighting and try again.'; -const permissionDeniedMessage = 'Camera access was denied. Enable permissions to scan your document.'; - -export default function DocumentCamera({ onBack }: Props) { - const scannerCopy = { - instructions: instructionsText, - success: successMessage, - error: errorMessage, - permissionDenied: permissionDeniedMessage, - resetAnnouncement: 'Ready to scan again. Align the document in the viewfinder.', - } as const; - - const { - permissionStatus, - scanState, - mrzResult, - error, - requestPermission, - handleMRZDetected, - handleScannerError, - handleScanAgain, - } = useMRZScanner(scannerCopy); - - const handleSaveDocument = useCallback(() => { - if (!mrzResult) { - Alert.alert('Save Document', 'Scan a document before attempting to save.'); - return; - } - - Alert.alert( - 'Save Document', - 'Document storage will be available in a future release. Your scan is ready when you need it.', - ); - }, [mrzResult]); - - const renderPermissionDenied = () => ( - - {permissionDeniedMessage} - - Request Permission - - - ); - - const renderLoading = () => ( - - - Preparing camera… - - ); - +export default function DocumentCamera({ onBack, onSuccess }: Props) { return ( - { - onBack(); - }} - contentStyle={styles.screenContent} - > - {permissionStatus === 'loading' && renderLoading()} - {permissionStatus === 'denied' && renderPermissionDenied()} - - {permissionStatus === 'granted' && ( - - - Position your document - {instructionsText} - - - - - - - - {scanState === 'scanning' && !error && ( - - - Scanning for MRZ data… - - )} - - {scanState === 'success' && mrzResult && ( - {successMessage} - )} - - {scanState === 'error' && error && {error}} - - - - - Scan Again - - - - Save Document - - - - {mrzResult && } - - )} - + <> + + ); } - -const styles = StyleSheet.create({ - screenContent: { - gap: 16, - }, - contentWrapper: { - flex: 1, - }, - instructionsContainer: { - marginBottom: 16, - }, - instructionsTitle: { - color: '#0f172a', - fontWeight: '600', - fontSize: 16, - marginBottom: 4, - }, - instructionsText: { - color: '#475569', - fontSize: 14, - lineHeight: 20, - }, - cameraWrapper: { - backgroundColor: '#0f172a', - borderRadius: 16, - overflow: 'hidden', - minHeight: 260, - marginBottom: 16, - }, - scanner: { - flex: 1, - width: '100%', - height: '100%', - backgroundColor: '#0f172a', - }, - statusContainer: { - marginBottom: 16, - alignItems: 'center', - }, - statusRow: { - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'center', - gap: 8, - }, - statusText: { - color: '#0f172a', - fontSize: 14, - marginTop: 8, - }, - successText: { - color: '#15803d', - fontWeight: '600', - }, - errorText: { - color: '#b91c1c', - fontWeight: '600', - }, - actions: { - flexDirection: 'row', - gap: 12, - }, - actionsWithResult: { - marginBottom: 16, - }, - primaryButton: { - flex: 1, - backgroundColor: '#0f172a', - paddingVertical: 12, - borderRadius: 8, - alignItems: 'center', - }, - primaryButtonText: { - color: '#ffffff', - fontSize: 15, - fontWeight: '600', - }, - secondaryButton: { - flex: 1, - backgroundColor: '#e2e8f0', - paddingVertical: 12, - borderRadius: 8, - alignItems: 'center', - }, - secondaryButtonText: { - color: '#0f172a', - fontSize: 15, - fontWeight: '600', - }, - centeredState: { - flex: 1, - alignItems: 'center', - justifyContent: 'center', - gap: 12, - }, - permissionText: { - color: '#0f172a', - textAlign: 'center', - fontSize: 15, - lineHeight: 22, - }, -}); diff --git a/packages/mobile-sdk-demo/src/screens/index.ts b/packages/mobile-sdk-demo/src/screens/index.ts index 4be4e64bb..ee37bb2fb 100644 --- a/packages/mobile-sdk-demo/src/screens/index.ts +++ b/packages/mobile-sdk-demo/src/screens/index.ts @@ -74,7 +74,10 @@ export const screenDescriptors: ScreenDescriptor[] = [ sectionTitle: '📸 Scanning', status: 'placeholder', load: () => require('./DocumentCamera').default, - getProps: ({ navigate }) => ({ onBack: () => navigate('home') }), + getProps: ({ navigate }) => ({ + onBack: () => navigate('home'), + onSuccess: () => navigate('nfc'), + }), }, { id: 'nfc', diff --git a/packages/mobile-sdk-demo/tests/screens/DocumentCamera.test.tsx b/packages/mobile-sdk-demo/tests/screens/DocumentCamera.test.tsx index f4be57707..9bfe15419 100644 --- a/packages/mobile-sdk-demo/tests/screens/DocumentCamera.test.tsx +++ b/packages/mobile-sdk-demo/tests/screens/DocumentCamera.test.tsx @@ -8,8 +8,9 @@ import DocumentCamera from '../../src/screens/DocumentCamera'; describe('DocumentCamera screen', () => { it('shows placeholder messaging and handles back navigation', async () => { const onBack = vi.fn(); + const onSuccess = vi.fn(); - render(); + render(); expect(screen.getByText('Document Camera')).toBeInTheDocument(); expect(screen.getByText(/camera-based document scanning/i)).toBeInTheDocument(); diff --git a/yarn.lock b/yarn.lock index dfc5f28b7..d79760da9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7457,6 +7457,7 @@ __metadata: eslint-plugin-simple-import-sort: "npm:^12.1.1" eslint-plugin-sort-exports: "npm:^0.9.1" jsdom: "npm:^25.0.1" + lottie-react-native: "npm:7.2.2" node-forge: "npm:^1.3.1" prettier: "npm:^3.5.3" react: "npm:^18.3.1" @@ -7474,6 +7475,7 @@ __metadata: xstate: "npm:^5.20.2" zustand: "npm:^4.5.2" peerDependencies: + lottie-react-native: 7.2.2 react: ^18.3.1 react-native: 0.76.9 react-native-haptic-feedback: "*" @@ -23818,6 +23820,8 @@ __metadata: ethers: "npm:^6.11.0" find-yarn-workspace-root: "npm:^2.0.0" jsdom: "npm:^25.0.1" + lottie-react: "npm:^2.4.1" + lottie-react-native: "npm:7.2.2" metro-react-native-babel-preset: "npm:0.76.9" prettier: "npm:^3.6.2" react: "npm:^18.3.1"