@osano/osano-cmp-react-native 0.13.0 → 0.15.0
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.dev.md +237 -12
- package/android/build.gradle +1 -1
- package/android/src/main/java/com/OsanoCMPSDK/OsanoCMPSDKModule.kt +147 -64
- package/android/src/main/java/com/OsanoCMPSDK/OsanoCMPSDKPackage.kt +0 -1
- package/ios/OsanoCmpSDK.mm +33 -3
- package/ios/OsanoCmpSdk.h +0 -7
- package/lib/commonjs/ConsentManager.js +32 -4
- package/lib/commonjs/ConsentManager.js.map +1 -1
- package/lib/commonjs/components/Button.js +105 -95
- package/lib/commonjs/components/Button.js.map +1 -1
- package/lib/commonjs/components/Locale.js +5 -3
- package/lib/commonjs/components/Locale.js.map +1 -1
- package/lib/commonjs/index.js +1 -1
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/native/OsanoCmp.js +35 -8
- package/lib/commonjs/native/OsanoCmp.js.map +1 -1
- package/lib/commonjs/native/OsanoCmpSdkSpec.js +9 -0
- package/lib/commonjs/native/OsanoCmpSdkSpec.js.map +1 -0
- package/lib/commonjs/services/consent.js +6 -2
- package/lib/commonjs/services/consent.js.map +1 -1
- package/lib/commonjs/utils/ExpoDetector.js +105 -0
- package/lib/commonjs/utils/ExpoDetector.js.map +1 -0
- package/lib/commonjs/utils/ExpoGoMemoryStorage.js +61 -0
- package/lib/commonjs/utils/ExpoGoMemoryStorage.js.map +1 -0
- package/lib/commonjs/views/Dialog/Buttons.js +26 -16
- package/lib/commonjs/views/Dialog/Buttons.js.map +1 -1
- package/lib/commonjs/views/Dialog/index.js +58 -95
- package/lib/commonjs/views/Dialog/index.js.map +1 -1
- package/lib/commonjs/views/Drawer/Drawer.ConsentCategories.js +12 -13
- package/lib/commonjs/views/Drawer/Drawer.ConsentCategories.js.map +1 -1
- package/lib/commonjs/views/Drawer/Drawer.Header.js +2 -2
- package/lib/commonjs/views/Drawer/Drawer.Header.js.map +1 -1
- package/lib/commonjs/views/Drawer/Drawer.Iab.Disclosures.js +10 -1
- package/lib/commonjs/views/Drawer/Drawer.Iab.Disclosures.js.map +1 -1
- package/lib/commonjs/views/Drawer/index.js +5 -4
- package/lib/commonjs/views/Drawer/index.js.map +1 -1
- package/lib/module/ConsentManager.js +32 -4
- package/lib/module/ConsentManager.js.map +1 -1
- package/lib/module/components/Button.js +99 -88
- package/lib/module/components/Button.js.map +1 -1
- package/lib/module/components/Locale.js +4 -3
- package/lib/module/components/Locale.js.map +1 -1
- package/lib/module/index.js +1 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/native/OsanoCmp.js +34 -8
- package/lib/module/native/OsanoCmp.js.map +1 -1
- package/lib/module/native/OsanoCmpSdkSpec.js +3 -0
- package/lib/module/native/OsanoCmpSdkSpec.js.map +1 -0
- package/lib/module/services/consent.js +7 -3
- package/lib/module/services/consent.js.map +1 -1
- package/lib/module/utils/ExpoDetector.js +98 -0
- package/lib/module/utils/ExpoDetector.js.map +1 -0
- package/lib/module/utils/ExpoGoMemoryStorage.js +54 -0
- package/lib/module/utils/ExpoGoMemoryStorage.js.map +1 -0
- package/lib/module/views/Dialog/Buttons.js +27 -17
- package/lib/module/views/Dialog/Buttons.js.map +1 -1
- package/lib/module/views/Dialog/index.js +59 -96
- package/lib/module/views/Dialog/index.js.map +1 -1
- package/lib/module/views/Drawer/Drawer.ConsentCategories.js +10 -12
- package/lib/module/views/Drawer/Drawer.ConsentCategories.js.map +1 -1
- package/lib/module/views/Drawer/Drawer.Header.js +2 -2
- package/lib/module/views/Drawer/Drawer.Header.js.map +1 -1
- package/lib/module/views/Drawer/Drawer.Iab.Disclosures.js +10 -1
- package/lib/module/views/Drawer/Drawer.Iab.Disclosures.js.map +1 -1
- package/lib/module/views/Drawer/index.js +6 -6
- package/lib/module/views/Drawer/index.js.map +1 -1
- package/lib/typescript/lib/commonjs/ConsentManager.d.ts.map +1 -1
- package/lib/typescript/lib/commonjs/components/Button.d.ts +4 -4
- package/lib/typescript/lib/commonjs/components/Button.d.ts.map +1 -1
- package/lib/typescript/lib/commonjs/components/Locale.d.ts.map +1 -1
- package/lib/typescript/lib/commonjs/hooks/useDeviceOrientation.d.ts +1 -1
- package/lib/typescript/lib/commonjs/native/OsanoCmp.d.ts.map +1 -1
- package/lib/typescript/lib/commonjs/native/OsanoCmpSdkSpec.d.ts +5 -0
- package/lib/typescript/lib/commonjs/native/OsanoCmpSdkSpec.d.ts.map +1 -0
- package/lib/typescript/lib/commonjs/services/consent.d.ts.map +1 -1
- package/lib/typescript/lib/commonjs/utils/ExpoDetector.d.ts +28 -0
- package/lib/typescript/lib/commonjs/utils/ExpoDetector.d.ts.map +1 -0
- package/lib/typescript/lib/commonjs/utils/ExpoGoMemoryStorage.d.ts +22 -0
- package/lib/typescript/lib/commonjs/utils/ExpoGoMemoryStorage.d.ts.map +1 -0
- package/lib/typescript/lib/commonjs/views/Dialog/Buttons.d.ts.map +1 -1
- package/lib/typescript/lib/commonjs/views/Dialog/index.d.ts.map +1 -1
- package/lib/typescript/lib/commonjs/views/Drawer/Drawer.ConsentCategories.d.ts.map +1 -1
- package/lib/typescript/lib/commonjs/views/Drawer/Drawer.Iab.Disclosures.d.ts.map +1 -1
- package/lib/typescript/lib/commonjs/views/Drawer/index.d.ts.map +1 -1
- package/lib/typescript/lib/module/ConsentManager.d.ts.map +1 -1
- package/lib/typescript/lib/module/components/Button.d.ts +7 -7
- package/lib/typescript/lib/module/components/Button.d.ts.map +1 -1
- package/lib/typescript/lib/module/components/Locale.d.ts +4 -1
- package/lib/typescript/lib/module/components/Locale.d.ts.map +1 -1
- package/lib/typescript/lib/module/hooks/useDeviceOrientation.d.ts +1 -1
- package/lib/typescript/lib/module/native/OsanoCmp.d.ts.map +1 -1
- package/lib/typescript/lib/module/native/OsanoCmpSdkSpec.d.ts +3 -0
- package/lib/typescript/lib/module/native/OsanoCmpSdkSpec.d.ts.map +1 -0
- package/lib/typescript/lib/module/services/consent.d.ts.map +1 -1
- package/lib/typescript/lib/module/utils/ExpoDetector.d.ts +27 -0
- package/lib/typescript/lib/module/utils/ExpoDetector.d.ts.map +1 -0
- package/lib/typescript/lib/module/utils/ExpoGoMemoryStorage.d.ts +21 -0
- package/lib/typescript/lib/module/utils/ExpoGoMemoryStorage.d.ts.map +1 -0
- package/lib/typescript/lib/module/views/Dialog/Buttons.d.ts.map +1 -1
- package/lib/typescript/lib/module/views/Dialog/index.d.ts.map +1 -1
- package/lib/typescript/lib/module/views/Drawer/Drawer.ConsentCategories.d.ts.map +1 -1
- package/lib/typescript/lib/module/views/Drawer/Drawer.Header.d.ts.map +1 -1
- package/lib/typescript/lib/module/views/Drawer/Drawer.Iab.Disclosures.d.ts.map +1 -1
- package/lib/typescript/lib/module/views/Drawer/index.d.ts.map +1 -1
- package/lib/typescript/src/ConsentManager.d.ts.map +1 -1
- package/lib/typescript/src/components/Button.d.ts +7 -7
- package/lib/typescript/src/components/Button.d.ts.map +1 -1
- package/lib/typescript/src/components/Locale.d.ts +2 -1
- package/lib/typescript/src/components/Locale.d.ts.map +1 -1
- package/lib/typescript/src/native/OsanoCmp.d.ts.map +1 -1
- package/lib/typescript/src/native/OsanoCmpSdkSpec.d.ts +17 -0
- package/lib/typescript/src/native/OsanoCmpSdkSpec.d.ts.map +1 -0
- package/lib/typescript/src/services/consent.d.ts.map +1 -1
- package/lib/typescript/src/utils/ExpoDetector.d.ts +29 -0
- package/lib/typescript/src/utils/ExpoDetector.d.ts.map +1 -0
- package/lib/typescript/src/utils/ExpoGoMemoryStorage.d.ts +21 -0
- package/lib/typescript/src/utils/ExpoGoMemoryStorage.d.ts.map +1 -0
- package/lib/typescript/src/views/Dialog/Buttons.d.ts +4 -2
- package/lib/typescript/src/views/Dialog/Buttons.d.ts.map +1 -1
- package/lib/typescript/src/views/Dialog/index.d.ts +1 -1
- package/lib/typescript/src/views/Dialog/index.d.ts.map +1 -1
- package/lib/typescript/src/views/Drawer/Drawer.ConsentCategories.d.ts.map +1 -1
- package/lib/typescript/src/views/Drawer/Drawer.Header.d.ts +1 -1
- package/lib/typescript/src/views/Drawer/Drawer.Header.d.ts.map +1 -1
- package/lib/typescript/src/views/Drawer/Drawer.Iab.Disclosures.d.ts.map +1 -1
- package/lib/typescript/src/views/Drawer/index.d.ts.map +1 -1
- package/osano-cmp-sdk.podspec +15 -15
- package/package.json +28 -3
- package/src/ConsentManager.ts +37 -4
- package/src/components/Button.tsx +122 -88
- package/src/components/Locale.tsx +28 -28
- package/src/constants.ts +2 -2
- package/src/index.tsx +1 -1
- package/src/native/OsanoCmp.ts +39 -23
- package/src/native/OsanoCmpSdkSpec.ts +25 -0
- package/src/services/consent.ts +9 -3
- package/src/utils/ExpoDetector.ts +114 -0
- package/src/utils/ExpoGoMemoryStorage.ts +61 -0
- package/src/views/Dialog/Buttons.tsx +33 -23
- package/src/views/Dialog/index.tsx +164 -208
- package/src/views/Drawer/Drawer.ConsentCategories.tsx +25 -25
- package/src/views/Drawer/Drawer.Header.tsx +7 -7
- package/src/views/Drawer/Drawer.Iab.Disclosures.tsx +6 -3
- package/src/views/Drawer/index.tsx +20 -19
- package/android/src/main/AndroidManifestNew.xml +0 -2
package/src/native/OsanoCmp.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { NativeModules, Platform } from 'react-native';
|
|
2
|
+
import OsanoCmpSdkTurboModule from './OsanoCmpSdkSpec';
|
|
3
|
+
import { ExpoDetector } from '../utils/ExpoDetector';
|
|
4
|
+
import { ExpoGoMemoryStorage } from '../utils/ExpoGoMemoryStorage';
|
|
2
5
|
|
|
3
6
|
const LINKING_ERROR =
|
|
4
7
|
`The package 'osano-cmp-react-native' doesn't seem to be linked. Make sure: \n\n` +
|
|
@@ -6,56 +9,69 @@ const LINKING_ERROR =
|
|
|
6
9
|
'- You rebuilt the app after installing the package\n' +
|
|
7
10
|
'- You are not using Expo Go\n';
|
|
8
11
|
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
{}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
},
|
|
18
|
-
},
|
|
19
|
-
);
|
|
12
|
+
const OsanoCmp = OsanoCmpSdkTurboModule || NativeModules.OsanoCmpSdk || new Proxy(
|
|
13
|
+
{},
|
|
14
|
+
{
|
|
15
|
+
get(_, prop) {
|
|
16
|
+
throw new Error(`${LINKING_ERROR}\nAttempted to call: ${String(prop)}`);
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
);
|
|
20
20
|
|
|
21
21
|
export function getDeviceId(): Promise<string | null | undefined> {
|
|
22
|
+
if (ExpoDetector.isExpoGo()) {
|
|
23
|
+
return ExpoGoMemoryStorage.getDeviceId();
|
|
24
|
+
}
|
|
22
25
|
return OsanoCmp.getDeviceId();
|
|
23
26
|
}
|
|
24
27
|
export function setStorage(key: string, value: string): Promise<string> {
|
|
28
|
+
if (ExpoDetector.isExpoGo()) {
|
|
29
|
+
return ExpoGoMemoryStorage.setStorage(key, value);
|
|
30
|
+
}
|
|
25
31
|
return OsanoCmp.setStorage(key, value);
|
|
26
32
|
}
|
|
27
33
|
export function getStorage(key: string): Promise<string | null | undefined> {
|
|
34
|
+
if (ExpoDetector.isExpoGo()) {
|
|
35
|
+
return ExpoGoMemoryStorage.getStorage(key);
|
|
36
|
+
}
|
|
28
37
|
return OsanoCmp.getStorage(key);
|
|
29
38
|
}
|
|
30
39
|
export function clearStorage(key: string): Promise<void> {
|
|
40
|
+
if (ExpoDetector.isExpoGo()) {
|
|
41
|
+
return ExpoGoMemoryStorage.clearStorage(key);
|
|
42
|
+
}
|
|
31
43
|
return OsanoCmp.clearStorage(key);
|
|
32
44
|
}
|
|
33
45
|
export function setStorageToDefault(
|
|
34
46
|
key: string,
|
|
35
47
|
value: string,
|
|
36
48
|
): Promise<string> {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
49
|
+
if (ExpoDetector.isExpoGo()) {
|
|
50
|
+
return ExpoGoMemoryStorage.setStorageToDefault(key, value);
|
|
51
|
+
}
|
|
52
|
+
return OsanoCmp.setStorageToDefault?.(key, value) ?? Promise.resolve(value);
|
|
40
53
|
}
|
|
41
54
|
export function setIntStorageToDefault(
|
|
42
55
|
key: string,
|
|
43
56
|
value: number,
|
|
44
57
|
): Promise<number> {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
58
|
+
if (ExpoDetector.isExpoGo()) {
|
|
59
|
+
return ExpoGoMemoryStorage.setIntStorageToDefault(key, value);
|
|
60
|
+
}
|
|
61
|
+
return OsanoCmp.setIntStorageToDefault?.(key, value) ?? Promise.resolve(value);
|
|
48
62
|
}
|
|
49
63
|
export function setBoolStorageToDefault(
|
|
50
64
|
key: string,
|
|
51
65
|
value: boolean,
|
|
52
66
|
): Promise<boolean> {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
67
|
+
if (ExpoDetector.isExpoGo()) {
|
|
68
|
+
return ExpoGoMemoryStorage.setBoolStorageToDefault(key, value);
|
|
69
|
+
}
|
|
70
|
+
return OsanoCmp.setBoolStorageToDefault?.(key, value) ?? Promise.resolve(value);
|
|
56
71
|
}
|
|
57
72
|
export function clearStorageFromDefault(key: string): Promise<void> {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
73
|
+
if (ExpoDetector.isExpoGo()) {
|
|
74
|
+
return ExpoGoMemoryStorage.clearStorageFromDefault(key);
|
|
75
|
+
}
|
|
76
|
+
return OsanoCmp.clearStorageFromDefault?.(key) ?? Promise.resolve();
|
|
61
77
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { TurboModule } from 'react-native';
|
|
2
|
+
import { TurboModuleRegistry } from 'react-native';
|
|
3
|
+
|
|
4
|
+
export interface Spec extends TurboModule {
|
|
5
|
+
// Core storage methods
|
|
6
|
+
setStorage(key: string, value: string): Promise<string>;
|
|
7
|
+
getStorage(key: string): Promise<string | null>;
|
|
8
|
+
clearStorage(key: string): Promise<void>;
|
|
9
|
+
|
|
10
|
+
// Default storage methods (iOS specific functionality)
|
|
11
|
+
setStorageToDefault(key: string, value: string): Promise<string>;
|
|
12
|
+
setIntStorageToDefault(key: string, value: number): Promise<number>;
|
|
13
|
+
setBoolStorageToDefault(key: string, value: boolean): Promise<boolean>;
|
|
14
|
+
clearStorageFromDefault(key: string): Promise<void>;
|
|
15
|
+
|
|
16
|
+
// Device identification
|
|
17
|
+
getDeviceId(): Promise<string>;
|
|
18
|
+
|
|
19
|
+
// Constants only (no synchronous methods for TurboModule compatibility)
|
|
20
|
+
getConstants(): {
|
|
21
|
+
IS_OFFICIAL_SAMPLE: boolean;
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export default TurboModuleRegistry.get<Spec>('OsanoCmpSdk');
|
package/src/services/consent.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { sha512 } from 'js-sha512';
|
|
2
|
-
import { Platform } from 'react-native';
|
|
2
|
+
import { Platform, NativeModules } from 'react-native';
|
|
3
3
|
import { TextEncoder } from 'text-encoding';
|
|
4
4
|
import type { ConsentManager } from '../ConsentManager';
|
|
5
5
|
import {
|
|
@@ -17,6 +17,10 @@ const Buffer = require('buffer').Buffer;
|
|
|
17
17
|
|
|
18
18
|
const { CONSENT_URI, LOOKUPS_URI, OSANO_ORIGIN } = env;
|
|
19
19
|
|
|
20
|
+
const IS_OFFICIAL_SAMPLE: boolean = (NativeModules as any)?.OsanoCmpSdk?.IS_OFFICIAL_SAMPLE;
|
|
21
|
+
|
|
22
|
+
const CONSENTING_PLATFORM_TAG = IS_OFFICIAL_SAMPLE ? `${Platform.OS}.sample-react-native` : `${Platform.OS}.react-native`;
|
|
23
|
+
|
|
20
24
|
const overrideConfig: Partial<Config> = {
|
|
21
25
|
// Override config here
|
|
22
26
|
variant: 'two',
|
|
@@ -52,13 +56,14 @@ function createConsentPayload(
|
|
|
52
56
|
cmp: ConsentManager,
|
|
53
57
|
consent?: ConsentCategoryType[],
|
|
54
58
|
): ConsentPayload {
|
|
59
|
+
osanoLogger.debug(`Consenting Platform: ${CONSENTING_PLATFORM_TAG}`);
|
|
55
60
|
return Object.fromEntries(
|
|
56
61
|
Object.entries({
|
|
57
62
|
customerId: cmp.customerId,
|
|
58
63
|
configId: cmp.configId,
|
|
59
64
|
consented: consent ?? cmp.consent,
|
|
60
65
|
consentingDomain: cmp.consentingDomain,
|
|
61
|
-
consentingPlatform:
|
|
66
|
+
consentingPlatform: CONSENTING_PLATFORM_TAG,
|
|
62
67
|
deviceId: cmp.deviceId,
|
|
63
68
|
extUsrData: cmp.extUsrData,
|
|
64
69
|
}).filter(([, value]) => value !== undefined),
|
|
@@ -81,7 +86,7 @@ function createConsentRecordPayload(
|
|
|
81
86
|
osnoConfigId: cmp.configId,
|
|
82
87
|
consented: consentedCategories.join(','),
|
|
83
88
|
consentingDomain: cmp.consentingDomain,
|
|
84
|
-
consentingPlatform:
|
|
89
|
+
consentingPlatform: CONSENTING_PLATFORM_TAG,
|
|
85
90
|
userConsentId: cmp.deviceId,
|
|
86
91
|
extUsrData: hashedExtUsrData,
|
|
87
92
|
}).filter(([, value]) => value !== undefined),
|
|
@@ -134,6 +139,7 @@ export const clearConsent = async (cmp: ConsentManager) => {
|
|
|
134
139
|
clearStorage(`${STORAGE_KEY}_${cmp.configId}`).then(resConsent);
|
|
135
140
|
break;
|
|
136
141
|
default:
|
|
142
|
+
resConsent();
|
|
137
143
|
break;
|
|
138
144
|
}
|
|
139
145
|
});
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { Platform } from 'react-native';
|
|
2
|
+
import { osanoLogger as OsanoLogger } from './OsanoLogger';
|
|
3
|
+
|
|
4
|
+
interface ExpoDetectionResult {
|
|
5
|
+
isExpo: boolean;
|
|
6
|
+
isExpoGo: boolean;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export class ExpoDetector {
|
|
10
|
+
private static _detectionResult: ExpoDetectionResult | null = null;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Detect Expo environment and cache result
|
|
14
|
+
*/
|
|
15
|
+
public static detect(): ExpoDetectionResult {
|
|
16
|
+
// Return cached result if available
|
|
17
|
+
if (this._detectionResult) {
|
|
18
|
+
return this._detectionResult;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const result: ExpoDetectionResult = {
|
|
22
|
+
isExpo: false,
|
|
23
|
+
isExpoGo: false,
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
// Check for Expo runtime via globals
|
|
27
|
+
try {
|
|
28
|
+
const hasExpoGlobalProp = !!(global as any).expo;
|
|
29
|
+
|
|
30
|
+
if (hasExpoGlobalProp) {
|
|
31
|
+
result.isExpo = true;
|
|
32
|
+
|
|
33
|
+
// Analyze global.expo to distinguish Expo Go from dev builds
|
|
34
|
+
const globalExpoContent = (global as any).expo;
|
|
35
|
+
|
|
36
|
+
if (globalExpoContent && typeof globalExpoContent === 'object') {
|
|
37
|
+
const documentsDir = globalExpoContent.documentsDir || '';
|
|
38
|
+
const cacheDir = globalExpoContent.cacheDir || '';
|
|
39
|
+
|
|
40
|
+
// Check execution environment
|
|
41
|
+
const exponentConstants = globalExpoContent.modules?.ExponentConstants;
|
|
42
|
+
const executionEnvironment = exponentConstants?.executionEnvironment;
|
|
43
|
+
|
|
44
|
+
// Check for Expo Go app ID
|
|
45
|
+
const expoApplication = globalExpoContent.modules?.ExpoApplication;
|
|
46
|
+
const applicationId = expoApplication?.applicationId;
|
|
47
|
+
|
|
48
|
+
// Expo Go indicators: package name, execution env, app ID
|
|
49
|
+
const hasExpoGoPackageName = documentsDir.includes('host.exp.exponent') ||
|
|
50
|
+
cacheDir.includes('host.exp.exponent');
|
|
51
|
+
const isStoreClient = executionEnvironment === 'storeClient';
|
|
52
|
+
const hasExpoGoAppId = applicationId === 'host.exp.exponent';
|
|
53
|
+
|
|
54
|
+
if (hasExpoGoPackageName || isStoreClient || hasExpoGoAppId) {
|
|
55
|
+
result.isExpoGo = true;
|
|
56
|
+
} else {
|
|
57
|
+
result.isExpoGo = false;
|
|
58
|
+
}
|
|
59
|
+
} else {
|
|
60
|
+
// Assume dev build for safety
|
|
61
|
+
result.isExpoGo = false;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
} catch (error) {
|
|
65
|
+
OsanoLogger.debug(`Expo detection failed: ${String(error)}`);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Cache the result
|
|
69
|
+
this._detectionResult = result;
|
|
70
|
+
|
|
71
|
+
return result;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Check if running in Expo Go
|
|
76
|
+
*/
|
|
77
|
+
public static isExpoGo(): boolean {
|
|
78
|
+
const result = this.detect();
|
|
79
|
+
return result.isExpoGo;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Check if any Expo environment
|
|
84
|
+
*/
|
|
85
|
+
public static isExpo(): boolean {
|
|
86
|
+
const result = this.detect();
|
|
87
|
+
return result.isExpo;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Get environment description
|
|
92
|
+
*/
|
|
93
|
+
public static getEnvironmentDescription(): string {
|
|
94
|
+
const result = this.detect();
|
|
95
|
+
|
|
96
|
+
if (!result.isExpo) {
|
|
97
|
+
return 'Bare React Native';
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (result.isExpoGo) {
|
|
101
|
+
return 'Expo Go';
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return 'Expo Development Build';
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Reset cached result for testing
|
|
109
|
+
*/
|
|
110
|
+
public static resetCache(): void {
|
|
111
|
+
this._detectionResult = null;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-memory storage fallback for Expo Go environment
|
|
3
|
+
* Provides storage functionality when native modules are not available
|
|
4
|
+
*/
|
|
5
|
+
export class ExpoGoMemoryStorage {
|
|
6
|
+
private static storage = new Map<string, string>();
|
|
7
|
+
private static defaultStorage = new Map<string, string | number | boolean>();
|
|
8
|
+
|
|
9
|
+
static setStorage(key: string, value: string): Promise<string> {
|
|
10
|
+
this.storage.set(key, value);
|
|
11
|
+
return Promise.resolve(value);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
static getStorage(key: string): Promise<string | null> {
|
|
15
|
+
const value = this.storage.get(key) || null;
|
|
16
|
+
return Promise.resolve(value);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
static clearStorage(key: string): Promise<void> {
|
|
20
|
+
this.storage.delete(key);
|
|
21
|
+
return Promise.resolve();
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
static setStorageToDefault(key: string, value: string): Promise<string> {
|
|
25
|
+
this.defaultStorage.set(key, value);
|
|
26
|
+
return Promise.resolve(value);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
static setIntStorageToDefault(key: string, value: number): Promise<number> {
|
|
30
|
+
this.defaultStorage.set(key, value);
|
|
31
|
+
return Promise.resolve(value);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
static setBoolStorageToDefault(key: string, value: boolean): Promise<boolean> {
|
|
35
|
+
this.defaultStorage.set(key, value);
|
|
36
|
+
return Promise.resolve(value);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
static clearStorageFromDefault(key: string): Promise<void> {
|
|
40
|
+
this.defaultStorage.delete(key);
|
|
41
|
+
return Promise.resolve();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
static getDeviceId(): Promise<string> {
|
|
45
|
+
// Generate a consistent device ID for Expo Go session
|
|
46
|
+
let deviceId = this.storage.get('__expo_device_id');
|
|
47
|
+
if (!deviceId) {
|
|
48
|
+
deviceId = `expo_go_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
49
|
+
this.storage.set('__expo_device_id', deviceId);
|
|
50
|
+
}
|
|
51
|
+
return Promise.resolve(deviceId);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Clear all storage for testing purposes
|
|
56
|
+
*/
|
|
57
|
+
static clearAll(): void {
|
|
58
|
+
this.storage.clear();
|
|
59
|
+
this.defaultStorage.clear();
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import React, { useContext, useMemo } from 'react';
|
|
2
|
+
import { StyleSheet, View, type ViewProps, type ViewStyle } from 'react-native';
|
|
1
3
|
import {
|
|
2
4
|
AcceptAllButton,
|
|
3
5
|
AcceptButton,
|
|
@@ -6,24 +8,27 @@ import {
|
|
|
6
8
|
RejectAllButton,
|
|
7
9
|
SaveButton,
|
|
8
10
|
} from '../../components/Button';
|
|
9
|
-
import React, { useContext } from 'react';
|
|
10
|
-
import { StyleSheet, View, type ViewProps } from 'react-native';
|
|
11
|
-
|
|
12
11
|
import { OsanoPrivateContext } from '../../context';
|
|
13
12
|
import { isDialogOpen } from '../../selectors';
|
|
14
13
|
|
|
15
|
-
export const Buttons: React.FC<ViewProps> = (
|
|
14
|
+
export const Buttons: React.FC<ViewProps & { buttonStyle?: ViewStyle }> = (
|
|
15
|
+
props,
|
|
16
|
+
) => {
|
|
16
17
|
const { style } = props;
|
|
17
18
|
const { config, getState } = useContext(OsanoPrivateContext);
|
|
18
19
|
|
|
19
20
|
const state = getState();
|
|
20
21
|
const disabled = !isDialogOpen(state);
|
|
22
|
+
const buttonStyle = useMemo(
|
|
23
|
+
() => [styles.button, props.buttonStyle],
|
|
24
|
+
[props.buttonStyle],
|
|
25
|
+
);
|
|
21
26
|
|
|
22
27
|
// Button Group 1
|
|
23
28
|
if (config?.isConsentImplied) {
|
|
24
29
|
return config.forceManagePreferencesButton ? (
|
|
25
|
-
<View style={style}>
|
|
26
|
-
<ManagePreferencesButton disabled={disabled} style={
|
|
30
|
+
<View style={[styles.container, style]}>
|
|
31
|
+
<ManagePreferencesButton disabled={disabled} style={buttonStyle} />
|
|
27
32
|
</View>
|
|
28
33
|
) : null;
|
|
29
34
|
}
|
|
@@ -31,41 +36,46 @@ export const Buttons: React.FC<ViewProps> = (props) => {
|
|
|
31
36
|
// Button Group 2
|
|
32
37
|
if (config?.tcfIsApplicable || config?.isButtonGroupTwo) {
|
|
33
38
|
return (
|
|
34
|
-
<View style={style}>
|
|
39
|
+
<View style={[styles.container, style]}>
|
|
35
40
|
{config.showManagePreferencesButtonInDialog ? (
|
|
36
|
-
<ManagePreferencesButton
|
|
37
|
-
disabled={disabled}
|
|
38
|
-
style={styles.fullWidth}
|
|
39
|
-
/>
|
|
41
|
+
<ManagePreferencesButton disabled={disabled} style={buttonStyle} />
|
|
40
42
|
) : (
|
|
41
|
-
<SaveButton disabled={disabled} style={
|
|
43
|
+
<SaveButton disabled={disabled} style={buttonStyle} />
|
|
42
44
|
)}
|
|
43
|
-
<AcceptAllButton disabled={disabled} style={
|
|
45
|
+
<AcceptAllButton disabled={disabled} style={buttonStyle} />
|
|
44
46
|
{config.rejectAllRequired ? (
|
|
45
|
-
<RejectAllButton disabled={disabled} style={
|
|
47
|
+
<RejectAllButton disabled={disabled} style={buttonStyle} />
|
|
46
48
|
) : null}
|
|
47
49
|
</View>
|
|
48
50
|
);
|
|
49
51
|
}
|
|
50
52
|
|
|
53
|
+
// Default button group
|
|
51
54
|
return (
|
|
52
|
-
<View style={style}>
|
|
53
|
-
<AcceptButton disabled={disabled} style={
|
|
54
|
-
<DenyButton disabled={disabled} style={
|
|
55
|
+
<View style={[styles.container, style]}>
|
|
56
|
+
<AcceptButton disabled={disabled} style={buttonStyle} />
|
|
57
|
+
<DenyButton disabled={disabled} style={buttonStyle} />
|
|
55
58
|
{config?.rejectAllRequired ? (
|
|
56
|
-
<RejectAllButton disabled={disabled} style={
|
|
59
|
+
<RejectAllButton disabled={disabled} style={buttonStyle} />
|
|
57
60
|
) : null}
|
|
58
61
|
{config?.forceManagePreferencesButton ? (
|
|
59
|
-
<ManagePreferencesButton disabled={disabled} style={
|
|
62
|
+
<ManagePreferencesButton disabled={disabled} style={buttonStyle} />
|
|
60
63
|
) : null}
|
|
61
64
|
</View>
|
|
62
65
|
);
|
|
63
66
|
};
|
|
64
67
|
|
|
65
|
-
export default Buttons;
|
|
66
|
-
|
|
67
68
|
const styles = StyleSheet.create({
|
|
68
|
-
|
|
69
|
-
|
|
69
|
+
container: {
|
|
70
|
+
justifyContent: 'center',
|
|
71
|
+
alignItems: 'center',
|
|
72
|
+
gap: 8,
|
|
73
|
+
},
|
|
74
|
+
button: {
|
|
75
|
+
flex: 1,
|
|
76
|
+
minWidth: 120,
|
|
77
|
+
maxWidth: 200,
|
|
70
78
|
},
|
|
71
79
|
});
|
|
80
|
+
|
|
81
|
+
export default Buttons;
|