@smileid/usesmileid 12.0.0-beta01 → 12.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/README.md +701 -89
- package/dist/camera/camera_defaults.d.ts +14 -9
- package/dist/camera/camera_defaults.d.ts.map +1 -1
- package/dist/camera/camera_defaults.js +11 -9
- package/dist/camera/camera_defaults.js.map +1 -1
- package/dist/camera/orientation_degrees.d.ts +5 -6
- package/dist/camera/orientation_degrees.d.ts.map +1 -1
- package/dist/camera/orientation_degrees.js +5 -6
- package/dist/camera/orientation_degrees.js.map +1 -1
- package/dist/core/models/document_capture_mode.d.ts +8 -0
- package/dist/core/models/document_capture_mode.d.ts.map +1 -1
- package/dist/core/models/document_capture_mode.js +24 -0
- package/dist/core/models/document_capture_mode.js.map +1 -1
- package/dist/core/models/document_type.d.ts +2 -2
- package/dist/core/models/document_type.d.ts.map +1 -1
- package/dist/core/models/document_type.js +6 -4
- package/dist/core/models/document_type.js.map +1 -1
- package/dist/core/models/result.d.ts +9 -8
- package/dist/core/models/result.d.ts.map +1 -1
- package/dist/core/models/result.js +5 -6
- package/dist/core/models/result.js.map +1 -1
- package/dist/data/api/interceptors/smile_auth_interceptor.js +1 -1
- package/dist/data/api/interceptors/smile_auth_interceptor.js.map +1 -1
- package/dist/data/api/interceptors/smile_integrity_interceptor.d.ts +11 -0
- package/dist/data/api/interceptors/smile_integrity_interceptor.d.ts.map +1 -1
- package/dist/data/api/interceptors/smile_integrity_interceptor.js +13 -0
- package/dist/data/api/interceptors/smile_integrity_interceptor.js.map +1 -1
- package/dist/data/api/interceptors/smile_request_mac_interceptor.d.ts +8 -0
- package/dist/data/api/interceptors/smile_request_mac_interceptor.d.ts.map +1 -1
- package/dist/data/api/interceptors/smile_request_mac_interceptor.js +11 -0
- package/dist/data/api/interceptors/smile_request_mac_interceptor.js.map +1 -1
- package/dist/data/compression/compressible_asset.d.ts +41 -0
- package/dist/data/compression/compressible_asset.d.ts.map +1 -0
- package/dist/data/compression/compressible_asset.js +34 -0
- package/dist/data/compression/compressible_asset.js.map +1 -0
- package/dist/data/compression/payload_compression_config.d.ts +36 -0
- package/dist/data/compression/payload_compression_config.d.ts.map +1 -0
- package/dist/data/compression/payload_compression_config.js +52 -0
- package/dist/data/compression/payload_compression_config.js.map +1 -0
- package/dist/data/compression/payload_compression_runner.d.ts +29 -0
- package/dist/data/compression/payload_compression_runner.d.ts.map +1 -0
- package/dist/data/compression/payload_compression_runner.js +55 -0
- package/dist/data/compression/payload_compression_runner.js.map +1 -0
- package/dist/data/compression/payload_compressor.d.ts +40 -0
- package/dist/data/compression/payload_compressor.d.ts.map +1 -0
- package/dist/data/compression/payload_compressor.js +126 -0
- package/dist/data/compression/payload_compressor.js.map +1 -0
- package/dist/data/compression/uri_compressible_asset.d.ts +23 -0
- package/dist/data/compression/uri_compressible_asset.d.ts.map +1 -0
- package/dist/data/compression/uri_compressible_asset.js +77 -0
- package/dist/data/compression/uri_compressible_asset.js.map +1 -0
- package/dist/data/dsl/builder/cache_config_builder.d.ts +2 -1
- package/dist/data/dsl/builder/cache_config_builder.d.ts.map +1 -1
- package/dist/data/dsl/builder/cache_config_builder.js +2 -1
- package/dist/data/dsl/builder/cache_config_builder.js.map +1 -1
- package/dist/data/dsl/builder/config_builder.d.ts +40 -14
- package/dist/data/dsl/builder/config_builder.d.ts.map +1 -1
- package/dist/data/dsl/builder/config_builder.js +40 -14
- package/dist/data/dsl/builder/config_builder.js.map +1 -1
- package/dist/data/dsl/builder/interceptor_config_builder.d.ts +9 -7
- package/dist/data/dsl/builder/interceptor_config_builder.d.ts.map +1 -1
- package/dist/data/dsl/builder/interceptor_config_builder.js +9 -7
- package/dist/data/dsl/builder/interceptor_config_builder.js.map +1 -1
- package/dist/data/dsl/builder/retry_config_builder.d.ts +16 -1
- package/dist/data/dsl/builder/retry_config_builder.d.ts.map +1 -1
- package/dist/data/dsl/builder/retry_config_builder.js +16 -1
- package/dist/data/dsl/builder/retry_config_builder.js.map +1 -1
- package/dist/data/dsl/builder/timeout_config_builder.d.ts +4 -0
- package/dist/data/dsl/builder/timeout_config_builder.d.ts.map +1 -1
- package/dist/data/dsl/builder/timeout_config_builder.js +4 -0
- package/dist/data/dsl/builder/timeout_config_builder.js.map +1 -1
- package/dist/data/dsl/use_smile_id_network_builder.d.ts +17 -0
- package/dist/data/dsl/use_smile_id_network_builder.d.ts.map +1 -1
- package/dist/data/dsl/use_smile_id_network_builder.js +17 -0
- package/dist/data/dsl/use_smile_id_network_builder.js.map +1 -1
- package/dist/data/factory/networking_factory.d.ts.map +1 -1
- package/dist/data/factory/networking_factory.js +11 -1
- package/dist/data/factory/networking_factory.js.map +1 -1
- package/dist/data/repository/use_smile_id_repository_impl.d.ts +6 -0
- package/dist/data/repository/use_smile_id_repository_impl.d.ts.map +1 -1
- package/dist/data/repository/use_smile_id_repository_impl.js +82 -8
- package/dist/data/repository/use_smile_id_repository_impl.js.map +1 -1
- package/dist/data/security/request_canonicalizer.d.ts.map +1 -1
- package/dist/data/security/request_canonicalizer.js +14 -2
- package/dist/data/security/request_canonicalizer.js.map +1 -1
- package/dist/data/security/security_policy.d.ts +43 -0
- package/dist/data/security/security_policy.d.ts.map +1 -0
- package/dist/data/security/security_policy.js +61 -0
- package/dist/data/security/security_policy.js.map +1 -0
- package/dist/data/util/retry_util.d.ts +1 -1
- package/dist/data/util/retry_util.d.ts.map +1 -1
- package/dist/data/util/retry_util.js +2 -1
- package/dist/data/util/retry_util.js.map +1 -1
- package/dist/data/util/use_smile_id_token_decoder.d.ts +22 -0
- package/dist/data/util/use_smile_id_token_decoder.d.ts.map +1 -1
- package/dist/data/util/use_smile_id_token_decoder.js +58 -24
- package/dist/data/util/use_smile_id_token_decoder.js.map +1 -1
- package/dist/l10n/strings_en.d.ts +2 -1
- package/dist/l10n/strings_en.d.ts.map +1 -1
- package/dist/l10n/strings_en.js +2 -1
- package/dist/l10n/strings_en.js.map +1 -1
- package/dist/l10n/use_smile_id_localizations.d.ts +1 -0
- package/dist/l10n/use_smile_id_localizations.d.ts.map +1 -1
- package/dist/l10n/use_smile_id_localizations.js +3 -0
- package/dist/l10n/use_smile_id_localizations.js.map +1 -1
- package/dist/metadata/builder_configuration.d.ts +39 -0
- package/dist/metadata/builder_configuration.d.ts.map +1 -0
- package/dist/metadata/builder_configuration.js +34 -0
- package/dist/metadata/builder_configuration.js.map +1 -0
- package/dist/metadata/captured_image_properties.d.ts +11 -0
- package/dist/metadata/captured_image_properties.d.ts.map +1 -0
- package/dist/metadata/captured_image_properties.js +11 -0
- package/dist/metadata/captured_image_properties.js.map +1 -0
- package/dist/metadata/device_orientation_collector.d.ts +17 -0
- package/dist/metadata/device_orientation_collector.d.ts.map +1 -0
- package/dist/metadata/device_orientation_collector.js +66 -0
- package/dist/metadata/device_orientation_collector.js.map +1 -0
- package/dist/metadata/geolocation.d.ts +20 -0
- package/dist/metadata/geolocation.d.ts.map +1 -0
- package/dist/metadata/geolocation.js +40 -0
- package/dist/metadata/geolocation.js.map +1 -0
- package/dist/metadata/metadata_configuration_mappers.d.ts +48 -0
- package/dist/metadata/metadata_configuration_mappers.d.ts.map +1 -0
- package/dist/metadata/metadata_configuration_mappers.js +171 -0
- package/dist/metadata/metadata_configuration_mappers.js.map +1 -0
- package/dist/metadata/model_configuration.d.ts +41 -0
- package/dist/metadata/model_configuration.d.ts.map +1 -0
- package/dist/metadata/model_configuration.js +44 -0
- package/dist/metadata/model_configuration.js.map +1 -0
- package/dist/metadata/optional_native_modules.d.ts +79 -3
- package/dist/metadata/optional_native_modules.d.ts.map +1 -1
- package/dist/metadata/optional_native_modules.js +108 -3
- package/dist/metadata/optional_native_modules.js.map +1 -1
- package/dist/metadata/use_smile_id_metadata.d.ts +45 -7
- package/dist/metadata/use_smile_id_metadata.d.ts.map +1 -1
- package/dist/metadata/use_smile_id_metadata.js +85 -13
- package/dist/metadata/use_smile_id_metadata.js.map +1 -1
- package/dist/metadata/use_smile_id_metadata_factory.d.ts +37 -0
- package/dist/metadata/use_smile_id_metadata_factory.d.ts.map +1 -1
- package/dist/metadata/use_smile_id_metadata_factory.js +184 -12
- package/dist/metadata/use_smile_id_metadata_factory.js.map +1 -1
- package/dist/presentation/assets/svg/document_shimmer_strings.d.ts +14 -0
- package/dist/presentation/assets/svg/document_shimmer_strings.d.ts.map +1 -0
- package/dist/presentation/assets/svg/document_shimmer_strings.js +14 -0
- package/dist/presentation/assets/svg/document_shimmer_strings.js.map +1 -0
- package/dist/presentation/assets/svg/instruction_svg_strings.d.ts +12 -4
- package/dist/presentation/assets/svg/instruction_svg_strings.d.ts.map +1 -1
- package/dist/presentation/assets/svg/instruction_svg_strings.js +19 -8
- package/dist/presentation/assets/svg/instruction_svg_strings.js.map +1 -1
- package/dist/presentation/components/helpers/enhanced_smart_selfie_animation_frames.d.ts +0 -5
- package/dist/presentation/components/helpers/enhanced_smart_selfie_animation_frames.d.ts.map +1 -1
- package/dist/presentation/components/helpers/enhanced_smart_selfie_animation_frames.js +0 -5
- package/dist/presentation/components/helpers/enhanced_smart_selfie_animation_frames.js.map +1 -1
- package/dist/presentation/components/icons/index.d.ts +24 -8
- package/dist/presentation/components/icons/index.d.ts.map +1 -1
- package/dist/presentation/components/icons/index.js +31 -11
- package/dist/presentation/components/icons/index.js.map +1 -1
- package/dist/presentation/components/use_smile_id_attribution.d.ts +1 -1
- package/dist/presentation/components/use_smile_id_button.d.ts +2 -2
- package/dist/presentation/components/use_smile_id_button.js +4 -4
- package/dist/presentation/components/use_smile_id_button.js.map +1 -1
- package/dist/presentation/components/use_smile_id_capture_content.d.ts +13 -0
- package/dist/presentation/components/use_smile_id_capture_content.d.ts.map +1 -1
- package/dist/presentation/components/use_smile_id_capture_content.js +15 -9
- package/dist/presentation/components/use_smile_id_capture_content.js.map +1 -1
- package/dist/presentation/components/use_smile_id_captured_document_image.d.ts +2 -3
- package/dist/presentation/components/use_smile_id_captured_document_image.d.ts.map +1 -1
- package/dist/presentation/components/use_smile_id_captured_document_image.js +1 -3
- package/dist/presentation/components/use_smile_id_captured_document_image.js.map +1 -1
- package/dist/presentation/components/use_smile_id_document_capture_controls.d.ts +12 -6
- package/dist/presentation/components/use_smile_id_document_capture_controls.d.ts.map +1 -1
- package/dist/presentation/components/use_smile_id_document_capture_controls.js +59 -16
- package/dist/presentation/components/use_smile_id_document_capture_controls.js.map +1 -1
- package/dist/presentation/components/use_smile_id_document_overlay.d.ts +22 -5
- package/dist/presentation/components/use_smile_id_document_overlay.d.ts.map +1 -1
- package/dist/presentation/components/use_smile_id_document_overlay.js +80 -40
- package/dist/presentation/components/use_smile_id_document_overlay.js.map +1 -1
- package/dist/presentation/components/use_smile_id_document_shimmer.d.ts +15 -0
- package/dist/presentation/components/use_smile_id_document_shimmer.d.ts.map +1 -0
- package/dist/presentation/components/use_smile_id_document_shimmer.js +23 -0
- package/dist/presentation/components/use_smile_id_document_shimmer.js.map +1 -0
- package/dist/presentation/components/use_smile_id_enhanced_smart_selfie_clip.d.ts.map +1 -1
- package/dist/presentation/components/use_smile_id_enhanced_smart_selfie_clip.js +1 -3
- package/dist/presentation/components/use_smile_id_enhanced_smart_selfie_clip.js.map +1 -1
- package/dist/presentation/components/use_smile_id_guideline_thumbnail.d.ts.map +1 -1
- package/dist/presentation/components/use_smile_id_guideline_thumbnail.js +84 -1
- package/dist/presentation/components/use_smile_id_guideline_thumbnail.js.map +1 -1
- package/dist/presentation/components/use_smile_id_instructions_hero.d.ts +3 -1
- package/dist/presentation/components/use_smile_id_instructions_hero.d.ts.map +1 -1
- package/dist/presentation/components/use_smile_id_instructions_hero.js +18 -3
- package/dist/presentation/components/use_smile_id_instructions_hero.js.map +1 -1
- package/dist/presentation/components/use_smile_id_oval_border_palette.d.ts.map +1 -1
- package/dist/presentation/components/use_smile_id_oval_border_palette.js +7 -3
- package/dist/presentation/components/use_smile_id_oval_border_palette.js.map +1 -1
- package/dist/presentation/flow/dsl/builder/config_builder.d.ts +12 -0
- package/dist/presentation/flow/dsl/builder/config_builder.d.ts.map +1 -1
- package/dist/presentation/flow/dsl/builder/config_builder.js +12 -0
- package/dist/presentation/flow/dsl/builder/config_builder.js.map +1 -1
- package/dist/presentation/flow/dsl/builder/ml_builder.d.ts +13 -4
- package/dist/presentation/flow/dsl/builder/ml_builder.d.ts.map +1 -1
- package/dist/presentation/flow/dsl/builder/ml_builder.js +3 -2
- package/dist/presentation/flow/dsl/builder/ml_builder.js.map +1 -1
- package/dist/presentation/flow/dsl/builder/screens_builder.d.ts +111 -10
- package/dist/presentation/flow/dsl/builder/screens_builder.d.ts.map +1 -1
- package/dist/presentation/flow/dsl/builder/screens_builder.js +111 -10
- package/dist/presentation/flow/dsl/builder/screens_builder.js.map +1 -1
- package/dist/presentation/flow/dsl/builder/theme_builder.d.ts +15 -2
- package/dist/presentation/flow/dsl/builder/theme_builder.d.ts.map +1 -1
- package/dist/presentation/flow/dsl/builder/theme_builder.js +15 -2
- package/dist/presentation/flow/dsl/builder/theme_builder.js.map +1 -1
- package/dist/presentation/flow/dsl/use_smile_id_builder.d.ts +6 -4
- package/dist/presentation/flow/dsl/use_smile_id_builder.d.ts.map +1 -1
- package/dist/presentation/flow/dsl/use_smile_id_builder.js.map +1 -1
- package/dist/presentation/flow/dsl/use_smile_id_flow_builder.d.ts +62 -36
- package/dist/presentation/flow/dsl/use_smile_id_flow_builder.d.ts.map +1 -1
- package/dist/presentation/flow/dsl/use_smile_id_flow_builder.js +62 -36
- package/dist/presentation/flow/dsl/use_smile_id_flow_builder.js.map +1 -1
- package/dist/presentation/flow/flow_navigation_manager.d.ts +39 -4
- package/dist/presentation/flow/flow_navigation_manager.d.ts.map +1 -1
- package/dist/presentation/flow/flow_navigation_manager.js +141 -10
- package/dist/presentation/flow/flow_navigation_manager.js.map +1 -1
- package/dist/presentation/flow/model/instruction_guideline.d.ts +9 -0
- package/dist/presentation/flow/model/instruction_guideline.d.ts.map +1 -1
- package/dist/presentation/flow/model/instructions_defaults.d.ts +11 -2
- package/dist/presentation/flow/model/instructions_defaults.d.ts.map +1 -1
- package/dist/presentation/flow/model/instructions_defaults.js +73 -25
- package/dist/presentation/flow/model/instructions_defaults.js.map +1 -1
- package/dist/presentation/flow/screen/orchestrated_capture_screen.d.ts.map +1 -1
- package/dist/presentation/flow/screen/orchestrated_capture_screen.js +36 -12
- package/dist/presentation/flow/screen/orchestrated_capture_screen.js.map +1 -1
- package/dist/presentation/flow/screen/orchestrated_instructions_screen.js +1 -1
- package/dist/presentation/flow/screen/orchestrated_instructions_screen.js.map +1 -1
- package/dist/presentation/flow/screen/orchestrated_preview_screen.d.ts.map +1 -1
- package/dist/presentation/flow/screen/orchestrated_preview_screen.js +3 -1
- package/dist/presentation/flow/screen/orchestrated_preview_screen.js.map +1 -1
- package/dist/presentation/flow/screen/orchestrated_processing_screen.js +3 -3
- package/dist/presentation/flow/screen/orchestrated_processing_screen.js.map +1 -1
- package/dist/presentation/flow/validation/job_type_validator.d.ts.map +1 -1
- package/dist/presentation/flow/validation/job_type_validator.js +14 -0
- package/dist/presentation/flow/validation/job_type_validator.js.map +1 -1
- package/dist/presentation/screen/helpers/capture_screen_helpers.d.ts.map +1 -1
- package/dist/presentation/screen/helpers/capture_screen_helpers.js +1 -0
- package/dist/presentation/screen/helpers/capture_screen_helpers.js.map +1 -1
- package/dist/presentation/screen/helpers/instructions_screen_helpers.d.ts +1 -0
- package/dist/presentation/screen/helpers/instructions_screen_helpers.d.ts.map +1 -1
- package/dist/presentation/screen/helpers/instructions_screen_helpers.js +6 -2
- package/dist/presentation/screen/helpers/instructions_screen_helpers.js.map +1 -1
- package/dist/presentation/screen/helpers/scan_state_to_overlay_state.js +3 -0
- package/dist/presentation/screen/helpers/scan_state_to_overlay_state.js.map +1 -1
- package/dist/presentation/screen/use_smile_id_capture_screen.d.ts +17 -1
- package/dist/presentation/screen/use_smile_id_capture_screen.d.ts.map +1 -1
- package/dist/presentation/screen/use_smile_id_capture_screen.js +153 -18
- package/dist/presentation/screen/use_smile_id_capture_screen.js.map +1 -1
- package/dist/presentation/screen/use_smile_id_document_preview_screen.d.ts +2 -3
- package/dist/presentation/screen/use_smile_id_document_preview_screen.d.ts.map +1 -1
- package/dist/presentation/screen/use_smile_id_document_preview_screen.js +16 -11
- package/dist/presentation/screen/use_smile_id_document_preview_screen.js.map +1 -1
- package/dist/presentation/screen/use_smile_id_instructions_screen.d.ts +2 -0
- package/dist/presentation/screen/use_smile_id_instructions_screen.d.ts.map +1 -1
- package/dist/presentation/screen/use_smile_id_instructions_screen.js +2 -1
- package/dist/presentation/screen/use_smile_id_instructions_screen.js.map +1 -1
- package/dist/presentation/screen/use_smile_id_preview_screen.d.ts +7 -6
- package/dist/presentation/screen/use_smile_id_preview_screen.d.ts.map +1 -1
- package/dist/presentation/screen/use_smile_id_preview_screen.js +9 -8
- package/dist/presentation/screen/use_smile_id_preview_screen.js.map +1 -1
- package/dist/presentation/screen/use_smile_id_processing_screen.d.ts +2 -3
- package/dist/presentation/screen/use_smile_id_processing_screen.d.ts.map +1 -1
- package/dist/presentation/screen/use_smile_id_processing_screen.js +3 -2
- package/dist/presentation/screen/use_smile_id_processing_screen.js.map +1 -1
- package/dist/presentation/theme/theme.d.ts +1 -1
- package/dist/presentation/theme/theme.d.ts.map +1 -1
- package/dist/presentation/theme/theme.js +20 -18
- package/dist/presentation/theme/theme.js.map +1 -1
- package/dist/presentation/utils/force_max_brightness.d.ts +4 -4
- package/package.json +26 -6
- package/src/__tests__/react_native_mock.tsx +8 -0
- package/src/camera/camera_defaults.ts +11 -9
- package/src/camera/orientation_degrees.ts +5 -6
- package/src/core/models/__tests__/document_type.test.ts +6 -4
- package/src/core/models/document_capture_mode.ts +27 -0
- package/src/core/models/document_type.ts +6 -4
- package/src/core/models/result.ts +9 -8
- package/src/data/api/interceptors/__tests__/smile_integrity_interceptor.test.ts +37 -1
- package/src/data/api/interceptors/__tests__/smile_request_mac_interceptor.test.ts +59 -1
- package/src/data/api/interceptors/smile_auth_interceptor.ts +1 -1
- package/src/data/api/interceptors/smile_integrity_interceptor.ts +20 -0
- package/src/data/api/interceptors/smile_request_mac_interceptor.ts +13 -0
- package/src/data/compression/__tests__/payload_compressor.test.ts +200 -0
- package/src/data/compression/__tests__/payload_compressor_real_jpeg.test.ts +222 -0
- package/src/data/compression/compressible_asset.ts +62 -0
- package/src/data/compression/payload_compression_config.ts +53 -0
- package/src/data/compression/payload_compression_runner.ts +102 -0
- package/src/data/compression/payload_compressor.ts +164 -0
- package/src/data/compression/uri_compressible_asset.ts +85 -0
- package/src/data/dsl/builder/cache_config_builder.ts +3 -1
- package/src/data/dsl/builder/config_builder.ts +45 -14
- package/src/data/dsl/builder/interceptor_config_builder.ts +9 -7
- package/src/data/dsl/builder/retry_config_builder.ts +22 -1
- package/src/data/dsl/builder/timeout_config_builder.ts +7 -0
- package/src/data/dsl/use_smile_id_network_builder.ts +17 -0
- package/src/data/factory/networking_factory.ts +14 -1
- package/src/data/repository/__tests__/network_retries.test.ts +117 -0
- package/src/data/repository/use_smile_id_repository_impl.ts +96 -9
- package/src/data/security/__tests__/security_policy.test.ts +96 -0
- package/src/data/security/__tests__/smile_id_crypto_manager.test.ts +18 -0
- package/src/data/security/request_canonicalizer.ts +15 -2
- package/src/data/security/security_policy.ts +70 -0
- package/src/data/util/__tests__/use_smile_id_token_decoder.test.ts +57 -1
- package/src/data/util/retry_util.ts +3 -2
- package/src/data/util/use_smile_id_token_decoder.ts +76 -28
- package/src/l10n/strings_en.ts +2 -1
- package/src/l10n/use_smile_id_localizations.ts +3 -0
- package/src/metadata/__tests__/device_orientation_collector.test.ts +15 -0
- package/src/metadata/__tests__/metadata_configuration_mappers.test.ts +215 -0
- package/src/metadata/__tests__/metadata_configuration_objects.test.ts +85 -0
- package/src/metadata/__tests__/metadata_device_context.test.ts +147 -0
- package/src/metadata/__tests__/metadata_golden_fixture.json +13 -0
- package/src/metadata/__tests__/metadata_payload_golden.test.ts +193 -0
- package/src/metadata/__tests__/use_smile_id_metadata.test.ts +18 -24
- package/src/metadata/builder_configuration.ts +63 -0
- package/src/metadata/captured_image_properties.ts +10 -0
- package/src/metadata/device_orientation_collector.ts +75 -0
- package/src/metadata/geolocation.ts +46 -0
- package/src/metadata/metadata_configuration_mappers.ts +234 -0
- package/src/metadata/model_configuration.ts +68 -0
- package/src/metadata/optional_native_modules.ts +157 -3
- package/src/metadata/use_smile_id_metadata.ts +140 -17
- package/src/metadata/use_smile_id_metadata_factory.ts +195 -11
- package/src/presentation/assets/si_ess_animation_all_directions.json +1300 -286
- package/src/presentation/assets/svg/document_shimmer_strings.ts +17 -0
- package/src/presentation/assets/svg/instruction_svg_strings.ts +34 -12
- package/src/presentation/components/__tests__/enhanced_smart_selfie_animation_frames.test.ts +1 -3
- package/src/presentation/components/__tests__/use_smile_id_enhanced_smart_selfie_clip.test.tsx +3 -4
- package/src/presentation/components/__tests__/use_smile_id_guideline_thumbnail.test.tsx +34 -1
- package/src/presentation/components/__tests__/use_smile_id_instructions_hero.test.tsx +27 -0
- package/src/presentation/components/__tests__/use_smile_id_oval_border_palette.test.ts +7 -5
- package/src/presentation/components/helpers/enhanced_smart_selfie_animation_frames.ts +0 -6
- package/src/presentation/components/icons/index.tsx +65 -18
- package/src/presentation/components/use_smile_id_attribution.tsx +1 -1
- package/src/presentation/components/use_smile_id_button.tsx +4 -4
- package/src/presentation/components/use_smile_id_capture_content.tsx +36 -12
- package/src/presentation/components/use_smile_id_captured_document_image.tsx +3 -8
- package/src/presentation/components/use_smile_id_document_capture_controls.tsx +103 -39
- package/src/presentation/components/use_smile_id_document_overlay.tsx +134 -44
- package/src/presentation/components/use_smile_id_document_shimmer.tsx +51 -0
- package/src/presentation/components/use_smile_id_enhanced_smart_selfie_clip.tsx +0 -3
- package/src/presentation/components/use_smile_id_guideline_thumbnail.tsx +131 -2
- package/src/presentation/components/use_smile_id_instructions_hero.tsx +100 -59
- package/src/presentation/components/use_smile_id_oval_border_palette.ts +7 -3
- package/src/presentation/flow/__tests__/document_flow_navigation.test.ts +200 -1
- package/src/presentation/flow/dsl/builder/config_builder.ts +14 -0
- package/src/presentation/flow/dsl/builder/ml_builder.ts +13 -4
- package/src/presentation/flow/dsl/builder/screens_builder.ts +111 -10
- package/src/presentation/flow/dsl/builder/theme_builder.ts +19 -2
- package/src/presentation/flow/dsl/use_smile_id_builder.tsx +6 -4
- package/src/presentation/flow/dsl/use_smile_id_flow_builder.ts +62 -36
- package/src/presentation/flow/flow_navigation_manager.ts +179 -13
- package/src/presentation/flow/model/instruction_guideline.ts +6 -0
- package/src/presentation/flow/model/instructions_defaults.ts +103 -25
- package/src/presentation/flow/screen/orchestrated_capture_screen.tsx +43 -10
- package/src/presentation/flow/screen/orchestrated_instructions_screen.tsx +1 -0
- package/src/presentation/flow/screen/orchestrated_preview_screen.tsx +4 -2
- package/src/presentation/flow/screen/orchestrated_processing_screen.tsx +3 -3
- package/src/presentation/flow/validation/__tests__/job_type_validator.test.ts +64 -0
- package/src/presentation/flow/validation/job_type_validator.ts +24 -0
- package/src/presentation/screen/__tests__/instructions_screen_helpers.test.ts +15 -3
- package/src/presentation/screen/__tests__/use_smile_id_capture_screen.test.tsx +6 -4
- package/src/presentation/screen/helpers/capture_screen_helpers.ts +1 -0
- package/src/presentation/screen/helpers/instructions_screen_helpers.ts +7 -2
- package/src/presentation/screen/helpers/scan_state_to_overlay_state.ts +3 -0
- package/src/presentation/screen/use_smile_id_capture_screen.tsx +234 -36
- package/src/presentation/screen/use_smile_id_document_preview_screen.tsx +32 -22
- package/src/presentation/screen/use_smile_id_instructions_screen.tsx +4 -0
- package/src/presentation/screen/use_smile_id_preview_screen.tsx +9 -9
- package/src/presentation/screen/use_smile_id_processing_screen.tsx +7 -7
- package/src/presentation/theme/theme.ts +21 -19
- package/src/presentation/utils/force_max_brightness.tsx +4 -4
- package/dist/camera/frame_processor_plugin.d.ts +0 -28
- package/dist/camera/frame_processor_plugin.d.ts.map +0 -1
- package/dist/camera/frame_processor_plugin.js +0 -21
- package/dist/camera/frame_processor_plugin.js.map +0 -1
- package/dist/camera/use_smile_id_frame_processor.d.ts +0 -38
- package/dist/camera/use_smile_id_frame_processor.d.ts.map +0 -1
- package/dist/camera/use_smile_id_frame_processor.js +0 -2
- package/dist/camera/use_smile_id_frame_processor.js.map +0 -1
- package/dist/presentation/components/use_smile_id_document_frame_glyph.d.ts +0 -17
- package/dist/presentation/components/use_smile_id_document_frame_glyph.d.ts.map +0 -1
- package/dist/presentation/components/use_smile_id_document_frame_glyph.js +0 -17
- package/dist/presentation/components/use_smile_id_document_frame_glyph.js.map +0 -1
- package/dist/presentation/components/use_smile_id_enhanced_smart_selfie_animation.d.ts +0 -24
- package/dist/presentation/components/use_smile_id_enhanced_smart_selfie_animation.d.ts.map +0 -1
- package/dist/presentation/components/use_smile_id_enhanced_smart_selfie_animation.js +0 -91
- package/dist/presentation/components/use_smile_id_enhanced_smart_selfie_animation.js.map +0 -1
- package/dist/presentation/components/use_smile_id_instruction_card.d.ts +0 -31
- package/dist/presentation/components/use_smile_id_instruction_card.d.ts.map +0 -1
- package/dist/presentation/components/use_smile_id_instruction_card.js +0 -43
- package/dist/presentation/components/use_smile_id_instruction_card.js.map +0 -1
- package/dist/presentation/screen/helpers/use_document_orientation_lock.d.ts +0 -24
- package/dist/presentation/screen/helpers/use_document_orientation_lock.d.ts.map +0 -1
- package/dist/presentation/screen/helpers/use_document_orientation_lock.js +0 -47
- package/dist/presentation/screen/helpers/use_document_orientation_lock.js.map +0 -1
- package/src/presentation/components/use_smile_id_document_frame_glyph.tsx +0 -162
|
@@ -15,7 +15,10 @@ import type {
|
|
|
15
15
|
} from "../../core/models/params";
|
|
16
16
|
import { JobType } from "../../core/models/job_type";
|
|
17
17
|
import { CaptureType } from "../../core/models/ml_config";
|
|
18
|
-
import
|
|
18
|
+
import {
|
|
19
|
+
defaultFrameAspectRatio,
|
|
20
|
+
type DocumentType,
|
|
21
|
+
} from "../../core/models/document_type";
|
|
19
22
|
import type { JobSubmissionResponse } from "../../data/model/job_submission_response";
|
|
20
23
|
import { MissingRequiredFieldException } from "../../core/exception/job_validation_exceptions";
|
|
21
24
|
import {
|
|
@@ -37,9 +40,18 @@ import {
|
|
|
37
40
|
DOCUMENT_FRONT_IMAGE_ORIGIN_KEY,
|
|
38
41
|
type DocumentImageOrigin,
|
|
39
42
|
} from "../../metadata/document_image_origin";
|
|
43
|
+
import { configurationMetadataEntries } from "../../metadata/metadata_configuration_mappers";
|
|
44
|
+
import {
|
|
45
|
+
CAPTURE_IMAGE_COLOR_DEPTH,
|
|
46
|
+
CAPTURE_IMAGE_PIXEL_CONFIG,
|
|
47
|
+
} from "../../metadata/captured_image_properties";
|
|
48
|
+
import type { CaptureTelemetry } from "../screen/use_smile_id_capture_screen";
|
|
40
49
|
import type { SdkConfig } from "../../data/model/sdk_config";
|
|
41
50
|
import { numSamplesOverride } from "../../data/model/sdk_config";
|
|
42
|
-
import {
|
|
51
|
+
import {
|
|
52
|
+
decodeSmileIDToken,
|
|
53
|
+
type DecodedToken,
|
|
54
|
+
} from "../../data/util/use_smile_id_token_decoder";
|
|
43
55
|
import {
|
|
44
56
|
DocumentSide,
|
|
45
57
|
EnhancedSmartSelfieConfig,
|
|
@@ -123,6 +135,17 @@ export class FlowNavigationManager {
|
|
|
123
135
|
DocumentSide,
|
|
124
136
|
DocumentImageOrigin
|
|
125
137
|
>();
|
|
138
|
+
// Capture telemetry recorded at capture completion (selfie + per document side).
|
|
139
|
+
private _selfieCaptureTelemetry: CaptureTelemetry | undefined;
|
|
140
|
+
private readonly _documentCaptureTelemetry = new Map<
|
|
141
|
+
DocumentSide,
|
|
142
|
+
CaptureTelemetry
|
|
143
|
+
>();
|
|
144
|
+
// Identifier of the camera used for the most recent capture.
|
|
145
|
+
private _cameraName: string | undefined;
|
|
146
|
+
// Accelerometer telemetry from the most recent capture (device_positions / movement).
|
|
147
|
+
private _devicePositions: readonly string[] = [];
|
|
148
|
+
private _deviceMovementDetected: number | null = null;
|
|
126
149
|
private _jobSubmissionState: JobSubmissionState = { kind: "notAttempted" };
|
|
127
150
|
private readonly _listeners = new Set<Listener>();
|
|
128
151
|
private readonly _steps: readonly ScreenSpec[];
|
|
@@ -140,6 +163,23 @@ export class FlowNavigationManager {
|
|
|
140
163
|
*/
|
|
141
164
|
readonly resolvedSdkConfig: SdkConfig | undefined;
|
|
142
165
|
|
|
166
|
+
/** Canonical `partner_id` decoded from the JWT (raw); resolved via the [partnerId] getter. */
|
|
167
|
+
private readonly _resolvedPartnerId: string | undefined;
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Partner identifier the capture screen stamps into the Smile EXIF tag — the tag's HMAC/AES
|
|
171
|
+
* keys derive from it and the backend validates the tag against the request's partner_id.
|
|
172
|
+
*
|
|
173
|
+
* Sourced from the JWT `partner_id` claim (server-canonical form, e.g. `"002"`) so the stamped
|
|
174
|
+
* value matches what the backend keys on; falls back to the partner-supplied config value when
|
|
175
|
+
* the claim is absent/blank. Empty = skip tagging.
|
|
176
|
+
*/
|
|
177
|
+
get partnerId(): string {
|
|
178
|
+
const jwtPartnerId = this._resolvedPartnerId;
|
|
179
|
+
if (jwtPartnerId && jwtPartnerId.length > 0) return jwtPartnerId;
|
|
180
|
+
return this._configuration.network?.config?.partnerConfig?.partnerId ?? "";
|
|
181
|
+
}
|
|
182
|
+
|
|
143
183
|
/** Stable per-flow session id, stamped into every analytics event's `session_id`. */
|
|
144
184
|
private readonly _sessionId: string;
|
|
145
185
|
|
|
@@ -157,9 +197,11 @@ export class FlowNavigationManager {
|
|
|
157
197
|
this._metadataProvider =
|
|
158
198
|
options.metadataProvider ?? new UseSmileIDMetadataFactory();
|
|
159
199
|
this._sessionId = this._metadataProvider.sessionId;
|
|
160
|
-
|
|
200
|
+
const decodedToken = FlowNavigationManager._decodeToken(
|
|
161
201
|
options.configuration,
|
|
162
202
|
);
|
|
203
|
+
this.resolvedSdkConfig = decodedToken?.sdkConfig;
|
|
204
|
+
this._resolvedPartnerId = decodedToken?.partnerId;
|
|
163
205
|
// Seed the path with the first screen so currentScreen/renderer have a
|
|
164
206
|
// deterministic start. Empty path → host renders the "no screens"
|
|
165
207
|
// sentinel (validation rejects empty screens at build time anyway).
|
|
@@ -204,6 +246,29 @@ export class FlowNavigationManager {
|
|
|
204
246
|
return undefined;
|
|
205
247
|
}
|
|
206
248
|
|
|
249
|
+
/**
|
|
250
|
+
* Resolved document capture-frame aspect ratio (width / height), shared by
|
|
251
|
+
* capture, preview, and processing. Precedence: type `knownAspectRatio` →
|
|
252
|
+
* partner `knownIdAspectRatio` → orientation default.
|
|
253
|
+
*/
|
|
254
|
+
get documentFrameAspectRatio(): number | undefined {
|
|
255
|
+
for (const step of this._steps) {
|
|
256
|
+
if (
|
|
257
|
+
step.kind === "capture" &&
|
|
258
|
+
step.config.captureType === CaptureType.document
|
|
259
|
+
) {
|
|
260
|
+
const documentConfig = step.config.documentConfig;
|
|
261
|
+
return (
|
|
262
|
+
documentConfig?.resolvedAspectRatio ??
|
|
263
|
+
defaultFrameAspectRatio(
|
|
264
|
+
documentConfig?.documentType?.orientation ?? "Landscape",
|
|
265
|
+
)
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
return undefined;
|
|
270
|
+
}
|
|
271
|
+
|
|
207
272
|
// --- navigation path --------------------------------------------------
|
|
208
273
|
|
|
209
274
|
/** Read-only navigation stack; top is the active screen. */
|
|
@@ -265,6 +330,23 @@ export class FlowNavigationManager {
|
|
|
265
330
|
if (next?.kind === "preview") return this._steps[currentIdx + 2];
|
|
266
331
|
}
|
|
267
332
|
|
|
333
|
+
// At the document capture step with the front captured, the back still
|
|
334
|
+
// pending, and no document preview to drive the per-side loop, re-enter the
|
|
335
|
+
// capture step for the back side so captureBothSides is honoured even when
|
|
336
|
+
// the flow omits the document preview { } step. When a preview does follow,
|
|
337
|
+
// the per-side loop above handles the back instead.
|
|
338
|
+
if (
|
|
339
|
+
current.kind === "capture" &&
|
|
340
|
+
current.config.captureType === CaptureType.document &&
|
|
341
|
+
this.documentCapturesBack() &&
|
|
342
|
+
this._captured.frontDocumentPath !== undefined &&
|
|
343
|
+
this._captured.backDocumentPath === undefined &&
|
|
344
|
+
!this._documentBackSkipped &&
|
|
345
|
+
!this.documentPreviewFollowsCapture()
|
|
346
|
+
) {
|
|
347
|
+
return current;
|
|
348
|
+
}
|
|
349
|
+
|
|
268
350
|
return this._steps[currentIdx + 1];
|
|
269
351
|
}
|
|
270
352
|
|
|
@@ -485,6 +567,31 @@ export class FlowNavigationManager {
|
|
|
485
567
|
this._documentImageOrigins.set(side, origin);
|
|
486
568
|
}
|
|
487
569
|
|
|
570
|
+
/** Records selfie capture telemetry (duration + retries) at capture completion. */
|
|
571
|
+
recordSelfieCaptureTelemetry(telemetry: CaptureTelemetry): void {
|
|
572
|
+
if (this._disposed) return;
|
|
573
|
+
this._selfieCaptureTelemetry = telemetry;
|
|
574
|
+
this._captureCameraName(telemetry);
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
/** Records per-side document capture telemetry at each side's completion. */
|
|
578
|
+
recordDocumentCaptureTelemetry(
|
|
579
|
+
side: DocumentSide,
|
|
580
|
+
telemetry: CaptureTelemetry,
|
|
581
|
+
): void {
|
|
582
|
+
if (this._disposed) return;
|
|
583
|
+
this._documentCaptureTelemetry.set(side, telemetry);
|
|
584
|
+
this._captureCameraName(telemetry);
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
private _captureCameraName(telemetry: CaptureTelemetry): void {
|
|
588
|
+
if (telemetry.cameraName) this._cameraName = telemetry.cameraName;
|
|
589
|
+
if (telemetry.devicePositions.length > 0) {
|
|
590
|
+
this._devicePositions = telemetry.devicePositions;
|
|
591
|
+
this._deviceMovementDetected = telemetry.deviceMovementDetected;
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
|
|
488
595
|
/** Per-side document origin wire entries (front then back; omitted when unset). */
|
|
489
596
|
private _documentImageOriginEntries(): MetadataEntry[] {
|
|
490
597
|
const entries: MetadataEntry[] = [];
|
|
@@ -499,6 +606,60 @@ export class FlowNavigationManager {
|
|
|
499
606
|
return entries;
|
|
500
607
|
}
|
|
501
608
|
|
|
609
|
+
/**
|
|
610
|
+
* Capture telemetry + image-property wire entries. Durations and retries keep
|
|
611
|
+
* a meaningful 0 (capture ran) and are omitted only when that capture type
|
|
612
|
+
* never ran. Color depth / pixel config are emitted for each present capture;
|
|
613
|
+
* document sizes when measured.
|
|
614
|
+
*/
|
|
615
|
+
private _captureTelemetryEntries(): MetadataEntry[] {
|
|
616
|
+
const entries: MetadataEntry[] = [];
|
|
617
|
+
const push = (name: string, value: string) => entries.push({ name, value });
|
|
618
|
+
|
|
619
|
+
const selfie = this._selfieCaptureTelemetry;
|
|
620
|
+
if (selfie) {
|
|
621
|
+
// Duration + retries keep a meaningful 0 (capture ran); telemetry is absent only when the
|
|
622
|
+
// capture type never ran.
|
|
623
|
+
push("selfie_capture_duration_ms", String(selfie.durationMs));
|
|
624
|
+
push("selfie_capture_retries", String(selfie.retries));
|
|
625
|
+
}
|
|
626
|
+
if (this._captured.selfiePath !== undefined) {
|
|
627
|
+
push("selfie_image_color_depth", String(CAPTURE_IMAGE_COLOR_DEPTH));
|
|
628
|
+
push("selfie_image_pixel_config", CAPTURE_IMAGE_PIXEL_CONFIG);
|
|
629
|
+
}
|
|
630
|
+
if (this._cameraName) {
|
|
631
|
+
push("camera_name", this._cameraName);
|
|
632
|
+
}
|
|
633
|
+
if (this._devicePositions.length > 0) {
|
|
634
|
+
push("device_positions", JSON.stringify(this._devicePositions));
|
|
635
|
+
if (this._deviceMovementDetected !== null) {
|
|
636
|
+
push("device_movement_detected", String(this._deviceMovementDetected));
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
const sideKey = (side: DocumentSide) =>
|
|
641
|
+
side === DocumentSide.Back ? "back" : "front";
|
|
642
|
+
for (const side of [DocumentSide.Front, DocumentSide.Back]) {
|
|
643
|
+
const key = sideKey(side);
|
|
644
|
+
const telemetry = this._documentCaptureTelemetry.get(side);
|
|
645
|
+
if (telemetry) {
|
|
646
|
+
push(
|
|
647
|
+
`document_${key}_capture_duration_ms`,
|
|
648
|
+
String(telemetry.durationMs),
|
|
649
|
+
);
|
|
650
|
+
push(`document_${key}_capture_retries`, String(telemetry.retries));
|
|
651
|
+
push(
|
|
652
|
+
`document_${key}_image_color_depth`,
|
|
653
|
+
String(CAPTURE_IMAGE_COLOR_DEPTH),
|
|
654
|
+
);
|
|
655
|
+
push(`document_${key}_image_pixel_config`, CAPTURE_IMAGE_PIXEL_CONFIG);
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
// Per-image original + final compressed sizes are stamped in the repository around the
|
|
659
|
+
// compression pass (it owns both the before and after byte counts), not here.
|
|
660
|
+
return entries;
|
|
661
|
+
}
|
|
662
|
+
|
|
502
663
|
private _precedingStepIsDocumentCapture(index: number): boolean {
|
|
503
664
|
const preceding = this._steps[index - 1];
|
|
504
665
|
return (
|
|
@@ -619,11 +780,16 @@ export class FlowNavigationManager {
|
|
|
619
780
|
// make() so a mid-flow rotation is captured. resolvedSdkConfig drives
|
|
620
781
|
// sdk_config_source + image_width/height provenance.
|
|
621
782
|
const baseMetadata = this._metadataProvider.make(this.resolvedSdkConfig);
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
783
|
+
// Append the per-side document origins plus the partner's builder setup and
|
|
784
|
+
// the active detection models, all as flat wire entries.
|
|
785
|
+
// configurationMetadataEntries always contributes the builder + model config objects, so
|
|
786
|
+
// there is always at least one extra entry to append.
|
|
787
|
+
const extraEntries = [
|
|
788
|
+
...this._documentImageOriginEntries(),
|
|
789
|
+
...this._captureTelemetryEntries(),
|
|
790
|
+
...configurationMetadataEntries(config),
|
|
791
|
+
];
|
|
792
|
+
const metadata = baseMetadata.withAdditionalEntries(extraEntries);
|
|
627
793
|
|
|
628
794
|
switch (jobType) {
|
|
629
795
|
// enableEnhancedLiveness is a screen-level capture flag, not a
|
|
@@ -960,16 +1126,16 @@ export class FlowNavigationManager {
|
|
|
960
1126
|
}
|
|
961
1127
|
|
|
962
1128
|
/**
|
|
963
|
-
* Decode the `sdk_config`
|
|
964
|
-
* no token, or
|
|
1129
|
+
* Decode the partner JWT into its claims (`sdk_config`, `partner_id`). `undefined` for offline
|
|
1130
|
+
* mode, no token, or an unparseable token — SDK defaults apply in those cases.
|
|
965
1131
|
*/
|
|
966
|
-
private static
|
|
1132
|
+
private static _decodeToken(
|
|
967
1133
|
configuration: FlowConfigurationSnapshot,
|
|
968
|
-
):
|
|
1134
|
+
): DecodedToken | undefined {
|
|
969
1135
|
if (configuration.config?.allowOfflineMode) return undefined;
|
|
970
1136
|
const token = configuration.network?.config?.token;
|
|
971
1137
|
if (!token || token.length === 0) return undefined;
|
|
972
|
-
return decodeSmileIDToken(token)
|
|
1138
|
+
return decodeSmileIDToken(token);
|
|
973
1139
|
}
|
|
974
1140
|
|
|
975
1141
|
private _notify(): void {
|
|
@@ -12,4 +12,10 @@ export type InstructionGuideline = {
|
|
|
12
12
|
readonly image: FC<{ readonly width?: number; readonly height?: number }>;
|
|
13
13
|
readonly label: (localizations: UseSmileIDLocalizations) => string;
|
|
14
14
|
readonly status: GuidelineStatus;
|
|
15
|
+
/**
|
|
16
|
+
* Visible-card size (device-independent px) for a self-contained document
|
|
17
|
+
* illustration (the SVG paints its own card). Set ⇒ document-card tile;
|
|
18
|
+
* omitted ⇒ selfie tile (framed card + pill).
|
|
19
|
+
*/
|
|
20
|
+
readonly card?: { readonly width: number; readonly height: number };
|
|
15
21
|
};
|
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
import type { AnimationObject } from "lottie-react-native";
|
|
2
2
|
import {
|
|
3
3
|
SiGuidelineAccessories,
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
SiGuidelineDocumentGenericGood,
|
|
5
|
+
SiGuidelineDocumentGenericNotBlurry,
|
|
6
|
+
SiGuidelineDocumentGenericNotCropped,
|
|
7
|
+
SiGuidelineDocumentGenericNotReflective,
|
|
8
|
+
SiGuidelineDocumentGreenBookGood,
|
|
9
|
+
SiGuidelineDocumentGreenBookNotBlurry,
|
|
10
|
+
SiGuidelineDocumentGreenBookNotCropped,
|
|
11
|
+
SiGuidelineDocumentGreenBookNotReflective,
|
|
12
|
+
SiGuidelineDocumentPassportGood,
|
|
13
|
+
SiGuidelineDocumentPassportNotBlurry,
|
|
14
|
+
SiGuidelineDocumentPassportNotCropped,
|
|
15
|
+
SiGuidelineDocumentPassportNotReflective,
|
|
8
16
|
SiGuidelineGood,
|
|
9
17
|
SiGuidelineMultipleFaces,
|
|
10
18
|
SiGuidelinePoorLighting,
|
|
@@ -73,34 +81,104 @@ export const SELFIE_GUIDELINES: readonly InstructionGuideline[] = Object.freeze(
|
|
|
73
81
|
SELFIE_GUIDELINE_ENTRIES.map((guideline) => Object.freeze(guideline)),
|
|
74
82
|
);
|
|
75
83
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
84
|
+
// Visible card size (device-independent px) per document guideline tile.
|
|
85
|
+
const DOCUMENT_CARD_LANDSCAPE = Object.freeze({ width: 80, height: 56 });
|
|
86
|
+
const DOCUMENT_CARD_PORTRAIT = Object.freeze({ width: 60, height: 84 });
|
|
87
|
+
|
|
88
|
+
type DocumentGuidelineImages = {
|
|
89
|
+
readonly good: InstructionGuideline["image"];
|
|
90
|
+
readonly notCropped: InstructionGuideline["image"];
|
|
91
|
+
readonly notBlurry: InstructionGuideline["image"];
|
|
92
|
+
readonly notReflective: InstructionGuideline["image"];
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Build the four document-capture guidelines (good + not cropped / blurry /
|
|
97
|
+
* reflective) for one document type. The order and labels are shared; only the
|
|
98
|
+
* per-type artwork and card size differ. Allocated once and deeply frozen.
|
|
99
|
+
*/
|
|
100
|
+
function buildDocumentGuidelines(
|
|
101
|
+
images: DocumentGuidelineImages,
|
|
102
|
+
card: { readonly width: number; readonly height: number },
|
|
103
|
+
): readonly InstructionGuideline[] {
|
|
104
|
+
const entries: InstructionGuideline[] = [
|
|
105
|
+
{
|
|
106
|
+
image: images.good,
|
|
107
|
+
label: (localizations) => localizations.siDocumentGuidelineGood,
|
|
108
|
+
status: "allowed",
|
|
109
|
+
card,
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
image: images.notCropped,
|
|
113
|
+
label: (localizations) => localizations.siDocumentGuidelineNotCropped,
|
|
114
|
+
status: "blocked",
|
|
115
|
+
card,
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
image: images.notBlurry,
|
|
119
|
+
label: (localizations) => localizations.siDocumentGuidelineNotBlurry,
|
|
120
|
+
status: "blocked",
|
|
121
|
+
card,
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
image: images.notReflective,
|
|
125
|
+
label: (localizations) => localizations.siDocumentGuidelineNotReflective,
|
|
126
|
+
status: "blocked",
|
|
127
|
+
card,
|
|
128
|
+
},
|
|
129
|
+
];
|
|
130
|
+
return Object.freeze(entries.map((guideline) => Object.freeze(guideline)));
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/** Generic-document capture guidelines (landscape card). */
|
|
134
|
+
export const DOCUMENT_GUIDELINES_GENERIC = buildDocumentGuidelines(
|
|
82
135
|
{
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
136
|
+
good: SiGuidelineDocumentGenericGood,
|
|
137
|
+
notCropped: SiGuidelineDocumentGenericNotCropped,
|
|
138
|
+
notBlurry: SiGuidelineDocumentGenericNotBlurry,
|
|
139
|
+
notReflective: SiGuidelineDocumentGenericNotReflective,
|
|
86
140
|
},
|
|
141
|
+
DOCUMENT_CARD_LANDSCAPE,
|
|
142
|
+
);
|
|
143
|
+
|
|
144
|
+
/** Passport capture guidelines (landscape card). */
|
|
145
|
+
export const DOCUMENT_GUIDELINES_PASSPORT = buildDocumentGuidelines(
|
|
87
146
|
{
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
147
|
+
good: SiGuidelineDocumentPassportGood,
|
|
148
|
+
notCropped: SiGuidelineDocumentPassportNotCropped,
|
|
149
|
+
notBlurry: SiGuidelineDocumentPassportNotBlurry,
|
|
150
|
+
notReflective: SiGuidelineDocumentPassportNotReflective,
|
|
91
151
|
},
|
|
152
|
+
DOCUMENT_CARD_LANDSCAPE,
|
|
153
|
+
);
|
|
154
|
+
|
|
155
|
+
/** South Africa green book capture guidelines (portrait card). */
|
|
156
|
+
export const DOCUMENT_GUIDELINES_GREEN_BOOK = buildDocumentGuidelines(
|
|
92
157
|
{
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
158
|
+
good: SiGuidelineDocumentGreenBookGood,
|
|
159
|
+
notCropped: SiGuidelineDocumentGreenBookNotCropped,
|
|
160
|
+
notBlurry: SiGuidelineDocumentGreenBookNotBlurry,
|
|
161
|
+
notReflective: SiGuidelineDocumentGreenBookNotReflective,
|
|
96
162
|
},
|
|
97
|
-
|
|
163
|
+
DOCUMENT_CARD_PORTRAIT,
|
|
164
|
+
);
|
|
98
165
|
|
|
99
|
-
/**
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
166
|
+
/**
|
|
167
|
+
* Resolve the document-capture guidelines for a document type. Falls back to
|
|
168
|
+
* the generic set when the type is unset or has no dedicated artwork.
|
|
169
|
+
*/
|
|
170
|
+
export function documentGuidelines(
|
|
171
|
+
documentType: DocumentType | undefined,
|
|
172
|
+
): readonly InstructionGuideline[] {
|
|
173
|
+
switch (documentType?.kind) {
|
|
174
|
+
case "southAfricaGreenBook":
|
|
175
|
+
return DOCUMENT_GUIDELINES_GREEN_BOOK;
|
|
176
|
+
case "passport":
|
|
177
|
+
return DOCUMENT_GUIDELINES_PASSPORT;
|
|
178
|
+
default:
|
|
179
|
+
return DOCUMENT_GUIDELINES_GENERIC;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
104
182
|
|
|
105
183
|
/**
|
|
106
184
|
* Resolve the document hero animation for a document type. Falls back to the
|
|
@@ -9,6 +9,7 @@ import type {
|
|
|
9
9
|
} from "@smileid/usesmileid_bridge";
|
|
10
10
|
import {
|
|
11
11
|
CaptureReadyEventKind,
|
|
12
|
+
DeviceIntegrityProvider,
|
|
12
13
|
DocumentSide,
|
|
13
14
|
ImageType,
|
|
14
15
|
} from "@smileid/usesmileid_bridge";
|
|
@@ -21,6 +22,7 @@ import { resolveFaceSessionConfig } from "./helpers/face_session_config";
|
|
|
21
22
|
import { useCaptureOrientationLock } from "../../screen/helpers/use_capture_orientation_lock";
|
|
22
23
|
import { resolveJpegQuality } from "../../../data/model/sdk_config_capture";
|
|
23
24
|
import { UseSmileIDCaptureScreen } from "../../screen/use_smile_id_capture_screen";
|
|
25
|
+
import { defaultLightTheme } from "../../theme/theme";
|
|
24
26
|
import { UseSmileIDDocumentBackInstructions } from "../../screen/use_smile_id_document_back_instructions";
|
|
25
27
|
import { useFlowNavigation } from "../flow_navigation_context";
|
|
26
28
|
import { UseSmileIDOrchestratedScreenHost } from "./use_smile_id_orchestrated_screen_host";
|
|
@@ -166,24 +168,37 @@ export function OrchestratedCaptureScreen({
|
|
|
166
168
|
}
|
|
167
169
|
return (
|
|
168
170
|
<UseSmileIDCaptureScreen
|
|
171
|
+
// Remount per document side so the camera resets between front and back captures.
|
|
172
|
+
key={
|
|
173
|
+
captureType === CaptureType.document
|
|
174
|
+
? `document-capture-${currentDocumentSide}`
|
|
175
|
+
: "capture"
|
|
176
|
+
}
|
|
169
177
|
captureType={captureType}
|
|
170
178
|
analyzer={analyzer}
|
|
179
|
+
// Capture is always light; pass the partner's resolved light tokens
|
|
180
|
+
// so partner colours still apply (the screen forces light internally).
|
|
181
|
+
theme={
|
|
182
|
+
navigationManager.configuration.theme?.light ?? defaultLightTheme
|
|
183
|
+
}
|
|
171
184
|
enableEnhancedLiveness={
|
|
172
185
|
configuration.selfieConfig?.enableEnhancedLiveness ?? false
|
|
173
186
|
}
|
|
174
187
|
{...(captureType === CaptureType.document && documentConfig
|
|
175
188
|
? {
|
|
176
|
-
//
|
|
177
|
-
//
|
|
189
|
+
// Type ratio → partner override → orientation default; matches
|
|
190
|
+
// the preview/processing frames so all three share one shape.
|
|
178
191
|
knownIdAspectRatio:
|
|
179
|
-
documentConfig.
|
|
180
|
-
documentType?.knownAspectRatio ??
|
|
192
|
+
documentConfig.resolvedAspectRatio ??
|
|
181
193
|
defaultFrameAspectRatio(
|
|
182
194
|
documentType?.orientation ?? "Landscape",
|
|
183
195
|
),
|
|
184
196
|
captureMode: documentConfig.captureMode,
|
|
185
197
|
allowGalleryUpload: documentConfig.allowGalleryUpload,
|
|
186
198
|
documentSide: currentDocumentSide,
|
|
199
|
+
...(documentType?.kind
|
|
200
|
+
? { documentTypeKind: documentType.kind }
|
|
201
|
+
: {}),
|
|
187
202
|
onDocumentOrigin: (origin) =>
|
|
188
203
|
navigationManager.recordDocumentImageOrigin(
|
|
189
204
|
currentDocumentSide,
|
|
@@ -207,7 +222,7 @@ export function OrchestratedCaptureScreen({
|
|
|
207
222
|
}
|
|
208
223
|
onBack();
|
|
209
224
|
}}
|
|
210
|
-
onCaptureComplete={(events) => {
|
|
225
|
+
onCaptureComplete={(events, telemetry) => {
|
|
211
226
|
const primary = pickPrimaryCaptureUrl(events, captureType);
|
|
212
227
|
if (!primary) {
|
|
213
228
|
// Pipeline finished without the expected artifact — stay so the user can retry.
|
|
@@ -218,9 +233,10 @@ export function OrchestratedCaptureScreen({
|
|
|
218
233
|
// (blank partnerId → native no-op). Context is rebound per
|
|
219
234
|
// capture because partnerConfig may change across re-renders
|
|
220
235
|
// (partner builder closures are not memoised).
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
236
|
+
//
|
|
237
|
+
// `navigationManager.partnerId` resolves the JWT's canonical partner_id (e.g.
|
|
238
|
+
// "002"), falling back to the config value — see FlowNavigationManager.partnerId.
|
|
239
|
+
const partnerId = navigationManager.partnerId;
|
|
224
240
|
const imageTypeForCapture: ImageTypeId =
|
|
225
241
|
captureType === CaptureType.selfie
|
|
226
242
|
? ImageType.Selfie
|
|
@@ -234,16 +250,33 @@ export function OrchestratedCaptureScreen({
|
|
|
234
250
|
)
|
|
235
251
|
.map((event) => event.url);
|
|
236
252
|
|
|
237
|
-
|
|
253
|
+
// Source the device fingerprint from the same native signal the metadata
|
|
254
|
+
// payload uses so the EXIF tag's `fingerprint` matches it. `signals()` is
|
|
255
|
+
// fail-open (resolves with `""` if unavailable); omit it when blank so a
|
|
256
|
+
// capture never ships an empty fingerprint that shadows a real one.
|
|
257
|
+
void DeviceIntegrityProvider.signals()
|
|
258
|
+
.then(({ fingerprint }) =>
|
|
259
|
+
SmileExifTagger.setContext({
|
|
260
|
+
partnerId,
|
|
261
|
+
...(fingerprint ? { fingerprint } : {}),
|
|
262
|
+
}),
|
|
263
|
+
)
|
|
238
264
|
.then(() =>
|
|
239
265
|
SmileExifTagger.finalize(primary, imageTypeForCapture),
|
|
240
266
|
)
|
|
241
|
-
.finally(() => {
|
|
267
|
+
.finally(async () => {
|
|
242
268
|
if (captureType === CaptureType.selfie) {
|
|
243
269
|
navigationManager.setCapturedSelfie(primary, livenessUrls);
|
|
270
|
+
navigationManager.recordSelfieCaptureTelemetry(telemetry);
|
|
244
271
|
onNavigateNext();
|
|
245
272
|
return;
|
|
246
273
|
}
|
|
274
|
+
// Document: record this side's capture telemetry before advancing.
|
|
275
|
+
// Image sizes are measured in the repository around the compression pass.
|
|
276
|
+
navigationManager.recordDocumentCaptureTelemetry(
|
|
277
|
+
currentDocumentSide,
|
|
278
|
+
telemetry,
|
|
279
|
+
);
|
|
247
280
|
if (
|
|
248
281
|
capturesBack &&
|
|
249
282
|
currentDocumentSide === DocumentSide.Front
|
|
@@ -87,6 +87,7 @@ function OrchestratedInstructionsContent({
|
|
|
87
87
|
showAttribution={resolved.showAttribution}
|
|
88
88
|
showHeroOval={resolved.showHeroOval}
|
|
89
89
|
showHeroOvalProgress={resolved.showHeroOvalProgress}
|
|
90
|
+
showCardBackground={resolved.showCardBackground}
|
|
90
91
|
{...(configuration.continueButton
|
|
91
92
|
? {
|
|
92
93
|
// Adapt the config slot `{ onClick, enabled }` to the screen's
|
|
@@ -2,6 +2,7 @@ import type { PreviewConfigBuilder } from "../dsl/builder/screens_builder";
|
|
|
2
2
|
import { UseSmileIDPreviewScreen } from "../../screen/use_smile_id_preview_screen";
|
|
3
3
|
import { UseSmileIDDocumentPreviewScreen } from "../../screen/use_smile_id_document_preview_screen";
|
|
4
4
|
import { UseSmileIDOrchestratedScreenHost } from "./use_smile_id_orchestrated_screen_host";
|
|
5
|
+
import { defaultFrameAspectRatio } from "../../../core/models/document_type";
|
|
5
6
|
|
|
6
7
|
export type OrchestratedPreviewScreenProps = {
|
|
7
8
|
readonly configuration: PreviewConfigBuilder;
|
|
@@ -23,8 +24,9 @@ export function OrchestratedPreviewScreen({
|
|
|
23
24
|
const documentPath = navigationManager.currentDocumentPreviewPath();
|
|
24
25
|
return (
|
|
25
26
|
<UseSmileIDDocumentPreviewScreen
|
|
26
|
-
|
|
27
|
-
navigationManager.
|
|
27
|
+
documentAspectRatio={
|
|
28
|
+
navigationManager.documentFrameAspectRatio ??
|
|
29
|
+
defaultFrameAspectRatio("Landscape")
|
|
28
30
|
}
|
|
29
31
|
showAttribution={configuration.showAttribution}
|
|
30
32
|
{...(documentPath !== undefined
|
|
@@ -66,7 +66,7 @@ function ProcessingScreenBody(props: ProcessingScreenBodyProps) {
|
|
|
66
66
|
const documentImageUri = requiresDocument(jobType)
|
|
67
67
|
? navigationManager.captured.frontDocumentPath
|
|
68
68
|
: undefined;
|
|
69
|
-
const
|
|
69
|
+
const documentAspectRatio = navigationManager.documentFrameAspectRatio;
|
|
70
70
|
|
|
71
71
|
return (
|
|
72
72
|
<UseSmileIDProcessingScreen
|
|
@@ -75,8 +75,8 @@ function ProcessingScreenBody(props: ProcessingScreenBodyProps) {
|
|
|
75
75
|
showProgressPercentage={props.processingConfig.showProgressPercentage}
|
|
76
76
|
showAttribution={props.processingConfig.showAttribution}
|
|
77
77
|
{...(documentImageUri !== undefined ? { documentImageUri } : {})}
|
|
78
|
-
{...(documentImageUri !== undefined &&
|
|
79
|
-
? {
|
|
78
|
+
{...(documentImageUri !== undefined && documentAspectRatio !== undefined
|
|
79
|
+
? { documentAspectRatio }
|
|
80
80
|
: {})}
|
|
81
81
|
{...(navigationManager.captured.selfiePath !== undefined
|
|
82
82
|
? { capturedSelfiePath: navigationManager.captured.selfiePath }
|
|
@@ -667,6 +667,70 @@ describe("DocumentJobTypeValidator — Android-parity rules", () => {
|
|
|
667
667
|
issues.some((i) => i instanceof InvalidJobTypeScreenConfigException),
|
|
668
668
|
).toBe(false);
|
|
669
669
|
});
|
|
670
|
+
|
|
671
|
+
it("rejects SouthAfricaGreenBook for EnhancedDocumentVerification", () => {
|
|
672
|
+
const greenBookStep = (() => {
|
|
673
|
+
const config = new CaptureConfigBuilder();
|
|
674
|
+
config.captureType = CaptureType.document;
|
|
675
|
+
config.document((d) => {
|
|
676
|
+
d.documentType = DocumentType.SouthAfricaGreenBook;
|
|
677
|
+
});
|
|
678
|
+
return { kind: "capture" as const, config };
|
|
679
|
+
})();
|
|
680
|
+
const issues = run({
|
|
681
|
+
steps: [
|
|
682
|
+
consentStep(),
|
|
683
|
+
captureStep(CaptureType.selfie),
|
|
684
|
+
greenBookStep,
|
|
685
|
+
previewStep(),
|
|
686
|
+
processingStep(),
|
|
687
|
+
],
|
|
688
|
+
network: validNetwork(JobType.enhancedDocumentVerification),
|
|
689
|
+
ml: { analyzers: { selfie: stubFaceAnalyzer() } },
|
|
690
|
+
userDetails: validUserDetails,
|
|
691
|
+
enhancedDocumentVerificationParams: validEnhancedDocumentParams,
|
|
692
|
+
});
|
|
693
|
+
expect(
|
|
694
|
+
issues.some(
|
|
695
|
+
(i) =>
|
|
696
|
+
i instanceof InvalidJobTypeScreenConfigException &&
|
|
697
|
+
i.message.includes(
|
|
698
|
+
"South Africa Green Book is not supported for Enhanced Document Verification",
|
|
699
|
+
),
|
|
700
|
+
),
|
|
701
|
+
).toBe(true);
|
|
702
|
+
});
|
|
703
|
+
|
|
704
|
+
it("accepts SouthAfricaGreenBook for DocumentVerification", () => {
|
|
705
|
+
const greenBookStep = (() => {
|
|
706
|
+
const config = new CaptureConfigBuilder();
|
|
707
|
+
config.captureType = CaptureType.document;
|
|
708
|
+
config.document((d) => {
|
|
709
|
+
d.documentType = DocumentType.SouthAfricaGreenBook;
|
|
710
|
+
});
|
|
711
|
+
return { kind: "capture" as const, config };
|
|
712
|
+
})();
|
|
713
|
+
const issues = run({
|
|
714
|
+
steps: [
|
|
715
|
+
consentStep(),
|
|
716
|
+
captureStep(CaptureType.selfie),
|
|
717
|
+
greenBookStep,
|
|
718
|
+
previewStep(),
|
|
719
|
+
processingStep(),
|
|
720
|
+
],
|
|
721
|
+
network: validNetwork(JobType.documentVerification),
|
|
722
|
+
ml: { analyzers: { selfie: stubFaceAnalyzer() } },
|
|
723
|
+
userDetails: validUserDetails,
|
|
724
|
+
documentVerificationParams: validDocumentParams,
|
|
725
|
+
});
|
|
726
|
+
expect(
|
|
727
|
+
issues.some(
|
|
728
|
+
(i) =>
|
|
729
|
+
i instanceof InvalidJobTypeScreenConfigException &&
|
|
730
|
+
i.message.includes("South Africa Green Book is not supported"),
|
|
731
|
+
),
|
|
732
|
+
).toBe(false);
|
|
733
|
+
});
|
|
670
734
|
});
|
|
671
735
|
|
|
672
736
|
describe("NonCaptureJobTypeValidator — Android-parity rules", () => {
|