diff --git a/android/build.gradle b/android/build.gradle index dbd8d94..491d945 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -51,6 +51,6 @@ android { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" - implementation "io.qonversion:sandwich:7.8.0" + implementation "io.qonversion:sandwich:7.9.0" implementation 'com.google.code.gson:gson:2.9.0' } diff --git a/android/src/main/kotlin/com/qonversion/flutter/sdk/qonversion_flutter_sdk/NoCodesPlugin.kt b/android/src/main/kotlin/com/qonversion/flutter/sdk/qonversion_flutter_sdk/NoCodesPlugin.kt index fa5f28a..fb15a29 100644 --- a/android/src/main/kotlin/com/qonversion/flutter/sdk/qonversion_flutter_sdk/NoCodesPlugin.kt +++ b/android/src/main/kotlin/com/qonversion/flutter/sdk/qonversion_flutter_sdk/NoCodesPlugin.kt @@ -106,9 +106,9 @@ class NoCodesPlugin(private val messenger: BinaryMessenger, private val context: } } - fun showNoCodesScreen(contextKey: String?, result: Result) { + fun showNoCodesScreen(contextKey: String?, customVariables: Map?, result: Result) { if (contextKey != null) { - noCodesSandwich?.showScreen(contextKey) + noCodesSandwich?.showScreen(contextKey, customVariables) result.success(null) } else { result.noNecessaryDataError() diff --git a/android/src/main/kotlin/com/qonversion/flutter/sdk/qonversion_flutter_sdk/QonversionPlugin.kt b/android/src/main/kotlin/com/qonversion/flutter/sdk/qonversion_flutter_sdk/QonversionPlugin.kt index d1a463f..28c4674 100644 --- a/android/src/main/kotlin/com/qonversion/flutter/sdk/qonversion_flutter_sdk/QonversionPlugin.kt +++ b/android/src/main/kotlin/com/qonversion/flutter/sdk/qonversion_flutter_sdk/QonversionPlugin.kt @@ -105,6 +105,9 @@ class QonversionPlugin : MethodCallHandler, FlutterPlugin, ActivityAware { "userProperties" -> { return userProperties(result) } + "forceSendProperties" -> { + return forceSendProperties(result) + } "logout" -> { qonversionSandwich.logout() return result.success(null) @@ -159,7 +162,7 @@ class QonversionPlugin : MethodCallHandler, FlutterPlugin, ActivityAware { // NoCodes methods "initializeNoCodes" -> noCodesPlugin?.initializeNoCodes(args, result) "setScreenPresentationConfig" -> noCodesPlugin?.setScreenPresentationConfig(args["config"] as? Map, args["contextKey"] as? String, result) - "showNoCodesScreen" -> noCodesPlugin?.showNoCodesScreen(args["contextKey"] as? String, result) + "showNoCodesScreen" -> noCodesPlugin?.showNoCodesScreen(args["contextKey"] as? String, args["customVariables"] as? Map, result) "setNoCodesLocale" -> noCodesPlugin?.setLocale(args["locale"] as? String, result) "setNoCodesTheme" -> noCodesPlugin?.setTheme(args["theme"] as? String, result) // NoCodes Purchase Delegate methods @@ -252,6 +255,12 @@ class QonversionPlugin : MethodCallHandler, FlutterPlugin, ActivityAware { qonversionSandwich.userProperties(result.toJsonResultListener()) } + private fun forceSendProperties(result: Result) { + qonversionSandwich.forceSendProperties { + result.success(null) + } + } + private fun isFallbackFileAccessible(result: Result) { qonversionSandwich.isFallbackFileAccessible(result.toJsonResultListener()) } diff --git a/ios/Classes/NoCodesPlugin.swift b/ios/Classes/NoCodesPlugin.swift index 8847fcc..30b8062 100644 --- a/ios/Classes/NoCodesPlugin.swift +++ b/ios/Classes/NoCodesPlugin.swift @@ -112,8 +112,10 @@ public class NoCodesPlugin: NSObject { let contextKey = args["contextKey"] as? String else { return result(FlutterError.noNecessaryData) } - - noCodesSandwich?.showScreen(contextKey) + + let customVariables = args["customVariables"] as? [String: String] + + noCodesSandwich?.showScreen(contextKey, customVariables: customVariables) result(nil) } diff --git a/ios/Classes/SwiftQonversionPlugin.swift b/ios/Classes/SwiftQonversionPlugin.swift index f3a3165..57a8742 100644 --- a/ios/Classes/SwiftQonversionPlugin.swift +++ b/ios/Classes/SwiftQonversionPlugin.swift @@ -84,6 +84,9 @@ public class SwiftQonversionPlugin: NSObject, FlutterPlugin { case "userProperties": return userProperties(result) + case "forceSendProperties": + return forceSendProperties(result) + case "presentCodeRedemptionSheet": return presentCodeRedemptionSheet(result) @@ -312,6 +315,12 @@ public class SwiftQonversionPlugin: NSObject, FlutterPlugin { private func userProperties(_ result: @escaping FlutterResult) { qonversionSandwich?.userProperties(getJsonCompletion(result)) } + + private func forceSendProperties(_ result: @escaping FlutterResult) { + qonversionSandwich?.forceSendProperties { + result(nil) + } + } private func restore(_ result: @escaping FlutterResult) { qonversionSandwich?.restore(getJsonCompletion(result)) diff --git a/ios/qonversion_flutter.podspec b/ios/qonversion_flutter.podspec index e29bcac..ec45045 100644 --- a/ios/qonversion_flutter.podspec +++ b/ios/qonversion_flutter.podspec @@ -16,7 +16,7 @@ Pod::Spec.new do |s| s.source_files = 'Classes/**/*' s.dependency 'Flutter' s.platform = :ios, '13.0' - s.dependency "QonversionSandwich", "7.8.0" + s.dependency "QonversionSandwich", "7.9.0" # Flutter.framework does not contain a i386 slice. Only x86_64 simulators are supported. s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'VALID_ARCHS[sdk=iphonesimulator*]' => 'x86_64' } diff --git a/lib/src/internal/constants.dart b/lib/src/internal/constants.dart index 861b4be..23cb728 100644 --- a/lib/src/internal/constants.dart +++ b/lib/src/internal/constants.dart @@ -38,6 +38,7 @@ class Constants { static const kSource = 'source'; static const kLocale = 'locale'; static const kTheme = 'theme'; + static const kCustomVariables = 'customVariables'; // MethodChannel methods names static const mInitialize = 'initialize'; @@ -54,6 +55,7 @@ class Constants { static const mSetDefinedUserProperty = 'setDefinedUserProperty'; static const mSetCustomUserProperty = 'setCustomUserProperty'; static const mUserProperties = 'userProperties'; + static const mForceSendProperties = 'forceSendProperties'; static const mSetEntitlementsCacheLifetime = 'setEntitlementsCacheLifetime'; static const mSyncPurchases = 'syncPurchases'; static const mAddAttributionData = 'addAttributionData'; diff --git a/lib/src/internal/nocodes_internal.dart b/lib/src/internal/nocodes_internal.dart index 5dff415..95656b2 100644 --- a/lib/src/internal/nocodes_internal.dart +++ b/lib/src/internal/nocodes_internal.dart @@ -167,12 +167,16 @@ class NoCodesInternal implements NoCodes { } @override - Future showScreen(String contextKey) async { + Future showScreen(String contextKey, {Map? customVariables}) async { if (Platform.isMacOS) { return; } - - await _invokeMethod(Constants.mShowNoCodesScreen, {Constants.kContextKey: contextKey}); + + final args = { + Constants.kContextKey: contextKey, + if (customVariables != null) Constants.kCustomVariables: customVariables, + }; + await _invokeMethod(Constants.mShowNoCodesScreen, args); } @override diff --git a/lib/src/internal/qonversion_internal.dart b/lib/src/internal/qonversion_internal.dart index 9895c61..92294a6 100644 --- a/lib/src/internal/qonversion_internal.dart +++ b/lib/src/internal/qonversion_internal.dart @@ -420,6 +420,11 @@ class QonversionInternal implements Qonversion { }); } + @override + Future forceSendProperties() async { + await _invokeMethod(Constants.mForceSendProperties); + } + @override Future userProperties() async { final rawResult = await _invokeMethod(Constants.mUserProperties); diff --git a/lib/src/nocodes.dart b/lib/src/nocodes.dart index be001af..5504d96 100644 --- a/lib/src/nocodes.dart +++ b/lib/src/nocodes.dart @@ -92,10 +92,14 @@ abstract class NoCodes { String? contextKey, }); - /// Show No-Codes screen with context key - /// + /// Show No-Codes screen with context key. + /// + /// Optionally pass [customVariables] — a map of custom variables that will be + /// injected into the screen's JavaScript context. Variables are scoped to the + /// provided [contextKey] and only applied to that screen. + /// /// **Platform Support:** iOS and Android. No-op on macOS. - Future showScreen(String contextKey); + Future showScreen(String contextKey, {Map? customVariables}); /// Close No-Codes screen /// diff --git a/lib/src/qonversion.dart b/lib/src/qonversion.dart index 0c8febf..6237e0f 100644 --- a/lib/src/qonversion.dart +++ b/lib/src/qonversion.dart @@ -191,6 +191,11 @@ abstract class Qonversion { /// in the result. Future userProperties(); + /// Force-flushes any pending user property updates to the server immediately. + /// Use this when you need to ensure all previously set properties have been sent + /// before performing an operation that depends on them. + Future forceSendProperties(); + /// iOS only. Does nothing, if called on Android. /// /// On iOS 14.5+, after requesting the app tracking entitlement using ATT, you need to notify Qonversion if tracking is allowed and IDFA is available. diff --git a/macos/qonversion_flutter.podspec b/macos/qonversion_flutter.podspec index 43fabfc..1e645b5 100644 --- a/macos/qonversion_flutter.podspec +++ b/macos/qonversion_flutter.podspec @@ -16,7 +16,7 @@ Pod::Spec.new do |s| s.source_files = 'Classes/**/*' s.dependency 'FlutterMacOS' s.platform = :osx, '10.12' - s.dependency "QonversionSandwich", "7.8.0" + s.dependency "QonversionSandwich", "7.9.0" s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' } s.swift_version = '5.0'