Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Changes for TV support #77

Merged
merged 1 commit into from
Oct 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

### 🎉 New features

- Add ability to show/hide different types of simulators, and add experimental TV support. ([#77](https://github.com/expo/orbit/pull/77) by [@douglowder](https://github.com/douglowder))
- Add support for opening tarballs with multiple apps. ([#73](https://github.com/expo/orbit/pull/73) by [@gabrieldonadel](https://github.com/gabrieldonadel))
- Improve feedback to the user when an error occurs. ([#64](https://github.com/expo/orbit/pull/64) by [@gabrieldonadel](https://github.com/gabrieldonadel))
- Added drag and drop support for installing apps. ([#57](https://github.com/expo/orbit/pull/57) by [@gabrieldonadel](https://github.com/gabrieldonadel))
Expand Down
7 changes: 0 additions & 7 deletions apps/menu-bar/.prettierrc.js

This file was deleted.

22 changes: 20 additions & 2 deletions apps/menu-bar/src/hooks/useListDevices.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ import { useCallback, useEffect, useState } from 'react';
import { DeviceEventEmitter } from 'react-native';

import { listDevicesAsync } from '../commands/listDevicesAsync';
import { UserPreferences } from '../modules/Storage';
import { getSectionsFromDeviceList } from '../utils/device';

export const useListDevices = () => {
export const useListDevices = (userPreferences: UserPreferences) => {
const [devicesPerPlatform, setDevicesPerPlatform] = useState<DevicesPerPlatform>({
android: { devices: [] },
ios: { devices: [] },
Expand All @@ -19,13 +20,30 @@ export const useListDevices = () => {
setLoading(true);
try {
const devicesList = await listDevicesAsync({ platform: 'all' });
const showIos = userPreferences.showIosSimulators;
const showTvos =
userPreferences.showExperimentalFeatures && userPreferences.showTvosSimulators;
const showAndroid = userPreferences.showAndroidEmulators;
if (!showIos) {
devicesList.ios.devices = devicesList.ios.devices.filter(
(device) => device.osType !== 'iOS'
);
}
if (!showTvos) {
devicesList.ios.devices = devicesList.ios.devices.filter(
(device) => device.osType !== 'tvOS'
);
}
if (!showAndroid) {
devicesList.android.devices = [];
}
setDevicesPerPlatform(devicesList);
} catch (err) {
setError(err as Error);
} finally {
setLoading(false);
}
}, []);
}, [userPreferences]);

useEffect(() => {
const listener = DeviceEventEmitter.addListener('popoverFocused', () => {
Expand Down
22 changes: 18 additions & 4 deletions apps/menu-bar/src/modules/Storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,28 @@ import { MMKV } from 'react-native-mmkv';
const userPreferencesStorageKey = 'user-preferences';

export type UserPreferences = {
launchOnLogin?: boolean;
emulatorWithoutAudio?: boolean;
launchOnLogin: boolean;
emulatorWithoutAudio: boolean;
customSdkPath?: string;
showExperimentalFeatures: boolean;
showIosSimulators: boolean;
showTvosSimulators: boolean;
showAndroidEmulators: boolean;
};

export const defaultUserPreferences: UserPreferences = {
launchOnLogin: false,
emulatorWithoutAudio: false,
showExperimentalFeatures: false,
showIosSimulators: true,
showTvosSimulators: false,
showAndroidEmulators: true,
};

export const getUserPreferences = async () => {
const value = await AsyncStorage.getItem(userPreferencesStorageKey);
return JSON.parse(value ?? '{}') as UserPreferences;
const stringValue = await AsyncStorage.getItem(userPreferencesStorageKey);
const value = (stringValue ? JSON.parse(stringValue) : defaultUserPreferences) as UserPreferences;
return value;
};

export const saveUserPreferences = async (preferences: UserPreferences) => {
Expand Down
69 changes: 67 additions & 2 deletions apps/menu-bar/src/popover/Core.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { bootDeviceAsync } from '../commands/bootDeviceAsync';
import { downloadBuildAsync } from '../commands/downloadBuildAsync';
import { installAndLaunchAppAsync } from '../commands/installAndLaunchAppAsync';
import { launchSnackAsync } from '../commands/launchSnackAsync';
import { Spacer, Text, View } from '../components';
import { Checkbox, Spacer, Text, View } from '../components';
import DeviceItem, { DEVICE_ITEM_HEIGHT } from '../components/DeviceItem';
import ProgressIndicator from '../components/ProgressIndicator';
import { useDeepLinking } from '../hooks/useDeepLinking';
Expand All @@ -31,6 +31,10 @@ import {
SelectedDevicesIds,
getSelectedDevicesIds,
saveSelectedDevicesIds,
UserPreferences,
defaultUserPreferences,
getUserPreferences,
saveUserPreferences,
} from '../modules/Storage';
import { openProjectsSelectorURL } from '../utils/constants';
import { getDeviceId, getDeviceOS, isVirtualDevice } from '../utils/device';
Expand All @@ -54,14 +58,23 @@ function Core(props: Props) {
android: undefined,
ios: undefined,
});
const [userPreferences, setUserPreferences] = useState<UserPreferences>(defaultUserPreferences);

useEffect(() => {
getUserPreferences().then((value) => {
saveUserPreferences(value);
setUserPreferences(value);
});
}, []);
gabrieldonadel marked this conversation as resolved.
Show resolved Hide resolved

const { apps } = useGetPinnedApps();
const showProjectsSection = Boolean(apps?.length);

const [status, setStatus] = useState(Status.LISTENING);
const [progress, setProgress] = useState(0);

const { devicesPerPlatform, numberOfDevices, sections, refetch } = useListDevices();
const { devicesPerPlatform, numberOfDevices, sections, refetch } =
useListDevices(userPreferences);
const { emulatorWithoutAudio } = useDeviceAudioPreferences();
const theme = useExpoTheme();

Expand Down Expand Up @@ -113,6 +126,36 @@ function Core(props: Props) {
[emulatorWithoutAudio]
);

const onPressShowIosSimulators = async (value: boolean) => {
const newPreferences = {
...userPreferences,
showIosSimulators: value,
};
saveUserPreferences(newPreferences).then(() => {
setUserPreferences(newPreferences);
});
};

const onPressShowTvosSimulators = async (value: boolean) => {
const newPreferences = {
...userPreferences,
showTvosSimulators: value,
};
saveUserPreferences(newPreferences).then(() => {
setUserPreferences(newPreferences);
});
};

const onPressShowAndroidEmulators = async (value: boolean) => {
const newPreferences = {
...userPreferences,
showAndroidEmulators: value,
};
saveUserPreferences(newPreferences).then(() => {
setUserPreferences(newPreferences);
});
};

// @TODO: create another hook
const handleSnackUrl = useCallback(
async (url: string) => {
Expand Down Expand Up @@ -277,6 +320,28 @@ function Core(props: Props) {
</View>
) : null}
</View>
<View px="medium" style={{ flexDirection: 'row' }}>
<Text size="small" weight="normal">
Devices to show:
</Text>
<Checkbox
value={userPreferences.showIosSimulators}
onValueChange={onPressShowIosSimulators}
label="iOS"
/>
{userPreferences.showExperimentalFeatures ? (
<Checkbox
value={userPreferences.showTvosSimulators}
onValueChange={onPressShowTvosSimulators}
label="tvOS"
/>
) : null}
<Checkbox
value={userPreferences.showAndroidEmulators}
onValueChange={onPressShowAndroidEmulators}
label="Android"
/>
</View>
{apps?.length ? <ProjectsSection apps={apps} /> : null}
<View shrink="1" pt="tiny">
<SectionList
Expand Down
5 changes: 4 additions & 1 deletion apps/menu-bar/src/utils/device.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,14 @@ export type BaseDevice = {
);

export function getDeviceOS(device: Device): 'android' | 'ios' {
if (device.osType === 'tvOS') {
return 'ios';
}
gabrieldonadel marked this conversation as resolved.
Show resolved Hide resolved
return device.osType.toLowerCase() as 'android' | 'ios';
}

export function getDeviceId(device: Device): string {
return device.osType === 'iOS' ? device.udid : device.name;
return device.osType === 'iOS' || device.osType === 'tvOS' ? device.udid : device.name;
}

export function getSectionsFromDeviceList(
Expand Down
25 changes: 24 additions & 1 deletion apps/menu-bar/src/windows/Settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import MenuBarModule from '../modules/MenuBarModule';
import SparkleModule from '../modules/SparkleModule';
import {
UserPreferences,
defaultUserPreferences,
getUserPreferences,
saveUserPreferences,
storage,
Expand All @@ -30,7 +31,7 @@ const Settings = () => {
Boolean(storage.getString('sessionSecret'))
);

const [userPreferences, setUserPreferences] = useState<UserPreferences>({});
const [userPreferences, setUserPreferences] = useState<UserPreferences>(defaultUserPreferences);
const [customSdkPathEnabled, setCustomSdkPathEnabled] = useState(false);
const [automaticallyChecksForUpdates, setAutomaticallyChecksForUpdates] = useState(false);

Expand Down Expand Up @@ -78,6 +79,14 @@ const Settings = () => {
SparkleModule.setAutomaticallyChecksForUpdates(value);
};

const onPressSetShowExperimentalFeatures = async (value: boolean) => {
setUserPreferences((prev) => {
const newPreferences = { ...prev, showExperimentalFeatures: value };
saveUserPreferences(newPreferences);
return newPreferences;
});
};

const onPressEmulatorWithoutAudio = async (value: boolean) => {
setUserPreferences((prev) => {
const newPreferences = { ...prev, emulatorWithoutAudio: value };
Expand Down Expand Up @@ -167,6 +176,13 @@ const Settings = () => {
color="primary"
/>
<Button title="Log In" onPress={() => handleAuthentication('login')} />
{__DEV__ ? (
<TouchableOpacity
onPress={() => WindowsNavigator.open('DebugMenu')}
style={[styles.debugButton, getStylesForColor('primary', theme)?.touchableStyle]}>
<SystemIconView systemIconName="ladybug" />
</TouchableOpacity>
) : null}
</Row>
)}
</View>
Expand Down Expand Up @@ -207,6 +223,13 @@ const Settings = () => {
label="Custom Android SDK root location"
/>
</Row>
<Row mb="2" align="center">
<Checkbox
value={userPreferences.showExperimentalFeatures}
onValueChange={onPressSetShowExperimentalFeatures}
label="Show experimental features (requires restart)"
/>
</Row>
<PathInput
editable={customSdkPathEnabled}
onChangeText={(text) => {
Expand Down
2 changes: 1 addition & 1 deletion packages/common-types/src/devices.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export interface IosSimulator {
runtime: string;
osVersion: string;
windowName: string;
osType: 'iOS';
osType: 'iOS' | 'tvOS';
state: 'Booted' | 'Shutdown';
isAvailable: boolean;
name: string;
Expand Down
6 changes: 3 additions & 3 deletions packages/eas-shared/src/run/ios/simulator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export async function getAvailableIosSimulatorsListAsync(query?: string): Promis
// Create an array [tvOS, 13, 4]
const [osType, ...osVersionComponents] = runtimeSuffix.split('-');

if (osType === 'iOS') {
if (osType === 'iOS' || osType === 'tvOS') {
// Join the end components [13, 4] -> '13.4'
const osVersion = osVersionComponents.join('.');
const sims = info.devices[runtime];
Expand All @@ -56,8 +56,8 @@ export async function getAvailableIosSimulatorsListAsync(query?: string): Promis
...device,
runtime,
osVersion,
windowName: `${device.name} (${osVersion})`,
osType: 'iOS' as const,
windowName: `${device.osType} ${device.name} (${osVersion})`,
osType,
state: device.state as 'Booted' | 'Shutdown',
deviceType: 'simulator',
lastBootedAt: device.lastBootedAt ? new Date(device.lastBootedAt).getTime() : undefined,
Expand Down