@deuna/react-native-sdk 1.0.3 → 1.0.4
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 +85 -77
- 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 +15 -21
- 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} +2 -2
- 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/types/helpers/buildElementsLink.js +3 -1
- package/lib/module/types/helpers/buildElementsLink.js.map +1 -1
- package/lib/module/types/helpers/buildPaymentLink.js +3 -1
- 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/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 +4 -6
- 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} +2 -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/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 +1 -0
- package/lib/typescript/deuna-sdk-react-native/src/types/interfaces/initWidgetBase.d.ts.map +1 -1
- package/package.json +3 -1
- package/src/DeunaSDK.ts +102 -90
- package/src/components/DeunaWidget.tsx +38 -35
- package/src/components/ExternalUrlWebView.tsx +65 -0
- package/src/controllers/BaseWebViewController.ts +21 -27
- 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} +1 -1
- package/src/helpers/getSubmitStrategy.ts +1 -1
- package/src/interfaces/constants.ts +2 -0
- package/src/types/helpers/buildElementsLink.ts +4 -1
- package/src/types/helpers/buildPaymentLink.ts +2 -0
- 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 +1 -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
package/src/DeunaSDK.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
BaseDeuna,
|
|
3
|
+
ClosedAction,
|
|
3
4
|
CustomStyles,
|
|
4
5
|
GetStateFn,
|
|
5
6
|
InitElementsWidgetParams,
|
|
@@ -18,21 +19,25 @@ import {
|
|
|
18
19
|
VoucherWidgetCallbacks,
|
|
19
20
|
} from './types';
|
|
20
21
|
import {
|
|
21
|
-
BaseWebViewController,
|
|
22
22
|
DeunaWebViewController,
|
|
23
23
|
WebViewDelegate,
|
|
24
24
|
} from './controllers/BaseWebViewController';
|
|
25
25
|
import { PaymentWidgetController } from './controllers/PaymentWidgetController';
|
|
26
|
-
import {
|
|
27
|
-
import { getWidgetController } from './helpers/getController';
|
|
28
|
-
import { Completer } from './helpers/Completer';
|
|
26
|
+
import { buildDeunaWidgetController } from './helpers/buildDeunaWidgetController';
|
|
29
27
|
import { ElementsWidgetController } from './controllers/ElementsWidgetController';
|
|
30
28
|
import { DownloadType, Mode, OnDownloadFile } from './interfaces/types';
|
|
31
|
-
import { Platform } from 'react-native';
|
|
32
29
|
import { DeviceFingerprintController } from './controllers/DeviceFingerprintController';
|
|
33
|
-
import {
|
|
30
|
+
import {
|
|
31
|
+
DEVICE_FINGERPRINT_URL,
|
|
32
|
+
DOMAINS_MUST_BE_USE_CROSS_PLATFORM_BROWSER,
|
|
33
|
+
} from './interfaces/constants';
|
|
34
34
|
import { SubmitStrategy } from './helpers/SubmitStrategy';
|
|
35
35
|
import { getSubmitStrategy } from './helpers/getSubmitStrategy';
|
|
36
|
+
import { WebViewManager } from './helpers/ViewManager';
|
|
37
|
+
import {
|
|
38
|
+
ExternalUrlBrowser,
|
|
39
|
+
ExternalUrlHelper,
|
|
40
|
+
} from './helpers/ExternalUrlHelper';
|
|
36
41
|
|
|
37
42
|
export class DeunaSDK extends BaseDeuna {
|
|
38
43
|
constructor(
|
|
@@ -42,8 +47,6 @@ export class DeunaSDK extends BaseDeuna {
|
|
|
42
47
|
super();
|
|
43
48
|
}
|
|
44
49
|
|
|
45
|
-
mode: Mode | null = null;
|
|
46
|
-
|
|
47
50
|
setCustomStyleFn?: SetCustomStyle | undefined;
|
|
48
51
|
refetchOrderFn?: RefetchOrder | undefined;
|
|
49
52
|
getStateFn?: GetStateFn | undefined;
|
|
@@ -52,23 +55,12 @@ export class DeunaSDK extends BaseDeuna {
|
|
|
52
55
|
closeFn?: (() => void) | undefined;
|
|
53
56
|
|
|
54
57
|
private listeners: Set<() => void> = new Set();
|
|
55
|
-
webViewController: DeunaWebViewController | null = null;
|
|
56
|
-
newTabWebViewController: BaseWebViewController | null = null;
|
|
57
|
-
deviceFingerprintController: DeviceFingerprintController | null = null;
|
|
58
|
-
submitStrategy: SubmitStrategy | null = null;
|
|
59
58
|
|
|
60
|
-
|
|
61
|
-
|
|
59
|
+
deunaWidgetManager = new WebViewManager<DeunaWebViewController>();
|
|
60
|
+
externalUrlHelper = new ExternalUrlHelper();
|
|
62
61
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
const errorMessage =
|
|
66
|
-
'A variant of the init method must be called first. Please call initPaymentWidget, initVoucherWidget, or another init method before using this functionality.';
|
|
67
|
-
console.error(errorMessage);
|
|
68
|
-
throw new Error(errorMessage);
|
|
69
|
-
}
|
|
70
|
-
return this.webViewController;
|
|
71
|
-
}
|
|
62
|
+
deviceFingerprintController: DeviceFingerprintController | null = null;
|
|
63
|
+
submitStrategy: SubmitStrategy | null = null;
|
|
72
64
|
|
|
73
65
|
/**
|
|
74
66
|
* Generates a device fingerprint, creates a invisible webview to get the device fingerprint
|
|
@@ -108,12 +100,11 @@ export class DeunaSDK extends BaseDeuna {
|
|
|
108
100
|
mode?: Mode;
|
|
109
101
|
}): void => {
|
|
110
102
|
const { controller, mode } = params;
|
|
111
|
-
this.
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
this.webViewController.delegate = this.buildDelegate();
|
|
103
|
+
this.deunaWidgetManager.initialize({
|
|
104
|
+
controller,
|
|
105
|
+
mode: mode ?? Mode.MODAL,
|
|
106
|
+
delegate: this.buildDelegate(),
|
|
107
|
+
});
|
|
117
108
|
this.notifyListeners();
|
|
118
109
|
};
|
|
119
110
|
|
|
@@ -129,7 +120,7 @@ export class DeunaSDK extends BaseDeuna {
|
|
|
129
120
|
}
|
|
130
121
|
) {
|
|
131
122
|
this.setWidgetController({
|
|
132
|
-
controller:
|
|
123
|
+
controller: buildDeunaWidgetController(this.config, {
|
|
133
124
|
widget: 'payment',
|
|
134
125
|
...props,
|
|
135
126
|
}),
|
|
@@ -146,7 +137,7 @@ export class DeunaSDK extends BaseDeuna {
|
|
|
146
137
|
props: InitElementsWidgetParams & { mode?: Mode; sessionId?: string }
|
|
147
138
|
) {
|
|
148
139
|
this.setWidgetController({
|
|
149
|
-
controller:
|
|
140
|
+
controller: buildDeunaWidgetController(this.config, {
|
|
150
141
|
widget: 'elements',
|
|
151
142
|
...props,
|
|
152
143
|
}),
|
|
@@ -161,7 +152,7 @@ export class DeunaSDK extends BaseDeuna {
|
|
|
161
152
|
*/
|
|
162
153
|
async initNextAction(props: InitNextActionWidgetParams & { mode: Mode }) {
|
|
163
154
|
this.setWidgetController({
|
|
164
|
-
controller:
|
|
155
|
+
controller: buildDeunaWidgetController(this.config, {
|
|
165
156
|
widget: 'nextAction',
|
|
166
157
|
...props,
|
|
167
158
|
}),
|
|
@@ -181,7 +172,7 @@ export class DeunaSDK extends BaseDeuna {
|
|
|
181
172
|
}
|
|
182
173
|
) {
|
|
183
174
|
this.setWidgetController({
|
|
184
|
-
controller:
|
|
175
|
+
controller: buildDeunaWidgetController(this.config, {
|
|
185
176
|
widget: 'voucher',
|
|
186
177
|
...props,
|
|
187
178
|
}),
|
|
@@ -190,7 +181,7 @@ export class DeunaSDK extends BaseDeuna {
|
|
|
190
181
|
}
|
|
191
182
|
|
|
192
183
|
isValid = async (): Promise<boolean> => {
|
|
193
|
-
return this.
|
|
184
|
+
return this.deunaWidgetManager.controller.isValid();
|
|
194
185
|
};
|
|
195
186
|
|
|
196
187
|
submit = async (): Promise<SubmitResult> => {
|
|
@@ -198,7 +189,7 @@ export class DeunaSDK extends BaseDeuna {
|
|
|
198
189
|
const submitStrategy = await getSubmitStrategy(this);
|
|
199
190
|
|
|
200
191
|
if (!submitStrategy) {
|
|
201
|
-
return this.
|
|
192
|
+
return this.deunaWidgetManager.controller.submit();
|
|
202
193
|
}
|
|
203
194
|
|
|
204
195
|
this.submitStrategy = submitStrategy;
|
|
@@ -207,57 +198,63 @@ export class DeunaSDK extends BaseDeuna {
|
|
|
207
198
|
};
|
|
208
199
|
|
|
209
200
|
setCustomStyle = async (style: Partial<CustomStyles>): Promise<void> => {
|
|
210
|
-
return this.
|
|
201
|
+
return this.deunaWidgetManager.controller.setCustomStyle(style);
|
|
211
202
|
};
|
|
212
203
|
|
|
213
204
|
refetchOrder = async (): Promise<Json | null> => {
|
|
214
|
-
return this.
|
|
205
|
+
return this.deunaWidgetManager.controller.refetchOrder();
|
|
215
206
|
};
|
|
216
207
|
|
|
217
208
|
getWidgetState = async (): Promise<State> => {
|
|
218
|
-
return this.
|
|
209
|
+
return this.deunaWidgetManager.controller.getWidgetState();
|
|
219
210
|
};
|
|
220
211
|
|
|
221
212
|
/**
|
|
222
213
|
* Closes the DEUNA widget and releases the resources
|
|
223
214
|
*/
|
|
224
215
|
close = async (): Promise<void> => {
|
|
225
|
-
if (this.
|
|
226
|
-
|
|
227
|
-
this.webViewController.closedAction
|
|
228
|
-
);
|
|
229
|
-
} else if (this.webViewController instanceof ElementsWidgetController) {
|
|
230
|
-
this.webViewController.callbacks.onClosed?.(
|
|
231
|
-
this.webViewController.closedAction
|
|
232
|
-
);
|
|
216
|
+
if (!this.deunaWidgetManager.isInitialized) {
|
|
217
|
+
return;
|
|
233
218
|
}
|
|
234
|
-
this.onCloseNewTab();
|
|
235
|
-
await this.newTabModalDismissPromise?.wait;
|
|
236
|
-
this.newTabWebViewController?.dispose();
|
|
237
219
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
220
|
+
try {
|
|
221
|
+
let onClosedCallback: ((action: ClosedAction) => void) | undefined;
|
|
222
|
+
const closedAction = this.deunaWidgetManager.controller.closedAction;
|
|
223
|
+
|
|
224
|
+
if (
|
|
225
|
+
this.deunaWidgetManager.controller instanceof PaymentWidgetController
|
|
226
|
+
) {
|
|
227
|
+
onClosedCallback =
|
|
228
|
+
this.deunaWidgetManager.controller.callbacks.onClosed;
|
|
229
|
+
} else if (
|
|
230
|
+
this.deunaWidgetManager.controller instanceof ElementsWidgetController
|
|
231
|
+
) {
|
|
232
|
+
onClosedCallback =
|
|
233
|
+
this.deunaWidgetManager.controller.callbacks.onClosed;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// If the external url was opened in a Safari View Controller or a Custom Chrome Tab
|
|
237
|
+
// we need to wait until the browser is dismissed
|
|
238
|
+
await this.externalUrlHelper.waitForClose();
|
|
239
|
+
|
|
240
|
+
// Destroy the main webview and dismiss the modal
|
|
241
|
+
this.deunaWidgetManager.destroy();
|
|
242
|
+
|
|
243
|
+
// Close the submit strategy if it exists
|
|
244
|
+
await this.submitStrategy?.deunaSDK.close();
|
|
245
|
+
this.submitStrategy = null;
|
|
246
|
+
|
|
247
|
+
// Notify listeners that the widget has been closed
|
|
248
|
+
this.notifyListeners();
|
|
249
|
+
|
|
250
|
+
// Notify the user that the widget has been closed
|
|
251
|
+
this.onDestroyed?.();
|
|
252
|
+
|
|
253
|
+
// Notify the widget that the user has closed the widget
|
|
254
|
+
onClosedCallback?.(closedAction);
|
|
255
|
+
} catch (error) {
|
|
256
|
+
console.error('Error closing the widget', error);
|
|
257
|
+
}
|
|
261
258
|
};
|
|
262
259
|
|
|
263
260
|
addListener = (listener: () => void) => {
|
|
@@ -273,21 +270,22 @@ export class DeunaSDK extends BaseDeuna {
|
|
|
273
270
|
};
|
|
274
271
|
|
|
275
272
|
private notifyDownloadFile = (url: string) => {
|
|
276
|
-
if (this.
|
|
277
|
-
this.
|
|
273
|
+
if (this.deunaWidgetManager.controller instanceof PaymentWidgetController) {
|
|
274
|
+
this.deunaWidgetManager.controller.callbacks.onDownloadFile?.({
|
|
278
275
|
type: DownloadType.URL,
|
|
279
276
|
data: url,
|
|
280
277
|
});
|
|
281
278
|
}
|
|
282
279
|
};
|
|
283
280
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
281
|
+
/**
|
|
282
|
+
* Closes the external URL Webview
|
|
283
|
+
*/
|
|
284
|
+
onCloseExternalUrl = async () => {
|
|
285
|
+
if (this.externalUrlHelper.externalUrlWebViewController) {
|
|
286
|
+
await this.externalUrlHelper.closeWebView();
|
|
287
|
+
this.notifyListeners();
|
|
287
288
|
}
|
|
288
|
-
this.newTabWebViewController?.dispose();
|
|
289
|
-
this.newTabWebViewController = null;
|
|
290
|
-
this.notifyListeners();
|
|
291
289
|
};
|
|
292
290
|
|
|
293
291
|
/**
|
|
@@ -298,19 +296,33 @@ export class DeunaSDK extends BaseDeuna {
|
|
|
298
296
|
*/
|
|
299
297
|
buildDelegate = (): WebViewDelegate => {
|
|
300
298
|
return {
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
299
|
+
onOpenExternalUrl: (url) => {
|
|
300
|
+
try {
|
|
301
|
+
const host = new URL(url).host;
|
|
302
|
+
let browser = ExternalUrlBrowser.WEB_VIEW;
|
|
303
|
+
// Check if the URL is from a domain that must be opened in a cross platform browser (SafariView or Chrome Custom Tab)
|
|
304
|
+
for (const domain of DOMAINS_MUST_BE_USE_CROSS_PLATFORM_BROWSER) {
|
|
305
|
+
if (host.includes(domain)) {
|
|
306
|
+
browser = ExternalUrlBrowser.CROSS_PLATFORM_BROWSER;
|
|
307
|
+
break;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
this.externalUrlHelper.openUrl({
|
|
312
|
+
url,
|
|
313
|
+
browser,
|
|
314
|
+
delegate: {
|
|
315
|
+
onCloseExternalUrl: this.onCloseExternalUrl,
|
|
316
|
+
onFileDownload: this.notifyDownloadFile,
|
|
317
|
+
},
|
|
318
|
+
});
|
|
319
|
+
this.notifyListeners();
|
|
320
|
+
} catch (error) {
|
|
321
|
+
console.error('Error opening external URL', error);
|
|
305
322
|
}
|
|
306
|
-
this.newTabWebViewController.delegate = {
|
|
307
|
-
onFileDownload: this.notifyDownloadFile,
|
|
308
|
-
onNewTabWindowClose: this.onCloseNewTab,
|
|
309
|
-
};
|
|
310
|
-
this.notifyListeners();
|
|
311
323
|
},
|
|
324
|
+
onCloseExternalUrl: this.onCloseExternalUrl,
|
|
312
325
|
onCloseButtonPressed: this.close, // Close the payment widget when the user presses the close button
|
|
313
|
-
onCloseSubWebView: this.onCloseNewTab, // Close the new tab web view when the DEUNA widget emits an error event or when the purchase is successful
|
|
314
326
|
onFileDownload: this.notifyDownloadFile, // Notify the user when a request to download a file is made
|
|
315
327
|
};
|
|
316
328
|
};
|
|
@@ -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 } });
|
|
@@ -13,20 +13,19 @@ import { Platform } from 'react-native';
|
|
|
13
13
|
import { ShouldStartLoadRequest } from 'react-native-webview/lib/WebViewTypes';
|
|
14
14
|
|
|
15
15
|
export interface WebViewDelegate {
|
|
16
|
-
|
|
16
|
+
onOpenExternalUrl?: (url: string) => void;
|
|
17
17
|
onCloseButtonPressed?: () => void;
|
|
18
|
-
onCloseSubWebView?: () => void;
|
|
19
18
|
onFileDownload?: (url: string) => void;
|
|
20
|
-
|
|
19
|
+
onCloseExternalUrl?: () => void;
|
|
21
20
|
}
|
|
22
21
|
|
|
23
22
|
export enum WebViewEventType {
|
|
24
23
|
consoleLog = 'consoleLog',
|
|
25
24
|
eventDispatch = 'eventDispatch',
|
|
26
25
|
jsExecutor = 'jsExecutor',
|
|
27
|
-
|
|
26
|
+
openExternalUrl = 'openExternalUrl',
|
|
28
27
|
redirect = 'redirect',
|
|
29
|
-
|
|
28
|
+
closeExternalUrl = 'closeExternalUrl',
|
|
30
29
|
}
|
|
31
30
|
|
|
32
31
|
const DOWNLOAD_FILE_REGEX =
|
|
@@ -34,7 +33,6 @@ const DOWNLOAD_FILE_REGEX =
|
|
|
34
33
|
|
|
35
34
|
export abstract class BaseWebViewController {
|
|
36
35
|
initialized = false;
|
|
37
|
-
redirectUrl: string | null = null;
|
|
38
36
|
webView: WebView | null = null;
|
|
39
37
|
url: string | null = null;
|
|
40
38
|
|
|
@@ -78,26 +76,22 @@ export abstract class BaseWebViewController {
|
|
|
78
76
|
* @returns boolean indicating if the URL should be loaded in current WebView
|
|
79
77
|
*/
|
|
80
78
|
onShouldStartLoadWithRequest = (request: ShouldStartLoadRequest) => {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
return false;
|
|
79
|
+
if (this.url === request.url) {
|
|
80
|
+
return true;
|
|
84
81
|
}
|
|
85
82
|
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
const
|
|
83
|
+
const isAndroid = Platform.OS === 'android';
|
|
84
|
+
|
|
85
|
+
const isNewNavigation = isAndroid
|
|
86
|
+
? request.url.startsWith('https://')
|
|
87
|
+
: request.navigationType === 'click';
|
|
88
|
+
|
|
89
|
+
const shouldOpenExternally = !this.urlMustBeLoadedInTheSameWebView(
|
|
89
90
|
request.url
|
|
90
91
|
);
|
|
91
92
|
|
|
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);
|
|
93
|
+
if (isNewNavigation && shouldOpenExternally) {
|
|
94
|
+
this.delegate?.onOpenExternalUrl?.(request.url);
|
|
101
95
|
return false;
|
|
102
96
|
}
|
|
103
97
|
|
|
@@ -158,18 +152,18 @@ export abstract class DeunaWebViewController extends BaseWebViewController {
|
|
|
158
152
|
this.jsExecutor.requests.get(requestId)?.(data);
|
|
159
153
|
this.jsExecutor.requests.delete(requestId);
|
|
160
154
|
},
|
|
161
|
-
[WebViewEventType.
|
|
162
|
-
this.delegate?.
|
|
155
|
+
[WebViewEventType.openExternalUrl]: () => {
|
|
156
|
+
this.delegate?.onOpenExternalUrl?.(eventData.url);
|
|
163
157
|
},
|
|
164
158
|
[WebViewEventType.redirect]: () => {
|
|
165
159
|
if (this.redirectUrl) {
|
|
166
160
|
return;
|
|
167
161
|
}
|
|
168
162
|
this.redirectUrl = eventData.url;
|
|
169
|
-
this.delegate?.
|
|
163
|
+
this.delegate?.onOpenExternalUrl?.(eventData.url);
|
|
170
164
|
},
|
|
171
|
-
[WebViewEventType.
|
|
172
|
-
this.delegate?.
|
|
165
|
+
[WebViewEventType.closeExternalUrl]: () => {
|
|
166
|
+
this.delegate?.onCloseExternalUrl?.();
|
|
173
167
|
},
|
|
174
168
|
};
|
|
175
169
|
|
|
@@ -180,7 +174,7 @@ export abstract class DeunaWebViewController extends BaseWebViewController {
|
|
|
180
174
|
this.webView?.injectJavaScript(
|
|
181
175
|
`
|
|
182
176
|
window.open = function(url, target, features) {
|
|
183
|
-
window.ReactNativeWebView.postMessage(JSON.stringify({ type: '${WebViewEventType.
|
|
177
|
+
window.ReactNativeWebView.postMessage(JSON.stringify({ type: '${WebViewEventType.openExternalUrl}', url }));
|
|
184
178
|
};
|
|
185
179
|
console.log = function(message) {
|
|
186
180
|
window.ReactNativeWebView.postMessage(JSON.stringify({ type: '${WebViewEventType.consoleLog}', message }));
|
|
@@ -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) {
|