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.
@@ -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
  }
@@ -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,10 +0,0 @@
1
- /**
2
- * Sample React Native App
3
- * https://github.com/facebook/react-native
4
- *
5
- * @format
6
- */
7
- import React from 'react';
8
- declare function App(): React.JSX.Element;
9
- export default App;
10
- //# sourceMappingURL=App.d.ts.map
@@ -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"}