diff --git a/CHANGELOG.md b/CHANGELOG.md index 34d394e..dfebb46 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ +## 4.9.0 + +Adds the opt-in `showLanguageSelector` configuration option. + +When enabled, users can change the verification language from the welcome screen using the same compact, searchable selector as the web verification flow. +The selector remains hidden by default. + +Pins the iOS and Android native SDKs exactly to 4.9.0. + + ## 4.8.0 - Native SDKs 4.8.0 on both platforms. diff --git a/README.md b/README.md index 4a8e3b2..12dd5e2 100644 --- a/README.md +++ b/README.md @@ -85,7 +85,7 @@ didit_sdk_ios_pod = case $DiditSdkIosVariant else raise "Invalid $DiditSdkIosVariant '#{$DiditSdkIosVariant}'. Supported values: all, core, autodetection, nfc." end -didit_sdk_ios_podspec = 'https://raw.githubusercontent.com/didit-protocol/sdk-ios/4.8.0/DiditSDK.podspec' +didit_sdk_ios_podspec = 'https://raw.githubusercontent.com/didit-protocol/sdk-ios/4.9.0/DiditSDK.podspec' target 'Runner' do use_frameworks! @@ -286,6 +286,7 @@ final result = await DiditSdk.startVerification( 'your-session-token', config: DiditConfig( languageCode: 'he', // Force Hebrew language + showLanguageSelector: true, // Let the user change language fontFamily: 'Avenir', // Custom font loggingEnabled: true, // Debug logging ), @@ -297,6 +298,7 @@ final result = await DiditSdk.startVerification( | Option | Type | Default | Description | |--------|------|---------|-------------| | `languageCode` | `String?` | Device locale | ISO 639-1 language code (e.g. `"en"`, `"fr"`, `"ar"`) | +| `showLanguageSelector` | `bool` | `false` | Show the web-style language selector on the welcome screen | | `fontFamily` | `String?` | System font | Custom font family name | | `loggingEnabled` | `bool` | `false` | Enable SDK debug logging | | `showCloseButton` | `bool` | `true` | Show the close (X) button on verification step screens | @@ -321,6 +323,17 @@ await DiditSdk.startVerification(token, config: DiditConfig(languageCode: 'he')) await DiditSdk.startVerification(token); ``` +### `showLanguageSelector` + +Set this to `true` to let users change the verification language from the welcome screen. The selector is hidden by default. + +```dart +await DiditSdk.startVerification( + token, + config: const DiditConfig(showLanguageSelector: true), +); +``` + ### `fontFamily` Overrides the font used throughout the SDK UI. The font must be registered in your app's native configuration: diff --git a/android/build.gradle.kts b/android/build.gradle.kts index 4afe297..f2eb4ee 100644 --- a/android/build.gradle.kts +++ b/android/build.gradle.kts @@ -1,7 +1,7 @@ group = "me.didit.sdk.sdk_flutter" version = "1.0-SNAPSHOT" -val diditSdkAndroidVersion = "4.8.0" +val diditSdkAndroidVersion = "4.9.0" val diditSdkAndroidVariant = ( rootProject.findProperty("diditSdkAndroidVariant") ?: findProperty("diditSdkAndroidVariant") diff --git a/android/src/main/kotlin/me/didit/sdk/sdk_flutter/SdkFlutterPlugin.kt b/android/src/main/kotlin/me/didit/sdk/sdk_flutter/SdkFlutterPlugin.kt index 32b1fe9..e943d3d 100644 --- a/android/src/main/kotlin/me/didit/sdk/sdk_flutter/SdkFlutterPlugin.kt +++ b/android/src/main/kotlin/me/didit/sdk/sdk_flutter/SdkFlutterPlugin.kt @@ -186,6 +186,7 @@ class SdkFlutterPlugin : return Configuration( languageLocale = language, + showLanguageSelector = map["showLanguageSelector"] as? Boolean ?: false, fontFamily = map["fontFamily"] as? String, loggingEnabled = map["loggingEnabled"] as? Boolean ?: false, showCloseButton = map["showCloseButton"] as? Boolean ?: true, diff --git a/example/ios/Podfile b/example/ios/Podfile index ec29184..3c5bf2e 100644 --- a/example/ios/Podfile +++ b/example/ios/Podfile @@ -48,7 +48,7 @@ didit_sdk_ios_pod = case $DiditSdkIosVariant end didit_sdk_ios_podspec = ENV.fetch( 'DIDIT_SDK_IOS_PODSPEC', - 'https://raw.githubusercontent.com/didit-protocol/sdk-ios/4.8.0/DiditSDK.podspec' + 'https://raw.githubusercontent.com/didit-protocol/sdk-ios/4.9.0/DiditSDK.podspec' ) target 'Runner' do diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index e6e6d1c..9b00b7b 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -1,15 +1,15 @@ PODS: - - didit_sdk (4.8.0): - - DiditSDK/All (= 4.8.0) + - didit_sdk (4.9.0): + - DiditSDK/All (= 4.9.0) - Flutter - - DiditSDK/All (4.8.0) + - DiditSDK/All (4.9.0) - Flutter (1.0.0) - integration_test (0.0.1): - Flutter DEPENDENCIES: - didit_sdk (from `.symlinks/plugins/didit_sdk/ios`) - - DiditSDK/All (from `https://raw.githubusercontent.com/didit-protocol/sdk-ios/4.8.0/DiditSDK.podspec`) + - DiditSDK/All (from `https://raw.githubusercontent.com/didit-protocol/sdk-ios/4.9.0/DiditSDK.podspec`) - Flutter (from `Flutter`) - integration_test (from `.symlinks/plugins/integration_test/ios`) @@ -17,18 +17,18 @@ EXTERNAL SOURCES: didit_sdk: :path: ".symlinks/plugins/didit_sdk/ios" DiditSDK: - :podspec: https://raw.githubusercontent.com/didit-protocol/sdk-ios/4.8.0/DiditSDK.podspec + :podspec: https://raw.githubusercontent.com/didit-protocol/sdk-ios/4.9.0/DiditSDK.podspec Flutter: :path: Flutter integration_test: :path: ".symlinks/plugins/integration_test/ios" SPEC CHECKSUMS: - didit_sdk: 5b9f62df3c640e3f8a8a12b607594e4694a98ead - DiditSDK: 1f7080792951b143ab66ac7327c7fe868a68d0ec + didit_sdk: 0f0ca48a71ae905c2de71b02d24475e05db52cf9 + DiditSDK: 18cfba785d456e42e3f6cc70f4c69da112fad0f7 Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467 integration_test: 4a889634ef21a45d28d50d622cf412dc6d9f586e -PODFILE CHECKSUM: 0b5e0608cb5879362a01eb8afc4c36bfbe81c08e +PODFILE CHECKSUM: dcce6b2a7fd6d6fac6c43415d61be3170315620f COCOAPODS: 1.16.2 diff --git a/example/pubspec.lock b/example/pubspec.lock index 4f81d84..4142d47 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -55,7 +55,7 @@ packages: path: ".." relative: true source: path - version: "4.8.0" + version: "4.9.0" fake_async: dependency: transitive description: diff --git a/ios/didit_sdk.podspec b/ios/didit_sdk.podspec index 8884cfd..7331c92 100644 --- a/ios/didit_sdk.podspec +++ b/ios/didit_sdk.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'didit_sdk' - s.version = '4.8.0' + s.version = '4.9.0' s.summary = 'Didit Identity Verification SDK for Flutter' s.description = <<-DESC Flutter plugin wrapping the native DiditSDK for identity verification @@ -31,7 +31,7 @@ with document scanning, NFC passport reading, and liveness detection. else raise "Invalid DiditSdk iOS variant '#{didit_sdk_ios_variant}'. Set $DiditSdkIosVariant in your Podfile to one of: all, core, autodetection, nfc." end - s.dependency didit_sdk_ios_pod, '4.8.0' + s.dependency didit_sdk_ios_pod, '4.9.0' s.platform = :ios, '13.0' s.static_framework = true diff --git a/ios/didit_sdk/Package.swift b/ios/didit_sdk/Package.swift index d760510..ebf4f93 100644 --- a/ios/didit_sdk/Package.swift +++ b/ios/didit_sdk/Package.swift @@ -15,7 +15,7 @@ let package = Package( .library(name: "didit-sdk", targets: ["didit_sdk"]) ], dependencies: [ - .package(url: "https://github.com/didit-protocol/sdk-ios.git", exact: "4.8.0") + .package(url: "https://github.com/didit-protocol/sdk-ios.git", exact: "4.9.0") ], targets: [ .target( diff --git a/ios/didit_sdk/Sources/didit_sdk/SdkFlutterPlugin.swift b/ios/didit_sdk/Sources/didit_sdk/SdkFlutterPlugin.swift index d051cde..dca6a66 100644 --- a/ios/didit_sdk/Sources/didit_sdk/SdkFlutterPlugin.swift +++ b/ios/didit_sdk/Sources/didit_sdk/SdkFlutterPlugin.swift @@ -206,7 +206,8 @@ public class SdkFlutterPlugin: NSObject, FlutterPlugin { defaultDocumentCamera: defaultDocumentCamera, defaultLivenessCamera: defaultLivenessCamera, showDocumentCameraSwitchButton: dict["showDocumentCameraSwitchButton"] as? Bool ?? true, - showLivenessCameraSwitchButton: dict["showLivenessCameraSwitchButton"] as? Bool ?? true + showLivenessCameraSwitchButton: dict["showLivenessCameraSwitchButton"] as? Bool ?? true, + showLanguageSelector: dict["showLanguageSelector"] as? Bool ?? false ) } diff --git a/lib/sdk_flutter.dart b/lib/sdk_flutter.dart index 00cf5dc..9c83490 100644 --- a/lib/sdk_flutter.dart +++ b/lib/sdk_flutter.dart @@ -80,7 +80,7 @@ class DiditSdk { static int _transactionCallCounter = 0; static bool _transactionUpdateHandlerRegistered = false; static final Map - _pendingTransactionUpdates = {}; + _pendingTransactionUpdates = {}; static void _ensureTransactionUpdateHandler() { if (_transactionUpdateHandlerRegistered) return; @@ -140,15 +140,12 @@ class DiditSdk { _pendingTransactionUpdates[callId] = onTransactionUpdated; } try { - final raw = await SdkFlutterPlatform.instance.submitTransaction( - transactionToken, - transaction.toMap(), - { - 'callId': callId, - 'autoLaunchAction': options.autoLaunchAction, - if (options.baseUrl != null) 'baseUrl': options.baseUrl, - }, - ); + final raw = await SdkFlutterPlatform.instance + .submitTransaction(transactionToken, transaction.toMap(), { + 'callId': callId, + 'autoLaunchAction': options.autoLaunchAction, + if (options.baseUrl != null) 'baseUrl': options.baseUrl, + }); final result = DiditTransactionResult.fromMap(raw); if (result.actionRequired == null) { _pendingTransactionUpdates.remove(callId); diff --git a/lib/sdk_flutter_method_channel.dart b/lib/sdk_flutter_method_channel.dart index f65c25a..03c6c2c 100644 --- a/lib/sdk_flutter_method_channel.dart +++ b/lib/sdk_flutter_method_channel.dart @@ -9,7 +9,7 @@ class MethodChannelSdkFlutter extends SdkFlutterPlatform { final methodChannel = const MethodChannel('didit_sdk'); void Function(String callId, Map result)? - _transactionUpdateHandler; + _transactionUpdateHandler; @override Future> startVerification( @@ -69,8 +69,9 @@ class MethodChannelSdkFlutter extends SdkFlutterPlatform { void Function(String callId, Map result)? handler, ) { _transactionUpdateHandler = handler; - methodChannel - .setMethodCallHandler(handler == null ? null : _handlePlatformCall); + methodChannel.setMethodCallHandler( + handler == null ? null : _handlePlatformCall, + ); } Future _handlePlatformCall(MethodCall call) async { diff --git a/lib/sdk_flutter_platform_interface.dart b/lib/sdk_flutter_platform_interface.dart index 028c0b8..b64abb7 100644 --- a/lib/sdk_flutter_platform_interface.dart +++ b/lib/sdk_flutter_platform_interface.dart @@ -31,7 +31,8 @@ abstract class SdkFlutterPlatform extends PlatformInterface { Map? config, ) { throw UnimplementedError( - 'startVerificationWithWorkflow() has not been implemented.'); + 'startVerificationWithWorkflow() has not been implemented.', + ); } /// Submit a transaction with a transaction SDK token. @@ -58,6 +59,7 @@ abstract class SdkFlutterPlatform extends PlatformInterface { void Function(String callId, Map result)? handler, ) { throw UnimplementedError( - 'setTransactionUpdateHandler() has not been implemented.'); + 'setTransactionUpdateHandler() has not been implemented.', + ); } } diff --git a/lib/src/transactions.dart b/lib/src/transactions.dart index 3dd4fcf..9a1e605 100644 --- a/lib/src/transactions.dart +++ b/lib/src/transactions.dart @@ -34,19 +34,18 @@ class DiditTransactionInfo { }); Map toMap() => { - if (direction != null) 'direction': direction, - if (amount != null) 'amount': amount, - if (currency != null) 'currency': currency, - if (currencyType != null) 'currencyType': currencyType, - if (amountInDefaultCurrency != null) - 'amountInDefaultCurrency': amountInDefaultCurrency, - if (defaultCurrencyCode != null) - 'defaultCurrencyCode': defaultCurrencyCode, - if (paymentDetails != null) 'paymentDetails': paymentDetails, - if (paymentTxnId != null) 'paymentTxnId': paymentTxnId, - if (type != null) 'type': type, - if (cryptoParams != null) 'cryptoParams': cryptoParams, - }; + if (direction != null) 'direction': direction, + if (amount != null) 'amount': amount, + if (currency != null) 'currency': currency, + if (currencyType != null) 'currencyType': currencyType, + if (amountInDefaultCurrency != null) + 'amountInDefaultCurrency': amountInDefaultCurrency, + if (defaultCurrencyCode != null) 'defaultCurrencyCode': defaultCurrencyCode, + if (paymentDetails != null) 'paymentDetails': paymentDetails, + if (paymentTxnId != null) 'paymentTxnId': paymentTxnId, + if (type != null) 'type': type, + if (cryptoParams != null) 'cryptoParams': cryptoParams, + }; } /// Payment method of a transaction participant. @@ -66,10 +65,10 @@ class DiditTransactionPaymentMethod { }); Map toMap() => { - if (type != null) 'type': type, - if (accountId != null) 'accountId': accountId, - if (issuingCountry != null) 'issuingCountry': issuingCountry, - }; + if (type != null) 'type': type, + if (accountId != null) 'accountId': accountId, + if (issuingCountry != null) 'issuingCountry': issuingCountry, + }; } /// A transaction participant (subject or counterparty). @@ -102,17 +101,17 @@ class DiditTransactionParticipant { }); Map toMap() => { - if (type != null) 'type': type, - if (externalUserId != null) 'externalUserId': externalUserId, - if (fullName != null) 'fullName': fullName, - if (firstName != null) 'firstName': firstName, - if (lastName != null) 'lastName': lastName, - if (dob != null) 'dob': dob, - if (address != null) 'address': address, - if (institutionInfo != null) 'institutionInfo': institutionInfo, - if (device != null) 'device': device, - if (paymentMethod != null) 'paymentMethod': paymentMethod!.toMap(), - }; + if (type != null) 'type': type, + if (externalUserId != null) 'externalUserId': externalUserId, + if (fullName != null) 'fullName': fullName, + if (firstName != null) 'firstName': firstName, + if (lastName != null) 'lastName': lastName, + if (dob != null) 'dob': dob, + if (address != null) 'address': address, + if (institutionInfo != null) 'institutionInfo': institutionInfo, + if (device != null) 'device': device, + if (paymentMethod != null) 'paymentMethod': paymentMethod!.toMap(), + }; } /// Travel rule information attached to a transaction. @@ -136,14 +135,14 @@ class DiditTravelRule { }); Map toMap() => { - if (status != null) 'status': status, - if (protocol != null) 'protocol': protocol, - if (required != null) 'required': required, - if (obligationsCount != null) 'obligationsCount': obligationsCount, - if (originatorData != null) 'originatorData': originatorData, - if (beneficiaryData != null) 'beneficiaryData': beneficiaryData, - if (metadata != null) 'metadata': metadata, - }; + if (status != null) 'status': status, + if (protocol != null) 'protocol': protocol, + if (required != null) 'required': required, + if (obligationsCount != null) 'obligationsCount': obligationsCount, + if (originatorData != null) 'originatorData': originatorData, + if (beneficiaryData != null) 'beneficiaryData': beneficiaryData, + if (metadata != null) 'metadata': metadata, + }; } /// A transaction to submit from the device. @@ -184,18 +183,18 @@ class DiditTransactionPayload { }); Map toMap() => { - 'txnId': txnId, - if (txnDate != null) 'txnDate': txnDate, - if (zoneId != null) 'zoneId': zoneId, - if (type != null) 'type': type, - if (info != null) 'info': info!.toMap(), - if (subject != null) 'subject': subject!.toMap(), - if (counterparty != null) 'counterparty': counterparty!.toMap(), - if (props != null) 'props': props, - if (travelRule != null) 'travelRule': travelRule!.toMap(), - if (includeCryptoScreening != null) - 'includeCryptoScreening': includeCryptoScreening, - }; + 'txnId': txnId, + if (txnDate != null) 'txnDate': txnDate, + if (zoneId != null) 'zoneId': zoneId, + if (type != null) 'type': type, + if (info != null) 'info': info!.toMap(), + if (subject != null) 'subject': subject!.toMap(), + if (counterparty != null) 'counterparty': counterparty!.toMap(), + if (props != null) 'props': props, + if (travelRule != null) 'travelRule': travelRule!.toMap(), + if (includeCryptoScreening != null) + 'includeCryptoScreening': includeCryptoScreening, + }; } /// A user action required to complete the transaction. diff --git a/lib/src/types.dart b/lib/src/types.dart index 879721b..626ec7b 100644 --- a/lib/src/types.dart +++ b/lib/src/types.dart @@ -109,9 +109,9 @@ sealed class VerificationResult { case 'failed': return VerificationFailed( error: VerificationError( - type: VerificationErrorType.fromString( - map['errorType'] as String?), - message: (map['errorMessage'] as String?) ?? + type: VerificationErrorType.fromString(map['errorType'] as String?), + message: + (map['errorMessage'] as String?) ?? 'An unknown error occurred during verification.', ), session: session, @@ -159,9 +159,9 @@ enum CameraLens { back; String toMap() => switch (this) { - CameraLens.front => 'front', - CameraLens.back => 'back', - }; + CameraLens.front => 'front', + CameraLens.back => 'back', + }; } /// Configuration options for the Didit verification SDK. @@ -174,6 +174,10 @@ class DiditConfig { /// ISO 639-1 language code for the SDK UI (e.g. "en", "he", "ar"). final String? languageCode; + /// Show the language selector on the verification welcome screen. + /// Default is `false`. + final bool showLanguageSelector; + /// Custom font family name to use throughout the SDK UI. final String? fontFamily; @@ -217,6 +221,7 @@ class DiditConfig { const DiditConfig({ this.languageCode, + this.showLanguageSelector = false, this.fontFamily, this.loggingEnabled = false, this.showCloseButton = true, @@ -231,6 +236,7 @@ class DiditConfig { Map toMap() { final map = {}; if (languageCode != null) map['languageCode'] = languageCode; + map['showLanguageSelector'] = showLanguageSelector; if (fontFamily != null) map['fontFamily'] = fontFamily; map['loggingEnabled'] = loggingEnabled; map['showCloseButton'] = showCloseButton; @@ -247,4 +253,3 @@ class DiditConfig { return map; } } - diff --git a/packages/didit_sdk_autodetection/CHANGELOG.md b/packages/didit_sdk_autodetection/CHANGELOG.md index a90177d..094cbd9 100644 --- a/packages/didit_sdk_autodetection/CHANGELOG.md +++ b/packages/didit_sdk_autodetection/CHANGELOG.md @@ -1,3 +1,13 @@ +## 4.9.0 + +Adds the opt-in `showLanguageSelector` configuration option. + +When enabled, users can change the verification language from the welcome screen using the same compact, searchable selector as the web verification flow. +The selector remains hidden by default. + +Pins the iOS and Android native SDKs exactly to 4.9.0. + + ## 4.8.0 - Native SDKs 4.8.0 on both platforms. diff --git a/packages/didit_sdk_autodetection/README.md b/packages/didit_sdk_autodetection/README.md index f74fe20..0c0ec74 100644 --- a/packages/didit_sdk_autodetection/README.md +++ b/packages/didit_sdk_autodetection/README.md @@ -13,7 +13,7 @@ Depend on exactly one of the `didit_sdk` packages: ```yaml dependencies: - didit_sdk_autodetection: ^4.8.0 + didit_sdk_autodetection: ^4.9.0 ``` ```dart diff --git a/packages/didit_sdk_autodetection/android/build.gradle.kts b/packages/didit_sdk_autodetection/android/build.gradle.kts index f2b8ea2..a4e118b 100644 --- a/packages/didit_sdk_autodetection/android/build.gradle.kts +++ b/packages/didit_sdk_autodetection/android/build.gradle.kts @@ -1,7 +1,7 @@ group = "me.didit.sdk.sdk_flutter" version = "1.0-SNAPSHOT" -val diditSdkAndroidVersion = "4.8.0" +val diditSdkAndroidVersion = "4.9.0" val diditSdkAndroidVariant = ( rootProject.findProperty("diditSdkAndroidVariant") ?: findProperty("diditSdkAndroidVariant") diff --git a/packages/didit_sdk_autodetection/android/src/main/kotlin/me/didit/sdk/sdk_flutter/SdkFlutterPlugin.kt b/packages/didit_sdk_autodetection/android/src/main/kotlin/me/didit/sdk/sdk_flutter/SdkFlutterPlugin.kt index 32b1fe9..e943d3d 100644 --- a/packages/didit_sdk_autodetection/android/src/main/kotlin/me/didit/sdk/sdk_flutter/SdkFlutterPlugin.kt +++ b/packages/didit_sdk_autodetection/android/src/main/kotlin/me/didit/sdk/sdk_flutter/SdkFlutterPlugin.kt @@ -186,6 +186,7 @@ class SdkFlutterPlugin : return Configuration( languageLocale = language, + showLanguageSelector = map["showLanguageSelector"] as? Boolean ?: false, fontFamily = map["fontFamily"] as? String, loggingEnabled = map["loggingEnabled"] as? Boolean ?: false, showCloseButton = map["showCloseButton"] as? Boolean ?: true, diff --git a/packages/didit_sdk_autodetection/ios/didit_sdk_autodetection.podspec b/packages/didit_sdk_autodetection/ios/didit_sdk_autodetection.podspec index 4c285af..16662b3 100644 --- a/packages/didit_sdk_autodetection/ios/didit_sdk_autodetection.podspec +++ b/packages/didit_sdk_autodetection/ios/didit_sdk_autodetection.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'didit_sdk_autodetection' - s.version = '4.8.0' + s.version = '4.9.0' s.summary = 'Didit Identity Verification SDK for Flutter - autodetection variant' s.description = <<-DESC Didit identity verification Flutter plugin pinned to the DiditSDK/AutoDetection native SDK @@ -17,7 +17,7 @@ variant (automatic capture without NFC). Generated from didit_sdk. # Fixed native variant - unlike didit_sdk this podspec intentionally ignores # $DiditSdkIosVariant. Keep your Podfile's DiditSDK subspec line in sync # (DiditSDK/AutoDetection) when building with CocoaPods. - s.dependency 'DiditSDK/AutoDetection', '4.8.0' + s.dependency 'DiditSDK/AutoDetection', '4.9.0' s.platform = :ios, '13.0' s.static_framework = true diff --git a/packages/didit_sdk_autodetection/ios/didit_sdk_autodetection/Package.swift b/packages/didit_sdk_autodetection/ios/didit_sdk_autodetection/Package.swift index 79768ab..7cacffb 100644 --- a/packages/didit_sdk_autodetection/ios/didit_sdk_autodetection/Package.swift +++ b/packages/didit_sdk_autodetection/ios/didit_sdk_autodetection/Package.swift @@ -11,7 +11,7 @@ let package = Package( .library(name: "didit-sdk-autodetection", targets: ["didit_sdk_autodetection"]) ], dependencies: [ - .package(url: "https://github.com/didit-protocol/sdk-ios.git", exact: "4.8.0") + .package(url: "https://github.com/didit-protocol/sdk-ios.git", exact: "4.9.0") ], targets: [ .target( diff --git a/packages/didit_sdk_autodetection/ios/didit_sdk_autodetection/Sources/didit_sdk_autodetection/SdkFlutterPlugin.swift b/packages/didit_sdk_autodetection/ios/didit_sdk_autodetection/Sources/didit_sdk_autodetection/SdkFlutterPlugin.swift index d051cde..dca6a66 100644 --- a/packages/didit_sdk_autodetection/ios/didit_sdk_autodetection/Sources/didit_sdk_autodetection/SdkFlutterPlugin.swift +++ b/packages/didit_sdk_autodetection/ios/didit_sdk_autodetection/Sources/didit_sdk_autodetection/SdkFlutterPlugin.swift @@ -206,7 +206,8 @@ public class SdkFlutterPlugin: NSObject, FlutterPlugin { defaultDocumentCamera: defaultDocumentCamera, defaultLivenessCamera: defaultLivenessCamera, showDocumentCameraSwitchButton: dict["showDocumentCameraSwitchButton"] as? Bool ?? true, - showLivenessCameraSwitchButton: dict["showLivenessCameraSwitchButton"] as? Bool ?? true + showLivenessCameraSwitchButton: dict["showLivenessCameraSwitchButton"] as? Bool ?? true, + showLanguageSelector: dict["showLanguageSelector"] as? Bool ?? false ) } diff --git a/packages/didit_sdk_autodetection/lib/sdk_flutter.dart b/packages/didit_sdk_autodetection/lib/sdk_flutter.dart index 00cf5dc..9c83490 100644 --- a/packages/didit_sdk_autodetection/lib/sdk_flutter.dart +++ b/packages/didit_sdk_autodetection/lib/sdk_flutter.dart @@ -80,7 +80,7 @@ class DiditSdk { static int _transactionCallCounter = 0; static bool _transactionUpdateHandlerRegistered = false; static final Map - _pendingTransactionUpdates = {}; + _pendingTransactionUpdates = {}; static void _ensureTransactionUpdateHandler() { if (_transactionUpdateHandlerRegistered) return; @@ -140,15 +140,12 @@ class DiditSdk { _pendingTransactionUpdates[callId] = onTransactionUpdated; } try { - final raw = await SdkFlutterPlatform.instance.submitTransaction( - transactionToken, - transaction.toMap(), - { - 'callId': callId, - 'autoLaunchAction': options.autoLaunchAction, - if (options.baseUrl != null) 'baseUrl': options.baseUrl, - }, - ); + final raw = await SdkFlutterPlatform.instance + .submitTransaction(transactionToken, transaction.toMap(), { + 'callId': callId, + 'autoLaunchAction': options.autoLaunchAction, + if (options.baseUrl != null) 'baseUrl': options.baseUrl, + }); final result = DiditTransactionResult.fromMap(raw); if (result.actionRequired == null) { _pendingTransactionUpdates.remove(callId); diff --git a/packages/didit_sdk_autodetection/lib/sdk_flutter_method_channel.dart b/packages/didit_sdk_autodetection/lib/sdk_flutter_method_channel.dart index f65c25a..03c6c2c 100644 --- a/packages/didit_sdk_autodetection/lib/sdk_flutter_method_channel.dart +++ b/packages/didit_sdk_autodetection/lib/sdk_flutter_method_channel.dart @@ -9,7 +9,7 @@ class MethodChannelSdkFlutter extends SdkFlutterPlatform { final methodChannel = const MethodChannel('didit_sdk'); void Function(String callId, Map result)? - _transactionUpdateHandler; + _transactionUpdateHandler; @override Future> startVerification( @@ -69,8 +69,9 @@ class MethodChannelSdkFlutter extends SdkFlutterPlatform { void Function(String callId, Map result)? handler, ) { _transactionUpdateHandler = handler; - methodChannel - .setMethodCallHandler(handler == null ? null : _handlePlatformCall); + methodChannel.setMethodCallHandler( + handler == null ? null : _handlePlatformCall, + ); } Future _handlePlatformCall(MethodCall call) async { diff --git a/packages/didit_sdk_autodetection/lib/sdk_flutter_platform_interface.dart b/packages/didit_sdk_autodetection/lib/sdk_flutter_platform_interface.dart index 028c0b8..b64abb7 100644 --- a/packages/didit_sdk_autodetection/lib/sdk_flutter_platform_interface.dart +++ b/packages/didit_sdk_autodetection/lib/sdk_flutter_platform_interface.dart @@ -31,7 +31,8 @@ abstract class SdkFlutterPlatform extends PlatformInterface { Map? config, ) { throw UnimplementedError( - 'startVerificationWithWorkflow() has not been implemented.'); + 'startVerificationWithWorkflow() has not been implemented.', + ); } /// Submit a transaction with a transaction SDK token. @@ -58,6 +59,7 @@ abstract class SdkFlutterPlatform extends PlatformInterface { void Function(String callId, Map result)? handler, ) { throw UnimplementedError( - 'setTransactionUpdateHandler() has not been implemented.'); + 'setTransactionUpdateHandler() has not been implemented.', + ); } } diff --git a/packages/didit_sdk_autodetection/lib/src/transactions.dart b/packages/didit_sdk_autodetection/lib/src/transactions.dart index 3dd4fcf..9a1e605 100644 --- a/packages/didit_sdk_autodetection/lib/src/transactions.dart +++ b/packages/didit_sdk_autodetection/lib/src/transactions.dart @@ -34,19 +34,18 @@ class DiditTransactionInfo { }); Map toMap() => { - if (direction != null) 'direction': direction, - if (amount != null) 'amount': amount, - if (currency != null) 'currency': currency, - if (currencyType != null) 'currencyType': currencyType, - if (amountInDefaultCurrency != null) - 'amountInDefaultCurrency': amountInDefaultCurrency, - if (defaultCurrencyCode != null) - 'defaultCurrencyCode': defaultCurrencyCode, - if (paymentDetails != null) 'paymentDetails': paymentDetails, - if (paymentTxnId != null) 'paymentTxnId': paymentTxnId, - if (type != null) 'type': type, - if (cryptoParams != null) 'cryptoParams': cryptoParams, - }; + if (direction != null) 'direction': direction, + if (amount != null) 'amount': amount, + if (currency != null) 'currency': currency, + if (currencyType != null) 'currencyType': currencyType, + if (amountInDefaultCurrency != null) + 'amountInDefaultCurrency': amountInDefaultCurrency, + if (defaultCurrencyCode != null) 'defaultCurrencyCode': defaultCurrencyCode, + if (paymentDetails != null) 'paymentDetails': paymentDetails, + if (paymentTxnId != null) 'paymentTxnId': paymentTxnId, + if (type != null) 'type': type, + if (cryptoParams != null) 'cryptoParams': cryptoParams, + }; } /// Payment method of a transaction participant. @@ -66,10 +65,10 @@ class DiditTransactionPaymentMethod { }); Map toMap() => { - if (type != null) 'type': type, - if (accountId != null) 'accountId': accountId, - if (issuingCountry != null) 'issuingCountry': issuingCountry, - }; + if (type != null) 'type': type, + if (accountId != null) 'accountId': accountId, + if (issuingCountry != null) 'issuingCountry': issuingCountry, + }; } /// A transaction participant (subject or counterparty). @@ -102,17 +101,17 @@ class DiditTransactionParticipant { }); Map toMap() => { - if (type != null) 'type': type, - if (externalUserId != null) 'externalUserId': externalUserId, - if (fullName != null) 'fullName': fullName, - if (firstName != null) 'firstName': firstName, - if (lastName != null) 'lastName': lastName, - if (dob != null) 'dob': dob, - if (address != null) 'address': address, - if (institutionInfo != null) 'institutionInfo': institutionInfo, - if (device != null) 'device': device, - if (paymentMethod != null) 'paymentMethod': paymentMethod!.toMap(), - }; + if (type != null) 'type': type, + if (externalUserId != null) 'externalUserId': externalUserId, + if (fullName != null) 'fullName': fullName, + if (firstName != null) 'firstName': firstName, + if (lastName != null) 'lastName': lastName, + if (dob != null) 'dob': dob, + if (address != null) 'address': address, + if (institutionInfo != null) 'institutionInfo': institutionInfo, + if (device != null) 'device': device, + if (paymentMethod != null) 'paymentMethod': paymentMethod!.toMap(), + }; } /// Travel rule information attached to a transaction. @@ -136,14 +135,14 @@ class DiditTravelRule { }); Map toMap() => { - if (status != null) 'status': status, - if (protocol != null) 'protocol': protocol, - if (required != null) 'required': required, - if (obligationsCount != null) 'obligationsCount': obligationsCount, - if (originatorData != null) 'originatorData': originatorData, - if (beneficiaryData != null) 'beneficiaryData': beneficiaryData, - if (metadata != null) 'metadata': metadata, - }; + if (status != null) 'status': status, + if (protocol != null) 'protocol': protocol, + if (required != null) 'required': required, + if (obligationsCount != null) 'obligationsCount': obligationsCount, + if (originatorData != null) 'originatorData': originatorData, + if (beneficiaryData != null) 'beneficiaryData': beneficiaryData, + if (metadata != null) 'metadata': metadata, + }; } /// A transaction to submit from the device. @@ -184,18 +183,18 @@ class DiditTransactionPayload { }); Map toMap() => { - 'txnId': txnId, - if (txnDate != null) 'txnDate': txnDate, - if (zoneId != null) 'zoneId': zoneId, - if (type != null) 'type': type, - if (info != null) 'info': info!.toMap(), - if (subject != null) 'subject': subject!.toMap(), - if (counterparty != null) 'counterparty': counterparty!.toMap(), - if (props != null) 'props': props, - if (travelRule != null) 'travelRule': travelRule!.toMap(), - if (includeCryptoScreening != null) - 'includeCryptoScreening': includeCryptoScreening, - }; + 'txnId': txnId, + if (txnDate != null) 'txnDate': txnDate, + if (zoneId != null) 'zoneId': zoneId, + if (type != null) 'type': type, + if (info != null) 'info': info!.toMap(), + if (subject != null) 'subject': subject!.toMap(), + if (counterparty != null) 'counterparty': counterparty!.toMap(), + if (props != null) 'props': props, + if (travelRule != null) 'travelRule': travelRule!.toMap(), + if (includeCryptoScreening != null) + 'includeCryptoScreening': includeCryptoScreening, + }; } /// A user action required to complete the transaction. diff --git a/packages/didit_sdk_autodetection/lib/src/types.dart b/packages/didit_sdk_autodetection/lib/src/types.dart index 879721b..626ec7b 100644 --- a/packages/didit_sdk_autodetection/lib/src/types.dart +++ b/packages/didit_sdk_autodetection/lib/src/types.dart @@ -109,9 +109,9 @@ sealed class VerificationResult { case 'failed': return VerificationFailed( error: VerificationError( - type: VerificationErrorType.fromString( - map['errorType'] as String?), - message: (map['errorMessage'] as String?) ?? + type: VerificationErrorType.fromString(map['errorType'] as String?), + message: + (map['errorMessage'] as String?) ?? 'An unknown error occurred during verification.', ), session: session, @@ -159,9 +159,9 @@ enum CameraLens { back; String toMap() => switch (this) { - CameraLens.front => 'front', - CameraLens.back => 'back', - }; + CameraLens.front => 'front', + CameraLens.back => 'back', + }; } /// Configuration options for the Didit verification SDK. @@ -174,6 +174,10 @@ class DiditConfig { /// ISO 639-1 language code for the SDK UI (e.g. "en", "he", "ar"). final String? languageCode; + /// Show the language selector on the verification welcome screen. + /// Default is `false`. + final bool showLanguageSelector; + /// Custom font family name to use throughout the SDK UI. final String? fontFamily; @@ -217,6 +221,7 @@ class DiditConfig { const DiditConfig({ this.languageCode, + this.showLanguageSelector = false, this.fontFamily, this.loggingEnabled = false, this.showCloseButton = true, @@ -231,6 +236,7 @@ class DiditConfig { Map toMap() { final map = {}; if (languageCode != null) map['languageCode'] = languageCode; + map['showLanguageSelector'] = showLanguageSelector; if (fontFamily != null) map['fontFamily'] = fontFamily; map['loggingEnabled'] = loggingEnabled; map['showCloseButton'] = showCloseButton; @@ -247,4 +253,3 @@ class DiditConfig { return map; } } - diff --git a/packages/didit_sdk_autodetection/pubspec.yaml b/packages/didit_sdk_autodetection/pubspec.yaml index f2ab91c..35a0612 100644 --- a/packages/didit_sdk_autodetection/pubspec.yaml +++ b/packages/didit_sdk_autodetection/pubspec.yaml @@ -1,6 +1,6 @@ name: didit_sdk_autodetection description: Didit Identity Verification SDK for Flutter, pinned to the autodetection native SDK variant (automatic capture without NFC). Same Dart API as didit_sdk - depend on exactly one of the didit_sdk packages. Generated from didit_sdk - do not edit by hand. -version: 4.8.0 +version: 4.9.0 homepage: https://didit.me repository: https://github.com/didit-protocol/sdk-flutter issue_tracker: https://github.com/didit-protocol/sdk-flutter/issues diff --git a/packages/didit_sdk_core/CHANGELOG.md b/packages/didit_sdk_core/CHANGELOG.md index a9a93af..2520b40 100644 --- a/packages/didit_sdk_core/CHANGELOG.md +++ b/packages/didit_sdk_core/CHANGELOG.md @@ -1,3 +1,13 @@ +## 4.9.0 + +Adds the opt-in `showLanguageSelector` configuration option. + +When enabled, users can change the verification language from the welcome screen using the same compact, searchable selector as the web verification flow. +The selector remains hidden by default. + +Pins the iOS and Android native SDKs exactly to 4.9.0. + + ## 4.8.0 - Native SDKs 4.8.0 on both platforms. diff --git a/packages/didit_sdk_core/README.md b/packages/didit_sdk_core/README.md index 9ba5927..7175762 100644 --- a/packages/didit_sdk_core/README.md +++ b/packages/didit_sdk_core/README.md @@ -13,7 +13,7 @@ Depend on exactly one of the `didit_sdk` packages: ```yaml dependencies: - didit_sdk_core: ^4.8.0 + didit_sdk_core: ^4.9.0 ``` ```dart diff --git a/packages/didit_sdk_core/android/build.gradle.kts b/packages/didit_sdk_core/android/build.gradle.kts index 21ef176..2ce5ab4 100644 --- a/packages/didit_sdk_core/android/build.gradle.kts +++ b/packages/didit_sdk_core/android/build.gradle.kts @@ -1,7 +1,7 @@ group = "me.didit.sdk.sdk_flutter" version = "1.0-SNAPSHOT" -val diditSdkAndroidVersion = "4.8.0" +val diditSdkAndroidVersion = "4.9.0" val diditSdkAndroidVariant = ( rootProject.findProperty("diditSdkAndroidVariant") ?: findProperty("diditSdkAndroidVariant") diff --git a/packages/didit_sdk_core/android/src/main/kotlin/me/didit/sdk/sdk_flutter/SdkFlutterPlugin.kt b/packages/didit_sdk_core/android/src/main/kotlin/me/didit/sdk/sdk_flutter/SdkFlutterPlugin.kt index 32b1fe9..e943d3d 100644 --- a/packages/didit_sdk_core/android/src/main/kotlin/me/didit/sdk/sdk_flutter/SdkFlutterPlugin.kt +++ b/packages/didit_sdk_core/android/src/main/kotlin/me/didit/sdk/sdk_flutter/SdkFlutterPlugin.kt @@ -186,6 +186,7 @@ class SdkFlutterPlugin : return Configuration( languageLocale = language, + showLanguageSelector = map["showLanguageSelector"] as? Boolean ?: false, fontFamily = map["fontFamily"] as? String, loggingEnabled = map["loggingEnabled"] as? Boolean ?: false, showCloseButton = map["showCloseButton"] as? Boolean ?: true, diff --git a/packages/didit_sdk_core/ios/didit_sdk_core.podspec b/packages/didit_sdk_core/ios/didit_sdk_core.podspec index f12ac90..02d4e23 100644 --- a/packages/didit_sdk_core/ios/didit_sdk_core.podspec +++ b/packages/didit_sdk_core/ios/didit_sdk_core.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'didit_sdk_core' - s.version = '4.8.0' + s.version = '4.9.0' s.summary = 'Didit Identity Verification SDK for Flutter - core variant' s.description = <<-DESC Didit identity verification Flutter plugin pinned to the DiditSDK/Core native SDK @@ -17,7 +17,7 @@ variant (smallest, manual capture only - no automatic capture, no NFC). Generate # Fixed native variant - unlike didit_sdk this podspec intentionally ignores # $DiditSdkIosVariant. Keep your Podfile's DiditSDK subspec line in sync # (DiditSDK/Core) when building with CocoaPods. - s.dependency 'DiditSDK/Core', '4.8.0' + s.dependency 'DiditSDK/Core', '4.9.0' s.platform = :ios, '13.0' s.static_framework = true diff --git a/packages/didit_sdk_core/ios/didit_sdk_core/Package.swift b/packages/didit_sdk_core/ios/didit_sdk_core/Package.swift index 0cffb03..78a250c 100644 --- a/packages/didit_sdk_core/ios/didit_sdk_core/Package.swift +++ b/packages/didit_sdk_core/ios/didit_sdk_core/Package.swift @@ -11,7 +11,7 @@ let package = Package( .library(name: "didit-sdk-core", targets: ["didit_sdk_core"]) ], dependencies: [ - .package(url: "https://github.com/didit-protocol/sdk-ios.git", exact: "4.8.0") + .package(url: "https://github.com/didit-protocol/sdk-ios.git", exact: "4.9.0") ], targets: [ .target( diff --git a/packages/didit_sdk_core/ios/didit_sdk_core/Sources/didit_sdk_core/SdkFlutterPlugin.swift b/packages/didit_sdk_core/ios/didit_sdk_core/Sources/didit_sdk_core/SdkFlutterPlugin.swift index d051cde..dca6a66 100644 --- a/packages/didit_sdk_core/ios/didit_sdk_core/Sources/didit_sdk_core/SdkFlutterPlugin.swift +++ b/packages/didit_sdk_core/ios/didit_sdk_core/Sources/didit_sdk_core/SdkFlutterPlugin.swift @@ -206,7 +206,8 @@ public class SdkFlutterPlugin: NSObject, FlutterPlugin { defaultDocumentCamera: defaultDocumentCamera, defaultLivenessCamera: defaultLivenessCamera, showDocumentCameraSwitchButton: dict["showDocumentCameraSwitchButton"] as? Bool ?? true, - showLivenessCameraSwitchButton: dict["showLivenessCameraSwitchButton"] as? Bool ?? true + showLivenessCameraSwitchButton: dict["showLivenessCameraSwitchButton"] as? Bool ?? true, + showLanguageSelector: dict["showLanguageSelector"] as? Bool ?? false ) } diff --git a/packages/didit_sdk_core/lib/sdk_flutter.dart b/packages/didit_sdk_core/lib/sdk_flutter.dart index 00cf5dc..9c83490 100644 --- a/packages/didit_sdk_core/lib/sdk_flutter.dart +++ b/packages/didit_sdk_core/lib/sdk_flutter.dart @@ -80,7 +80,7 @@ class DiditSdk { static int _transactionCallCounter = 0; static bool _transactionUpdateHandlerRegistered = false; static final Map - _pendingTransactionUpdates = {}; + _pendingTransactionUpdates = {}; static void _ensureTransactionUpdateHandler() { if (_transactionUpdateHandlerRegistered) return; @@ -140,15 +140,12 @@ class DiditSdk { _pendingTransactionUpdates[callId] = onTransactionUpdated; } try { - final raw = await SdkFlutterPlatform.instance.submitTransaction( - transactionToken, - transaction.toMap(), - { - 'callId': callId, - 'autoLaunchAction': options.autoLaunchAction, - if (options.baseUrl != null) 'baseUrl': options.baseUrl, - }, - ); + final raw = await SdkFlutterPlatform.instance + .submitTransaction(transactionToken, transaction.toMap(), { + 'callId': callId, + 'autoLaunchAction': options.autoLaunchAction, + if (options.baseUrl != null) 'baseUrl': options.baseUrl, + }); final result = DiditTransactionResult.fromMap(raw); if (result.actionRequired == null) { _pendingTransactionUpdates.remove(callId); diff --git a/packages/didit_sdk_core/lib/sdk_flutter_method_channel.dart b/packages/didit_sdk_core/lib/sdk_flutter_method_channel.dart index f65c25a..03c6c2c 100644 --- a/packages/didit_sdk_core/lib/sdk_flutter_method_channel.dart +++ b/packages/didit_sdk_core/lib/sdk_flutter_method_channel.dart @@ -9,7 +9,7 @@ class MethodChannelSdkFlutter extends SdkFlutterPlatform { final methodChannel = const MethodChannel('didit_sdk'); void Function(String callId, Map result)? - _transactionUpdateHandler; + _transactionUpdateHandler; @override Future> startVerification( @@ -69,8 +69,9 @@ class MethodChannelSdkFlutter extends SdkFlutterPlatform { void Function(String callId, Map result)? handler, ) { _transactionUpdateHandler = handler; - methodChannel - .setMethodCallHandler(handler == null ? null : _handlePlatformCall); + methodChannel.setMethodCallHandler( + handler == null ? null : _handlePlatformCall, + ); } Future _handlePlatformCall(MethodCall call) async { diff --git a/packages/didit_sdk_core/lib/sdk_flutter_platform_interface.dart b/packages/didit_sdk_core/lib/sdk_flutter_platform_interface.dart index 028c0b8..b64abb7 100644 --- a/packages/didit_sdk_core/lib/sdk_flutter_platform_interface.dart +++ b/packages/didit_sdk_core/lib/sdk_flutter_platform_interface.dart @@ -31,7 +31,8 @@ abstract class SdkFlutterPlatform extends PlatformInterface { Map? config, ) { throw UnimplementedError( - 'startVerificationWithWorkflow() has not been implemented.'); + 'startVerificationWithWorkflow() has not been implemented.', + ); } /// Submit a transaction with a transaction SDK token. @@ -58,6 +59,7 @@ abstract class SdkFlutterPlatform extends PlatformInterface { void Function(String callId, Map result)? handler, ) { throw UnimplementedError( - 'setTransactionUpdateHandler() has not been implemented.'); + 'setTransactionUpdateHandler() has not been implemented.', + ); } } diff --git a/packages/didit_sdk_core/lib/src/transactions.dart b/packages/didit_sdk_core/lib/src/transactions.dart index 3dd4fcf..9a1e605 100644 --- a/packages/didit_sdk_core/lib/src/transactions.dart +++ b/packages/didit_sdk_core/lib/src/transactions.dart @@ -34,19 +34,18 @@ class DiditTransactionInfo { }); Map toMap() => { - if (direction != null) 'direction': direction, - if (amount != null) 'amount': amount, - if (currency != null) 'currency': currency, - if (currencyType != null) 'currencyType': currencyType, - if (amountInDefaultCurrency != null) - 'amountInDefaultCurrency': amountInDefaultCurrency, - if (defaultCurrencyCode != null) - 'defaultCurrencyCode': defaultCurrencyCode, - if (paymentDetails != null) 'paymentDetails': paymentDetails, - if (paymentTxnId != null) 'paymentTxnId': paymentTxnId, - if (type != null) 'type': type, - if (cryptoParams != null) 'cryptoParams': cryptoParams, - }; + if (direction != null) 'direction': direction, + if (amount != null) 'amount': amount, + if (currency != null) 'currency': currency, + if (currencyType != null) 'currencyType': currencyType, + if (amountInDefaultCurrency != null) + 'amountInDefaultCurrency': amountInDefaultCurrency, + if (defaultCurrencyCode != null) 'defaultCurrencyCode': defaultCurrencyCode, + if (paymentDetails != null) 'paymentDetails': paymentDetails, + if (paymentTxnId != null) 'paymentTxnId': paymentTxnId, + if (type != null) 'type': type, + if (cryptoParams != null) 'cryptoParams': cryptoParams, + }; } /// Payment method of a transaction participant. @@ -66,10 +65,10 @@ class DiditTransactionPaymentMethod { }); Map toMap() => { - if (type != null) 'type': type, - if (accountId != null) 'accountId': accountId, - if (issuingCountry != null) 'issuingCountry': issuingCountry, - }; + if (type != null) 'type': type, + if (accountId != null) 'accountId': accountId, + if (issuingCountry != null) 'issuingCountry': issuingCountry, + }; } /// A transaction participant (subject or counterparty). @@ -102,17 +101,17 @@ class DiditTransactionParticipant { }); Map toMap() => { - if (type != null) 'type': type, - if (externalUserId != null) 'externalUserId': externalUserId, - if (fullName != null) 'fullName': fullName, - if (firstName != null) 'firstName': firstName, - if (lastName != null) 'lastName': lastName, - if (dob != null) 'dob': dob, - if (address != null) 'address': address, - if (institutionInfo != null) 'institutionInfo': institutionInfo, - if (device != null) 'device': device, - if (paymentMethod != null) 'paymentMethod': paymentMethod!.toMap(), - }; + if (type != null) 'type': type, + if (externalUserId != null) 'externalUserId': externalUserId, + if (fullName != null) 'fullName': fullName, + if (firstName != null) 'firstName': firstName, + if (lastName != null) 'lastName': lastName, + if (dob != null) 'dob': dob, + if (address != null) 'address': address, + if (institutionInfo != null) 'institutionInfo': institutionInfo, + if (device != null) 'device': device, + if (paymentMethod != null) 'paymentMethod': paymentMethod!.toMap(), + }; } /// Travel rule information attached to a transaction. @@ -136,14 +135,14 @@ class DiditTravelRule { }); Map toMap() => { - if (status != null) 'status': status, - if (protocol != null) 'protocol': protocol, - if (required != null) 'required': required, - if (obligationsCount != null) 'obligationsCount': obligationsCount, - if (originatorData != null) 'originatorData': originatorData, - if (beneficiaryData != null) 'beneficiaryData': beneficiaryData, - if (metadata != null) 'metadata': metadata, - }; + if (status != null) 'status': status, + if (protocol != null) 'protocol': protocol, + if (required != null) 'required': required, + if (obligationsCount != null) 'obligationsCount': obligationsCount, + if (originatorData != null) 'originatorData': originatorData, + if (beneficiaryData != null) 'beneficiaryData': beneficiaryData, + if (metadata != null) 'metadata': metadata, + }; } /// A transaction to submit from the device. @@ -184,18 +183,18 @@ class DiditTransactionPayload { }); Map toMap() => { - 'txnId': txnId, - if (txnDate != null) 'txnDate': txnDate, - if (zoneId != null) 'zoneId': zoneId, - if (type != null) 'type': type, - if (info != null) 'info': info!.toMap(), - if (subject != null) 'subject': subject!.toMap(), - if (counterparty != null) 'counterparty': counterparty!.toMap(), - if (props != null) 'props': props, - if (travelRule != null) 'travelRule': travelRule!.toMap(), - if (includeCryptoScreening != null) - 'includeCryptoScreening': includeCryptoScreening, - }; + 'txnId': txnId, + if (txnDate != null) 'txnDate': txnDate, + if (zoneId != null) 'zoneId': zoneId, + if (type != null) 'type': type, + if (info != null) 'info': info!.toMap(), + if (subject != null) 'subject': subject!.toMap(), + if (counterparty != null) 'counterparty': counterparty!.toMap(), + if (props != null) 'props': props, + if (travelRule != null) 'travelRule': travelRule!.toMap(), + if (includeCryptoScreening != null) + 'includeCryptoScreening': includeCryptoScreening, + }; } /// A user action required to complete the transaction. diff --git a/packages/didit_sdk_core/lib/src/types.dart b/packages/didit_sdk_core/lib/src/types.dart index 879721b..626ec7b 100644 --- a/packages/didit_sdk_core/lib/src/types.dart +++ b/packages/didit_sdk_core/lib/src/types.dart @@ -109,9 +109,9 @@ sealed class VerificationResult { case 'failed': return VerificationFailed( error: VerificationError( - type: VerificationErrorType.fromString( - map['errorType'] as String?), - message: (map['errorMessage'] as String?) ?? + type: VerificationErrorType.fromString(map['errorType'] as String?), + message: + (map['errorMessage'] as String?) ?? 'An unknown error occurred during verification.', ), session: session, @@ -159,9 +159,9 @@ enum CameraLens { back; String toMap() => switch (this) { - CameraLens.front => 'front', - CameraLens.back => 'back', - }; + CameraLens.front => 'front', + CameraLens.back => 'back', + }; } /// Configuration options for the Didit verification SDK. @@ -174,6 +174,10 @@ class DiditConfig { /// ISO 639-1 language code for the SDK UI (e.g. "en", "he", "ar"). final String? languageCode; + /// Show the language selector on the verification welcome screen. + /// Default is `false`. + final bool showLanguageSelector; + /// Custom font family name to use throughout the SDK UI. final String? fontFamily; @@ -217,6 +221,7 @@ class DiditConfig { const DiditConfig({ this.languageCode, + this.showLanguageSelector = false, this.fontFamily, this.loggingEnabled = false, this.showCloseButton = true, @@ -231,6 +236,7 @@ class DiditConfig { Map toMap() { final map = {}; if (languageCode != null) map['languageCode'] = languageCode; + map['showLanguageSelector'] = showLanguageSelector; if (fontFamily != null) map['fontFamily'] = fontFamily; map['loggingEnabled'] = loggingEnabled; map['showCloseButton'] = showCloseButton; @@ -247,4 +253,3 @@ class DiditConfig { return map; } } - diff --git a/packages/didit_sdk_core/pubspec.yaml b/packages/didit_sdk_core/pubspec.yaml index a559ce3..96f2884 100644 --- a/packages/didit_sdk_core/pubspec.yaml +++ b/packages/didit_sdk_core/pubspec.yaml @@ -1,6 +1,6 @@ name: didit_sdk_core description: Didit Identity Verification SDK for Flutter, pinned to the core native SDK variant (smallest, manual capture only - no automatic capture, no NFC). Same Dart API as didit_sdk - depend on exactly one of the didit_sdk packages. Generated from didit_sdk - do not edit by hand. -version: 4.8.0 +version: 4.9.0 homepage: https://didit.me repository: https://github.com/didit-protocol/sdk-flutter issue_tracker: https://github.com/didit-protocol/sdk-flutter/issues diff --git a/packages/didit_sdk_nfc/CHANGELOG.md b/packages/didit_sdk_nfc/CHANGELOG.md index e24c0f4..d03889e 100644 --- a/packages/didit_sdk_nfc/CHANGELOG.md +++ b/packages/didit_sdk_nfc/CHANGELOG.md @@ -1,3 +1,13 @@ +## 4.9.0 + +Adds the opt-in `showLanguageSelector` configuration option. + +When enabled, users can change the verification language from the welcome screen using the same compact, searchable selector as the web verification flow. +The selector remains hidden by default. + +Pins the iOS and Android native SDKs exactly to 4.9.0. + + ## 4.8.0 - Native SDKs 4.8.0 on both platforms. diff --git a/packages/didit_sdk_nfc/README.md b/packages/didit_sdk_nfc/README.md index a61d979..3375a15 100644 --- a/packages/didit_sdk_nfc/README.md +++ b/packages/didit_sdk_nfc/README.md @@ -13,7 +13,7 @@ Depend on exactly one of the `didit_sdk` packages: ```yaml dependencies: - didit_sdk_nfc: ^4.8.0 + didit_sdk_nfc: ^4.9.0 ``` ```dart diff --git a/packages/didit_sdk_nfc/android/build.gradle.kts b/packages/didit_sdk_nfc/android/build.gradle.kts index f23fffb..1fe4d38 100644 --- a/packages/didit_sdk_nfc/android/build.gradle.kts +++ b/packages/didit_sdk_nfc/android/build.gradle.kts @@ -1,7 +1,7 @@ group = "me.didit.sdk.sdk_flutter" version = "1.0-SNAPSHOT" -val diditSdkAndroidVersion = "4.8.0" +val diditSdkAndroidVersion = "4.9.0" val diditSdkAndroidVariant = ( rootProject.findProperty("diditSdkAndroidVariant") ?: findProperty("diditSdkAndroidVariant") diff --git a/packages/didit_sdk_nfc/android/src/main/kotlin/me/didit/sdk/sdk_flutter/SdkFlutterPlugin.kt b/packages/didit_sdk_nfc/android/src/main/kotlin/me/didit/sdk/sdk_flutter/SdkFlutterPlugin.kt index 32b1fe9..e943d3d 100644 --- a/packages/didit_sdk_nfc/android/src/main/kotlin/me/didit/sdk/sdk_flutter/SdkFlutterPlugin.kt +++ b/packages/didit_sdk_nfc/android/src/main/kotlin/me/didit/sdk/sdk_flutter/SdkFlutterPlugin.kt @@ -186,6 +186,7 @@ class SdkFlutterPlugin : return Configuration( languageLocale = language, + showLanguageSelector = map["showLanguageSelector"] as? Boolean ?: false, fontFamily = map["fontFamily"] as? String, loggingEnabled = map["loggingEnabled"] as? Boolean ?: false, showCloseButton = map["showCloseButton"] as? Boolean ?: true, diff --git a/packages/didit_sdk_nfc/ios/didit_sdk_nfc.podspec b/packages/didit_sdk_nfc/ios/didit_sdk_nfc.podspec index a84281d..5bde96d 100644 --- a/packages/didit_sdk_nfc/ios/didit_sdk_nfc.podspec +++ b/packages/didit_sdk_nfc/ios/didit_sdk_nfc.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'didit_sdk_nfc' - s.version = '4.8.0' + s.version = '4.9.0' s.summary = 'Didit Identity Verification SDK for Flutter - nfc variant' s.description = <<-DESC Didit identity verification Flutter plugin pinned to the DiditSDK/NFC native SDK @@ -17,7 +17,7 @@ variant (NFC passport reading without automatic capture). Generated from didit_s # Fixed native variant - unlike didit_sdk this podspec intentionally ignores # $DiditSdkIosVariant. Keep your Podfile's DiditSDK subspec line in sync # (DiditSDK/NFC) when building with CocoaPods. - s.dependency 'DiditSDK/NFC', '4.8.0' + s.dependency 'DiditSDK/NFC', '4.9.0' s.platform = :ios, '15.0' s.static_framework = true diff --git a/packages/didit_sdk_nfc/ios/didit_sdk_nfc/Package.swift b/packages/didit_sdk_nfc/ios/didit_sdk_nfc/Package.swift index 6ce0e7d..bf444cd 100644 --- a/packages/didit_sdk_nfc/ios/didit_sdk_nfc/Package.swift +++ b/packages/didit_sdk_nfc/ios/didit_sdk_nfc/Package.swift @@ -11,7 +11,7 @@ let package = Package( .library(name: "didit-sdk-nfc", targets: ["didit_sdk_nfc"]) ], dependencies: [ - .package(url: "https://github.com/didit-protocol/sdk-ios.git", exact: "4.8.0") + .package(url: "https://github.com/didit-protocol/sdk-ios.git", exact: "4.9.0") ], targets: [ .target( diff --git a/packages/didit_sdk_nfc/ios/didit_sdk_nfc/Sources/didit_sdk_nfc/SdkFlutterPlugin.swift b/packages/didit_sdk_nfc/ios/didit_sdk_nfc/Sources/didit_sdk_nfc/SdkFlutterPlugin.swift index d051cde..dca6a66 100644 --- a/packages/didit_sdk_nfc/ios/didit_sdk_nfc/Sources/didit_sdk_nfc/SdkFlutterPlugin.swift +++ b/packages/didit_sdk_nfc/ios/didit_sdk_nfc/Sources/didit_sdk_nfc/SdkFlutterPlugin.swift @@ -206,7 +206,8 @@ public class SdkFlutterPlugin: NSObject, FlutterPlugin { defaultDocumentCamera: defaultDocumentCamera, defaultLivenessCamera: defaultLivenessCamera, showDocumentCameraSwitchButton: dict["showDocumentCameraSwitchButton"] as? Bool ?? true, - showLivenessCameraSwitchButton: dict["showLivenessCameraSwitchButton"] as? Bool ?? true + showLivenessCameraSwitchButton: dict["showLivenessCameraSwitchButton"] as? Bool ?? true, + showLanguageSelector: dict["showLanguageSelector"] as? Bool ?? false ) } diff --git a/packages/didit_sdk_nfc/lib/sdk_flutter.dart b/packages/didit_sdk_nfc/lib/sdk_flutter.dart index 00cf5dc..9c83490 100644 --- a/packages/didit_sdk_nfc/lib/sdk_flutter.dart +++ b/packages/didit_sdk_nfc/lib/sdk_flutter.dart @@ -80,7 +80,7 @@ class DiditSdk { static int _transactionCallCounter = 0; static bool _transactionUpdateHandlerRegistered = false; static final Map - _pendingTransactionUpdates = {}; + _pendingTransactionUpdates = {}; static void _ensureTransactionUpdateHandler() { if (_transactionUpdateHandlerRegistered) return; @@ -140,15 +140,12 @@ class DiditSdk { _pendingTransactionUpdates[callId] = onTransactionUpdated; } try { - final raw = await SdkFlutterPlatform.instance.submitTransaction( - transactionToken, - transaction.toMap(), - { - 'callId': callId, - 'autoLaunchAction': options.autoLaunchAction, - if (options.baseUrl != null) 'baseUrl': options.baseUrl, - }, - ); + final raw = await SdkFlutterPlatform.instance + .submitTransaction(transactionToken, transaction.toMap(), { + 'callId': callId, + 'autoLaunchAction': options.autoLaunchAction, + if (options.baseUrl != null) 'baseUrl': options.baseUrl, + }); final result = DiditTransactionResult.fromMap(raw); if (result.actionRequired == null) { _pendingTransactionUpdates.remove(callId); diff --git a/packages/didit_sdk_nfc/lib/sdk_flutter_method_channel.dart b/packages/didit_sdk_nfc/lib/sdk_flutter_method_channel.dart index f65c25a..03c6c2c 100644 --- a/packages/didit_sdk_nfc/lib/sdk_flutter_method_channel.dart +++ b/packages/didit_sdk_nfc/lib/sdk_flutter_method_channel.dart @@ -9,7 +9,7 @@ class MethodChannelSdkFlutter extends SdkFlutterPlatform { final methodChannel = const MethodChannel('didit_sdk'); void Function(String callId, Map result)? - _transactionUpdateHandler; + _transactionUpdateHandler; @override Future> startVerification( @@ -69,8 +69,9 @@ class MethodChannelSdkFlutter extends SdkFlutterPlatform { void Function(String callId, Map result)? handler, ) { _transactionUpdateHandler = handler; - methodChannel - .setMethodCallHandler(handler == null ? null : _handlePlatformCall); + methodChannel.setMethodCallHandler( + handler == null ? null : _handlePlatformCall, + ); } Future _handlePlatformCall(MethodCall call) async { diff --git a/packages/didit_sdk_nfc/lib/sdk_flutter_platform_interface.dart b/packages/didit_sdk_nfc/lib/sdk_flutter_platform_interface.dart index 028c0b8..b64abb7 100644 --- a/packages/didit_sdk_nfc/lib/sdk_flutter_platform_interface.dart +++ b/packages/didit_sdk_nfc/lib/sdk_flutter_platform_interface.dart @@ -31,7 +31,8 @@ abstract class SdkFlutterPlatform extends PlatformInterface { Map? config, ) { throw UnimplementedError( - 'startVerificationWithWorkflow() has not been implemented.'); + 'startVerificationWithWorkflow() has not been implemented.', + ); } /// Submit a transaction with a transaction SDK token. @@ -58,6 +59,7 @@ abstract class SdkFlutterPlatform extends PlatformInterface { void Function(String callId, Map result)? handler, ) { throw UnimplementedError( - 'setTransactionUpdateHandler() has not been implemented.'); + 'setTransactionUpdateHandler() has not been implemented.', + ); } } diff --git a/packages/didit_sdk_nfc/lib/src/transactions.dart b/packages/didit_sdk_nfc/lib/src/transactions.dart index 3dd4fcf..9a1e605 100644 --- a/packages/didit_sdk_nfc/lib/src/transactions.dart +++ b/packages/didit_sdk_nfc/lib/src/transactions.dart @@ -34,19 +34,18 @@ class DiditTransactionInfo { }); Map toMap() => { - if (direction != null) 'direction': direction, - if (amount != null) 'amount': amount, - if (currency != null) 'currency': currency, - if (currencyType != null) 'currencyType': currencyType, - if (amountInDefaultCurrency != null) - 'amountInDefaultCurrency': amountInDefaultCurrency, - if (defaultCurrencyCode != null) - 'defaultCurrencyCode': defaultCurrencyCode, - if (paymentDetails != null) 'paymentDetails': paymentDetails, - if (paymentTxnId != null) 'paymentTxnId': paymentTxnId, - if (type != null) 'type': type, - if (cryptoParams != null) 'cryptoParams': cryptoParams, - }; + if (direction != null) 'direction': direction, + if (amount != null) 'amount': amount, + if (currency != null) 'currency': currency, + if (currencyType != null) 'currencyType': currencyType, + if (amountInDefaultCurrency != null) + 'amountInDefaultCurrency': amountInDefaultCurrency, + if (defaultCurrencyCode != null) 'defaultCurrencyCode': defaultCurrencyCode, + if (paymentDetails != null) 'paymentDetails': paymentDetails, + if (paymentTxnId != null) 'paymentTxnId': paymentTxnId, + if (type != null) 'type': type, + if (cryptoParams != null) 'cryptoParams': cryptoParams, + }; } /// Payment method of a transaction participant. @@ -66,10 +65,10 @@ class DiditTransactionPaymentMethod { }); Map toMap() => { - if (type != null) 'type': type, - if (accountId != null) 'accountId': accountId, - if (issuingCountry != null) 'issuingCountry': issuingCountry, - }; + if (type != null) 'type': type, + if (accountId != null) 'accountId': accountId, + if (issuingCountry != null) 'issuingCountry': issuingCountry, + }; } /// A transaction participant (subject or counterparty). @@ -102,17 +101,17 @@ class DiditTransactionParticipant { }); Map toMap() => { - if (type != null) 'type': type, - if (externalUserId != null) 'externalUserId': externalUserId, - if (fullName != null) 'fullName': fullName, - if (firstName != null) 'firstName': firstName, - if (lastName != null) 'lastName': lastName, - if (dob != null) 'dob': dob, - if (address != null) 'address': address, - if (institutionInfo != null) 'institutionInfo': institutionInfo, - if (device != null) 'device': device, - if (paymentMethod != null) 'paymentMethod': paymentMethod!.toMap(), - }; + if (type != null) 'type': type, + if (externalUserId != null) 'externalUserId': externalUserId, + if (fullName != null) 'fullName': fullName, + if (firstName != null) 'firstName': firstName, + if (lastName != null) 'lastName': lastName, + if (dob != null) 'dob': dob, + if (address != null) 'address': address, + if (institutionInfo != null) 'institutionInfo': institutionInfo, + if (device != null) 'device': device, + if (paymentMethod != null) 'paymentMethod': paymentMethod!.toMap(), + }; } /// Travel rule information attached to a transaction. @@ -136,14 +135,14 @@ class DiditTravelRule { }); Map toMap() => { - if (status != null) 'status': status, - if (protocol != null) 'protocol': protocol, - if (required != null) 'required': required, - if (obligationsCount != null) 'obligationsCount': obligationsCount, - if (originatorData != null) 'originatorData': originatorData, - if (beneficiaryData != null) 'beneficiaryData': beneficiaryData, - if (metadata != null) 'metadata': metadata, - }; + if (status != null) 'status': status, + if (protocol != null) 'protocol': protocol, + if (required != null) 'required': required, + if (obligationsCount != null) 'obligationsCount': obligationsCount, + if (originatorData != null) 'originatorData': originatorData, + if (beneficiaryData != null) 'beneficiaryData': beneficiaryData, + if (metadata != null) 'metadata': metadata, + }; } /// A transaction to submit from the device. @@ -184,18 +183,18 @@ class DiditTransactionPayload { }); Map toMap() => { - 'txnId': txnId, - if (txnDate != null) 'txnDate': txnDate, - if (zoneId != null) 'zoneId': zoneId, - if (type != null) 'type': type, - if (info != null) 'info': info!.toMap(), - if (subject != null) 'subject': subject!.toMap(), - if (counterparty != null) 'counterparty': counterparty!.toMap(), - if (props != null) 'props': props, - if (travelRule != null) 'travelRule': travelRule!.toMap(), - if (includeCryptoScreening != null) - 'includeCryptoScreening': includeCryptoScreening, - }; + 'txnId': txnId, + if (txnDate != null) 'txnDate': txnDate, + if (zoneId != null) 'zoneId': zoneId, + if (type != null) 'type': type, + if (info != null) 'info': info!.toMap(), + if (subject != null) 'subject': subject!.toMap(), + if (counterparty != null) 'counterparty': counterparty!.toMap(), + if (props != null) 'props': props, + if (travelRule != null) 'travelRule': travelRule!.toMap(), + if (includeCryptoScreening != null) + 'includeCryptoScreening': includeCryptoScreening, + }; } /// A user action required to complete the transaction. diff --git a/packages/didit_sdk_nfc/lib/src/types.dart b/packages/didit_sdk_nfc/lib/src/types.dart index 879721b..626ec7b 100644 --- a/packages/didit_sdk_nfc/lib/src/types.dart +++ b/packages/didit_sdk_nfc/lib/src/types.dart @@ -109,9 +109,9 @@ sealed class VerificationResult { case 'failed': return VerificationFailed( error: VerificationError( - type: VerificationErrorType.fromString( - map['errorType'] as String?), - message: (map['errorMessage'] as String?) ?? + type: VerificationErrorType.fromString(map['errorType'] as String?), + message: + (map['errorMessage'] as String?) ?? 'An unknown error occurred during verification.', ), session: session, @@ -159,9 +159,9 @@ enum CameraLens { back; String toMap() => switch (this) { - CameraLens.front => 'front', - CameraLens.back => 'back', - }; + CameraLens.front => 'front', + CameraLens.back => 'back', + }; } /// Configuration options for the Didit verification SDK. @@ -174,6 +174,10 @@ class DiditConfig { /// ISO 639-1 language code for the SDK UI (e.g. "en", "he", "ar"). final String? languageCode; + /// Show the language selector on the verification welcome screen. + /// Default is `false`. + final bool showLanguageSelector; + /// Custom font family name to use throughout the SDK UI. final String? fontFamily; @@ -217,6 +221,7 @@ class DiditConfig { const DiditConfig({ this.languageCode, + this.showLanguageSelector = false, this.fontFamily, this.loggingEnabled = false, this.showCloseButton = true, @@ -231,6 +236,7 @@ class DiditConfig { Map toMap() { final map = {}; if (languageCode != null) map['languageCode'] = languageCode; + map['showLanguageSelector'] = showLanguageSelector; if (fontFamily != null) map['fontFamily'] = fontFamily; map['loggingEnabled'] = loggingEnabled; map['showCloseButton'] = showCloseButton; @@ -247,4 +253,3 @@ class DiditConfig { return map; } } - diff --git a/packages/didit_sdk_nfc/pubspec.yaml b/packages/didit_sdk_nfc/pubspec.yaml index 0d79352..429da96 100644 --- a/packages/didit_sdk_nfc/pubspec.yaml +++ b/packages/didit_sdk_nfc/pubspec.yaml @@ -1,6 +1,6 @@ name: didit_sdk_nfc description: Didit Identity Verification SDK for Flutter, pinned to the nfc native SDK variant (NFC passport reading without automatic capture). Same Dart API as didit_sdk - depend on exactly one of the didit_sdk packages. Generated from didit_sdk - do not edit by hand. -version: 4.8.0 +version: 4.9.0 homepage: https://didit.me repository: https://github.com/didit-protocol/sdk-flutter issue_tracker: https://github.com/didit-protocol/sdk-flutter/issues diff --git a/pubspec.yaml b/pubspec.yaml index 7759b79..31fe6a2 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: didit_sdk description: Didit Identity Verification SDK for Flutter. Wraps native iOS and Android SDKs for document scanning, NFC passport reading, face verification, and liveness detection. -version: 4.8.0 +version: 4.9.0 homepage: https://didit.me repository: https://github.com/didit-protocol/sdk-flutter issue_tracker: https://github.com/didit-protocol/sdk-flutter/issues diff --git a/release-notes/4.9.0.md b/release-notes/4.9.0.md new file mode 100644 index 0000000..dfed802 --- /dev/null +++ b/release-notes/4.9.0.md @@ -0,0 +1,6 @@ +Adds the opt-in `showLanguageSelector` configuration option. + +When enabled, users can change the verification language from the welcome screen using the same compact, searchable selector as the web verification flow. +The selector remains hidden by default. + +Pins the iOS and Android native SDKs exactly to 4.9.0. diff --git a/test/sdk_flutter_method_channel_test.dart b/test/sdk_flutter_method_channel_test.dart index 054d3b0..a9f37bf 100644 --- a/test/sdk_flutter_method_channel_test.dart +++ b/test/sdk_flutter_method_channel_test.dart @@ -114,15 +114,15 @@ void main() { const codec = StandardMethodCodec(); await TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger .handlePlatformMessage( - 'didit_sdk', - codec.encodeMethodCall( - const MethodCall('onTransactionUpdated', { - 'callId': 'call-9', - 'result': {'transactionId': 'txn-9', 'status': 'APPROVED'}, - }), - ), - (data) {}, - ); + 'didit_sdk', + codec.encodeMethodCall( + const MethodCall('onTransactionUpdated', { + 'callId': 'call-9', + 'result': {'transactionId': 'txn-9', 'status': 'APPROVED'}, + }), + ), + (data) {}, + ); expect(receivedCallId, 'call-9'); expect(receivedResult?['transactionId'], 'txn-9'); diff --git a/test/sdk_flutter_test.dart b/test/sdk_flutter_test.dart index f5cbe94..9127358 100644 --- a/test/sdk_flutter_test.dart +++ b/test/sdk_flutter_test.dart @@ -9,7 +9,7 @@ class MockSdkFlutterPlatform with MockPlatformInterfaceMixin implements SdkFlutterPlatform { void Function(String callId, Map result)? - transactionUpdateHandler; + transactionUpdateHandler; Map? lastTransactionOptions; Map? lastVerificationConfig; Map? lastWorkflowConfig; @@ -110,9 +110,28 @@ void main() { expect(platform.lastVerificationConfig?['languageCode'], 'he'); }); - testWidgets('startVerification propagates a Hebrew device locale', - (tester) async { - tester.binding.platformDispatcher.localeTestValue = const Locale('he', 'IL'); + test('language selector is disabled by default', () async { + await DiditSdk.startVerification('test-token', config: const DiditConfig()); + + expect(platform.lastVerificationConfig?['showLanguageSelector'], false); + }); + + test('startVerification forwards an enabled language selector', () async { + await DiditSdk.startVerification( + 'test-token', + config: const DiditConfig(showLanguageSelector: true), + ); + + expect(platform.lastVerificationConfig?['showLanguageSelector'], true); + }); + + testWidgets('startVerification propagates a Hebrew device locale', ( + tester, + ) async { + tester.binding.platformDispatcher.localeTestValue = const Locale( + 'he', + 'IL', + ); addTearDown(tester.binding.platformDispatcher.clearLocaleTestValue); await DiditSdk.startVerification('test-token'); @@ -120,9 +139,13 @@ void main() { expect(platform.lastVerificationConfig?['languageCode'], 'he'); }); - testWidgets('startVerification normalizes the legacy Hebrew locale code', - (tester) async { - tester.binding.platformDispatcher.localeTestValue = const Locale('iw', 'IL'); + testWidgets('startVerification normalizes the legacy Hebrew locale code', ( + tester, + ) async { + tester.binding.platformDispatcher.localeTestValue = const Locale( + 'iw', + 'IL', + ); addTearDown(tester.binding.platformDispatcher.clearLocaleTestValue); await DiditSdk.startVerification('test-token'); @@ -237,8 +260,7 @@ void main() { expect(result.actionRequired, isNull); }); - test( - 'DiditTransactionResult.fromMap surfaces actionRequired unconditionally ' + test('DiditTransactionResult.fromMap surfaces actionRequired unconditionally ' 'for verification_session, including sessionId and sessionToken', () { final result = DiditTransactionResult.fromMap({ 'transactionId': 'txn-vs-1', diff --git a/tool/generate_variant_packages.sh b/tool/generate_variant_packages.sh index d796d29..3d20f69 100755 --- a/tool/generate_variant_packages.sh +++ b/tool/generate_variant_packages.sh @@ -7,8 +7,9 @@ # per-app native variant selection inside a single package under Swift Package # Manager). Run from the repo root after ANY change to lib/, android/, # ios/didit_sdk/Sources, the version, or the native SDK pins - the variants -# must never drift. CHANGELOG.md files are left untouched when they exist - -# update those by hand per release. See README "Native SDK Variants". +# must never drift. When release-notes/.md exists, this script also +# generates matching changelog entries for the root and variant packages. +# See README "Native SDK Variants". set -euo pipefail cd "$(dirname "$0")/.." @@ -18,6 +19,25 @@ NATIVE_IOS_VERSION=$(sed -n 's/.*exact: "\(.*\)").*/\1/p' ios/didit_sdk/Package. [[ -n "$VERSION" && -n "$NATIVE_IOS_VERSION" ]] || { echo "failed to read versions" >&2; exit 1; } echo "wrapper $VERSION / native iOS DiditSDK $NATIVE_IOS_VERSION" +prepend_release_notes() { + local changelog=$1 + local release_notes="release-notes/$VERSION.md" + [[ -f "$release_notes" ]] || return 0 + grep -q "^## $VERSION$" "$changelog" && return 0 + + local generated_changelog + generated_changelog=$(mktemp) + { + printf '## %s\n\n' "$VERSION" + cat "$release_notes" + printf '\n\n' + cat "$changelog" + } > "$generated_changelog" + mv "$generated_changelog" "$changelog" +} + +prepend_release_notes CHANGELOG.md + generate() { local name=$1 variant=$2 product=$3 subspec=$4 floor=$5 feature_desc=$6 auto=$7 nfc=$8 local pkg=packages/$name @@ -168,6 +188,7 @@ EOF * Initial release: the didit_sdk Flutter plugin pinned to the $variant native SDK variant on both platforms ($feature_desc; minimum iOS $floor). Supports both Swift Package Manager and CocoaPods on iOS. EOF fi + prepend_release_notes "$pkg/CHANGELOG.md" } # name variant SPM product pod subspec floor description auto nfc