react-native-nami-sdk 3.4.1-dev.202605280043 → 3.4.1-dev.202605300006

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -85,8 +85,8 @@ dependencies {
85
85
  implementation fileTree(dir: 'libs', include: ['*.jar'])
86
86
  implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
87
87
 
88
- playImplementation "com.namiml:sdk-android:3.4.1-dev.202605280043"
89
- amazonImplementation "com.namiml:sdk-amazon:3.4.1-dev.202605280043"
88
+ playImplementation "com.namiml:sdk-android:3.4.1-dev.202605300006"
89
+ amazonImplementation "com.namiml:sdk-amazon:3.4.1-dev.202605300006"
90
90
 
91
91
  implementation "com.facebook.react:react-native:+" // From node_modules
92
92
  coreLibraryDesugaring "com.android.tools:desugar_jdk_libs:2.0.4"
@@ -3,7 +3,12 @@ package com.namiml.reactnative
3
3
  import android.os.Handler
4
4
  import android.os.Looper
5
5
  import android.util.Log
6
- import com.facebook.react.bridge.*
6
+ import com.facebook.react.bridge.Arguments
7
+ import com.facebook.react.bridge.Promise
8
+ import com.facebook.react.bridge.ReactApplicationContext
9
+ import com.facebook.react.bridge.ReactContextBaseJavaModule
10
+ import com.facebook.react.bridge.ReactMethod
11
+ import com.facebook.react.bridge.WritableMap
7
12
  import com.facebook.react.module.annotations.ReactModule
8
13
  import com.facebook.react.modules.core.DeviceEventManagerModule
9
14
  import com.facebook.react.turbomodule.core.interfaces.TurboModule
@@ -20,9 +25,17 @@ class NamiFlowManagerBridgeModule internal constructor(
20
25
 
21
26
  override fun getName(): String = NAME
22
27
 
28
+ @Volatile
29
+ private var eventHandlerActive: Boolean = false
30
+
31
+ @Volatile
32
+ private var stepHandoffActive: Boolean = false
33
+
23
34
  @ReactMethod
24
35
  fun registerStepHandoff() {
36
+ stepHandoffActive = true
25
37
  NamiFlowManager.registerStepHandoff { handoffTag, handoffData ->
38
+ if (!stepHandoffActive) return@registerStepHandoff
26
39
  val payload =
27
40
  Arguments.createMap().apply {
28
41
  putString("handoffTag", handoffTag)
@@ -41,14 +54,26 @@ class NamiFlowManagerBridgeModule internal constructor(
41
54
  }
42
55
  }
43
56
 
57
+ @ReactMethod
58
+ fun unregisterStepHandoff() {
59
+ stepHandoffActive = false
60
+ }
61
+
44
62
  @ReactMethod
45
63
  fun registerEventHandler() {
64
+ eventHandlerActive = true
46
65
  NamiFlowManager.registerEventHandler { data ->
66
+ if (!eventHandlerActive) return@registerEventHandler
47
67
  val payload = Arguments.makeNativeMap(data)
48
68
  sendEvent("FlowEvent", payload)
49
69
  }
50
70
  }
51
71
 
72
+ @ReactMethod
73
+ fun unregisterEventHandler() {
74
+ eventHandlerActive = false
75
+ }
76
+
52
77
  @ReactMethod
53
78
  fun resume() {
54
79
  Handler(Looper.getMainLooper()).postDelayed({
@@ -3,9 +3,11 @@ export interface Spec extends TurboModule {
3
3
  finish(): void;
4
4
  isFlowOpen(): Promise<boolean>;
5
5
  registerStepHandoff(): void;
6
+ unregisterStepHandoff(): void;
6
7
  resume(): void;
7
8
  pause(): void;
8
9
  registerEventHandler(): void;
10
+ unregisterEventHandler(): void;
9
11
  purchaseSuccess(): void;
10
12
  }
11
13
  declare const _default: Spec;
@@ -2,4 +2,4 @@
2
2
  * Auto-generated file. Do not edit manually.
3
3
  * React Native Nami SDK version.
4
4
  */
5
- export declare const NAMI_REACT_NATIVE_VERSION = "3.4.1-dev.202605280043";
5
+ export declare const NAMI_REACT_NATIVE_VERSION = "3.4.1-dev.202605300006";
@@ -10,7 +10,9 @@
10
10
 
11
11
  @interface RCT_EXTERN_MODULE(RNNamiFlowManager, RCTEventEmitter)
12
12
  RCT_EXTERN_METHOD(registerStepHandoff)
13
+ RCT_EXTERN_METHOD(unregisterStepHandoff)
13
14
  RCT_EXTERN_METHOD(registerEventHandler)
15
+ RCT_EXTERN_METHOD(unregisterEventHandler)
14
16
  RCT_EXTERN_METHOD(resume)
15
17
  RCT_EXTERN_METHOD(pause)
16
18
  RCT_EXTERN_METHOD(finish)
@@ -17,11 +17,20 @@ class RNNamiFlowManager: RCTEventEmitter {
17
17
  super.init()
18
18
  }
19
19
 
20
- override class func requiresMainQueueSetup() -> Bool { true }
20
+ override class func requiresMainQueueSetup() -> Bool {
21
+ true
22
+ }
21
23
 
22
24
  private var hasListeners = false
23
- override func startObserving() { hasListeners = true }
24
- override func stopObserving() { hasListeners = false }
25
+ private var eventHandlerActive = false
26
+ private var stepHandoffActive = false
27
+ override func startObserving() {
28
+ hasListeners = true
29
+ }
30
+
31
+ override func stopObserving() {
32
+ hasListeners = false
33
+ }
25
34
 
26
35
  private func safeSend(withName name: String, body: Any?) {
27
36
  guard hasListeners else {
@@ -36,7 +45,9 @@ class RNNamiFlowManager: RCTEventEmitter {
36
45
  }
37
46
 
38
47
  @objc func registerStepHandoff() {
39
- NamiFlowManager.registerStepHandoff { tag, data in
48
+ stepHandoffActive = true
49
+ NamiFlowManager.registerStepHandoff { [weak self] tag, data in
50
+ guard let self = self, self.stepHandoffActive else { return }
40
51
  var payload: [String: Any] = [
41
52
  "handoffTag": tag,
42
53
  ]
@@ -48,12 +59,22 @@ class RNNamiFlowManager: RCTEventEmitter {
48
59
  }
49
60
  }
50
61
 
62
+ @objc func unregisterStepHandoff() {
63
+ stepHandoffActive = false
64
+ }
65
+
51
66
  @objc func registerEventHandler() {
52
- NamiFlowManager.registerEventHandler { payload in
67
+ eventHandlerActive = true
68
+ NamiFlowManager.registerEventHandler { [weak self] payload in
69
+ guard let self = self, self.eventHandlerActive else { return }
53
70
  self.safeSend(withName: "FlowEvent", body: payload)
54
71
  }
55
72
  }
56
73
 
74
+ @objc func unregisterEventHandler() {
75
+ eventHandlerActive = false
76
+ }
77
+
57
78
  @objc func resume() {
58
79
  NamiFlowManager.resume()
59
80
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-nami-sdk",
3
- "version": "3.4.1-dev.202605280043",
3
+ "version": "3.4.1-dev.202605300006",
4
4
  "description": "React Native SDK for Nami - No-code paywall and onboarding flows with A/B testing.",
5
5
  "main": "index.ts",
6
6
  "types": "dist/index.d.ts",
@@ -63,7 +63,7 @@
63
63
  ]
64
64
  },
65
65
  "peerDependencies": {
66
- "@namiml/expo-nami-iap": "3.4.1-dev.202605280043",
66
+ "@namiml/expo-nami-iap": "3.4.1-dev.202605300006",
67
67
  "react": ">=18",
68
68
  "react-native": ">=0.73"
69
69
  },
@@ -21,7 +21,7 @@ Pod::Spec.new do |s|
21
21
  s.requires_arc = true
22
22
  s.swift_version = '5.0' # or your supported version
23
23
 
24
- s.dependency 'Nami', '3.4.1-dev.202605280043'
24
+ s.dependency 'Nami', '3.4.1-dev.202605300006'
25
25
 
26
26
  pod_target_xcconfig = {
27
27
  'DEFINES_MODULE' => 'YES',
@@ -6,9 +6,11 @@ export interface Spec extends TurboModule {
6
6
  isFlowOpen(): Promise<boolean>;
7
7
 
8
8
  registerStepHandoff(): void;
9
+ unregisterStepHandoff(): void;
9
10
  resume(): void;
10
11
  pause(): void;
11
12
  registerEventHandler(): void;
13
+ unregisterEventHandler(): void;
12
14
  purchaseSuccess(): void;
13
15
  }
14
16
 
@@ -38,7 +38,10 @@ export const NamiFlowManager = {
38
38
 
39
39
  RNNamiFlowManager.registerStepHandoff?.();
40
40
 
41
- return () => sub.remove();
41
+ return () => {
42
+ sub.remove();
43
+ RNNamiFlowManager.unregisterStepHandoff?.();
44
+ };
42
45
  },
43
46
 
44
47
  resume: (): void => {
@@ -56,7 +59,10 @@ export const NamiFlowManager = {
56
59
  ): (() => void) => {
57
60
  const sub = emitter.addListener(NamiFlowManagerEvents.FlowEvent, callback);
58
61
  RNNamiFlowManager.registerEventHandler?.();
59
- return () => sub.remove();
62
+ return () => {
63
+ sub.remove();
64
+ RNNamiFlowManager.unregisterEventHandler?.();
65
+ };
60
66
  },
61
67
 
62
68
  finish: (): void => {
@@ -0,0 +1,88 @@
1
+ // Mock react-native BEFORE importing the SDK — `../NamiFlowManager` resolves
2
+ // the native module via TurboModuleRegistry at import time, and the
3
+ // NativeEventEmitter constructor is called at module top-level.
4
+
5
+ const registerStepHandoff = jest.fn();
6
+ const unregisterStepHandoff = jest.fn();
7
+ const registerEventHandler = jest.fn();
8
+ const unregisterEventHandler = jest.fn();
9
+ const finishMock = jest.fn();
10
+ const isFlowOpenMock = jest.fn().mockResolvedValue(false);
11
+ const resumeMock = jest.fn();
12
+ const pauseMock = jest.fn();
13
+
14
+ const subRemove = jest.fn();
15
+ const addListener = jest.fn(() => ({ remove: subRemove }));
16
+
17
+ jest.mock('react-native', () => ({
18
+ TurboModuleRegistry: {
19
+ getEnforcing: jest.fn(() => ({
20
+ registerStepHandoff,
21
+ unregisterStepHandoff,
22
+ registerEventHandler,
23
+ unregisterEventHandler,
24
+ finish: finishMock,
25
+ isFlowOpen: isFlowOpenMock,
26
+ resume: resumeMock,
27
+ pause: pauseMock,
28
+ })),
29
+ },
30
+ NativeModules: {
31
+ RNNamiFlowManager: {
32
+ registerStepHandoff,
33
+ unregisterStepHandoff,
34
+ registerEventHandler,
35
+ unregisterEventHandler,
36
+ },
37
+ },
38
+ NativeEventEmitter: jest.fn().mockImplementation(() => ({
39
+ addListener,
40
+ })),
41
+ }));
42
+
43
+ import { NamiFlowManager } from '../NamiFlowManager';
44
+
45
+ describe('NamiFlowManager (React Native bridge)', () => {
46
+ beforeEach(() => {
47
+ registerStepHandoff.mockClear();
48
+ unregisterStepHandoff.mockClear();
49
+ registerEventHandler.mockClear();
50
+ unregisterEventHandler.mockClear();
51
+ subRemove.mockClear();
52
+ addListener.mockClear();
53
+ });
54
+
55
+ describe('registerStepHandoff', () => {
56
+ it('returns a function and triggers native register', () => {
57
+ const unsubscribe = NamiFlowManager.registerStepHandoff(() => {});
58
+ expect(typeof unsubscribe).toBe('function');
59
+ expect(registerStepHandoff).toHaveBeenCalledTimes(1);
60
+ expect(addListener).toHaveBeenCalledTimes(1);
61
+ });
62
+
63
+ it('returned unsubscribe removes the JS listener AND calls native unregister', () => {
64
+ const unsubscribe = NamiFlowManager.registerStepHandoff(() => {});
65
+ unsubscribe();
66
+
67
+ expect(subRemove).toHaveBeenCalledTimes(1);
68
+ expect(unregisterStepHandoff).toHaveBeenCalledTimes(1);
69
+ });
70
+ });
71
+
72
+ describe('registerEventHandler', () => {
73
+ it('returns a function and triggers native register', () => {
74
+ const unsubscribe = NamiFlowManager.registerEventHandler(() => {});
75
+ expect(typeof unsubscribe).toBe('function');
76
+ expect(registerEventHandler).toHaveBeenCalledTimes(1);
77
+ expect(addListener).toHaveBeenCalledTimes(1);
78
+ });
79
+
80
+ it('returned unsubscribe removes the JS listener AND calls native unregister', () => {
81
+ const unsubscribe = NamiFlowManager.registerEventHandler(() => {});
82
+ unsubscribe();
83
+
84
+ expect(subRemove).toHaveBeenCalledTimes(1);
85
+ expect(unregisterEventHandler).toHaveBeenCalledTimes(1);
86
+ });
87
+ });
88
+ });
package/src/version.ts CHANGED
@@ -2,4 +2,4 @@
2
2
  * Auto-generated file. Do not edit manually.
3
3
  * React Native Nami SDK version.
4
4
  */
5
- export const NAMI_REACT_NATIVE_VERSION = '3.4.1-dev.202605280043';
5
+ export const NAMI_REACT_NATIVE_VERSION = '3.4.1-dev.202605300006';