1import { requireNativeModule, EventEmitter } from 'expo-modules-core';
2import { NativeModules, NativeEventEmitter, Platform } from 'react-native';
3
4import { RecentApp } from '../providers/RecentlyOpenedAppsProvider';
5
6const DevLauncher =
7  Platform.OS === 'ios'
8    ? requireNativeModule('ExpoDevLauncherInternal')
9    : NativeModules.EXDevLauncherInternal;
10const emitter =
11  Platform.OS === 'ios' ? new EventEmitter(DevLauncher) : new NativeEventEmitter(DevLauncher);
12
13const ON_NEW_DEEP_LINK_EVENT = 'expo.modules.devlauncher.onnewdeeplink';
14
15export async function getRecentlyOpenedApps(): Promise<RecentApp[]> {
16  const recentlyOpenedApps = await DevLauncher.getRecentlyOpenedApps();
17  return recentlyOpenedApps;
18}
19
20export async function clearRecentlyOpenedApps(): Promise<void> {
21  return await DevLauncher.clearRecentlyOpenedApps();
22}
23
24export async function loadApp(url: string): Promise<void> {
25  return await DevLauncher.loadApp(url);
26}
27
28export async function loadUpdate(updateUrl: string, projectUrl: string) {
29  return await DevLauncher.loadUpdate(updateUrl, projectUrl);
30}
31
32export async function getNavigationStateAsync() {
33  return await DevLauncher.getNavigationState();
34}
35
36export async function consumeNavigationStateAsync() {
37  const serializedNavigationState = await DevLauncher.getNavigationState();
38  let navigationState;
39
40  try {
41    navigationState = JSON.parse(serializedNavigationState);
42  } catch {}
43
44  // not necessary to await this as its effects are only applied on app launch
45  clearNavigationStateAsync();
46  return navigationState;
47}
48
49export async function saveNavigationStateAsync(navigationState: string) {
50  return await DevLauncher.saveNavigationState(navigationState);
51}
52
53export async function clearNavigationStateAsync() {
54  return await DevLauncher.clearNavigationState();
55}
56
57export async function getPendingDeepLink(): Promise<string | null> {
58  return await DevLauncher.getPendingDeepLink();
59}
60
61export type CrashReport = {
62  timestamp: number;
63  message: string;
64  stack: string;
65};
66
67export async function getCrashReport(): Promise<CrashReport | null> {
68  return await DevLauncher.getCrashReport();
69}
70
71export async function openCamera(): Promise<void> {
72  return await DevLauncher.openCamera();
73}
74
75export function addDeepLinkListener(callback: (string) => void) {
76  return emitter.addListener(ON_NEW_DEEP_LINK_EVENT, callback);
77}
78
79export type BuildInfo = {
80  appName?: string;
81  appVersion?: string;
82  appIcon?: string;
83  sdkVersion?: string;
84  runtimeVersion?: string;
85  appId?: string;
86};
87
88export async function getBuildInfoAsync(): Promise<BuildInfo> {
89  return DevLauncher.getBuildInfo();
90}
91
92export async function copyToClipboardAsync(content: string): Promise<null> {
93  return DevLauncher.copyToClipboard(content);
94}
95
96export const clientUrlScheme = DevLauncher.clientUrlScheme;
97export const installationID = DevLauncher.installationID;
98export const isDevice = !!DevLauncher.isDevice;
99
100export type EXUpdatesConfig = {
101  runtimeVersion: string;
102  sdkVersion: string;
103  appId: string;
104  usesEASUpdates: boolean;
105  projectUrl: string;
106};
107
108export const updatesConfig: EXUpdatesConfig = DevLauncher.updatesConfig;
109
110export async function loadFontsAsync() {
111  return await DevLauncher.loadFontsAsync();
112}
113