@primer-io/react-native 2.43.0 → 2.44.0

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.
@@ -133,7 +133,7 @@ dependencies {
133
133
  implementation 'com.facebook.react:react-native:+'
134
134
  implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
135
135
  implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.3"
136
- implementation 'io.primer:android:2.49.0'
136
+ implementation 'io.primer:android:2.50.0'
137
137
  testImplementation 'io.mockk:mockk:1.14.2'
138
138
  testImplementation 'org.junit.jupiter:junit-jupiter-api:5.10.2'
139
139
  testImplementation 'org.junit.jupiter:junit-jupiter-api:5.10.2'
@@ -1,6 +1,7 @@
1
1
  package com.primerioreactnative.datamodels
2
2
 
3
3
  import android.content.Context
4
+ import android.content.res.Configuration
4
5
  import com.primerioreactnative.extensions.toLocale
5
6
  import com.primerioreactnative.extensions.toPrimerDebugOptions
6
7
  import com.primerioreactnative.extensions.toPrimerPaymentMethodOptions
@@ -62,8 +63,10 @@ data class PrimerThemeRN(
62
63
  val colors: ColorThemeRN? = null,
63
64
  val darkModeColors: ColorThemeRN? = null,
64
65
  ) {
65
- fun toPrimerTheme(): PrimerTheme {
66
- val isDarkMode = false
66
+ fun toPrimerTheme(context: Context): PrimerTheme {
67
+ val isDarkMode =
68
+ (context.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK) ==
69
+ Configuration.UI_MODE_NIGHT_YES
67
70
 
68
71
  return PrimerTheme.buildWithDynamicValues(
69
72
  isDarkMode = isDarkMode,
@@ -206,7 +209,7 @@ fun PrimerSettingsRN.toPrimerSettings(context: Context) =
206
209
  paymentHandling = paymentHandling,
207
210
  locale = localeData.toLocale(),
208
211
  paymentMethodOptions = paymentMethodOptions.toPrimerPaymentMethodOptions(context),
209
- uiOptions = uiOptions.toPrimerUIOptions(),
212
+ uiOptions = uiOptions.toPrimerUIOptions(context),
210
213
  debugOptions = debugOptions.toPrimerDebugOptions(),
211
214
  clientSessionCachingEnabled = clientSessionCachingEnabled,
212
215
  apiVersion = when (apiVersion) {
@@ -1,11 +1,12 @@
1
1
  package com.primerioreactnative.extensions
2
2
 
3
+ import android.content.Context
3
4
  import com.primerioreactnative.datamodels.PrimerUIOptionsRN
4
5
  import io.primer.android.data.settings.DismissalMechanism
5
6
  import io.primer.android.ui.settings.PrimerUIOptions
6
7
 
7
8
  @OptIn(kotlin.ExperimentalStdlibApi::class)
8
- internal fun PrimerUIOptionsRN.toPrimerUIOptions() =
9
+ internal fun PrimerUIOptionsRN.toPrimerUIOptions(context: Context) =
9
10
  PrimerUIOptions(
10
11
  isInitScreenEnabled,
11
12
  isSuccessScreenEnabled,
@@ -19,6 +20,6 @@ internal fun PrimerUIOptionsRN.toPrimerUIOptions() =
19
20
  }
20
21
  }
21
22
  }.toList().takeIf { it.isNotEmpty() } ?: listOf(DismissalMechanism.GESTURES),
22
- theme.toPrimerTheme(),
23
+ theme.toPrimerTheme(context),
23
24
  cardFormUIOptions.toPrimerCardFormUIOptions(),
24
25
  )
@@ -1,2 +1,2 @@
1
1
  // swiftlint:disable:next identifier_name
2
- public let PrimerReactNativeSDKVersion = "2.43.0"
2
+ public let PrimerReactNativeSDKVersion = "2.44.0"
@@ -1,12 +1,13 @@
1
1
  "use strict";
2
2
 
3
3
  import { NativeEventEmitter, NativeModules } from 'react-native';
4
- import { eventTypes } from "./Utils/EventType.js";
5
4
  const {
6
5
  RNTPrimerHeadlessUniversalCheckoutKlarnaComponent
7
6
  } = NativeModules;
8
7
  const eventEmitter = new NativeEventEmitter(RNTPrimerHeadlessUniversalCheckoutKlarnaComponent);
9
8
  export class PrimerHeadlessUniversalCheckoutKlarnaManager {
9
+ subscriptions = [];
10
+
10
11
  ///////////////////////////////////////////
11
12
  // Init
12
13
  ///////////////////////////////////////////
@@ -17,6 +18,9 @@ export class PrimerHeadlessUniversalCheckoutKlarnaManager {
17
18
  ///////////////////////////////////////////
18
19
 
19
20
  async provide(props) {
21
+ // Drain any subscriptions left over from a previous provide() on this instance,
22
+ // so consumers who skip explicit cleanUp don't accumulate duplicate listeners.
23
+ this.drainSubscriptions();
20
24
  await this.configureListeners(props);
21
25
  const klarnaComponent = {
22
26
  start: async () => {
@@ -36,6 +40,10 @@ export class PrimerHeadlessUniversalCheckoutKlarnaManager {
36
40
  },
37
41
  finalizePayment: async () => {
38
42
  RNTPrimerHeadlessUniversalCheckoutKlarnaComponent.onFinalizePayment();
43
+ },
44
+ cleanUp: async () => {
45
+ await RNTPrimerHeadlessUniversalCheckoutKlarnaComponent.cleanUp();
46
+ this.drainSubscriptions();
39
47
  }
40
48
  };
41
49
  await RNTPrimerHeadlessUniversalCheckoutKlarnaComponent.configure(props.primerSessionIntent);
@@ -43,34 +51,40 @@ export class PrimerHeadlessUniversalCheckoutKlarnaManager {
43
51
  }
44
52
  async configureListeners(props) {
45
53
  if (props?.onStep) {
46
- this.addListener('onStep', data => {
54
+ const sub = await this.addListener('onStep', data => {
47
55
  props.onStep?.(data);
48
56
  });
57
+ this.subscriptions.push(sub);
49
58
  }
50
59
  if (props?.onInvalid) {
51
- this.addListener('onInvalid', data => {
60
+ const sub = await this.addListener('onInvalid', data => {
52
61
  props.onInvalid?.(data);
53
62
  });
63
+ this.subscriptions.push(sub);
54
64
  }
55
65
  if (props?.onError) {
56
- this.addListener('onError', data => {
66
+ const sub = await this.addListener('onError', data => {
57
67
  props.onError?.(data);
58
68
  });
69
+ this.subscriptions.push(sub);
59
70
  }
60
71
  if (props?.onValid) {
61
- this.addListener('onValid', data => {
72
+ const sub = await this.addListener('onValid', data => {
62
73
  props.onValid?.(data);
63
74
  });
75
+ this.subscriptions.push(sub);
64
76
  }
65
77
  if (props?.onValidating) {
66
- this.addListener('onValidating', data => {
78
+ const sub = await this.addListener('onValidating', data => {
67
79
  props.onValidating?.(data);
68
80
  });
81
+ this.subscriptions.push(sub);
69
82
  }
70
83
  if (props?.onValidationError) {
71
- this.addListener('onValidationError', data => {
84
+ const sub = await this.addListener('onValidationError', data => {
72
85
  props.onValidationError?.(data);
73
86
  });
87
+ this.subscriptions.push(sub);
74
88
  }
75
89
  }
76
90
 
@@ -82,13 +96,23 @@ export class PrimerHeadlessUniversalCheckoutKlarnaManager {
82
96
  return eventEmitter.addListener(eventType, listener);
83
97
  }
84
98
  removeListener(subscription) {
85
- return subscription.remove();
99
+ subscription.remove();
100
+ this.subscriptions = this.subscriptions.filter(sub => sub !== subscription);
86
101
  }
87
102
  removeAllListenersForEvent(eventType) {
88
103
  eventEmitter.removeAllListeners(eventType);
89
104
  }
105
+
106
+ // Routes through per-instance bookkeeping. Avoids the global-nuke approach
107
+ // (eventEmitter.removeAllListeners(eventName)) which on Android would also
108
+ // wipe other modules' listeners for overlapping event names like onError —
109
+ // those modules share the global RCTDeviceEventEmitter.
90
110
  removeAllListeners() {
91
- eventTypes.forEach(eventType => this.removeAllListenersForEvent(eventType));
111
+ this.drainSubscriptions();
112
+ }
113
+ drainSubscriptions() {
114
+ this.subscriptions.forEach(subscription => subscription.remove());
115
+ this.subscriptions = [];
92
116
  }
93
117
  }
94
118
  //# sourceMappingURL=KlarnaManager.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["NativeEventEmitter","NativeModules","eventTypes","RNTPrimerHeadlessUniversalCheckoutKlarnaComponent","eventEmitter","PrimerHeadlessUniversalCheckoutKlarnaManager","constructor","provide","props","configureListeners","klarnaComponent","start","submit","onSetPaymentOptions","paymentOptions","handlePaymentOptionsChange","onFinalizePayment","finalizePayment","configure","primerSessionIntent","onStep","addListener","data","onInvalid","onError","onValid","onValidating","onValidationError","eventType","listener","removeListener","subscription","remove","removeAllListenersForEvent","removeAllListeners","forEach"],"sourceRoot":"../../../../../src","sources":["HeadlessUniversalCheckout/Managers/PaymentMethodManagers/KlarnaManager.ts"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["NativeEventEmitter","NativeModules","RNTPrimerHeadlessUniversalCheckoutKlarnaComponent","eventEmitter","PrimerHeadlessUniversalCheckoutKlarnaManager","subscriptions","constructor","provide","props","drainSubscriptions","configureListeners","klarnaComponent","start","submit","onSetPaymentOptions","paymentOptions","handlePaymentOptionsChange","onFinalizePayment","finalizePayment","cleanUp","configure","primerSessionIntent","onStep","sub","addListener","data","push","onInvalid","onError","onValid","onValidating","onValidationError","eventType","listener","removeListener","subscription","remove","filter","removeAllListenersForEvent","removeAllListeners","forEach"],"sourceRoot":"../../../../../src","sources":["HeadlessUniversalCheckout/Managers/PaymentMethodManagers/KlarnaManager.ts"],"mappings":"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","ignoreList":[]}
@@ -50,8 +50,16 @@ export interface KlarnaComponent {
50
50
  * {@link handlePaymentOptionsChange}.
51
51
  */
52
52
  submit(): Promise<void>;
53
+ /**
54
+ * Tears down the underlying Klarna component and releases the JS event
55
+ * subscriptions registered by {@link KlarnaManager.provide}. Call this after
56
+ * a payment completes (or before initiating another) to allow consecutive
57
+ * Klarna payments within the same app session.
58
+ */
59
+ cleanUp(): Promise<void>;
53
60
  }
54
61
  export declare class PrimerHeadlessUniversalCheckoutKlarnaManager {
62
+ private subscriptions;
55
63
  constructor();
56
64
  provide(props: KlarnaManagerProps): Promise<KlarnaComponent>;
57
65
  private configureListeners;
@@ -59,5 +67,6 @@ export declare class PrimerHeadlessUniversalCheckoutKlarnaManager {
59
67
  removeListener(subscription: EmitterSubscription): void;
60
68
  removeAllListenersForEvent(eventType: EventType): void;
61
69
  removeAllListeners(): void;
70
+ private drainSubscriptions;
62
71
  }
63
72
  //# sourceMappingURL=KlarnaManager.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"KlarnaManager.d.ts","sourceRoot":"","sources":["../../../../../../src/HeadlessUniversalCheckout/Managers/PaymentMethodManagers/KlarnaManager.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACxD,OAAO,KAAK,EACV,kCAAkC,EAClC,0BAA0B,EAC1B,wBAAwB,EACxB,6BAA6B,EAC9B,MAAM,+CAA+C,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC1D,OAAO,KAAK,EACV,oBAAoB,EACpB,4BAA4B,EAC7B,MAAM,qDAAqD,CAAC;AAC7D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2CAA2C,CAAC;AAEnF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AAK1E,MAAM,WAAW,kBAAkB;IACjC,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,iBAAiB,KAAK,IAAI,CAAC;IAC3C,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC;IACvC,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,0BAA0B,CAAC,4BAA4B,CAAC,KAAK,IAAI,CAAC;IACrF,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,wBAAwB,CAAC,4BAA4B,CAAC,KAAK,IAAI,CAAC;IACjF,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,6BAA6B,CAAC,4BAA4B,CAAC,KAAK,IAAI,CAAC;IAC3F,iBAAiB,CAAC,EAAE,CAAC,IAAI,EAAE,kCAAkC,CAAC,4BAA4B,CAAC,KAAK,IAAI,CAAC;CACtG;AAED,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAEvB;;;;;;OAMG;IACH,mBAAmB,CAAC,cAAc,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEzE;;;;;OAKG;IACH,0BAA0B,CAAC,cAAc,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEhF;;;OAGG;IACH,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAEnC;;OAEG;IACH,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjC;;;;OAIG;IACH,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACzB;AAED,qBAAa,4CAA4C;;IAUjD,OAAO,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,eAAe,CAAC;YA2BpD,kBAAkB;IA0C1B,WAAW,CAAC,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAIxG,cAAc,CAAC,YAAY,EAAE,mBAAmB,GAAG,IAAI;IAIvD,0BAA0B,CAAC,SAAS,EAAE,SAAS;IAI/C,kBAAkB;CAGnB"}
1
+ {"version":3,"file":"KlarnaManager.d.ts","sourceRoot":"","sources":["../../../../../../src/HeadlessUniversalCheckout/Managers/PaymentMethodManagers/KlarnaManager.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACxD,OAAO,KAAK,EACV,kCAAkC,EAClC,0BAA0B,EAC1B,wBAAwB,EACxB,6BAA6B,EAC9B,MAAM,+CAA+C,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC1D,OAAO,KAAK,EACV,oBAAoB,EACpB,4BAA4B,EAC7B,MAAM,qDAAqD,CAAC;AAC7D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2CAA2C,CAAC;AACnF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AAK1E,MAAM,WAAW,kBAAkB;IACjC,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,iBAAiB,KAAK,IAAI,CAAC;IAC3C,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC;IACvC,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,0BAA0B,CAAC,4BAA4B,CAAC,KAAK,IAAI,CAAC;IACrF,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,wBAAwB,CAAC,4BAA4B,CAAC,KAAK,IAAI,CAAC;IACjF,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,6BAA6B,CAAC,4BAA4B,CAAC,KAAK,IAAI,CAAC;IAC3F,iBAAiB,CAAC,EAAE,CAAC,IAAI,EAAE,kCAAkC,CAAC,4BAA4B,CAAC,KAAK,IAAI,CAAC;CACtG;AAED,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAEvB;;;;;;OAMG;IACH,mBAAmB,CAAC,cAAc,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEzE;;;;;OAKG;IACH,0BAA0B,CAAC,cAAc,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEhF;;;OAGG;IACH,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAEnC;;OAEG;IACH,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjC;;;;OAIG;IACH,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAExB;;;;;OAKG;IACH,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;AAED,qBAAa,4CAA4C;IACvD,OAAO,CAAC,aAAa,CAA6B;;IAW5C,OAAO,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,eAAe,CAAC;YAkCpD,kBAAkB;IAgD1B,WAAW,CAAC,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAIxG,cAAc,CAAC,YAAY,EAAE,mBAAmB,GAAG,IAAI;IAKvD,0BAA0B,CAAC,SAAS,EAAE,SAAS;IAQ/C,kBAAkB;IAIlB,OAAO,CAAC,kBAAkB;CAI3B"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@primer-io/react-native",
3
- "version": "2.43.0",
3
+ "version": "2.44.0",
4
4
  "description": "Primer SDK for RN",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",
@@ -17,7 +17,7 @@ Pod::Spec.new do |s|
17
17
  s.private_header_files = ['ios/PrimerSwiftInterop.h' ]
18
18
 
19
19
  s.dependency "React-Core"
20
- s.dependency "PrimerSDK", "2.47.0"
20
+ s.dependency "PrimerSDK", "2.48.0"
21
21
 
22
22
  s.pod_target_xcconfig = {
23
23
  "SWIFT_ENABLE_EXPLICIT_MODULES" => "NO"
@@ -12,7 +12,6 @@ import type {
12
12
  KlarnaPaymentValidatableData,
13
13
  } from '../../../models/klarna/KlarnaPaymentCollectableData';
14
14
  import type { KlarnaPaymentStep } from '../../../models/klarna/KlarnaPaymentSteps';
15
- import { eventTypes } from './Utils/EventType';
16
15
  import type { EventType } from './Utils/EventType';
17
16
  import { PrimerSessionIntent } from '../../../models/PrimerSessionIntent';
18
17
 
@@ -70,9 +69,19 @@ export interface KlarnaComponent {
70
69
  * {@link handlePaymentOptionsChange}.
71
70
  */
72
71
  submit(): Promise<void>;
72
+
73
+ /**
74
+ * Tears down the underlying Klarna component and releases the JS event
75
+ * subscriptions registered by {@link KlarnaManager.provide}. Call this after
76
+ * a payment completes (or before initiating another) to allow consecutive
77
+ * Klarna payments within the same app session.
78
+ */
79
+ cleanUp(): Promise<void>;
73
80
  }
74
81
 
75
82
  export class PrimerHeadlessUniversalCheckoutKlarnaManager {
83
+ private subscriptions: EmitterSubscription[] = [];
84
+
76
85
  ///////////////////////////////////////////
77
86
  // Init
78
87
  ///////////////////////////////////////////
@@ -83,6 +92,9 @@ export class PrimerHeadlessUniversalCheckoutKlarnaManager {
83
92
  ///////////////////////////////////////////
84
93
 
85
94
  async provide(props: KlarnaManagerProps): Promise<KlarnaComponent> {
95
+ // Drain any subscriptions left over from a previous provide() on this instance,
96
+ // so consumers who skip explicit cleanUp don't accumulate duplicate listeners.
97
+ this.drainSubscriptions();
86
98
  await this.configureListeners(props);
87
99
 
88
100
  const klarnaComponent: KlarnaComponent = {
@@ -104,6 +116,10 @@ export class PrimerHeadlessUniversalCheckoutKlarnaManager {
104
116
  finalizePayment: async () => {
105
117
  RNTPrimerHeadlessUniversalCheckoutKlarnaComponent.onFinalizePayment();
106
118
  },
119
+ cleanUp: async () => {
120
+ await RNTPrimerHeadlessUniversalCheckoutKlarnaComponent.cleanUp();
121
+ this.drainSubscriptions();
122
+ },
107
123
  };
108
124
  await RNTPrimerHeadlessUniversalCheckoutKlarnaComponent.configure(props.primerSessionIntent);
109
125
  return klarnaComponent;
@@ -111,39 +127,45 @@ export class PrimerHeadlessUniversalCheckoutKlarnaManager {
111
127
 
112
128
  private async configureListeners(props: KlarnaManagerProps): Promise<void> {
113
129
  if (props?.onStep) {
114
- this.addListener('onStep', (data) => {
130
+ const sub = await this.addListener('onStep', (data) => {
115
131
  props.onStep?.(data);
116
132
  });
133
+ this.subscriptions.push(sub);
117
134
  }
118
135
 
119
136
  if (props?.onInvalid) {
120
- this.addListener('onInvalid', (data) => {
137
+ const sub = await this.addListener('onInvalid', (data) => {
121
138
  props.onInvalid?.(data);
122
139
  });
140
+ this.subscriptions.push(sub);
123
141
  }
124
142
 
125
143
  if (props?.onError) {
126
- this.addListener('onError', (data) => {
144
+ const sub = await this.addListener('onError', (data) => {
127
145
  props.onError?.(data);
128
146
  });
147
+ this.subscriptions.push(sub);
129
148
  }
130
149
 
131
150
  if (props?.onValid) {
132
- this.addListener('onValid', (data) => {
151
+ const sub = await this.addListener('onValid', (data) => {
133
152
  props.onValid?.(data);
134
153
  });
154
+ this.subscriptions.push(sub);
135
155
  }
136
156
 
137
157
  if (props?.onValidating) {
138
- this.addListener('onValidating', (data) => {
158
+ const sub = await this.addListener('onValidating', (data) => {
139
159
  props.onValidating?.(data);
140
160
  });
161
+ this.subscriptions.push(sub);
141
162
  }
142
163
 
143
164
  if (props?.onValidationError) {
144
- this.addListener('onValidationError', (data) => {
165
+ const sub = await this.addListener('onValidationError', (data) => {
145
166
  props.onValidationError?.(data);
146
167
  });
168
+ this.subscriptions.push(sub);
147
169
  }
148
170
  }
149
171
 
@@ -156,14 +178,24 @@ export class PrimerHeadlessUniversalCheckoutKlarnaManager {
156
178
  }
157
179
 
158
180
  removeListener(subscription: EmitterSubscription): void {
159
- return subscription.remove();
181
+ subscription.remove();
182
+ this.subscriptions = this.subscriptions.filter((sub) => sub !== subscription);
160
183
  }
161
184
 
162
185
  removeAllListenersForEvent(eventType: EventType) {
163
186
  eventEmitter.removeAllListeners(eventType);
164
187
  }
165
188
 
189
+ // Routes through per-instance bookkeeping. Avoids the global-nuke approach
190
+ // (eventEmitter.removeAllListeners(eventName)) which on Android would also
191
+ // wipe other modules' listeners for overlapping event names like onError —
192
+ // those modules share the global RCTDeviceEventEmitter.
166
193
  removeAllListeners() {
167
- eventTypes.forEach((eventType) => this.removeAllListenersForEvent(eventType));
194
+ this.drainSubscriptions();
195
+ }
196
+
197
+ private drainSubscriptions(): void {
198
+ this.subscriptions.forEach((subscription) => subscription.remove());
199
+ this.subscriptions = [];
168
200
  }
169
201
  }