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

add metro web support to NCL #27439

Merged
merged 26 commits into from Mar 5, 2024
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion apps/native-component-list/App.tsx
Expand Up @@ -5,14 +5,15 @@ import { Platform, StatusBar } from 'react-native';
import RootNavigation from './src/navigation/RootNavigation';
import loadAssetsAsync from './src/utilities/loadAssetsAsync';

SplashScreen.preventAutoHideAsync();

function useSplashScreen(loadingFunction: () => void) {
const [isLoadingCompleted, setLoadingComplete] = React.useState(false);

// Load any resources or data that we need prior to rendering the app
React.useEffect(() => {
async function loadAsync() {
try {
await SplashScreen.preventAutoHideAsync();
await loadingFunction();
} catch (e) {
// We might want to provide this error information to an error reporting service
Expand Down
3 changes: 3 additions & 0 deletions apps/native-component-list/app.json
Expand Up @@ -30,6 +30,9 @@
"updates": {
"url": "https://u.expo.dev/2c28de10-a2cd-11e6-b8ce-59d1587e6774"
},
"web": {
"bundler": "metro"
},
"facebookScheme": "fb1696089354000816",
"facebookAppId": "1696089354000816",
"facebookDisplayName": "Expo APIs",
Expand Down
1 change: 1 addition & 0 deletions apps/native-component-list/index.js
@@ -1,3 +1,4 @@
import '@expo/metro-runtime';
import { registerRootComponent } from 'expo';

import App from './App';
Expand Down
11 changes: 4 additions & 7 deletions apps/native-component-list/package.json
Expand Up @@ -6,14 +6,13 @@
"private": true,
"main": "index.js",
"scripts": {
"build:web": "expo export:web",
"web": "expo start --web --https",
"eject": "SDK_VERSION=43.0.0 expo prebuild",
"build:web": "expo export -p web",
"web": "expo start --web",
"lint": "eslint .",
"tsc": "tsc --noEmit -p ./tsconfig.json",
"start": "expo start",
"ios": "react-native run-ios",
"android": "react-native run-android"
"ios": "expo run:ios",
"android": "expo run:android"
},
"expo": {
"autolinking": {
Expand Down Expand Up @@ -153,15 +152,13 @@
},
"devDependencies": {
"@babel/core": "^7.23.7",
"@babel/plugin-transform-export-namespace-from": "^7.23.4",
"@types/fbemitter": "^2.0.32",
"@types/i18n-js": "^3.0.1",
"@types/pixi.js": "^4.8.6",
"@types/react": "~18.0.14",
"@types/three": "^0.137.0",
"@types/victory": "^31.0.14",
"babel-jest": "^29.2.1",
"babel-preset-expo": "~10.0.0",
"expo-module-scripts": "^3.0.0",
"jest": "^29.2.1",
"react-test-renderer": "18.2.0"
Expand Down
@@ -1,5 +1,4 @@
import Ionicons from '@expo/vector-icons/build/Ionicons';
import React from 'react';
import Ionicons from '@expo/vector-icons/Ionicons';
import { StyleSheet, TouchableOpacity, TouchableOpacityProps } from 'react-native';

type Props = TouchableOpacityProps & {
Expand Down
@@ -1,4 +1,4 @@
import Ionicons from '@expo/vector-icons/build/Ionicons';
import Ionicons from '@expo/vector-icons/Ionicons';
import { useNavigation } from '@react-navigation/native';
import React from 'react';
import {
Expand Down
2 changes: 1 addition & 1 deletion apps/native-component-list/src/components/SearchBar.tsx
@@ -1,4 +1,4 @@
import Ionicons from '@expo/vector-icons/build/Ionicons';
import Ionicons from '@expo/vector-icons/Ionicons';
import React from 'react';
import { StyleSheet, TextInput, TextStyle, TouchableOpacity, View, Platform } from 'react-native';

Expand Down
79 changes: 32 additions & 47 deletions apps/native-component-list/src/components/ShowActionSheetButton.tsx
@@ -1,45 +1,33 @@
import { ActionSheetOptions } from '@expo/react-native-action-sheet';
import MaterialCommunityIcons from '@expo/vector-icons/build/MaterialCommunityIcons';
import React from 'react';
import MaterialCommunityIcons from '@expo/vector-icons/MaterialCommunityIcons';
import { Text, TextStyle, View } from 'react-native';

const icon = (name: string) => <MaterialCommunityIcons key={name} name={name as any} size={24} />;

interface Props {
// A custom button that shows examples of different share sheet configurations
export default function ShowActionSheetButton({
title,
withTitle = false,
withMessage = false,
withIcons = false,
withSeparators = false,
withCustomStyles = false,
onSelection = null,
showActionSheetWithOptions,
}: {
title: string;
showActionSheetWithOptions: (
options: ActionSheetOptions,
onSelection: (index: number) => void
) => void;
onSelection: (index: number) => void;
onSelection: ((index: number) => void) | null;
withTitle?: boolean;
withMessage?: boolean;
withIcons?: boolean;
withSeparators?: boolean;
withCustomStyles?: boolean;
}

// A custom button that shows examples of different share sheet configurations
export default class ShowActionSheetButton extends React.PureComponent<Props> {
static defaultProps = {
withTitle: false,
withMessage: false,
withIcons: false,
withSeparators: false,
withCustomStyles: false,
onSelection: null,
};

_showActionSheet = () => {
const {
withTitle,
withMessage,
withIcons,
withSeparators,
withCustomStyles,
onSelection,
showActionSheetWithOptions,
} = this.props;
}) {
const showActionSheet = () => {
// Same interface as https://facebook.github.io/react-native/docs/actionsheetios.html
const options = ['Delete', 'Save', 'Share', 'Cancel'];
const icons = withIcons
Expand Down Expand Up @@ -82,28 +70,25 @@ export default class ShowActionSheetButton extends React.PureComponent<Props> {
},
(buttonIndex) => {
// Do something here depending on the button index selected
onSelection(buttonIndex);
onSelection?.(buttonIndex);
}
);
};

render() {
const { title } = this.props;
return (
<View style={{ margin: 6 }}>
<MaterialCommunityIcons.Button
name="code-tags"
backgroundColor="#3e3e3e"
onPress={this._showActionSheet}>
<Text
style={{
fontSize: 15,
color: '#fff',
}}>
{title}
</Text>
</MaterialCommunityIcons.Button>
</View>
);
}
return (
<View style={{ margin: 6 }}>
<MaterialCommunityIcons.Button
name="code-tags"
backgroundColor="#3e3e3e"
onPress={showActionSheet}>
<Text
style={{
fontSize: 15,
color: '#fff',
}}>
{title}
</Text>
</MaterialCommunityIcons.Button>
</View>
);
}
2 changes: 1 addition & 1 deletion apps/native-component-list/src/components/TabIcon.tsx
@@ -1,4 +1,4 @@
import MaterialCommunityIcons from '@expo/vector-icons/build/MaterialCommunityIcons';
import MaterialCommunityIcons from '@expo/vector-icons/MaterialCommunityIcons';
import React from 'react';
import { Platform } from 'react-native';

Expand Down
2 changes: 1 addition & 1 deletion apps/native-component-list/src/navigation/StackConfig.tsx
@@ -1,4 +1,4 @@
import Ionicons from '@expo/vector-icons/build/Ionicons';
import Ionicons from '@expo/vector-icons/Ionicons';
import { BottomTabNavigationProp } from '@react-navigation/bottom-tabs';
import { HeaderStyleInterpolators } from '@react-navigation/stack';
import * as React from 'react';
Expand Down
2 changes: 1 addition & 1 deletion apps/native-component-list/src/screens/AV/Player.tsx
@@ -1,4 +1,4 @@
import Ionicons from '@expo/vector-icons/build/Ionicons';
import Ionicons from '@expo/vector-icons/Ionicons';
import Slider from '@react-native-community/slider';
import SegmentedControl from '@react-native-segmented-control/segmented-control';
import { AVMetadata } from 'expo-av';
Expand Down
2 changes: 1 addition & 1 deletion apps/native-component-list/src/screens/AV/Recorder.tsx
@@ -1,4 +1,4 @@
import Ionicons from '@expo/vector-icons/build/Ionicons';
import Ionicons from '@expo/vector-icons/Ionicons';
import { Audio } from 'expo-av';
import React from 'react';
import {
Expand Down
59 changes: 23 additions & 36 deletions apps/native-component-list/src/screens/AV/RecordingScreen.tsx
@@ -1,46 +1,33 @@
import React from 'react';
import { PixelRatio, ScrollView, StyleSheet } from 'react-native';
import { useState } from 'react';
import { ScrollView, StyleSheet } from 'react-native';

import AudioModeSelector from './AudioModeSelector';
import Player from './AudioPlayer';
import Recorder from './Recorder';
import HeadingText from '../../components/HeadingText';

interface State {
recordingUri?: string;
export default function RecordingScreen() {
const [recordingUri, setRecordingUri] = useState<string | undefined>(undefined);

return (
<ScrollView contentContainerStyle={styles.contentContainer}>
<HeadingText>Audio mode</HeadingText>
<AudioModeSelector />
<HeadingText>Recorder</HeadingText>
<Recorder onDone={(recordingUri: string) => setRecordingUri(recordingUri)} />
{recordingUri && (
<>
<HeadingText>Last recording</HeadingText>
<Player source={{ uri: recordingUri }} />
</>
)}
</ScrollView>
);
}

// See: https://github.com/expo/expo/pull/10229#discussion_r490961694
// eslint-disable-next-line @typescript-eslint/ban-types
export default class RecordingScreen extends React.Component<{}, State> {
static navigationOptions = {
title: 'Audio Recording',
};

readonly state: State = {};

_handleRecordingFinished = (recordingUri: string) => this.setState({ recordingUri });

_maybeRenderLastRecording = () =>
this.state.recordingUri ? (
<>
<HeadingText>Last recording</HeadingText>
<Player source={{ uri: this.state.recordingUri }} />
</>
) : null;

render() {
return (
<ScrollView contentContainerStyle={styles.contentContainer}>
<HeadingText>Audio mode</HeadingText>
<AudioModeSelector />
<HeadingText>Recorder</HeadingText>
<Recorder onDone={this._handleRecordingFinished} />
{this._maybeRenderLastRecording()}
</ScrollView>
);
}
}
RecordingScreen.navigationOptions = {
title: 'Audio Recording',
};

const styles = StyleSheet.create({
contentContainer: {
Expand All @@ -65,7 +52,7 @@ const styles = StyleSheet.create({
marginHorizontal: 30,
},
player: {
borderBottomWidth: 1.0 / PixelRatio.get(),
borderBottomWidth: StyleSheet.hairlineWidth,
borderBottomColor: '#cccccc',
},
});
61 changes: 16 additions & 45 deletions apps/native-component-list/src/screens/AppearanceScreen.tsx
@@ -1,54 +1,25 @@
import React from 'react';
import { Appearance, StyleSheet, Text, View } from 'react-native';
import type { NativeEventSubscription } from 'react-native';
import { StyleSheet, Text, View, useColorScheme } from 'react-native';

type ColorSchemeName = Appearance.AppearancePreferences['colorScheme'];
export default function AppearanceScreen() {
const colorScheme = useColorScheme();

interface State {
colorScheme: ColorSchemeName;
}

// See: https://github.com/expo/expo/pull/10229#discussion_r490961694
// eslint-disable-next-line @typescript-eslint/ban-types
export default class AppearanceScreen extends React.Component<{}, State> {
static navigationOptions = {
title: 'Appearance',
};

subscription?: NativeEventSubscription;

state: State = {
colorScheme: Appearance.getColorScheme(),
};
const isDark = colorScheme === 'dark';

componentDidMount() {
this.subscription = Appearance.addChangeListener(
({ colorScheme }: { colorScheme: ColorSchemeName }) => {
this.setState({ colorScheme });
}
);
}
return (
<View style={[styles.screen, isDark ? styles.darkScreen : styles.lightScreen]}>
<Text style={isDark ? styles.darkText : styles.lightText}>
{`Current color scheme: `}

componentWillUnmount() {
if (this.subscription) this.subscription.remove();
}

render() {
const { colorScheme } = this.state;
const isDark = colorScheme === 'dark';

return (
<View style={[styles.screen, isDark ? styles.darkScreen : styles.lightScreen]}>
<Text style={isDark ? styles.darkText : styles.lightText}>
{`Current color scheme: `}

<Text style={styles.boldText}>{this.state.colorScheme}</Text>
</Text>
</View>
);
}
<Text style={styles.boldText}>{colorScheme}</Text>
</Text>
</View>
);
}

AppearanceScreen.navigationOptions = {
title: 'Appearance',
};

const styles = StyleSheet.create({
screen: {
flex: 1,
Expand Down