1import { Platform, uuid } from 'expo-modules-core';
2
3import {
4  ExecutionEnvironment,
5  NativeConstants,
6  PlatformManifest,
7  WebManifest,
8} from './Constants.types';
9
10const ID_KEY = 'EXPO_CONSTANTS_INSTALLATION_ID';
11
12declare let __DEV__: boolean;
13declare let process: { env: any };
14declare let navigator: Navigator;
15declare let location: Location;
16declare let localStorage: Storage;
17
18const _sessionId = uuid.v4();
19
20function getBrowserName(): string | undefined {
21  if (Platform.isDOMAvailable) {
22    const agent = navigator.userAgent.toLowerCase();
23    if (agent.includes('edge')) {
24      return 'Edge';
25    } else if (agent.includes('edg')) {
26      return 'Chromium Edge';
27    } else if (agent.includes('opr') && !!window['opr']) {
28      return 'Opera';
29    } else if (agent.includes('chrome') && !!window['chrome']) {
30      return 'Chrome';
31    } else if (agent.includes('trident')) {
32      return 'IE';
33    } else if (agent.includes('firefox')) {
34      return 'Firefox';
35    } else if (agent.includes('safari')) {
36      return 'Safari';
37    }
38  }
39
40  return undefined;
41}
42
43export default {
44  get name(): string {
45    return 'ExponentConstants';
46  },
47  get appOwnership() {
48    return null;
49  },
50  get executionEnvironment() {
51    return ExecutionEnvironment.Bare;
52  },
53  get installationId(): string {
54    let installationId;
55    try {
56      installationId = localStorage.getItem(ID_KEY);
57      if (installationId == null || typeof installationId !== 'string') {
58        installationId = uuid.v4();
59        localStorage.setItem(ID_KEY, installationId as string);
60      }
61    } catch {
62      installationId = _sessionId;
63    } finally {
64      return installationId;
65    }
66  },
67  get sessionId(): string {
68    return _sessionId;
69  },
70  get platform(): PlatformManifest {
71    return { web: Platform.isDOMAvailable ? { ua: navigator.userAgent } : undefined };
72  },
73  get isHeadless(): boolean {
74    if (!Platform.isDOMAvailable) return true;
75
76    return /\bHeadlessChrome\//.test(navigator.userAgent);
77  },
78  get isDevice(): true {
79    // TODO: Bacon: Possibly want to add information regarding simulators
80    return true;
81  },
82  get expoVersion(): string | null {
83    return (this.manifest as any)!.sdkVersion || null;
84  },
85  get linkingUri(): string {
86    if (Platform.isDOMAvailable) {
87      // On native this is `exp://`
88      // On web we should use the protocol and hostname (location.origin)
89      return location.origin;
90    } else {
91      return '';
92    }
93  },
94  get expoRuntimeVersion(): string | null {
95    return this.expoVersion;
96  },
97  get deviceName(): string | undefined {
98    return getBrowserName();
99  },
100  get nativeAppVersion(): null {
101    return null;
102  },
103  get nativeBuildVersion(): null {
104    return null;
105  },
106  get systemFonts(): string[] {
107    // TODO: Bacon: Maybe possible.
108    return [];
109  },
110  get statusBarHeight(): number {
111    return 0;
112  },
113  get deviceYearClass(): number | null {
114    // TODO: Bacon: The android version isn't very accurate either, maybe we could try and guess this value.
115    return null;
116  },
117  get manifest(): WebManifest {
118    // This is defined by @expo/webpack-config.
119    // If your site is bundled with a different config then you may not have access to the app.json automatically.
120    return process.env.APP_MANIFEST || {};
121  },
122  get manifest2(): null {
123    return null;
124  },
125  get experienceUrl(): string {
126    if (Platform.isDOMAvailable) {
127      return location.origin;
128    } else {
129      return '';
130    }
131  },
132  get debugMode(): boolean {
133    return __DEV__;
134  },
135  async getWebViewUserAgentAsync(): Promise<string | null> {
136    if (Platform.isDOMAvailable) {
137      return navigator.userAgent;
138    } else {
139      return null;
140    }
141  },
142} as NativeConstants;
143