diff --git a/CHANGELOG.md b/CHANGELOG.md index c972e66..b5e394e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [Unreleased] + +### Changes +- Upgrade Android SDK dependency to v2.14.5 +- Upgrade iOS SDK dependency to v2.14.5 + + ## [2.14.5] - 2025-11-21 ### Changes diff --git a/MindboxSdk.podspec b/MindboxSdk.podspec index 6ff7941..6cd9d95 100644 --- a/MindboxSdk.podspec +++ b/MindboxSdk.podspec @@ -17,6 +17,6 @@ Pod::Spec.new do |s| s.dependency "React-Core" - s.dependency "Mindbox", "2.14.4" - s.dependency "MindboxNotifications", "2.14.4" + s.dependency "Mindbox", "2.14.5" + s.dependency "MindboxNotifications", "2.14.5" end diff --git a/android/build.gradle b/android/build.gradle index 3bc1804..fea7b90 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -126,5 +126,5 @@ dependencies { // noinspection GradleDynamicVersion api 'com.facebook.react:react-native:+' implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" - api 'cloud.mindbox:mobile-sdk:2.14.4' + api 'cloud.mindbox:mobile-sdk:2.14.5' } diff --git a/android/src/main/java/com/mindboxsdk/MindboxSdkLifecycleListener.kt b/android/src/main/java/com/mindboxsdk/MindboxSdkLifecycleListener.kt index 4274e62..7d8798c 100644 --- a/android/src/main/java/com/mindboxsdk/MindboxSdkLifecycleListener.kt +++ b/android/src/main/java/com/mindboxsdk/MindboxSdkLifecycleListener.kt @@ -64,13 +64,13 @@ internal class MindboxSdkLifecycleListener private constructor( application: Application, onReady: (ReactContext) -> Unit ) { - val reactApplication = application.getReactApplication() ?: return val reactInstanceManager = getReactInstanceManager() val wrapperListener = object : ReactInstanceManager.ReactInstanceEventListener { private val called = AtomicBoolean(false) override fun onReactContextInitialized(context: ReactContext) { if (called.compareAndSet(false, true)) { + Mindbox.writeLog("[RN] ReactContext initialized (listener)", Level.INFO) onReady(context) } } @@ -90,14 +90,19 @@ internal class MindboxSdkLifecycleListener private constructor( override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) { if (!isMainActivity(activity)) return - getReactInstanceManager()?.currentReactContext?.let { - onReactContextAvailable(it, activity) - Mindbox.writeLog("[RN] ReactContext already available; skipping listener registration ", Level.INFO) - return - } + val hasConsumedReactContext = AtomicBoolean(false) registerReactContextListener(application) { reactContext -> - onReactContextAvailable(reactContext, activity) + if (hasConsumedReactContext.compareAndSet(false, true)) { + onReactContextAvailable(reactContext, activity) + } + } + + getReactContext()?.let { + if (hasConsumedReactContext.compareAndSet(false, true)) { + onReactContextAvailable(it, activity) + Mindbox.writeLog("[RN] ReactContext available (pre-existing)", Level.INFO) + } } } @@ -129,9 +134,7 @@ internal class MindboxSdkLifecycleListener private constructor( override fun onActivityDestroyed(activity: Activity) { if (!isMainActivity(activity)) return subscriber.onEvent(MindboxSdkLifecycleEvent.ActivityDestroyed(activity)) - getReactInstanceManager() - ?.currentReactContext - ?.removeActivityEventListener(activityEventListener) + getReactContext()?.removeActivityEventListener(activityEventListener) activityEventListener = null } @@ -153,6 +156,26 @@ internal class MindboxSdkLifecycleListener private constructor( private fun Application.getReactApplication() = this as? ReactApplication + private fun getReactContext(): ReactContext? { + return getReactInstanceManagerContext() ?: getReactHostContext(application) + } + + private fun getReactInstanceManagerContext(): ReactContext? { + return getReactInstanceManager()?.currentReactContext + } + + private fun getReactHostContext(application: Application): ReactContext? = + runCatching { + // RN 0.78+ moves reactContext from reactNativeHost.reactInstanceManager to reactHost + val reactApplication = application as ReactApplication + val getHostMethod = reactApplication.javaClass.getMethod("getReactHost") + val reactHost = getHostMethod.invoke(reactApplication) + val getContextMethod = reactHost.javaClass.getMethod("getCurrentReactContext") + getContextMethod.invoke(reactHost) as? ReactContext + }.onFailure { + Mindbox.writeLog("[RN] ReactHost currentReactContext unavailable", Level.INFO) + }.getOrNull() + private fun addReactHostListener( application: Application, wrapperListener: ReactInstanceManager.ReactInstanceEventListener diff --git a/ios/MindboxJsDeliveryBridge.swift b/ios/MindboxJsDeliveryBridge.swift new file mode 100644 index 0000000..dca2790 --- /dev/null +++ b/ios/MindboxJsDeliveryBridge.swift @@ -0,0 +1,10 @@ +import Foundation +import UserNotifications + +@objc(MindboxJsDeliveryBridge) +public final class MindboxJsDeliveryBridge: NSObject { + + @objc public static func emit(_ response: UNNotificationResponse) { + MindboxJsDelivery.emitEvent(response) + } +} diff --git a/ios/MindboxSdk.swift b/ios/MindboxSdk.swift index 49a39a3..8779d91 100644 --- a/ios/MindboxSdk.swift +++ b/ios/MindboxSdk.swift @@ -1,6 +1,5 @@ import Mindbox import MindboxLogger -import CoreFoundation enum CustomError: Error { case tokenAPNSisNull diff --git a/ios/MindboxSdk.xcodeproj/project.pbxproj b/ios/MindboxSdk.xcodeproj/project.pbxproj index ab70bfd..4fa4356 100644 --- a/ios/MindboxSdk.xcodeproj/project.pbxproj +++ b/ios/MindboxSdk.xcodeproj/project.pbxproj @@ -8,6 +8,7 @@ /* Begin PBXBuildFile section */ 61249CFA2719673B00FC4033 /* MindboxJsDelivery.m in Sources */ = {isa = PBXBuildFile; fileRef = 61249CF92719673B00FC4033 /* MindboxJsDelivery.m */; }; + D0F7B0012B1C4A1A00A1B2C3 /* MindboxJsDeliveryBridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0F7B0002B1C4A1A00A1B2C3 /* MindboxJsDeliveryBridge.swift */; }; F4FF95D7245B92E800C19C63 /* MindboxSdk.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4FF95D6245B92E800C19C63 /* MindboxSdk.swift */; }; /* End PBXBuildFile section */ @@ -28,6 +29,7 @@ 61249CF82719673B00FC4033 /* MindboxJsDelivery.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MindboxJsDelivery.h; sourceTree = ""; }; 61249CF92719673B00FC4033 /* MindboxJsDelivery.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MindboxJsDelivery.m; sourceTree = ""; }; B3E7B5891CC2AC0600A0062D /* MindboxSdk.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MindboxSdk.m; sourceTree = ""; }; + D0F7B0002B1C4A1A00A1B2C3 /* MindboxJsDeliveryBridge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MindboxJsDeliveryBridge.swift; sourceTree = ""; }; F4FF95D5245B92E700C19C63 /* MindboxSdk-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "MindboxSdk-Bridging-Header.h"; sourceTree = ""; }; F4FF95D6245B92E800C19C63 /* MindboxSdk.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MindboxSdk.swift; sourceTree = ""; }; /* End PBXFileReference section */ @@ -56,6 +58,7 @@ children = ( 61249CF82719673B00FC4033 /* MindboxJsDelivery.h */, 61249CF92719673B00FC4033 /* MindboxJsDelivery.m */, + D0F7B0002B1C4A1A00A1B2C3 /* MindboxJsDeliveryBridge.swift */, F4FF95D6245B92E800C19C63 /* MindboxSdk.swift */, B3E7B5891CC2AC0600A0062D /* MindboxSdk.m */, F4FF95D5245B92E700C19C63 /* MindboxSdk-Bridging-Header.h */, @@ -121,6 +124,7 @@ buildActionMask = 2147483647; files = ( 61249CFA2719673B00FC4033 /* MindboxJsDelivery.m in Sources */, + D0F7B0012B1C4A1A00A1B2C3 /* MindboxJsDeliveryBridge.swift in Sources */, F4FF95D7245B92E800C19C63 /* MindboxSdk.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/package.json b/package.json index a867cbf..516d138 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mindbox-sdk", "version": "2.14.5", - "target-version": "2.14.5", + "target-version": "2.14.6", "description": "SDK for integration React Native mobile apps with Mindbox", "main": "lib/commonjs/index", "module": "lib/module/index",