Add routes and core views

zio/stable
Paul Frazee 2022-06-09 16:32:03 -05:00
parent d6942bffab
commit fc3b2952bb
16 changed files with 293 additions and 118 deletions

View File

@ -21,3 +21,14 @@ Uses:
- Tips
- `npx react-native info` Checks what has been installed.
- Android instructions are a *little* inaccurate but not as much as you might think. I had to manually create a virtual device, then run `yarn android` twice (once to start the emulator and the second time to connect to it).
## TODOs
- Navigation
- Auth / Unauthed
- Web
- Desktop vs mobile styling
- API
- Create mock api
- Tests
- Should just try to catch errors on basic load

View File

@ -3,6 +3,7 @@ package com.app;
import com.facebook.react.ReactActivity;
import com.facebook.react.ReactActivityDelegate;
import com.facebook.react.ReactRootView;
import android.os.Bundle;
public class MainActivity extends ReactActivity {
@ -36,5 +37,10 @@ public class MainActivity extends ReactActivity {
reactRootView.setIsFabric(BuildConfig.IS_NEW_ARCHITECTURE_ENABLED);
return reactRootView;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(null);
}
}
}

View File

@ -353,6 +353,8 @@ PODS:
- React-jsi (= 0.68.2)
- React-logger (= 0.68.2)
- React-perflogger (= 0.68.2)
- RNCAsyncStorage (1.17.6):
- React-Core
- RNScreens (3.13.1):
- React-Core
- React-RCTImage
@ -417,6 +419,7 @@ DEPENDENCIES:
- React-RCTVibration (from `../node_modules/react-native/Libraries/Vibration`)
- React-runtimeexecutor (from `../node_modules/react-native/ReactCommon/runtimeexecutor`)
- ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`)
- "RNCAsyncStorage (from `../node_modules/@react-native-async-storage/async-storage`)"
- RNScreens (from `../node_modules/react-native-screens`)
- Yoga (from `../node_modules/react-native/ReactCommon/yoga`)
@ -501,6 +504,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native/ReactCommon/runtimeexecutor"
ReactCommon:
:path: "../node_modules/react-native/ReactCommon"
RNCAsyncStorage:
:path: "../node_modules/@react-native-async-storage/async-storage"
RNScreens:
:path: "../node_modules/react-native-screens"
Yoga:
@ -551,6 +556,7 @@ SPEC CHECKSUMS:
React-RCTVibration: 79040b92bfa9c3c2d2cb4f57e981164ec7ab9374
React-runtimeexecutor: b960b687d2dfef0d3761fbb187e01812ebab8b23
ReactCommon: 095366164a276d91ea704ce53cb03825c487a3f2
RNCAsyncStorage: 466b9df1a14bccda91da86e0b7d9a345d78e1673
RNScreens: 40a2cb40a02a609938137a1e0acfbf8fc9eebf19
SocketRocket: fccef3f9c5cedea1353a9ef6ada904fde10d6608
Yoga: 99652481fcd320aefa4a7ef90095b95acd181952

View File

@ -12,8 +12,10 @@
},
"dependencies": {
"@react-native-async-storage/async-storage": "^1.17.6",
"@react-navigation/bottom-tabs": "^6.3.1",
"@react-navigation/native": "^6.0.10",
"@react-navigation/native-stack": "^6.6.2",
"@react-navigation/stack": "^6.2.1",
"mobx": "^6.6.0",
"mobx-state-tree": "^5.1.5",
"react": "17.0.2",

View File

@ -4,8 +4,16 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<title> WEBAPP </title>
<style>
/* These styles make the body full-height */
html, body { height: 100%; }
/* These styles disable body scrolling if you are using <ScrollView> */
body { overflow: hidden; }
/* These styles make the root element full-height */
#root { display:flex; height:100%; }
</style>
</head>
<body>
<div id="root"></div>
<div id="root"></div>
</body>
</html>

View File

@ -1,52 +1,6 @@
import React, {useState, useEffect} from 'react'
import {
SafeAreaView,
ScrollView,
StatusBar,
Text,
Button,
useColorScheme,
View,
} from 'react-native'
import {NavigationContainer} from '@react-navigation/native'
import {
createNativeStackNavigator,
NativeStackScreenProps,
} from '@react-navigation/native-stack'
import {RootStore, setupState, RootStoreProvider} from './state'
type RootStackParamList = {
Home: undefined
Profile: {name: string}
}
const Stack = createNativeStackNavigator()
const HomeScreen = ({
navigation,
}: NativeStackScreenProps<RootStackParamList, 'Home'>) => {
const isDarkMode = useColorScheme() === 'dark'
return (
<SafeAreaView>
<StatusBar barStyle={isDarkMode ? 'light-content' : 'dark-content'} />
<ScrollView contentInsetAdjustmentBehavior="automatic">
<View>
<Text>Native</Text>
<Button
title="Go to Jane's profile"
onPress={() => navigation.navigate('Profile', {name: 'Jane'})}
/>
</View>
</ScrollView>
</SafeAreaView>
)
}
const ProfileScreen = ({
route,
}: NativeStackScreenProps<RootStackParamList, 'Profile'>) => {
return <Text>This is {route.params.name}'s profile</Text>
}
import * as Routes from './routes'
function App() {
const [rootStore, setRootStore] = useState<RootStore | undefined>(undefined)
@ -63,16 +17,7 @@ function App() {
return (
<RootStoreProvider value={rootStore}>
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="Home"
component={HomeScreen}
options={{title: 'Welcome'}}
/>
<Stack.Screen name="Profile" component={ProfileScreen} />
</Stack.Navigator>
</NavigationContainer>
<Routes.Root />
</RootStoreProvider>
)
}

View File

@ -1,52 +1,6 @@
import React, {useState, useEffect} from 'react'
import {
SafeAreaView,
ScrollView,
StatusBar,
Text,
Button,
useColorScheme,
View,
} from 'react-native'
import {NavigationContainer} from '@react-navigation/native'
import {
createNativeStackNavigator,
NativeStackScreenProps,
} from '@react-navigation/native-stack'
import {RootStore, setupState, RootStoreProvider} from './state'
type RootStackParamList = {
Home: undefined
Profile: {name: string}
}
const Stack = createNativeStackNavigator()
const HomeScreen = ({
navigation,
}: NativeStackScreenProps<RootStackParamList, 'Home'>) => {
const isDarkMode = useColorScheme() === 'dark'
return (
<SafeAreaView>
<StatusBar barStyle={isDarkMode ? 'light-content' : 'dark-content'} />
<ScrollView contentInsetAdjustmentBehavior="automatic">
<View>
<Text>Web</Text>
<Button
title="Go to Jane's profile"
onPress={() => navigation.navigate('Profile', {name: 'Jane'})}
/>
</View>
</ScrollView>
</SafeAreaView>
)
}
const ProfileScreen = ({
route,
}: NativeStackScreenProps<RootStackParamList, 'Profile'>) => {
return <Text>This is {route.params.name}'s profile</Text>
}
import * as Routes from './routes'
function App() {
const [rootStore, setRootStore] = useState<RootStore | undefined>(undefined)
@ -63,16 +17,7 @@ function App() {
return (
<RootStoreProvider value={rootStore}>
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="Home"
component={HomeScreen}
options={{title: 'Welcome'}}
/>
<Stack.Screen name="Profile" component={ProfileScreen} />
</Stack.Navigator>
</NavigationContainer>
<Routes.Root />
</RootStoreProvider>
)
}

View File

@ -0,0 +1,72 @@
import React from 'react'
import {Text} from 'react-native'
import {
NavigationContainer,
LinkingOptions,
RouteProp,
ParamListBase,
} from '@react-navigation/native'
import {createNativeStackNavigator} from '@react-navigation/native-stack'
import {createBottomTabNavigator} from '@react-navigation/bottom-tabs'
import type {RootStackParamList} from './types'
import {Home} from '../screens/Home'
import {Search} from '../screens/Search'
import {Notifications} from '../screens/Notifications'
import {Menu} from '../screens/Menu'
import {Profile} from '../screens/Profile'
import {NotFound} from '../screens/NotFound'
const linking: LinkingOptions<RootStackParamList> = {
prefixes: [
'http://localhost:3000', // local dev
],
config: {
screens: {
Primary: {
screens: {
Home: '',
Search: 'search',
Notifications: 'notifications',
Menu: 'menu',
},
},
Profile: 'profile/:name',
NotFound: '*',
},
},
}
export const RootStack = createNativeStackNavigator()
export const PrimaryTab = createBottomTabNavigator()
const tabBarScreenOptions = ({
route,
}: {
route: RouteProp<ParamListBase, string>
}) => ({
tabBarIcon: (_state: {focused: boolean; color: string; size: number}) => {
// TODO: icons
return <Text>{route.name.at(0)}</Text>
},
})
const Primary = () => (
<PrimaryTab.Navigator
screenOptions={tabBarScreenOptions}
initialRouteName="Home">
<PrimaryTab.Screen name="Home" component={Home} />
<PrimaryTab.Screen name="Search" component={Search} />
<PrimaryTab.Screen name="Notifications" component={Notifications} />
<PrimaryTab.Screen name="Menu" component={Menu} />
</PrimaryTab.Navigator>
)
export const Root = () => (
<NavigationContainer linking={linking} fallback={<Text>Loading...</Text>}>
<RootStack.Navigator initialRouteName="Primary">
<RootStack.Screen name="Primary" component={Primary} />
<RootStack.Screen name="Profile" component={Profile} />
<RootStack.Screen name="NotFound" component={NotFound} />
</RootStack.Navigator>
</NavigationContainer>
)

View File

@ -0,0 +1,24 @@
import type {NavigatorScreenParams} from '@react-navigation/native'
import type {CompositeScreenProps} from '@react-navigation/native'
import type {StackScreenProps} from '@react-navigation/stack'
import type {BottomTabScreenProps} from '@react-navigation/bottom-tabs'
export type RootStackParamList = {
Primary: undefined
Profile: {name: string}
NotFound: undefined
}
export type RootStackScreenProps<T extends keyof RootStackParamList> =
StackScreenProps<RootStackParamList, T>
export type PrimaryTabParamList = {
Home: NavigatorScreenParams<RootStackParamList>
Search: undefined
Notifications: undefined
Menu: undefined
}
export type PrimaryTabScreenProps<T extends keyof PrimaryTabParamList> =
CompositeScreenProps<
BottomTabScreenProps<PrimaryTabParamList, T>,
RootStackScreenProps<keyof RootStackParamList>
>

View File

@ -0,0 +1,17 @@
import React from 'react'
import {Text, Button, View, SafeAreaView} from 'react-native'
import type {PrimaryTabScreenProps} from '../routes/types'
export const Home = ({navigation}: PrimaryTabScreenProps<'Home'>) => {
return (
<SafeAreaView style={{flex: 1}}>
<View style={{flex: 1}}>
<Text>Hello world</Text>
<Button
title="Go to Jane's profile"
onPress={() => navigation.navigate('Profile', {name: 'Jane'})}
/>
</View>
</SafeAreaView>
)
}

View File

@ -0,0 +1,19 @@
import React from 'react'
import {SafeAreaView, ScrollView, Text, Button, View} from 'react-native'
import type {PrimaryTabScreenProps} from '../routes/types'
export const Menu = ({navigation}: PrimaryTabScreenProps<'Menu'>) => {
return (
<SafeAreaView>
<ScrollView contentInsetAdjustmentBehavior="automatic">
<View>
<Text>Hello world</Text>
<Button
title="Go to Jane's profile"
onPress={() => navigation.navigate('Profile', {name: 'Jane'})}
/>
</View>
</ScrollView>
</SafeAreaView>
)
}

View File

@ -0,0 +1,27 @@
import React from 'react'
import {
SafeAreaView,
ScrollView,
StatusBar,
Text,
Button,
useColorScheme,
View,
} from 'react-native'
import type {RootStackScreenProps} from '../routes/types'
export const NotFound = ({navigation}: RootStackScreenProps<'NotFound'>) => {
const isDarkMode = useColorScheme() === 'dark'
return (
<SafeAreaView>
<StatusBar barStyle={isDarkMode ? 'light-content' : 'dark-content'} />
<ScrollView contentInsetAdjustmentBehavior="automatic">
<View>
<Text>Page not found</Text>
<Button title="Home" onPress={() => navigation.navigate('Primary')} />
</View>
</ScrollView>
</SafeAreaView>
)
}

View File

@ -0,0 +1,21 @@
import React from 'react'
import {SafeAreaView, ScrollView, Text, Button, View} from 'react-native'
import type {PrimaryTabScreenProps} from '../routes/types'
export const Notifications = ({
navigation,
}: PrimaryTabScreenProps<'Notifications'>) => {
return (
<SafeAreaView>
<ScrollView contentInsetAdjustmentBehavior="automatic">
<View>
<Text>Hello world</Text>
<Button
title="Go to Jane's profile"
onPress={() => navigation.navigate('Profile', {name: 'Jane'})}
/>
</View>
</ScrollView>
</SafeAreaView>
)
}

View File

@ -0,0 +1,7 @@
import React from 'react'
import {Text} from 'react-native'
import type {RootStackScreenProps} from '../routes/types'
export const Profile = ({route}: RootStackScreenProps<'Profile'>) => {
return <Text>This is {route.params.name}'s profile</Text>
}

View File

@ -0,0 +1,19 @@
import React from 'react'
import {SafeAreaView, ScrollView, Text, Button, View} from 'react-native'
import type {PrimaryTabScreenProps} from '../routes/types'
export const Search = ({navigation}: PrimaryTabScreenProps<'Search'>) => {
return (
<SafeAreaView>
<ScrollView contentInsetAdjustmentBehavior="automatic">
<View>
<Text>Hello world</Text>
<Button
title="Go to Jane's profile"
onPress={() => navigation.navigate('Profile', {name: 'Jane'})}
/>
</View>
</ScrollView>
</SafeAreaView>
)
}

View File

@ -2012,6 +2012,15 @@
resolved "https://registry.yarnpkg.com/@react-native/polyfills/-/polyfills-2.0.0.tgz#4c40b74655c83982c8cf47530ee7dc13d957b6aa"
integrity sha512-K0aGNn1TjalKj+65D7ycc1//H9roAQ51GJVk5ZJQFb2teECGmzd86bYDC0aYdbRf7gtovescq4Zt6FR0tgXiHQ==
"@react-navigation/bottom-tabs@^6.3.1":
version "6.3.1"
resolved "https://registry.yarnpkg.com/@react-navigation/bottom-tabs/-/bottom-tabs-6.3.1.tgz#1552ccdb789b6c9fc05af0877f8f3a50ab28870c"
integrity sha512-sL9F4WMhhR6I9bE7bpsPVHnK1cN9doaFHAuy5YmD+Sw6OyO0TAmNgQFx4xZWqboA5ZwSkN0tWcRCr6wGXaRRag==
dependencies:
"@react-navigation/elements" "^1.3.3"
color "^3.1.3"
warn-once "^0.1.0"
"@react-navigation/core@^6.2.1":
version "6.2.1"
resolved "https://registry.yarnpkg.com/@react-navigation/core/-/core-6.2.1.tgz#90459f9afd25b71a9471b0706ebea2cdd2534fc4"
@ -2053,6 +2062,15 @@
dependencies:
nanoid "^3.1.23"
"@react-navigation/stack@^6.2.1":
version "6.2.1"
resolved "https://registry.yarnpkg.com/@react-navigation/stack/-/stack-6.2.1.tgz#2b14473579eced6def5cca06860044d60e59d06e"
integrity sha512-JI7boxtPAMCBXi4VJHVEq61jLVHFW5f3npvbndS+XfOsv7Gf0f91HOVJ28DS5c2Fn4+CO4AByjUozzlN296X+A==
dependencies:
"@react-navigation/elements" "^1.3.3"
color "^3.1.3"
warn-once "^0.1.0"
"@rollup/plugin-babel@^5.2.0":
version "5.3.1"
resolved "https://registry.yarnpkg.com/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz#04bc0608f4aa4b2e4b1aebf284344d0f68fda283"
@ -3998,7 +4016,7 @@ collection-visit@^1.0.0:
map-visit "^1.0.0"
object-visit "^1.0.0"
color-convert@^1.9.0:
color-convert@^1.9.0, color-convert@^1.9.3:
version "1.9.3"
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
@ -4017,11 +4035,27 @@ color-name@1.1.3:
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==
color-name@^1.1.4, color-name@~1.1.4:
color-name@^1.0.0, color-name@^1.1.4, color-name@~1.1.4:
version "1.1.4"
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
color-string@^1.6.0:
version "1.9.1"
resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.9.1.tgz#4467f9146f036f855b764dfb5bf8582bf342c7a4"
integrity sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==
dependencies:
color-name "^1.0.0"
simple-swizzle "^0.2.2"
color@^3.1.3:
version "3.2.1"
resolved "https://registry.yarnpkg.com/color/-/color-3.2.1.tgz#3544dc198caf4490c3ecc9a790b54fe9ff45e164"
integrity sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==
dependencies:
color-convert "^1.9.3"
color-string "^1.6.0"
colord@^2.9.1:
version "2.9.2"
resolved "https://registry.yarnpkg.com/colord/-/colord-2.9.2.tgz#25e2bacbbaa65991422c07ea209e2089428effb1"
@ -6468,6 +6502,11 @@ is-arrayish@^0.2.1:
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==
is-arrayish@^0.3.1:
version "0.3.2"
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03"
integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==
is-bigint@^1.0.1:
version "1.0.4"
resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3"
@ -10832,6 +10871,13 @@ simple-plist@^1.1.0:
bplist-parser "0.3.1"
plist "^3.0.5"
simple-swizzle@^0.2.2:
version "0.2.2"
resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a"
integrity sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==
dependencies:
is-arrayish "^0.3.1"
sisteransi@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed"