react-native-klarna-inapp-sdk 2.4.2 → 2.4.3

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.
package/README.md CHANGED
@@ -27,8 +27,8 @@ This repository also includes a test application that you can use to see how it
27
27
 
28
28
  ### Documentations
29
29
 
30
- * [Overview](https://docs.klarna.com/mobile-sdk/)
31
- * [Using the Mobile SDK on React Native](https://docs.klarna.com/mobile-sdk/reactnative/)
30
+ * [Overview](https://docs.klarna.com/payments/mobile-payments/before-you-start/introduction-mobile-integrations/)
31
+ * [Using the Mobile SDK on React Native](https://docs.klarna.com/payments/mobile-payments/integrate-with-mobile-sdk/reactnative/native-view/)
32
32
 
33
33
  ## Getting started
34
34
 
@@ -10,15 +10,28 @@ import com.klarna.mobile.sdk.api.component.KlarnaComponent;
10
10
 
11
11
  public class KlarnaCheckoutViewEventHandler implements KlarnaEventHandler {
12
12
 
13
+ public interface OnLoadListener {
14
+ void onLoad(KlarnaCheckoutView klarnaCheckoutView);
15
+ }
16
+
17
+ private static final String EVENT_LOAD = "load";
13
18
  private final KlarnaCheckoutViewEventSender klarnaCheckoutViewEventSender;
19
+ private final OnLoadListener onLoadListener;
14
20
 
15
- public KlarnaCheckoutViewEventHandler(KlarnaCheckoutViewEventSender klarnaCheckoutViewEventSender) {
21
+ public KlarnaCheckoutViewEventHandler(@NonNull KlarnaCheckoutViewEventSender klarnaCheckoutViewEventSender, OnLoadListener onLoadListener) {
16
22
  this.klarnaCheckoutViewEventSender = klarnaCheckoutViewEventSender;
23
+ this.onLoadListener = onLoadListener;
17
24
  }
18
25
 
19
26
  @Override
20
27
  public void onEvent(@NonNull KlarnaComponent klarnaComponent, @NonNull KlarnaProductEvent klarnaProductEvent) {
21
28
  if (klarnaComponent instanceof KlarnaCheckoutView) {
29
+ String eventName = klarnaProductEvent.getAction();
30
+ if (EVENT_LOAD.equalsIgnoreCase(eventName)) {
31
+ if (onLoadListener != null) {
32
+ onLoadListener.onLoad((KlarnaCheckoutView) klarnaComponent);
33
+ }
34
+ }
22
35
  klarnaCheckoutViewEventSender.sendKlarnaProductEvent((KlarnaCheckoutView) klarnaComponent, klarnaProductEvent);
23
36
  }
24
37
  }
@@ -13,7 +13,6 @@ import com.klarna.mobile.sdk.reactnative.common.event.KlarnaEventHandlerEventsUt
13
13
  import com.klarna.mobile.sdk.reactnative.common.ui.ResizeObserverWrapperView;
14
14
  import com.klarna.mobile.sdk.reactnative.common.util.ArgumentsUtil;
15
15
 
16
- import java.lang.ref.WeakReference;
17
16
  import java.util.Arrays;
18
17
  import java.util.Collection;
19
18
  import java.util.HashMap;
@@ -24,7 +23,7 @@ public class KlarnaCheckoutViewEventSender extends ComponentEventSender<ResizeOb
24
23
  private static final String EVENT_NAME_ON_RESIZED = "onResized";
25
24
  private static final String EVENT_NAME_ON_CHECKOUT_VIEW_READY = "onCheckoutViewReady";
26
25
 
27
- KlarnaCheckoutViewEventSender(@NonNull final Map<WeakReference<ResizeObserverWrapperView<KlarnaCheckoutView>>, EventDispatcher> viewToDispatcher) {
26
+ KlarnaCheckoutViewEventSender(@NonNull final Map<ResizeObserverWrapperView<KlarnaCheckoutView>, EventDispatcher> viewToDispatcher) {
28
27
  super(viewToDispatcher);
29
28
  }
30
29
 
@@ -19,38 +19,56 @@ import com.klarna.mobile.sdk.reactnative.common.WebViewResizeObserver;
19
19
  import com.klarna.mobile.sdk.reactnative.common.ui.ResizeObserverWrapperView;
20
20
  import com.klarna.mobile.sdk.reactnative.spec.RNKlarnaCheckoutViewSpec;
21
21
 
22
- import java.lang.ref.WeakReference;
23
- import java.util.HashMap;
24
22
  import java.util.Map;
25
23
  import java.util.Objects;
24
+ import java.util.WeakHashMap;
26
25
 
27
26
  public class KlarnaCheckoutViewManager extends RNKlarnaCheckoutViewSpec<ResizeObserverWrapperView<KlarnaCheckoutView>> {
28
27
 
28
+ private static final int MAX_SET_SNIPPET_RETRIES = 3;
29
29
  public static final String KLARNA_CHECKOUT_VIEW_REACT_CLASS = "RNKlarnaCheckoutView";
30
-
31
30
  // Commands that can be triggered from RN
32
31
  public static final String COMMAND_SET_SNIPPET = "setSnippet";
33
32
  public static final String COMMAND_SUSPEND = "suspend";
34
33
  public static final String COMMAND_RESUME = "resume";
35
34
 
36
35
  private final ReactApplicationContext reactAppContext;
37
-
38
36
  /**
39
37
  * Store a map of views to event dispatchers so we send up events via the right views.
40
38
  */
41
- private final Map<WeakReference<ResizeObserverWrapperView<KlarnaCheckoutView>>, EventDispatcher> viewToDispatcher;
39
+ private final Map<ResizeObserverWrapperView<KlarnaCheckoutView>, EventDispatcher> viewToDispatcher;
40
+ private final Map<KlarnaCheckoutView, ResizeObserverWrapperView<KlarnaCheckoutView>> checkoutViewToResizeObserverWrapperMap = new WeakHashMap<>();
41
+ private final Map<ResizeObserverWrapperView<KlarnaCheckoutView>, Integer> setSnippetRetriesMap = new WeakHashMap<>();
42
+ private final Map<ResizeObserverWrapperView<KlarnaCheckoutView>, String> snippetMap = new WeakHashMap<>();
42
43
 
43
44
  private final KlarnaCheckoutViewEventSender eventSender;
44
45
  private final KlarnaCheckoutViewEventHandler eventHandler;
45
- private Runnable javascriptInterfaceInjectionRunnable;
46
46
  private final Handler handler = new Handler(Looper.getMainLooper());
47
+ private Runnable javascriptInterfaceInjectionRunnable;
47
48
 
48
49
  public KlarnaCheckoutViewManager(ReactApplicationContext reactApplicationContext) {
49
50
  super();
50
- viewToDispatcher = new HashMap<>();
51
+ viewToDispatcher = new WeakHashMap<>();
51
52
  reactAppContext = reactApplicationContext;
52
53
  eventSender = new KlarnaCheckoutViewEventSender(viewToDispatcher);
53
- eventHandler = new KlarnaCheckoutViewEventHandler(eventSender);
54
+ eventHandler = new KlarnaCheckoutViewEventHandler(eventSender, klarnaCheckoutView -> {
55
+ ResizeObserverWrapperView<KlarnaCheckoutView> resizeObserverWrapperView =
56
+ checkoutViewToResizeObserverWrapperMap.get(klarnaCheckoutView);
57
+ if (resizeObserverWrapperView == null) {
58
+ return;
59
+ }
60
+ Integer retries = setSnippetRetriesMap.getOrDefault(resizeObserverWrapperView, 0);
61
+ if (retries == null || retries >= MAX_SET_SNIPPET_RETRIES) {
62
+ return;
63
+ }
64
+ String snippet = snippetMap.get(resizeObserverWrapperView);
65
+ handler.postDelayed(() -> {
66
+ if (klarnaCheckoutView != null && klarnaCheckoutView.getHeight() == 0) {
67
+ setSnippet(resizeObserverWrapperView, snippet);
68
+ setSnippetRetriesMap.put(resizeObserverWrapperView, retries + 1);
69
+ }
70
+ }, 500);
71
+ });
54
72
  }
55
73
 
56
74
  @NonNull
@@ -65,9 +83,11 @@ public class KlarnaCheckoutViewManager extends RNKlarnaCheckoutViewSpec<ResizeOb
65
83
  KlarnaCheckoutView klarnaCheckoutView = new KlarnaCheckoutView(reactAppContext.getCurrentActivity(), null, 0, eventHandler);
66
84
  ResizeObserverWrapperView<KlarnaCheckoutView> view = new ResizeObserverWrapperView<>(reactAppContext, null, klarnaCheckoutView);
67
85
 
86
+ checkoutViewToResizeObserverWrapperMap.put(klarnaCheckoutView, view);
87
+
68
88
  // Each view has its own event dispatcher.
69
89
  EventDispatcher eventDispatcher = UIManagerHelper.getEventDispatcherForReactTag((ReactContext) view.getContext(), view.getId());
70
- viewToDispatcher.put(new WeakReference<>(view), eventDispatcher);
90
+ viewToDispatcher.put(view, eventDispatcher);
71
91
 
72
92
  view.initiateWebViewResizeObserver(WebViewResizeObserver.TargetElement.CHECKOUT_CONTAINER, (resizeObserverWrapperView, newHeight) -> {
73
93
  if (resizeObserverWrapperView == null || eventDispatcher == null) {
@@ -152,6 +172,8 @@ public class KlarnaCheckoutViewManager extends RNKlarnaCheckoutViewSpec<ResizeOb
152
172
  return;
153
173
  }
154
174
 
175
+ snippetMap.put(view, snippet);
176
+
155
177
  klarnaCheckoutView.setSnippet(snippet);
156
178
  view.addJavascriptInterfaceToWebView();
157
179
 
@@ -12,14 +12,13 @@ import com.facebook.react.uimanager.UIManagerHelper;
12
12
  import com.facebook.react.uimanager.events.EventDispatcher;
13
13
  import com.klarna.mobile.sdk.reactnative.common.ui.WrapperView;
14
14
 
15
- import java.lang.ref.WeakReference;
16
15
  import java.util.Collection;
17
16
  import java.util.Map;
18
17
 
19
18
  public abstract class ComponentEventSender<T extends View> {
20
- private final Map<WeakReference<T>, EventDispatcher> viewToDispatcher;
19
+ private final Map<T, EventDispatcher> viewToDispatcher;
21
20
 
22
- protected ComponentEventSender(@NonNull final Map<WeakReference<T>, EventDispatcher> viewToDispatcher) {
21
+ protected ComponentEventSender(@NonNull final Map<T, EventDispatcher> viewToDispatcher) {
23
22
  this.viewToDispatcher = viewToDispatcher;
24
23
  }
25
24
 
@@ -50,15 +49,14 @@ public abstract class ComponentEventSender<T extends View> {
50
49
  if (view == null) {
51
50
  return null;
52
51
  }
53
- for (WeakReference<T> reference : viewToDispatcher.keySet()) {
54
- T viewReference = reference.get();
55
- if (viewReference != null && viewReference == view) {
56
- return viewReference;
52
+ for (T reference : viewToDispatcher.keySet()) {
53
+ if (reference != null && reference == view) {
54
+ return reference;
57
55
  }
58
- if (viewReference instanceof WrapperView) {
59
- View wrappedView = ((WrapperView) viewReference).getView();
56
+ if (reference instanceof WrapperView) {
57
+ View wrappedView = ((WrapperView) reference).getView();
60
58
  if (wrappedView == view) {
61
- return viewReference;
59
+ return reference;
62
60
  }
63
61
  }
64
62
  }
@@ -1,7 +1,10 @@
1
1
  package com.klarna.mobile.sdk.reactnative.common.ui;
2
2
 
3
3
  import android.content.Context;
4
+ import android.os.Handler;
5
+ import android.os.Looper;
4
6
  import android.util.AttributeSet;
7
+ import android.util.TypedValue;
5
8
  import android.view.View;
6
9
  import android.view.ViewGroup;
7
10
  import android.webkit.WebView;
@@ -23,6 +26,7 @@ public class ResizeObserverWrapperView<T extends ViewGroup> extends WrapperView<
23
26
  private WebViewResizeObserver webViewResizeObserver;
24
27
  private WebViewResizeObserver.WebViewResizeObserverCallback webViewResizeObserverCallback;
25
28
  private OnResizedListener<T> onResizedListener;
29
+ private final Handler handler = new Handler(Looper.getMainLooper());
26
30
 
27
31
  public ResizeObserverWrapperView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
28
32
  super(context, attrs, defStyleAttr);
@@ -43,12 +47,36 @@ public class ResizeObserverWrapperView<T extends ViewGroup> extends WrapperView<
43
47
  OnResizedListener<T> listener = onResizedListenerWeakReference.get();
44
48
  if (listener != null) {
45
49
  listener.onResized(ResizeObserverWrapperView.this, value);
50
+ int height = convertDpToPx(value);
51
+ for (int i = 0; i < getChildCount(); i++) {
52
+ View view = getChildAt(i);
53
+ setViewHeight(view, height);
54
+ }
46
55
  }
47
56
  }
48
57
  };
49
58
  this.webViewResizeObserver = new WebViewResizeObserver(webViewResizeObserverCallback, targetElement);
50
59
  }
51
60
 
61
+ private void setViewHeight(View view, int heightInPx) {
62
+ if (view == null || heightInPx < 0) {
63
+ return;
64
+ }
65
+ handler.post(() -> {
66
+ ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
67
+ if (layoutParams != null) {
68
+ layoutParams.height = heightInPx;
69
+ } else {
70
+ layoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, heightInPx);
71
+ }
72
+ view.setLayoutParams(layoutParams);
73
+ });
74
+ }
75
+
76
+ private int convertDpToPx(int value) {
77
+ return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, value, getResources().getDisplayMetrics());
78
+ }
79
+
52
80
  public void addJavascriptInterfaceToWebView() {
53
81
  WebView webView = findWebView(getView());
54
82
  if (webView != null && webViewResizeObserver != null) {
@@ -7,7 +7,6 @@ import androidx.test.core.app.ApplicationProvider;
7
7
  import com.facebook.react.bridge.NativeModule;
8
8
  import com.facebook.react.bridge.ReactApplicationContext;
9
9
  import com.facebook.react.uimanager.ViewManager;
10
- import com.klarna.mobile.sdk.reactnative.KlarnaMobileSDKPackage;
11
10
  import com.klarna.mobile.sdk.reactnative.checkout.KlarnaCheckoutViewManager;
12
11
  import com.klarna.mobile.sdk.reactnative.payments.KlarnaPaymentViewManager;
13
12
  import com.klarna.mobile.sdk.reactnative.spec.RNKlarnaSignInModuleSpec;
@@ -17,6 +16,7 @@ import org.junit.Assert;
17
16
  import org.junit.Before;
18
17
  import org.junit.Test;
19
18
  import org.junit.runner.RunWith;
19
+ import org.mockito.Mockito;
20
20
  import org.robolectric.RobolectricTestRunner;
21
21
 
22
22
  import java.util.List;
@@ -30,7 +30,8 @@ public class KlarnaMobileSDKPackageTest {
30
30
  @Before
31
31
  public void setup() {
32
32
  application = ApplicationProvider.getApplicationContext();
33
- reactContext = new ReactApplicationContext(application);
33
+ reactContext = Mockito.mock(ReactApplicationContext.class);
34
+ Mockito.when(reactContext.getApplicationContext()).thenAnswer(invocation -> application);
34
35
  }
35
36
 
36
37
  @Test
@@ -16,7 +16,6 @@ import org.mockito.MockedStatic;
16
16
  import org.mockito.Mockito;
17
17
  import org.mockito.junit.MockitoJUnitRunner;
18
18
 
19
- import java.lang.ref.WeakReference;
20
19
  import java.util.Arrays;
21
20
  import java.util.Collection;
22
21
  import java.util.HashMap;
@@ -30,14 +29,14 @@ public class ComponentEventSenderTest {
30
29
  private TestEventSender testEventSender;
31
30
  private View view;
32
31
  private EventDispatcher eventDispatcher;
33
- private Map<WeakReference<View>, EventDispatcher> viewToDispatcher;
32
+ private Map<View, EventDispatcher> viewToDispatcher;
34
33
 
35
34
  @Before
36
35
  public void setUp() {
37
36
  view = Mockito.mock(View.class);
38
37
  eventDispatcher = Mockito.mock(EventDispatcher.class);
39
38
  viewToDispatcher = new HashMap<>() {{
40
- put(new WeakReference<>(view), eventDispatcher);
39
+ put(view, eventDispatcher);
41
40
  }};
42
41
  testEventSender = new TestEventSender(viewToDispatcher);
43
42
 
@@ -76,7 +75,7 @@ public class ComponentEventSenderTest {
76
75
  }
77
76
 
78
77
  private class TestEventSender extends ComponentEventSender<View> {
79
- public TestEventSender(Map<WeakReference<View>, EventDispatcher> viewToDispatcher) {
78
+ public TestEventSender(Map<View, EventDispatcher> viewToDispatcher) {
80
79
  super(viewToDispatcher);
81
80
  }
82
81
 
@@ -27,7 +27,6 @@ import org.junit.Test;
27
27
  import org.junit.runner.RunWith;
28
28
  import org.mockito.MockedStatic;
29
29
  import org.mockito.Mockito;
30
- import org.mockito.junit.MockitoJUnitRunner;
31
30
  import org.robolectric.RobolectricTestRunner;
32
31
 
33
32
  import java.util.Collections;
@@ -42,7 +41,8 @@ public class KlarnaPaymentViewManagerTest {
42
41
  @Before
43
42
  public void setup() {
44
43
  Application application = ApplicationProvider.getApplicationContext();
45
- ReactApplicationContext reactContext = new ReactApplicationContext(application);
44
+ ReactApplicationContext reactContext = Mockito.mock(ReactApplicationContext.class);
45
+ Mockito.when(reactContext.getApplicationContext()).thenAnswer(invocation -> application);
46
46
 
47
47
  manager = new KlarnaPaymentViewManager(reactContext);
48
48
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "react-native-klarna-inapp-sdk",
3
3
  "title": "Klarna Mobile SDK React Native",
4
- "version": "2.4.2",
4
+ "version": "2.4.3",
5
5
  "description": "This library wraps Klarna Mobile SDK and exposes its functionality as React Native components.",
6
6
  "main": "lib/commonjs/index",
7
7
  "module": "lib/module/index",
@@ -105,6 +105,13 @@
105
105
  "jsSrcsDir": "src/specs",
106
106
  "android": {
107
107
  "javaPackageName": "com.klarna.mobile.sdk.reactnative"
108
+ },
109
+ "ios": {
110
+ "componentProvider": {
111
+ "RNKlarnaStandaloneWebView": "KlarnaStandaloneWebViewWrapper",
112
+ "RNKlarnaCheckoutView": "KlarnaCheckoutViewWrapper",
113
+ "RNKlarnaPaymentView": "PaymentViewWrapper"
114
+ }
108
115
  }
109
116
  }
110
117
  }