1import { requireNativeModule } from 'expo-modules-core';
2import { DeviceEventEmitter, NativeModules, EventSubscription, Platform } from 'react-native';
3
4export type JSEngine = 'Hermes' | 'JSC' | 'V8';
5
6export type AppInfo = {
7  appIcon?: string;
8  appVersion?: string;
9  hostUrl?: string;
10  appName?: string;
11  sdkVersion?: string;
12  runtimeVersion?: string;
13  engine?: JSEngine;
14};
15
16export type DevSettings = {
17  isDebuggingRemotely?: boolean;
18  isElementInspectorShown?: boolean;
19  isHotLoadingEnabled?: boolean;
20  isPerfMonitorShown?: boolean;
21  isRemoteDebuggingAvailable?: boolean;
22  isElementInspectorAvailable?: boolean;
23  isHotLoadingAvailable?: boolean;
24  isPerfMonitorAvailable?: boolean;
25  isJSInspectorAvailable?: boolean;
26};
27
28export type MenuPreferences = {
29  isOnboardingFinished?: boolean;
30};
31
32const DevMenu =
33  Platform.OS === 'ios'
34    ? requireNativeModule('ExpoDevMenuInternal')
35    : NativeModules.ExpoDevMenuInternal;
36
37export async function dispatchCallableAsync(
38  callableId: string,
39  args: object | null = null
40): Promise<void> {
41  return await DevMenu.dispatchCallableAsync(callableId, args);
42}
43
44export function hideMenu(): void {
45  DevMenu.hideMenu();
46}
47
48export function closeMenu(): void {
49  DevMenu.closeMenu();
50}
51
52export function subscribeToCloseEvents(listener: () => void): EventSubscription {
53  return DeviceEventEmitter.addListener('closeDevMenu', listener);
54}
55
56export function subscribeToOpenEvents(listener: () => void): EventSubscription {
57  return DeviceEventEmitter.addListener('openDevMenu', listener);
58}
59
60export function openDevMenuFromReactNative() {
61  DevMenu.openDevMenuFromReactNative();
62}
63
64export async function togglePerformanceMonitorAsync() {
65  return await dispatchCallableAsync('performance-monitor');
66}
67
68export async function toggleElementInspectorAsync() {
69  return await dispatchCallableAsync('inspector');
70}
71
72export async function reloadAsync() {
73  return await dispatchCallableAsync('reload');
74}
75
76export async function toggleDebugRemoteJSAsync() {
77  return await dispatchCallableAsync('remote-debug');
78}
79
80export async function toggleFastRefreshAsync() {
81  return await dispatchCallableAsync('fast-refresh');
82}
83
84export async function openJSInspector() {
85  return await dispatchCallableAsync('js-inspector');
86}
87
88export async function copyToClipboardAsync(content: string) {
89  return await DevMenu.copyToClipboardAsync(content);
90}
91
92export async function setOnboardingFinishedAsync(isFinished: boolean) {
93  return await DevMenu.setOnboardingFinished(isFinished);
94}
95
96export async function loadFontsAsync() {
97  return await DevMenu.loadFontsAsync();
98}
99
100export async function fireCallbackAsync(name: string) {
101  return await DevMenu.fireCallback(name).catch((error) => console.warn(error.message));
102}
103