Created a new Expo app
This commit is contained in:
6
.expo-shared/assets.json
Normal file
6
.expo-shared/assets.json
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"e997a5256149a4b76e6bfd6cbf519c5e5a0f1d278a3d8fa1253022b03c90473b": true,
|
||||||
|
"af683c96e0ffd2cf81287651c9433fa44debc1220ca7cb431fe482747f34a505": true,
|
||||||
|
"12bb71342c6255bbf50437ec8f4441c083f47cdb74bd89160c15e4f43e52a1cb": true,
|
||||||
|
"40b842e832070c58deac6aa9e08fa459302ee3f9da492c7e77d93d2fbf4a56fd": true
|
||||||
|
}
|
||||||
13
.gitignore
vendored
Normal file
13
.gitignore
vendored
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
node_modules/**/*
|
||||||
|
.expo/*
|
||||||
|
npm-debug.*
|
||||||
|
*.jks
|
||||||
|
*.p8
|
||||||
|
*.p12
|
||||||
|
*.key
|
||||||
|
*.mobileprovision
|
||||||
|
*.orig.*
|
||||||
|
web-build/
|
||||||
|
|
||||||
|
# macOS
|
||||||
|
.DS_Store
|
||||||
23
App.tsx
Normal file
23
App.tsx
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import { StatusBar } from 'expo-status-bar';
|
||||||
|
import React from 'react';
|
||||||
|
import { SafeAreaProvider } from 'react-native-safe-area-context';
|
||||||
|
|
||||||
|
import useCachedResources from './hooks/useCachedResources';
|
||||||
|
import useColorScheme from './hooks/useColorScheme';
|
||||||
|
import Navigation from './navigation';
|
||||||
|
|
||||||
|
export default function App() {
|
||||||
|
const isLoadingComplete = useCachedResources();
|
||||||
|
const colorScheme = useColorScheme();
|
||||||
|
|
||||||
|
if (!isLoadingComplete) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<SafeAreaProvider>
|
||||||
|
<Navigation colorScheme={colorScheme} />
|
||||||
|
<StatusBar />
|
||||||
|
</SafeAreaProvider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
34
app.json
Normal file
34
app.json
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
{
|
||||||
|
"expo": {
|
||||||
|
"name": "naga",
|
||||||
|
"slug": "naga",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"orientation": "portrait",
|
||||||
|
"icon": "./assets/images/icon.png",
|
||||||
|
"scheme": "myapp",
|
||||||
|
"userInterfaceStyle": "automatic",
|
||||||
|
"splash": {
|
||||||
|
"image": "./assets/images/splash.png",
|
||||||
|
"resizeMode": "contain",
|
||||||
|
"backgroundColor": "#ffffff"
|
||||||
|
},
|
||||||
|
"updates": {
|
||||||
|
"fallbackToCacheTimeout": 0
|
||||||
|
},
|
||||||
|
"assetBundlePatterns": [
|
||||||
|
"**/*"
|
||||||
|
],
|
||||||
|
"ios": {
|
||||||
|
"supportsTablet": true
|
||||||
|
},
|
||||||
|
"android": {
|
||||||
|
"adaptiveIcon": {
|
||||||
|
"foregroundImage": "./assets/images/adaptive-icon.png",
|
||||||
|
"backgroundColor": "#FFFFFF"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"web": {
|
||||||
|
"favicon": "./assets/images/favicon.png"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
assets/fonts/SpaceMono-Regular.ttf
Normal file
BIN
assets/fonts/SpaceMono-Regular.ttf
Normal file
Binary file not shown.
BIN
assets/images/adaptive-icon.png
Normal file
BIN
assets/images/adaptive-icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
BIN
assets/images/favicon.png
Normal file
BIN
assets/images/favicon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.4 KiB |
BIN
assets/images/icon.png
Normal file
BIN
assets/images/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 22 KiB |
BIN
assets/images/splash.png
Normal file
BIN
assets/images/splash.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 47 KiB |
6
babel.config.js
Normal file
6
babel.config.js
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
module.exports = function(api) {
|
||||||
|
api.cache(true);
|
||||||
|
return {
|
||||||
|
presets: ['babel-preset-expo'],
|
||||||
|
};
|
||||||
|
};
|
||||||
108
components/EditScreenInfo.tsx
Normal file
108
components/EditScreenInfo.tsx
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
import * as WebBrowser from 'expo-web-browser';
|
||||||
|
import React from 'react';
|
||||||
|
import { StyleSheet, TouchableOpacity } from 'react-native';
|
||||||
|
|
||||||
|
import Colors from '../constants/Colors';
|
||||||
|
import { MonoText } from './StyledText';
|
||||||
|
import { Text, View } from './Themed';
|
||||||
|
|
||||||
|
export default function EditScreenInfo({ path }: { path: string }) {
|
||||||
|
return (
|
||||||
|
<View>
|
||||||
|
<View style={styles.getStartedContainer}>
|
||||||
|
<Text
|
||||||
|
style={styles.getStartedText}
|
||||||
|
lightColor="rgba(0,0,0,0.8)"
|
||||||
|
darkColor="rgba(255,255,255,0.8)">
|
||||||
|
Open up the code for this screen:
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<View
|
||||||
|
style={[styles.codeHighlightContainer, styles.homeScreenFilename]}
|
||||||
|
darkColor="rgba(255,255,255,0.05)"
|
||||||
|
lightColor="rgba(0,0,0,0.05)">
|
||||||
|
<MonoText>{path}</MonoText>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<Text
|
||||||
|
style={styles.getStartedText}
|
||||||
|
lightColor="rgba(0,0,0,0.8)"
|
||||||
|
darkColor="rgba(255,255,255,0.8)">
|
||||||
|
Change any of the text, save the file, and your app will automatically update.
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View style={styles.helpContainer}>
|
||||||
|
<TouchableOpacity onPress={handleHelpPress} style={styles.helpLink}>
|
||||||
|
<Text style={styles.helpLinkText} lightColor={Colors.light.tint}>
|
||||||
|
Tap here if your app doesn't automatically update after making changes
|
||||||
|
</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleHelpPress() {
|
||||||
|
WebBrowser.openBrowserAsync(
|
||||||
|
'https://docs.expo.io/get-started/create-a-new-app/#opening-the-app-on-your-phonetablet'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: '#fff',
|
||||||
|
},
|
||||||
|
developmentModeText: {
|
||||||
|
marginBottom: 20,
|
||||||
|
fontSize: 14,
|
||||||
|
lineHeight: 19,
|
||||||
|
textAlign: 'center',
|
||||||
|
},
|
||||||
|
contentContainer: {
|
||||||
|
paddingTop: 30,
|
||||||
|
},
|
||||||
|
welcomeContainer: {
|
||||||
|
alignItems: 'center',
|
||||||
|
marginTop: 10,
|
||||||
|
marginBottom: 20,
|
||||||
|
},
|
||||||
|
welcomeImage: {
|
||||||
|
width: 100,
|
||||||
|
height: 80,
|
||||||
|
resizeMode: 'contain',
|
||||||
|
marginTop: 3,
|
||||||
|
marginLeft: -10,
|
||||||
|
},
|
||||||
|
getStartedContainer: {
|
||||||
|
alignItems: 'center',
|
||||||
|
marginHorizontal: 50,
|
||||||
|
},
|
||||||
|
homeScreenFilename: {
|
||||||
|
marginVertical: 7,
|
||||||
|
},
|
||||||
|
codeHighlightText: {
|
||||||
|
color: 'rgba(96,100,109, 0.8)',
|
||||||
|
},
|
||||||
|
codeHighlightContainer: {
|
||||||
|
borderRadius: 3,
|
||||||
|
paddingHorizontal: 4,
|
||||||
|
},
|
||||||
|
getStartedText: {
|
||||||
|
fontSize: 17,
|
||||||
|
lineHeight: 24,
|
||||||
|
textAlign: 'center',
|
||||||
|
},
|
||||||
|
helpContainer: {
|
||||||
|
marginTop: 15,
|
||||||
|
marginHorizontal: 20,
|
||||||
|
alignItems: 'center',
|
||||||
|
},
|
||||||
|
helpLink: {
|
||||||
|
paddingVertical: 15,
|
||||||
|
},
|
||||||
|
helpLinkText: {
|
||||||
|
textAlign: 'center',
|
||||||
|
},
|
||||||
|
});
|
||||||
7
components/StyledText.tsx
Normal file
7
components/StyledText.tsx
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
|
||||||
|
import { Text, TextProps } from './Themed';
|
||||||
|
|
||||||
|
export function MonoText(props: TextProps) {
|
||||||
|
return <Text {...props} style={[props.style, { fontFamily: 'space-mono' }]} />;
|
||||||
|
}
|
||||||
41
components/Themed.tsx
Normal file
41
components/Themed.tsx
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
import { Text as DefaultText, View as DefaultView } from 'react-native';
|
||||||
|
|
||||||
|
import Colors from '../constants/Colors';
|
||||||
|
import useColorScheme from '../hooks/useColorScheme';
|
||||||
|
|
||||||
|
export function useThemeColor(
|
||||||
|
props: { light?: string; dark?: string },
|
||||||
|
colorName: keyof typeof Colors.light & keyof typeof Colors.dark
|
||||||
|
) {
|
||||||
|
const theme = useColorScheme();
|
||||||
|
const colorFromProps = props[theme];
|
||||||
|
|
||||||
|
if (colorFromProps) {
|
||||||
|
return colorFromProps;
|
||||||
|
} else {
|
||||||
|
return Colors[theme][colorName];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type ThemeProps = {
|
||||||
|
lightColor?: string;
|
||||||
|
darkColor?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TextProps = ThemeProps & DefaultText['props'];
|
||||||
|
export type ViewProps = ThemeProps & DefaultView['props'];
|
||||||
|
|
||||||
|
export function Text(props: TextProps) {
|
||||||
|
const { style, lightColor, darkColor, ...otherProps } = props;
|
||||||
|
const color = useThemeColor({ light: lightColor, dark: darkColor }, 'text');
|
||||||
|
|
||||||
|
return <DefaultText style={[{ color }, style]} {...otherProps} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function View(props: ViewProps) {
|
||||||
|
const { style, lightColor, darkColor, ...otherProps } = props;
|
||||||
|
const backgroundColor = useThemeColor({ light: lightColor, dark: darkColor }, 'background');
|
||||||
|
|
||||||
|
return <DefaultView style={[{ backgroundColor }, style]} {...otherProps} />;
|
||||||
|
}
|
||||||
10
components/__tests__/StyledText-test.js
Normal file
10
components/__tests__/StyledText-test.js
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
import renderer from 'react-test-renderer';
|
||||||
|
|
||||||
|
import { MonoText } from '../StyledText';
|
||||||
|
|
||||||
|
it(`renders correctly`, () => {
|
||||||
|
const tree = renderer.create(<MonoText>Snapshot test!</MonoText>).toJSON();
|
||||||
|
|
||||||
|
expect(tree).toMatchSnapshot();
|
||||||
|
});
|
||||||
19
constants/Colors.ts
Normal file
19
constants/Colors.ts
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
const tintColorLight = '#2f95dc';
|
||||||
|
const tintColorDark = '#fff';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
light: {
|
||||||
|
text: '#000',
|
||||||
|
background: '#fff',
|
||||||
|
tint: tintColorLight,
|
||||||
|
tabIconDefault: '#ccc',
|
||||||
|
tabIconSelected: tintColorLight,
|
||||||
|
},
|
||||||
|
dark: {
|
||||||
|
text: '#fff',
|
||||||
|
background: '#000',
|
||||||
|
tint: tintColorDark,
|
||||||
|
tabIconDefault: '#ccc',
|
||||||
|
tabIconSelected: tintColorDark,
|
||||||
|
},
|
||||||
|
};
|
||||||
12
constants/Layout.ts
Normal file
12
constants/Layout.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import { Dimensions } from 'react-native';
|
||||||
|
|
||||||
|
const width = Dimensions.get('window').width;
|
||||||
|
const height = Dimensions.get('window').height;
|
||||||
|
|
||||||
|
export default {
|
||||||
|
window: {
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
},
|
||||||
|
isSmallDevice: width < 375,
|
||||||
|
};
|
||||||
33
hooks/useCachedResources.ts
Normal file
33
hooks/useCachedResources.ts
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import { Ionicons } from '@expo/vector-icons';
|
||||||
|
import * as Font from 'expo-font';
|
||||||
|
import * as SplashScreen from 'expo-splash-screen';
|
||||||
|
import * as React from 'react';
|
||||||
|
|
||||||
|
export default function useCachedResources() {
|
||||||
|
const [isLoadingComplete, setLoadingComplete] = React.useState(false);
|
||||||
|
|
||||||
|
// Load any resources or data that we need prior to rendering the app
|
||||||
|
React.useEffect(() => {
|
||||||
|
async function loadResourcesAndDataAsync() {
|
||||||
|
try {
|
||||||
|
SplashScreen.preventAutoHideAsync();
|
||||||
|
|
||||||
|
// Load fonts
|
||||||
|
await Font.loadAsync({
|
||||||
|
...Ionicons.font,
|
||||||
|
'space-mono': require('../assets/fonts/SpaceMono-Regular.ttf'),
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
// We might want to provide this error information to an error reporting service
|
||||||
|
console.warn(e);
|
||||||
|
} finally {
|
||||||
|
setLoadingComplete(true);
|
||||||
|
SplashScreen.hideAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loadResourcesAndDataAsync();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return isLoadingComplete;
|
||||||
|
}
|
||||||
8
hooks/useColorScheme.ts
Normal file
8
hooks/useColorScheme.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import { ColorSchemeName, useColorScheme as _useColorScheme } from 'react-native';
|
||||||
|
|
||||||
|
// The useColorScheme value is always either light or dark, but the built-in
|
||||||
|
// type suggests that it can be null. This will not happen in practice, so this
|
||||||
|
// makes it a bit easier to work with.
|
||||||
|
export default function useColorScheme(): NonNullable<ColorSchemeName> {
|
||||||
|
return _useColorScheme() as NonNullable<ColorSchemeName>;
|
||||||
|
}
|
||||||
5
hooks/useColorScheme.web.ts
Normal file
5
hooks/useColorScheme.web.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
// useColorScheme from react-native does not support web currently. You can replace
|
||||||
|
// this with react-native-appearance if you would like theme support on web.
|
||||||
|
export default function useColorScheme() {
|
||||||
|
return 'light';
|
||||||
|
}
|
||||||
73
navigation/BottomTabNavigator.tsx
Normal file
73
navigation/BottomTabNavigator.tsx
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
import { Ionicons } from '@expo/vector-icons';
|
||||||
|
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
|
||||||
|
import { createStackNavigator } from '@react-navigation/stack';
|
||||||
|
import * as React from 'react';
|
||||||
|
|
||||||
|
import Colors from '../constants/Colors';
|
||||||
|
import useColorScheme from '../hooks/useColorScheme';
|
||||||
|
import TabOneScreen from '../screens/TabOneScreen';
|
||||||
|
import TabTwoScreen from '../screens/TabTwoScreen';
|
||||||
|
import { BottomTabParamList, TabOneParamList, TabTwoParamList } from '../types';
|
||||||
|
|
||||||
|
const BottomTab = createBottomTabNavigator<BottomTabParamList>();
|
||||||
|
|
||||||
|
export default function BottomTabNavigator() {
|
||||||
|
const colorScheme = useColorScheme();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<BottomTab.Navigator
|
||||||
|
initialRouteName="TabOne"
|
||||||
|
tabBarOptions={{ activeTintColor: Colors[colorScheme].tint }}>
|
||||||
|
<BottomTab.Screen
|
||||||
|
name="TabOne"
|
||||||
|
component={TabOneNavigator}
|
||||||
|
options={{
|
||||||
|
tabBarIcon: ({ color }) => <TabBarIcon name="ios-code" color={color} />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<BottomTab.Screen
|
||||||
|
name="TabTwo"
|
||||||
|
component={TabTwoNavigator}
|
||||||
|
options={{
|
||||||
|
tabBarIcon: ({ color }) => <TabBarIcon name="ios-code" color={color} />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</BottomTab.Navigator>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// You can explore the built-in icon families and icons on the web at:
|
||||||
|
// https://icons.expo.fyi/
|
||||||
|
function TabBarIcon(props: { name: React.ComponentProps<typeof Ionicons>['name']; color: string }) {
|
||||||
|
return <Ionicons size={30} style={{ marginBottom: -3 }} {...props} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Each tab has its own navigation stack, you can read more about this pattern here:
|
||||||
|
// https://reactnavigation.org/docs/tab-based-navigation#a-stack-navigator-for-each-tab
|
||||||
|
const TabOneStack = createStackNavigator<TabOneParamList>();
|
||||||
|
|
||||||
|
function TabOneNavigator() {
|
||||||
|
return (
|
||||||
|
<TabOneStack.Navigator>
|
||||||
|
<TabOneStack.Screen
|
||||||
|
name="TabOneScreen"
|
||||||
|
component={TabOneScreen}
|
||||||
|
options={{ headerTitle: 'Tab One Title' }}
|
||||||
|
/>
|
||||||
|
</TabOneStack.Navigator>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const TabTwoStack = createStackNavigator<TabTwoParamList>();
|
||||||
|
|
||||||
|
function TabTwoNavigator() {
|
||||||
|
return (
|
||||||
|
<TabTwoStack.Navigator>
|
||||||
|
<TabTwoStack.Screen
|
||||||
|
name="TabTwoScreen"
|
||||||
|
component={TabTwoScreen}
|
||||||
|
options={{ headerTitle: 'Tab Two Title' }}
|
||||||
|
/>
|
||||||
|
</TabTwoStack.Navigator>
|
||||||
|
);
|
||||||
|
}
|
||||||
24
navigation/LinkingConfiguration.ts
Normal file
24
navigation/LinkingConfiguration.ts
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
import * as Linking from 'expo-linking';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
prefixes: [Linking.makeUrl('/')],
|
||||||
|
config: {
|
||||||
|
screens: {
|
||||||
|
Root: {
|
||||||
|
screens: {
|
||||||
|
TabOne: {
|
||||||
|
screens: {
|
||||||
|
TabOneScreen: 'one',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
TabTwo: {
|
||||||
|
screens: {
|
||||||
|
TabTwoScreen: 'two',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
NotFound: '*',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
34
navigation/index.tsx
Normal file
34
navigation/index.tsx
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
import { NavigationContainer, DefaultTheme, DarkTheme } from '@react-navigation/native';
|
||||||
|
import { createStackNavigator } from '@react-navigation/stack';
|
||||||
|
import * as React from 'react';
|
||||||
|
import { ColorSchemeName } from 'react-native';
|
||||||
|
|
||||||
|
import NotFoundScreen from '../screens/NotFoundScreen';
|
||||||
|
import { RootStackParamList } from '../types';
|
||||||
|
import BottomTabNavigator from './BottomTabNavigator';
|
||||||
|
import LinkingConfiguration from './LinkingConfiguration';
|
||||||
|
|
||||||
|
// If you are not familiar with React Navigation, we recommend going through the
|
||||||
|
// "Fundamentals" guide: https://reactnavigation.org/docs/getting-started
|
||||||
|
export default function Navigation({ colorScheme }: { colorScheme: ColorSchemeName }) {
|
||||||
|
return (
|
||||||
|
<NavigationContainer
|
||||||
|
linking={LinkingConfiguration}
|
||||||
|
theme={colorScheme === 'dark' ? DarkTheme : DefaultTheme}>
|
||||||
|
<RootNavigator />
|
||||||
|
</NavigationContainer>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// A root stack navigator is often used for displaying modals on top of all other content
|
||||||
|
// Read more here: https://reactnavigation.org/docs/modal
|
||||||
|
const Stack = createStackNavigator<RootStackParamList>();
|
||||||
|
|
||||||
|
function RootNavigator() {
|
||||||
|
return (
|
||||||
|
<Stack.Navigator screenOptions={{ headerShown: false }}>
|
||||||
|
<Stack.Screen name="Root" component={BottomTabNavigator} />
|
||||||
|
<Stack.Screen name="NotFound" component={NotFoundScreen} options={{ title: 'Oops!' }} />
|
||||||
|
</Stack.Navigator>
|
||||||
|
);
|
||||||
|
}
|
||||||
29778
package-lock.json
generated
Normal file
29778
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
44
package.json
Normal file
44
package.json
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
{
|
||||||
|
"main": "node_modules/expo/AppEntry.js",
|
||||||
|
"scripts": {
|
||||||
|
"start": "expo start",
|
||||||
|
"android": "expo start --android",
|
||||||
|
"ios": "expo start --ios",
|
||||||
|
"web": "expo start --web",
|
||||||
|
"eject": "expo eject",
|
||||||
|
"test": "jest --watchAll"
|
||||||
|
},
|
||||||
|
"jest": {
|
||||||
|
"preset": "jest-expo"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@expo/vector-icons": "^12.0.0",
|
||||||
|
"@react-native-community/masked-view": "0.1.10",
|
||||||
|
"@react-navigation/bottom-tabs": "5.11.2",
|
||||||
|
"@react-navigation/native": "~5.8.10",
|
||||||
|
"@react-navigation/stack": "~5.12.8",
|
||||||
|
"expo": "~40.0.0",
|
||||||
|
"expo-asset": "~8.2.1",
|
||||||
|
"expo-constants": "~9.3.0",
|
||||||
|
"expo-font": "~8.4.0",
|
||||||
|
"expo-linking": "~2.0.0",
|
||||||
|
"expo-splash-screen": "~0.8.0",
|
||||||
|
"expo-status-bar": "~1.0.3",
|
||||||
|
"expo-web-browser": "~8.6.0",
|
||||||
|
"react": "16.13.1",
|
||||||
|
"react-dom": "16.13.1",
|
||||||
|
"react-native": "https://github.com/expo/react-native/archive/sdk-40.0.1.tar.gz",
|
||||||
|
"react-native-gesture-handler": "~1.8.0",
|
||||||
|
"react-native-safe-area-context": "3.1.9",
|
||||||
|
"react-native-screens": "~2.15.0",
|
||||||
|
"react-native-web": "~0.13.12"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/core": "^7.9.0",
|
||||||
|
"@types/react": "~16.9.35",
|
||||||
|
"@types/react-native": "~0.63.2",
|
||||||
|
"jest-expo": "~40.0.0",
|
||||||
|
"typescript": "~4.0.0"
|
||||||
|
},
|
||||||
|
"private": true
|
||||||
|
}
|
||||||
40
screens/NotFoundScreen.tsx
Normal file
40
screens/NotFoundScreen.tsx
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
import { StackScreenProps } from '@react-navigation/stack';
|
||||||
|
import * as React from 'react';
|
||||||
|
import { StyleSheet, Text, TouchableOpacity, View } from 'react-native';
|
||||||
|
|
||||||
|
import { RootStackParamList } from '../types';
|
||||||
|
|
||||||
|
export default function NotFoundScreen({
|
||||||
|
navigation,
|
||||||
|
}: StackScreenProps<RootStackParamList, 'NotFound'>) {
|
||||||
|
return (
|
||||||
|
<View style={styles.container}>
|
||||||
|
<Text style={styles.title}>This screen doesn't exist.</Text>
|
||||||
|
<TouchableOpacity onPress={() => navigation.replace('Root')} style={styles.link}>
|
||||||
|
<Text style={styles.linkText}>Go to home screen!</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: '#fff',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
padding: 20,
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: 'bold',
|
||||||
|
},
|
||||||
|
link: {
|
||||||
|
marginTop: 15,
|
||||||
|
paddingVertical: 15,
|
||||||
|
},
|
||||||
|
linkText: {
|
||||||
|
fontSize: 14,
|
||||||
|
color: '#2e78b7',
|
||||||
|
},
|
||||||
|
});
|
||||||
32
screens/TabOneScreen.tsx
Normal file
32
screens/TabOneScreen.tsx
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
import { StyleSheet } from 'react-native';
|
||||||
|
|
||||||
|
import EditScreenInfo from '../components/EditScreenInfo';
|
||||||
|
import { Text, View } from '../components/Themed';
|
||||||
|
|
||||||
|
export default function TabOneScreen() {
|
||||||
|
return (
|
||||||
|
<View style={styles.container}>
|
||||||
|
<Text style={styles.title}>Tab One</Text>
|
||||||
|
<View style={styles.separator} lightColor="#eee" darkColor="rgba(255,255,255,0.1)" />
|
||||||
|
<EditScreenInfo path="/screens/TabOneScreen.tsx" />
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: 'bold',
|
||||||
|
},
|
||||||
|
separator: {
|
||||||
|
marginVertical: 30,
|
||||||
|
height: 1,
|
||||||
|
width: '80%',
|
||||||
|
},
|
||||||
|
});
|
||||||
32
screens/TabTwoScreen.tsx
Normal file
32
screens/TabTwoScreen.tsx
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
import { StyleSheet } from 'react-native';
|
||||||
|
|
||||||
|
import EditScreenInfo from '../components/EditScreenInfo';
|
||||||
|
import { Text, View } from '../components/Themed';
|
||||||
|
|
||||||
|
export default function TabTwoScreen() {
|
||||||
|
return (
|
||||||
|
<View style={styles.container}>
|
||||||
|
<Text style={styles.title}>Tab Two</Text>
|
||||||
|
<View style={styles.separator} lightColor="#eee" darkColor="rgba(255,255,255,0.1)" />
|
||||||
|
<EditScreenInfo path="/screens/TabTwoScreen.tsx" />
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: 'bold',
|
||||||
|
},
|
||||||
|
separator: {
|
||||||
|
marginVertical: 30,
|
||||||
|
height: 1,
|
||||||
|
width: '80%',
|
||||||
|
},
|
||||||
|
});
|
||||||
12
tsconfig.json
Normal file
12
tsconfig.json
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"jsx": "react-native",
|
||||||
|
"lib": ["dom", "esnext"],
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"noEmit": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"strict": true
|
||||||
|
}
|
||||||
|
}
|
||||||
17
types.tsx
Normal file
17
types.tsx
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
export type RootStackParamList = {
|
||||||
|
Root: undefined;
|
||||||
|
NotFound: undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type BottomTabParamList = {
|
||||||
|
TabOne: undefined;
|
||||||
|
TabTwo: undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TabOneParamList = {
|
||||||
|
TabOneScreen: undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TabTwoParamList = {
|
||||||
|
TabTwoScreen: undefined;
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user