Skip to content

[WIP] 🚧 Rework Platform Views #146

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 16 commits into
base: main
Choose a base branch
from
Open

Conversation

jumaallan
Copy link
Member

@jumaallan jumaallan commented Mar 3, 2025

User description

Story: https://app.shortcut.com/smileid/story/xxx

Summary

A few sentences/bullet points about the changes

Known Issues

Any shortcomings in your work. This may include corner cases not correctly handled or issues related
to but not within the scope of your PR. Design compromises should be discussed here if they were not
already discussed above.

Test Instructions

Concise test instructions on how to verify that your feature works as intended. This should include
changes to the development environment (if applicable) and all commands needed to run your work.

Screenshot

If applicable (e.g. UI changes), add screenshots to help explain your work.


PR Type

Enhancement, Documentation


Description

  • Reworked platform views with type-safe results

  • Added SmileIDProductsApi for unified product handling

  • Migrated to Pigeon v22.7.1 codegen

  • Improved error handling and result delivery


Changes walkthrough 📝

Relevant files
Enhancement
7 files
smileid_messages.g.dart
Update Pigeon generated code with new message types           
+2034/-685
smile_id_sdk_result.dart
Add sealed class for type-safe SDK results                             
+20/-0   
smile_id_product_views_api.dart
Add unified API for SmileID product views                               
+169/-0 
result_clients_interfaces.dart
Add interfaces for handling product results                           
+15/-0   
product_result_adapters.dart
Add adapters for handling product results                               
+177/-0 
SmileIDProductsPluginApi.kt
Add Android implementation of SmileIDProductsApi                 
+659/-0 
SmileIDProductsPluginApi.swift
Add iOS implementation of SmileIDProductsApi                         
+185/-0 
Documentation
1 files
main.dart
Update example app to use new type-safe results                   
+236/-198
Additional files
76 files
build.yaml +5/-3     
AndroidManifest.xml +58/-1   
SmileComposablePlatformView.kt +0/-112 
SmileIDBiometricKYC.kt +0/-114 
SmileIDDocumentVerification.kt +0/-97   
SmileIDEnhancedDocumentVerification.kt +0/-108 
SmileIDPlugin.kt +59/-21 
SmileIDSmartSelfieAuthentication.kt +0/-52   
SmileIDSmartSelfieEnrollment.kt +0/-52   
SmileSelfieComposablePlatformView.kt +0/-49   
SmileIDSmartSelfieAuthenticationEnhanced.kt +0/-52   
SmileIDSmartSelfieEnrollmentEnhanced.kt +0/-52   
SmileIDMessages.g.kt +1912/-1293
Mapper.kt +73/-35 
SmileIDBiometricKYC.kt +88/-0   
SmileIDBiometricKYCActivity.kt +94/-0   
SmileIDDocumentCaptureView.kt +26/-45 
SmileIDSmartSelfieCaptureView.kt +38/-21 
SmileIDDocumentVerification.kt +74/-0   
SmileIDDocumentVerificationActivity.kt +95/-0   
SmileIDEnhancedDocumentVerification.kt +87/-0   
SmileIDEnhancedDocumentVerificationActivity.kt +95/-0   
SmileIDSmartSelfieAuthenticationEnhanced.kt +62/-0   
SmileIDSmartSelfieAuthenticationEnhancedActivity.kt +64/-0   
SmileIDSmartSelfieEnrollmentEnhanced.kt +62/-0   
SmileIDSmartSelfieEnrollmentEnhancedActivity.kt +63/-0   
SmileIDSmartSelfieAuthentication.kt +63/-0   
SmileIDSmartSelfieAuthenticationActivity.kt +72/-0   
SmileIDSmartSelfieEnrollment.kt +63/-0   
SmileIDSmartSelfieEnrollmentActivity.kt +72/-0   
SmileComposablePlatformView.kt +64/-0   
SmileIDPlatformView.kt +55/-0   
gradle.properties +1/-1     
AppFrameworkInfo.plist +1/-1     
project.pbxproj +87/-59 
Runner.xcscheme +20/-1   
AppDelegate.swift +1/-1     
widget_test.dart +2/-2     
Mapper.swift +16/-0   
SmileDocumentCaptureView.swift +79/-0   
SmileIDBiometricKYC.swift +12/-26 
SmileIDBiometricKYCView.swift +64/-0   
SmileIDDocumentCaptureView.swift +15/-35 
SmileIDDocumentVerification.swift +15/-24 
SmileIDDocumentVerificationView.swift +56/-0   
SmileIDEnhancedDocumentVerification.swift +10/-24 
SmileIDEnhancedDocumentVerificationView.swift +55/-0   
SmileIDMessages.g.swift +1505/-528
SmileIDPlugin.swift +27/-23 
SmileIDProductResultsPluginApi.swift +4/-0     
SmileIDSmartSelfieAuthentication.swift +10/-21 
SmileIDSmartSelfieAuthenticationEnhanced.swift +13/-20 
SmileIDSmartSelfieAuthenticationEnhancedView.swift +50/-0   
SmileIDSmartSelfieAuthenticationView.swift +48/-0   
SmileIDSmartSelfieCaptureView.swift +16/-45 
SmileIDSmartSelfieEnrollment.swift +16/-18 
SmileIDSmartSelfieEnrollmentEnhanced.swift +14/-21 
SmileIDSmartSelfieEnrollmentEnhancedView.swift +51/-0   
SmileIDSmartSelfieEnrollmentView.swift +54/-0   
SmileSelfieCaptureView.swift +87/-0   
smile_id.dart +126/-7 
smile_id_biometric_kyc.dart +42/-33 
smile_id_document_capture_view.dart +44/-33 
smile_id_document_verification.dart +48/-36 
smile_id_enhanced_document_verification.dart +48/-36 
smile_id_service.dart +42/-32 
smile_id_smart_selfie_authentication.dart +47/-35 
smile_id_smart_selfie_authentication_enhanced.dart +47/-35 
smile_id_smart_selfie_capture_view.dart +45/-33 
smile_id_smart_selfie_enrollment.dart +47/-35 
smile_id_smart_selfie_enrollment_enhanced.dart +47/-35 
lint.sh +3/-0     
messages.dart +330/-22
pubspec.yaml +4/-2     
smile_id_test.dart +3/-5     
smile_id_test.mocks.dart +7/-7     

Need help?
  • Type /help how to ... in the comments thread for any questions about PR-Agent usage.
  • Check out the documentation for more information.
  • Copy link
    Contributor

    This PR is stale because it has been open 14 days with no activity. Remove stale label or comment or this will be closed in 7 days.

    @github-actions github-actions bot added the Stale label Mar 17, 2025
    Copy link
    Contributor

    This PR was closed because it has been stalled for 7 days with no activity.

    @github-actions github-actions bot closed this Mar 25, 2025
    @jumaallan jumaallan reopened this Mar 31, 2025
    @github-actions github-actions bot removed the Stale label Mar 31, 2025
    CoderNamedHendrick and others added 2 commits April 2, 2025 18:24
    * rough poc of platform views migration
    
    * remove unncessary delegate controller
    
    * resolve comments
    
    * upgrade pigeon, get codegen improvements
    
    * updated configurations
    
    * code formatting and linting
    
    * - remove title bar
    - add format/lint to build script
    
    * - added smartSelfieEnrollment to SmileID class returning SmileIDSdkResult
    - added deprecation notice for SmileIDSmartSelfieEnrollment widget
    
    * remove unnecessary format
    
    * remove unused didSubmitBiometricKycJob parameter
    
    * - added smile_id_smart_selfie_authentication method
    - added smile_id_smart_selfie_enrollment_enhanced method
    - added smile_id_smart_selfie_authentication_enhanced_method
    
    * refactor products api to separate implementation
    
    * remove xcode file creation comments
    
    * remove need for client to wrap application in a UINavigationController
    
    * fix linting issues flutter
    
    * resolve linting issues on android
    
    * - attend to issues with PR
    - lock orientation on android
    - set preferred colorScheme to light mode on iOS
    
    * remove portrait hosting controller attempt at locking iOS to portrait mode
    
    * fix force light mode on ios
    
    * add back button
    
    * - added document verification product
    - added document verification enhanced product
    - added biometric kyc product
    
    * - added selfie capture product
    - added document capture product
    
    * linting code
    
    ---------
    
    Co-authored-by: Juma Allan <allanjuma@gmail.com>
    * fixed issue with back button not being aligned at the top
    
    * lock orientation using custom smile id controller.
    
    * apply perfectionist weak var fix
    @jumaallan jumaallan force-pushed the epic/rework-platform-views branch from fd4d146 to 4f72e77 Compare April 2, 2025 15:25
    jumaallan and others added 14 commits April 2, 2025 18:38
    * Migration from platform views 🚧 (#136)
    
    * rough poc of platform views migration
    
    * remove unncessary delegate controller
    
    * resolve comments
    
    * upgrade pigeon, get codegen improvements
    
    * updated configurations
    
    * code formatting and linting
    
    * - remove title bar
    - add format/lint to build script
    
    * - added smartSelfieEnrollment to SmileID class returning SmileIDSdkResult
    - added deprecation notice for SmileIDSmartSelfieEnrollment widget
    
    * remove unnecessary format
    
    * remove unused didSubmitBiometricKycJob parameter
    
    * - added smile_id_smart_selfie_authentication method
    - added smile_id_smart_selfie_enrollment_enhanced method
    - added smile_id_smart_selfie_authentication_enhanced_method
    
    * refactor products api to separate implementation
    
    * remove xcode file creation comments
    
    * remove need for client to wrap application in a UINavigationController
    
    * fix linting issues flutter
    
    * resolve linting issues on android
    
    * - attend to issues with PR
    - lock orientation on android
    - set preferred colorScheme to light mode on iOS
    
    * remove portrait hosting controller attempt at locking iOS to portrait mode
    
    * fix force light mode on ios
    
    * add back button
    
    * - added document verification product
    - added document verification enhanced product
    - added biometric kyc product
    
    * - added selfie capture product
    - added document capture product
    
    * linting code
    
    ---------
    
    Co-authored-by: Juma Allan <allanjuma@gmail.com>
    
    * feature: typesafe results for SmileID widgets
    - SmileSelfieEnrollment
    
    * resolve linting issues on android
    
    * Added dart linter format to the build script to ensure dart code is formatted before merging
    
    * remove format temporarily from build script
    
    * update flutter version in analyse and lint build script
    
    * - refactor plugin to widget communication
    - added lint.sh for flutter and kotlin linting
    
    * - resolve merge conflicts
    
    * update ios flutter version to resolve swift package manager issue
    
    * resolve comments
    
    * fixed lint issues
    
    * retrieve packages
    
    ---------
    
    Co-authored-by: Juma Allan <allanjuma@gmail.com>
    * - typesafe results client/dart apis update
    - typesafe result backend(ios) api update
    
    - typesafe result backend(android) api update
    
    * lint fixes
    
    * resolve perfectionist suggestions
    
    * improve code and apply lint
    
    * updated the mapper
    
    * undo my smart ass changes
    
    * re organized project directories
    
    * re organized project directories
    
    * updated products to use a more abstract setup
    
    * removed unnecessary dependency on binaryMessenger
    
    ---------
    
    Co-authored-by: Juma Allan <allanjuma@gmail.com>
    @jumaallan jumaallan changed the title [Draft] Rework Platform Views Rework Platform Views Apr 16, 2025
    @jumaallan jumaallan marked this pull request as ready for review April 16, 2025 14:15
    @jumaallan jumaallan requested a review from a team as a code owner April 16, 2025 14:15
    @prfectionist
    Copy link

    prfectionist bot commented Apr 16, 2025

    PR Reviewer Guide 🔍

    Here are some key observations to aid the review process:

    ⏱️ Estimated effort to review: 5 🔵🔵🔵🔵🔵
    🧪 No relevant tests
    🔒 No security concerns identified
    ⚡ Recommended focus areas for review

    API Breaking Changes

    Major changes to enum values and API structure that could break existing integrations. Need to verify all enum value changes are backwards compatible and properly handled.

    enum FlutterJobType {
      enhancedKyc,
      documentVerification,
      biometricKyc,
      enhancedDocumentVerification,
      smartSelfieEnrollment,
      smartSelfieAuthentication,
    }
    
    enum FlutterJobTypeV2 {
      smartSelfieAuthentication,
      smartSelfieEnrollment,
    }
    
    enum FlutterImageType {
      selfieJpgFile,
      idCardJpgFile,
      selfieJpgBase64,
      idCardJpgBase64,
      livenessJpgFile,
      idCardRearJpgFile,
      livenessJpgBase64,
      idCardRearJpgBase64,
    }
    
    enum FlutterActionResult {
      passed,
      completed,
      approved,
      verified,
      provisionallyApproved,
      returned,
      notReturned,
      failed,
      rejected,
      underReview,
      unableToDetermine,
      notApplicable,
      notVerified,
      notDone,
      issuerUnavailable,
      idAuthorityPhotoNotAvailable,
      sentToHumanReview,
      unknown,
    }
    
    enum FlutterSmartSelfieStatus {
      approved,
      pending,
      rejected,
      unknown,
    }
    
    class FlutterConsentInformation {
      FlutterConsentInformation({
        required this.consentGrantedDate,
        required this.personalDetailsConsentGranted,
        required this.contactInfoConsentGranted,
        required this.documentInfoConsentGranted,
      });
    
      String consentGrantedDate;
    
      bool personalDetailsConsentGranted;
    
      bool contactInfoConsentGranted;
    
      bool documentInfoConsentGranted;
    
      Object encode() {
        return <Object?>[
          consentGrantedDate,
          personalDetailsConsentGranted,
          contactInfoConsentGranted,
          documentInfoConsentGranted,
        ];
      }
    
      static FlutterConsentInformation decode(Object result) {
        result as List<Object?>;
        return FlutterConsentInformation(
          consentGrantedDate: result[0]! as String,
          personalDetailsConsentGranted: result[1]! as bool,
          contactInfoConsentGranted: result[2]! as bool,
          documentInfoConsentGranted: result[3]! as bool,
        );
      }
    }
    
    ///  Custom values specific to partners can be placed in [extras]
    class FlutterPartnerParams {
      FlutterPartnerParams({
        this.jobType,
        required this.jobId,
        required this.userId,
        this.extras,
      });
    
      FlutterJobType? jobType;
    
      String jobId;
    
      String userId;
    
      Map<String?, String?>? extras;
    
      Object encode() {
        return <Object?>[
          jobType,
          jobId,
          userId,
          extras,
        ];
      }
    
      static FlutterPartnerParams decode(Object result) {
        result as List<Object?>;
        return FlutterPartnerParams(
          jobType: result[0] as FlutterJobType?,
          jobId: result[1]! as String,
          userId: result[2]! as String,
          extras: (result[3] as Map<Object?, Object?>?)?.cast<String?, String?>(),
        );
      }
    }
    
    class SmartSelfieCreationParams {
      SmartSelfieCreationParams({
        this.userId,
        required this.allowNewEnroll,
        required this.allowAgentMode,
        required this.showAttribution,
        required this.showInstructions,
        required this.skipApiSubmission,
        this.extraPartnerParams,
      });
    
      String? userId;
    
      bool allowNewEnroll;
    
      bool allowAgentMode;
    
      bool showAttribution;
    
      bool showInstructions;
    
      bool skipApiSubmission;
    
      Map<String, String>? extraPartnerParams;
    
      Object encode() {
        return <Object?>[
          userId,
          allowNewEnroll,
          allowAgentMode,
          showAttribution,
          showInstructions,
          skipApiSubmission,
          extraPartnerParams,
        ];
      }
    
      static SmartSelfieCreationParams decode(Object result) {
        result as List<Object?>;
        return SmartSelfieCreationParams(
          userId: result[0] as String?,
          allowNewEnroll: result[1]! as bool,
          allowAgentMode: result[2]! as bool,
          showAttribution: result[3]! as bool,
          showInstructions: result[4]! as bool,
          skipApiSubmission: result[5]! as bool,
          extraPartnerParams:
    Error Handling

    New error handling implementation with SmileIDSdkResult needs thorough validation to ensure errors are properly propagated and handled across the SDK.

      return platformInterface.getUnsubmittedJobs();
    }
    
    Future<SmileIDSdkResult<SmartSelfieCaptureResult>> smartSelfieEnrollment({
      required SmartSelfieCreationParams creationParams,
    }) async {
      try {
        final result =
            await productsInterface.smartSelfieEnrollment(creationParams);
        return SmileIDSdkResultSuccess(result);
      } on PlatformException catch (e) {
        return SmileIDSdkResultError(e.message ?? _defaultSdkErrorMessage);
      }
    }
    
    Future<SmileIDSdkResult<SmartSelfieCaptureResult>> smartSelfieAuthentication({
      required SmartSelfieCreationParams creationParams,
    }) async {
      try {
        final result =
            await productsInterface.smartSelfieAuthentication(creationParams);
        return SmileIDSdkResultSuccess(result);
      } on PlatformException catch (e) {
        return SmileIDSdkResultError(e.message ?? _defaultSdkErrorMessage);
      }
    }
    
    Future<SmileIDSdkResult<SmartSelfieCaptureResult>>
        smartSelfieEnrollmentEnhanced({
      required SmartSelfieEnhancedCreationParams creationParams,
    }) async {
      try {
        final result =
            await productsInterface.smartSelfieEnrollmentEnhanced(creationParams);
        return SmileIDSdkResultSuccess(result);
      } on PlatformException catch (e) {
        return SmileIDSdkResultError(e.message ?? _defaultSdkErrorMessage);
      }
    }
    
    Future<SmileIDSdkResult<SmartSelfieCaptureResult>>
        smartSelfieAuthenticationEnhanced({
      required SmartSelfieEnhancedCreationParams creationParams,
    }) async {
      try {
        final result = await productsInterface
            .smartSelfieAuthenticationEnhanced(creationParams);
        return SmileIDSdkResultSuccess(result);
      } on PlatformException catch (e) {
        return SmileIDSdkResultError(e.message ?? _defaultSdkErrorMessage);
      }
    }
    
    Future<SmileIDSdkResult<DocumentCaptureResult>> documentVerification({
      required DocumentVerificationCreationParams creationParams,
    }) async {
      try {
        final result =
            await productsInterface.documentVerification(creationParams);
        return SmileIDSdkResultSuccess(result);
      } on PlatformException catch (e) {
        return SmileIDSdkResultError(e.message ?? _defaultSdkErrorMessage);
      }
    }
    
    Future<SmileIDSdkResult<DocumentCaptureResult>> documentVerificationEnhanced({
      required DocumentVerificationEnhancedCreationParams creationParams,
    }) async {
      try {
        final result =
            await productsInterface.documentVerificationEnhanced(creationParams);
        return SmileIDSdkResultSuccess(result);
      } on PlatformException catch (e) {
        return SmileIDSdkResultError(e.message ?? _defaultSdkErrorMessage);
      }
    }
    
    Future<SmileIDSdkResult<BiometricKYCCaptureResult>> biometricKYC({
      required BiometricKYCCreationParams creationParams,
    }) async {
      try {
        final result = await productsInterface.biometricKYC(creationParams);
        return SmileIDSdkResultSuccess(result);
      } on PlatformException catch (e) {
        return SmileIDSdkResultError(e.message ?? _defaultSdkErrorMessage);
      }
    }
    
    Future<SmileIDSdkResult<SmartSelfieCaptureResult>> selfieCapture({
      required SelfieCaptureViewCreationParams creationParams,
    }) async {
      try {
        final result = await productsInterface.selfieCapture(creationParams);
        return SmileIDSdkResultSuccess(result);
      } on PlatformException catch (e) {
        return SmileIDSdkResultError(e.message ?? _defaultSdkErrorMessage);
      }
    }
    
    Future<SmileIDSdkResult<DocumentCaptureResult>> documentCapture({
      required DocumentCaptureCreationParams creationParams,
    }) async {
      try {
        final result = await productsInterface.documentCapture(creationParams);
        return SmileIDSdkResultSuccess(result);
      } on PlatformException catch (e) {
        return SmileIDSdkResultError(e.message ?? _defaultSdkErrorMessage);
      }
    
    Platform Integration

    Complex platform-specific implementation that handles activity results and callbacks. Need to verify proper lifecycle management and memory leaks.

        ActivityResultListener,
        SmileIDProductsApi {
        private var activity: Activity? = null
        private var smartSelfieResult: ((Result<SmartSelfieCaptureResult>) -> Unit)? = null
        private var documentCaptureResult: ((Result<DocumentCaptureResult>) -> Unit)? = null
        private var biometricKycResult: ((Result<BiometricKYCCaptureResult>) -> Unit)? = null
    
        fun onAttachActivity(activity: Activity?) {
            this.activity = activity
        }
    
        fun onAttachedToEngine(binding: FlutterPluginBinding) {
            SmileIDProductsApi.setUp(binding.binaryMessenger, this)
        }
    
        fun onDetachedFromEngine(binding: FlutterPluginBinding) {
            SmileIDProductsApi.setUp(binding.binaryMessenger, null)
        }
    
        override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?): Boolean {
            when (requestCode) {
                SmileIDSmartSelfieEnrollmentActivity.REQUEST_CODE -> {
                    smartSelfieResult?.let { resultCallback ->
                        handleSelfieResult(
                            resultCode,
                            data,
                            SmileIDSmartSelfieEnrollmentActivity.REQUEST_CODE.toString(),
                            resultCallback,
                        )
    
                        smartSelfieResult = null
                        return true
                    }
    
                    return false
                }
    
                SmileIDSmartSelfieAuthenticationActivity.REQUEST_CODE -> {
                    smartSelfieResult?.let { resultCallback ->
                        handleSelfieResult(
                            resultCode,
                            data,
                            SmileIDSmartSelfieAuthenticationActivity.REQUEST_CODE.toString(),
                            resultCallback,
                        )
    
                        smartSelfieResult = null
                        return true
                    }
    
                    return false
                }
    
                SmileIDSmartSelfieEnrollmentEnhancedActivity.REQUEST_CODE -> {
                    smartSelfieResult?.let { resultCallback ->
                        handleSelfieResult(
                            resultCode,
                            data,
                            SmileIDSmartSelfieEnrollmentEnhancedActivity.REQUEST_CODE.toString(),
                            resultCallback,
                        )
    
                        smartSelfieResult = null
                        return true
                    }
    
                    return false
                }
    
                SmileIDSmartSelfieAuthenticationEnhancedActivity.REQUEST_CODE -> {
                    smartSelfieResult?.let { resultCallback ->
                        handleSelfieResult(
                            resultCode,
                            data,
                            SmileIDSmartSelfieAuthenticationEnhancedActivity.REQUEST_CODE.toString(),
                            resultCallback,
                        )
    
                        smartSelfieResult = null
                        return true
                    }
    
                    return false
                }
    
    //            SmileIDSelfieCaptureActivity.REQUEST_CODE -> {
    //                smartSelfieResult?.let { resultCallback ->
    //                    handleSelfieResult(
    //                        resultCode,
    //                        data,
    //                        SmileIDSelfieCaptureActivity.REQUEST_CODE.toString(),
    //                        resultCallback,
    //                    )
    //
    //                    smartSelfieResult = null
    //                    return true
    //                }
    //
    //                return false
    //            }
    
                SmileIDDocumentVerificationActivity.REQUEST_CODE -> {
                    documentCaptureResult?.let { resultCallback ->
                        handleDocumentResult(
                            resultCode,
                            data,
                            SmileIDDocumentVerificationActivity.REQUEST_CODE.toString(),
                            resultCallback,
                        )
    
                        documentCaptureResult = null
                        return true
                    }
    
                    return false
                }
    
                SmileIDEnhancedDocumentVerificationActivity.REQUEST_CODE -> {
                    documentCaptureResult?.let { resultCallback ->
                        handleDocumentResult(
                            resultCode,
                            data,
                            SmileIDEnhancedDocumentVerificationActivity.REQUEST_CODE.toString(),
                            resultCallback,
                        )
    
                        documentCaptureResult = null
                        return true
                    }
    
                    return false
                }
    
    //            SmileIDDocumentCaptureActivity.REQUEST_CODE -> {
    //                documentCaptureResult?.let { resultCallback ->
    //                    handleDocumentResult(
    //                        resultCode,
    //                        data,
    //                        SmileIDDocumentCaptureActivity.REQUEST_CODE.toString(),
    //                        resultCallback,
    //                    )
    //
    //                    documentCaptureResult = null
    //                    return true
    //                }
    //
    //                return false
    //            }
    
                SmileIDBiometricKYCActivity.REQUEST_CODE -> {
                    biometricKycResult?.let { resultCallback ->
                        val errorCode = SmileIDBiometricKYCActivity.REQUEST_CODE.toString()
                        when (resultCode) {
                            Activity.RESULT_OK -> {
                                val result =
                                    BiometricKYCCaptureResult(
                                        selfieFile = data?.getStringExtra("selfieFile") ?: "",
                                        livenessFiles =
                                        data?.getStringArrayListExtra("livenessFiles")
                                            ?: emptyList(),
                                        didSubmitBiometricKycJob =
                                        data?.getBooleanExtra(
                                            "didSubmitBiometricKycJob",
                                            false,
                                        ),
                                    )
    
                                resultCallback.invoke(Result.success(result))
                            }
    
                            Activity.RESULT_CANCELED -> {
                                val error = data?.getStringExtra("error") ?: "Unknown error"
                                resultCallback.invoke(
                                    Result.failure(
                                        SmileFlutterError(
                                            errorCode,
                                            message = error,
                                        ),
                                    ),
                                )
                            }
    
                            else -> {
                                resultCallback(
                                    Result.failure(
                                        SmileFlutterError(
                                            errorCode,
                                            message = "User cancelled operation",
                                        ),
                                    ),
                                )
                            }
                        }
    
                        biometricKycResult = null
                        return true
                    }
    
                    return false
                }
    
                else -> {
                    return false
                }
            }
        }
    
        override fun documentVerification(
            creationParams: DocumentVerificationCreationParams,
            callback: (Result<DocumentCaptureResult>) -> Unit,
        ) {
            val intent = Intent(activity, SmileIDDocumentVerificationActivity::class.java)
            intent.putExtra("countryCode", creationParams.countryCode)
            intent.putExtra("documentType", creationParams.documentType)
            intent.putExtra("idAspectRatio", creationParams.idAspectRatio)
            intent.putExtra("captureBothSides", creationParams.captureBothSides)
            intent.putExtra("bypassSelfieCaptureWithFile", creationParams.bypassSelfieCaptureWithFile)
            intent.putExtra("userId", creationParams.userId)
            intent.putExtra("jobId", creationParams.jobId)
            intent.putExtra("allowNewEnroll", creationParams.allowNewEnroll)
            intent.putExtra("showAttribution", creationParams.showAttribution)
            intent.putExtra("allowAgentMode", creationParams.allowAgentMode)
            intent.putExtra("allowGalleryUpload", creationParams.allowGalleryUpload)
            intent.putExtra("showInstructions", creationParams.showInstructions)
            intent.putExtra("skipApiSubmission", creationParams.skipApiSubmission)
            intent.putExtra(
                "extraPartnerParams",
                Bundle().apply {
                    creationParams.extraPartnerParams?.forEach { (key, value) ->
                        putString(key, value)
                    }
                },
            )
    
            if (activity != null) {
                documentCaptureResult = callback
                activity!!.startActivityForResult(
                    intent,
                    SmileIDDocumentVerificationActivity.REQUEST_CODE,
                )
            } else {
                callback(
                    Result.failure(
                        SmileFlutterError(
                            SmileIDDocumentVerificationActivity.REQUEST_CODE.toString(),
                            "Failed to start document verification",
                        ),
                    ),
                )
            }
        }
    
        override fun documentVerificationEnhanced(
            creationParams: DocumentVerificationEnhancedCreationParams,
            callback: (Result<DocumentCaptureResult>) -> Unit,
        ) {
            val intent = Intent(activity, SmileIDEnhancedDocumentVerificationActivity::class.java)
            intent.putExtra("countryCode", creationParams.countryCode)
            intent.putExtra("documentType", creationParams.documentType)
            intent.putExtra("idAspectRatio", creationParams.idAspectRatio)
            intent.putExtra("captureBothSides", creationParams.captureBothSides)
            intent.putExtra("bypassSelfieCaptureWithFile", creationParams.bypassSelfieCaptureWithFile)
            intent.putExtra("userId", creationParams.userId)
            intent.putExtra("jobId", creationParams.jobId)
            intent.putExtra("allowNewEnroll", creationParams.allowNewEnroll)
            intent.putExtra("showAttribution", creationParams.showAttribution)
            intent.putExtra("allowAgentMode", creationParams.allowAgentMode)
            intent.putExtra("allowGalleryUpload", creationParams.allowGalleryUpload)
            intent.putExtra("showInstructions", creationParams.showInstructions)
            intent.putExtra("skipApiSubmission", creationParams.skipApiSubmission)
            intent.putExtra(
                "extraPartnerParams",
                Bundle().apply {
                    creationParams.extraPartnerParams?.forEach { (key, value) ->
                        putString(key, value)
                    }
                },
            )
    
            if (activity != null) {
                documentCaptureResult = callback
                activity!!.startActivityForResult(
                    intent,
                    SmileIDEnhancedDocumentVerificationActivity.REQUEST_CODE,
                )
            } else {
                callback(
                    Result.failure(
                        SmileFlutterError(
                            SmileIDEnhancedDocumentVerificationActivity.REQUEST_CODE.toString(),
                            "Failed to start enhanced document verification",
                        ),
                    ),
                )
            }
        }
    
        override fun smartSelfieEnrollment(
            creationParams: SmartSelfieCreationParams,
            callback: (Result<SmartSelfieCaptureResult>) -> Unit,
        ) {
            val intent = Intent(activity, SmileIDSmartSelfieEnrollmentActivity::class.java)
            intent.putSmartSelfieCreationParams(creationParams)
    
            if (activity != null) {
                smartSelfieResult = callback
                activity!!.startActivityForResult(
                    intent,
                    SmileIDSmartSelfieEnrollmentActivity.REQUEST_CODE,
                )
            } else {
                callback(
                    Result.failure(
                        SmileFlutterError(
                            SmileIDSmartSelfieEnrollmentActivity.REQUEST_CODE.toString(),
                            "Failed to start smart selfie enrollment",
                        ),
                    ),
                )
            }
        }
    
        override fun smartSelfieAuthentication(
            creationParams: SmartSelfieCreationParams,
            callback: (Result<SmartSelfieCaptureResult>) -> Unit,
        ) {
            val intent = Intent(activity, SmileIDSmartSelfieAuthenticationActivity::class.java)
            intent.putSmartSelfieCreationParams(creationParams)
    
            if (activity != null) {
                smartSelfieResult = callback
                activity!!.startActivityForResult(
                    intent,
                    SmileIDSmartSelfieAuthenticationActivity.REQUEST_CODE,
                )
            } else {
                callback(
                    Result.failure(
                        SmileFlutterError(
                            SmileIDSmartSelfieAuthenticationActivity.REQUEST_CODE.toString(),
                            "Failed to start smart selfie authentication",
                        ),
                    ),
                )
            }
        }
    
        override fun smartSelfieEnrollmentEnhanced(
            creationParams: SmartSelfieEnhancedCreationParams,
            callback: (Result<SmartSelfieCaptureResult>) -> Unit,
        ) {
            val intent = Intent(activity, SmileIDSmartSelfieEnrollmentEnhancedActivity::class.java)
            intent.putSmartSelfieEnhancedCreationParams(creationParams)
    
            if (activity != null) {
                smartSelfieResult = callback
                activity!!.startActivityForResult(
                    intent,
                    SmileIDSmartSelfieEnrollmentEnhancedActivity.REQUEST_CODE,
                )
            } else {
                callback(
                    Result.failure(
                        SmileFlutterError(
                            SmileIDSmartSelfieEnrollmentEnhancedActivity.REQUEST_CODE.toString(),
                            "Failed to start smart selfie enrollment enhanced",
                        ),
                    ),
                )
            }
        }
    
        override fun smartSelfieAuthenticationEnhanced(
            creationParams: SmartSelfieEnhancedCreationParams,
            callback: (Result<SmartSelfieCaptureResult>) -> Unit,
        ) {
            val intent = Intent(activity, SmileIDSmartSelfieAuthenticationEnhancedActivity::class.java)
            intent.putSmartSelfieEnhancedCreationParams(creationParams)
    
            if (activity != null) {
                smartSelfieResult = callback
                activity?.startActivityForResult(
                    intent,
                    SmileIDSmartSelfieAuthenticationEnhancedActivity.REQUEST_CODE,
                )
            } else {
                callback(
                    Result.failure(
                        SmileFlutterError(
                            SmileIDSmartSelfieAuthenticationEnhancedActivity.REQUEST_CODE.toString(),
                            "Failed to start smart selfie authentication enhanced",
                        ),
                    ),
                )
            }
        }
    
        override fun biometricKYC(
            creationParams: BiometricKYCCreationParams,
            callback: (Result<BiometricKYCCaptureResult>) -> Unit,
        ) {
            val intent = Intent(activity, SmileIDBiometricKYCActivity::class.java)
            intent.putExtra("country", creationParams.country)
            intent.putExtra("idType", creationParams.idType)
            intent.putExtra("idNumber", creationParams.idNumber)
            intent.putExtra("firstName", creationParams.firstName)
            intent.putExtra("middleName", creationParams.middleName)
            intent.putExtra("lastName", creationParams.lastName)
            intent.putExtra("dob", creationParams.dob)
            intent.putExtra("bankCode", creationParams.bankCode)
            intent.putExtra("entered", creationParams.entered)
            intent.putExtra("userId", creationParams.userId)
            intent.putExtra("jobId", creationParams.jobId)
            intent.putExtra("allowNewEnroll", creationParams.allowNewEnroll)
            intent.putExtra("allowAgentMode", creationParams.allowAgentMode)
            intent.putExtra("showAttribution", creationParams.showAttribution)
            intent.putExtra("showInstructions", creationParams.showInstructions)
            intent.putExtra(
                "extraPartnerParams",
                Bundle().apply {
                    creationParams.extraPartnerParams?.forEach { (key, value) ->
                        putString(key, value)
                    }
                },
            )
    
            if (activity != null) {
                biometricKycResult = callback
                activity!!.startActivityForResult(intent, SmileIDBiometricKYCActivity.REQUEST_CODE)
            } else {
                callback(
                    Result.failure(
                        SmileFlutterError(
                            SmileIDBiometricKYCActivity.REQUEST_CODE.toString(),
                            "Failed to start biometric KYC",
                        ),
                    ),
                )
            }
        }
    
        override fun selfieCapture(
            creationParams: SelfieCaptureViewCreationParams,
            callback: (Result<SmartSelfieCaptureResult>) -> Unit,
        ) {
    //        val intent = Intent(activity, SmileIDSelfieCaptureActivity::class.java)
    //        intent.putExtra("showConfirmationDialog", creationParams.showConfirmationDialog)
    //        intent.putExtra("showInstructions", creationParams.showInstructions)
    //        intent.putExtra("showAttribution", creationParams.showAttribution)
    //        intent.putExtra("allowAgentMode", creationParams.allowAgentMode)
    //
    //        if (activity != null) {
    //            smartSelfieResult = callback
    //            activity!!.startActivityForResult(intent, SmileIDSelfieCaptureActivity.REQUEST_CODE)
    //        } else {
    //            callback(
    //                Result.failure(
    //                    SmileFlutterError(
    //                        SmileIDSelfieCaptureActivity.REQUEST_CODE.toString(),
    //                        "Failed to start selfie capture",
    //                    ),
    //                ),
    //            )
    //        }
        }
    
        override fun documentCapture(
            creationParams: DocumentCaptureCreationParams,
            callback: (Result<DocumentCaptureResult>) -> Unit,
        ) {
    //        val intent = Intent(activity, SmileIDDocumentCaptureActivity::class.java)
    //        intent.putExtra("isDocumentFrontSide", creationParams.isDocumentFrontSide)
    //        intent.putExtra("showInstructions", creationParams.showInstructions)
    //        intent.putExtra("showAttribution", creationParams.showAttribution)
    //        intent.putExtra("allowGalleryUpload", creationParams.allowGalleryUpload)
    //        intent.putExtra("showConfirmationDialog", creationParams.showConfirmationDialog)
    //        intent.putExtra("idAspectRatio", creationParams.idAspectRatio)
    //
    //        if (activity != null) {
    //            documentCaptureResult = callback
    //            activity!!.startActivityForResult(intent, SmileIDDocumentCaptureActivity.REQUEST_CODE)
    //        } else {
    //            callback(
    //                Result.failure(
    //                    SmileFlutterError(
    //                        SmileIDDocumentCaptureActivity.REQUEST_CODE.toString(),
    //                        "Failed to start document capture",
    //                    ),
    //                ),
    //            )
    //        }
        }
    }
    
    private fun Intent.putSmartSelfieCreationParams(creationParams: SmartSelfieCreationParams) =
        this.apply {
            putExtra("userId", creationParams.userId)
            putExtra("allowNewEnroll", creationParams.allowNewEnroll)
            putExtra("allowAgentMode", creationParams.allowAgentMode)
            putExtra("showAttribution", creationParams.showAttribution)
            putExtra("showInstructions", creationParams.showInstructions)
            putExtra("skipApiSubmission", creationParams.skipApiSubmission)
            putExtra(
                "extraPartnerParams",
                Bundle().apply {
                    creationParams.extraPartnerParams?.forEach { (key, value) ->
                        putString(key, value)
                    }
                },
            )
        }
    
    private fun Intent.putSmartSelfieEnhancedCreationParams(
        creationParams: SmartSelfieEnhancedCreationParams,
    ) = this.apply {
        putExtra("userId", creationParams.userId)
        putExtra("allowNewEnroll", creationParams.allowNewEnroll)
        putExtra("showAttribution", creationParams.showAttribution)
        putExtra("showInstructions", creationParams.showInstructions)
        putExtra(
            "extraPartnerParams",
            Bundle().apply {
                creationParams.extraPartnerParams?.forEach { (key, value) ->
                    putString(key, value)
                }
            },
        )
    }
    
    private fun handleSelfieResult(
        resultCode: Int,
        data: Intent?,
        errorCode: String,
        resultCallback: (Result<SmartSelfieCaptureResult>) -> Unit,
    ) {
        when (resultCode) {
            Activity.RESULT_OK -> {
                val apiResponseBundle = data?.getBundleExtra("apiResponse")
                val apiResponse =
                    apiResponseBundle?.keySet()?.associateWith {
                        return@associateWith if (apiResponseBundle.getString(it) != null) {
                            apiResponseBundle.getString(it)
                        } else {
                            val newBundle = apiResponseBundle.getBundle(it)
                            newBundle?.keySet()?.associateWith { key ->
                                newBundle.getString(key)
                            }
                        }
                    } as Map<String, Any>? ?: emptyMap()
    
                val result =
                    SmartSelfieCaptureResult(
                        selfieFile = data?.getStringExtra("selfieFile") ?: "",
                        livenessFiles =
                        data?.getStringArrayListExtra("livenessFiles")
                            ?: emptyList(),
                        apiResponse = apiResponse,
                    )
                resultCallback.invoke(Result.success(result))
            }
    
            Activity.RESULT_CANCELED -> {
                val error = data?.getStringExtra("error") ?: "Unknown error"
                resultCallback.invoke(Result.failure(SmileFlutterError(errorCode, message = error)))
            }
    
            else -> {
                resultCallback.invoke(
                    Result.failure(
                        SmileFlutterError(
                            errorCode,
                            message = "User cancelled operation",
                        ),
                    ),
                )
            }
        }
    }
    
    private fun handleDocumentResult(
        resultCode: Int,
        data: Intent?,
        errorCode: String,
        resultCallback: (Result<DocumentCaptureResult>) -> Unit,
    ) {
        when (resultCode) {
            Activity.RESULT_OK -> {
                val result =
                    DocumentCaptureResult(
                        selfieFile = data?.getStringExtra("selfieFile") ?: "",
                        livenessFiles = data?.getStringArrayListExtra("livenessFiles") ?: emptyList(),
                        documentFrontFile = data?.getStringExtra("documentFrontFile") ?: "",
                        documentBackFile = data?.getStringExtra("documentBackFile") ?: "",
                        didSubmitDocumentVerificationJob =
                        if (data?.hasExtra("didSubmitDocumentVerificationJob") == true) {
                            data?.getBooleanExtra(
                                "didSubmitDocumentVerificationJob",
                                false,
                            )
                        } else {
                            null
                        },
                        didSubmitEnhancedDocVJob =
                        if (data?.hasExtra("didSubmitEnhanceDocVJob") == true
                        ) {
                            data.getBooleanExtra("didSubmitEnhanceDocVJob", false)
                        } else {
                            null
                        },
                    )
    
                resultCallback.invoke(Result.success(result))
            }
    
            Activity.RESULT_CANCELED -> {
                val error = data?.getStringExtra("error") ?: "Unknown error"
                resultCallback.invoke(Result.failure(SmileFlutterError(errorCode, message = error)))
            }
    
            else -> {
                resultCallback.invoke(
                    Result.failure(
                        SmileFlutterError(
                            errorCode,
                            message = "User cancelled operation",
                        ),
                    ),
                )
            }
        }
    }

    Comment on lines 136 to 140
    return <Object?>[
    jobType?.index,
    jobType,
    jobId,
    userId,
    extras,
    Copy link

    Choose a reason for hiding this comment

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

    Suggestion: The code directly uses jobType?.index which will cause a runtime error when the enum value is passed directly in the updated Pigeon version. Update to use jobType directly as it's done in other parts of the updated code. [possible issue, importance: 9]

    New proposed code:
     Object encode() {
       return <Object?>[
    -    jobType?.index,
    +    jobType,
         jobId,
         userId,
         extras,
       ];
     }

    Comment on lines +146 to +164
    body: SmileIDDocumentVerification(
    countryCode: 'GH',
    documentType: "DRIVERS_LICENSE",
    onResult: (result) {
    switch (result) {
    case SmileIDSdkResultSuccess<DocumentCaptureResult>(
    :final data
    ):
    final snackBar = SnackBar(
    content: Text("Success: ${data.prettyPrint}"));
    ScaffoldMessenger.of(context).showSnackBar(snackBar);
    case SmileIDSdkResultError<DocumentCaptureResult>(
    :final error
    ):
    final snackBar = SnackBar(content: Text("Error: $error"));
    ScaffoldMessenger.of(context).showSnackBar(snackBar);
    }
    Navigator.of(context).pop();
    },
    Copy link

    Choose a reason for hiding this comment

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

    Suggestion: The pattern matching in the switch statement is missing a default case. If the result is neither a success nor an error, the code will throw an exception. Add a default case to handle unexpected result types. [possible issue, importance: 7]

    Suggested change
    body: SmileIDDocumentVerification(
    countryCode: 'GH',
    documentType: "DRIVERS_LICENSE",
    onResult: (result) {
    switch (result) {
    case SmileIDSdkResultSuccess<DocumentCaptureResult>(
    :final data
    ):
    final snackBar = SnackBar(
    content: Text("Success: ${data.prettyPrint}"));
    ScaffoldMessenger.of(context).showSnackBar(snackBar);
    case SmileIDSdkResultError<DocumentCaptureResult>(
    :final error
    ):
    final snackBar = SnackBar(content: Text("Error: $error"));
    ScaffoldMessenger.of(context).showSnackBar(snackBar);
    }
    Navigator.of(context).pop();
    },
    onResult: (result) {
    switch (result) {
    case SmileIDSdkResultSuccess<DocumentCaptureResult>(
    :final data
    ):
    final snackBar = SnackBar(
    content: Text("Success: ${data.prettyPrint}"));
    ScaffoldMessenger.of(context).showSnackBar(snackBar);
    case SmileIDSdkResultError<DocumentCaptureResult>(
    :final error
    ):
    final snackBar = SnackBar(content: Text("Error: $error"));
    ScaffoldMessenger.of(context).showSnackBar(snackBar);
    default:
    final snackBar = SnackBar(content: Text("Unexpected result type"));
    ScaffoldMessenger.of(context).showSnackBar(snackBar);
    }
    Navigator.of(context).pop();
    },

    Comment on lines +118 to +133
    SmileID.api.doEnhancedKycAsync(
    FlutterEnhancedKycRequest(
    country: "GH",
    idType: "DRIVERS_LICENSE",
    idNumber: "B0000000",
    callbackUrl: "https://somedummyurl.com/demo",
    partnerParams: FlutterPartnerParams(
    jobType: FlutterJobType.enhancedKyc,
    jobId: userId,
    userId: userId,
    extras: {
    "name": "Dummy Name",
    "work": "SmileID",
    }),
    timestamp: authResponse!.timestamp,
    signature: authResponse.signature))
    Copy link

    Choose a reason for hiding this comment

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

    Suggestion: The FlutterEnhancedKycRequest is missing the consentInformation parameter which was present in the previous code. This parameter is important for compliance with data protection regulations and should be included. [possible issue, importance: 8]

    Suggested change
    SmileID.api.doEnhancedKycAsync(
    FlutterEnhancedKycRequest(
    country: "GH",
    idType: "DRIVERS_LICENSE",
    idNumber: "B0000000",
    callbackUrl: "https://somedummyurl.com/demo",
    partnerParams: FlutterPartnerParams(
    jobType: FlutterJobType.enhancedKyc,
    jobId: userId,
    userId: userId,
    extras: {
    "name": "Dummy Name",
    "work": "SmileID",
    }),
    timestamp: authResponse!.timestamp,
    signature: authResponse.signature))
    SmileID.api.doEnhancedKycAsync(
    FlutterEnhancedKycRequest(
    country: "GH",
    idType: "DRIVERS_LICENSE",
    idNumber: "B0000000",
    callbackUrl: "https://somedummyurl.com/demo",
    partnerParams: FlutterPartnerParams(
    jobType: FlutterJobType.enhancedKyc,
    jobId: userId,
    userId: userId,
    extras: {
    "name": "Dummy Name",
    "work": "SmileID",
    }),
    timestamp: authResponse!.timestamp,
    signature: authResponse.signature,
    consentInformation: FlutterConsentInformation(
    consentGrantedDate: "",
    personalDetailsConsentGranted: true,
    contactInfoConsentGranted: true,
    documentInfoConsentGranted: true)))

    Comment on lines +61 to +71
    Future<SmileIDSdkResult<SmartSelfieCaptureResult>> smartSelfieEnrollment({
    required SmartSelfieCreationParams creationParams,
    }) async {
    try {
    final result =
    await productsInterface.smartSelfieEnrollment(creationParams);
    return SmileIDSdkResultSuccess(result);
    } on PlatformException catch (e) {
    return SmileIDSdkResultError(e.message ?? _defaultSdkErrorMessage);
    }
    }
    Copy link

    Choose a reason for hiding this comment

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

    Suggestion: The smartSelfieEnrollment method and other similar methods in this class are instance methods, but they're not accessible because there's no instance of SmileID being created. These methods should be static to match the class's usage pattern. [possible issue, importance: 9]

    Suggested change
    Future<SmileIDSdkResult<SmartSelfieCaptureResult>> smartSelfieEnrollment({
    required SmartSelfieCreationParams creationParams,
    }) async {
    try {
    final result =
    await productsInterface.smartSelfieEnrollment(creationParams);
    return SmileIDSdkResultSuccess(result);
    } on PlatformException catch (e) {
    return SmileIDSdkResultError(e.message ?? _defaultSdkErrorMessage);
    }
    }
    static Future<SmileIDSdkResult<SmartSelfieCaptureResult>> smartSelfieEnrollment({
    required SmartSelfieCreationParams creationParams,
    }) async {
    try {
    final result =
    await productsInterface.smartSelfieEnrollment(creationParams);
    return SmileIDSdkResultSuccess(result);
    } on PlatformException catch (e) {
    return SmileIDSdkResultError(e.message ?? _defaultSdkErrorMessage);
    }
    }

    Comment on lines +425 to +428
    final formattedResult = jsonEncode({
    'documentFrontFile': data.documentFrontFile,
    'documentBackFile': data.documentBackFile
    });
    Copy link

    Choose a reason for hiding this comment

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

    Suggestion: The code is encoding only a subset of the available data fields from DocumentCaptureResult. If other fields like selfieFile or livenessFiles contain important information, they should be included in the formatted result. [general, importance: 5]

    Suggested change
    final formattedResult = jsonEncode({
    'documentFrontFile': data.documentFrontFile,
    'documentBackFile': data.documentBackFile
    });
    final formattedResult = jsonEncode({
    'documentFrontFile': data.documentFrontFile,
    'documentBackFile': data.documentBackFile,
    'selfieFile': data.selfieFile,
    'livenessFiles': data.livenessFiles,
    'didSubmitDocumentVerificationJob': data.didSubmitDocumentVerificationJob
    });

    Comment on lines +92 to 103
    viewType: SmileIDSmartSelfieAuthenticationEnhanced.viewType,
    layoutDirection: Directionality.of(context),
    creationParams: creationParams,
    creationParams: widget.creationParams,
    creationParamsCodec: const StandardMessageCodec(),
    onFocus: () {
    params.onFocusChanged(true);
    },
    )
    ..addOnPlatformViewCreatedListener(params.onPlatformViewCreated)
    ..addOnPlatformViewCreatedListener(_onPlatformViewCreated)
    ..create();
    },
    );
    Copy link

    Choose a reason for hiding this comment

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

    Suggestion: The platform view initialization is missing the registration of the API with the platform view. Add a listener for platform view creation to register the API with the newly created view. [possible issue, importance: 8]

    Suggested change
    viewType: SmileIDSmartSelfieAuthenticationEnhanced.viewType,
    layoutDirection: Directionality.of(context),
    creationParams: creationParams,
    creationParams: widget.creationParams,
    creationParamsCodec: const StandardMessageCodec(),
    onFocus: () {
    params.onFocusChanged(true);
    },
    )
    ..addOnPlatformViewCreatedListener(params.onPlatformViewCreated)
    ..addOnPlatformViewCreatedListener(_onPlatformViewCreated)
    ..create();
    },
    );
    return PlatformViewsService.initExpensiveAndroidView(
    id: params.id,
    viewType: SmileIDSmartSelfieAuthenticationEnhanced.viewType,
    layoutDirection: Directionality.of(context),
    creationParams: widget.creationParams,
    creationParamsCodec: const StandardMessageCodec(),
    onFocus: () {
    params.onFocusChanged(true);
    },
    )
    ..addOnPlatformViewCreatedListener(params.onPlatformViewCreated)
    ..addOnPlatformViewCreatedListener((id) => api.registerViewId(id))
    ..create();

    Comment on lines 107 to 110
    return UiKitView(
    viewType: viewType,
    creationParams: creationParams,
    viewType: SmileIDSmartSelfieAuthentication.viewType,
    creationParams: widget.creationParams,
    creationParamsCodec: const StandardMessageCodec(),
    Copy link

    Choose a reason for hiding this comment

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

    Suggestion: The iOS UiKitView is missing the onPlatformViewCreated callback to register the API with the platform view. This will prevent the API from receiving callbacks from the native side. [possible issue, importance: 8]

    Suggested change
    return UiKitView(
    viewType: viewType,
    creationParams: creationParams,
    viewType: SmileIDSmartSelfieAuthentication.viewType,
    creationParams: widget.creationParams,
    creationParamsCodec: const StandardMessageCodec(),
    return UiKitView(
    viewType: SmileIDSmartSelfieAuthentication.viewType,
    creationParams: widget.creationParams,
    creationParamsCodec: const StandardMessageCodec(),
    onPlatformViewCreated: (id) => api.registerViewId(id),
    );

    Comment on lines 123 to 126
    return UiKitView(
    viewType: viewType,
    creationParams: creationParams,
    viewType: SmileIDDocumentVerification.viewType,
    creationParams: widget.creationParams,
    creationParamsCodec: const StandardMessageCodec(),
    Copy link

    Choose a reason for hiding this comment

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

    Suggestion: The iOS UiKitView implementation is missing the onPlatformViewCreated callback needed to register the API with the platform view. This will prevent communication between Flutter and native iOS code. [possible issue, importance: 8]

    Suggested change
    return UiKitView(
    viewType: viewType,
    creationParams: creationParams,
    viewType: SmileIDDocumentVerification.viewType,
    creationParams: widget.creationParams,
    creationParamsCodec: const StandardMessageCodec(),
    return UiKitView(
    viewType: SmileIDDocumentVerification.viewType,
    creationParams: widget.creationParams,
    creationParamsCodec: const StandardMessageCodec(),
    onPlatformViewCreated: (id) => api.registerViewId(id),
    );

    Comment on lines +1 to +6
    import 'result_clients_interfaces.dart';
    import 'smile_id_product_views_api.dart';
    import 'smile_id_sdk_result.dart';
    import 'smileid_messages.g.dart';

    class DocumentVerificationAdapter extends SmileIDProductViewsResultApi {
    Copy link

    Choose a reason for hiding this comment

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

    Suggestion: The adapter classes are missing a method to register the view ID with the platform channel. Without this, the platform views won't be able to communicate with the Flutter side. [possible issue, importance: 9]

    Suggested change
    import 'result_clients_interfaces.dart';
    import 'smile_id_product_views_api.dart';
    import 'smile_id_sdk_result.dart';
    import 'smileid_messages.g.dart';
    class DocumentVerificationAdapter extends SmileIDProductViewsResultApi {
    class DocumentVerificationAdapter extends SmileIDProductViewsResultApi {
    final DocumentCaptureResultClient client;
    DocumentVerificationAdapter(this.client) {
    SmileIDProductsResultApi.setUp(this);
    }
    void registerViewId(int id) {
    setupMethodChannel(SmileIDDocumentVerification.viewType, id);
    }

    @jumaallan jumaallan changed the title Rework Platform Views [WIP] 🚧 Rework Platform Views Apr 17, 2025
    Copy link
    Contributor

    github-actions bot commented May 1, 2025

    This PR is stale because it has been open 14 days with no activity. Remove stale label or comment or this will be closed in 7 days.

    @github-actions github-actions bot added the Stale label May 1, 2025
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Projects
    None yet
    Development

    Successfully merging this pull request may close these issues.

    2 participants