partner_react_native_sdk 0.1.8 → 1.0.1
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/helpers/network/APICall.js +75 -96
- package/lib/module/helpers/network/APICall.js.map +1 -1
- package/lib/module/helpers/network/Encryption.js +146 -239
- package/lib/module/helpers/network/Encryption.js.map +1 -1
- package/lib/module/helpers/partner_library_react_native.js +81 -0
- package/lib/module/helpers/partner_library_react_native.js.map +1 -1
- package/lib/module/helpers/webview.js +70 -0
- package/lib/module/helpers/webview.js.map +1 -1
- package/lib/typescript/src/helpers/network/APICall.d.ts +1 -0
- package/lib/typescript/src/helpers/network/APICall.d.ts.map +1 -1
- package/lib/typescript/src/helpers/network/Encryption.d.ts +23 -0
- package/lib/typescript/src/helpers/network/Encryption.d.ts.map +1 -1
- package/lib/typescript/src/helpers/partner_library_react_native.d.ts +9 -0
- package/lib/typescript/src/helpers/partner_library_react_native.d.ts.map +1 -1
- package/lib/typescript/src/helpers/webview.d.ts +10 -0
- package/lib/typescript/src/helpers/webview.d.ts.map +1 -1
- package/package.json +9 -6
- package/src/helpers/network/APICall.tsx +99 -94
- package/src/helpers/network/Encryption.tsx +179 -239
- package/src/helpers/partner_library_react_native.tsx +106 -0
- package/src/helpers/webview.tsx +87 -0
- package/lib/typescript/rn78test/App.d.ts +0 -10
- package/lib/typescript/rn78test/App.d.ts.map +0 -1
|
@@ -9,11 +9,19 @@ import { SafeAreaView } from 'react-native-safe-area-context';
|
|
|
9
9
|
import { StatusBar } from 'react-native';
|
|
10
10
|
export type { WebViewCallbackFunction } from './utils/webviewCallback';
|
|
11
11
|
import { AnalyticsLogger } from './analytics/analytics_logger';
|
|
12
|
+
import * as base64js from 'base64-js';
|
|
13
|
+
|
|
12
14
|
type InitOptions = {
|
|
13
15
|
whitelistedDomains: string[];
|
|
14
16
|
deviceBindingEnabled: boolean;
|
|
15
17
|
};
|
|
16
18
|
|
|
19
|
+
// Extend the global type to include base64FromArrayBuffer
|
|
20
|
+
declare global {
|
|
21
|
+
var base64FromArrayBuffer: ((arrayBuffer: ArrayBuffer) => string) | undefined;
|
|
22
|
+
}
|
|
23
|
+
type JSONMap = Record<string, any>;
|
|
24
|
+
|
|
17
25
|
export class PartnerLibrary {
|
|
18
26
|
private static instance: PartnerLibrary | null = null;
|
|
19
27
|
private static intialized = false;
|
|
@@ -41,6 +49,12 @@ export class PartnerLibrary {
|
|
|
41
49
|
if (PartnerLibrary.intialized) return;
|
|
42
50
|
|
|
43
51
|
try {
|
|
52
|
+
if (!global.base64FromArrayBuffer) {
|
|
53
|
+
global.base64FromArrayBuffer = (arrayBuffer: ArrayBuffer) => {
|
|
54
|
+
return base64js.fromByteArray(new Uint8Array(arrayBuffer));
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
44
58
|
// Ensure instance exists before setup
|
|
45
59
|
if (!PartnerLibrary.instance) {
|
|
46
60
|
// console.log("PartnerLibrary.init - creating new instance");
|
|
@@ -136,6 +150,7 @@ export class PartnerLibrary {
|
|
|
136
150
|
let tokenResponse: any;
|
|
137
151
|
const url = ServiceNames.LOGIN_URL;
|
|
138
152
|
console.log('SDK:LOG: ', url);
|
|
153
|
+
console.log('SDK:LOG: Token is : ', token);
|
|
139
154
|
tokenResponse = await this._apiCall.callAPI(
|
|
140
155
|
'POST',
|
|
141
156
|
ServiceNames.LOGIN_URL,
|
|
@@ -145,6 +160,7 @@ export class PartnerLibrary {
|
|
|
145
160
|
},
|
|
146
161
|
}
|
|
147
162
|
);
|
|
163
|
+
console.log('SDK:LOG Token response is : ', tokenResponse);
|
|
148
164
|
// this._analyticsLogger.logEvent({
|
|
149
165
|
// event: 'REACT_NATIVE_LOGIN_FN_RESPONSE :',
|
|
150
166
|
// response: tokenResponse,
|
|
@@ -275,6 +291,7 @@ export class PartnerLibrary {
|
|
|
275
291
|
ServiceNames.THEME_URL
|
|
276
292
|
);
|
|
277
293
|
const theme = themeResponse?.data;
|
|
294
|
+
console.log('SDK:LOG: Theme response:', theme);
|
|
278
295
|
|
|
279
296
|
if (theme && theme['--color-primary-500']) {
|
|
280
297
|
const rgbValues = theme['--color-primary-500'].split(' ').map(Number);
|
|
@@ -304,4 +321,93 @@ export class PartnerLibrary {
|
|
|
304
321
|
throw e;
|
|
305
322
|
}
|
|
306
323
|
}
|
|
324
|
+
async publicapi(
|
|
325
|
+
method: string,
|
|
326
|
+
apiUrl: string,
|
|
327
|
+
options?: {
|
|
328
|
+
body?: Record<string, any>;
|
|
329
|
+
headers?: Record<string, any>;
|
|
330
|
+
}
|
|
331
|
+
): Promise<any> {
|
|
332
|
+
return this._apiCall.callAPI(method, apiUrl, options);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
public async sdkLogin(token: string, partner: string): Promise<JSONMap> {
|
|
336
|
+
try {
|
|
337
|
+
// 1) LOGIN
|
|
338
|
+
console.log('SDK:LOG: ', ServiceNames.LOGIN_URL);
|
|
339
|
+
console.log('SDK:LOG: Token is: ', token);
|
|
340
|
+
|
|
341
|
+
const loginResp = await this._apiCall.callAPI(
|
|
342
|
+
'POST',
|
|
343
|
+
ServiceNames.LOGIN_URL,
|
|
344
|
+
{
|
|
345
|
+
body: { token },
|
|
346
|
+
}
|
|
347
|
+
);
|
|
348
|
+
|
|
349
|
+
// Normalize to a JSON object
|
|
350
|
+
const loginData: JSONMap =
|
|
351
|
+
loginResp?.data && typeof loginResp.data === 'object'
|
|
352
|
+
? { ...loginResp.data }
|
|
353
|
+
: {};
|
|
354
|
+
|
|
355
|
+
const isSuccess =
|
|
356
|
+
loginResp?.status === 200 && loginData?.code === 'USER_LOGIN_SUCCESS';
|
|
357
|
+
|
|
358
|
+
if (!isSuccess) {
|
|
359
|
+
// Not a successful login → return login JSON as-is
|
|
360
|
+
return loginData;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
// 2) DEVICE SESSION
|
|
364
|
+
try {
|
|
365
|
+
console.log('SDK:LOG: in device-session');
|
|
366
|
+
|
|
367
|
+
const deviceInfo = await DeviceInfoManager.getDeviceInfo();
|
|
368
|
+
const appVersion = deviceInfo['app_version'] || 'unknown';
|
|
369
|
+
|
|
370
|
+
if (__DEV__) {
|
|
371
|
+
console.log('Device Info:', deviceInfo);
|
|
372
|
+
console.log('App Version:', appVersion);
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
const deviceResp = await this._apiCall.callAPI(
|
|
376
|
+
'POST',
|
|
377
|
+
ServiceNames.DEVICE_SESSION.params({ partner }),
|
|
378
|
+
{
|
|
379
|
+
body: {
|
|
380
|
+
[Constants.MANUFACTURER]: deviceInfo[Constants.MANUFACTURER],
|
|
381
|
+
[Constants.MODEL]: deviceInfo[Constants.MODEL],
|
|
382
|
+
[Constants.DEVICE_UUID]: deviceInfo[Constants.DEVICE_UUID],
|
|
383
|
+
[Constants.OS]: deviceInfo[Constants.OS], // "Android"/"iOS" from your manager
|
|
384
|
+
[Constants.OS_VERSION]: deviceInfo[Constants.OS_VERSION],
|
|
385
|
+
[Constants.APP_VERSION]: appVersion,
|
|
386
|
+
},
|
|
387
|
+
}
|
|
388
|
+
);
|
|
389
|
+
|
|
390
|
+
// Nest device-session response into the same login JSON
|
|
391
|
+
loginData.device =
|
|
392
|
+
deviceResp?.data && typeof deviceResp.data === 'object'
|
|
393
|
+
? deviceResp.data
|
|
394
|
+
: { success: false, message: 'device session null' };
|
|
395
|
+
|
|
396
|
+
return loginData;
|
|
397
|
+
} catch (err: any) {
|
|
398
|
+
// Keep shape stable if device session fails
|
|
399
|
+
loginData.device = {
|
|
400
|
+
success: false,
|
|
401
|
+
message: String(err?.message || err),
|
|
402
|
+
};
|
|
403
|
+
return loginData;
|
|
404
|
+
}
|
|
405
|
+
} catch (err: any) {
|
|
406
|
+
// Absolute fallback: minimal error shape
|
|
407
|
+
return {
|
|
408
|
+
success: false,
|
|
409
|
+
message: `sdkLogin failed: ${String(err?.message || err)}`,
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
}
|
|
307
413
|
}
|
package/src/helpers/webview.tsx
CHANGED
|
@@ -30,6 +30,7 @@ import FileViewer from 'react-native-file-viewer';
|
|
|
30
30
|
import RNFS from 'react-native-fs';
|
|
31
31
|
import CookieManager from '@react-native-cookies/cookies';
|
|
32
32
|
import { AnalyticsLogger } from './analytics/analytics_logger';
|
|
33
|
+
import SendIntentAndroid from 'react-native-send-intent';
|
|
33
34
|
|
|
34
35
|
interface ExtendedWebViewProps extends WebViewProps {
|
|
35
36
|
onPermissionRequest?: (event: any) => void;
|
|
@@ -47,6 +48,63 @@ interface WebViewCustomProps {
|
|
|
47
48
|
whitelistedUrls?: string[];
|
|
48
49
|
onPageFinished?: () => void;
|
|
49
50
|
}
|
|
51
|
+
type MailApp = 'gmail' | 'outlook' | 'yahoo';
|
|
52
|
+
|
|
53
|
+
const PKG: Record<MailApp, string> = {
|
|
54
|
+
gmail: 'com.google.android.gm',
|
|
55
|
+
outlook: 'com.microsoft.office.outlook',
|
|
56
|
+
yahoo: 'com.yahoo.mobile.client.android.mail',
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const SCHEME: Record<MailApp, string> = {
|
|
60
|
+
gmail: 'googlegmail://',
|
|
61
|
+
outlook: 'ms-outlook://',
|
|
62
|
+
yahoo: 'ymail://',
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Try to open a specific mail app, like Gmail.
|
|
67
|
+
* Returns true if something was opened, false otherwise.
|
|
68
|
+
*
|
|
69
|
+
* Order of attempts:
|
|
70
|
+
* 1. openApp(<package>) via react-native-send-intent
|
|
71
|
+
* 2. Linking.openURL(<custom scheme>) as fallback
|
|
72
|
+
*/
|
|
73
|
+
export async function openMailAppIntent(app: MailApp): Promise<boolean> {
|
|
74
|
+
if (Platform.OS !== 'android') {
|
|
75
|
+
// iOS? We don't do anything special here. Just say "not handled".
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const pkg = PKG[app];
|
|
80
|
+
const scheme = SCHEME[app];
|
|
81
|
+
|
|
82
|
+
// Step 1: Try launching the package directly.
|
|
83
|
+
try {
|
|
84
|
+
// openApp(packageName) resolves to boolean: wasOpened
|
|
85
|
+
// according to the lib docs. :contentReference[oaicite:3]{index=3}
|
|
86
|
+
const wasOpened = await SendIntentAndroid.openApp(pkg, {});
|
|
87
|
+
if (wasOpened) {
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
} catch (err) {
|
|
91
|
+
console.log(`[mailIntent] openApp(${pkg}) failed:`, err);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Step 2: Fallback to the custom scheme.
|
|
95
|
+
try {
|
|
96
|
+
const canOpen = await Linking.canOpenURL(scheme);
|
|
97
|
+
if (canOpen) {
|
|
98
|
+
await Linking.openURL(scheme);
|
|
99
|
+
return true;
|
|
100
|
+
}
|
|
101
|
+
} catch (err2) {
|
|
102
|
+
console.log(`[mailIntent] Linking fallback (${scheme}) failed:`, err2);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
|
|
50
108
|
const clearAllCookies = async () => {
|
|
51
109
|
try {
|
|
52
110
|
await CookieManager.clearAll(true);
|
|
@@ -202,6 +260,35 @@ export const WebView = ({
|
|
|
202
260
|
if (url === 'about:blank' || url === 'about:srcdoc') {
|
|
203
261
|
return true;
|
|
204
262
|
}
|
|
263
|
+
if (Platform.OS === 'android' && url) {
|
|
264
|
+
if (url.includes('ms-outlook://')) {
|
|
265
|
+
console.log('Intent to open Outlook detected');
|
|
266
|
+
openMailAppIntent('outlook').then(
|
|
267
|
+
(ok) =>
|
|
268
|
+
!ok &&
|
|
269
|
+
ToastAndroid.show('Outlook app not found', ToastAndroid.SHORT)
|
|
270
|
+
);
|
|
271
|
+
return false; // cancel WebView navigation
|
|
272
|
+
}
|
|
273
|
+
if (url.includes('googlegmail://')) {
|
|
274
|
+
console.log('Intent to open Gmail detected');
|
|
275
|
+
openMailAppIntent('gmail').then(
|
|
276
|
+
(ok) =>
|
|
277
|
+
!ok && ToastAndroid.show('Gmail app not found', ToastAndroid.SHORT)
|
|
278
|
+
);
|
|
279
|
+
return false;
|
|
280
|
+
}
|
|
281
|
+
if (url.includes('ymail://')) {
|
|
282
|
+
console.log('Intent to open Yahoo Mail detected');
|
|
283
|
+
openMailAppIntent('yahoo').then(
|
|
284
|
+
(ok) =>
|
|
285
|
+
!ok &&
|
|
286
|
+
ToastAndroid.show('Yahoo Mail app not found', ToastAndroid.SHORT)
|
|
287
|
+
);
|
|
288
|
+
return false;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
205
292
|
// _analyticsLogger.logEvent({ event: 'REACT_NATIVE_LOADING_URL ', url });
|
|
206
293
|
|
|
207
294
|
if (
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"App.d.ts","sourceRoot":"","sources":["../../../rn78test/App.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAiD1B,iBAAS,GAAG,IAAI,KAAK,CAAC,GAAG,CAAC,OAAO,CAqDhC;AAqBD,eAAe,GAAG,CAAC"}
|