@deuna/react-native-sdk 1.0.3 → 1.0.6
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/lib/module/DeunaSDK.js +87 -78
- package/lib/module/DeunaSDK.js.map +1 -1
- package/lib/module/components/DeunaWidget.js +27 -25
- package/lib/module/components/DeunaWidget.js.map +1 -1
- package/lib/module/components/ExternalUrlWebView.js +56 -0
- package/lib/module/components/ExternalUrlWebView.js.map +1 -0
- package/lib/module/controllers/BaseWebViewController.js +59 -23
- package/lib/module/controllers/BaseWebViewController.js.map +1 -1
- package/lib/module/controllers/ElementsWidgetController.js +2 -3
- package/lib/module/controllers/ElementsWidgetController.js.map +1 -1
- package/lib/module/controllers/{OpenInNewTabController.js → ExternalUrlController.js} +4 -4
- package/lib/module/controllers/ExternalUrlController.js.map +1 -0
- package/lib/module/controllers/PaymentWidgetController.js +2 -2
- package/lib/module/controllers/PaymentWidgetController.js.map +1 -1
- package/lib/module/helpers/Completer.js +2 -2
- package/lib/module/helpers/Completer.js.map +1 -1
- package/lib/module/helpers/CrossPlatformBrowser.js +51 -0
- package/lib/module/helpers/CrossPlatformBrowser.js.map +1 -0
- package/lib/module/helpers/ExternalUrlHelper.js +96 -0
- package/lib/module/helpers/ExternalUrlHelper.js.map +1 -0
- package/lib/module/helpers/ViewManager.js +32 -0
- package/lib/module/helpers/ViewManager.js.map +1 -0
- package/lib/module/helpers/{getController.js → buildDeunaWidgetController.js} +20 -10
- package/lib/module/helpers/buildDeunaWidgetController.js.map +1 -0
- package/lib/module/helpers/getSubmitStrategy.js +1 -1
- package/lib/module/helpers/getSubmitStrategy.js.map +1 -1
- package/lib/module/interfaces/constants.js +1 -0
- package/lib/module/interfaces/constants.js.map +1 -1
- package/lib/module/interfaces/types.js.map +1 -1
- package/lib/module/types/base.js.map +1 -1
- package/lib/module/types/envs.js +48 -0
- package/lib/module/types/envs.js.map +1 -0
- package/lib/module/types/fraudProviders.js +4 -0
- package/lib/module/types/fraudProviders.js.map +1 -0
- package/lib/module/types/helpers/buildElementsLink.js +15 -6
- package/lib/module/types/helpers/buildElementsLink.js.map +1 -1
- package/lib/module/types/helpers/buildPaymentLink.js +7 -3
- package/lib/module/types/helpers/buildPaymentLink.js.map +1 -1
- package/lib/module/types/helpers/buildVoucherLink.js +3 -1
- package/lib/module/types/helpers/buildVoucherLink.js.map +1 -1
- package/lib/module/types/helpers/constants.js +4 -0
- package/lib/module/types/helpers/constants.js.map +1 -0
- package/lib/module/types/helpers/urlConfig.js +1 -1
- package/lib/module/types/helpers/urlConfig.js.map +1 -1
- package/lib/module/types/utils/addSearchParamWhen.js +8 -0
- package/lib/module/types/utils/addSearchParamWhen.js.map +1 -0
- package/lib/typescript/deuna-sdk-react-native/src/DeunaSDK.d.ts +9 -11
- package/lib/typescript/deuna-sdk-react-native/src/DeunaSDK.d.ts.map +1 -1
- package/lib/typescript/deuna-sdk-react-native/src/components/DeunaWidget.d.ts.map +1 -1
- package/lib/typescript/deuna-sdk-react-native/src/components/ExternalUrlWebView.d.ts +7 -0
- package/lib/typescript/deuna-sdk-react-native/src/components/ExternalUrlWebView.d.ts.map +1 -0
- package/lib/typescript/deuna-sdk-react-native/src/controllers/BaseWebViewController.d.ts +9 -7
- package/lib/typescript/deuna-sdk-react-native/src/controllers/BaseWebViewController.d.ts.map +1 -1
- package/lib/typescript/deuna-sdk-react-native/src/controllers/ElementsWidgetController.d.ts.map +1 -1
- package/lib/typescript/deuna-sdk-react-native/src/controllers/{OpenInNewTabController.d.ts → ExternalUrlController.d.ts} +2 -2
- package/lib/typescript/deuna-sdk-react-native/src/controllers/ExternalUrlController.d.ts.map +1 -0
- package/lib/typescript/deuna-sdk-react-native/src/helpers/CrossPlatformBrowser.d.ts +25 -0
- package/lib/typescript/deuna-sdk-react-native/src/helpers/CrossPlatformBrowser.d.ts.map +1 -0
- package/lib/typescript/deuna-sdk-react-native/src/helpers/ExternalUrlHelper.d.ts +48 -0
- package/lib/typescript/deuna-sdk-react-native/src/helpers/ExternalUrlHelper.d.ts.map +1 -0
- package/lib/typescript/deuna-sdk-react-native/src/helpers/ViewManager.d.ts +19 -0
- package/lib/typescript/deuna-sdk-react-native/src/helpers/ViewManager.d.ts.map +1 -0
- package/lib/typescript/deuna-sdk-react-native/src/helpers/{getController.d.ts → buildDeunaWidgetController.d.ts} +4 -2
- package/lib/typescript/deuna-sdk-react-native/src/helpers/buildDeunaWidgetController.d.ts.map +1 -0
- package/lib/typescript/deuna-sdk-react-native/src/interfaces/constants.d.ts +1 -0
- package/lib/typescript/deuna-sdk-react-native/src/interfaces/constants.d.ts.map +1 -1
- package/lib/typescript/deuna-sdk-react-native/src/interfaces/types.d.ts +4 -0
- package/lib/typescript/deuna-sdk-react-native/src/interfaces/types.d.ts.map +1 -1
- package/lib/typescript/deuna-sdk-react-native/src/types/base.d.ts +2 -0
- package/lib/typescript/deuna-sdk-react-native/src/types/base.d.ts.map +1 -1
- package/lib/typescript/deuna-sdk-react-native/src/types/envs.d.ts +45 -0
- package/lib/typescript/deuna-sdk-react-native/src/types/envs.d.ts.map +1 -0
- package/lib/typescript/deuna-sdk-react-native/src/types/fraudProviders.d.ts +68 -0
- package/lib/typescript/deuna-sdk-react-native/src/types/fraudProviders.d.ts.map +1 -0
- package/lib/typescript/deuna-sdk-react-native/src/types/helpers/buildElementsLink.d.ts +15 -0
- package/lib/typescript/deuna-sdk-react-native/src/types/helpers/buildElementsLink.d.ts.map +1 -1
- package/lib/typescript/deuna-sdk-react-native/src/types/helpers/buildPaymentLink.d.ts.map +1 -1
- package/lib/typescript/deuna-sdk-react-native/src/types/helpers/buildVoucherLink.d.ts.map +1 -1
- package/lib/typescript/deuna-sdk-react-native/src/types/helpers/constants.d.ts +2 -0
- package/lib/typescript/deuna-sdk-react-native/src/types/helpers/constants.d.ts.map +1 -0
- package/lib/typescript/deuna-sdk-react-native/src/types/helpers/urlConfig.d.ts +1 -0
- package/lib/typescript/deuna-sdk-react-native/src/types/helpers/urlConfig.d.ts.map +1 -1
- package/lib/typescript/deuna-sdk-react-native/src/types/interfaces/callbacks.d.ts +8 -0
- package/lib/typescript/deuna-sdk-react-native/src/types/interfaces/callbacks.d.ts.map +1 -1
- package/lib/typescript/deuna-sdk-react-native/src/types/interfaces/initWidgetBase.d.ts +2 -0
- package/lib/typescript/deuna-sdk-react-native/src/types/interfaces/initWidgetBase.d.ts.map +1 -1
- package/lib/typescript/deuna-sdk-react-native/src/types/utils/addSearchParamWhen.d.ts +3 -0
- package/lib/typescript/deuna-sdk-react-native/src/types/utils/addSearchParamWhen.d.ts.map +1 -0
- package/package.json +3 -1
- package/src/DeunaSDK.ts +103 -90
- package/src/components/DeunaWidget.tsx +38 -35
- package/src/components/ExternalUrlWebView.tsx +65 -0
- package/src/controllers/BaseWebViewController.ts +70 -29
- package/src/controllers/ElementsWidgetController.ts +2 -3
- package/src/controllers/{OpenInNewTabController.ts → ExternalUrlController.ts} +3 -3
- package/src/controllers/PaymentWidgetController.ts +2 -2
- package/src/helpers/Completer.ts +2 -2
- package/src/helpers/CrossPlatformBrowser.ts +49 -0
- package/src/helpers/ExternalUrlHelper.ts +118 -0
- package/src/helpers/ViewManager.ts +45 -0
- package/src/helpers/{getController.ts → buildDeunaWidgetController.ts} +41 -12
- package/src/helpers/getSubmitStrategy.ts +1 -1
- package/src/interfaces/constants.ts +2 -0
- package/src/interfaces/types.ts +4 -0
- package/src/types/base.ts +2 -0
- package/src/types/envs.ts +50 -0
- package/src/types/fraudProviders.ts +98 -0
- package/src/types/helpers/buildElementsLink.ts +19 -11
- package/src/types/helpers/buildPaymentLink.ts +7 -2
- package/src/types/helpers/buildVoucherLink.ts +2 -0
- package/src/types/helpers/constants.ts +1 -0
- package/src/types/helpers/urlConfig.ts +3 -1
- package/src/types/interfaces/callbacks.ts +10 -1
- package/src/types/interfaces/initWidgetBase.ts +2 -0
- package/src/types/utils/addSearchParamWhen.ts +11 -0
- package/lib/module/components/NewTabWebView.js +0 -56
- package/lib/module/components/NewTabWebView.js.map +0 -1
- package/lib/module/controllers/OpenInNewTabController.js.map +0 -1
- package/lib/module/helpers/getController.js.map +0 -1
- package/lib/typescript/deuna-sdk-react-native/src/components/NewTabWebView.d.ts +0 -7
- package/lib/typescript/deuna-sdk-react-native/src/components/NewTabWebView.d.ts.map +0 -1
- package/lib/typescript/deuna-sdk-react-native/src/controllers/OpenInNewTabController.d.ts.map +0 -1
- package/lib/typescript/deuna-sdk-react-native/src/helpers/getController.d.ts.map +0 -1
- package/src/components/NewTabWebView.tsx +0 -64
|
@@ -3,10 +3,9 @@ import { useEffect, useRef, useState } from 'react';
|
|
|
3
3
|
|
|
4
4
|
import { DeunaSDK } from '../DeunaSDK';
|
|
5
5
|
import { DeunaWebView } from './DeunaWebView';
|
|
6
|
-
import { NewTabWebView } from './NewTabWebView';
|
|
7
|
-
import { DeunaWebViewController } from '../controllers/BaseWebViewController';
|
|
8
6
|
import { Mode } from '../interfaces/types';
|
|
9
7
|
import { DeviceFingerprintWebView } from './DeviceFingerprintWebView';
|
|
8
|
+
import { ExternalUrlWebView } from './ExternalUrlWebView';
|
|
10
9
|
|
|
11
10
|
interface DeunaWidgetProps {
|
|
12
11
|
instance: DeunaSDK;
|
|
@@ -52,7 +51,9 @@ export const DeunaWidget = (props: DeunaWidgetProps) => {
|
|
|
52
51
|
const DeunaWidgetContainer = (props: DeunaWidgetProps) => {
|
|
53
52
|
const { instance } = props;
|
|
54
53
|
const instanceRef = useRef(instance);
|
|
55
|
-
const [
|
|
54
|
+
const [isVisible, setIsVisible] = useState(
|
|
55
|
+
instanceRef.current.deunaWidgetManager.isInitialized
|
|
56
|
+
);
|
|
56
57
|
|
|
57
58
|
useEffect(() => {
|
|
58
59
|
instanceRef.current = instance;
|
|
@@ -62,74 +63,76 @@ const DeunaWidgetContainer = (props: DeunaWidgetProps) => {
|
|
|
62
63
|
// has changed
|
|
63
64
|
useEffect(() => {
|
|
64
65
|
const listener = () => {
|
|
65
|
-
|
|
66
|
+
setIsVisible(instanceRef.current.deunaWidgetManager.isInitialized);
|
|
66
67
|
};
|
|
67
68
|
|
|
68
69
|
instanceRef.current.addListener(listener);
|
|
69
70
|
|
|
70
71
|
return () => {
|
|
71
72
|
instanceRef.current.removeListener(listener);
|
|
72
|
-
instanceRef.current.
|
|
73
|
+
if (instanceRef.current.deunaWidgetManager.isInitialized) {
|
|
74
|
+
instanceRef.current.deunaWidgetManager.controller?.dispose();
|
|
75
|
+
}
|
|
73
76
|
};
|
|
74
77
|
}, []);
|
|
75
78
|
|
|
76
|
-
const isModal = mode === Mode.MODAL;
|
|
77
|
-
const isEmbedded = mode === Mode.EMBEDDED;
|
|
78
|
-
|
|
79
79
|
/**
|
|
80
80
|
* This function is used to close the widget
|
|
81
81
|
*/
|
|
82
82
|
const onClose = () => {
|
|
83
|
-
const controller = instanceRef.current
|
|
84
|
-
.webViewController as DeunaWebViewController;
|
|
83
|
+
const controller = instanceRef.current.deunaWidgetManager.controller;
|
|
85
84
|
controller.closedAction = 'userAction';
|
|
86
85
|
instanceRef.current.close();
|
|
87
86
|
};
|
|
88
87
|
|
|
89
88
|
// render the widget if mode is not null
|
|
89
|
+
const viewManager = instanceRef.current.deunaWidgetManager;
|
|
90
|
+
const controller = viewManager.isInitialized ? viewManager.controller : null;
|
|
91
|
+
|
|
92
|
+
const isModal = isVisible && viewManager.mode === Mode.MODAL;
|
|
93
|
+
const isEmbedded = isVisible && viewManager.mode === Mode.EMBEDDED;
|
|
94
|
+
|
|
90
95
|
return (
|
|
91
96
|
<>
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
>
|
|
99
|
-
{isModal && (
|
|
97
|
+
{isModal && (
|
|
98
|
+
<Modal
|
|
99
|
+
presentationStyle="pageSheet"
|
|
100
|
+
animationType="slide"
|
|
101
|
+
onRequestClose={onClose}
|
|
102
|
+
>
|
|
100
103
|
<SafeAreaView style={styles.container}>
|
|
101
104
|
<View style={styles.container}>
|
|
102
105
|
<DeunaWebView
|
|
103
|
-
url={
|
|
104
|
-
onWebView={
|
|
105
|
-
onMessage={
|
|
106
|
-
onLoad={
|
|
107
|
-
onError={
|
|
106
|
+
url={controller?.url ?? ''}
|
|
107
|
+
onWebView={controller?.setWebView}
|
|
108
|
+
onMessage={controller?.onMessage}
|
|
109
|
+
onLoad={controller?.onLoad}
|
|
110
|
+
onError={controller?.onError}
|
|
108
111
|
onShouldStartLoadWithRequest={
|
|
109
|
-
|
|
110
|
-
?.onShouldStartLoadWithRequest
|
|
112
|
+
controller?.onShouldStartLoadWithRequest
|
|
111
113
|
}
|
|
112
114
|
/>
|
|
113
|
-
<
|
|
115
|
+
<ExternalUrlWebView instance={instanceRef.current} />
|
|
114
116
|
</View>
|
|
115
117
|
</SafeAreaView>
|
|
116
|
-
|
|
117
|
-
|
|
118
|
+
</Modal>
|
|
119
|
+
)}
|
|
118
120
|
|
|
119
|
-
{isEmbedded && <
|
|
121
|
+
{isEmbedded && <ExternalUrlWebView instance={instanceRef.current} />}
|
|
120
122
|
|
|
121
123
|
{isEmbedded && (
|
|
122
124
|
<DeunaWebView
|
|
123
|
-
url={
|
|
124
|
-
onWebView={
|
|
125
|
-
onMessage={
|
|
126
|
-
onLoad={
|
|
127
|
-
onError={
|
|
125
|
+
url={controller?.url ?? ''}
|
|
126
|
+
onWebView={controller?.setWebView}
|
|
127
|
+
onMessage={controller?.onMessage}
|
|
128
|
+
onLoad={controller?.onLoad}
|
|
129
|
+
onError={controller?.onError}
|
|
128
130
|
onShouldStartLoadWithRequest={
|
|
129
|
-
|
|
131
|
+
controller?.onShouldStartLoadWithRequest
|
|
130
132
|
}
|
|
131
133
|
/>
|
|
132
134
|
)}
|
|
135
|
+
|
|
133
136
|
<DeviceFingerprintWebView instance={instanceRef.current} />
|
|
134
137
|
</>
|
|
135
138
|
);
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { useEffect, useRef, useState } from 'react';
|
|
2
|
+
import { DeunaSDK } from '../DeunaSDK';
|
|
3
|
+
import { Modal, SafeAreaView, StyleSheet } from 'react-native';
|
|
4
|
+
import { DeunaWebView } from './DeunaWebView';
|
|
5
|
+
|
|
6
|
+
interface ExternalUrlWebViewProps {
|
|
7
|
+
instance: DeunaSDK;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const ExternalUrlWebView = (props: ExternalUrlWebViewProps) => {
|
|
11
|
+
const { instance } = props;
|
|
12
|
+
const instanceRef = useRef<DeunaSDK>(instance);
|
|
13
|
+
const [visible, setVisible] = useState(false);
|
|
14
|
+
|
|
15
|
+
useEffect(() => {
|
|
16
|
+
instanceRef.current = instance;
|
|
17
|
+
}, [instance]);
|
|
18
|
+
|
|
19
|
+
// Listen when the DeunaSDK instance configuration
|
|
20
|
+
// has changed
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
const ref = instanceRef.current;
|
|
23
|
+
const listener = () => {
|
|
24
|
+
const isVisible = !!ref.externalUrlHelper.externalUrlWebViewController;
|
|
25
|
+
setVisible(isVisible);
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
instanceRef.current.addListener(listener);
|
|
29
|
+
|
|
30
|
+
return () => {
|
|
31
|
+
ref.removeListener(listener);
|
|
32
|
+
ref.externalUrlHelper.externalUrlWebViewController?.dispose();
|
|
33
|
+
};
|
|
34
|
+
}, []);
|
|
35
|
+
|
|
36
|
+
const externalUrlWebViewController =
|
|
37
|
+
instanceRef.current.externalUrlHelper.externalUrlWebViewController;
|
|
38
|
+
|
|
39
|
+
return (
|
|
40
|
+
<>
|
|
41
|
+
{visible && (
|
|
42
|
+
<Modal
|
|
43
|
+
presentationStyle="pageSheet"
|
|
44
|
+
animationType="slide"
|
|
45
|
+
onRequestClose={instanceRef.current.onCloseExternalUrl}
|
|
46
|
+
>
|
|
47
|
+
<SafeAreaView style={styles.container}>
|
|
48
|
+
<DeunaWebView
|
|
49
|
+
url={externalUrlWebViewController?.url ?? ''}
|
|
50
|
+
onWebView={externalUrlWebViewController?.setWebView}
|
|
51
|
+
onMessage={externalUrlWebViewController?.onMessage}
|
|
52
|
+
onLoad={externalUrlWebViewController?.onLoad}
|
|
53
|
+
onError={externalUrlWebViewController?.onError}
|
|
54
|
+
onShouldStartLoadWithRequest={
|
|
55
|
+
externalUrlWebViewController?.onShouldStartLoadWithRequest
|
|
56
|
+
}
|
|
57
|
+
/>
|
|
58
|
+
</SafeAreaView>
|
|
59
|
+
</Modal>
|
|
60
|
+
)}
|
|
61
|
+
</>
|
|
62
|
+
);
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const styles = StyleSheet.create({ container: { flex: 1 } });
|
|
@@ -11,30 +11,29 @@ import {
|
|
|
11
11
|
import { submitError, WidgetConfig } from '../interfaces';
|
|
12
12
|
import { Platform } from 'react-native';
|
|
13
13
|
import { ShouldStartLoadRequest } from 'react-native-webview/lib/WebViewTypes';
|
|
14
|
+
import { InitFraudProvidersProps } from '../types/fraudProviders';
|
|
15
|
+
import { DeunaSDK } from '../DeunaSDK';
|
|
14
16
|
|
|
15
17
|
export interface WebViewDelegate {
|
|
16
|
-
|
|
18
|
+
onOpenExternalUrl?: (url: string) => void;
|
|
17
19
|
onCloseButtonPressed?: () => void;
|
|
18
|
-
onCloseSubWebView?: () => void;
|
|
19
20
|
onFileDownload?: (url: string) => void;
|
|
20
|
-
|
|
21
|
+
onCloseExternalUrl?: () => void;
|
|
21
22
|
}
|
|
22
23
|
|
|
23
24
|
export enum WebViewEventType {
|
|
24
25
|
consoleLog = 'consoleLog',
|
|
25
26
|
eventDispatch = 'eventDispatch',
|
|
26
27
|
jsExecutor = 'jsExecutor',
|
|
27
|
-
|
|
28
|
+
openExternalUrl = 'openExternalUrl',
|
|
28
29
|
redirect = 'redirect',
|
|
29
|
-
|
|
30
|
+
closeExternalUrl = 'closeExternalUrl',
|
|
30
31
|
}
|
|
31
32
|
|
|
32
33
|
const DOWNLOAD_FILE_REGEX =
|
|
33
34
|
/\.(pdf|doc|docx|xls|xlsx|zip|rar|txt|mp3|mp4|jpg|jpeg|png|gif)$/i;
|
|
34
35
|
|
|
35
36
|
export abstract class BaseWebViewController {
|
|
36
|
-
initialized = false;
|
|
37
|
-
redirectUrl: string | null = null;
|
|
38
37
|
webView: WebView | null = null;
|
|
39
38
|
url: string | null = null;
|
|
40
39
|
|
|
@@ -78,26 +77,22 @@ export abstract class BaseWebViewController {
|
|
|
78
77
|
* @returns boolean indicating if the URL should be loaded in current WebView
|
|
79
78
|
*/
|
|
80
79
|
onShouldStartLoadWithRequest = (request: ShouldStartLoadRequest) => {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
return false;
|
|
80
|
+
if (this.url === request.url) {
|
|
81
|
+
return true;
|
|
84
82
|
}
|
|
85
83
|
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
const
|
|
84
|
+
const isAndroid = Platform.OS === 'android';
|
|
85
|
+
|
|
86
|
+
const isNewNavigation = isAndroid
|
|
87
|
+
? request.url.startsWith('https://')
|
|
88
|
+
: request.navigationType === 'click';
|
|
89
|
+
|
|
90
|
+
const shouldOpenExternally = !this.urlMustBeLoadedInTheSameWebView(
|
|
89
91
|
request.url
|
|
90
92
|
);
|
|
91
93
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
const shouldOpenInNewTab =
|
|
95
|
-
Platform.OS === 'ios'
|
|
96
|
-
? (isClickNavigation || isNewNavigation) && shouldHandleInNewTab
|
|
97
|
-
: isNewNavigation && shouldHandleInNewTab;
|
|
98
|
-
|
|
99
|
-
if (shouldOpenInNewTab) {
|
|
100
|
-
this.delegate?.onOpenInNewTab?.(request.url);
|
|
94
|
+
if (isNewNavigation && shouldOpenExternally) {
|
|
95
|
+
this.delegate?.onOpenExternalUrl?.(request.url);
|
|
101
96
|
return false;
|
|
102
97
|
}
|
|
103
98
|
|
|
@@ -118,13 +113,51 @@ export abstract class DeunaWebViewController extends BaseWebViewController {
|
|
|
118
113
|
redirectUrl: string | null = null;
|
|
119
114
|
closedAction: ClosedAction = 'systemAction';
|
|
120
115
|
|
|
116
|
+
isWebViewInitialized = false;
|
|
117
|
+
|
|
118
|
+
fraudId = '';
|
|
119
|
+
|
|
121
120
|
constructor(readonly widgetConfig: WidgetConfig) {
|
|
122
121
|
super();
|
|
122
|
+
this.init();
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
private init() {
|
|
126
|
+
const { fraudCredentials, sdkInstance } = this.widgetConfig;
|
|
127
|
+
if (!sdkInstance || !fraudCredentials) {
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (fraudCredentials) {
|
|
132
|
+
this.generateFraudId({ sdkInstance, fraudCredentials });
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
private async generateFraudId({
|
|
137
|
+
sdkInstance,
|
|
138
|
+
fraudCredentials,
|
|
139
|
+
}: {
|
|
140
|
+
sdkInstance: DeunaSDK;
|
|
141
|
+
fraudCredentials: Partial<InitFraudProvidersProps>;
|
|
142
|
+
}) {
|
|
143
|
+
try {
|
|
144
|
+
this.fraudId = await sdkInstance.getSessionId(fraudCredentials);
|
|
145
|
+
if (this.isWebViewInitialized) {
|
|
146
|
+
this.jsExecutor.execute(this.getFraudIdFnString());
|
|
147
|
+
}
|
|
148
|
+
} catch (e) {
|
|
149
|
+
console.log('❌ fraudId', e);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
private getFraudIdFnString() {
|
|
154
|
+
return `window.getFraudId = function(){ return '${this.fraudId}';}`;
|
|
123
155
|
}
|
|
124
156
|
|
|
125
157
|
abstract onEventDispatch: (event: Record<string, any>) => void;
|
|
126
158
|
|
|
127
159
|
onLoad = () => {
|
|
160
|
+
this.isWebViewInitialized = true;
|
|
128
161
|
this.setXprops();
|
|
129
162
|
};
|
|
130
163
|
|
|
@@ -158,18 +191,18 @@ export abstract class DeunaWebViewController extends BaseWebViewController {
|
|
|
158
191
|
this.jsExecutor.requests.get(requestId)?.(data);
|
|
159
192
|
this.jsExecutor.requests.delete(requestId);
|
|
160
193
|
},
|
|
161
|
-
[WebViewEventType.
|
|
162
|
-
this.delegate?.
|
|
194
|
+
[WebViewEventType.openExternalUrl]: () => {
|
|
195
|
+
this.delegate?.onOpenExternalUrl?.(eventData.url);
|
|
163
196
|
},
|
|
164
197
|
[WebViewEventType.redirect]: () => {
|
|
165
198
|
if (this.redirectUrl) {
|
|
166
199
|
return;
|
|
167
200
|
}
|
|
168
201
|
this.redirectUrl = eventData.url;
|
|
169
|
-
this.delegate?.
|
|
202
|
+
this.delegate?.onOpenExternalUrl?.(eventData.url);
|
|
170
203
|
},
|
|
171
|
-
[WebViewEventType.
|
|
172
|
-
this.delegate?.
|
|
204
|
+
[WebViewEventType.closeExternalUrl]: () => {
|
|
205
|
+
this.delegate?.onCloseExternalUrl?.();
|
|
173
206
|
},
|
|
174
207
|
};
|
|
175
208
|
|
|
@@ -180,7 +213,7 @@ export abstract class DeunaWebViewController extends BaseWebViewController {
|
|
|
180
213
|
this.webView?.injectJavaScript(
|
|
181
214
|
`
|
|
182
215
|
window.open = function(url, target, features) {
|
|
183
|
-
window.ReactNativeWebView.postMessage(JSON.stringify({ type: '${WebViewEventType.
|
|
216
|
+
window.ReactNativeWebView.postMessage(JSON.stringify({ type: '${WebViewEventType.openExternalUrl}', url }));
|
|
184
217
|
};
|
|
185
218
|
console.log = function(message) {
|
|
186
219
|
window.ReactNativeWebView.postMessage(JSON.stringify({ type: '${WebViewEventType.consoleLog}', message }));
|
|
@@ -205,7 +238,15 @@ export abstract class DeunaWebViewController extends BaseWebViewController {
|
|
|
205
238
|
onSubmit: function (fn) {
|
|
206
239
|
window.submit = fn;
|
|
207
240
|
},
|
|
208
|
-
|
|
241
|
+
getFraudId: function(){
|
|
242
|
+
if(typeof window.getFraudId === 'function'){
|
|
243
|
+
return window.getFraudId();
|
|
244
|
+
}
|
|
245
|
+
return "";
|
|
246
|
+
}
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
${this.fraudId.length > 0 ? this.getFraudIdFnString() : ''}
|
|
209
250
|
`
|
|
210
251
|
);
|
|
211
252
|
};
|
|
@@ -37,12 +37,11 @@ export class ElementsWidgetController extends DeunaWebViewController {
|
|
|
37
37
|
this.delegate?.onCloseButtonPressed?.();
|
|
38
38
|
},
|
|
39
39
|
[ElementsEventType.vaultSaveSuccess]: () => {
|
|
40
|
-
this.delegate?.
|
|
40
|
+
this.delegate?.onCloseExternalUrl?.();
|
|
41
41
|
this.callbacks.onSuccess?.(event.data);
|
|
42
42
|
},
|
|
43
43
|
[ElementsEventType.vaultSaveError]: () => {
|
|
44
|
-
this.delegate?.
|
|
45
|
-
this.delegate?.onCloseSubWebView?.();
|
|
44
|
+
this.delegate?.onCloseExternalUrl?.();
|
|
46
45
|
const { metadata } = elementsEvent.data;
|
|
47
46
|
|
|
48
47
|
if (metadata) {
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
} from './BaseWebViewController';
|
|
6
6
|
import { DeunaLogs } from '../DeunaLogs';
|
|
7
7
|
|
|
8
|
-
export class
|
|
8
|
+
export class ExternalUrlController extends BaseWebViewController {
|
|
9
9
|
constructor(readonly url: string) {
|
|
10
10
|
super();
|
|
11
11
|
this.url = url;
|
|
@@ -16,7 +16,7 @@ export class OpenInNewTabController extends BaseWebViewController {
|
|
|
16
16
|
};
|
|
17
17
|
|
|
18
18
|
onError = (event: any) => {
|
|
19
|
-
|
|
19
|
+
DeunaLogs.error(`EXTERNAL URL ERROR`, event);
|
|
20
20
|
};
|
|
21
21
|
|
|
22
22
|
urlMustBeLoadedInTheSameWebView = (url: string) => {
|
|
@@ -41,7 +41,7 @@ export class OpenInNewTabController extends BaseWebViewController {
|
|
|
41
41
|
window.ReactNativeWebView.postMessage(JSON.stringify({ type: '${WebViewEventType.consoleLog}', message }));
|
|
42
42
|
};
|
|
43
43
|
window.close = function() {
|
|
44
|
-
window.ReactNativeWebView.postMessage(JSON.stringify({ type: '${WebViewEventType.
|
|
44
|
+
window.ReactNativeWebView.postMessage(JSON.stringify({ type: '${WebViewEventType.closeExternalUrl}', data: '' }));
|
|
45
45
|
};
|
|
46
46
|
(function() {
|
|
47
47
|
setTimeout(function() {
|
|
@@ -85,11 +85,11 @@ export class PaymentWidgetController extends DeunaWebViewController {
|
|
|
85
85
|
this.callbacks.onPaymentProcessing?.();
|
|
86
86
|
},
|
|
87
87
|
[CheckoutEventType.purchase]: () => {
|
|
88
|
-
this.delegate?.
|
|
88
|
+
this.delegate?.onCloseExternalUrl?.();
|
|
89
89
|
this.callbacks.onSuccess?.(checkoutEvent.data.order);
|
|
90
90
|
},
|
|
91
91
|
[CheckoutEventType.purchaseError]: () => {
|
|
92
|
-
this.delegate?.
|
|
92
|
+
this.delegate?.onCloseExternalUrl?.();
|
|
93
93
|
const { metadata } = checkoutEvent.data;
|
|
94
94
|
|
|
95
95
|
if (metadata) {
|
package/src/helpers/Completer.ts
CHANGED
|
@@ -17,14 +17,14 @@ export class Completer<T> {
|
|
|
17
17
|
|
|
18
18
|
complete(value: T): void {
|
|
19
19
|
if (this.completed) return;
|
|
20
|
-
this.completed = true;
|
|
21
20
|
this.resolvePromise?.(value);
|
|
21
|
+
this.completed = true;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
completeError(error: any): void {
|
|
25
25
|
if (this.completed) return;
|
|
26
|
-
this.completed = true;
|
|
27
26
|
this.rejectPromise?.(error);
|
|
27
|
+
this.completed = true;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
isCompleted(): boolean {
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import * as WebBrowser from 'expo-web-browser';
|
|
2
|
+
import { Platform } from 'react-native';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* This class is used to open a browser in a SafariView Controller (iOS) or
|
|
6
|
+
* a Chrome Custom Tab (Android) depending on the platform.
|
|
7
|
+
*
|
|
8
|
+
* It is used to open the external URLs in the DEUNA widget.
|
|
9
|
+
*/
|
|
10
|
+
class CrossPlatformBrowser {
|
|
11
|
+
private initialized = false;
|
|
12
|
+
/**
|
|
13
|
+
* Initialize the browser
|
|
14
|
+
*/
|
|
15
|
+
async initialize() {
|
|
16
|
+
if (this.initialized) return;
|
|
17
|
+
await WebBrowser.maybeCompleteAuthSession();
|
|
18
|
+
this.initialized = true;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Open an URL in a SafariView Controller (iOS) or a Chrome Custom Tab (Android) depending on the platform
|
|
23
|
+
* @param url - The URL to open
|
|
24
|
+
*/
|
|
25
|
+
async openBrowser(url: string) {
|
|
26
|
+
try {
|
|
27
|
+
await this.initialize();
|
|
28
|
+
await WebBrowser.openBrowserAsync(url);
|
|
29
|
+
} catch (error) {
|
|
30
|
+
console.error('Error opening browser', error);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Close the browser
|
|
36
|
+
*/
|
|
37
|
+
async closeBrowser() {
|
|
38
|
+
if (Platform.OS !== 'ios') {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
try {
|
|
42
|
+
await WebBrowser.dismissBrowser();
|
|
43
|
+
} catch (error) {
|
|
44
|
+
console.error('Error closing browser', error);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export const crossPlatformBrowser = new CrossPlatformBrowser();
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { AppState, Platform } from 'react-native';
|
|
2
|
+
import { WebViewDelegate } from '../controllers/BaseWebViewController';
|
|
3
|
+
import { ExternalUrlController } from '../controllers/ExternalUrlController';
|
|
4
|
+
import { Completer } from './Completer';
|
|
5
|
+
import { crossPlatformBrowser } from './CrossPlatformBrowser';
|
|
6
|
+
|
|
7
|
+
export enum ExternalUrlBrowser {
|
|
8
|
+
WEB_VIEW = 'web_view',
|
|
9
|
+
CROSS_PLATFORM_BROWSER = 'cross_platform_browser',
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
interface OpenUrlParams {
|
|
13
|
+
url: string;
|
|
14
|
+
browser: ExternalUrlBrowser;
|
|
15
|
+
delegate: WebViewDelegate;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
interface ExternalUrlManager<T extends ExternalUrlBrowser> {
|
|
19
|
+
type: T;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface WebViewManager
|
|
23
|
+
extends ExternalUrlManager<ExternalUrlBrowser.WEB_VIEW> {
|
|
24
|
+
controller: ExternalUrlController;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface CrossPlatformBrowserManager
|
|
28
|
+
extends ExternalUrlManager<ExternalUrlBrowser.CROSS_PLATFORM_BROWSER> {
|
|
29
|
+
type: ExternalUrlBrowser.CROSS_PLATFORM_BROWSER;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export class ExternalUrlHelper {
|
|
33
|
+
private manager: ExternalUrlManager<ExternalUrlBrowser> | null = null;
|
|
34
|
+
private completer: Completer<void> | null = null;
|
|
35
|
+
|
|
36
|
+
constructor() {
|
|
37
|
+
this.startCloseChecker();
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
get externalUrlWebViewController() {
|
|
41
|
+
if (this.manager?.type === ExternalUrlBrowser.WEB_VIEW) {
|
|
42
|
+
return (this.manager as WebViewManager).controller;
|
|
43
|
+
}
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Wait until the webview or cross platform browser is closed
|
|
49
|
+
*/
|
|
50
|
+
async waitForClose() {
|
|
51
|
+
if (this.completer) {
|
|
52
|
+
await this.completer.wait;
|
|
53
|
+
this.completer = null;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Listen when the app is brought back to the foreground
|
|
59
|
+
*/
|
|
60
|
+
private startCloseChecker() {
|
|
61
|
+
AppState.addEventListener('change', (state) => {
|
|
62
|
+
if (
|
|
63
|
+
state === 'active' &&
|
|
64
|
+
this.manager?.type === ExternalUrlBrowser.CROSS_PLATFORM_BROWSER
|
|
65
|
+
) {
|
|
66
|
+
this.manager = null;
|
|
67
|
+
this.completeClose();
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Opens the webview or cross platform browser
|
|
74
|
+
*/
|
|
75
|
+
async openUrl(params: OpenUrlParams) {
|
|
76
|
+
const { url, browser, delegate } = params;
|
|
77
|
+
|
|
78
|
+
const mapper = {
|
|
79
|
+
[ExternalUrlBrowser.WEB_VIEW]: async () => {
|
|
80
|
+
const controller = new ExternalUrlController(url);
|
|
81
|
+
controller.delegate = delegate;
|
|
82
|
+
this.manager = {
|
|
83
|
+
type: ExternalUrlBrowser.WEB_VIEW,
|
|
84
|
+
controller,
|
|
85
|
+
} as WebViewManager;
|
|
86
|
+
},
|
|
87
|
+
[ExternalUrlBrowser.CROSS_PLATFORM_BROWSER]: async () => {
|
|
88
|
+
this.completer = new Completer<void>();
|
|
89
|
+
this.manager = {
|
|
90
|
+
type: ExternalUrlBrowser.CROSS_PLATFORM_BROWSER,
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
await crossPlatformBrowser.openBrowser(url);
|
|
94
|
+
if (Platform.OS === 'ios') {
|
|
95
|
+
this.completer?.complete();
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
await mapper[browser]();
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Notify that the browser has been closed
|
|
104
|
+
*/
|
|
105
|
+
private completeClose() {
|
|
106
|
+
this.completer?.complete();
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Closes the web view
|
|
111
|
+
*/
|
|
112
|
+
async closeWebView() {
|
|
113
|
+
if (this.manager?.type === ExternalUrlBrowser.WEB_VIEW) {
|
|
114
|
+
(this.manager as WebViewManager).controller?.dispose();
|
|
115
|
+
this.manager = null;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BaseWebViewController,
|
|
3
|
+
WebViewDelegate,
|
|
4
|
+
} from '../controllers/BaseWebViewController';
|
|
5
|
+
import { Mode } from '../interfaces';
|
|
6
|
+
|
|
7
|
+
export class WebViewManager<
|
|
8
|
+
T extends BaseWebViewController = BaseWebViewController,
|
|
9
|
+
> {
|
|
10
|
+
private _controller: T | null = null;
|
|
11
|
+
private _mode: Mode | null = null;
|
|
12
|
+
|
|
13
|
+
initialize = (params: {
|
|
14
|
+
controller: T;
|
|
15
|
+
delegate: WebViewDelegate;
|
|
16
|
+
mode: Mode;
|
|
17
|
+
}): void => {
|
|
18
|
+
this._controller = params.controller;
|
|
19
|
+
this._controller.delegate = params.delegate;
|
|
20
|
+
this._mode = params.mode;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
get isInitialized(): boolean {
|
|
24
|
+
return !!this._controller;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
get mode(): Mode | null {
|
|
28
|
+
return this._mode;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
get controller(): T {
|
|
32
|
+
if (!this._controller) {
|
|
33
|
+
throw new Error('WebView not initialized');
|
|
34
|
+
}
|
|
35
|
+
return this._controller;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Destroy the webview and the modal (if it exists)
|
|
40
|
+
*/
|
|
41
|
+
destroy = () => {
|
|
42
|
+
this._controller?.dispose();
|
|
43
|
+
this._controller = null;
|
|
44
|
+
};
|
|
45
|
+
}
|