1import {
2  PermissionResponse,
3  PermissionStatus,
4  PermissionExpiration,
5  PermissionHookOptions,
6  UnavailabilityError,
7  createPermissionHook,
8} from 'expo-modules-core';
9import { Platform } from 'react-native';
10
11import ExpoTrackingTransparency from './ExpoTrackingTransparency';
12
13const androidAndWebPermissionsResponse: PermissionResponse = {
14  granted: true,
15  expires: 'never',
16  canAskAgain: true,
17  status: PermissionStatus.GRANTED,
18};
19
20/**
21 * Requests the user to authorize or deny access to app-related data that can be used for tracking
22 * the user or the device. Examples of data used for tracking include email address, device ID,
23 * advertising ID, etc. On iOS 14.5 and above, if the user denies this permission, any attempt to
24 * collect the IDFA will return a string of 0s.
25 *
26 * The system remembers the user’s choice and doesn’t prompt again unless a user uninstalls and then
27 * reinstalls the app on the device.
28 *
29 * On Android, web, and iOS 13 and below, this method always returns that the permission was
30 * granted.
31 * @example
32 * ```typescript
33 * const { granted } = await requestTrackingPermissionsAsync();
34 *
35 * if (granted) {
36 *   // Your app is authorized to track the user or their device
37 * }
38 * ```
39 */
40export async function requestTrackingPermissionsAsync(): Promise<PermissionResponse> {
41  if (Platform.OS !== 'ios') {
42    return Promise.resolve(androidAndWebPermissionsResponse);
43  }
44
45  if (!ExpoTrackingTransparency.requestPermissionsAsync) {
46    throw new UnavailabilityError('TrackingTransparency', 'requestPermissionsAsync');
47  }
48  return await ExpoTrackingTransparency.requestPermissionsAsync();
49}
50
51/**
52 * Checks whether or not the user has authorized the app to access app-related data that can be used
53 * for tracking the user or the device. See `requestTrackingPermissionsAsync` for more details.
54 *
55 * On Android, web, and iOS 13 and below, this method always returns that the permission was
56 * granted.
57 *
58 * @example
59 * ```typescript
60 * const { granted } = await getTrackingPermissionsAsync();
61 *
62 * if (granted) {
63 *   // Your app is authorized to track the user or their device
64 * }
65 * ```
66 */
67export async function getTrackingPermissionsAsync(): Promise<PermissionResponse> {
68  if (Platform.OS !== 'ios') {
69    return Promise.resolve(androidAndWebPermissionsResponse);
70  }
71
72  if (!ExpoTrackingTransparency.getPermissionsAsync) {
73    throw new UnavailabilityError('TrackingTransparency', 'getPermissionsAsync');
74  }
75  return await ExpoTrackingTransparency.getPermissionsAsync();
76}
77
78/**
79 * Check or request the user to authorize or deny access to app-related data that can be used for tracking
80 * the user or the device. Examples of data used for tracking include email address, device ID,
81 * advertising ID, etc. On iOS 14.5 and above, if the user denies this permission, any attempt to
82 * collect the IDFA will return a string of 0s.
83 *
84 * The system remembers the user’s choice and doesn’t prompt again unless a user uninstalls and then
85 * reinstalls the app on the device.
86 *
87 * On Android, web, and iOS 13 and below, this method always returns that the permission was
88 * granted.
89 * @example
90 * ```ts
91 * const [status, requestPermission] = useTrackingPermissions();
92 * ```
93 */
94export const useTrackingPermissions = createPermissionHook({
95  getMethod: getTrackingPermissionsAsync,
96  requestMethod: requestTrackingPermissionsAsync,
97});
98
99/**
100 * Returns whether the TrackingTransparency API is available on the current device.
101 *
102 * @returns Currently this is `true` on iOS 14 and above only. On devices where the
103 * Tracking Transparency API is unavailable, the get and request permissions methods will always
104 * resolve to `granted`.
105 */
106export function isAvailable(): boolean {
107  return (
108    Platform.OS === 'ios' &&
109    parseInt(Platform.Version.toString(), 10) >= 14 &&
110    ExpoTrackingTransparency
111  );
112}
113
114export { PermissionResponse, PermissionStatus, PermissionExpiration, PermissionHookOptions };
115