@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
|
@@ -453,6 +453,30 @@ export class DocumentJobTypeValidator implements JobTypeValidator {
|
|
|
453
453
|
|
|
454
454
|
this.appendParamsRule(input, issues);
|
|
455
455
|
|
|
456
|
+
// The South Africa Green Book carries no usable data on its back and is not
|
|
457
|
+
// supported by the Enhanced Document Verification ID-authority cross check.
|
|
458
|
+
// Reject it for that job type so the partner sees a build-time error instead
|
|
459
|
+
// of a server-side job failure.
|
|
460
|
+
if (
|
|
461
|
+
this.jobType === JobType.enhancedDocumentVerification &&
|
|
462
|
+
documentCaptures.some(
|
|
463
|
+
(s) =>
|
|
464
|
+
s.kind === "capture" &&
|
|
465
|
+
s.config.documentConfig?.documentType?.kind ===
|
|
466
|
+
"southAfricaGreenBook",
|
|
467
|
+
)
|
|
468
|
+
) {
|
|
469
|
+
issues.push(
|
|
470
|
+
InvalidJobTypeScreenConfigException.forJob({
|
|
471
|
+
jobType: this.jobType,
|
|
472
|
+
reason:
|
|
473
|
+
"South Africa Green Book is not supported for Enhanced Document Verification",
|
|
474
|
+
suggestedFix:
|
|
475
|
+
"Use JobType.documentVerification for the Green Book, or choose a supported document type for Enhanced Document Verification",
|
|
476
|
+
}),
|
|
477
|
+
);
|
|
478
|
+
}
|
|
479
|
+
|
|
456
480
|
if (input.userDetails === undefined) {
|
|
457
481
|
issues.push(
|
|
458
482
|
InvalidJobTypeScreenConfigException.forJob({
|
|
@@ -6,7 +6,9 @@ import {
|
|
|
6
6
|
} from "../helpers/instructions_screen_helpers";
|
|
7
7
|
import {
|
|
8
8
|
DOCUMENT_GREEN_BOOK_HERO_ANIMATION,
|
|
9
|
-
|
|
9
|
+
DOCUMENT_GUIDELINES_GENERIC,
|
|
10
|
+
DOCUMENT_GUIDELINES_GREEN_BOOK,
|
|
11
|
+
DOCUMENT_GUIDELINES_PASSPORT,
|
|
10
12
|
DOCUMENT_HERO_ANIMATION,
|
|
11
13
|
ESS_HERO_ANIMATION,
|
|
12
14
|
SELFIE_GUIDELINES,
|
|
@@ -85,7 +87,7 @@ describe("resolveInstructionsConfig — document variant", () => {
|
|
|
85
87
|
loc,
|
|
86
88
|
);
|
|
87
89
|
expect(resolved.titleEmphasis).toBe("Green Book");
|
|
88
|
-
expect(resolved.guidelines).toBe(
|
|
90
|
+
expect(resolved.guidelines).toBe(DOCUMENT_GUIDELINES_GREEN_BOOK);
|
|
89
91
|
expect(resolved.heroSource).toBe(DOCUMENT_GREEN_BOOK_HERO_ANIMATION);
|
|
90
92
|
expect(resolved.showHeroOval).toBe(false);
|
|
91
93
|
expect(resolved.showHeroOvalProgress).toBe(false);
|
|
@@ -93,7 +95,7 @@ describe("resolveInstructionsConfig — document variant", () => {
|
|
|
93
95
|
expect(resolved.titlePrefix).toBe(loc.siInstructionsTitlePrefix);
|
|
94
96
|
});
|
|
95
97
|
|
|
96
|
-
it("falls back to the generic document hero for GenericDocument", () => {
|
|
98
|
+
it("falls back to the generic document hero + guidelines for GenericDocument", () => {
|
|
97
99
|
const resolved = resolveInstructionsConfig(
|
|
98
100
|
{},
|
|
99
101
|
{
|
|
@@ -103,9 +105,19 @@ describe("resolveInstructionsConfig — document variant", () => {
|
|
|
103
105
|
loc,
|
|
104
106
|
);
|
|
105
107
|
expect(resolved.heroSource).toBe(DOCUMENT_HERO_ANIMATION);
|
|
108
|
+
expect(resolved.guidelines).toBe(DOCUMENT_GUIDELINES_GENERIC);
|
|
106
109
|
expect(resolved.titleEmphasis).toBe("Document");
|
|
107
110
|
});
|
|
108
111
|
|
|
112
|
+
it("uses the passport guidelines for a passport document", () => {
|
|
113
|
+
const resolved = resolveInstructionsConfig(
|
|
114
|
+
{},
|
|
115
|
+
{ enhancedLivenessEnabled: false, documentType: DocumentType.Passport },
|
|
116
|
+
loc,
|
|
117
|
+
);
|
|
118
|
+
expect(resolved.guidelines).toBe(DOCUMENT_GUIDELINES_PASSPORT);
|
|
119
|
+
});
|
|
120
|
+
|
|
109
121
|
it("respects partner title/guideline overrides but always hides the oval for documents", () => {
|
|
110
122
|
const customGuidelines: InstructionGuideline[] = [SELFIE_GUIDELINES[0]!];
|
|
111
123
|
const resolved = resolveInstructionsConfig(
|
|
@@ -534,10 +534,12 @@ describe("UseSmileIDCaptureScreen", () => {
|
|
|
534
534
|
|
|
535
535
|
expect(onCaptureComplete).toHaveBeenCalledTimes(1);
|
|
536
536
|
// Only the post-reset events survive — the stale ones were cleared.
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
537
|
+
// The capture telemetry (duration + retries) travels as a second argument;
|
|
538
|
+
// the retry count reflects the one unsatisfied reset observed above.
|
|
539
|
+
expect(onCaptureComplete).toHaveBeenCalledWith(
|
|
540
|
+
[freshSelfie, freshLiveness],
|
|
541
|
+
expect.objectContaining({ retries: 1 }),
|
|
542
|
+
);
|
|
541
543
|
});
|
|
542
544
|
});
|
|
543
545
|
|
|
@@ -93,6 +93,7 @@ const FEEDBACK_COPY: Partial<
|
|
|
93
93
|
si_ess_look_left: (loc) => loc.siEssLookLeft,
|
|
94
94
|
si_ess_look_right: (loc) => loc.siEssLookRight,
|
|
95
95
|
si_ess_look_up: (loc) => loc.siEssLookUp,
|
|
96
|
+
si_ess_look_at_camera: (loc) => loc.siEssLookAtCamera,
|
|
96
97
|
si_document_initial_instruction: (loc) => loc.siDocumentInitialInstruction,
|
|
97
98
|
si_document_ready: (loc) => loc.siDocumentReady,
|
|
98
99
|
si_document_capturing: (loc) => loc.siDocumentCapturing,
|
|
@@ -2,7 +2,7 @@ import type { UseSmileIDLocalizations } from "../../../l10n/use_smile_id_localiz
|
|
|
2
2
|
import type { DocumentType } from "../../../core/models/document_type";
|
|
3
3
|
import type { InstructionGuideline } from "../../flow/model/instruction_guideline";
|
|
4
4
|
import {
|
|
5
|
-
|
|
5
|
+
documentGuidelines,
|
|
6
6
|
documentHeroAnimation,
|
|
7
7
|
ESS_HERO_ANIMATION,
|
|
8
8
|
SELFIE_GUIDELINES,
|
|
@@ -33,6 +33,7 @@ export type ResolvedInstructions = {
|
|
|
33
33
|
readonly showAttribution: boolean;
|
|
34
34
|
readonly showHeroOval: boolean;
|
|
35
35
|
readonly showHeroOvalProgress: boolean;
|
|
36
|
+
readonly showCardBackground: boolean;
|
|
36
37
|
};
|
|
37
38
|
|
|
38
39
|
/**
|
|
@@ -74,7 +75,7 @@ export function resolveInstructionsConfig(
|
|
|
74
75
|
const isDocument = documentType !== undefined;
|
|
75
76
|
|
|
76
77
|
const defaultGuidelines = isDocument
|
|
77
|
-
?
|
|
78
|
+
? documentGuidelines(documentType)
|
|
78
79
|
: SELFIE_GUIDELINES;
|
|
79
80
|
const guidelines =
|
|
80
81
|
config.guidelines && config.guidelines.length > 0
|
|
@@ -104,5 +105,9 @@ export function resolveInstructionsConfig(
|
|
|
104
105
|
// selfie flows only (a document has no face to frame).
|
|
105
106
|
showHeroOval: isDocument ? false : (config.showHeroOval ?? true),
|
|
106
107
|
showHeroOvalProgress: isDocument ? false : !enhanced,
|
|
108
|
+
// Card hero is the document variant only — tied to the flow type, not to
|
|
109
|
+
// `!showHeroOval` (a selfie flow can disable the oval without becoming a
|
|
110
|
+
// document, and must not then render the document card).
|
|
111
|
+
showCardBackground: isDocument,
|
|
107
112
|
};
|
|
108
113
|
}
|
|
@@ -104,6 +104,9 @@ function resolveFeedbackOverlay(
|
|
|
104
104
|
return UseSmileIDOverlayState.MOVE_UP;
|
|
105
105
|
case "si_capture_move_lower":
|
|
106
106
|
return UseSmileIDOverlayState.MOVE_DOWN;
|
|
107
|
+
// ESS re-center gate between head-turn directions
|
|
108
|
+
case "si_ess_look_at_camera":
|
|
109
|
+
return UseSmileIDOverlayState.FACE_NOT_CENTERED;
|
|
107
110
|
default:
|
|
108
111
|
return fallback;
|
|
109
112
|
}
|
|
@@ -6,7 +6,13 @@ import {
|
|
|
6
6
|
useState,
|
|
7
7
|
type ReactNode,
|
|
8
8
|
} from "react";
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
Platform,
|
|
11
|
+
StatusBar,
|
|
12
|
+
StyleSheet,
|
|
13
|
+
View,
|
|
14
|
+
useWindowDimensions,
|
|
15
|
+
} from "react-native";
|
|
10
16
|
import {
|
|
11
17
|
Camera,
|
|
12
18
|
useCameraDevice,
|
|
@@ -30,17 +36,24 @@ import {
|
|
|
30
36
|
} from "@smileid/usesmileid_bridge";
|
|
31
37
|
import { CaptureType } from "../../core/models/ml_config";
|
|
32
38
|
import type { DocumentCaptureMode } from "../../core/models/document_capture_mode";
|
|
39
|
+
import type { DocumentType } from "../../core/models/document_type";
|
|
33
40
|
import { resampleImportedDocument } from "../../camera/document_image_pipeline";
|
|
34
41
|
import { defaultLightTheme, type UseSmileIDTheme } from "../theme/theme";
|
|
42
|
+
import { UseSmileIDThemeProvider } from "../theme/theme_context";
|
|
35
43
|
import {
|
|
36
44
|
UseSmileIDCaptureContent,
|
|
37
45
|
type UseSmileIDCaptureContentState,
|
|
38
46
|
} from "../components/use_smile_id_capture_content";
|
|
47
|
+
import {
|
|
48
|
+
DEFAULT_DOCUMENT_ASPECT,
|
|
49
|
+
documentGuideRect,
|
|
50
|
+
} from "../components/use_smile_id_document_overlay";
|
|
39
51
|
import { UseSmileIDCrashReporting } from "@smileid/usesmileid_bridge";
|
|
40
52
|
import { ForceMaxBrightness } from "../utils/force_max_brightness";
|
|
41
53
|
import { CameraDefaults } from "../../camera/camera_defaults";
|
|
42
54
|
import type { SiKey } from "../../l10n/strings_en";
|
|
43
55
|
import { DocumentImageOrigin } from "../../metadata/document_image_origin";
|
|
56
|
+
import { DeviceOrientationCollector } from "../../metadata/device_orientation_collector";
|
|
44
57
|
import { useSmileIDFrameStream } from "../../camera/use_smile_id_frame_stream";
|
|
45
58
|
import { orientationToDegrees } from "../../camera/orientation_degrees";
|
|
46
59
|
import {
|
|
@@ -55,6 +68,20 @@ import {
|
|
|
55
68
|
triggerEssTurnHaptic,
|
|
56
69
|
} from "./helpers/ess_turn_haptics";
|
|
57
70
|
|
|
71
|
+
/** Capture telemetry surfaced alongside the captured artifacts at completion. */
|
|
72
|
+
export interface CaptureTelemetry {
|
|
73
|
+
/** Elapsed time in ms from the first analyzed frame to completion. */
|
|
74
|
+
readonly durationMs: number;
|
|
75
|
+
/** Count of face/document-lost resets (rising edges of `unsatisfied`). */
|
|
76
|
+
readonly retries: number;
|
|
77
|
+
/** Identifier of the camera used for capture (`CameraDevice.id`); `undefined` until resolved. */
|
|
78
|
+
readonly cameraName?: string;
|
|
79
|
+
/** Accelerometer `"epochMs,x,y,z"` samples collected during capture. */
|
|
80
|
+
readonly devicePositions: readonly string[];
|
|
81
|
+
/** Span of movement magnitude during capture; `null` when no samples ran. */
|
|
82
|
+
readonly deviceMovementDetected: number | null;
|
|
83
|
+
}
|
|
84
|
+
|
|
58
85
|
export type UseSmileIDCaptureScreenProps = {
|
|
59
86
|
readonly captureType: CaptureType;
|
|
60
87
|
|
|
@@ -73,7 +100,10 @@ export type UseSmileIDCaptureScreenProps = {
|
|
|
73
100
|
* settled, with every `CaptureReadyEvent` of the session (one
|
|
74
101
|
* `"selfie"` + N `"liveness"` for face, one `"document"` for document).
|
|
75
102
|
*/
|
|
76
|
-
readonly onCaptureComplete?: (
|
|
103
|
+
readonly onCaptureComplete?: (
|
|
104
|
+
events: readonly CaptureReadyEvent[],
|
|
105
|
+
telemetry: CaptureTelemetry,
|
|
106
|
+
) => void;
|
|
77
107
|
/** Records how a document side was produced (auto/manual/gallery), fired just before delivery. */
|
|
78
108
|
readonly onDocumentOrigin?: (origin: DocumentImageOrigin) => void;
|
|
79
109
|
|
|
@@ -106,6 +136,8 @@ export type UseSmileIDCaptureScreenProps = {
|
|
|
106
136
|
* `document_front.jpg` / `document_back.jpg`. Ignored for selfie capture.
|
|
107
137
|
*/
|
|
108
138
|
readonly documentSide?: DocumentSide;
|
|
139
|
+
/** Document type — selects the in-frame capture shimmer skeleton. Ignored for selfie. */
|
|
140
|
+
readonly documentTypeKind?: DocumentType["kind"];
|
|
109
141
|
/** Close/cancel the whole flow (document capture chrome — top-right X). */
|
|
110
142
|
readonly onClose?: () => void;
|
|
111
143
|
|
|
@@ -140,15 +172,24 @@ export function UseSmileIDCaptureScreen(props: UseSmileIDCaptureScreenProps) {
|
|
|
140
172
|
const cameraRef = useRef<Camera>(null);
|
|
141
173
|
// Pin an explicit format: the "highest supported" heuristic can pick 4K,
|
|
142
174
|
// stalling the frame-processor thread and stuttering the pipeline.
|
|
175
|
+
// Document capture uses 16:9 so the analysis FOV matches the visible 16:9
|
|
176
|
+
// preview — keeping the guide-rectangle crop aligned with the framed document
|
|
177
|
+
// (mirrors the native Android SDK's RATIO_16_9 + 1280×720 pin). Selfie keeps
|
|
178
|
+
// 4:3: the face geometry + smile heuristic are calibrated on 4:3, and 16:9
|
|
179
|
+
// skews normalized landmark ratios and shifts every threshold.
|
|
180
|
+
const isDocumentFormat = props.captureType === CaptureType.document;
|
|
143
181
|
const format = useCameraFormat(device, [
|
|
144
|
-
|
|
145
|
-
// 16:9 skews normalized landmark ratios and shifts every threshold.
|
|
146
|
-
{ videoAspectRatio: 4 / 3 },
|
|
182
|
+
{ videoAspectRatio: isDocumentFormat ? 16 / 9 : 4 / 3 },
|
|
147
183
|
{
|
|
148
|
-
videoResolution:
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
184
|
+
videoResolution: isDocumentFormat
|
|
185
|
+
? {
|
|
186
|
+
width: CameraDefaults.documentAnalysisResolution.width,
|
|
187
|
+
height: CameraDefaults.documentAnalysisResolution.height,
|
|
188
|
+
}
|
|
189
|
+
: {
|
|
190
|
+
width: CameraDefaults.analysisTargetResolution.width,
|
|
191
|
+
height: CameraDefaults.analysisTargetResolution.height,
|
|
192
|
+
},
|
|
152
193
|
},
|
|
153
194
|
{ fps: CameraDefaults.analysisTargetFps },
|
|
154
195
|
]);
|
|
@@ -193,6 +234,33 @@ export function UseSmileIDCaptureScreen(props: UseSmileIDCaptureScreenProps) {
|
|
|
193
234
|
// transitions the 1% bucketing skips committing are still seen.
|
|
194
235
|
const previousScanStateRef = useRef<ScanState | null>(null);
|
|
195
236
|
|
|
237
|
+
// Capture telemetry: wall-clock start (first analyzed frame) and a
|
|
238
|
+
// rising-edge `unsatisfied` retry counter, surfaced via onCaptureComplete.
|
|
239
|
+
const captureStartedAtRef = useRef<number | null>(null);
|
|
240
|
+
const captureRetriesRef = useRef<number>(0);
|
|
241
|
+
const wasUnsatisfiedRef = useRef<boolean>(false);
|
|
242
|
+
// Accelerometer sampler for device_positions / device_movement_detected, run only
|
|
243
|
+
// while the live capture loop is streaming.
|
|
244
|
+
const deviceOrientationRef = useRef<DeviceOrientationCollector>(
|
|
245
|
+
new DeviceOrientationCollector(),
|
|
246
|
+
);
|
|
247
|
+
|
|
248
|
+
const captureTelemetry = useCallback(
|
|
249
|
+
(): CaptureTelemetry => ({
|
|
250
|
+
durationMs:
|
|
251
|
+
captureStartedAtRef.current === null
|
|
252
|
+
? 0
|
|
253
|
+
: Date.now() - captureStartedAtRef.current,
|
|
254
|
+
retries: captureRetriesRef.current,
|
|
255
|
+
devicePositions: deviceOrientationRef.current.devicePositions,
|
|
256
|
+
deviceMovementDetected:
|
|
257
|
+
deviceOrientationRef.current.deviceMovementDetected,
|
|
258
|
+
// Omit (not set to undefined) when unresolved — exactOptionalPropertyTypes.
|
|
259
|
+
...(device?.id !== undefined ? { cameraName: device.id } : {}),
|
|
260
|
+
}),
|
|
261
|
+
[device],
|
|
262
|
+
);
|
|
263
|
+
|
|
196
264
|
const onStartCapture = props.onStartCapture;
|
|
197
265
|
const handleStart = useCallback(() => {
|
|
198
266
|
if (streaming || completedRef.current) return;
|
|
@@ -213,6 +281,23 @@ export function UseSmileIDCaptureScreen(props: UseSmileIDCaptureScreenProps) {
|
|
|
213
281
|
const documentSide = props.documentSide ?? DocumentSide.Front;
|
|
214
282
|
const isDocumentCapture = props.captureType === CaptureType.document;
|
|
215
283
|
|
|
284
|
+
// Reset capture telemetry per side so each document side reports its own
|
|
285
|
+
// duration / retries (the screen instance is reused across the front→back flip).
|
|
286
|
+
useEffect(() => {
|
|
287
|
+
captureStartedAtRef.current = null;
|
|
288
|
+
captureRetriesRef.current = 0;
|
|
289
|
+
wasUnsatisfiedRef.current = false;
|
|
290
|
+
}, [documentSide]);
|
|
291
|
+
|
|
292
|
+
// Sample the accelerometer only while the live capture loop streams. start()
|
|
293
|
+
// clears prior samples, so a retry / side switch begins fresh; cleanup stops it.
|
|
294
|
+
useEffect(() => {
|
|
295
|
+
if (streaming) {
|
|
296
|
+
deviceOrientationRef.current.start();
|
|
297
|
+
}
|
|
298
|
+
return () => deviceOrientationRef.current.stop();
|
|
299
|
+
}, [streaming]);
|
|
300
|
+
|
|
216
301
|
// Reveal the fallback shutter after the delay once streaming begins.
|
|
217
302
|
// Bound to `streaming`: any capture clears it, tearing this effect down
|
|
218
303
|
// and clearing the timer, so it can't fire post-capture or leak.
|
|
@@ -249,13 +334,16 @@ export function UseSmileIDCaptureScreen(props: UseSmileIDCaptureScreenProps) {
|
|
|
249
334
|
documentSide,
|
|
250
335
|
);
|
|
251
336
|
onDocumentOrigin?.(DocumentImageOrigin.CameraManualCapture);
|
|
252
|
-
onCaptureComplete?.(
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
337
|
+
onCaptureComplete?.(
|
|
338
|
+
[
|
|
339
|
+
{
|
|
340
|
+
kind: CaptureReadyEventKind.Document,
|
|
341
|
+
captureIndex: 0,
|
|
342
|
+
url: processedUri,
|
|
343
|
+
},
|
|
344
|
+
],
|
|
345
|
+
captureTelemetry(),
|
|
346
|
+
);
|
|
259
347
|
} catch (error) {
|
|
260
348
|
UseSmileIDCrashReporting.captureException(
|
|
261
349
|
error instanceof Error ? error : new Error(String(error)),
|
|
@@ -318,13 +406,16 @@ export function UseSmileIDCaptureScreen(props: UseSmileIDCaptureScreenProps) {
|
|
|
318
406
|
documentSide,
|
|
319
407
|
);
|
|
320
408
|
onDocumentOrigin?.(DocumentImageOrigin.Gallery);
|
|
321
|
-
onCaptureComplete?.(
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
409
|
+
onCaptureComplete?.(
|
|
410
|
+
[
|
|
411
|
+
{
|
|
412
|
+
kind: CaptureReadyEventKind.Document,
|
|
413
|
+
captureIndex: 0,
|
|
414
|
+
url: processedUri,
|
|
415
|
+
},
|
|
416
|
+
],
|
|
417
|
+
captureTelemetry(),
|
|
418
|
+
);
|
|
328
419
|
} catch (error) {
|
|
329
420
|
UseSmileIDCrashReporting.captureException(
|
|
330
421
|
error instanceof Error ? error : new Error(String(error)),
|
|
@@ -379,6 +470,17 @@ export function UseSmileIDCaptureScreen(props: UseSmileIDCaptureScreenProps) {
|
|
|
379
470
|
// Unsatisfied = native session reset; drop accumulated events so it
|
|
380
471
|
// can't leak stale liveness frames. `else` so a reset frame can't
|
|
381
472
|
// re-add its own stale events on the same pass.
|
|
473
|
+
// Capture telemetry: anchor the start clock on the first analyzed frame,
|
|
474
|
+
// and count rising edges of `unsatisfied` as retries.
|
|
475
|
+
if (captureStartedAtRef.current === null) {
|
|
476
|
+
captureStartedAtRef.current = Date.now();
|
|
477
|
+
}
|
|
478
|
+
const isUnsatisfied = result.state.type === ScanStateType.Unsatisfied;
|
|
479
|
+
if (isUnsatisfied && !wasUnsatisfiedRef.current) {
|
|
480
|
+
captureRetriesRef.current += 1;
|
|
481
|
+
}
|
|
482
|
+
wasUnsatisfiedRef.current = isUnsatisfied;
|
|
483
|
+
|
|
382
484
|
if (result.state.type === ScanStateType.Unsatisfied) {
|
|
383
485
|
capturedEventsRef.current = [];
|
|
384
486
|
} else if (result.capturedEvents.length > 0) {
|
|
@@ -420,7 +522,7 @@ export function UseSmileIDCaptureScreen(props: UseSmileIDCaptureScreenProps) {
|
|
|
420
522
|
.finally(() => {
|
|
421
523
|
// No-op for selfie (callback unset).
|
|
422
524
|
onDocumentOrigin?.(DocumentImageOrigin.CameraAutoCapture);
|
|
423
|
-
onCaptureComplete?.(capturedEventsRef.current);
|
|
525
|
+
onCaptureComplete?.(capturedEventsRef.current, captureTelemetry());
|
|
424
526
|
});
|
|
425
527
|
} else if (result.state.type === ScanStateType.Timeout) {
|
|
426
528
|
if (completedRef.current) return;
|
|
@@ -487,21 +589,99 @@ export function UseSmileIDCaptureScreen(props: UseSmileIDCaptureScreenProps) {
|
|
|
487
589
|
});
|
|
488
590
|
}, [onFrameResult]);
|
|
489
591
|
|
|
490
|
-
// Physical device tilt (0 =
|
|
491
|
-
//
|
|
492
|
-
// never derived from `frame.orientation` (fixed sensor mounting).
|
|
592
|
+
// Physical device tilt (0 = portrait) for the native upright validator /
|
|
593
|
+
// head-pose math; gravity-sourced, never from `frame.orientation`.
|
|
493
594
|
const [deviceOrientationDegrees, setDeviceOrientationDegrees] = useState(0);
|
|
494
595
|
|
|
596
|
+
// Locked INTERFACE orientation (0/90/270) — the axis the preview and guide are
|
|
597
|
+
// drawn against, from VisionCamera's preview orientation, NOT device gravity
|
|
598
|
+
// (the document screen locks the interface while the phone is held flat, so
|
|
599
|
+
// gravity disagrees). iOS uprights the saved document to this axis.
|
|
600
|
+
const [previewOrientationDegrees, setPreviewOrientationDegrees] = useState(0);
|
|
601
|
+
|
|
602
|
+
// VisionCamera derives its iOS preview orientation from the interface
|
|
603
|
+
// orientation but only refreshes it on a PHYSICAL rotation — a programmatic
|
|
604
|
+
// lock (the document landscape lock) never fires that, so the preview stays
|
|
605
|
+
// portrait in the rotated UI. Remounting <Camera> when the interface flips
|
|
606
|
+
// forces a re-read. iOS only — Android's preview already tracks the lock.
|
|
607
|
+
const { width: windowWidth, height: windowHeight } = useWindowDimensions();
|
|
608
|
+
const cameraOrientationKey =
|
|
609
|
+
Platform.OS === "ios"
|
|
610
|
+
? windowWidth > windowHeight
|
|
611
|
+
? "landscape"
|
|
612
|
+
: "portrait"
|
|
613
|
+
: "camera";
|
|
614
|
+
|
|
615
|
+
// Camera viewport size, reported by the capture content on layout. Drives the
|
|
616
|
+
// document crop region so the saved capture matches the on-screen frame.
|
|
617
|
+
const [viewport, setViewport] = useState({ width: 0, height: 0 });
|
|
618
|
+
const handleViewportLayout = useCallback(
|
|
619
|
+
(size: { width: number; height: number }) => {
|
|
620
|
+
setViewport((previous) =>
|
|
621
|
+
previous.width === size.width && previous.height === size.height
|
|
622
|
+
? previous
|
|
623
|
+
: size,
|
|
624
|
+
);
|
|
625
|
+
},
|
|
626
|
+
[],
|
|
627
|
+
);
|
|
628
|
+
|
|
629
|
+
// The document guide rectangle as a native crop region — viewport fractions +
|
|
630
|
+
// size + cover scale — derived from the SAME geometry the overlay draws
|
|
631
|
+
// (documentGuideRect), so the native side crops the saved document to exactly
|
|
632
|
+
// the framed rectangle. undefined for selfie or before the viewport is known.
|
|
633
|
+
const documentCropRegion = useMemo(() => {
|
|
634
|
+
if (!isDocumentCapture || viewport.width <= 0 || viewport.height <= 0) {
|
|
635
|
+
return undefined;
|
|
636
|
+
}
|
|
637
|
+
const aspect = props.knownIdAspectRatio ?? DEFAULT_DOCUMENT_ASPECT;
|
|
638
|
+
const rect = documentGuideRect(aspect, viewport.width, viewport.height);
|
|
639
|
+
return {
|
|
640
|
+
left: rect.left / viewport.width,
|
|
641
|
+
top: rect.top / viewport.height,
|
|
642
|
+
width: rect.width / viewport.width,
|
|
643
|
+
height: rect.height / viewport.height,
|
|
644
|
+
viewportWidthPx: Math.round(viewport.width),
|
|
645
|
+
viewportHeightPx: Math.round(viewport.height),
|
|
646
|
+
};
|
|
647
|
+
}, [isDocumentCapture, viewport, props.knownIdAspectRatio]);
|
|
648
|
+
|
|
495
649
|
const frameProcessor = useFrameProcessor(
|
|
496
650
|
(frame) => {
|
|
497
651
|
"worklet";
|
|
498
652
|
if (!plugin) return;
|
|
653
|
+
// Crop region passed as FLAT numeric args — frame-processor arguments
|
|
654
|
+
// don't reliably accept nested objects. cropWidth <= 0 signals "no region"
|
|
655
|
+
// (selfie, or before the viewport is measured), leaving it uncropped.
|
|
656
|
+
//
|
|
657
|
+
// The saved document uprights to the LOCKED INTERFACE axis (what the
|
|
658
|
+
// preview and guide are drawn against), never device gravity (the phone is
|
|
659
|
+
// held flat): iOS uprights to `viewportOrientation`, Android via its
|
|
660
|
+
// display-tracking `rotationDegrees`. `rotation` stays the RAW gravity
|
|
661
|
+
// tilt the native upright validator needs.
|
|
499
662
|
const rawResult = plugin.call(frame, {
|
|
500
663
|
rotation: deviceOrientationDegrees,
|
|
664
|
+
viewportOrientation: previewOrientationDegrees,
|
|
665
|
+
cropLeft: documentCropRegion ? documentCropRegion.left : 0,
|
|
666
|
+
cropTop: documentCropRegion ? documentCropRegion.top : 0,
|
|
667
|
+
cropWidth: documentCropRegion ? documentCropRegion.width : 0,
|
|
668
|
+
cropHeight: documentCropRegion ? documentCropRegion.height : 0,
|
|
669
|
+
cropViewportWidth: documentCropRegion
|
|
670
|
+
? documentCropRegion.viewportWidthPx
|
|
671
|
+
: 0,
|
|
672
|
+
cropViewportHeight: documentCropRegion
|
|
673
|
+
? documentCropRegion.viewportHeightPx
|
|
674
|
+
: 0,
|
|
501
675
|
});
|
|
502
676
|
onFrameResultRunOnJS(rawResult);
|
|
503
677
|
},
|
|
504
|
-
[
|
|
678
|
+
[
|
|
679
|
+
plugin,
|
|
680
|
+
onFrameResultRunOnJS,
|
|
681
|
+
deviceOrientationDegrees,
|
|
682
|
+
previewOrientationDegrees,
|
|
683
|
+
documentCropRegion,
|
|
684
|
+
],
|
|
505
685
|
);
|
|
506
686
|
|
|
507
687
|
// Document controls — live capture only (after Start). Manual shutter
|
|
@@ -530,9 +710,13 @@ export function UseSmileIDCaptureScreen(props: UseSmileIDCaptureScreenProps) {
|
|
|
530
710
|
showCaptureButton: isInstructionState && !isDocumentCapture,
|
|
531
711
|
showManualShutter: manualShutterAvailable,
|
|
532
712
|
showGalleryUpload: galleryAvailable,
|
|
713
|
+
isBackSide: documentSide === DocumentSide.Back,
|
|
533
714
|
...(props.knownIdAspectRatio !== undefined
|
|
534
715
|
? { knownIdAspectRatio: props.knownIdAspectRatio }
|
|
535
716
|
: {}),
|
|
717
|
+
...(props.documentTypeKind !== undefined
|
|
718
|
+
? { documentTypeKind: props.documentTypeKind }
|
|
719
|
+
: {}),
|
|
536
720
|
}),
|
|
537
721
|
[
|
|
538
722
|
props.captureType,
|
|
@@ -546,7 +730,9 @@ export function UseSmileIDCaptureScreen(props: UseSmileIDCaptureScreenProps) {
|
|
|
546
730
|
isDocumentCapture,
|
|
547
731
|
manualShutterAvailable,
|
|
548
732
|
galleryAvailable,
|
|
733
|
+
documentSide,
|
|
549
734
|
props.knownIdAspectRatio,
|
|
735
|
+
props.documentTypeKind,
|
|
550
736
|
],
|
|
551
737
|
);
|
|
552
738
|
|
|
@@ -554,14 +740,14 @@ export function UseSmileIDCaptureScreen(props: UseSmileIDCaptureScreenProps) {
|
|
|
554
740
|
const cameraPreview = useMemo(
|
|
555
741
|
() => (
|
|
556
742
|
<>
|
|
557
|
-
{/*
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
/>
|
|
743
|
+
{/* Every capture screen runs at max brightness with the screen kept
|
|
744
|
+
awake, restored on unmount. Selfie uses the front camera with the
|
|
745
|
+
screen as fill light; document capture keeps the same guarantee so
|
|
746
|
+
the preview never dims or auto-locks mid-scan. */}
|
|
747
|
+
<ForceMaxBrightness />
|
|
563
748
|
{previewReady ? (
|
|
564
749
|
<Camera
|
|
750
|
+
key={cameraOrientationKey}
|
|
565
751
|
ref={cameraRef}
|
|
566
752
|
style={StyleSheet.absoluteFill}
|
|
567
753
|
device={device}
|
|
@@ -576,6 +762,11 @@ export function UseSmileIDCaptureScreen(props: UseSmileIDCaptureScreenProps) {
|
|
|
576
762
|
onOutputOrientationChanged={(orientation) => {
|
|
577
763
|
setDeviceOrientationDegrees(orientationToDegrees(orientation));
|
|
578
764
|
}}
|
|
765
|
+
// The LOCKED interface orientation (follows the screen even under a
|
|
766
|
+
// programmatic lock) — the axis the saved document uprights to.
|
|
767
|
+
onPreviewOrientationChanged={(orientation) => {
|
|
768
|
+
setPreviewOrientationDegrees(orientationToDegrees(orientation));
|
|
769
|
+
}}
|
|
579
770
|
// Attach the frame processor only while streaming (skip pre-Start
|
|
580
771
|
// preview). Spread idiom because exactOptionalPropertyTypes rejects
|
|
581
772
|
// passing `undefined` to an optional prop directly.
|
|
@@ -602,11 +793,17 @@ export function UseSmileIDCaptureScreen(props: UseSmileIDCaptureScreenProps) {
|
|
|
602
793
|
streaming,
|
|
603
794
|
frameProcessor,
|
|
604
795
|
theme.colors.offBlack,
|
|
796
|
+
cameraOrientationKey,
|
|
605
797
|
],
|
|
606
798
|
);
|
|
607
799
|
|
|
608
800
|
return (
|
|
609
|
-
|
|
801
|
+
// The capture screen is always light, regardless of the system dark-mode
|
|
802
|
+
// setting (every other screen tracks the system). Providing the light theme
|
|
803
|
+
// here forces every descendant that reads it from context — not only the
|
|
804
|
+
// ones passing `forceLightMode` — to render light; partner colours still
|
|
805
|
+
// apply because `theme` carries the partner's resolved light tokens.
|
|
806
|
+
<UseSmileIDThemeProvider value={theme}>
|
|
610
807
|
{/* Translucent status bar → full-bleed window so the oval's reference
|
|
611
808
|
frame is the full screen (no-op on iOS). On-device-pending: residual
|
|
612
809
|
inset also depends on the host SafeAreaProvider config. */}
|
|
@@ -620,6 +817,7 @@ export function UseSmileIDCaptureScreen(props: UseSmileIDCaptureScreenProps) {
|
|
|
620
817
|
onBack={props.onBack}
|
|
621
818
|
showAttribution={showAttribution}
|
|
622
819
|
startButton={props.startButton}
|
|
820
|
+
onViewportLayout={handleViewportLayout}
|
|
623
821
|
{...(isDocumentCapture
|
|
624
822
|
? {
|
|
625
823
|
onManualShutter: handleManualShutter,
|
|
@@ -630,6 +828,6 @@ export function UseSmileIDCaptureScreen(props: UseSmileIDCaptureScreenProps) {
|
|
|
630
828
|
: {})}
|
|
631
829
|
theme={theme}
|
|
632
830
|
/>
|
|
633
|
-
|
|
831
|
+
</UseSmileIDThemeProvider>
|
|
634
832
|
);
|
|
635
833
|
}
|