@savers_app/react-native-sandbox-sdk 1.2.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/LICENSE +20 -0
- package/README.md +556 -0
- package/lib/module/@types/@react-native-async-storage__async-storage.d.js +2 -0
- package/lib/module/@types/@react-native-async-storage__async-storage.d.js.map +1 -0
- package/lib/module/@types/@react-native-community__geolocation.d.js +2 -0
- package/lib/module/@types/@react-native-community__geolocation.d.js.map +1 -0
- package/lib/module/@types/react-native-aes-gcm-crypto.d.js +2 -0
- package/lib/module/@types/react-native-aes-gcm-crypto.d.js.map +1 -0
- package/lib/module/@types/react-native-device-info.d.js +2 -0
- package/lib/module/@types/react-native-device-info.d.js.map +1 -0
- package/lib/module/core/runtime.js +70 -0
- package/lib/module/core/runtime.js.map +1 -0
- package/lib/module/data/models/apiResponse.js +19 -0
- package/lib/module/data/models/apiResponse.js.map +1 -0
- package/lib/module/data/models/onboardingModel.js +67 -0
- package/lib/module/data/models/onboardingModel.js.map +1 -0
- package/lib/module/data/models/tokenModel.js +25 -0
- package/lib/module/data/models/tokenModel.js.map +1 -0
- package/lib/module/data/network/apiClient.js +109 -0
- package/lib/module/data/network/apiClient.js.map +1 -0
- package/lib/module/data/network/apiEndpoints.js +7 -0
- package/lib/module/data/network/apiEndpoints.js.map +1 -0
- package/lib/module/data/network/apiExceptionHandler.js +16 -0
- package/lib/module/data/network/apiExceptionHandler.js.map +1 -0
- package/lib/module/data/network/apiRepository.js +84 -0
- package/lib/module/data/network/apiRepository.js.map +1 -0
- package/lib/module/data/network/apiService.js +102 -0
- package/lib/module/data/network/apiService.js.map +1 -0
- package/lib/module/data/network/dataTypeUtils.js +77 -0
- package/lib/module/data/network/dataTypeUtils.js.map +1 -0
- package/lib/module/data/network/interceptors/authInterceptor.js +72 -0
- package/lib/module/data/network/interceptors/authInterceptor.js.map +1 -0
- package/lib/module/data/network/interceptors/errorInterceptor.js +15 -0
- package/lib/module/data/network/interceptors/errorInterceptor.js.map +1 -0
- package/lib/module/data/network/interceptors/loggingInterceptor.js +17 -0
- package/lib/module/data/network/interceptors/loggingInterceptor.js.map +1 -0
- package/lib/module/data/network/interceptors/networkInterceptor.js +22 -0
- package/lib/module/data/network/interceptors/networkInterceptor.js.map +1 -0
- package/lib/module/data/network/interceptors/retryInterceptor.js +22 -0
- package/lib/module/data/network/interceptors/retryInterceptor.js.map +1 -0
- package/lib/module/data/storage/asyncStorageManager.js +50 -0
- package/lib/module/data/storage/asyncStorageManager.js.map +1 -0
- package/lib/module/data/storage/deviceIdManager.js +45 -0
- package/lib/module/data/storage/deviceIdManager.js.map +1 -0
- package/lib/module/data/storage/keysManager.js +70 -0
- package/lib/module/data/storage/keysManager.js.map +1 -0
- package/lib/module/data/storage/locationManager.js +30 -0
- package/lib/module/data/storage/locationManager.js.map +1 -0
- package/lib/module/data/storage/reactRefManager.js +22 -0
- package/lib/module/data/storage/reactRefManager.js.map +1 -0
- package/lib/module/data/storage/sessionManager.js +12 -0
- package/lib/module/data/storage/sessionManager.js.map +1 -0
- package/lib/module/data/storage/storageKeys.js +7 -0
- package/lib/module/data/storage/storageKeys.js.map +1 -0
- package/lib/module/data/storage/storageManager.js +76 -0
- package/lib/module/data/storage/storageManager.js.map +1 -0
- package/lib/module/index.js +20 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/services/device/location.js +47 -0
- package/lib/module/services/device/location.js.map +1 -0
- package/lib/module/services/navigation/dialPad.js +29 -0
- package/lib/module/services/navigation/dialPad.js.map +1 -0
- package/lib/module/services/navigation/goBackNavigation.js +19 -0
- package/lib/module/services/navigation/goBackNavigation.js.map +1 -0
- package/lib/module/services/navigation/openBrowser.js +8 -0
- package/lib/module/services/navigation/openBrowser.js.map +1 -0
- package/lib/module/services/navigation/openMap.js +42 -0
- package/lib/module/services/navigation/openMap.js.map +1 -0
- package/lib/module/services/permissions/permissionManager.js +28 -0
- package/lib/module/services/permissions/permissionManager.js.map +1 -0
- package/lib/module/services/url/urlGenerator.js +94 -0
- package/lib/module/services/url/urlGenerator.js.map +1 -0
- package/lib/module/services/webview/messageHandler.js +72 -0
- package/lib/module/services/webview/messageHandler.js.map +1 -0
- package/lib/module/utils/config.js +34 -0
- package/lib/module/utils/config.js.map +1 -0
- package/lib/module/utils/dependencyManager.js +51 -0
- package/lib/module/utils/dependencyManager.js.map +1 -0
- package/lib/module/utils/encryption.js +63 -0
- package/lib/module/utils/encryption.js.map +1 -0
- package/lib/module/utils/errors.js +9 -0
- package/lib/module/utils/errors.js.map +1 -0
- package/lib/module/utils/logger.js +14 -0
- package/lib/module/utils/logger.js.map +1 -0
- package/lib/module/utils/platformManager.js +14 -0
- package/lib/module/utils/platformManager.js.map +1 -0
- package/lib/module/utils/validator.js +26 -0
- package/lib/module/utils/validator.js.map +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/core/runtime.d.ts +11 -0
- package/lib/typescript/src/core/runtime.d.ts.map +1 -0
- package/lib/typescript/src/data/models/apiResponse.d.ts +9 -0
- package/lib/typescript/src/data/models/apiResponse.d.ts.map +1 -0
- package/lib/typescript/src/data/models/onboardingModel.d.ts +24 -0
- package/lib/typescript/src/data/models/onboardingModel.d.ts.map +1 -0
- package/lib/typescript/src/data/models/tokenModel.d.ts +15 -0
- package/lib/typescript/src/data/models/tokenModel.d.ts.map +1 -0
- package/lib/typescript/src/data/network/apiClient.d.ts +17 -0
- package/lib/typescript/src/data/network/apiClient.d.ts.map +1 -0
- package/lib/typescript/src/data/network/apiEndpoints.d.ts +5 -0
- package/lib/typescript/src/data/network/apiEndpoints.d.ts.map +1 -0
- package/lib/typescript/src/data/network/apiExceptionHandler.d.ts +3 -0
- package/lib/typescript/src/data/network/apiExceptionHandler.d.ts.map +1 -0
- package/lib/typescript/src/data/network/apiRepository.d.ts +21 -0
- package/lib/typescript/src/data/network/apiRepository.d.ts.map +1 -0
- package/lib/typescript/src/data/network/apiService.d.ts +25 -0
- package/lib/typescript/src/data/network/apiService.d.ts.map +1 -0
- package/lib/typescript/src/data/network/dataTypeUtils.d.ts +10 -0
- package/lib/typescript/src/data/network/dataTypeUtils.d.ts.map +1 -0
- package/lib/typescript/src/data/network/interceptors/authInterceptor.d.ts +15 -0
- package/lib/typescript/src/data/network/interceptors/authInterceptor.d.ts.map +1 -0
- package/lib/typescript/src/data/network/interceptors/errorInterceptor.d.ts +4 -0
- package/lib/typescript/src/data/network/interceptors/errorInterceptor.d.ts.map +1 -0
- package/lib/typescript/src/data/network/interceptors/loggingInterceptor.d.ts +5 -0
- package/lib/typescript/src/data/network/interceptors/loggingInterceptor.d.ts.map +1 -0
- package/lib/typescript/src/data/network/interceptors/networkInterceptor.d.ts +4 -0
- package/lib/typescript/src/data/network/interceptors/networkInterceptor.d.ts.map +1 -0
- package/lib/typescript/src/data/network/interceptors/retryInterceptor.d.ts +7 -0
- package/lib/typescript/src/data/network/interceptors/retryInterceptor.d.ts.map +1 -0
- package/lib/typescript/src/data/storage/asyncStorageManager.d.ts +13 -0
- package/lib/typescript/src/data/storage/asyncStorageManager.d.ts.map +1 -0
- package/lib/typescript/src/data/storage/deviceIdManager.d.ts +2 -0
- package/lib/typescript/src/data/storage/deviceIdManager.d.ts.map +1 -0
- package/lib/typescript/src/data/storage/keysManager.d.ts +29 -0
- package/lib/typescript/src/data/storage/keysManager.d.ts.map +1 -0
- package/lib/typescript/src/data/storage/locationManager.d.ts +21 -0
- package/lib/typescript/src/data/storage/locationManager.d.ts.map +1 -0
- package/lib/typescript/src/data/storage/reactRefManager.d.ts +11 -0
- package/lib/typescript/src/data/storage/reactRefManager.d.ts.map +1 -0
- package/lib/typescript/src/data/storage/sessionManager.d.ts +3 -0
- package/lib/typescript/src/data/storage/sessionManager.d.ts.map +1 -0
- package/lib/typescript/src/data/storage/storageKeys.d.ts +5 -0
- package/lib/typescript/src/data/storage/storageKeys.d.ts.map +1 -0
- package/lib/typescript/src/data/storage/storageManager.d.ts +16 -0
- package/lib/typescript/src/data/storage/storageManager.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +18 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/services/device/location.d.ts +8 -0
- package/lib/typescript/src/services/device/location.d.ts.map +1 -0
- package/lib/typescript/src/services/navigation/dialPad.d.ts +3 -0
- package/lib/typescript/src/services/navigation/dialPad.d.ts.map +1 -0
- package/lib/typescript/src/services/navigation/goBackNavigation.d.ts +3 -0
- package/lib/typescript/src/services/navigation/goBackNavigation.d.ts.map +1 -0
- package/lib/typescript/src/services/navigation/openBrowser.d.ts +2 -0
- package/lib/typescript/src/services/navigation/openBrowser.d.ts.map +1 -0
- package/lib/typescript/src/services/navigation/openMap.d.ts +2 -0
- package/lib/typescript/src/services/navigation/openMap.d.ts.map +1 -0
- package/lib/typescript/src/services/permissions/permissionManager.d.ts +4 -0
- package/lib/typescript/src/services/permissions/permissionManager.d.ts.map +1 -0
- package/lib/typescript/src/services/url/urlGenerator.d.ts +44 -0
- package/lib/typescript/src/services/url/urlGenerator.d.ts.map +1 -0
- package/lib/typescript/src/services/webview/messageHandler.d.ts +2 -0
- package/lib/typescript/src/services/webview/messageHandler.d.ts.map +1 -0
- package/lib/typescript/src/utils/config.d.ts +5 -0
- package/lib/typescript/src/utils/config.d.ts.map +1 -0
- package/lib/typescript/src/utils/dependencyManager.d.ts +31 -0
- package/lib/typescript/src/utils/dependencyManager.d.ts.map +1 -0
- package/lib/typescript/src/utils/encryption.d.ts +5 -0
- package/lib/typescript/src/utils/encryption.d.ts.map +1 -0
- package/lib/typescript/src/utils/errors.d.ts +4 -0
- package/lib/typescript/src/utils/errors.d.ts.map +1 -0
- package/lib/typescript/src/utils/logger.d.ts +6 -0
- package/lib/typescript/src/utils/logger.d.ts.map +1 -0
- package/lib/typescript/src/utils/platformManager.d.ts +4 -0
- package/lib/typescript/src/utils/platformManager.d.ts.map +1 -0
- package/lib/typescript/src/utils/validator.d.ts +4 -0
- package/lib/typescript/src/utils/validator.d.ts.map +1 -0
- package/package.json +184 -0
- package/src/@types/@react-native-async-storage__async-storage.d.ts +7 -0
- package/src/@types/@react-native-community__geolocation.d.ts +18 -0
- package/src/@types/react-native-aes-gcm-crypto.d.ts +22 -0
- package/src/@types/react-native-device-info.d.ts +3 -0
- package/src/core/runtime.ts +84 -0
- package/src/data/models/apiResponse.ts +28 -0
- package/src/data/models/onboardingModel.ts +97 -0
- package/src/data/models/tokenModel.ts +43 -0
- package/src/data/network/apiClient.ts +148 -0
- package/src/data/network/apiEndpoints.ts +4 -0
- package/src/data/network/apiExceptionHandler.ts +16 -0
- package/src/data/network/apiRepository.ts +130 -0
- package/src/data/network/apiService.ts +113 -0
- package/src/data/network/dataTypeUtils.ts +78 -0
- package/src/data/network/interceptors/authInterceptor.ts +86 -0
- package/src/data/network/interceptors/errorInterceptor.ts +13 -0
- package/src/data/network/interceptors/loggingInterceptor.ts +16 -0
- package/src/data/network/interceptors/networkInterceptor.ts +20 -0
- package/src/data/network/interceptors/retryInterceptor.ts +24 -0
- package/src/data/storage/asyncStorageManager.ts +56 -0
- package/src/data/storage/deviceIdManager.ts +46 -0
- package/src/data/storage/keysManager.ts +89 -0
- package/src/data/storage/locationManager.ts +39 -0
- package/src/data/storage/reactRefManager.ts +25 -0
- package/src/data/storage/sessionManager.ts +11 -0
- package/src/data/storage/storageKeys.ts +4 -0
- package/src/data/storage/storageManager.ts +83 -0
- package/src/index.tsx +17 -0
- package/src/services/device/location.ts +51 -0
- package/src/services/navigation/dialPad.ts +39 -0
- package/src/services/navigation/goBackNavigation.ts +19 -0
- package/src/services/navigation/openBrowser.ts +6 -0
- package/src/services/navigation/openMap.ts +53 -0
- package/src/services/permissions/permissionManager.ts +33 -0
- package/src/services/url/urlGenerator.ts +140 -0
- package/src/services/webview/messageHandler.ts +45 -0
- package/src/utils/config.ts +35 -0
- package/src/utils/dependencyManager.ts +82 -0
- package/src/utils/encryption.ts +96 -0
- package/src/utils/errors.ts +6 -0
- package/src/utils/logger.ts +11 -0
- package/src/utils/platformManager.ts +14 -0
- package/src/utils/validator.ts +29 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
type AsyncStorageModule =
|
|
2
|
+
| {
|
|
3
|
+
getItem: (key: string) => Promise<string | null>;
|
|
4
|
+
setItem: (key: string, value: string) => Promise<void>;
|
|
5
|
+
}
|
|
6
|
+
| undefined;
|
|
7
|
+
|
|
8
|
+
type GeolocationModule =
|
|
9
|
+
| {
|
|
10
|
+
getCurrentPosition: (
|
|
11
|
+
success: (pos: {
|
|
12
|
+
coords: { latitude: number; longitude: number };
|
|
13
|
+
}) => void,
|
|
14
|
+
error?: (err: unknown) => void,
|
|
15
|
+
options?: {
|
|
16
|
+
enableHighAccuracy?: boolean;
|
|
17
|
+
timeout?: number;
|
|
18
|
+
maximumAge?: number;
|
|
19
|
+
}
|
|
20
|
+
) => void;
|
|
21
|
+
}
|
|
22
|
+
| undefined;
|
|
23
|
+
|
|
24
|
+
type DeviceInfoModule =
|
|
25
|
+
| {
|
|
26
|
+
getUniqueId?: () => Promise<string>;
|
|
27
|
+
}
|
|
28
|
+
| undefined;
|
|
29
|
+
|
|
30
|
+
let AsyncStorage: AsyncStorageModule;
|
|
31
|
+
let Geolocation: GeolocationModule;
|
|
32
|
+
let DeviceInfo: DeviceInfoModule;
|
|
33
|
+
|
|
34
|
+
function loadAsyncStorage(): AsyncStorageModule {
|
|
35
|
+
try {
|
|
36
|
+
const mod = require('@react-native-async-storage/async-storage');
|
|
37
|
+
return mod?.default ?? mod;
|
|
38
|
+
} catch {
|
|
39
|
+
return undefined;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function loadGeolocation(): GeolocationModule {
|
|
44
|
+
try {
|
|
45
|
+
const mod = require('@react-native-community/geolocation');
|
|
46
|
+
return mod?.default ?? mod;
|
|
47
|
+
} catch {
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function loadDeviceInfo(): DeviceInfoModule {
|
|
53
|
+
try {
|
|
54
|
+
const mod = require('react-native-device-info');
|
|
55
|
+
return mod?.default ?? mod;
|
|
56
|
+
} catch {
|
|
57
|
+
return undefined;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function resolveNativeDependencies() {
|
|
62
|
+
if (!AsyncStorage) AsyncStorage = loadAsyncStorage();
|
|
63
|
+
if (!Geolocation) Geolocation = loadGeolocation();
|
|
64
|
+
if (!DeviceInfo) DeviceInfo = loadDeviceInfo();
|
|
65
|
+
return {
|
|
66
|
+
AsyncStorage,
|
|
67
|
+
Geolocation,
|
|
68
|
+
DeviceInfo,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export const SDKRequirements = {
|
|
73
|
+
get asyncStorage() {
|
|
74
|
+
return Boolean(resolveNativeDependencies().AsyncStorage);
|
|
75
|
+
},
|
|
76
|
+
get geolocation() {
|
|
77
|
+
return Boolean(resolveNativeDependencies().Geolocation);
|
|
78
|
+
},
|
|
79
|
+
get deviceInfo() {
|
|
80
|
+
return Boolean(resolveNativeDependencies().DeviceInfo);
|
|
81
|
+
},
|
|
82
|
+
};
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { NativeModules } from 'react-native';
|
|
2
|
+
import AesGcmCrypto from 'react-native-aes-gcm-crypto';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Ensure native module is installed & linked
|
|
6
|
+
*/
|
|
7
|
+
function ensureAesAvailable() {
|
|
8
|
+
const nativeModule =
|
|
9
|
+
NativeModules.AesGcmCrypto || NativeModules.RNAesGcmCrypto;
|
|
10
|
+
|
|
11
|
+
if (!AesGcmCrypto || !nativeModule) {
|
|
12
|
+
throw new Error(
|
|
13
|
+
'react-native-aes-gcm-crypto is not installed or linked correctly.\n\n' +
|
|
14
|
+
'Fix:\n' +
|
|
15
|
+
'1. yarn add react-native-aes-gcm-crypto\n' +
|
|
16
|
+
'2. cd ios && pod install\n' +
|
|
17
|
+
'3. Rebuild the app\n'
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (typeof AesGcmCrypto.encrypt !== 'function') {
|
|
22
|
+
throw new Error(
|
|
23
|
+
'AES-GCM native functions unavailable. Please rebuild the app.'
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function isBase64(input: string): boolean {
|
|
29
|
+
return /^[A-Za-z0-9+/]+={0,2}$/.test(input);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function base64ByteLength(b64: string): number {
|
|
33
|
+
const cleaned = b64.replace(/[=]+$/, '');
|
|
34
|
+
return Math.floor((cleaned.length * 3) / 4);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export async function aesEncrypt(text: string, key: string): Promise<string> {
|
|
38
|
+
ensureAesAvailable();
|
|
39
|
+
|
|
40
|
+
if (!isBase64(key) || base64ByteLength(key) !== 32) {
|
|
41
|
+
throw new Error(
|
|
42
|
+
'Encryption key must be base64-encoded 32-byte (256-bit) value'
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
try {
|
|
47
|
+
const { iv, tag, content } = await AesGcmCrypto.encrypt(text, false, key);
|
|
48
|
+
|
|
49
|
+
return base64Encrypt(`${iv}:${content}:${tag}`);
|
|
50
|
+
} catch (err: any) {
|
|
51
|
+
throw new Error(`AES encryption failed: ${err?.message || err}`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export async function aesDecrypt(
|
|
56
|
+
ciphertext: string,
|
|
57
|
+
key: string
|
|
58
|
+
): Promise<string> {
|
|
59
|
+
ensureAesAvailable();
|
|
60
|
+
|
|
61
|
+
if (!isBase64(key) || base64ByteLength(key) !== 32) {
|
|
62
|
+
throw new Error(
|
|
63
|
+
'Encryption key must be base64-encoded 32-byte (256-bit) value'
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
try {
|
|
68
|
+
const [iv = '', content = '', tag = ''] = ciphertext.split(':');
|
|
69
|
+
|
|
70
|
+
const decrypted = await AesGcmCrypto.decrypt(content, key, iv, tag, false);
|
|
71
|
+
|
|
72
|
+
return decrypted;
|
|
73
|
+
} catch (err: any) {
|
|
74
|
+
throw new Error(`AES decryption failed: ${err?.message || err}`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
declare function btoa(data: string): string;
|
|
79
|
+
declare function atob(data: string): string;
|
|
80
|
+
|
|
81
|
+
export function base64Encrypt(plain: string): string {
|
|
82
|
+
const utf8 = encodeURIComponent(plain).replace(
|
|
83
|
+
/%([0-9A-F]{2})/g,
|
|
84
|
+
(_, p1: string) => String.fromCharCode(parseInt(p1, 16))
|
|
85
|
+
);
|
|
86
|
+
return btoa(utf8);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export function base64Decrypt(encoded: string): string {
|
|
90
|
+
const binary = atob(encoded);
|
|
91
|
+
const utf8 = binary
|
|
92
|
+
.split('')
|
|
93
|
+
.map((c) => '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2))
|
|
94
|
+
.join('');
|
|
95
|
+
return decodeURIComponent(utf8);
|
|
96
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// React Native Core
|
|
2
|
+
import { Platform } from 'react-native';
|
|
3
|
+
|
|
4
|
+
export function isIOS(): boolean {
|
|
5
|
+
return Platform.OS === 'ios';
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function isAndroid(): boolean {
|
|
9
|
+
return Platform.OS === 'android';
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function platformVersion(): number {
|
|
13
|
+
return Number(Platform.Version);
|
|
14
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// React Native Core
|
|
2
|
+
import { Linking } from 'react-native';
|
|
3
|
+
|
|
4
|
+
// Platform / Environment helpers
|
|
5
|
+
import { isIOS } from './platformManager';
|
|
6
|
+
|
|
7
|
+
export function isValidPhoneNumber(input: string): boolean {
|
|
8
|
+
if (!input) return false;
|
|
9
|
+
return /^\+?[0-9]{8,15}$/.test(input);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export async function isMapAppAvailable(): Promise<boolean> {
|
|
13
|
+
if (isIOS()) {
|
|
14
|
+
// Apple Maps scheme
|
|
15
|
+
return Linking.canOpenURL('maps:0,0?q=test');
|
|
16
|
+
}
|
|
17
|
+
// Android geo scheme
|
|
18
|
+
return Linking.canOpenURL('geo:0,0?q=0,0');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export async function isValidCoordinates(
|
|
22
|
+
lat: number,
|
|
23
|
+
lng: number
|
|
24
|
+
): Promise<boolean> {
|
|
25
|
+
if (!Number.isFinite(lat) || !Number.isFinite(lng)) return false;
|
|
26
|
+
if (lat < -90 || lat > 90) return false;
|
|
27
|
+
if (lng < -180 || lng > 180) return false;
|
|
28
|
+
return true;
|
|
29
|
+
}
|